Merge branch 'master' into sculpt-dev
This commit is contained in:
commit
97ab225428
|
@ -610,7 +610,13 @@ endif()
|
|||
|
||||
# GNU Compiler
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
|
||||
# ffp-contract=off:
|
||||
# Automatically turned on when building with "-march=native". This is
|
||||
# explicitly turned off here as it will make floating point math give a bit
|
||||
# different results. This will lead to automated test failures. So disable
|
||||
# this until we support it. Seems to default to off in clang and the intel
|
||||
# compiler.
|
||||
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing -ffp-contract=off")
|
||||
|
||||
# `maybe-uninitialized` is unreliable in release builds, but fine in debug builds.
|
||||
set(GCC_EXTRA_FLAGS_RELEASE "-Wno-maybe-uninitialized")
|
||||
|
|
|
@ -379,6 +379,9 @@ endif()
|
|||
# Subdirectories
|
||||
|
||||
if(WITH_CYCLES_BLENDER)
|
||||
# Not needed to make cycles automated tests pass with -march=native.
|
||||
# However Blender itself needs this flag.
|
||||
remove_cc_flag("-ffp-contract=off")
|
||||
add_definitions(-DWITH_BLENDER_GUARDEDALLOC)
|
||||
add_subdirectory(blender)
|
||||
endif()
|
||||
|
|
|
@ -541,11 +541,11 @@ GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32
|
|||
input.type = INPUT_MOUSE;
|
||||
input.mi.mouseData = 0;
|
||||
input.mi.time = ::GetTickCount();
|
||||
/* Map from virtual screen to 0-65536. */
|
||||
input.mi.dx = (x - GetSystemMetrics(SM_XVIRTUALSCREEN)) * 65536 /
|
||||
GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||
input.mi.dy = (y - GetSystemMetrics(SM_YVIRTUALSCREEN)) * 65536 /
|
||||
GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||
/* Map from virtual screen to 0-65535 inclusive. */
|
||||
input.mi.dx = (x - GetSystemMetrics(SM_XVIRTUALSCREEN)) * 65535 /
|
||||
(GetSystemMetrics(SM_CXVIRTUALSCREEN) - 1);
|
||||
input.mi.dy = (y - GetSystemMetrics(SM_YVIRTUALSCREEN)) * 65535 /
|
||||
(GetSystemMetrics(SM_CYVIRTUALSCREEN) - 1);
|
||||
input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK;
|
||||
SendInput(1, &input, sizeof(input));
|
||||
|
||||
|
|
|
@ -74,9 +74,11 @@ def kmi_args_as_data(kmi):
|
|||
s.append(f"\"key_modifier\": '{kmi.key_modifier}'")
|
||||
|
||||
if kmi.repeat:
|
||||
if kmi.map_type == 'KEYBOARD':
|
||||
if kmi.value in {'PRESS', 'ANY'}:
|
||||
s.append("\"repeat\": True")
|
||||
if (
|
||||
(kmi.map_type == 'KEYBOARD' and kmi.value in {'PRESS', 'ANY'}) or
|
||||
(kmi.map_type == 'TEXTINPUT')
|
||||
):
|
||||
s.append("\"repeat\": True")
|
||||
|
||||
return "{" + ", ".join(s) + "}"
|
||||
|
||||
|
|
|
@ -537,6 +537,9 @@ def km_screen(params):
|
|||
("ed.undo_history", {"type": 'Z', "value": 'PRESS', "ctrl": True, "alt": True}, None),
|
||||
("screen.screen_full_area", {"type": 'UP_ARROW', "value": 'PRESS', "ctrl": True}, None),
|
||||
("screen.screen_full_area", {"type": 'DOWN_ARROW', "value": 'PRESS', "ctrl": True}, None),
|
||||
("screen.screen_full_area", {"type": 'SPACE', "value": 'PRESS', "shift": True}, None),
|
||||
("screen.screen_full_area", {"type": 'F10', "value": 'PRESS', "alt": True},
|
||||
{"properties": [("use_hide_panels", True)]}),
|
||||
("screen.screen_set", {"type": 'RIGHT_ARROW', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("delta", 1)]}),
|
||||
("screen.screen_set", {"type": 'LEFT_ARROW', "value": 'PRESS', "ctrl": True},
|
||||
|
@ -1591,12 +1594,26 @@ def km_graph_editor(params):
|
|||
("wm.context_toggle", {"type": 'O', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'tool_settings.use_proportional_fcurve')]}),
|
||||
op_menu_pie("VIEW3D_MT_proportional_editing_falloff_pie", {"type": 'O', "value": 'PRESS', "shift": True}),
|
||||
op_menu_pie("GRAPH_MT_pivot_pie", {"type": 'PERIOD', "value": 'PRESS'}),
|
||||
("marker.add", {"type": 'M', "value": 'PRESS'}, None),
|
||||
("marker.rename", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
|
||||
*_template_items_context_menu("GRAPH_MT_context_menu", params.context_menu_event),
|
||||
])
|
||||
|
||||
if not params.legacy:
|
||||
items.extend([
|
||||
op_menu_pie("GRAPH_MT_pivot_pie", {"type": 'PERIOD', "value": 'PRESS'}),
|
||||
])
|
||||
else:
|
||||
items.extend([
|
||||
# Old pivot.
|
||||
("wm.context_set_enum", {"type": 'COMMA', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'space_data.pivot_point'), ("value", 'BOUNDING_BOX_CENTER')]}),
|
||||
("wm.context_set_enum", {"type": 'PERIOD', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'space_data.pivot_point'), ("value", 'CURSOR')]}),
|
||||
("wm.context_set_enum", {"type": 'PERIOD', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("data_path", 'space_data.pivot_point'), ("value", 'INDIVIDUAL_ORIGINS')]}),
|
||||
])
|
||||
|
||||
if params.select_mouse == 'LEFTMOUSE' and not params.legacy:
|
||||
items.extend([
|
||||
("graph.cursor_set", {"type": 'RIGHTMOUSE', "value": 'PRESS', "shift": True}, None),
|
||||
|
@ -1697,14 +1714,25 @@ def km_image(params):
|
|||
for i in range(9)
|
||||
)
|
||||
),
|
||||
op_menu_pie("IMAGE_MT_pivot_pie", {"type": 'PERIOD', "value": 'PRESS'}),
|
||||
("image.render_border", {"type": 'B', "value": 'PRESS', "ctrl": True}, None),
|
||||
("image.clear_render_border", {"type": 'B', "value": 'PRESS', "ctrl": True, "alt": True}, None),
|
||||
*_template_items_context_menu("IMAGE_MT_mask_context_menu", params.context_menu_event),
|
||||
])
|
||||
|
||||
if params.legacy:
|
||||
if not params.legacy:
|
||||
items.extend([
|
||||
op_menu_pie("IMAGE_MT_pivot_pie", {"type": 'PERIOD', "value": 'PRESS'}),
|
||||
])
|
||||
else:
|
||||
items.extend([
|
||||
# Old pivot.
|
||||
("wm.context_set_enum", {"type": 'COMMA', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'space_data.pivot_point'), ("value", 'CENTER')]}),
|
||||
("wm.context_set_enum", {"type": 'COMMA', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("data_path", 'space_data.pivot_point'), ("value", 'MEDIAN')]}),
|
||||
("wm.context_set_enum", {"type": 'PERIOD', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'space_data.pivot_point'), ("value", 'CURSOR')]}),
|
||||
|
||||
("image.view_center_cursor", {"type": 'HOME', "value": 'PRESS', "alt": True}, None),
|
||||
])
|
||||
|
||||
|
@ -2826,14 +2854,25 @@ def km_clip_editor(params):
|
|||
("clip.clear_track_path", {"type": 'T', "value": 'PRESS', "shift": True, "alt": True},
|
||||
{"properties": [("action", 'ALL'), ("clear_active", False)]}),
|
||||
("clip.cursor_set", params.cursor_set_event, None),
|
||||
op_menu_pie("CLIP_MT_pivot_pie", {"type": 'PERIOD', "value": 'PRESS'}),
|
||||
("clip.copy_tracks", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
|
||||
("clip.paste_tracks", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
|
||||
*_template_items_context_menu("CLIP_MT_tracking_context_menu", params.context_menu_event),
|
||||
])
|
||||
|
||||
if params.legacy:
|
||||
if not params.legacy:
|
||||
op_menu_pie("CLIP_MT_pivot_pie", {"type": 'PERIOD', "value": 'PRESS'}),
|
||||
else:
|
||||
items.extend([
|
||||
# Old pivot.
|
||||
("wm.context_set_enum", {"type": 'COMMA', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'space_data.pivot_point'), ("value", 'BOUNDING_BOX_CENTER')]}),
|
||||
("wm.context_set_enum", {"type": 'COMMA', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("data_path", 'space_data.pivot_point'), ("value", 'MEDIAN_POINT')]}),
|
||||
("wm.context_set_enum", {"type": 'PERIOD', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'space_data.pivot_point'), ("value", 'CURSOR')]}),
|
||||
("wm.context_set_enum", {"type": 'PERIOD', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("data_path", 'space_data.pivot_point'), ("value", 'INDIVIDUAL_ORIGINS')]}),
|
||||
|
||||
("clip.view_center_cursor", {"type": 'HOME', "value": 'PRESS', "alt": True}, None),
|
||||
])
|
||||
|
||||
|
|
|
@ -1435,7 +1435,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel):
|
|||
row.prop(gp_settings, "fill_layer_mode", text="Layers")
|
||||
|
||||
col.separator()
|
||||
col.prop(gp_settings, "fill_factor", text="Resolution")
|
||||
col.prop(gp_settings, "fill_factor")
|
||||
if gp_settings.fill_draw_mode != 'STROKE':
|
||||
col = layout.column(align=False, heading="Ignore Transparent")
|
||||
col.use_property_decorate = False
|
||||
|
|
|
@ -65,6 +65,62 @@ template<> struct DefaultHash<GeometryComponentType> {
|
|||
};
|
||||
} // namespace blender
|
||||
|
||||
class GeometryComponent;
|
||||
|
||||
/**
|
||||
* An #OutputAttributePtr wraps a #WriteAttributePtr that might not be stored in its final
|
||||
* destination yet. Therefore, once the attribute has been filled with data, the #save method has
|
||||
* to be called, to store the attribute where it belongs (possibly by replacing an existing
|
||||
* attribute with the same name).
|
||||
*
|
||||
* This is useful for example in the Attribute Color Ramp node, when the same attribute name is
|
||||
* used as input and output. Typically the input is a float attribute, and the output is a color.
|
||||
* Those two attributes cannot exist at the same time, due to a name collision. To handle this
|
||||
* situation well, first the output colors have to be computed before the input floats are deleted.
|
||||
* Therefore, the outputs have to be written to a temporary buffer that replaces the existing
|
||||
* attribute once all computations are done.
|
||||
*/
|
||||
class OutputAttributePtr {
|
||||
private:
|
||||
blender::bke::WriteAttributePtr attribute_;
|
||||
|
||||
public:
|
||||
OutputAttributePtr() = default;
|
||||
OutputAttributePtr(blender::bke::WriteAttributePtr attribute);
|
||||
OutputAttributePtr(GeometryComponent &component,
|
||||
AttributeDomain domain,
|
||||
std::string name,
|
||||
CustomDataType data_type);
|
||||
|
||||
~OutputAttributePtr();
|
||||
|
||||
/* Returns false, when this wrapper is empty. */
|
||||
operator bool() const
|
||||
{
|
||||
return static_cast<bool>(attribute_);
|
||||
}
|
||||
|
||||
/* Get a reference to the underlying #WriteAttribute. */
|
||||
blender::bke::WriteAttribute &get()
|
||||
{
|
||||
BLI_assert(attribute_);
|
||||
return *attribute_;
|
||||
}
|
||||
|
||||
blender::bke::WriteAttribute &operator*()
|
||||
{
|
||||
return *attribute_;
|
||||
}
|
||||
|
||||
blender::bke::WriteAttribute *operator->()
|
||||
{
|
||||
return attribute_.get();
|
||||
}
|
||||
|
||||
void save();
|
||||
void apply_span_and_save();
|
||||
};
|
||||
|
||||
/**
|
||||
* This is the base class for specialized geometry component types.
|
||||
*/
|
||||
|
@ -185,14 +241,17 @@ class GeometryComponent {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute with the given parameters if it exists.
|
||||
* If an exact match does not exist, other attributes with the same name are deleted and a new
|
||||
* attribute is created if possible.
|
||||
* If an attribute with the given params exist, it is returned.
|
||||
* If no attribute with the given name exists, it is created and returned.
|
||||
* If an attribute with the given name but different domain or type exists, a temporary attribute
|
||||
* is created that has to be saved after the output has been computed. This avoids deleting
|
||||
* another attribute, before a computation is finished.
|
||||
*
|
||||
* This might return no attribute when the attribute cannot exist on the component.
|
||||
*/
|
||||
blender::bke::WriteAttributePtr attribute_try_ensure_for_write(
|
||||
const blender::StringRef attribute_name,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type);
|
||||
OutputAttributePtr attribute_try_get_for_output(const blender::StringRef attribute_name,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -40,8 +40,10 @@ static CLG_LogRef LOG = {"bke.attribute_access"};
|
|||
using blender::float3;
|
||||
using blender::Set;
|
||||
using blender::StringRef;
|
||||
using blender::StringRefNull;
|
||||
using blender::bke::ReadAttributePtr;
|
||||
using blender::bke::WriteAttributePtr;
|
||||
using blender::fn::GMutableSpan;
|
||||
|
||||
/* Can't include BKE_object_deform.h right now, due to an enum forward declaration. */
|
||||
extern "C" MDeformVert *BKE_object_defgroup_data_create(ID *id);
|
||||
|
@ -250,6 +252,54 @@ template<typename T> class ArrayWriteAttribute final : public WriteAttribute {
|
|||
}
|
||||
};
|
||||
|
||||
/* This is used by the #OutputAttributePtr class. */
|
||||
class TemporaryWriteAttribute final : public WriteAttribute {
|
||||
public:
|
||||
GMutableSpan data;
|
||||
GeometryComponent &component;
|
||||
std::string final_name;
|
||||
|
||||
TemporaryWriteAttribute(AttributeDomain domain,
|
||||
GMutableSpan data,
|
||||
GeometryComponent &component,
|
||||
std::string final_name)
|
||||
: WriteAttribute(domain, data.type(), data.size()),
|
||||
data(data),
|
||||
component(component),
|
||||
final_name(std::move(final_name))
|
||||
{
|
||||
}
|
||||
|
||||
~TemporaryWriteAttribute() override
|
||||
{
|
||||
if (data.data() != nullptr) {
|
||||
cpp_type_.destruct_n(data.data(), data.size());
|
||||
MEM_freeN(data.data());
|
||||
}
|
||||
}
|
||||
|
||||
void get_internal(const int64_t index, void *r_value) const override
|
||||
{
|
||||
data.type().copy_to_uninitialized(data[index], r_value);
|
||||
}
|
||||
|
||||
void set_internal(const int64_t index, const void *value) override
|
||||
{
|
||||
data.type().copy_to_initialized(value, data[index]);
|
||||
}
|
||||
|
||||
void initialize_span(const bool UNUSED(write_only)) override
|
||||
{
|
||||
array_buffer_ = data.data();
|
||||
array_is_temporary_ = false;
|
||||
}
|
||||
|
||||
void apply_span_if_necessary() override
|
||||
{
|
||||
/* Do nothing, because the span contains the attribute itself already. */
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> class ArrayReadAttribute final : public ReadAttribute {
|
||||
private:
|
||||
Span<T> data_;
|
||||
|
@ -762,30 +812,117 @@ blender::bke::ReadAttributePtr GeometryComponent::attribute_get_constant_for_rea
|
|||
return attribute;
|
||||
}
|
||||
|
||||
WriteAttributePtr GeometryComponent::attribute_try_ensure_for_write(const StringRef attribute_name,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type)
|
||||
OutputAttributePtr GeometryComponent::attribute_try_get_for_output(const StringRef attribute_name,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type)
|
||||
{
|
||||
BLI_assert(this->attribute_domain_with_type_supported(domain, data_type));
|
||||
|
||||
const blender::fn::CPPType *cpp_type = blender::bke::custom_data_type_to_cpp_type(data_type);
|
||||
BLI_assert(cpp_type != nullptr);
|
||||
|
||||
WriteAttributePtr attribute = this->attribute_try_get_for_write(attribute_name);
|
||||
if (attribute && attribute->domain() == domain && attribute->cpp_type() == *cpp_type) {
|
||||
return attribute;
|
||||
|
||||
/* If the attribute doesn't exist, make a new one with the correct type. */
|
||||
if (!attribute) {
|
||||
this->attribute_try_create(attribute_name, domain, data_type);
|
||||
attribute = this->attribute_try_get_for_write(attribute_name);
|
||||
return OutputAttributePtr(std::move(attribute));
|
||||
}
|
||||
|
||||
if (attribute) {
|
||||
if (!this->attribute_try_delete(attribute_name)) {
|
||||
return {};
|
||||
}
|
||||
/* If an existing attribute has a matching domain and type, just use that. */
|
||||
if (attribute->domain() == domain && attribute->cpp_type() == *cpp_type) {
|
||||
return OutputAttributePtr(std::move(attribute));
|
||||
}
|
||||
if (!this->attribute_domain_with_type_supported(domain, data_type)) {
|
||||
return {};
|
||||
|
||||
/* Otherwise create a temporary buffer to use before saving the new attribute. */
|
||||
return OutputAttributePtr(*this, domain, attribute_name, data_type);
|
||||
}
|
||||
|
||||
/* Construct from an attribute that already exists in the geometry component. */
|
||||
OutputAttributePtr::OutputAttributePtr(WriteAttributePtr attribute)
|
||||
: attribute_(std::move(attribute))
|
||||
{
|
||||
}
|
||||
|
||||
/* Construct a temporary attribute that has to replace an existing one later on. */
|
||||
OutputAttributePtr::OutputAttributePtr(GeometryComponent &component,
|
||||
AttributeDomain domain,
|
||||
std::string final_name,
|
||||
CustomDataType data_type)
|
||||
{
|
||||
const blender::fn::CPPType *cpp_type = blender::bke::custom_data_type_to_cpp_type(data_type);
|
||||
BLI_assert(cpp_type != nullptr);
|
||||
|
||||
const int domain_size = component.attribute_domain_size(domain);
|
||||
void *buffer = MEM_malloc_arrayN(domain_size, cpp_type->size(), __func__);
|
||||
cpp_type->construct_default_n(buffer, domain_size);
|
||||
|
||||
attribute_ = std::make_unique<blender::bke::TemporaryWriteAttribute>(
|
||||
domain, GMutableSpan{*cpp_type, buffer, domain_size}, component, std::move(final_name));
|
||||
}
|
||||
|
||||
/* Store the computed attribute. If it was stored from the beginning already, nothing is done. This
|
||||
* might delete another attribute with the same name. */
|
||||
void OutputAttributePtr::save()
|
||||
{
|
||||
if (!attribute_) {
|
||||
CLOG_WARN(&LOG, "Trying to save an attribute that does not exist anymore.");
|
||||
return;
|
||||
}
|
||||
if (!this->attribute_try_create(attribute_name, domain, data_type)) {
|
||||
return {};
|
||||
|
||||
blender::bke::TemporaryWriteAttribute *attribute =
|
||||
dynamic_cast<blender::bke::TemporaryWriteAttribute *>(attribute_.get());
|
||||
|
||||
if (attribute == nullptr) {
|
||||
/* The attribute is saved already. */
|
||||
attribute_.reset();
|
||||
return;
|
||||
}
|
||||
return this->attribute_try_get_for_write(attribute_name);
|
||||
|
||||
StringRefNull name = attribute->final_name;
|
||||
const blender::fn::CPPType &cpp_type = attribute->cpp_type();
|
||||
|
||||
/* Delete an existing attribute with the same name if necessary. */
|
||||
attribute->component.attribute_try_delete(name);
|
||||
|
||||
if (!attribute->component.attribute_try_create(
|
||||
name, attribute_->domain(), attribute_->custom_data_type())) {
|
||||
/* Cannot create the target attribute for some reason. */
|
||||
CLOG_WARN(&LOG,
|
||||
"Creating the '%s' attribute with type '%s' failed.",
|
||||
name.c_str(),
|
||||
cpp_type.name().c_str());
|
||||
attribute_.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
WriteAttributePtr new_attribute = attribute->component.attribute_try_get_for_write(name);
|
||||
|
||||
GMutableSpan temp_span = attribute->data;
|
||||
GMutableSpan new_span = new_attribute->get_span_for_write_only();
|
||||
BLI_assert(temp_span.size() == new_span.size());
|
||||
|
||||
/* Currently we copy over the attribute. In the future we want to reuse the buffer. */
|
||||
cpp_type.move_to_initialized_n(temp_span.data(), new_span.data(), new_span.size());
|
||||
new_attribute->apply_span();
|
||||
|
||||
attribute_.reset();
|
||||
}
|
||||
|
||||
OutputAttributePtr::~OutputAttributePtr()
|
||||
{
|
||||
if (attribute_) {
|
||||
CLOG_ERROR(&LOG, "Forgot to call #save or #apply_span_and_save.");
|
||||
}
|
||||
}
|
||||
|
||||
/* Utility function to call #apply_span and #save in the right order. */
|
||||
void OutputAttributePtr::apply_span_and_save()
|
||||
{
|
||||
BLI_assert(attribute_);
|
||||
attribute_->apply_span();
|
||||
this->save();
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -1032,7 +1032,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
|
|||
brush->gpencil_settings->fill_leak = 3;
|
||||
brush->gpencil_settings->fill_threshold = 0.1f;
|
||||
brush->gpencil_settings->fill_simplylvl = 1;
|
||||
brush->gpencil_settings->fill_factor = 1;
|
||||
brush->gpencil_settings->fill_factor = 1.0f;
|
||||
|
||||
brush->gpencil_settings->draw_strength = 1.0f;
|
||||
brush->gpencil_settings->hardeness = 1.0f;
|
||||
|
|
|
@ -2519,7 +2519,7 @@ void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer,
|
|||
int cfra)
|
||||
{
|
||||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
const bool is_multiedit = GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
|
||||
const bool is_multiedit = ((GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) && (!GPENCIL_PLAY_ON(gpd)));
|
||||
const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0);
|
||||
const bool is_drawing = (gpd->runtime.sbuffer_used > 0);
|
||||
|
||||
|
|
|
@ -214,6 +214,7 @@ void GPENCIL_cache_init(void *ved)
|
|||
NULL :
|
||||
false;
|
||||
pd->do_onion = show_onion && !hide_overlay && !playing;
|
||||
pd->playing = playing;
|
||||
/* Save simplify flags (can change while drawing, so it's better to save). */
|
||||
Scene *scene = draw_ctx->scene;
|
||||
pd->simplify_fill = GPENCIL_SIMPLIFY_FILL(scene, playing);
|
||||
|
@ -241,6 +242,7 @@ void GPENCIL_cache_init(void *ved)
|
|||
pd->simplify_fill = false;
|
||||
pd->simplify_fx = false;
|
||||
pd->fade_layer_opacity = -1.0f;
|
||||
pd->playing = false;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -617,7 +619,7 @@ void GPENCIL_cache_populate(void *ved, Object *ob)
|
|||
/* Special case for rendering onion skin. */
|
||||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
bool do_onion = (!pd->is_render) ? pd->do_onion : (gpd->onion_flag & GP_ONION_GHOST_ALWAYS);
|
||||
|
||||
gpd->runtime.playing = (short)pd->playing;
|
||||
BKE_gpencil_visible_stroke_iter(is_final_render ? pd->view_layer : NULL,
|
||||
ob,
|
||||
gpencil_layer_cache_populate,
|
||||
|
|
|
@ -342,6 +342,8 @@ typedef struct GPENCIL_PrivateData {
|
|||
|
||||
/* Display onion skinning */
|
||||
bool do_onion;
|
||||
/* Playing animation */
|
||||
bool playing;
|
||||
/* simplify settings */
|
||||
bool simplify_fill;
|
||||
bool simplify_fx;
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
|
||||
#define LEAK_HORZ 0
|
||||
#define LEAK_VERT 1
|
||||
#define MIN_WINDOW_SIZE 128
|
||||
|
||||
/* Temporary fill operation data (op->customdata) */
|
||||
typedef struct tGPDfill {
|
||||
|
@ -137,7 +138,7 @@ typedef struct tGPDfill {
|
|||
/** boundary limits drawing mode */
|
||||
int fill_draw_mode;
|
||||
/* scaling factor */
|
||||
short fill_factor;
|
||||
float fill_factor;
|
||||
|
||||
/* Frame to use. */
|
||||
int active_cfra;
|
||||
|
@ -398,8 +399,8 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf)
|
|||
/* resize region */
|
||||
tgpf->region->winrct.xmin = 0;
|
||||
tgpf->region->winrct.ymin = 0;
|
||||
tgpf->region->winrct.xmax = (int)tgpf->region->winx * tgpf->fill_factor;
|
||||
tgpf->region->winrct.ymax = (int)tgpf->region->winy * tgpf->fill_factor;
|
||||
tgpf->region->winrct.xmax = max_ii((int)tgpf->region->winx * tgpf->fill_factor, MIN_WINDOW_SIZE);
|
||||
tgpf->region->winrct.ymax = max_ii((int)tgpf->region->winy * tgpf->fill_factor, MIN_WINDOW_SIZE);
|
||||
tgpf->region->winx = (short)abs(tgpf->region->winrct.xmax - tgpf->region->winrct.xmin);
|
||||
tgpf->region->winy = (short)abs(tgpf->region->winrct.ymax - tgpf->region->winrct.ymin);
|
||||
|
||||
|
@ -456,7 +457,7 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf)
|
|||
}
|
||||
|
||||
GPU_matrix_push_projection();
|
||||
GPU_matrix_identity_set();
|
||||
GPU_matrix_identity_projection_set();
|
||||
GPU_matrix_push();
|
||||
GPU_matrix_identity_set();
|
||||
|
||||
|
@ -1394,11 +1395,12 @@ static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *UNUSED(op))
|
|||
Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
|
||||
tgpf->brush = brush;
|
||||
tgpf->flag = brush->gpencil_settings->flag;
|
||||
tgpf->fill_leak = brush->gpencil_settings->fill_leak;
|
||||
tgpf->fill_threshold = brush->gpencil_settings->fill_threshold;
|
||||
tgpf->fill_simplylvl = brush->gpencil_settings->fill_simplylvl;
|
||||
tgpf->fill_draw_mode = brush->gpencil_settings->fill_draw_mode;
|
||||
tgpf->fill_factor = (short)max_ii(1, min_ii((int)brush->gpencil_settings->fill_factor, 8));
|
||||
tgpf->fill_factor = max_ff(GPENCIL_MIN_FILL_FAC,
|
||||
min_ff(brush->gpencil_settings->fill_factor, 8.0f));
|
||||
tgpf->fill_leak = (int)ceil((float)brush->gpencil_settings->fill_leak * tgpf->fill_factor);
|
||||
|
||||
int totcol = tgpf->ob->totcol;
|
||||
|
||||
|
|
|
@ -61,28 +61,22 @@ int ED_gpencil_session_active(void)
|
|||
return (BLI_listbase_is_empty(&undo_nodes) == false);
|
||||
}
|
||||
|
||||
int ED_undo_gpencil_step(bContext *C, int step, const char *name)
|
||||
int ED_undo_gpencil_step(bContext *C, const int step)
|
||||
{
|
||||
bGPdata **gpd_ptr = NULL, *new_gpd = NULL;
|
||||
|
||||
gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
|
||||
|
||||
if (step == 1) { /* undo */
|
||||
// printf("\t\tGP - undo step\n");
|
||||
if (step == -1) { /* undo */
|
||||
if (cur_node->prev) {
|
||||
if (!name || STREQ(cur_node->name, name)) {
|
||||
cur_node = cur_node->prev;
|
||||
new_gpd = cur_node->gpd;
|
||||
}
|
||||
cur_node = cur_node->prev;
|
||||
new_gpd = cur_node->gpd;
|
||||
}
|
||||
}
|
||||
else if (step == -1) {
|
||||
// printf("\t\tGP - redo step\n");
|
||||
else if (step == 1) {
|
||||
if (cur_node->next) {
|
||||
if (!name || STREQ(cur_node->name, name)) {
|
||||
cur_node = cur_node->next;
|
||||
new_gpd = cur_node->gpd;
|
||||
}
|
||||
cur_node = cur_node->next;
|
||||
new_gpd = cur_node->gpd;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ bool ED_gpencil_anim_copybuf_paste(struct bAnimContext *ac, const short copy_mod
|
|||
|
||||
/* ------------ Grease-Pencil Undo System ------------------ */
|
||||
int ED_gpencil_session_active(void);
|
||||
int ED_undo_gpencil_step(struct bContext *C, int step, const char *name);
|
||||
int ED_undo_gpencil_step(struct bContext *C, const int step);
|
||||
|
||||
/* ------------ Grease-Pencil Armature ------------------ */
|
||||
bool ED_gpencil_add_armature(const struct bContext *C,
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "ED_space_api.h"
|
||||
#include "ED_transform.h"
|
||||
#include "ED_userpref.h"
|
||||
#include "ED_util.h"
|
||||
#include "ED_uvedit.h"
|
||||
|
||||
#include "io_ops.h"
|
||||
|
@ -124,6 +125,7 @@ void ED_spacetypes_init(void)
|
|||
ED_operatortypes_render();
|
||||
ED_operatortypes_mask();
|
||||
ED_operatortypes_io();
|
||||
ED_operatortypes_edutils();
|
||||
|
||||
ED_operatortypes_view2d();
|
||||
ED_operatortypes_ui();
|
||||
|
|
|
@ -987,7 +987,10 @@ static void clip_main_region_draw(const bContext *C, ARegion *region)
|
|||
}
|
||||
|
||||
/* callback */
|
||||
GPU_matrix_push_projection();
|
||||
wmOrtho2(region->v2d.cur.xmin, region->v2d.cur.xmax, region->v2d.cur.ymin, region->v2d.cur.ymax);
|
||||
ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
|
||||
GPU_matrix_pop_projection();
|
||||
|
||||
/* reset view matrix */
|
||||
UI_view2d_view_restore(C);
|
||||
|
|
|
@ -104,6 +104,7 @@ static ARegion *file_tool_props_region_ensure(ScrArea *area, ARegion *region_pre
|
|||
BLI_insertlinkafter(&area->regionbase, region_prev, region);
|
||||
region->regiontype = RGN_TYPE_TOOL_PROPS;
|
||||
region->alignment = RGN_ALIGN_RIGHT;
|
||||
region->flag = RGN_FLAG_HIDDEN;
|
||||
|
||||
return region;
|
||||
}
|
||||
|
@ -246,13 +247,13 @@ static void file_ensure_valid_region_state(bContext *C,
|
|||
BLI_assert(region_tools);
|
||||
|
||||
if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS) {
|
||||
ARegion *region_execute = file_execute_region_ensure(area, region_tools);
|
||||
ARegion *region_props = file_tool_props_region_ensure(area, region_execute);
|
||||
|
||||
/* Hide specific regions by default. */
|
||||
region_props->flag |= RGN_FLAG_HIDDEN;
|
||||
region_execute->flag |= RGN_FLAG_HIDDEN;
|
||||
file_tool_props_region_ensure(area, region_tools);
|
||||
|
||||
ARegion *region_execute = BKE_area_find_region_type(area, RGN_TYPE_EXECUTE);
|
||||
if (region_execute) {
|
||||
ED_region_remove(C, area, region_execute);
|
||||
needs_init = true;
|
||||
}
|
||||
ARegion *region_ui = BKE_area_find_region_type(area, RGN_TYPE_UI);
|
||||
if (region_ui) {
|
||||
ED_region_remove(C, area, region_ui);
|
||||
|
@ -281,13 +282,14 @@ static void file_ensure_valid_region_state(bContext *C,
|
|||
ARegion *region_ui = file_ui_region_ensure(area, region_tools);
|
||||
UNUSED_VARS(region_ui);
|
||||
|
||||
if (region_props) {
|
||||
BLI_assert(region_execute);
|
||||
|
||||
ED_region_remove(C, area, region_props);
|
||||
if (region_execute) {
|
||||
ED_region_remove(C, area, region_execute);
|
||||
needs_init = true;
|
||||
}
|
||||
if (region_props) {
|
||||
ED_region_remove(C, area, region_props);
|
||||
needs_init = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_init) {
|
||||
|
|
|
@ -946,6 +946,24 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv
|
|||
}
|
||||
}
|
||||
|
||||
/* For tweak events the snap target may have changed since dragging,
|
||||
* update the snap target at the cursor location where tweak began.
|
||||
*
|
||||
* NOTE: we could investigating solving this in a more generic way,
|
||||
* so each operator doesn't have to account for it. */
|
||||
if (ISTWEAK(event->type)) {
|
||||
if (ipd->snap_gizmo != NULL) {
|
||||
ED_gizmotypes_snap_3d_update(ipd->snap_gizmo,
|
||||
CTX_data_ensure_evaluated_depsgraph(C),
|
||||
ipd->region,
|
||||
ipd->v3d,
|
||||
G_MAIN->wm.first,
|
||||
mval_fl,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
ipd->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
|
||||
|
||||
view3d_interactive_add_calc_plane(C,
|
||||
|
|
|
@ -52,6 +52,7 @@ typedef struct TransDataTracking {
|
|||
|
||||
float (*smarkers)[2];
|
||||
int markersnr;
|
||||
int framenr;
|
||||
MovieTrackingMarker *markers;
|
||||
|
||||
/* marker transformation from curves editor */
|
||||
|
@ -73,9 +74,25 @@ enum transDataTracking_Mode {
|
|||
*
|
||||
* \{ */
|
||||
|
||||
static void markerToTransDataInit(TransData *td,
|
||||
TransData2D *td2d,
|
||||
TransDataTracking *tdt,
|
||||
typedef struct TransformInitContext {
|
||||
SpaceClip *space_clip;
|
||||
|
||||
TransInfo *t;
|
||||
TransDataContainer *tc;
|
||||
|
||||
/* MOTE: There pointers will be nullptr during counting step.
|
||||
* This means, that the transformation data initialization functions are to increment
|
||||
* `tc->data_len` instead of filling in the transformation data when these pointers are nullptr.
|
||||
* For simplicitly, check the `current.td` against nullptr.
|
||||
* Do not `tc->data_len` when filling in the transformation data. */
|
||||
struct {
|
||||
TransData *td;
|
||||
TransData2D *td2d;
|
||||
TransDataTracking *tdt;
|
||||
} current;
|
||||
} TransformInitContext;
|
||||
|
||||
static void markerToTransDataInit(TransformInitContext *init_context,
|
||||
MovieTrackingTrack *track,
|
||||
MovieTrackingMarker *marker,
|
||||
int area,
|
||||
|
@ -84,8 +101,19 @@ static void markerToTransDataInit(TransData *td,
|
|||
const float off[2],
|
||||
const float aspect[2])
|
||||
{
|
||||
TransData *td = init_context->current.td;
|
||||
TransData2D *td2d = init_context->current.td2d;
|
||||
TransDataTracking *tdt = init_context->current.tdt;
|
||||
|
||||
if (td == NULL) {
|
||||
init_context->tc->data_len++;
|
||||
return;
|
||||
}
|
||||
|
||||
int anchor = area == TRACK_AREA_POINT && off;
|
||||
|
||||
tdt->flag = marker->flag;
|
||||
tdt->framenr = marker->framenr;
|
||||
tdt->mode = transDataTracking_ModeTracks;
|
||||
|
||||
if (anchor) {
|
||||
|
@ -143,23 +171,20 @@ static void markerToTransDataInit(TransData *td,
|
|||
|
||||
unit_m3(td->mtx);
|
||||
unit_m3(td->smtx);
|
||||
|
||||
init_context->current.td++;
|
||||
init_context->current.td2d++;
|
||||
init_context->current.tdt++;
|
||||
}
|
||||
|
||||
static void trackToTransData(const int framenr,
|
||||
TransData *td,
|
||||
TransData2D *td2d,
|
||||
TransDataTracking *tdt,
|
||||
static void trackToTransData(TransformInitContext *init_context,
|
||||
const int framenr,
|
||||
MovieTrackingTrack *track,
|
||||
const float aspect[2])
|
||||
{
|
||||
MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
|
||||
|
||||
tdt->flag = marker->flag;
|
||||
marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
|
||||
|
||||
markerToTransDataInit(td++,
|
||||
td2d++,
|
||||
tdt++,
|
||||
markerToTransDataInit(init_context,
|
||||
track,
|
||||
marker,
|
||||
TRACK_AREA_POINT,
|
||||
|
@ -170,16 +195,14 @@ static void trackToTransData(const int framenr,
|
|||
|
||||
if (track->flag & SELECT) {
|
||||
markerToTransDataInit(
|
||||
td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT, marker->pos, NULL, NULL, aspect);
|
||||
init_context, track, marker, TRACK_AREA_POINT, marker->pos, NULL, NULL, aspect);
|
||||
}
|
||||
|
||||
if (track->pat_flag & SELECT) {
|
||||
int a;
|
||||
|
||||
for (a = 0; a < 4; a++) {
|
||||
markerToTransDataInit(td++,
|
||||
td2d++,
|
||||
tdt++,
|
||||
markerToTransDataInit(init_context,
|
||||
track,
|
||||
marker,
|
||||
TRACK_AREA_PAT,
|
||||
|
@ -191,9 +214,7 @@ static void trackToTransData(const int framenr,
|
|||
}
|
||||
|
||||
if (track->search_flag & SELECT) {
|
||||
markerToTransDataInit(td++,
|
||||
td2d++,
|
||||
tdt++,
|
||||
markerToTransDataInit(init_context,
|
||||
track,
|
||||
marker,
|
||||
TRACK_AREA_SEARCH,
|
||||
|
@ -202,9 +223,7 @@ static void trackToTransData(const int framenr,
|
|||
NULL,
|
||||
aspect);
|
||||
|
||||
markerToTransDataInit(td++,
|
||||
td2d++,
|
||||
tdt++,
|
||||
markerToTransDataInit(init_context,
|
||||
track,
|
||||
marker,
|
||||
TRACK_AREA_SEARCH,
|
||||
|
@ -213,15 +232,43 @@ static void trackToTransData(const int framenr,
|
|||
NULL,
|
||||
aspect);
|
||||
}
|
||||
|
||||
if (init_context->current.td != NULL) {
|
||||
marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
|
||||
}
|
||||
}
|
||||
|
||||
static void planeMarkerToTransDataInit(TransData *td,
|
||||
TransData2D *td2d,
|
||||
TransDataTracking *tdt,
|
||||
static void trackToTransDataIfNeeded(TransformInitContext *init_context,
|
||||
const int framenr,
|
||||
MovieTrackingTrack *track,
|
||||
const float aspect[2])
|
||||
{
|
||||
if (!TRACK_VIEW_SELECTED(init_context->space_clip, track)) {
|
||||
return;
|
||||
}
|
||||
if (track->flag & TRACK_LOCKED) {
|
||||
return;
|
||||
}
|
||||
trackToTransData(init_context, framenr, track, aspect);
|
||||
}
|
||||
|
||||
static void planeMarkerToTransDataInit(TransformInitContext *init_context,
|
||||
MovieTrackingPlaneTrack *plane_track,
|
||||
MovieTrackingPlaneMarker *plane_marker,
|
||||
float corner[2],
|
||||
const float aspect[2])
|
||||
{
|
||||
TransData *td = init_context->current.td;
|
||||
TransData2D *td2d = init_context->current.td2d;
|
||||
TransDataTracking *tdt = init_context->current.tdt;
|
||||
|
||||
if (td == NULL) {
|
||||
init_context->tc->data_len++;
|
||||
return;
|
||||
}
|
||||
|
||||
tdt->flag = plane_marker->flag;
|
||||
tdt->framenr = plane_marker->framenr;
|
||||
tdt->mode = transDataTracking_ModePlaneTracks;
|
||||
tdt->plane_track = plane_track;
|
||||
|
||||
|
@ -247,24 +294,38 @@ static void planeMarkerToTransDataInit(TransData *td,
|
|||
|
||||
unit_m3(td->mtx);
|
||||
unit_m3(td->smtx);
|
||||
|
||||
init_context->current.td++;
|
||||
init_context->current.td2d++;
|
||||
init_context->current.tdt++;
|
||||
}
|
||||
|
||||
static void planeTrackToTransData(const int framenr,
|
||||
TransData *td,
|
||||
TransData2D *td2d,
|
||||
TransDataTracking *tdt,
|
||||
static void planeTrackToTransData(TransformInitContext *init_context,
|
||||
const int framenr,
|
||||
MovieTrackingPlaneTrack *plane_track,
|
||||
const float aspect[2])
|
||||
{
|
||||
MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
|
||||
int i;
|
||||
|
||||
tdt->flag = plane_marker->flag;
|
||||
plane_marker->flag &= ~PLANE_MARKER_TRACKED;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspect);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
planeMarkerToTransDataInit(
|
||||
init_context, plane_track, plane_marker, plane_marker->corners[i], aspect);
|
||||
}
|
||||
|
||||
if (init_context->current.td != NULL) {
|
||||
plane_marker->flag &= ~PLANE_MARKER_TRACKED;
|
||||
}
|
||||
}
|
||||
|
||||
static void planeTrackToTransDataIfNeeded(TransformInitContext *init_context,
|
||||
const int framenr,
|
||||
MovieTrackingPlaneTrack *plane_track,
|
||||
const float aspect[2])
|
||||
{
|
||||
if (!PLANE_TRACK_VIEW_SELECTED(plane_track)) {
|
||||
return;
|
||||
}
|
||||
planeTrackToTransData(init_context, framenr, plane_track, aspect);
|
||||
}
|
||||
|
||||
static void transDataTrackingFree(TransInfo *UNUSED(t),
|
||||
|
@ -284,101 +345,53 @@ static void transDataTrackingFree(TransInfo *UNUSED(t),
|
|||
|
||||
static void createTransTrackingTracksData(bContext *C, TransInfo *t)
|
||||
{
|
||||
TransData *td;
|
||||
TransData2D *td2d;
|
||||
SpaceClip *sc = CTX_wm_space_clip(C);
|
||||
MovieClip *clip = ED_space_clip_get_clip(sc);
|
||||
ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
|
||||
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
|
||||
MovieTrackingTrack *track;
|
||||
MovieTrackingPlaneTrack *plane_track;
|
||||
TransDataTracking *tdt;
|
||||
int framenr = ED_space_clip_get_clip_frame_number(sc);
|
||||
SpaceClip *space_clip = CTX_wm_space_clip(C);
|
||||
MovieClip *clip = ED_space_clip_get_clip(space_clip);
|
||||
const ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
|
||||
const ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
|
||||
const int framenr = ED_space_clip_get_clip_frame_number(space_clip);
|
||||
|
||||
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
|
||||
|
||||
/* count */
|
||||
TransformInitContext init_context = {NULL};
|
||||
init_context.space_clip = space_clip;
|
||||
init_context.t = t;
|
||||
init_context.tc = tc;
|
||||
|
||||
/* Count required tranformation data. */
|
||||
|
||||
tc->data_len = 0;
|
||||
|
||||
track = tracksbase->first;
|
||||
while (track) {
|
||||
if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
|
||||
tc->data_len++; /* offset */
|
||||
|
||||
if (track->flag & SELECT) {
|
||||
tc->data_len++;
|
||||
}
|
||||
|
||||
if (track->pat_flag & SELECT) {
|
||||
tc->data_len += 4;
|
||||
}
|
||||
|
||||
if (track->search_flag & SELECT) {
|
||||
tc->data_len += 2;
|
||||
}
|
||||
}
|
||||
|
||||
track = track->next;
|
||||
LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
|
||||
trackToTransDataIfNeeded(&init_context, framenr, track, t->aspect);
|
||||
}
|
||||
|
||||
for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
|
||||
if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
|
||||
tc->data_len += 4;
|
||||
}
|
||||
LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
|
||||
planeTrackToTransDataIfNeeded(&init_context, framenr, plane_track, t->aspect);
|
||||
}
|
||||
|
||||
if (tc->data_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData");
|
||||
td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D),
|
||||
"TransTracking TransData2D");
|
||||
tdt = tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataTracking),
|
||||
"TransTracking TransDataTracking");
|
||||
|
||||
tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData");
|
||||
tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransTracking TransData2D");
|
||||
tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataTracking),
|
||||
"TransTracking TransDataTracking");
|
||||
tc->custom.type.free_cb = transDataTrackingFree;
|
||||
|
||||
/* create actual data */
|
||||
track = tracksbase->first;
|
||||
while (track) {
|
||||
if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
|
||||
trackToTransData(framenr, td, td2d, tdt, track, t->aspect);
|
||||
init_context.current.td = tc->data;
|
||||
init_context.current.td2d = tc->data_2d;
|
||||
init_context.current.tdt = tc->custom.type.data;
|
||||
|
||||
/* offset */
|
||||
td++;
|
||||
td2d++;
|
||||
tdt++;
|
||||
/* Create actual transformation data. */
|
||||
|
||||
if (track->flag & SELECT) {
|
||||
td++;
|
||||
td2d++;
|
||||
tdt++;
|
||||
}
|
||||
|
||||
if (track->pat_flag & SELECT) {
|
||||
td += 4;
|
||||
td2d += 4;
|
||||
tdt += 4;
|
||||
}
|
||||
|
||||
if (track->search_flag & SELECT) {
|
||||
td += 2;
|
||||
td2d += 2;
|
||||
tdt += 2;
|
||||
}
|
||||
}
|
||||
|
||||
track = track->next;
|
||||
LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
|
||||
trackToTransDataIfNeeded(&init_context, framenr, track, t->aspect);
|
||||
}
|
||||
|
||||
for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
|
||||
if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
|
||||
planeTrackToTransData(framenr, td, td2d, tdt, plane_track, t->aspect);
|
||||
td += 4;
|
||||
td2d += 4;
|
||||
tdt += 4;
|
||||
}
|
||||
LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
|
||||
planeTrackToTransDataIfNeeded(&init_context, framenr, plane_track, t->aspect);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -560,17 +573,17 @@ void createTransTrackingData(bContext *C, TransInfo *t)
|
|||
static void cancelTransTracking(TransInfo *t)
|
||||
{
|
||||
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
|
||||
SpaceClip *sc = t->area->spacedata.first;
|
||||
int i, framenr = ED_space_clip_get_clip_frame_number(sc);
|
||||
TransDataTracking *tdt_array = tc->custom.type.data;
|
||||
|
||||
i = 0;
|
||||
int i = 0;
|
||||
while (i < tc->data_len) {
|
||||
TransDataTracking *tdt = &tdt_array[i];
|
||||
|
||||
if (tdt->mode == transDataTracking_ModeTracks) {
|
||||
MovieTrackingTrack *track = tdt->track;
|
||||
MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
|
||||
MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, tdt->framenr);
|
||||
|
||||
BLI_assert(marker != NULL);
|
||||
|
||||
marker->flag = tdt->flag;
|
||||
|
||||
|
@ -606,7 +619,10 @@ static void cancelTransTracking(TransInfo *t)
|
|||
}
|
||||
else if (tdt->mode == transDataTracking_ModePlaneTracks) {
|
||||
MovieTrackingPlaneTrack *plane_track = tdt->plane_track;
|
||||
MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
|
||||
MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track,
|
||||
tdt->framenr);
|
||||
|
||||
BLI_assert(plane_marker != NULL);
|
||||
|
||||
plane_marker->flag = tdt->flag;
|
||||
i += 3;
|
||||
|
|
|
@ -3026,7 +3026,11 @@ static short transform_snap_context_project_view3d_mixed_impl(
|
|||
|
||||
bool has_hit = false;
|
||||
Object *ob = NULL;
|
||||
float loc[3], no[3], obmat[4][4];
|
||||
float loc[3];
|
||||
/* Not all snapping callbacks set the normal,
|
||||
* initialize this since any hit copies both the `loc` and `no`. */
|
||||
float no[3] = {0.0f, 0.0f, 0.0f};
|
||||
float obmat[4][4];
|
||||
int index = -1;
|
||||
|
||||
const ARegion *region = sctx->v3d_data.region;
|
||||
|
|
|
@ -70,6 +70,17 @@
|
|||
/** We only need this locally. */
|
||||
static CLG_LogRef LOG = {"ed.undo"};
|
||||
|
||||
/**
|
||||
* \warning Values are used in #ED_undo_gpencil_step,
|
||||
* which should eventually be replaced with the undo-system.
|
||||
*/
|
||||
enum eUndoStepDir {
|
||||
STEP_REDO = 1,
|
||||
STEP_UNDO = -1,
|
||||
/** Only used when the undo step name or index is passed to #ed_undo_step_impl. */
|
||||
STEP_NONE = 0,
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Generic Undo System Access
|
||||
*
|
||||
|
@ -171,13 +182,16 @@ void ED_undo_push(bContext *C, const char *str)
|
|||
/**
|
||||
* \note Also check #undo_history_exec in bottom if you change notifiers.
|
||||
*/
|
||||
static int ed_undo_step_impl(
|
||||
bContext *C, int step, const char *undoname, int undo_index, ReportList *reports)
|
||||
static int ed_undo_step_impl(bContext *C,
|
||||
enum eUndoStepDir step,
|
||||
const char *undo_name,
|
||||
const int undo_index,
|
||||
ReportList *reports)
|
||||
{
|
||||
/* Mutually exclusives, ensure correct input. */
|
||||
BLI_assert(((undoname || undo_index != -1) && !step) ||
|
||||
(!(undoname || undo_index != -1) && step));
|
||||
CLOG_INFO(&LOG, 1, "name='%s', step=%d", undoname, step);
|
||||
BLI_assert(((undo_name || undo_index != -1) && (step == STEP_NONE)) ||
|
||||
(!(undo_name || undo_index != -1) && (step != STEP_NONE)));
|
||||
CLOG_INFO(&LOG, 1, "name='%s', index=%d, step=%d", undo_name, undo_index, step);
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
|
@ -196,8 +210,12 @@ static int ed_undo_step_impl(
|
|||
|
||||
/* TODO(campbell): undo_system: use undo system */
|
||||
/* grease pencil can be can be used in plenty of spaces, so check it first */
|
||||
/* FIXME: This gpencil undo effectively only supports the one step undo/redo, undo based on name
|
||||
* or index is fully not implemented.
|
||||
* FIXME: However, it seems to never be used in current code (`ED_gpencil_session_active` seems
|
||||
* to always return false). */
|
||||
if (ED_gpencil_session_active()) {
|
||||
return ED_undo_gpencil_step(C, step, undoname);
|
||||
return ED_undo_gpencil_step(C, (int)step);
|
||||
}
|
||||
if (area && (area->spacetype == SPACE_VIEW3D)) {
|
||||
Object *obact = CTX_data_active_object(C);
|
||||
|
@ -207,9 +225,9 @@ static int ed_undo_step_impl(
|
|||
}
|
||||
|
||||
UndoStep *step_data_from_name = NULL;
|
||||
int step_for_callback = step;
|
||||
if (undoname != NULL) {
|
||||
step_data_from_name = BKE_undosys_step_find_by_name(wm->undo_stack, undoname);
|
||||
enum eUndoStepDir step_for_callback = step;
|
||||
if (undo_name != NULL) {
|
||||
step_data_from_name = BKE_undosys_step_find_by_name(wm->undo_stack, undo_name);
|
||||
if (step_data_from_name == NULL) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
@ -218,14 +236,14 @@ static int ed_undo_step_impl(
|
|||
/* Pointers match on redo. */
|
||||
step_for_callback = (BLI_findindex(&wm->undo_stack->steps, step_data_from_name) <
|
||||
BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active)) ?
|
||||
1 :
|
||||
-1;
|
||||
STEP_UNDO :
|
||||
STEP_REDO;
|
||||
}
|
||||
else if (undo_index != -1) {
|
||||
step_for_callback = (undo_index <
|
||||
BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active)) ?
|
||||
1 :
|
||||
-1;
|
||||
STEP_UNDO :
|
||||
STEP_REDO;
|
||||
}
|
||||
|
||||
/* App-Handlers (pre). */
|
||||
|
@ -240,14 +258,14 @@ static int ed_undo_step_impl(
|
|||
|
||||
/* Undo System */
|
||||
{
|
||||
if (undoname) {
|
||||
if (undo_name) {
|
||||
BKE_undosys_step_undo_with_data(wm->undo_stack, C, step_data_from_name);
|
||||
}
|
||||
else if (undo_index != -1) {
|
||||
BKE_undosys_step_undo_from_index(wm->undo_stack, C, undo_index);
|
||||
}
|
||||
else {
|
||||
if (step == 1) {
|
||||
if (step == STEP_UNDO) {
|
||||
BKE_undosys_step_undo(wm->undo_stack, C);
|
||||
}
|
||||
else {
|
||||
|
@ -310,19 +328,19 @@ static int ed_undo_step_impl(
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int ed_undo_step_direction(bContext *C, int step, ReportList *reports)
|
||||
static int ed_undo_step_direction(bContext *C, enum eUndoStepDir step, ReportList *reports)
|
||||
{
|
||||
return ed_undo_step_impl(C, step, NULL, -1, reports);
|
||||
}
|
||||
|
||||
static int ed_undo_step_by_name(bContext *C, const char *undo_name, ReportList *reports)
|
||||
{
|
||||
return ed_undo_step_impl(C, 0, undo_name, -1, reports);
|
||||
return ed_undo_step_impl(C, STEP_NONE, undo_name, -1, reports);
|
||||
}
|
||||
|
||||
static int ed_undo_step_by_index(bContext *C, int index, ReportList *reports)
|
||||
static int ed_undo_step_by_index(bContext *C, const int undo_index, ReportList *reports)
|
||||
{
|
||||
return ed_undo_step_impl(C, 0, NULL, index, reports);
|
||||
return ed_undo_step_impl(C, STEP_NONE, NULL, undo_index, reports);
|
||||
}
|
||||
|
||||
void ED_undo_grouped_push(bContext *C, const char *str)
|
||||
|
@ -340,11 +358,11 @@ void ED_undo_grouped_push(bContext *C, const char *str)
|
|||
|
||||
void ED_undo_pop(bContext *C)
|
||||
{
|
||||
ed_undo_step_direction(C, 1, NULL);
|
||||
ed_undo_step_direction(C, STEP_UNDO, NULL);
|
||||
}
|
||||
void ED_undo_redo(bContext *C)
|
||||
{
|
||||
ed_undo_step_direction(C, -1, NULL);
|
||||
ed_undo_step_direction(C, STEP_REDO, NULL);
|
||||
}
|
||||
|
||||
void ED_undo_push_op(bContext *C, wmOperator *op)
|
||||
|
@ -448,7 +466,7 @@ static int ed_undo_exec(bContext *C, wmOperator *op)
|
|||
{
|
||||
/* "last operator" should disappear, later we can tie this with undo stack nicer */
|
||||
WM_operator_stack_clear(CTX_wm_manager(C));
|
||||
int ret = ed_undo_step_direction(C, 1, op->reports);
|
||||
int ret = ed_undo_step_direction(C, STEP_UNDO, op->reports);
|
||||
if (ret & OPERATOR_FINISHED) {
|
||||
/* Keep button under the cursor active. */
|
||||
WM_event_add_mousemove(CTX_wm_window(C));
|
||||
|
@ -477,7 +495,7 @@ static int ed_undo_push_exec(bContext *C, wmOperator *op)
|
|||
|
||||
static int ed_redo_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
int ret = ed_undo_step_direction(C, -1, op->reports);
|
||||
int ret = ed_undo_step_direction(C, STEP_REDO, op->reports);
|
||||
if (ret & OPERATOR_FINISHED) {
|
||||
/* Keep button under the cursor active. */
|
||||
WM_event_add_mousemove(CTX_wm_window(C));
|
||||
|
|
|
@ -161,6 +161,14 @@ class GMutableSpan {
|
|||
|
||||
void *operator[](int64_t index)
|
||||
{
|
||||
BLI_assert(index >= 0);
|
||||
BLI_assert(index < size_);
|
||||
return POINTER_OFFSET(data_, type_->size() * index);
|
||||
}
|
||||
|
||||
void *operator[](int64_t index) const
|
||||
{
|
||||
BLI_assert(index >= 0);
|
||||
BLI_assert(index < size_);
|
||||
return POINTER_OFFSET(data_, type_->size() * index);
|
||||
}
|
||||
|
|
|
@ -292,6 +292,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
|
|||
uiItemR(col, ptr, "factor_thickness", 0, IFACE_("Thickness"), ICON_NONE);
|
||||
uiItemR(col, ptr, "factor_uvs", 0, IFACE_("UV"), ICON_NONE);
|
||||
uiItemR(col, ptr, "noise_scale", 0, NULL, ICON_NONE);
|
||||
uiItemR(col, ptr, "seed", 0, NULL, ICON_NONE);
|
||||
|
||||
gpencil_modifier_panel_end(layout, ptr);
|
||||
}
|
||||
|
@ -316,7 +317,6 @@ static void random_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
|||
uiLayoutSetActive(layout, RNA_boolean_get(ptr, "random"));
|
||||
|
||||
uiItemR(layout, ptr, "step", 0, NULL, ICON_NONE);
|
||||
uiItemR(layout, ptr, "seed", 0, NULL, ICON_NONE);
|
||||
}
|
||||
|
||||
static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
||||
|
|
|
@ -324,6 +324,11 @@ struct _RGBAZ {
|
|||
|
||||
using RGBAZ = _RGBAZ;
|
||||
|
||||
static half float_to_half_safe(const float value)
|
||||
{
|
||||
return half(clamp_f(value, -HALF_MAX, HALF_MAX));
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
/**
|
||||
|
@ -472,10 +477,10 @@ static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags
|
|||
from = ibuf->rect_float + channels * i * width;
|
||||
|
||||
for (int j = ibuf->x; j > 0; j--) {
|
||||
to->r = from[0];
|
||||
to->g = (channels >= 2) ? from[1] : from[0];
|
||||
to->b = (channels >= 3) ? from[2] : from[0];
|
||||
to->a = (channels >= 4) ? from[3] : 1.0f;
|
||||
to->r = float_to_half_safe(from[0]);
|
||||
to->g = float_to_half_safe((channels >= 2) ? from[1] : from[0]);
|
||||
to->b = float_to_half_safe((channels >= 3) ? from[2] : from[0]);
|
||||
to->a = float_to_half_safe((channels >= 4) ? from[3] : 1.0f);
|
||||
to++;
|
||||
from += channels;
|
||||
}
|
||||
|
@ -1116,7 +1121,7 @@ void IMB_exr_write_channels(void *handle)
|
|||
float *rect = echan->rect;
|
||||
half *cur = current_rect_half;
|
||||
for (size_t i = 0; i < num_pixels; i++, cur++) {
|
||||
*cur = rect[i * echan->xstride];
|
||||
*cur = float_to_half_safe(rect[i * echan->xstride]);
|
||||
}
|
||||
half *rect_to_write = current_rect_half + (data->height - 1L) * data->width;
|
||||
frameBuffer.insert(
|
||||
|
|
|
@ -47,10 +47,13 @@ typedef struct BrushClone {
|
|||
char _pad[4];
|
||||
} BrushClone;
|
||||
|
||||
#define GPENCIL_MIN_FILL_FAC 0.05f
|
||||
|
||||
typedef struct BrushGpencilSettings {
|
||||
/** Amount of smoothing to apply to newly created strokes. */
|
||||
float draw_smoothfac;
|
||||
char _pad2[4];
|
||||
/** Fill zoom factor */
|
||||
float fill_factor;
|
||||
/** Amount of alpha strength to apply to newly created strokes. */
|
||||
float draw_strength;
|
||||
/** Amount of jitter to apply to newly created strokes. */
|
||||
|
@ -75,8 +78,8 @@ typedef struct BrushGpencilSettings {
|
|||
float fill_threshold;
|
||||
/** Number of pixel to consider the leak is too small (x 2). */
|
||||
short fill_leak;
|
||||
/** Fill zoom factor */
|
||||
short fill_factor;
|
||||
char _pad2[2];
|
||||
|
||||
int flag2;
|
||||
|
||||
/** Number of simplify steps. */
|
||||
|
|
|
@ -574,7 +574,9 @@ typedef struct bGPdata_Runtime {
|
|||
/** Temp stroke used for drawing. */
|
||||
struct bGPDstroke *sbuffer_gps;
|
||||
|
||||
char _pad[2];
|
||||
/** Animation playing flag. */
|
||||
short playing;
|
||||
|
||||
/** Material index of the stroke. */
|
||||
short matid;
|
||||
|
||||
|
@ -840,6 +842,8 @@ typedef enum eGP_DrawMode {
|
|||
((flag & (GP_VERTEX_MASK_SELECTMODE_POINT | GP_VERTEX_MASK_SELECTMODE_STROKE | \
|
||||
GP_VERTEX_MASK_SELECTMODE_SEGMENT)))
|
||||
|
||||
#define GPENCIL_PLAY_ON(gpd) ((gpd) && ((gpd)->runtime.playing == 1))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1466,13 +1466,13 @@ static void rna_def_gpencil_options(BlenderRNA *brna)
|
|||
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
|
||||
|
||||
/* fill factor size */
|
||||
prop = RNA_def_property(srna, "fill_factor", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "fill_factor");
|
||||
RNA_def_property_range(prop, 1, 8);
|
||||
prop = RNA_def_property(srna, "fill_factor", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "fill_factor");
|
||||
RNA_def_property_range(prop, GPENCIL_MIN_FILL_FAC, 8.0f);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Resolution",
|
||||
"Multiplier for fill resolution, higher resolution is more accurate but slower");
|
||||
"Precision",
|
||||
"Factor for fill boundary accuracy, higher values are more accurate but slower");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
|
||||
|
||||
|
|
|
@ -489,7 +489,7 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna)
|
|||
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "seed", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_ui_text(prop, "Seed", "Random seed");
|
||||
RNA_def_property_ui_text(prop, "Noise Seed", "Random seed");
|
||||
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "noise_scale", PROP_FLOAT, PROP_FACTOR);
|
||||
|
|
|
@ -9347,7 +9347,6 @@ static void rna_def_node_socket_vector(BlenderRNA *brna,
|
|||
prop = RNA_def_property(srna, "default_value", PROP_FLOAT, subtype);
|
||||
RNA_def_property_float_sdna(prop, NULL, "value");
|
||||
RNA_def_property_float_array_default(prop, value_default);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketStandard_vector_range");
|
||||
RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
|
||||
|
|
|
@ -110,17 +110,26 @@ static bool meshcache_read_mdd_range_from_time(FILE *fp,
|
|||
return false;
|
||||
}
|
||||
|
||||
size_t num_frames_read = 0;
|
||||
size_t num_frames_expect = mdd_head.frame_tot;
|
||||
errno = 0;
|
||||
for (i = 0; i < mdd_head.frame_tot; i++) {
|
||||
fread(&f_time, sizeof(float), 1, fp);
|
||||
num_frames_read += fread(&f_time, sizeof(float), 1, fp);
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
BLI_endian_switch_float(&f_time);
|
||||
#endif
|
||||
if (f_time >= time) {
|
||||
num_frames_expect = i + 1;
|
||||
break;
|
||||
}
|
||||
f_time_prev = f_time;
|
||||
}
|
||||
|
||||
if (num_frames_read != num_frames_expect) {
|
||||
*err_str = errno ? strerror(errno) : "Timestamp read failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i == mdd_head.frame_tot) {
|
||||
frame = (float)(mdd_head.frame_tot - 1);
|
||||
}
|
||||
|
@ -165,12 +174,14 @@ bool MOD_meshcache_read_mdd_index(FILE *fp,
|
|||
return false;
|
||||
}
|
||||
|
||||
size_t num_verts_read = 0;
|
||||
errno = 0;
|
||||
if (factor >= 1.0f) {
|
||||
#if 1
|
||||
float *vco = *vertexCos;
|
||||
uint i;
|
||||
for (i = mdd_head.verts_tot; i != 0; i--, vco += 3) {
|
||||
fread(vco, sizeof(float[3]), 1, fp);
|
||||
num_verts_read += fread(vco, sizeof(float[3]), 1, fp);
|
||||
|
||||
# ifdef __LITTLE_ENDIAN__
|
||||
BLI_endian_switch_float(vco + 0);
|
||||
|
@ -195,7 +206,7 @@ bool MOD_meshcache_read_mdd_index(FILE *fp,
|
|||
uint i;
|
||||
for (i = mdd_head.verts_tot; i != 0; i--, vco += 3) {
|
||||
float tvec[3];
|
||||
fread(tvec, sizeof(float[3]), 1, fp);
|
||||
num_verts_read += fread(tvec, sizeof(float[3]), 1, fp);
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
BLI_endian_switch_float(tvec + 0);
|
||||
|
@ -209,6 +220,11 @@ bool MOD_meshcache_read_mdd_index(FILE *fp,
|
|||
}
|
||||
}
|
||||
|
||||
if (num_verts_read != mdd_head.verts_tot) {
|
||||
*err_str = errno ? strerror(errno) : "Vertex coordinate read failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -151,11 +151,13 @@ bool MOD_meshcache_read_pc2_index(FILE *fp,
|
|||
return false;
|
||||
}
|
||||
|
||||
size_t num_verts_read = 0;
|
||||
errno = 0;
|
||||
if (factor >= 1.0f) {
|
||||
float *vco = *vertexCos;
|
||||
uint i;
|
||||
for (i = pc2_head.verts_tot; i != 0; i--, vco += 3) {
|
||||
fread(vco, sizeof(float[3]), 1, fp);
|
||||
num_verts_read += fread(vco, sizeof(float[3]), 1, fp);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
BLI_endian_switch_float(vco + 0);
|
||||
|
@ -170,7 +172,7 @@ bool MOD_meshcache_read_pc2_index(FILE *fp,
|
|||
uint i;
|
||||
for (i = pc2_head.verts_tot; i != 0; i--, vco += 3) {
|
||||
float tvec[3];
|
||||
fread(tvec, sizeof(float[3]), 1, fp);
|
||||
num_verts_read += fread(tvec, sizeof(float[3]), 1, fp);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
BLI_endian_switch_float(tvec + 0);
|
||||
|
@ -184,6 +186,11 @@ bool MOD_meshcache_read_pc2_index(FILE *fp,
|
|||
}
|
||||
}
|
||||
|
||||
if (num_verts_read != pc2_head.verts_tot) {
|
||||
*err_str = errno ? strerror(errno) : "Vertex coordinate read failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,12 +41,12 @@ static void align_rotations_on_component(GeometryComponent &component,
|
|||
const NodeGeometryAlignRotationToVector &storage = *(const NodeGeometryAlignRotationToVector *)
|
||||
node.storage;
|
||||
|
||||
WriteAttributePtr rotation_attribute = component.attribute_try_ensure_for_write(
|
||||
OutputAttributePtr rotation_attribute = component.attribute_try_get_for_output(
|
||||
"rotation", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
if (!rotation_attribute) {
|
||||
return;
|
||||
}
|
||||
MutableSpan<float3> rotations = rotation_attribute->get_span().typed<float3>();
|
||||
MutableSpan<float3> rotations = rotation_attribute->get_span<float3>();
|
||||
|
||||
FloatReadAttribute factors = params.get_input_attribute<float>(
|
||||
"Factor", component, ATTR_DOMAIN_POINT, 1.0f);
|
||||
|
@ -85,7 +85,7 @@ static void align_rotations_on_component(GeometryComponent &component,
|
|||
rotations[i] = new_rotation;
|
||||
}
|
||||
|
||||
rotation_attribute->apply_span();
|
||||
rotation_attribute.apply_span_and_save();
|
||||
}
|
||||
|
||||
static void geo_node_align_rotation_to_vector_exec(GeoNodeExecParams params)
|
||||
|
|
|
@ -37,15 +37,16 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
|||
const bNode &bnode = params.node();
|
||||
NodeAttributeColorRamp *node_storage = (NodeAttributeColorRamp *)bnode.storage;
|
||||
|
||||
/* Use the type of the input attribute, but create a color attribute if it doesn't exist yet. */
|
||||
const CustomDataType result_type = params.get_input_attribute_data_type(
|
||||
"Attribute", component, CD_PROP_COLOR);
|
||||
/* Always output a color attribute for now. We might want to allow users to customize.
|
||||
* Using the type of an existing attribute could work, but does not have a real benefit
|
||||
* currently. */
|
||||
const CustomDataType result_type = CD_PROP_COLOR;
|
||||
|
||||
const std::string result_name = params.get_input<std::string>("Result");
|
||||
/* Once we support more domains at the user level, we have to decide how the result domain is
|
||||
* chosen. */
|
||||
const AttributeDomain result_domain = ATTR_DOMAIN_POINT;
|
||||
WriteAttributePtr attribute_result = component.attribute_try_ensure_for_write(
|
||||
OutputAttributePtr attribute_result = component.attribute_try_get_for_output(
|
||||
result_name, result_domain, result_type);
|
||||
if (!attribute_result) {
|
||||
return;
|
||||
|
@ -63,7 +64,7 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
|||
BKE_colorband_evaluate(color_ramp, data_in[i], data_out[i]);
|
||||
}
|
||||
|
||||
attribute_result->apply_span();
|
||||
attribute_result.apply_span_and_save();
|
||||
}
|
||||
|
||||
static void geo_node_attribute_color_ramp_exec(GeoNodeExecParams params)
|
||||
|
|
|
@ -242,7 +242,7 @@ static void attribute_compare_calc(GeometryComponent &component, const GeoNodeEx
|
|||
|
||||
/* Get result attribute first, in case it has to overwrite one of the existing attributes. */
|
||||
const std::string result_name = params.get_input<std::string>("Result");
|
||||
WriteAttributePtr attribute_result = component.attribute_try_ensure_for_write(
|
||||
OutputAttributePtr attribute_result = component.attribute_try_get_for_output(
|
||||
result_name, result_domain, result_type);
|
||||
if (!attribute_result) {
|
||||
return;
|
||||
|
@ -260,8 +260,7 @@ static void attribute_compare_calc(GeometryComponent &component, const GeoNodeEx
|
|||
return;
|
||||
}
|
||||
|
||||
BooleanWriteAttribute attribute_result_bool = *attribute_result;
|
||||
MutableSpan<bool> result_span = attribute_result_bool.get_span_for_write_only();
|
||||
MutableSpan<bool> result_span = attribute_result->get_span_for_write_only<bool>();
|
||||
|
||||
/* Use specific types for correct equality operations, but for other operations we use implicit
|
||||
* conversions and float comparison. In other words, the comparison is not element-wise. */
|
||||
|
@ -300,7 +299,7 @@ static void attribute_compare_calc(GeometryComponent &component, const GeoNodeEx
|
|||
do_math_operation(*attribute_a, *attribute_b, operation, result_span);
|
||||
}
|
||||
|
||||
attribute_result_bool.apply_span();
|
||||
attribute_result.apply_span_and_save();
|
||||
}
|
||||
|
||||
static void geo_node_attribute_compare_exec(GeoNodeExecParams params)
|
||||
|
|
|
@ -68,7 +68,7 @@ static void fill_attribute(GeometryComponent &component, const GeoNodeExecParams
|
|||
return;
|
||||
}
|
||||
|
||||
WriteAttributePtr attribute = component.attribute_try_ensure_for_write(
|
||||
OutputAttributePtr attribute = component.attribute_try_get_for_output(
|
||||
attribute_name, domain, data_type);
|
||||
if (!attribute) {
|
||||
return;
|
||||
|
@ -79,33 +79,31 @@ static void fill_attribute(GeometryComponent &component, const GeoNodeExecParams
|
|||
const float value = params.get_input<float>("Value_001");
|
||||
MutableSpan<float> attribute_span = attribute->get_span_for_write_only<float>();
|
||||
attribute_span.fill(value);
|
||||
attribute->apply_span();
|
||||
break;
|
||||
}
|
||||
case CD_PROP_FLOAT3: {
|
||||
const float3 value = params.get_input<float3>("Value");
|
||||
MutableSpan<float3> attribute_span = attribute->get_span_for_write_only<float3>();
|
||||
attribute_span.fill(value);
|
||||
attribute->apply_span();
|
||||
break;
|
||||
}
|
||||
case CD_PROP_COLOR: {
|
||||
const Color4f value = params.get_input<Color4f>("Value_002");
|
||||
MutableSpan<Color4f> attribute_span = attribute->get_span_for_write_only<Color4f>();
|
||||
attribute_span.fill(value);
|
||||
attribute->apply_span();
|
||||
break;
|
||||
}
|
||||
case CD_PROP_BOOL: {
|
||||
const bool value = params.get_input<bool>("Value_003");
|
||||
MutableSpan<bool> attribute_span = attribute->get_span_for_write_only<bool>();
|
||||
attribute_span.fill(value);
|
||||
attribute->apply_span();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
attribute.apply_span_and_save();
|
||||
}
|
||||
|
||||
static void geo_node_attribute_fill_exec(GeoNodeExecParams params)
|
||||
|
|
|
@ -107,7 +107,7 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP
|
|||
|
||||
/* Get result attribute first, in case it has to overwrite one of the existing attributes. */
|
||||
const std::string result_name = params.get_input<std::string>("Result");
|
||||
WriteAttributePtr attribute_result = component.attribute_try_ensure_for_write(
|
||||
OutputAttributePtr attribute_result = component.attribute_try_get_for_output(
|
||||
result_name, result_domain, result_type);
|
||||
if (!attribute_result) {
|
||||
return;
|
||||
|
@ -123,6 +123,7 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP
|
|||
}
|
||||
|
||||
do_math_operation(*attribute_a, *attribute_b, *attribute_result, operation);
|
||||
attribute_result.save();
|
||||
}
|
||||
|
||||
static void geo_node_attribute_math_exec(GeoNodeExecParams params)
|
||||
|
|
|
@ -136,7 +136,7 @@ static void attribute_mix_calc(GeometryComponent &component, const GeoNodeExecPa
|
|||
result_domain = result_attribute_read->domain();
|
||||
}
|
||||
|
||||
WriteAttributePtr attribute_result = component.attribute_try_ensure_for_write(
|
||||
OutputAttributePtr attribute_result = component.attribute_try_get_for_output(
|
||||
result_name, result_domain, result_type);
|
||||
if (!attribute_result) {
|
||||
return;
|
||||
|
@ -155,6 +155,7 @@ static void attribute_mix_calc(GeometryComponent &component, const GeoNodeExecPa
|
|||
*attribute_a,
|
||||
*attribute_b,
|
||||
*attribute_result);
|
||||
attribute_result.save();
|
||||
}
|
||||
|
||||
static void geo_node_attribute_mix_exec(GeoNodeExecParams params)
|
||||
|
|
|
@ -151,7 +151,7 @@ static void randomize_attribute(GeometryComponent &component,
|
|||
return;
|
||||
}
|
||||
|
||||
WriteAttributePtr attribute = component.attribute_try_ensure_for_write(
|
||||
OutputAttributePtr attribute = component.attribute_try_get_for_output(
|
||||
attribute_name, domain, data_type);
|
||||
if (!attribute) {
|
||||
return;
|
||||
|
@ -179,6 +179,8 @@ static void randomize_attribute(GeometryComponent &component,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
attribute.save();
|
||||
}
|
||||
|
||||
static void geo_node_random_attribute_exec(GeoNodeExecParams params)
|
||||
|
|
|
@ -345,7 +345,7 @@ static void attribute_vector_math_calc(GeometryComponent &component,
|
|||
|
||||
/* Get result attribute first, in case it has to overwrite one of the existing attributes. */
|
||||
const std::string result_name = params.get_input<std::string>("Result");
|
||||
WriteAttributePtr attribute_result = component.attribute_try_ensure_for_write(
|
||||
OutputAttributePtr attribute_result = component.attribute_try_get_for_output(
|
||||
result_name, result_domain, result_type);
|
||||
if (!attribute_result) {
|
||||
return;
|
||||
|
@ -390,6 +390,7 @@ static void attribute_vector_math_calc(GeometryComponent &component,
|
|||
*attribute_a, *attribute_b, *attribute_c, *attribute_result, operation);
|
||||
break;
|
||||
}
|
||||
attribute_result.save();
|
||||
}
|
||||
|
||||
static void geo_node_attribute_vector_math_exec(GeoNodeExecParams params)
|
||||
|
|
|
@ -217,12 +217,12 @@ BLI_NOINLINE static void eliminate_points_based_on_mask(Span<bool> elimination_m
|
|||
}
|
||||
}
|
||||
|
||||
BLI_NOINLINE static void compute_remaining_point_data(const Mesh &mesh,
|
||||
Span<float3> bary_coords,
|
||||
Span<int> looptri_indices,
|
||||
MutableSpan<float3> r_normals,
|
||||
MutableSpan<int> r_ids,
|
||||
MutableSpan<float3> r_rotations)
|
||||
BLI_NOINLINE static void compute_special_attributes(const Mesh &mesh,
|
||||
Span<float3> bary_coords,
|
||||
Span<int> looptri_indices,
|
||||
MutableSpan<float3> r_normals,
|
||||
MutableSpan<int> r_ids,
|
||||
MutableSpan<float3> r_rotations)
|
||||
{
|
||||
Span<MLoopTri> looptris = get_mesh_looptris(mesh);
|
||||
for (const int i : bary_coords.index_range()) {
|
||||
|
@ -243,6 +243,30 @@ BLI_NOINLINE static void compute_remaining_point_data(const Mesh &mesh,
|
|||
}
|
||||
}
|
||||
|
||||
BLI_NOINLINE static void add_remaining_point_attributes(const Mesh &mesh,
|
||||
GeometryComponent &component,
|
||||
Span<float3> bary_coords,
|
||||
Span<int> looptri_indices)
|
||||
{
|
||||
OutputAttributePtr id_attribute = component.attribute_try_get_for_output(
|
||||
"id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
|
||||
OutputAttributePtr normal_attribute = component.attribute_try_get_for_output(
|
||||
"normal", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
OutputAttributePtr rotation_attribute = component.attribute_try_get_for_output(
|
||||
"rotation", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
|
||||
compute_special_attributes(mesh,
|
||||
bary_coords,
|
||||
looptri_indices,
|
||||
normal_attribute->get_span_for_write_only<float3>(),
|
||||
id_attribute->get_span_for_write_only<int>(),
|
||||
rotation_attribute->get_span_for_write_only<float3>());
|
||||
|
||||
id_attribute.apply_span_and_save();
|
||||
normal_attribute.apply_span_and_save();
|
||||
rotation_attribute.apply_span_and_save();
|
||||
}
|
||||
|
||||
static void sample_mesh_surface_with_minimum_distance(const Mesh &mesh,
|
||||
const float max_density,
|
||||
const float minimum_distance,
|
||||
|
@ -315,11 +339,6 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
|
|||
break;
|
||||
}
|
||||
const int tot_points = positions.size();
|
||||
Array<float3> normals(tot_points);
|
||||
Array<int> stable_ids(tot_points);
|
||||
Array<float3> rotations(tot_points);
|
||||
compute_remaining_point_data(
|
||||
*mesh_in, bary_coords, looptri_indices, normals, stable_ids, rotations);
|
||||
|
||||
PointCloud *pointcloud = BKE_pointcloud_new_nomain(tot_points);
|
||||
memcpy(pointcloud->co, positions.data(), sizeof(float3) * tot_points);
|
||||
|
@ -332,29 +351,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
|
|||
geometry_set_out.get_component_for_write<PointCloudComponent>();
|
||||
point_component.replace(pointcloud);
|
||||
|
||||
{
|
||||
Int32WriteAttribute stable_id_attribute = point_component.attribute_try_ensure_for_write(
|
||||
"id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
|
||||
MutableSpan<int> stable_ids_span = stable_id_attribute.get_span();
|
||||
stable_ids_span.copy_from(stable_ids);
|
||||
stable_id_attribute.apply_span();
|
||||
}
|
||||
|
||||
{
|
||||
Float3WriteAttribute normals_attribute = point_component.attribute_try_ensure_for_write(
|
||||
"normal", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
MutableSpan<float3> normals_span = normals_attribute.get_span();
|
||||
normals_span.copy_from(normals);
|
||||
normals_attribute.apply_span();
|
||||
}
|
||||
|
||||
{
|
||||
Float3WriteAttribute rotations_attribute = point_component.attribute_try_ensure_for_write(
|
||||
"rotation", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
MutableSpan<float3> rotations_span = rotations_attribute.get_span();
|
||||
rotations_span.copy_from(rotations);
|
||||
rotations_attribute.apply_span();
|
||||
}
|
||||
add_remaining_point_attributes(*mesh_in, point_component, bary_coords, looptri_indices);
|
||||
|
||||
params.set_output("Geometry", std::move(geometry_set_out));
|
||||
}
|
||||
|
|
|
@ -104,13 +104,13 @@ static void point_rotate_on_component(GeometryComponent &component,
|
|||
const bNode &node = params.node();
|
||||
const NodeGeometryRotatePoints &storage = *(const NodeGeometryRotatePoints *)node.storage;
|
||||
|
||||
WriteAttributePtr rotation_attribute = component.attribute_try_ensure_for_write(
|
||||
OutputAttributePtr rotation_attribute = component.attribute_try_get_for_output(
|
||||
"rotation", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
if (!rotation_attribute) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutableSpan<float3> rotations = rotation_attribute->get_span().typed<float3>();
|
||||
MutableSpan<float3> rotations = rotation_attribute->get_span<float3>();
|
||||
const int domain_size = rotations.size();
|
||||
|
||||
if (storage.type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE) {
|
||||
|
@ -138,7 +138,7 @@ static void point_rotate_on_component(GeometryComponent &component,
|
|||
}
|
||||
}
|
||||
|
||||
rotation_attribute->apply_span();
|
||||
rotation_attribute.apply_span_and_save();
|
||||
}
|
||||
|
||||
static void geo_node_point_rotate_exec(GeoNodeExecParams params)
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace blender::nodes {
|
|||
|
||||
static void execute_on_component(GeoNodeExecParams params, GeometryComponent &component)
|
||||
{
|
||||
Float3WriteAttribute scale_attribute = component.attribute_try_ensure_for_write(
|
||||
OutputAttributePtr scale_attribute = component.attribute_try_get_for_output(
|
||||
"scale", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
ReadAttributePtr attribute = params.get_input_attribute(
|
||||
"Factor", component, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, nullptr);
|
||||
|
@ -43,12 +43,12 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
|
|||
}
|
||||
|
||||
Span<float3> data = attribute->get_span<float3>();
|
||||
MutableSpan<float3> scale_span = scale_attribute.get_span();
|
||||
MutableSpan<float3> scale_span = scale_attribute->get_span<float3>();
|
||||
for (const int i : scale_span.index_range()) {
|
||||
scale_span[i] = scale_span[i] * data[i];
|
||||
}
|
||||
|
||||
scale_attribute.apply_span();
|
||||
scale_attribute.apply_span_and_save();
|
||||
}
|
||||
|
||||
static void geo_node_point_scale_exec(GeoNodeExecParams params)
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace blender::nodes {
|
|||
|
||||
static void execute_on_component(GeoNodeExecParams params, GeometryComponent &component)
|
||||
{
|
||||
Float3WriteAttribute position_attribute = component.attribute_try_ensure_for_write(
|
||||
OutputAttributePtr position_attribute = component.attribute_try_get_for_output(
|
||||
"position", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
ReadAttributePtr attribute = params.get_input_attribute(
|
||||
"Translation", component, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, nullptr);
|
||||
|
@ -43,12 +43,12 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
|
|||
}
|
||||
|
||||
Span<float3> data = attribute->get_span<float3>();
|
||||
MutableSpan<float3> scale_span = position_attribute.get_span();
|
||||
MutableSpan<float3> scale_span = position_attribute->get_span<float3>();
|
||||
for (const int i : scale_span.index_range()) {
|
||||
scale_span[i] = scale_span[i] + data[i];
|
||||
}
|
||||
|
||||
position_attribute.apply_span();
|
||||
position_attribute.apply_span_and_save();
|
||||
}
|
||||
|
||||
static void geo_node_point_translate_exec(GeoNodeExecParams params)
|
||||
|
|
|
@ -1079,7 +1079,12 @@ PyDoc_STRVAR(
|
|||
" :arg cage: Get the mesh as a deformed cage.\n"
|
||||
" :type cage: boolean\n"
|
||||
" :arg face_normals: Calculate face normals.\n"
|
||||
" :type face_normals: boolean\n");
|
||||
" :type face_normals: boolean\n"
|
||||
"\n"
|
||||
" .. deprecated:: 2.93\n"
|
||||
"\n"
|
||||
" The deform parameter is deprecated, assumed to be True, and will be removed in version "
|
||||
"3.0.\n");
|
||||
static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
static const char *kwlist[] = {"object", "depsgraph", "deform", "cage", "face_normals", NULL};
|
||||
|
@ -1120,45 +1125,36 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (use_deform == false) {
|
||||
PyErr_WarnEx(PyExc_FutureWarning,
|
||||
"from_object(...): the deform parameter is deprecated, assumed to be True, and "
|
||||
"will be removed in version 3.0",
|
||||
1);
|
||||
}
|
||||
|
||||
const bool use_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER;
|
||||
scene_eval = DEG_get_evaluated_scene(depsgraph);
|
||||
ob_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
bool need_free = false;
|
||||
|
||||
/* Write the display mesh into the dummy mesh */
|
||||
if (use_deform) {
|
||||
if (use_render) {
|
||||
if (use_cage) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"from_object(...): cage arg is unsupported when dependency graph "
|
||||
"evaluation mode is RENDER");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
me_eval = BKE_mesh_new_from_object(depsgraph, ob_eval, true);
|
||||
need_free = true;
|
||||
}
|
||||
else {
|
||||
if (use_cage) {
|
||||
me_eval = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &data_masks);
|
||||
}
|
||||
else {
|
||||
me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &data_masks);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* !use_deform */
|
||||
if (use_render) {
|
||||
if (use_cage) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"from_object(...): cage arg is unsupported when deform=False");
|
||||
"from_object(...): cage arg is unsupported when dependency graph "
|
||||
"evaluation mode is RENDER");
|
||||
return NULL;
|
||||
}
|
||||
if (use_render) {
|
||||
me_eval = mesh_create_eval_no_deform_render(depsgraph, scene_eval, ob, &data_masks);
|
||||
|
||||
me_eval = BKE_mesh_new_from_object(depsgraph, ob_eval, true);
|
||||
need_free = true;
|
||||
}
|
||||
else {
|
||||
if (use_cage) {
|
||||
me_eval = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &data_masks);
|
||||
}
|
||||
else {
|
||||
me_eval = mesh_create_eval_no_deform(depsgraph, scene_eval, ob, &data_masks);
|
||||
me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &data_masks);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -651,6 +651,9 @@ if(WITH_CYCLES OR WITH_OPENGL_RENDER_TESTS)
|
|||
|
||||
# Cycles
|
||||
if(WITH_CYCLES)
|
||||
if(NOT WITH_CYCLES_OSL)
|
||||
set(_cycles_blacklist OSL)
|
||||
endif()
|
||||
foreach(_cycles_device ${CYCLES_TEST_DEVICES})
|
||||
string(TOLOWER "${_cycles_device}" _cycles_device_lower)
|
||||
set(_cycles_render_tests bake;${render_tests};osl)
|
||||
|
@ -664,6 +667,7 @@ if(WITH_CYCLES OR WITH_OPENGL_RENDER_TESTS)
|
|||
-idiff "${OPENIMAGEIO_IDIFF}"
|
||||
-outdir "${TEST_OUT_DIR}/cycles"
|
||||
-device ${_cycles_device}
|
||||
-blacklist ${_cycles_blacklist}
|
||||
)
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
|
|
@ -9,6 +9,53 @@ import subprocess
|
|||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# List of .blend files that are known to be failing and are not ready to be
|
||||
# tested, or that only make sense on some devices. Accepts regular expressions.
|
||||
BLACKLIST_OSL = [
|
||||
# OSL only supported on CPU.
|
||||
'.*_osl.blend',
|
||||
'osl_.*.blend',
|
||||
]
|
||||
|
||||
BLACKLIST_OPTIX = [
|
||||
# No branched path on Optix.
|
||||
'T53854.blend',
|
||||
'T50164.blend',
|
||||
'portal.blend',
|
||||
'denoise_sss.blend',
|
||||
'denoise_passes.blend',
|
||||
'distant_light.blend',
|
||||
'aov_position.blend',
|
||||
'subsurface_branched_path.blend',
|
||||
'T43865.blend',
|
||||
]
|
||||
|
||||
BLACKLIST_GPU = [
|
||||
# Missing equiangular sampling on GPU.
|
||||
'area_light.blend',
|
||||
'denoise_hair.blend',
|
||||
'point_density_.*.blend',
|
||||
'point_light.blend',
|
||||
'shadow_catcher_bpt_.*.blend',
|
||||
'sphere_light.blend',
|
||||
'spot_light.blend',
|
||||
'T48346.blend',
|
||||
'world_volume.blend',
|
||||
# Uninvestigated differences with GPU.
|
||||
'image_log.blend',
|
||||
'subsurface_behind_glass_branched.blend',
|
||||
'T40964.blend',
|
||||
'T45609.blend',
|
||||
'T48860.blend',
|
||||
'smoke_color.blend',
|
||||
'bevel_mblur.blend',
|
||||
# Inconsistency between Embree and Hair primitive on GPU.
|
||||
'hair_basemesh_intercept.blend',
|
||||
'hair_instancer_uv.blend',
|
||||
'hair_particle_random.blend',
|
||||
'principled_hair_.*.blend',
|
||||
'transparent_shadow_hair.*.blend',
|
||||
]
|
||||
|
||||
def get_arguments(filepath, output_filepath):
|
||||
dirname = os.path.dirname(filepath)
|
||||
|
@ -51,6 +98,7 @@ def create_argparse():
|
|||
parser.add_argument("-outdir", nargs=1)
|
||||
parser.add_argument("-idiff", nargs=1)
|
||||
parser.add_argument("-device", nargs=1)
|
||||
parser.add_argument("-blacklist", nargs="*")
|
||||
return parser
|
||||
|
||||
|
||||
|
@ -64,8 +112,16 @@ def main():
|
|||
output_dir = args.outdir[0]
|
||||
device = args.device[0]
|
||||
|
||||
blacklist = []
|
||||
if device != 'CPU':
|
||||
blacklist += BLACKLIST_GPU
|
||||
if device != 'CPU' or 'OSL' in args.blacklist:
|
||||
blacklist += BLACKLIST_OSL
|
||||
if device == 'OPTIX':
|
||||
blacklist += BLACKLIST_OPTIX
|
||||
|
||||
from modules import render_report
|
||||
report = render_report.Report('Cycles', output_dir, idiff, device)
|
||||
report = render_report.Report('Cycles', output_dir, idiff, device, blacklist)
|
||||
report.set_pixelated(True)
|
||||
report.set_reference_dir("cycles_renders")
|
||||
if device == 'CPU':
|
||||
|
|
|
@ -29,57 +29,6 @@ class COLORS_DUMMY:
|
|||
COLORS = COLORS_DUMMY
|
||||
|
||||
|
||||
# List of .blend files that are known to be failing and are not ready to be
|
||||
# tested, or that only make sense on some devices. Accepts regular expressions.
|
||||
BLACKLIST = (
|
||||
# OSL only supported on CPU.
|
||||
('.*_osl.blend', '(?!CPU)'),
|
||||
('osl_.*.blend', '(?!CPU)'),
|
||||
|
||||
# No baking, branched path and shader raytrace on Optix.
|
||||
('bake_.*.blend', 'OPTIX'),
|
||||
('ambient_occlusion.blend', 'OPTIX'),
|
||||
('ambient_occlusion_only_local.blend', 'OPTIX'),
|
||||
('bevel.blend', 'OPTIX'),
|
||||
('bevel_mblur.blend', 'OPTIX'),
|
||||
('T53854.blend', 'OPTIX'),
|
||||
('T50164.blend', 'OPTIX'),
|
||||
('portal.blend', 'OPTIX'),
|
||||
('denoise_sss.blend', 'OPTIX'),
|
||||
('denoise_passes.blend', 'OPTIX'),
|
||||
('distant_light.blend', 'OPTIX'),
|
||||
('aov_position.blend', 'OPTIX'),
|
||||
('subsurface_branched_path.blend', 'OPTIX'),
|
||||
|
||||
# Missing equiangular sampling on GPU.
|
||||
('area_light.blend', '(?!CPU)'),
|
||||
('denoise_hair.blend', '(?!CPU)'),
|
||||
('point_density_.*.blend', '(?!CPU)'),
|
||||
('point_light.blend', '(?!CPU)'),
|
||||
('shadow_catcher_bpt_.*.blend', '(?!CPU)'),
|
||||
('sphere_light.blend', '(?!CPU)'),
|
||||
('spot_light.blend', '(?!CPU)'),
|
||||
('T48346.blend', '(?!CPU)'),
|
||||
('world_volume.blend', '(?!CPU)'),
|
||||
|
||||
# Inconsistency between Embree and Hair primitive on GPU.
|
||||
('hair_basemesh_intercept.blend', '(?!CPU)'),
|
||||
('hair_instancer_uv.blend', '(?!CPU)'),
|
||||
('hair_particle_random.blend', '(?!CPU)'),
|
||||
('principled_hair_.*.blend', '(?!CPU)'),
|
||||
('transparent_shadow_hair.*.blend', '(?!CPU)'),
|
||||
|
||||
# Uninvestigated differences with GPU.
|
||||
('image_log.blend', '(?!CPU)'),
|
||||
('subsurface_behind_glass_branched.blend', '(?!CPU)'),
|
||||
('T40964.blend', '(?!CPU)'),
|
||||
('T45609.blend', '(?!CPU)'),
|
||||
('T48860.blend', '(?!CPU)'),
|
||||
('smoke_color.blend', '(?!CPU)'),
|
||||
('T43865.blend', 'OPTIX')
|
||||
)
|
||||
|
||||
|
||||
def print_message(message, type=None, status=''):
|
||||
if type == 'SUCCESS':
|
||||
print(COLORS.GREEN, end="")
|
||||
|
@ -103,7 +52,7 @@ def print_message(message, type=None, status=''):
|
|||
sys.stdout.flush()
|
||||
|
||||
|
||||
def blend_list(dirpath, device):
|
||||
def blend_list(dirpath, device, blacklist):
|
||||
import re
|
||||
|
||||
for root, dirs, files in os.walk(dirpath):
|
||||
|
@ -112,12 +61,10 @@ def blend_list(dirpath, device):
|
|||
continue
|
||||
|
||||
skip = False
|
||||
for blacklist in BLACKLIST:
|
||||
if not re.match(blacklist[0], filename):
|
||||
continue
|
||||
if device and blacklist[1] and not re.match(blacklist[1], device):
|
||||
continue
|
||||
skip = True
|
||||
for blacklist_entry in blacklist:
|
||||
if re.match(blacklist_entry, filename):
|
||||
skip = True
|
||||
break
|
||||
|
||||
if not skip:
|
||||
filepath = os.path.join(root, filename)
|
||||
|
@ -169,10 +116,11 @@ class Report:
|
|||
'passed_tests',
|
||||
'compare_tests',
|
||||
'compare_engine',
|
||||
'device'
|
||||
'device',
|
||||
'blacklist',
|
||||
)
|
||||
|
||||
def __init__(self, title, output_dir, idiff, device=None):
|
||||
def __init__(self, title, output_dir, idiff, device=None, blacklist=[]):
|
||||
self.title = title
|
||||
self.output_dir = output_dir
|
||||
self.global_dir = os.path.dirname(output_dir)
|
||||
|
@ -182,6 +130,7 @@ class Report:
|
|||
self.fail_threshold = 0.016
|
||||
self.fail_percent = 1
|
||||
self.device = device
|
||||
self.blacklist = blacklist
|
||||
|
||||
if device:
|
||||
self.title = self._engine_title(title, device)
|
||||
|
@ -575,7 +524,7 @@ class Report:
|
|||
def _run_all_tests(self, dirname, dirpath, blender, arguments_cb, batch):
|
||||
passed_tests = []
|
||||
failed_tests = []
|
||||
all_files = list(blend_list(dirpath, self.device))
|
||||
all_files = list(blend_list(dirpath, self.device, self.blacklist))
|
||||
all_files.sort()
|
||||
print_message("Running {} tests from 1 test case." .
|
||||
format(len(all_files)),
|
||||
|
|
Loading…
Reference in New Issue