diff options
Diffstat (limited to 'source')
34 files changed, 492 insertions, 209 deletions
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index f83ee409187..b7c226ada1d 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -41,6 +41,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_math_color_blend.h" #include "BLI_rect.h" #include "BLI_string.h" #include "BLI_string_utf8.h" @@ -640,18 +641,12 @@ static void blf_font_draw_buffer_ex(FontBLF *font, (size_t)buf_info->ch); float *fbuf = buf_info->fbuf + buf_ofs; - if (a >= 1.0f) { - fbuf[0] = b_col_float[0]; - fbuf[1] = b_col_float[1]; - fbuf[2] = b_col_float[2]; - fbuf[3] = 1.0f; - } - else { - fbuf[0] = (b_col_float[0] * a) + (fbuf[0] * (1.0f - a)); - fbuf[1] = (b_col_float[1] * a) + (fbuf[1] * (1.0f - a)); - fbuf[2] = (b_col_float[2] * a) + (fbuf[2] * (1.0f - a)); - fbuf[3] = MIN2(fbuf[3] + a, 1.0f); /* clamp to 1.0 */ - } + float font_pixel[4]; + font_pixel[0] = b_col_float[0] * a; + font_pixel[1] = b_col_float[1] * a; + font_pixel[2] = b_col_float[2] * a; + font_pixel[3] = a; + blend_color_mix_float(fbuf, fbuf, font_pixel); } } @@ -677,19 +672,12 @@ static void blf_font_draw_buffer_ex(FontBLF *font, (size_t)buf_info->ch); unsigned char *cbuf = buf_info->cbuf + buf_ofs; - if (a >= 1.0f) { - cbuf[0] = b_col_char[0]; - cbuf[1] = b_col_char[1]; - cbuf[2] = b_col_char[2]; - cbuf[3] = 255; - } - else { - cbuf[0] = (unsigned char)((b_col_char[0] * a) + (cbuf[0] * (1.0f - a))); - cbuf[1] = (unsigned char)((b_col_char[1] * a) + (cbuf[1] * (1.0f - a))); - cbuf[2] = (unsigned char)((b_col_char[2] * a) + (cbuf[2] * (1.0f - a))); - /* clamp to 255 */ - cbuf[3] = (unsigned char)MIN2((int)cbuf[3] + (int)(a * 255), 255); - } + uchar font_pixel[4]; + font_pixel[0] = b_col_char[0]; + font_pixel[1] = b_col_char[1]; + font_pixel[2] = b_col_char[2]; + font_pixel[3] = unit_float_to_uchar_clamp(a); + blend_color_mix_byte(cbuf, cbuf, font_pixel); } } diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index 38f692fee0e..027338a5d5c 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -70,6 +70,65 @@ using AttributeForeachCallback = blender::FunctionRef<bool(blender::StringRefNul const AttributeMetaData &meta_data)>; /** + * Base class for the attribute intializer types described below. + */ +struct AttributeInit { + enum class Type { + Default, + VArray, + MoveArray, + }; + Type type; + AttributeInit(const Type type) : type(type) + { + } +}; + +/** + * Create an attribute using the default value for the data type. + * The default values may depend on the attribute provider implementation. + */ +struct AttributeInitDefault : public AttributeInit { + AttributeInitDefault() : AttributeInit(Type::Default) + { + } +}; + +/** + * Create an attribute by copying data from an existing virtual array. The virtual array + * must have the same type as the newly created attribute. + * + * Note that this can be used to fill the new attribute with the default + */ +struct AttributeInitVArray : public AttributeInit { + const blender::fn::GVArray *varray; + + AttributeInitVArray(const blender::fn::GVArray *varray) + : AttributeInit(Type::VArray), varray(varray) + { + } +}; + +/** + * Create an attribute with a by passing ownership of a pre-allocated contiguous array of data. + * Sometimes data is created before a geometry component is available. In that case, it's + * preferable to move data directly to the created attribute to avoid a new allocation and a copy. + * + * Note that this will only have a benefit for attributes that are stored directly as contigious + * arrays, so not for some built-in attributes. + * + * The array must be allocated with MEM_*, since `attribute_try_create` will free the array if it + * can't be used directly, and that is generally how Blender expects custom data to be allocated. + */ +struct AttributeInitMove : public AttributeInit { + void *data = nullptr; + + AttributeInitMove(void *data) : AttributeInit(Type::MoveArray), data(data) + { + } +}; + +/** * This is the base class for specialized geometry component types. */ class GeometryComponent { @@ -102,6 +161,10 @@ class GeometryComponent { /* Return true when any attribute with this name exists, including built in attributes. */ bool attribute_exists(const blender::StringRef attribute_name) const; + /* Return the data type and domain of an attribute with the given name if it exists. */ + std::optional<AttributeMetaData> attribute_get_meta_data( + const blender::StringRef attribute_name) const; + /* Returns true when the geometry component supports this attribute domain. */ bool attribute_domain_supported(const AttributeDomain domain) const; /* Can only be used with supported domain types. */ @@ -133,11 +196,13 @@ class GeometryComponent { /* Returns true when the attribute has been created. */ bool attribute_try_create(const blender::StringRef attribute_name, const AttributeDomain domain, - const CustomDataType data_type); + const CustomDataType data_type, + const AttributeInit &initializer); /* Try to create the builtin attribute with the given name. No data type or domain has to be * provided, because those are fixed for builtin attributes. */ - bool attribute_try_create_builtin(const blender::StringRef attribute_name); + bool attribute_try_create_builtin(const blender::StringRef attribute_name, + const AttributeInit &initializer); blender::Set<std::string> attribute_names() const; bool attribute_foreach(const AttributeForeachCallback callback) const; diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 3b2ee126d91..6c37d34dc9b 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -254,7 +254,43 @@ bool BuiltinCustomDataLayerProvider::try_delete(GeometryComponent &component) co return delete_success; } -bool BuiltinCustomDataLayerProvider::try_create(GeometryComponent &component) const +static bool add_custom_data_layer_from_attribute_init(CustomData &custom_data, + const CustomDataType data_type, + const int domain_size, + const AttributeInit &initializer) +{ + switch (initializer.type) { + case AttributeInit::Type::Default: { + void *data = CustomData_add_layer(&custom_data, data_type, CD_DEFAULT, nullptr, domain_size); + return data != nullptr; + } + case AttributeInit::Type::VArray: { + void *data = CustomData_add_layer(&custom_data, data_type, CD_DEFAULT, nullptr, domain_size); + if (data == nullptr) { + return false; + } + const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray; + varray->materialize_to_uninitialized(IndexRange(varray->size()), data); + return true; + } + case AttributeInit::Type::MoveArray: { + void *source_data = static_cast<const AttributeInitMove &>(initializer).data; + void *data = CustomData_add_layer( + &custom_data, data_type, CD_ASSIGN, source_data, domain_size); + if (data == nullptr) { + MEM_freeN(source_data); + return false; + } + return true; + } + } + + BLI_assert_unreachable(); + return false; +} + +bool BuiltinCustomDataLayerProvider::try_create(GeometryComponent &component, + const AttributeInit &initializer) const { if (createable_ != Creatable) { return false; @@ -267,10 +303,10 @@ bool BuiltinCustomDataLayerProvider::try_create(GeometryComponent &component) co /* Exists already. */ return false; } + const int domain_size = component.attribute_domain_size(domain_); - const void *data = CustomData_add_layer( - custom_data, stored_type_, CD_DEFAULT, nullptr, domain_size); - const bool success = data != nullptr; + const bool success = add_custom_data_layer_from_attribute_init( + *custom_data, stored_type_, domain_size, initializer); if (success) { custom_data_access_.update_custom_data_pointers(component); } @@ -372,10 +408,52 @@ bool CustomDataAttributeProvider::try_delete(GeometryComponent &component, return false; } +static bool add_named_custom_data_layer_from_attribute_init(const StringRef attribute_name, + CustomData &custom_data, + const CustomDataType data_type, + const int domain_size, + const AttributeInit &initializer) +{ + char attribute_name_c[MAX_NAME]; + attribute_name.copy(attribute_name_c); + + switch (initializer.type) { + case AttributeInit::Type::Default: { + void *data = CustomData_add_layer_named( + &custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_name_c); + return data != nullptr; + } + case AttributeInit::Type::VArray: { + void *data = CustomData_add_layer_named( + &custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_name_c); + if (data == nullptr) { + return false; + } + const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray; + varray->materialize_to_uninitialized(IndexRange(varray->size()), data); + return true; + } + case AttributeInit::Type::MoveArray: { + void *source_data = static_cast<const AttributeInitMove &>(initializer).data; + void *data = CustomData_add_layer_named( + &custom_data, data_type, CD_ASSIGN, source_data, domain_size, attribute_name_c); + if (data == nullptr) { + MEM_freeN(source_data); + return false; + } + return true; + } + } + + BLI_assert_unreachable(); + return false; +} + bool CustomDataAttributeProvider::try_create(GeometryComponent &component, const StringRef attribute_name, const AttributeDomain domain, - const CustomDataType data_type) const + const CustomDataType data_type, + const AttributeInit &initializer) const { if (domain_ != domain) { return false; @@ -393,10 +471,8 @@ bool CustomDataAttributeProvider::try_create(GeometryComponent &component, } } const int domain_size = component.attribute_domain_size(domain_); - char attribute_name_c[MAX_NAME]; - attribute_name.copy(attribute_name_c); - CustomData_add_layer_named( - custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_name_c); + add_named_custom_data_layer_from_attribute_init( + attribute_name, *custom_data, data_type, domain_size, initializer); return true; } @@ -621,7 +697,8 @@ bool GeometryComponent::attribute_try_delete(const StringRef attribute_name) bool GeometryComponent::attribute_try_create(const StringRef attribute_name, const AttributeDomain domain, - const CustomDataType data_type) + const CustomDataType data_type, + const AttributeInit &initializer) { using namespace blender::bke; if (attribute_name.is_empty()) { @@ -640,18 +717,19 @@ bool GeometryComponent::attribute_try_create(const StringRef attribute_name, if (builtin_provider->data_type() != data_type) { return false; } - return builtin_provider->try_create(*this); + return builtin_provider->try_create(*this, initializer); } for (const DynamicAttributesProvider *dynamic_provider : providers->dynamic_attribute_providers()) { - if (dynamic_provider->try_create(*this, attribute_name, domain, data_type)) { + if (dynamic_provider->try_create(*this, attribute_name, domain, data_type, initializer)) { return true; } } return false; } -bool GeometryComponent::attribute_try_create_builtin(const blender::StringRef attribute_name) +bool GeometryComponent::attribute_try_create_builtin(const blender::StringRef attribute_name, + const AttributeInit &initializer) { using namespace blender::bke; if (attribute_name.is_empty()) { @@ -666,7 +744,7 @@ bool GeometryComponent::attribute_try_create_builtin(const blender::StringRef at if (builtin_provider == nullptr) { return false; } - return builtin_provider->try_create(*this); + return builtin_provider->try_create(*this, initializer); } Set<std::string> GeometryComponent::attribute_names() const @@ -729,6 +807,20 @@ bool GeometryComponent::attribute_exists(const blender::StringRef attribute_name return false; } +std::optional<AttributeMetaData> GeometryComponent::attribute_get_meta_data( + const StringRef attribute_name) const +{ + std::optional<AttributeMetaData> result{std::nullopt}; + this->attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) { + if (attribute_name == name) { + result = meta_data; + return false; + } + return true; + }); + return result; +} + static std::unique_ptr<blender::fn::GVArray> try_adapt_data_type( std::unique_ptr<blender::fn::GVArray> varray, const blender::fn::CPPType &to_type) { @@ -860,7 +952,8 @@ static void save_output_attribute(blender::bke::OutputAttribute &output_attribut const CPPType &cpp_type = output_attribute.cpp_type(); component.attribute_try_delete(name); - if (!component.attribute_try_create(varray.final_name, domain, data_type)) { + if (!component.attribute_try_create( + varray.final_name, domain, data_type, AttributeInitDefault())) { CLOG_WARN(&LOG, "Could not create the '%s' attribute with type '%s'.", name.c_str(), @@ -898,7 +991,15 @@ static blender::bke::OutputAttribute create_output_attribute( if (component.attribute_is_builtin(attribute_name)) { WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_name); if (!attribute) { - component.attribute_try_create_builtin(attribute_name); + if (default_value) { + const int64_t domain_size = component.attribute_domain_size(domain); + const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value}; + component.attribute_try_create_builtin(attribute_name, + AttributeInitVArray(&default_varray)); + } + else { + component.attribute_try_create_builtin(attribute_name, AttributeInitDefault()); + } attribute = component.attribute_try_get_for_write(attribute_name); if (!attribute) { /* Builtin attribute does not exist and can't be created. */ @@ -919,9 +1020,19 @@ static blender::bke::OutputAttribute create_output_attribute( return OutputAttribute(std::move(varray), domain, {}, ignore_old_values); } + const int domain_size = component.attribute_domain_size(domain); + WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_name); if (!attribute) { - component.attribute_try_create(attribute_name, domain, data_type); + if (default_value) { + const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value}; + component.attribute_try_create( + attribute_name, domain, data_type, AttributeInitVArray(&default_varray)); + } + else { + component.attribute_try_create(attribute_name, domain, data_type, AttributeInitDefault()); + } + attribute = component.attribute_try_get_for_write(attribute_name); if (!attribute) { /* Can't create the attribute. */ @@ -933,7 +1044,6 @@ static blender::bke::OutputAttribute create_output_attribute( return OutputAttribute(std::move(attribute.varray), domain, {}, ignore_old_values); } - const int domain_size = component.attribute_domain_size(domain); /* Allocate a new array that lives next to the existing attribute. It will overwrite the existing * attribute after processing is done. */ void *data = MEM_mallocN_aligned( diff --git a/source/blender/blenkernel/intern/attribute_access_intern.hh b/source/blender/blenkernel/intern/attribute_access_intern.hh index 7cf585dfbfc..b3a795faa30 100644 --- a/source/blender/blenkernel/intern/attribute_access_intern.hh +++ b/source/blender/blenkernel/intern/attribute_access_intern.hh @@ -89,7 +89,8 @@ class BuiltinAttributeProvider { virtual GVArrayPtr try_get_for_read(const GeometryComponent &component) const = 0; virtual GVMutableArrayPtr try_get_for_write(GeometryComponent &component) const = 0; virtual bool try_delete(GeometryComponent &component) const = 0; - virtual bool try_create(GeometryComponent &UNUSED(component)) const = 0; + virtual bool try_create(GeometryComponent &UNUSED(component), + const AttributeInit &UNUSED(initializer)) const = 0; virtual bool exists(const GeometryComponent &component) const = 0; StringRefNull name() const @@ -122,7 +123,8 @@ class DynamicAttributesProvider { virtual bool try_create(GeometryComponent &UNUSED(component), const StringRef UNUSED(attribute_name), const AttributeDomain UNUSED(domain), - const CustomDataType UNUSED(data_type)) const + const CustomDataType UNUSED(data_type), + const AttributeInit &UNUSED(initializer)) const { /* Some providers should not create new attributes. */ return false; @@ -162,7 +164,8 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider { bool try_create(GeometryComponent &component, const StringRef attribute_name, const AttributeDomain domain, - const CustomDataType data_type) const final; + const CustomDataType data_type, + const AttributeInit &initializer) const final; bool foreach_attribute(const GeometryComponent &component, const AttributeForeachCallback callback) const final; @@ -278,7 +281,7 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider { GVArrayPtr try_get_for_read(const GeometryComponent &component) const final; GVMutableArrayPtr try_get_for_write(GeometryComponent &component) const final; bool try_delete(GeometryComponent &component) const final; - bool try_create(GeometryComponent &component) const final; + bool try_create(GeometryComponent &component, const AttributeInit &initializer) const final; bool exists(const GeometryComponent &component) const final; }; diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index e5accd98952..e54c3716660 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -1014,7 +1014,8 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider { return false; } - bool try_create(GeometryComponent &UNUSED(component)) const final + bool try_create(GeometryComponent &UNUSED(component), + const AttributeInit &UNUSED(initializer)) const final { return false; } diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc index 2e9f6daabad..47db5d1f901 100644 --- a/source/blender/blenkernel/intern/geometry_set_instances.cc +++ b/source/blender/blenkernel/intern/geometry_set_instances.cc @@ -449,7 +449,8 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups, const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(data_type_output); BLI_assert(cpp_type != nullptr); - result.attribute_try_create(entry.key, domain_output, data_type_output); + result.attribute_try_create( + entry.key, domain_output, data_type_output, AttributeInitDefault()); WriteAttributeLookup write_attribute = result.attribute_try_get_for_write(name); if (!write_attribute || &write_attribute.varray->type() != cpp_type || write_attribute.domain != domain_output) { diff --git a/source/blender/blenkernel/intern/mesh_mirror.c b/source/blender/blenkernel/intern/mesh_mirror.c index a22b52d68d5..93a2e9058fa 100644 --- a/source/blender/blenkernel/intern/mesh_mirror.c +++ b/source/blender/blenkernel/intern/mesh_mirror.c @@ -51,7 +51,7 @@ Mesh *BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(MirrorModifierData *mm (axis == 1 && mmd->flag & MOD_MIR_BISECT_FLIP_AXIS_Y) || (axis == 2 && mmd->flag & MOD_MIR_BISECT_FLIP_AXIS_Z)); - const float bisect_distance = 0.001f; + const float bisect_distance = mmd->bisect_threshold; Mesh *result; BMesh *bm; diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index 95cbb1afa5d..e52067a03b3 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -20,6 +20,12 @@ /* allow readfile to use deprecated functionality */ #define DNA_DEPRECATED_ALLOW +#include "BLI_listbase.h" +#include "BLI_utildefines.h" + +#include "DNA_genfile.h" +#include "DNA_modifier_types.h" + #include "DNA_gpencil_types.h" #include "BKE_main.h" @@ -63,9 +69,9 @@ void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports)) } /* NOLINTNEXTLINE: readability-function-size */ -void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *UNUSED(bmain)) +void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) { - UNUSED_VARS(fd); + /** * Versioning code until next subversion bump goes here. * @@ -77,5 +83,18 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *UNUSED(bmain) */ { /* Keep this block, even when empty. */ + + /* Set default value for the new bisect_threshold parameter in the mirror modifier. */ + if (!DNA_struct_elem_find(fd->filesdna, "MirrorModifierData", "float", "bisect_threshold")) { + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { + if (md->type == eModifierType_Mirror) { + MirrorModifierData *mmd = (MirrorModifierData *)md; + /* This was the previous hard-coded value. */ + mmd->bisect_threshold = 0.001f; + } + } + } + } } } diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 12d6f1fce54..179c9d5b30d 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -511,6 +511,7 @@ bool ED_autokeyframe_property(struct bContext *C, #define ANIM_KS_ROTATION_ID "Rotation" #define ANIM_KS_SCALING_ID "Scaling" #define ANIM_KS_LOC_ROT_SCALE_ID "LocRotScale" +#define ANIM_KS_LOC_ROT_SCALE_CPROP_ID "LocRotScaleCProp" #define ANIM_KS_AVAILABLE_ID "Available" #define ANIM_KS_WHOLE_CHARACTER_ID "WholeCharacter" #define ANIM_KS_WHOLE_CHARACTER_SELECTED_ID "WholeCharacterSelected" diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 3277baeba5b..512f912a532 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -43,6 +43,7 @@ #include "BKE_curve.h" #include "BKE_duplilist.h" #include "BKE_editmesh.h" +#include "BKE_geometry_set.h" #include "BKE_global.h" #include "BKE_layer.h" #include "BKE_mesh.h" @@ -500,10 +501,12 @@ static void iter_snap_objects(SnapObjectContext *sctx, } Object *obj_eval = DEG_get_evaluated_object(depsgraph, base->object); - if (obj_eval->transflag & OB_DUPLI) { - DupliObject *dupli_ob; + if (obj_eval->transflag & OB_DUPLI || + (obj_eval->runtime.geometry_set_eval != NULL && + BKE_geometry_set_has_instances(obj_eval->runtime.geometry_set_eval))) { ListBase *lb = object_duplilist(depsgraph, sctx->scene, obj_eval); - for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { + for (DupliObject *dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { + BLI_assert(DEG_is_evaluated_object(dupli_ob->ob)); sob_callback(sctx, dupli_ob->ob, dupli_ob->mat, diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index d8e48c51107..f6dac88051b 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -429,6 +429,7 @@ { \ .flag = MOD_MIR_AXIS_X | MOD_MIR_VGROUP, \ .tolerance = 0.001f, \ + .bisect_threshold = 0.001f, \ .uv_offset = {0.0f, 0.0f}, \ .uv_offset_copy = {0.0f, 0.0f}, \ .mirror_ob = NULL, \ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index ca6f1467d9c..c61e940190f 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -368,6 +368,8 @@ typedef struct MirrorModifierData { short axis DNA_DEPRECATED; short flag; float tolerance; + float bisect_threshold; + char _pad[4]; float uv_offset[2]; float uv_offset_copy[2]; struct Object *mirror_ob; diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 67335b81a31..e3fb443951f 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -2226,6 +2226,14 @@ static void rna_def_modifier_mirror(BlenderRNA *brna) prop, "Merge Distance", "Distance within which mirrored vertices are merged"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "bisect_threshold", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_float_sdna(prop, NULL, "bisect_threshold"); + RNA_def_property_range(prop, 0, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 0.01, 6); + RNA_def_property_ui_text( + prop, "Bisect Distance", "Distance from the bisect plane within which vertices are removed"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "mirror_object", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "mirror_ob"); RNA_def_property_ui_text(prop, "Mirror Object", "Object to use as mirror"); diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index afe94d8dead..b800ce7f803 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -165,6 +165,13 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_mirror_merge")); uiItemR(sub, ptr, "merge_threshold", 0, "", ICON_NONE); + bool is_bisect_set[3]; + RNA_boolean_get_array(ptr, "use_bisect_axis", is_bisect_set); + + sub = uiLayoutRow(col, true); + uiLayoutSetActive(sub, is_bisect_set[0] || is_bisect_set[1] || is_bisect_set[2]); + uiItemR(sub, ptr, "bisect_threshold", 0, IFACE_("Bisect Distance"), ICON_NONE); + modifier_panel_end(layout, ptr); } diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 53b79d0b2a5..57de629fc18 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -271,6 +271,17 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return false; } +static bool logging_enabled(const ModifierEvalContext *ctx) +{ + if (!DEG_is_active(ctx->depsgraph)) { + return false; + } + if ((ctx->flag & MOD_APPLY_ORCO) != 0) { + return false; + } + return true; +} + class GeometryNodesEvaluator { public: using LogSocketValueFn = std::function<void(DSocket, Span<GPointer>)>; @@ -1290,7 +1301,7 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree, find_sockets_to_preview(nmd, ctx, tree, preview_sockets); auto log_socket_value = [&](const DSocket socket, const Span<GPointer> values) { - if (!DEG_is_active(ctx->depsgraph)) { + if (!logging_enabled(ctx)) { return; } Span<uint64_t> keys = preview_sockets.lookup(socket); @@ -1401,7 +1412,7 @@ static void modifyGeometry(ModifierData *md, return; } - if (DEG_is_active(ctx->depsgraph)) { + if (logging_enabled(ctx)) { reset_tree_ui_storage(tree.used_node_tree_refs(), *ctx->object, *md); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc index e7677ed41e1..1943971d49f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc @@ -126,13 +126,13 @@ static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef source_name, StringRef result_name) { - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(result_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); + if (result_info) { + return result_info->domain; } - ReadAttributeLookup source_attribute = component.attribute_try_get_for_read(source_name); - if (source_attribute) { - return source_attribute.domain; + std::optional<AttributeMetaData> source_info = component.attribute_get_meta_data(source_name); + if (source_info) { + return source_info->domain; } return ATTR_DOMAIN_POINT; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc index af65fe110e9..9e697226a01 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc @@ -47,15 +47,15 @@ static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef result_name) { /* Use the domain of the result attribute if it already exists. */ - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(result_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); + if (result_info) { + return result_info->domain; } /* Otherwise use the input attribute's domain if it exists. */ - ReadAttributeLookup input_attribute = component.attribute_try_get_for_read(input_name); - if (input_attribute) { - return input_attribute.domain; + std::optional<AttributeMetaData> source_info = component.attribute_get_meta_data(input_name); + if (source_info) { + return source_info->domain; } return ATTR_DOMAIN_POINT; diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_combine_xyz.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_combine_xyz.cc index c3db26c7299..69e628267a4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_combine_xyz.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_combine_xyz.cc @@ -77,9 +77,9 @@ static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef result_name) { /* Use the domain of the result attribute if it already exists. */ - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(result_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); + if (result_info) { + return result_info->domain; } /* Otherwise use the highest priority domain from existing input attributes, or the default. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc index 22855787ab0..ccfaeb9bb47 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc @@ -234,9 +234,9 @@ static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef result_name) { /* Use the domain of the result attribute if it already exists. */ - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(result_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); + if (result_info) { + return result_info->domain; } /* Otherwise use the highest priority domain from existing input attributes, or the default. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_convert.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_convert.cc index bb46c5c84cd..60bb27191b4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_convert.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_convert.cc @@ -55,13 +55,13 @@ static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef source_name, StringRef result_name) { - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(result_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); + if (result_info) { + return result_info->domain; } - ReadAttributeLookup source_attribute = component.attribute_try_get_for_read(source_name); - if (source_attribute) { - return source_attribute.domain; + std::optional<AttributeMetaData> source_info = component.attribute_get_meta_data(source_name); + if (source_info) { + return source_info->domain; } return ATTR_DOMAIN_POINT; } @@ -75,14 +75,14 @@ static bool conversion_can_be_skipped(const GeometryComponent &component, if (source_name != result_name) { return false; } - ReadAttributeLookup read_attribute = component.attribute_try_get_for_read(source_name); - if (!read_attribute) { + std::optional<AttributeMetaData> info = component.attribute_get_meta_data(result_name); + if (!info) { return false; } - if (read_attribute.domain != result_domain) { + if (info->domain != result_domain) { return false; } - if (read_attribute.varray->type() != *bke::custom_data_type_to_cpp_type(result_type)) { + if (info->data_type != result_type) { return false; } return true; diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc index 8287313e400..3df64625b99 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc @@ -68,13 +68,12 @@ static void geo_node_attribute_fill_update(bNodeTree *UNUSED(ntree), bNode *node namespace blender::nodes { -static AttributeDomain get_result_domain(const GeometryComponent &component, - StringRef attribute_name) +static AttributeDomain get_result_domain(const GeometryComponent &component, const StringRef name) { /* Use the domain of the result attribute if it already exists. */ - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(attribute_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(name); + if (result_info) { + return result_info->domain; } return ATTR_DOMAIN_POINT; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc index 4a98d6caed2..5d82897e9db 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc @@ -318,13 +318,13 @@ static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef source_name, StringRef result_name) { - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(result_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); + if (result_info) { + return result_info->domain; } - ReadAttributeLookup source_attribute = component.attribute_try_get_for_read(source_name); - if (source_attribute) { - return source_attribute.domain; + std::optional<AttributeMetaData> source_info = component.attribute_get_meta_data(source_name); + if (source_info) { + return source_info->domain; } return ATTR_DOMAIN_POINT; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc index 99ba6acd94d..00ae6b373b2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc @@ -200,9 +200,9 @@ static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef result_name) { /* Use the domain of the result attribute if it already exists. */ - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(result_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); + if (result_info) { + return result_info->domain; } /* Otherwise use the highest priority domain from existing input attributes, or the default. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc index e7f0de8f28e..7129679117d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc @@ -141,9 +141,9 @@ static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef result_name) { /* Use the domain of the result attribute if it already exists. */ - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(result_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); + if (result_info) { + return result_info->domain; } /* Otherwise use the highest priority domain from existing input attributes, or the default. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc index e86fa3ae0ed..cc6aacaca79 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc @@ -196,12 +196,12 @@ Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &compo static AttributeDomain get_result_domain(const GeometryComponent &component, const GeoNodeExecParams ¶ms, - StringRef attribute_name) + const StringRef name) { /* Use the domain of the result attribute if it already exists. */ - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(attribute_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(name); + if (result_info) { + return result_info->domain; } /* Otherwise use the input domain chosen in the interface. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc index 5b3fd75342a..fa11ef936cd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc @@ -49,20 +49,19 @@ static void geo_node_attribute_sample_texture_layout(uiLayout *layout, namespace blender::nodes { static AttributeDomain get_result_domain(const GeometryComponent &component, - StringRef result_attribute_name, - StringRef map_attribute_name) + const StringRef result_name, + const StringRef map_name) { /* Use the domain of the result attribute if it already exists. */ - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read( - result_attribute_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); + if (result_info) { + return result_info->domain; } /* Otherwise use the name of the map attribute. */ - ReadAttributeLookup map_attribute = component.attribute_try_get_for_read(map_attribute_name); - if (map_attribute) { - return map_attribute.domain; + std::optional<AttributeMetaData> map_info = component.attribute_get_meta_data(map_name); + if (map_info) { + return map_info->domain; } /* The node won't execute in this case, but we still have to return a value. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_separate_xyz.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_separate_xyz.cc index daf61b6bf57..bbc6cb71032 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_separate_xyz.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_separate_xyz.cc @@ -71,23 +71,23 @@ static void extract_input(const int index, const Span<float3> &input, MutableSpa static AttributeDomain get_result_domain(const GeometryComponent &component, const GeoNodeExecParams ¶ms, - StringRef result_name_x, - StringRef result_name_y, - StringRef result_name_z) + const StringRef name_x, + const StringRef name_y, + const StringRef name_z) { /* Use the highest priority domain from any existing attribute outputs. */ Vector<AttributeDomain, 3> output_domains; - ReadAttributeLookup attribute_x = component.attribute_try_get_for_read(result_name_x); - ReadAttributeLookup attribute_y = component.attribute_try_get_for_read(result_name_y); - ReadAttributeLookup attribute_z = component.attribute_try_get_for_read(result_name_z); - if (attribute_x) { - output_domains.append(attribute_x.domain); + std::optional<AttributeMetaData> info_x = component.attribute_get_meta_data(name_x); + std::optional<AttributeMetaData> info_y = component.attribute_get_meta_data(name_y); + std::optional<AttributeMetaData> info_z = component.attribute_get_meta_data(name_z); + if (info_x) { + output_domains.append(info_x->domain); } - if (attribute_y) { - output_domains.append(attribute_y.domain); + if (info_y) { + output_domains.append(info_y->domain); } - if (attribute_z) { - output_domains.append(attribute_z.domain); + if (info_z) { + output_domains.append(info_z->domain); } if (output_domains.size() > 0) { return bke::attribute_domain_highest_priority(output_domains); diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc index 28d5d9a96f7..772bd8a1080 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc @@ -306,17 +306,14 @@ BLI_NOINLINE static void interpolate_existing_attributes( const MeshComponent &source_component = *set.get_component_for_read<MeshComponent>(); const Mesh &mesh = *source_component.get_for_read(); - /* Use a dummy read without specifying a domain or data type in order to - * get the existing attribute's domain. Interpolation is done manually based - * on the bary coords in #interpolate_attribute. */ - ReadAttributeLookup dummy_attribute = source_component.attribute_try_get_for_read( + std::optional<AttributeMetaData> attribute_info = component.attribute_get_meta_data( attribute_name); - if (!dummy_attribute) { + if (!attribute_info) { i_instance += set_group.transforms.size(); continue; } - const AttributeDomain source_domain = dummy_attribute.domain; + const AttributeDomain source_domain = attribute_info->domain; GVArrayPtr source_attribute = source_component.attribute_get_for_read( attribute_name, source_domain, output_data_type, nullptr); if (!source_attribute) { diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc index 2648336f0c0..08fbe1ac1e6 100644 --- a/source/blender/nodes/intern/node_geometry_exec.cc +++ b/source/blender/nodes/intern/node_geometry_exec.cc @@ -126,11 +126,11 @@ CustomDataType GeoNodeExecParams::get_input_attribute_data_type( if (found_socket->type == SOCK_STRING) { const std::string name = this->get_input<std::string>(found_socket->identifier); - ReadAttributeLookup attribute = component.attribute_try_get_for_read(name); - if (!attribute) { - return default_type; + std::optional<AttributeMetaData> info = component.attribute_get_meta_data(name); + if (info) { + return info->data_type; } - return bke::cpp_type_to_custom_data_type(attribute.varray->type()); + return default_type; } if (found_socket->type == SOCK_FLOAT) { return CD_PROP_FLOAT; @@ -169,9 +169,9 @@ AttributeDomain GeoNodeExecParams::get_highest_priority_input_domain( if (found_socket->type == SOCK_STRING) { const std::string name = this->get_input<std::string>(found_socket->identifier); - ReadAttributeLookup attribute = component.attribute_try_get_for_read(name); - if (attribute) { - input_domains.append(attribute.domain); + std::optional<AttributeMetaData> info = component.attribute_get_meta_data(name); + if (info) { + input_domains.append(info->domain); } } } diff --git a/source/blender/python/gpu/gpu_py_buffer.c b/source/blender/python/gpu/gpu_py_buffer.c index d0965e83e33..e36e3b42617 100644 --- a/source/blender/python/gpu/gpu_py_buffer.c +++ b/source/blender/python/gpu/gpu_py_buffer.c @@ -37,17 +37,90 @@ #include "gpu_py_buffer.h" -// #define PYGPU_BUFFER_PROTOCOL +//#define PYGPU_BUFFER_PROTOCOL +#define MAX_DIMENSIONS 64 /* -------------------------------------------------------------------- */ /** \name Utility Functions * \{ */ -static bool pygpu_buffer_dimensions_compare(int ndim, - const Py_ssize_t *shape_a, - const Py_ssize_t *shape_b) +static Py_ssize_t pygpu_buffer_dimensions_tot_elem(const Py_ssize_t *shape, Py_ssize_t shape_len) +{ + Py_ssize_t tot = shape[0]; + for (int i = 1; i < shape_len; i++) { + tot *= shape[i]; + } + + return tot; +} + +static bool pygpu_buffer_dimensions_tot_len_compare(const Py_ssize_t *shape_a, + const Py_ssize_t shape_a_len, + const Py_ssize_t *shape_b, + const Py_ssize_t shape_b_len) +{ + if (pygpu_buffer_dimensions_tot_elem(shape_a, shape_a_len) != + pygpu_buffer_dimensions_tot_elem(shape_b, shape_b_len)) { + PyErr_Format(PyExc_BufferError, "array size does not match"); + return false; + } + + return true; +} + +static bool pygpu_buffer_pyobj_as_shape(PyObject *shape_obj, + Py_ssize_t r_shape[MAX_DIMENSIONS], + Py_ssize_t *r_shape_len) { - return (bool)memcmp(shape_a, shape_b, ndim * sizeof(Py_ssize_t)); + Py_ssize_t shape_len = 0; + if (PyLong_Check(shape_obj)) { + shape_len = 1; + if (((r_shape[0] = PyLong_AsLong(shape_obj)) < 1)) { + PyErr_SetString(PyExc_AttributeError, "dimension must be greater than or equal to 1"); + return false; + } + } + else if (PySequence_Check(shape_obj)) { + shape_len = PySequence_Size(shape_obj); + if (shape_len > MAX_DIMENSIONS) { + PyErr_SetString(PyExc_AttributeError, + "too many dimensions, max is " STRINGIFY(MAX_DIMENSIONS)); + return false; + } + if (shape_len < 1) { + PyErr_SetString(PyExc_AttributeError, "sequence must have at least one dimension"); + return false; + } + + for (int i = 0; i < shape_len; i++) { + PyObject *ob = PySequence_GetItem(shape_obj, i); + if (!PyLong_Check(ob)) { + PyErr_Format(PyExc_TypeError, + "invalid dimension %i, expected an int, not a %.200s", + i, + Py_TYPE(ob)->tp_name); + Py_DECREF(ob); + return false; + } + + r_shape[i] = PyLong_AsLong(ob); + Py_DECREF(ob); + + if (r_shape[i] < 1) { + PyErr_SetString(PyExc_AttributeError, "dimension must be greater than or equal to 1"); + return false; + } + } + } + else { + PyErr_Format(PyExc_TypeError, + "invalid second argument argument expected a sequence " + "or an int, not a %.200s", + Py_TYPE(shape_obj)->tp_name); + } + + *r_shape_len = shape_len; + return true; } static const char *pygpu_buffer_formatstr(eGPUDataFormat data_format) @@ -174,7 +247,7 @@ static PyObject *pygpu_buffer_to_list_recursive(BPyGPUBuffer *self) return list; } -static PyObject *pygpu_buffer_dimensions(BPyGPUBuffer *self, void *UNUSED(arg)) +static PyObject *pygpu_buffer_dimensions_get(BPyGPUBuffer *self, void *UNUSED(arg)) { PyObject *list = PyList_New(self->shape_len); int i; @@ -186,6 +259,30 @@ static PyObject *pygpu_buffer_dimensions(BPyGPUBuffer *self, void *UNUSED(arg)) return list; } +static int pygpu_buffer_dimensions_set(BPyGPUBuffer *self, PyObject *value, void *UNUSED(type)) +{ + Py_ssize_t shape[MAX_DIMENSIONS]; + Py_ssize_t shape_len = 0; + + if (!pygpu_buffer_pyobj_as_shape(value, shape, &shape_len)) { + return -1; + } + + if (!pygpu_buffer_dimensions_tot_len_compare(shape, shape_len, self->shape, self->shape_len)) { + return -1; + } + + size_t size = shape_len * sizeof(*self->shape); + if (shape_len != self->shape_len) { + MEM_freeN(self->shape); + self->shape = MEM_mallocN(size, __func__); + } + + self->shape_len = shape_len; + memcpy(self->shape, shape, size); + return 0; +} + static int pygpu_buffer__tp_traverse(BPyGPUBuffer *self, visitproc visit, void *arg) { Py_VISIT(self->parent); @@ -280,14 +377,13 @@ static int pygpu_buffer_ass_slice(BPyGPUBuffer *self, return err; } -#define MAX_DIMENSIONS 64 static PyObject *pygpu_buffer__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) { PyObject *length_ob, *init = NULL; BPyGPUBuffer *buffer = NULL; Py_ssize_t shape[MAX_DIMENSIONS]; - Py_ssize_t i, shape_len = 0; + Py_ssize_t shape_len = 0; if (kwds && PyDict_Size(kwds)) { PyErr_SetString(PyExc_TypeError, "Buffer(): takes no keyword args"); @@ -300,49 +396,7 @@ static PyObject *pygpu_buffer__tp_new(PyTypeObject *UNUSED(type), PyObject *args return NULL; } - if (PyLong_Check(length_ob)) { - shape_len = 1; - if (((shape[0] = PyLong_AsLong(length_ob)) < 1)) { - PyErr_SetString(PyExc_AttributeError, "dimension must be greater than or equal to 1"); - return NULL; - } - } - else if (PySequence_Check(length_ob)) { - shape_len = PySequence_Size(length_ob); - if (shape_len > MAX_DIMENSIONS) { - PyErr_SetString(PyExc_AttributeError, - "too many dimensions, max is " STRINGIFY(MAX_DIMENSIONS)); - return NULL; - } - if (shape_len < 1) { - PyErr_SetString(PyExc_AttributeError, "sequence must have at least one dimension"); - return NULL; - } - - for (i = 0; i < shape_len; i++) { - PyObject *ob = PySequence_GetItem(length_ob, i); - if (!PyLong_Check(ob)) { - PyErr_Format(PyExc_TypeError, - "invalid dimension %i, expected an int, not a %.200s", - i, - Py_TYPE(ob)->tp_name); - Py_DECREF(ob); - return NULL; - } - shape[i] = PyLong_AsLong(ob); - Py_DECREF(ob); - - if (shape[i] < 1) { - PyErr_SetString(PyExc_AttributeError, "dimension must be greater than or equal to 1"); - return NULL; - } - } - } - else { - PyErr_Format(PyExc_TypeError, - "invalid second argument argument expected a sequence " - "or an int, not a %.200s", - Py_TYPE(length_ob)->tp_name); + if (!pygpu_buffer_pyobj_as_shape(length_ob, shape, &shape_len)) { return NULL; } @@ -354,11 +408,7 @@ static PyObject *pygpu_buffer__tp_new(PyTypeObject *UNUSED(type), PyObject *args return NULL; } - if (shape_len != pybuffer.ndim || - !pygpu_buffer_dimensions_compare(shape_len, shape, pybuffer.shape)) { - PyErr_Format(PyExc_TypeError, "array size does not match"); - } - else { + if (pygpu_buffer_dimensions_tot_len_compare(shape, shape_len, pybuffer.shape, pybuffer.ndim)) { buffer = pygpu_buffer_make_from_data( init, pygpu_dataformat.value_found, pybuffer.ndim, shape, pybuffer.buf); } @@ -518,7 +568,11 @@ static PyMethodDef pygpu_buffer__tp_methods[] = { }; static PyGetSetDef pygpu_buffer_getseters[] = { - {"dimensions", (getter)pygpu_buffer_dimensions, NULL, NULL, NULL}, + {"dimensions", + (getter)pygpu_buffer_dimensions_get, + (setter)pygpu_buffer_dimensions_set, + NULL, + NULL}, {NULL, NULL, NULL, NULL, NULL}, }; @@ -625,13 +679,7 @@ static size_t pygpu_buffer_calc_size(const int format, const int shape_len, const Py_ssize_t *shape) { - size_t r_size = GPU_texture_dataformat_size(format); - - for (int i = 0; i < shape_len; i++) { - r_size *= shape[i]; - } - - return r_size; + return pygpu_buffer_dimensions_tot_elem(shape, shape_len) * GPU_texture_dataformat_size(format); } size_t bpygpu_Buffer_size(BPyGPUBuffer *buffer) diff --git a/source/blender/python/gpu/gpu_py_framebuffer.c b/source/blender/python/gpu/gpu_py_framebuffer.c index 34d17bb10c3..bc393aaafa4 100644 --- a/source/blender/python/gpu/gpu_py_framebuffer.c +++ b/source/blender/python/gpu/gpu_py_framebuffer.c @@ -492,7 +492,7 @@ static struct PyMethodDef pygpu_framebuffer__tp_methods[] = { pygpu_framebuffer_viewport_set_doc}, {"viewport_get", (PyCFunction)pygpu_framebuffer_viewport_get, - METH_VARARGS, + METH_NOARGS, pygpu_framebuffer_viewport_get_doc}, #ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD {"free", (PyCFunction)pygpu_framebuffer_free, METH_NOARGS, pygpu_framebuffer_free_doc}, diff --git a/source/blender/sequencer/intern/image_cache.c b/source/blender/sequencer/intern/image_cache.c index 290ee185865..089bb5a6bec 100644 --- a/source/blender/sequencer/intern/image_cache.c +++ b/source/blender/sequencer/intern/image_cache.c @@ -976,14 +976,34 @@ static void seq_cache_recycle_linked(Scene *scene, SeqCacheKey *base) SeqCacheKey *next = base->link_next; while (base) { + if (!BLI_ghash_haskey(cache->hash, base)) { + break; /* Key has already been removed from cache. */ + } + SeqCacheKey *prev = base->link_prev; + if (prev != NULL && prev->link_next != base) { + /* Key has been removed and replaced and doesn't belong to this chain anymore. */ + base->link_prev = NULL; + break; + } + BLI_ghash_remove(cache->hash, base, seq_cache_keyfree, seq_cache_valfree); base = prev; } base = next; while (base) { + if (!BLI_ghash_haskey(cache->hash, base)) { + break; /* Key has already been removed from cache. */ + } + next = base->link_next; + if (next != NULL && next->link_prev != base) { + /* Key has been removed and replaced and doesn't belong to this chain anymore. */ + base->link_next = NULL; + break; + } + BLI_ghash_remove(cache->hash, base, seq_cache_keyfree, seq_cache_valfree); base = next; } diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c index 572fff0ad38..96c881c9c5f 100644 --- a/source/blender/sequencer/intern/render.c +++ b/source/blender/sequencer/intern/render.c @@ -1537,13 +1537,14 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, /* opengl offscreen render */ depsgraph = BKE_scene_ensure_depsgraph(context->bmain, scene, view_layer); BKE_scene_graph_update_for_newframe(depsgraph); + Object *camera_eval = DEG_get_evaluated_object(depsgraph, camera); ibuf = sequencer_view3d_fn( /* set for OpenGL render (NULL when scrubbing) */ depsgraph, scene, &context->scene->display.shading, context->scene->r.seq_prev_type, - camera, + camera_eval, width, height, IB_rect, diff --git a/source/blender/sequencer/intern/strip_relations.c b/source/blender/sequencer/intern/strip_relations.c index 1a2ff08bd08..1215cb78b56 100644 --- a/source/blender/sequencer/intern/strip_relations.c +++ b/source/blender/sequencer/intern/strip_relations.c @@ -114,7 +114,6 @@ static void sequence_invalidate_cache(Scene *scene, Editing *ed = scene->ed; if (invalidate_self) { - SEQ_relations_sequence_free_anim(seq); seq_cache_cleanup_sequence(scene, seq, seq, invalidate_types, false); } |