diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
52 files changed, 1210 insertions, 1034 deletions
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 842902b51ed..2cc1cba99cd 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -176,7 +176,7 @@ static void action_foreach_id(ID *id, LibraryForeachIDData *data) bAction *act = (bAction *)id; LISTBASE_FOREACH (FCurve *, fcu, &act->curves) { - BKE_fcurve_foreach_id(fcu, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, BKE_fcurve_foreach_id(fcu, data)); } LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) { diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c index 23d2c4fe55f..21887d514d9 100644 --- a/source/blender/blenkernel/intern/anim_data.c +++ b/source/blender/blenkernel/intern/anim_data.c @@ -294,7 +294,7 @@ bool BKE_animdata_id_is_animated(const struct ID *id) void BKE_animdata_foreach_id(AnimData *adt, LibraryForeachIDData *data) { LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) { - BKE_fcurve_foreach_id(fcu, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, BKE_fcurve_foreach_id(fcu, data)); } BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, adt->action, IDWALK_CB_USER); diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 08a3b7d0bbb..d872dc67dcb 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -279,23 +279,31 @@ bool BKE_appdir_folder_caches(char *r_path, const size_t path_len) /** * Gets a good default directory for fonts. */ -bool BKE_appdir_font_folder_default( - /* This parameter can only be `const` on non-windows platforms. - * NOLINTNEXTLINE: readability-non-const-parameter. */ - char *dir) +bool BKE_appdir_font_folder_default(char *dir) { - bool success = false; + char test_dir[FILE_MAXDIR]; + test_dir[0] = '\0'; + #ifdef WIN32 wchar_t wpath[FILE_MAXDIR]; - success = SHGetSpecialFolderPathW(0, wpath, CSIDL_FONTS, 0); - if (success) { + if (SHGetSpecialFolderPathW(0, wpath, CSIDL_FONTS, 0)) { wcscat(wpath, L"\\"); - BLI_strncpy_wchar_as_utf8(dir, wpath, FILE_MAXDIR); + BLI_strncpy_wchar_as_utf8(test_dir, wpath, sizeof(test_dir)); + } +#elif defined(__APPLE__) + const char *home = BLI_getenv("HOME"); + if (home) { + BLI_path_join(test_dir, sizeof(test_dir), home, "Library", "Fonts", NULL); } +#else + STRNCPY(test_dir, "/usr/share/fonts"); #endif - /* TODO: Values for other platforms. */ - UNUSED_VARS(dir); - return success; + + if (test_dir[0] && BLI_exists(test_dir)) { + BLI_strncpy(dir, test_dir, FILE_MAXDIR); + return true; + } + return false; } /** \} */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index b64b050f4e7..b830c9de5f5 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -161,30 +161,36 @@ static void armature_free_data(struct ID *id) static void armature_foreach_id_bone(Bone *bone, LibraryForeachIDData *data) { - IDP_foreach_property( - bone->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, + IDP_foreach_property( + bone->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data)); LISTBASE_FOREACH (Bone *, curbone, &bone->childbase) { - armature_foreach_id_bone(curbone, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, armature_foreach_id_bone(curbone, data)); } } static void armature_foreach_id_editbone(EditBone *edit_bone, LibraryForeachIDData *data) { - IDP_foreach_property( - edit_bone->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, + IDP_foreach_property(edit_bone->prop, + IDP_TYPE_FILTER_ID, + BKE_lib_query_idpropertiesForeachIDLink_callback, + data)); } static void armature_foreach_id(ID *id, LibraryForeachIDData *data) { bArmature *arm = (bArmature *)id; LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) { - armature_foreach_id_bone(bone, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, armature_foreach_id_bone(bone, data)); } if (arm->edbo != NULL) { LISTBASE_FOREACH (EditBone *, edit_bone, arm->edbo) { - armature_foreach_id_editbone(edit_bone, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, armature_foreach_id_editbone(edit_bone, data)); } } } diff --git a/source/blender/blenkernel/intern/asset.cc b/source/blender/blenkernel/intern/asset.cc index 7bea089b9bf..59e402b6680 100644 --- a/source/blender/blenkernel/intern/asset.cc +++ b/source/blender/blenkernel/intern/asset.cc @@ -21,14 +21,12 @@ #include <cstring> #include "DNA_ID.h" -#include "DNA_asset_types.h" #include "DNA_defaults.h" #include "BLI_listbase.h" #include "BLI_string.h" #include "BLI_string_ref.hh" #include "BLI_string_utils.h" -#include "BLI_utildefines.h" #include "BLI_uuid.h" #include "BKE_asset.h" diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc index 13f66445c46..03043f3b784 100644 --- a/source/blender/blenkernel/intern/asset_catalog.cc +++ b/source/blender/blenkernel/intern/asset_catalog.cc @@ -18,25 +18,20 @@ * \ingroup bke */ +#include <fstream> +#include <set> + #include "BKE_asset_catalog.hh" #include "BKE_asset_library.h" -#include "BKE_preferences.h" #include "BLI_fileops.h" #include "BLI_path_util.h" -#include "BLI_set.hh" -#include "BLI_string_ref.hh" - -#include "DNA_userdef_types.h" /* For S_ISREG() and S_ISDIR() on Windows. */ #ifdef WIN32 # include "BLI_winstuff.h" #endif -#include <fstream> -#include <set> - namespace blender::bke { const CatalogFilePath AssetCatalogService::DEFAULT_CATALOG_FILENAME = "blender_assets.cats.txt"; diff --git a/source/blender/blenkernel/intern/asset_catalog_test.cc b/source/blender/blenkernel/intern/asset_catalog_test.cc index 2cef34966f8..ba8f8716823 100644 --- a/source/blender/blenkernel/intern/asset_catalog_test.cc +++ b/source/blender/blenkernel/intern/asset_catalog_test.cc @@ -24,6 +24,7 @@ #include "BLI_fileops.h" #include "BLI_path_util.h" +#include "DNA_asset_types.h" #include "DNA_userdef_types.h" #include "testing/testing.h" @@ -930,6 +931,28 @@ TEST_F(AssetCatalogTest, update_catalog_path_simple_name) << "Changing the path should update the simplename of children."; } +TEST_F(AssetCatalogTest, update_catalog_path_longer_than_simplename) +{ + AssetCatalogService service(asset_library_root_); + service.load_from_disk(asset_library_root_ + "/" + + AssetCatalogService::DEFAULT_CATALOG_FILENAME); + const std::string new_path = + "this/is/a/very/long/path/that/exceeds/the/simple-name/length/of/assets"; + ASSERT_GT(new_path.length(), sizeof(AssetMetaData::catalog_simple_name)) + << "This test case should work with paths longer than AssetMetaData::catalog_simple_name"; + + service.update_catalog_path(UUID_POSES_RUZENA, new_path); + + const std::string new_simple_name = service.find_catalog(UUID_POSES_RUZENA)->simple_name; + EXPECT_LT(new_simple_name.length(), sizeof(AssetMetaData::catalog_simple_name)) + << "The new simple name should fit in the asset metadata."; + EXPECT_EQ("...very-long-path-that-exceeds-the-simple-name-length-of-assets", new_simple_name) + << "Changing the path should update the simplename."; + EXPECT_EQ("...long-path-that-exceeds-the-simple-name-length-of-assets-face", + service.find_catalog(UUID_POSES_RUZENA_FACE)->simple_name) + << "Changing the path should update the simplename of children."; +} + TEST_F(AssetCatalogTest, update_catalog_path_add_slashes) { AssetCatalogService service(asset_library_root_); diff --git a/source/blender/blenkernel/intern/asset_library.cc b/source/blender/blenkernel/intern/asset_library.cc index aae8a289d32..68e43852a21 100644 --- a/source/blender/blenkernel/intern/asset_library.cc +++ b/source/blender/blenkernel/intern/asset_library.cc @@ -18,9 +18,9 @@ * \ingroup bke */ -#include "BKE_asset_catalog.hh" +#include <memory> + #include "BKE_asset_library.hh" -#include "BKE_callbacks.h" #include "BKE_main.h" #include "BKE_preferences.h" @@ -29,12 +29,8 @@ #include "DNA_asset_types.h" #include "DNA_userdef_types.h" -#include "MEM_guardedalloc.h" - #include "asset_library_service.hh" -#include <memory> - bool blender::bke::AssetLibrary::save_catalogs_when_file_is_saved = true; /** diff --git a/source/blender/blenkernel/intern/asset_library_service.cc b/source/blender/blenkernel/intern/asset_library_service.cc index 7cf95ee4cc1..d202d6462cf 100644 --- a/source/blender/blenkernel/intern/asset_library_service.cc +++ b/source/blender/blenkernel/intern/asset_library_service.cc @@ -20,16 +20,12 @@ #include "asset_library_service.hh" -#include "BKE_asset_library.hh" #include "BKE_blender.h" -#include "BKE_callbacks.h" -#include "BLI_fileops.h" +#include "BLI_fileops.h" /* For PATH_MAX (at least on Windows). */ #include "BLI_path_util.h" #include "BLI_string_ref.hh" -#include "MEM_guardedalloc.h" - #include "CLG_log.h" static CLG_LogRef LOG = {"bke.asset_service"}; diff --git a/source/blender/blenkernel/intern/asset_library_service_test.cc b/source/blender/blenkernel/intern/asset_library_service_test.cc index e26ae05301e..ee910cab945 100644 --- a/source/blender/blenkernel/intern/asset_library_service_test.cc +++ b/source/blender/blenkernel/intern/asset_library_service_test.cc @@ -19,7 +19,7 @@ #include "asset_library_service.hh" -#include "BLI_fileops.h" +#include "BLI_fileops.h" /* For PATH_MAX (at least on Windows). */ #include "BLI_path_util.h" #include "BKE_appdir.h" diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index cd394a4ca42..f3ece270618 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -50,9 +50,7 @@ using blender::bke::AttributeIDRef; using blender::bke::OutputAttribute; using blender::fn::GMutableSpan; using blender::fn::GSpan; -using blender::fn::GVArray_For_GSpan; -using blender::fn::GVArray_For_SingleValue; -using blender::fn::GVMutableArray_For_GMutableSpan; +using blender::fn::GVMutableArrayImpl_For_GMutableSpan; namespace blender::bke { @@ -207,7 +205,7 @@ fn::GMutableSpan OutputAttribute::as_span() { if (!optional_span_varray_) { const bool materialize_old_values = !ignore_old_values_; - optional_span_varray_ = std::make_unique<fn::GVMutableArray_GSpan>(*varray_, + optional_span_varray_ = std::make_unique<fn::GVMutableArray_GSpan>(varray_, materialize_old_values); } fn::GVMutableArray_GSpan &span_varray = *optional_span_varray_; @@ -257,8 +255,8 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data if (data == nullptr) { return false; } - const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray; - varray->materialize_to_uninitialized(IndexRange(varray->size()), data); + const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray; + varray.materialize_to_uninitialized(varray.index_range(), data); return true; } case AttributeInit::Type::MoveArray: { @@ -313,8 +311,8 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr if (data == nullptr) { return false; } - const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray; - varray->materialize_to_uninitialized(IndexRange(varray->size()), data); + const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray; + varray.materialize_to_uninitialized(varray.index_range(), data); return true; } case AttributeInit::Type::MoveArray: { @@ -345,8 +343,7 @@ static bool custom_data_layer_matches_attribute_id(const CustomDataLayer &layer, return layer.name == attribute_id.name(); } -GVArrayPtr BuiltinCustomDataLayerProvider::try_get_for_read( - const GeometryComponent &component) const +GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const GeometryComponent &component) const { const CustomData *custom_data = custom_data_access_.get_const_custom_data(component); if (custom_data == nullptr) { @@ -511,7 +508,7 @@ ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read( continue; } GSpan data{*type, layer.data, domain_size}; - return {std::make_unique<GVArray_For_GSpan>(data), domain_}; + return {GVArray::ForSpan(data), domain_}; } return {}; } @@ -541,7 +538,7 @@ WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write( continue; } GMutableSpan data{*type, layer.data, domain_size}; - return {std::make_unique<GVMutableArray_For_GMutableSpan>(data), domain_}; + return {GVMutableArray::ForSpan(data), domain_}; } return {}; } @@ -751,25 +748,25 @@ std::optional<GSpan> CustomDataAttributes::get_for_read(const AttributeIDRef &at * value if the attribute doesn't exist. If no default value is provided, the default value for the * type will be used. */ -GVArrayPtr CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id, - const CustomDataType data_type, - const void *default_value) const +GVArray CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id, + const CustomDataType data_type, + const void *default_value) const { const CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type); std::optional<GSpan> attribute = this->get_for_read(attribute_id); if (!attribute) { const int domain_size = this->size_; - return std::make_unique<GVArray_For_SingleValue>( + return GVArray::ForSingle( *type, domain_size, (default_value == nullptr) ? type->default_value() : default_value); } if (attribute->type() == *type) { - return std::make_unique<GVArray_For_GSpan>(*attribute); + return GVArray::ForSpan(*attribute); } const blender::nodes::DataTypeConversions &conversions = blender::nodes::get_implicit_type_conversions(); - return conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), *type); + return conversions.try_convert(GVArray::ForSpan(*attribute), *type); } std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const AttributeIDRef &attribute_id) @@ -922,8 +919,8 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read( return {}; } -std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_adapt_domain( - std::unique_ptr<blender::fn::GVArray> varray, +blender::fn::GVArray GeometryComponent::attribute_try_adapt_domain_impl( + const blender::fn::GVArray &varray, const AttributeDomain from_domain, const AttributeDomain to_domain) const { @@ -1110,15 +1107,15 @@ std::optional<AttributeMetaData> GeometryComponent::attribute_get_meta_data( 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) +static blender::fn::GVArray try_adapt_data_type(blender::fn::GVArray varray, + const blender::fn::CPPType &to_type) { const blender::nodes::DataTypeConversions &conversions = blender::nodes::get_implicit_type_conversions(); return conversions.try_convert(std::move(varray), to_type); } -std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_read( +blender::fn::GVArray GeometryComponent::attribute_try_get_for_read( const AttributeIDRef &attribute_id, const AttributeDomain domain, const CustomDataType data_type) const @@ -1128,7 +1125,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r return {}; } - std::unique_ptr<blender::fn::GVArray> varray = std::move(attribute.varray); + blender::fn::GVArray varray = std::move(attribute.varray); if (!ELEM(domain, ATTR_DOMAIN_AUTO, attribute.domain)) { varray = this->attribute_try_adapt_domain(std::move(varray), attribute.domain, domain); if (!varray) { @@ -1138,7 +1135,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r const blender::fn::CPPType *cpp_type = blender::bke::custom_data_type_to_cpp_type(data_type); BLI_assert(cpp_type != nullptr); - if (varray->type() != *cpp_type) { + if (varray.type() != *cpp_type) { varray = try_adapt_data_type(std::move(varray), *cpp_type); if (!varray) { return {}; @@ -1148,7 +1145,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r return varray; } -std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_try_get_for_read( +blender::fn::GVArray GeometryComponent::attribute_try_get_for_read( const AttributeIDRef &attribute_id, const AttributeDomain domain) const { if (!this->attribute_domain_supported(domain)) { @@ -1176,7 +1173,7 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read( } const blender::fn::CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type); BLI_assert(type != nullptr); - if (attribute.varray->type() == *type) { + if (attribute.varray.type() == *type) { return attribute; } const blender::nodes::DataTypeConversions &conversions = @@ -1184,14 +1181,12 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read( return {conversions.try_convert(std::move(attribute.varray), *type), attribute.domain}; } -std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read( - const AttributeIDRef &attribute_id, - const AttributeDomain domain, - const CustomDataType data_type, - const void *default_value) const +blender::fn::GVArray GeometryComponent::attribute_get_for_read(const AttributeIDRef &attribute_id, + const AttributeDomain domain, + const CustomDataType data_type, + const void *default_value) const { - std::unique_ptr<blender::bke::GVArray> varray = this->attribute_try_get_for_read( - attribute_id, domain, data_type); + blender::fn::GVArray varray = this->attribute_try_get_for_read(attribute_id, domain, data_type); if (varray) { return varray; } @@ -1200,11 +1195,11 @@ std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read default_value = type->default_value(); } const int domain_size = this->attribute_domain_size(domain); - return std::make_unique<blender::fn::GVArray_For_SingleValue>(*type, domain_size, default_value); + return blender::fn::GVArray::ForSingle(*type, domain_size, default_value); } class GVMutableAttribute_For_OutputAttribute - : public blender::fn::GVMutableArray_For_GMutableSpan { + : public blender::fn::GVMutableArrayImpl_For_GMutableSpan { public: GeometryComponent *component; std::string attribute_name; @@ -1213,7 +1208,7 @@ class GVMutableAttribute_For_OutputAttribute GVMutableAttribute_For_OutputAttribute(GMutableSpan data, GeometryComponent &component, const AttributeIDRef &attribute_id) - : blender::fn::GVMutableArray_For_GMutableSpan(data), component(&component) + : blender::fn::GVMutableArrayImpl_For_GMutableSpan(data), component(&component) { if (attribute_id.is_named()) { this->attribute_name = attribute_id.name(); @@ -1239,7 +1234,8 @@ static void save_output_attribute(OutputAttribute &output_attribute) using namespace blender::bke; GVMutableAttribute_For_OutputAttribute &varray = - dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(output_attribute.varray()); + dynamic_cast<GVMutableAttribute_For_OutputAttribute &>( + *output_attribute.varray().get_implementation()); GeometryComponent &component = *varray.component; AttributeIDRef attribute_id; @@ -1267,7 +1263,7 @@ static void save_output_attribute(OutputAttribute &output_attribute) BUFFER_FOR_CPP_TYPE_VALUE(varray.type(), buffer); for (const int i : IndexRange(varray.size())) { varray.get(i, buffer); - write_attribute.varray->set_by_relocate(i, buffer); + write_attribute.varray.set_by_relocate(i, buffer); } if (write_attribute.tag_modified_fn) { write_attribute.tag_modified_fn(); @@ -1310,9 +1306,9 @@ static OutputAttribute create_output_attribute(GeometryComponent &component, if (!attribute) { 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)); + component.attribute_try_create_builtin( + attribute_name, + AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_size, default_value))); } else { component.attribute_try_create_builtin(attribute_name, AttributeInitDefault()); @@ -1327,9 +1323,8 @@ static OutputAttribute create_output_attribute(GeometryComponent &component, /* Builtin attribute is on different domain. */ return {}; } - - GVMutableArrayPtr varray = std::move(attribute.varray); - if (varray->type() == *cpp_type) { + GVMutableArray varray = std::move(attribute.varray); + if (varray.type() == *cpp_type) { /* Builtin attribute matches exactly. */ return OutputAttribute(std::move(varray), domain, @@ -1349,9 +1344,11 @@ static OutputAttribute create_output_attribute(GeometryComponent &component, WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_id); if (!attribute) { if (default_value) { - const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value}; component.attribute_try_create( - attribute_id, domain, data_type, AttributeInitVArray(&default_varray)); + attribute_id, + domain, + data_type, + AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_size, default_value))); } else { component.attribute_try_create(attribute_id, domain, data_type, AttributeInitDefault()); @@ -1363,7 +1360,7 @@ static OutputAttribute create_output_attribute(GeometryComponent &component, return {}; } } - if (attribute.domain == domain && attribute.varray->type() == *cpp_type) { + if (attribute.domain == domain && attribute.varray.type() == *cpp_type) { /* Existing generic attribute matches exactly. */ return OutputAttribute(std::move(attribute.varray), @@ -1382,11 +1379,11 @@ static OutputAttribute create_output_attribute(GeometryComponent &component, } else { /* Fill the temporary array with values from the existing attribute. */ - GVArrayPtr old_varray = component.attribute_get_for_read( + GVArray old_varray = component.attribute_get_for_read( attribute_id, domain, data_type, default_value); - old_varray->materialize_to_uninitialized(IndexRange(domain_size), data); + old_varray.materialize_to_uninitialized(IndexRange(domain_size), data); } - GVMutableArrayPtr varray = std::make_unique<GVMutableAttribute_For_OutputAttribute>( + GVMutableArray varray = GVMutableArray::For<GVMutableAttribute_For_OutputAttribute>( GMutableSpan{*cpp_type, data, domain_size}, component, attribute_id); return OutputAttribute(std::move(varray), domain, save_output_attribute, true); @@ -1410,21 +1407,21 @@ OutputAttribute GeometryComponent::attribute_try_get_for_output_only( namespace blender::bke { -const GVArray *AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context, - IndexMask UNUSED(mask), - ResourceScope &scope) const +GVArray AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context, + IndexMask UNUSED(mask), + ResourceScope &UNUSED(scope)) const { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const GeometryComponent &component = geometry_context->geometry_component(); const AttributeDomain domain = geometry_context->domain(); const CustomDataType data_type = cpp_type_to_custom_data_type(*type_); - GVArrayPtr attribute = component.attribute_try_get_for_read(name_, domain, data_type); + GVArray attribute = component.attribute_try_get_for_read(name_, domain, data_type); if (attribute) { - return scope.add(std::move(attribute)); + return attribute; } } - return nullptr; + return {}; } std::string AttributeFieldInput::socket_inspection_name() const @@ -1457,25 +1454,25 @@ static StringRef get_random_id_attribute_name(const AttributeDomain domain) } } -const GVArray *IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context, - IndexMask mask, - ResourceScope &scope) const +GVArray IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope &scope) const { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const GeometryComponent &component = geometry_context->geometry_component(); const AttributeDomain domain = geometry_context->domain(); const StringRef name = get_random_id_attribute_name(domain); - GVArrayPtr attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32); + GVArray attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32); if (attribute) { - BLI_assert(attribute->size() == component.attribute_domain_size(domain)); - return scope.add(std::move(attribute)); + BLI_assert(attribute.size() == component.attribute_domain_size(domain)); + return attribute; } /* Use the index as the fallback if no random ID attribute exists. */ return fn::IndexFieldInput::get_index_varray(mask, scope); } - return nullptr; + return {}; } std::string IDAttributeFieldInput::socket_inspection_name() const @@ -1495,19 +1492,20 @@ bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr; } -const GVArray *AnonymousAttributeFieldInput::get_varray_for_context( - const fn::FieldContext &context, IndexMask UNUSED(mask), ResourceScope &scope) const +GVArray AnonymousAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context, + IndexMask UNUSED(mask), + ResourceScope &UNUSED(scope)) const { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const GeometryComponent &component = geometry_context->geometry_component(); const AttributeDomain domain = geometry_context->domain(); const CustomDataType data_type = cpp_type_to_custom_data_type(*type_); - GVArrayPtr attribute = component.attribute_try_get_for_read( + GVArray attribute = component.attribute_try_get_for_read( anonymous_id_.get(), domain, data_type); - return scope.add(std::move(attribute)); + return attribute; } - return nullptr; + return {}; } std::string AnonymousAttributeFieldInput::socket_inspection_name() const diff --git a/source/blender/blenkernel/intern/attribute_access_intern.hh b/source/blender/blenkernel/intern/attribute_access_intern.hh index 140498bdb01..b77d7010efa 100644 --- a/source/blender/blenkernel/intern/attribute_access_intern.hh +++ b/source/blender/blenkernel/intern/attribute_access_intern.hh @@ -24,9 +24,6 @@ namespace blender::bke { -using fn::GVArrayPtr; -using fn::GVMutableArrayPtr; - /** * Utility to group together multiple functions that are used to access custom data on geometry * components in a generic way. @@ -86,7 +83,7 @@ class BuiltinAttributeProvider { { } - virtual GVArrayPtr try_get_for_read(const GeometryComponent &component) const = 0; + virtual GVArray try_get_for_read(const GeometryComponent &component) const = 0; virtual WriteAttributeLookup try_get_for_write(GeometryComponent &component) const = 0; virtual bool try_delete(GeometryComponent &component) const = 0; virtual bool try_create(GeometryComponent &UNUSED(component), @@ -188,8 +185,8 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider { */ class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider { private: - using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size); - using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size); + using AsReadAttribute = GVArray (*)(const void *data, const int domain_size); + using AsWriteAttribute = GVMutableArray (*)(void *data, const int domain_size); const AttributeDomain domain_; const CustomDataType attribute_type_; const CustomDataType stored_type_; @@ -232,8 +229,8 @@ class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider { * if the stored type is the same as the attribute type. */ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider { - using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size); - using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size); + using AsReadAttribute = GVArray (*)(const void *data, const int domain_size); + using AsWriteAttribute = GVMutableArray (*)(void *data, const int domain_size); using UpdateOnRead = void (*)(const GeometryComponent &component); using UpdateOnWrite = void (*)(GeometryComponent &component); const CustomDataType stored_type_; @@ -266,7 +263,7 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider { { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const final; + GVArray try_get_for_read(const GeometryComponent &component) const final; WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final; bool try_delete(GeometryComponent &component) const final; bool try_create(GeometryComponent &component, const AttributeInit &initializer) const final; diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 97f8bddc043..fb65a9bec7e 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -90,7 +90,6 @@ void BKE_blender_free(void) IMB_exit(); BKE_cachefiles_exit(); - BKE_images_exit(); DEG_free_node_types(); BKE_brush_system_exit(); diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c index 9c9f898afef..f8b943d3479 100644 --- a/source/blender/blenkernel/intern/blender_copybuffer.c +++ b/source/blender/blenkernel/intern/blender_copybuffer.c @@ -57,20 +57,26 @@ /** \name Copy/Paste `.blend`, partial saves. * \{ */ -void BKE_copybuffer_begin(Main *bmain_src) +/** Initialize a copy operation. */ +void BKE_copybuffer_copy_begin(Main *bmain_src) { BKE_blendfile_write_partial_begin(bmain_src); } -void BKE_copybuffer_tag_ID(ID *id) +/** Mark an ID to be copied. Should only be called after a call to #BKE_copybuffer_copy_begin. */ +void BKE_copybuffer_copy_tag_ID(ID *id) { BKE_blendfile_write_partial_tag_ID(id, true); } /** - * \return Success. + * Finalize a copy operation into given .blend file 'buffer'. + * + * \param filename: Full path to the .blend file used as copy/paste buffer. + * + * \return true on success, false otherwise. */ -bool BKE_copybuffer_save(Main *bmain_src, const char *filename, ReportList *reports) +bool BKE_copybuffer_copy_end(Main *bmain_src, const char *filename, ReportList *reports) { const int write_flags = 0; const eBLO_WritePathRemap remap_mode = BLO_WRITE_PATH_REMAP_RELATIVE; @@ -82,6 +88,16 @@ bool BKE_copybuffer_save(Main *bmain_src, const char *filename, ReportList *repo return retval; } +/** + * Paste datablocks from the given .blend file 'buffer' (i.e. append them). + * + * Unlike #BKE_copybuffer_paste, it does not perform any instantiation of collections/objects/etc. + * + * \param libname: Full path to the .blend file used as copy/paste buffer. + * \param id_types_mask: Only directly link IDs of those types from the given .blend file buffer. + * + * \return true on success, false otherwise. + */ bool BKE_copybuffer_read(Main *bmain_dst, const char *libname, ReportList *reports, @@ -116,12 +132,22 @@ bool BKE_copybuffer_read(Main *bmain_dst, } /** - * \return Number of IDs directly pasted from the buffer - * (does not includes indirectly pulled out ones). + * Paste datablocks from the given .blend file 'buffer' (i.e. append them). + * + * Similar to #BKE_copybuffer_read, but also handles instantiation of collections/objects/etc. + * + * \param libname: Full path to the .blend file used as copy/paste buffer. + * \param flag: A combination of #eBLOLibLinkFlags and ##eFileSel_Params_Flag to control + * link/append behavior. + * \note: Ignores #FILE_LINK flag, since it always appends IDs. + * \param id_types_mask: Only directly link IDs of those types from the given .blend file buffer. + * + * \return Number of IDs directly pasted from the buffer (does not includes indirectly linked + * ones). */ int BKE_copybuffer_paste(bContext *C, const char *libname, - const short flag, + const int flag, ReportList *reports, const uint64_t id_types_mask) { diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 7d217d6907d..dc3c2a8e55e 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -213,8 +213,9 @@ static void brush_foreach_id(ID *id, LibraryForeachIDData *data) if (brush->gpencil_settings) { BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, brush->gpencil_settings->material, IDWALK_CB_USER); } - BKE_texture_mtex_foreach_id(data, &brush->mtex); - BKE_texture_mtex_foreach_id(data, &brush->mask_mtex); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, BKE_texture_mtex_foreach_id(data, &brush->mtex)); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, + BKE_texture_mtex_foreach_id(data, &brush->mask_mtex)); } static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_address) diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 2dca5dcb75d..22b939d3cf9 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -716,7 +716,7 @@ Collection *BKE_collection_duplicate(Main *bmain, collection_new->id.tag &= ~LIB_TAG_NEW; /* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */ - BKE_libblock_relink_to_newid(&collection_new->id); + BKE_libblock_relink_to_newid(bmain, &collection_new->id, 0); #ifndef NDEBUG /* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags. */ diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index 1ef205c6903..03525e32a52 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -32,8 +32,6 @@ using blender::fn::GMutableSpan; using blender::fn::GSpan; -using blender::fn::GVArray_Typed; -using blender::fn::GVArrayPtr; namespace blender::bke { @@ -76,7 +74,7 @@ static void vert_extrude_to_mesh_data(const Spline &spline, Span<float3> positions = spline.evaluated_positions(); Span<float3> tangents = spline.evaluated_tangents(); Span<float3> normals = spline.evaluated_normals(); - GVArray_Typed<float> radii = spline.interpolate_to_evaluated(spline.radii()); + VArray<float> radii = spline.interpolate_to_evaluated(spline.radii()); for (const int i : IndexRange(eval_size)) { float4x4 point_matrix = float4x4::from_normalized_axis_data( positions[i], normals[i], tangents[i]); @@ -227,7 +225,7 @@ static void spline_extrude_to_mesh_data(const ResultInfo &info, Span<float3> normals = spline.evaluated_normals(); Span<float3> profile_positions = profile.evaluated_positions(); - GVArray_Typed<float> radii = spline.interpolate_to_evaluated(spline.radii()); + VArray<float> radii = spline.interpolate_to_evaluated(spline.radii()); for (const int i_ring : IndexRange(info.spline_vert_len)) { float4x4 point_matrix = float4x4::from_normalized_axis_data( positions[i_ring], normals[i_ring], tangents[i_ring]); @@ -495,8 +493,8 @@ static void copy_curve_point_attribute_to_mesh(const GSpan src, const ResultInfo &info, ResultAttributeData &dst) { - GVArrayPtr interpolated_gvarray = info.spline.interpolate_to_evaluated(src); - GSpan interpolated = interpolated_gvarray->get_internal_span(); + GVArray interpolated_gvarray = info.spline.interpolate_to_evaluated(src); + GSpan interpolated = interpolated_gvarray.get_internal_span(); attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); @@ -561,8 +559,8 @@ static void copy_profile_point_attribute_to_mesh(const GSpan src, const ResultInfo &info, ResultAttributeData &dst) { - GVArrayPtr interpolated_gvarray = info.profile.interpolate_to_evaluated(src); - GSpan interpolated = interpolated_gvarray->get_internal_span(); + GVArray interpolated_gvarray = info.profile.interpolate_to_evaluated(src); + GSpan interpolated = interpolated_gvarray.get_internal_span(); attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 1564eb3aa7b..bbf61c51bfb 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -205,12 +205,16 @@ void BKE_fcurve_foreach_id(FCurve *fcu, LibraryForeachIDData *data) FMod_Python *fcm_py = (FMod_Python *)fcm->data; BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, fcm_py->script, IDWALK_CB_NOP); - IDP_foreach_property(fcm_py->prop, - IDP_TYPE_FILTER_ID, - BKE_lib_query_idpropertiesForeachIDLink_callback, - data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, + IDP_foreach_property(fcm_py->prop, + IDP_TYPE_FILTER_ID, + BKE_lib_query_idpropertiesForeachIDLink_callback, + data)); break; } + default: + break; } } } diff --git a/source/blender/blenkernel/intern/fcurve_driver.c b/source/blender/blenkernel/intern/fcurve_driver.c index d1bf523acef..3ac64dbf84b 100644 --- a/source/blender/blenkernel/intern/fcurve_driver.c +++ b/source/blender/blenkernel/intern/fcurve_driver.c @@ -326,7 +326,7 @@ static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar) float(*mat[2])[4]; - /* NOTE: for now, these are all just worldspace */ + /* NOTE: for now, these are all just world-space. */ for (int i = 0; i < 2; i++) { /* Get pointer to loc values to store in. */ DriverTarget *dtar = &dvar->targets[i]; @@ -422,7 +422,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) } } else { - /* Convert to worldspace. */ + /* Convert to world-space. */ copy_v3_v3(tmp_loc, pchan->pose_head); mul_m4_v3(ob->obmat, tmp_loc); } diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc index d3c3fcc1e67..0b80ff5acdf 100644 --- a/source/blender/blenkernel/intern/geometry_component_curve.cc +++ b/source/blender/blenkernel/intern/geometry_component_curve.cc @@ -28,10 +28,8 @@ using blender::fn::GMutableSpan; using blender::fn::GSpan; -using blender::fn::GVArray_For_GSpan; +using blender::fn::GVArray; using blender::fn::GVArray_GSpan; -using blender::fn::GVArrayPtr; -using blender::fn::GVMutableArray_For_GMutableSpan; /* -------------------------------------------------------------------- */ /** \name Geometry Component Implementation @@ -253,15 +251,15 @@ void adapt_curve_domain_point_to_spline_impl(const CurveEval &curve, } } -static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArrayPtr varray) +static GVArray adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArray varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(curve.splines().size()); - adapt_curve_domain_point_to_spline_impl<T>(curve, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_curve_domain_point_to_spline_impl<T>(curve, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -272,29 +270,29 @@ static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVA * attributes. The goal is to avoid copying the spline value for every one of its control points * unless it is necessary (in that case the materialize functions will be called). */ -template<typename T> class VArray_For_SplineToPoint final : public VArray<T> { - GVArrayPtr original_varray_; +template<typename T> class VArray_For_SplineToPoint final : public VArrayImpl<T> { + GVArray original_varray_; /* Store existing data materialized if it was not already a span. This is expected * to be worth it because a single spline's value will likely be accessed many times. */ - fn::GVArray_Span<T> original_data_; + VArray_Span<T> original_data_; Array<int> offsets_; public: - VArray_For_SplineToPoint(GVArrayPtr original_varray, Array<int> offsets) - : VArray<T>(offsets.last()), + VArray_For_SplineToPoint(GVArray original_varray, Array<int> offsets) + : VArrayImpl<T>(offsets.last()), original_varray_(std::move(original_varray)), - original_data_(*original_varray_), + original_data_(original_varray_.typed<T>()), offsets_(std::move(offsets)) { } - T get_impl(const int64_t index) const final + T get(const int64_t index) const final { const PointIndices indices = lookup_point_indices(offsets_, index); return original_data_[indices.spline_index]; } - void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final + void materialize(const IndexMask mask, MutableSpan<T> r_span) const final { const int total_size = offsets_.last(); if (mask.is_range() && mask.as_range() == IndexRange(total_size)) { @@ -315,7 +313,7 @@ template<typename T> class VArray_For_SplineToPoint final : public VArray<T> { } } - void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final + void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final { T *dst = r_span.data(); const int total_size = offsets_.last(); @@ -338,29 +336,29 @@ template<typename T> class VArray_For_SplineToPoint final : public VArray<T> { } }; -static GVArrayPtr adapt_curve_domain_spline_to_point(const CurveEval &curve, GVArrayPtr varray) +static GVArray adapt_curve_domain_spline_to_point(const CurveEval &curve, GVArray varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); Array<int> offsets = curve.control_point_offsets(); - new_varray = std::make_unique<fn::GVArray_For_EmbeddedVArray<T, VArray_For_SplineToPoint<T>>>( - offsets.last(), std::move(varray), std::move(offsets)); + new_varray = VArray<T>::template For<VArray_For_SplineToPoint<T>>(std::move(varray), + std::move(offsets)); }); return new_varray; } } // namespace blender::bke -GVArrayPtr CurveComponent::attribute_try_adapt_domain(GVArrayPtr varray, - const AttributeDomain from_domain, - const AttributeDomain to_domain) const +GVArray CurveComponent::attribute_try_adapt_domain_impl(const GVArray &varray, + const AttributeDomain from_domain, + const AttributeDomain to_domain) const { if (!varray) { return {}; } - if (varray->size() == 0) { + if (varray.is_empty()) { return {}; } if (from_domain == to_domain) { @@ -402,8 +400,8 @@ static const CurveEval *get_curve_from_component_for_read(const GeometryComponen namespace blender::bke { class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider { - using AsReadAttribute = GVArrayPtr (*)(const CurveEval &data); - using AsWriteAttribute = GVMutableArrayPtr (*)(CurveEval &data); + using AsReadAttribute = GVArray (*)(const CurveEval &data); + using AsWriteAttribute = GVMutableArray (*)(CurveEval &data); const AsReadAttribute as_read_attribute_; const AsWriteAttribute as_write_attribute_; @@ -424,7 +422,7 @@ class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider { { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const final + GVArray try_get_for_read(const GeometryComponent &component) const final { const CurveEval *curve = get_curve_from_component_for_read(component); if (curve == nullptr) { @@ -483,19 +481,15 @@ static void set_spline_resolution(SplinePtr &spline, const int resolution) } } -static GVArrayPtr make_resolution_read_attribute(const CurveEval &curve) +static GVArray make_resolution_read_attribute(const CurveEval &curve) { - return std::make_unique<fn::GVArray_For_DerivedSpan<SplinePtr, int, get_spline_resolution>>( - curve.splines()); + return VArray<int>::ForDerivedSpan<SplinePtr, get_spline_resolution>(curve.splines()); } -static GVMutableArrayPtr make_resolution_write_attribute(CurveEval &curve) +static GVMutableArray make_resolution_write_attribute(CurveEval &curve) { - return std::make_unique<fn::GVMutableArray_For_DerivedSpan<SplinePtr, - int, - get_spline_resolution, - set_spline_resolution>>( - curve.splines()); + return VMutableArray<int>:: + ForDerivedSpan<SplinePtr, get_spline_resolution, set_spline_resolution>(curve.splines()); } static bool get_cyclic_value(const SplinePtr &spline) @@ -511,16 +505,14 @@ static void set_cyclic_value(SplinePtr &spline, const bool value) } } -static GVArrayPtr make_cyclic_read_attribute(const CurveEval &curve) +static GVArray make_cyclic_read_attribute(const CurveEval &curve) { - return std::make_unique<fn::GVArray_For_DerivedSpan<SplinePtr, bool, get_cyclic_value>>( - curve.splines()); + return VArray<bool>::ForDerivedSpan<SplinePtr, get_cyclic_value>(curve.splines()); } -static GVMutableArrayPtr make_cyclic_write_attribute(CurveEval &curve) +static GVMutableArray make_cyclic_write_attribute(CurveEval &curve) { - return std::make_unique< - fn::GVMutableArray_For_DerivedSpan<SplinePtr, bool, get_cyclic_value, set_cyclic_value>>( + return VMutableArray<bool>::ForDerivedSpan<SplinePtr, get_cyclic_value, set_cyclic_value>( curve.splines()); } @@ -623,9 +615,9 @@ static void point_attribute_materialize_to_uninitialized(Span<Span<T>> data, } } -static GVArrayPtr varray_from_initializer(const AttributeInit &initializer, - const CustomDataType data_type, - const Span<SplinePtr> splines) +static GVArray varray_from_initializer(const AttributeInit &initializer, + const CustomDataType data_type, + const Span<SplinePtr> splines) { switch (initializer.type) { case AttributeInit::Type::Default: @@ -634,16 +626,15 @@ static GVArrayPtr varray_from_initializer(const AttributeInit &initializer, BLI_assert_unreachable(); return {}; case AttributeInit::Type::VArray: - return static_cast<const AttributeInitVArray &>(initializer).varray->shallow_copy(); + return static_cast<const AttributeInitVArray &>(initializer).varray; case AttributeInit::Type::MoveArray: int total_size = 0; for (const SplinePtr &spline : splines) { total_size += spline->size(); } - return std::make_unique<fn::GVArray_For_GSpan>( - GSpan(*bke::custom_data_type_to_cpp_type(data_type), - static_cast<const AttributeInitMove &>(initializer).data, - total_size)); + return GVArray::ForSpan(GSpan(*bke::custom_data_type_to_cpp_type(data_type), + static_cast<const AttributeInitMove &>(initializer).data, + total_size)); } BLI_assert_unreachable(); return {}; @@ -691,11 +682,11 @@ static bool create_point_attribute(GeometryComponent &component, /* We just created the attribute, it should exist. */ BLI_assert(write_attribute); - GVArrayPtr source_varray = varray_from_initializer(initializer, data_type, splines); + GVArray source_varray = varray_from_initializer(initializer, data_type, splines); /* TODO: When we can call a variant of #set_all with a virtual array argument, * this theoretically unnecessary materialize step could be removed. */ - GVArray_GSpan source_varray_span{*source_varray}; - write_attribute.varray->set_all(source_varray_span.data()); + GVArray_GSpan source_varray_span{source_varray}; + write_attribute.varray.set_all(source_varray_span.data()); if (initializer.type == AttributeInit::Type::MoveArray) { MEM_freeN(static_cast<const AttributeInitMove &>(initializer).data); @@ -723,29 +714,29 @@ static bool remove_point_attribute(GeometryComponent &component, /** * Virtual array for any control point data accessed with spans and an offset array. */ -template<typename T> class VArray_For_SplinePoints : public VArray<T> { +template<typename T> class VArray_For_SplinePoints : public VArrayImpl<T> { private: const Array<Span<T>> data_; Array<int> offsets_; public: VArray_For_SplinePoints(Array<Span<T>> data, Array<int> offsets) - : VArray<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets)) + : VArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets)) { } - T get_impl(const int64_t index) const final + T get(const int64_t index) const final { const PointIndices indices = lookup_point_indices(offsets_, index); return data_[indices.spline_index][indices.point_index]; } - void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final + void materialize(const IndexMask mask, MutableSpan<T> r_span) const final { point_attribute_materialize(data_.as_span(), offsets_, mask, r_span); } - void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final + void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final { point_attribute_materialize_to_uninitialized(data_.as_span(), offsets_, mask, r_span); } @@ -754,30 +745,30 @@ template<typename T> class VArray_For_SplinePoints : public VArray<T> { /** * Mutable virtual array for any control point data accessed with spans and an offset array. */ -template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArray<T> { +template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArrayImpl<T> { private: Array<MutableSpan<T>> data_; Array<int> offsets_; public: VMutableArray_For_SplinePoints(Array<MutableSpan<T>> data, Array<int> offsets) - : VMutableArray<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets)) + : VMutableArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets)) { } - T get_impl(const int64_t index) const final + T get(const int64_t index) const final { const PointIndices indices = lookup_point_indices(offsets_, index); return data_[indices.spline_index][indices.point_index]; } - void set_impl(const int64_t index, T value) final + void set(const int64_t index, T value) final { const PointIndices indices = lookup_point_indices(offsets_, index); data_[indices.spline_index][indices.point_index] = value; } - void set_all_impl(Span<T> src) final + void set_all(Span<T> src) final { for (const int spline_index : data_.index_range()) { const int offset = offsets_[spline_index]; @@ -786,30 +777,28 @@ template<typename T> class VMutableArray_For_SplinePoints final : public VMutabl } } - void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final + void materialize(const IndexMask mask, MutableSpan<T> r_span) const final { point_attribute_materialize({(Span<T> *)data_.data(), data_.size()}, offsets_, mask, r_span); } - void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final + void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final { point_attribute_materialize_to_uninitialized( {(Span<T> *)data_.data(), data_.size()}, offsets_, mask, r_span); } }; -template<typename T> GVArrayPtr point_data_gvarray(Array<Span<T>> spans, Array<int> offsets) +template<typename T> VArray<T> point_data_varray(Array<Span<T>> spans, Array<int> offsets) { - return std::make_unique<fn::GVArray_For_EmbeddedVArray<T, VArray_For_SplinePoints<T>>>( - offsets.last(), std::move(spans), std::move(offsets)); + return VArray<T>::template For<VArray_For_SplinePoints<T>>(std::move(spans), std::move(offsets)); } template<typename T> -GVMutableArrayPtr point_data_gvarray(Array<MutableSpan<T>> spans, Array<int> offsets) +VMutableArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offsets) { - return std::make_unique< - fn::GVMutableArray_For_EmbeddedVMutableArray<T, VMutableArray_For_SplinePoints<T>>>( - offsets.last(), std::move(spans), std::move(offsets)); + return VMutableArray<T>::template For<VMutableArray_For_SplinePoints<T>>(std::move(spans), + std::move(offsets)); } /** @@ -820,24 +809,24 @@ GVMutableArrayPtr point_data_gvarray(Array<MutableSpan<T>> spans, Array<int> off * \note There is no need to check the handle type to avoid changing auto handles, since * retrieving write access to the position data will mark them for recomputation anyway. */ -class VMutableArray_For_SplinePosition final : public VMutableArray<float3> { +class VMutableArray_For_SplinePosition final : public VMutableArrayImpl<float3> { private: MutableSpan<SplinePtr> splines_; Array<int> offsets_; public: VMutableArray_For_SplinePosition(MutableSpan<SplinePtr> splines, Array<int> offsets) - : VMutableArray<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets)) + : VMutableArrayImpl<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets)) { } - float3 get_impl(const int64_t index) const final + float3 get(const int64_t index) const final { const PointIndices indices = lookup_point_indices(offsets_, index); return splines_[indices.spline_index]->positions()[indices.point_index]; } - void set_impl(const int64_t index, float3 value) final + void set(const int64_t index, float3 value) final { const PointIndices indices = lookup_point_indices(offsets_, index); Spline &spline = *splines_[indices.spline_index]; @@ -852,7 +841,7 @@ class VMutableArray_For_SplinePosition final : public VMutableArray<float3> { } } - void set_all_impl(Span<float3> src) final + void set_all(Span<float3> src) final { for (const int spline_index : splines_.index_range()) { Spline &spline = *splines_[spline_index]; @@ -885,21 +874,20 @@ class VMutableArray_For_SplinePosition final : public VMutableArray<float3> { return spans; } - void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final + void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final { Array<Span<float3>> spans = this->get_position_spans(); point_attribute_materialize(spans.as_span(), offsets_, mask, r_span); } - void materialize_to_uninitialized_impl(const IndexMask mask, - MutableSpan<float3> r_span) const final + void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final { Array<Span<float3>> spans = this->get_position_spans(); point_attribute_materialize_to_uninitialized(spans.as_span(), offsets_, mask, r_span); } }; -class VArray_For_BezierHandle final : public VArray<float3> { +class VArray_For_BezierHandle final : public VArrayImpl<float3> { private: Span<SplinePtr> splines_; Array<int> offsets_; @@ -907,7 +895,7 @@ class VArray_For_BezierHandle final : public VArray<float3> { public: VArray_For_BezierHandle(Span<SplinePtr> splines, Array<int> offsets, const bool is_right) - : VArray<float3>(offsets.last()), + : VArrayImpl<float3>(offsets.last()), splines_(std::move(splines)), offsets_(std::move(offsets)), is_right_(is_right) @@ -929,7 +917,7 @@ class VArray_For_BezierHandle final : public VArray<float3> { return float3(0); } - float3 get_impl(const int64_t index) const final + float3 get(const int64_t index) const final { return get_internal(index, splines_, offsets_, is_right_); } @@ -976,19 +964,18 @@ class VArray_For_BezierHandle final : public VArray<float3> { point_attribute_materialize_to_uninitialized(spans.as_span(), offsets, mask, r_span); } - void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final + void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final { materialize_internal(mask, splines_, offsets_, is_right_, r_span); } - void materialize_to_uninitialized_impl(const IndexMask mask, - MutableSpan<float3> r_span) const final + void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final { materialize_to_uninitialized_internal(mask, splines_, offsets_, is_right_, r_span); } }; -class VMutableArray_For_BezierHandles final : public VMutableArray<float3> { +class VMutableArray_For_BezierHandles final : public VMutableArrayImpl<float3> { private: MutableSpan<SplinePtr> splines_; Array<int> offsets_; @@ -998,19 +985,19 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> { VMutableArray_For_BezierHandles(MutableSpan<SplinePtr> splines, Array<int> offsets, const bool is_right) - : VMutableArray<float3>(offsets.last()), + : VMutableArrayImpl<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets)), is_right_(is_right) { } - float3 get_impl(const int64_t index) const final + float3 get(const int64_t index) const final { return VArray_For_BezierHandle::get_internal(index, splines_, offsets_, is_right_); } - void set_impl(const int64_t index, float3 value) final + void set(const int64_t index, float3 value) final { const PointIndices indices = lookup_point_indices(offsets_, index); Spline &spline = *splines_[indices.spline_index]; @@ -1026,7 +1013,7 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> { } } - void set_all_impl(Span<float3> src) final + void set_all(Span<float3> src) final { for (const int spline_index : splines_.index_range()) { Spline &spline = *splines_[spline_index]; @@ -1049,13 +1036,12 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> { } } - void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final + void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final { VArray_For_BezierHandle::materialize_internal(mask, splines_, offsets_, is_right_, r_span); } - void materialize_to_uninitialized_impl(const IndexMask mask, - MutableSpan<float3> r_span) const final + void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final { VArray_For_BezierHandle::materialize_to_uninitialized_internal( mask, splines_, offsets_, is_right_, r_span); @@ -1097,7 +1083,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const override + GVArray try_get_for_read(const GeometryComponent &component) const override { const CurveEval *curve = get_curve_from_component_for_read(component); if (curve == nullptr) { @@ -1110,7 +1096,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu Span<SplinePtr> splines = curve->splines(); if (splines.size() == 1) { - return std::make_unique<fn::GVArray_For_GSpan>(get_span_(*splines.first())); + return GVArray::ForSpan(get_span_(*splines.first())); } Array<int> offsets = curve->control_point_offsets(); @@ -1119,7 +1105,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu spans[i] = get_span_(*splines[i]); } - return point_data_gvarray(spans, offsets); + return point_data_varray(spans, offsets); } WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override @@ -1144,8 +1130,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu MutableSpan<SplinePtr> splines = curve->splines(); if (splines.size() == 1) { - return {std::make_unique<fn::GVMutableArray_For_GMutableSpan>( - get_mutable_span_(*splines.first())), + return {GVMutableArray::ForSpan(get_mutable_span_(*splines.first())), domain_, std::move(tag_modified_fn)}; } @@ -1156,7 +1141,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu spans[i] = get_mutable_span_(*splines[i]); } - return {point_data_gvarray(spans, offsets), domain_, tag_modified_fn}; + return {point_data_varray(spans, offsets), domain_, tag_modified_fn}; } bool try_delete(GeometryComponent &component) const final @@ -1248,10 +1233,8 @@ class PositionAttributeProvider final : public BuiltinPointAttributeProvider<flo }; Array<int> offsets = curve->control_point_offsets(); - return {std::make_unique< - fn::GVMutableArray_For_EmbeddedVMutableArray<float3, - VMutableArray_For_SplinePosition>>( - offsets.last(), curve->splines(), std::move(offsets)), + return {VMutableArray<float3>::For<VMutableArray_For_SplinePosition>(curve->splines(), + std::move(offsets)), domain_, tag_modified_fn}; } @@ -1273,7 +1256,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const override + GVArray try_get_for_read(const GeometryComponent &component) const override { const CurveEval *curve = get_curve_from_component_for_read(component); if (curve == nullptr) { @@ -1285,8 +1268,8 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { } Array<int> offsets = curve->control_point_offsets(); - return std::make_unique<fn::GVArray_For_EmbeddedVArray<float3, VArray_For_BezierHandle>>( - offsets.last(), curve->splines(), std::move(offsets), is_right_); + return VArray<float3>::For<VArray_For_BezierHandle>( + curve->splines(), std::move(offsets), is_right_); } WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override @@ -1303,12 +1286,10 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { auto tag_modified_fn = [curve]() { curve->mark_cache_invalid(); }; Array<int> offsets = curve->control_point_offsets(); - return { - std::make_unique< - fn::GVMutableArray_For_EmbeddedVMutableArray<float3, VMutableArray_For_BezierHandles>>( - offsets.last(), curve->splines(), std::move(offsets), is_right_), - domain_, - tag_modified_fn}; + return {VMutableArray<float3>::For<VMutableArray_For_BezierHandles>( + curve->splines(), std::move(offsets), is_right_), + domain_, + tag_modified_fn}; } bool try_delete(GeometryComponent &UNUSED(component)) const final @@ -1387,7 +1368,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { /* First check for the simpler situation when we can return a simpler span virtual array. */ if (spans.size() == 1) { - return {std::make_unique<GVArray_For_GSpan>(spans.first()), ATTR_DOMAIN_POINT}; + return {GVArray::ForSpan(spans.first()), ATTR_DOMAIN_POINT}; } ReadAttributeLookup attribute = {}; @@ -1399,7 +1380,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { data[i] = spans[i].typed<T>(); BLI_assert(data[i].data() != nullptr); } - attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT}; + attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT}; }); return attribute; } @@ -1440,7 +1421,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { /* First check for the simpler situation when we can return a simpler span virtual array. */ if (spans.size() == 1) { - return {std::make_unique<GVMutableArray_For_GMutableSpan>(spans.first()), ATTR_DOMAIN_POINT}; + return {GVMutableArray::ForSpan(spans.first()), ATTR_DOMAIN_POINT}; } WriteAttributeLookup attribute = {}; @@ -1452,7 +1433,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { data[i] = spans[i].typed<T>(); BLI_assert(data[i].data() != nullptr); } - attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT}; + attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT}; }); return attribute; } diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc index 5fe77000519..047bceda4fe 100644 --- a/source/blender/blenkernel/intern/geometry_component_instances.cc +++ b/source/blender/blenkernel/intern/geometry_component_instances.cc @@ -389,25 +389,22 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const final + GVArray try_get_for_read(const GeometryComponent &component) const final { const InstancesComponent &instances_component = static_cast<const InstancesComponent &>( component); Span<float4x4> transforms = instances_component.instance_transforms(); - return std::make_unique<fn::GVArray_For_DerivedSpan<float4x4, float3, get_transform_position>>( - transforms); + return VArray<float3>::ForDerivedSpan<float4x4, get_transform_position>(transforms); } WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final { InstancesComponent &instances_component = static_cast<InstancesComponent &>(component); MutableSpan<float4x4> transforms = instances_component.instance_transforms(); - return { - std::make_unique<fn::GVMutableArray_For_DerivedSpan<float4x4, - float3, - get_transform_position, - set_transform_position>>(transforms), - domain_}; + return {VMutableArray<float3>::ForDerivedSpan<float4x4, + get_transform_position, + set_transform_position>(transforms), + domain_}; } bool try_delete(GeometryComponent &UNUSED(component)) const final @@ -435,13 +432,13 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider { { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const final + GVArray try_get_for_read(const GeometryComponent &component) const final { const InstancesComponent &instances = static_cast<const InstancesComponent &>(component); if (instances.instance_ids().is_empty()) { return {}; } - return std::make_unique<fn::GVArray_For_Span<int>>(instances.instance_ids()); + return VArray<int>::ForSpan(instances.instance_ids()); } WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final @@ -450,8 +447,7 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider { if (instances.instance_ids().is_empty()) { return {}; } - return {std::make_unique<fn::GVMutableArray_For_MutableSpan<int>>(instances.instance_ids()), - domain_}; + return {VMutableArray<int>::ForSpan(instances.instance_ids()), domain_}; } bool try_delete(GeometryComponent &component) const final @@ -477,8 +473,8 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider { break; } case AttributeInit::Type::VArray: { - const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray; - varray->materialize_to_uninitialized(IndexRange(varray->size()), ids.data()); + const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray; + varray.materialize_to_uninitialized(varray.index_range(), ids.data()); break; } case AttributeInit::Type::MoveArray: { diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index c3e39c0b2cb..86a52b420b6 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -32,8 +32,6 @@ /* 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); -using blender::fn::GVArray; - /* -------------------------------------------------------------------- */ /** \name Geometry Component Implementation * \{ */ @@ -203,17 +201,17 @@ void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_corner_to_point(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_corner_to_point(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { /* We compute all interpolated values at once, because for this interpolation, one has to * iterate over all loops anyway. */ Array<T> values(mesh.totvert); - adapt_mesh_domain_corner_to_point_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_corner_to_point_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -239,14 +237,14 @@ static void adapt_mesh_domain_point_to_corner_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_point_to_corner(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_point_to_corner(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); Array<T> values(mesh.totloop); - adapt_mesh_domain_point_to_corner_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_point_to_corner_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); }); return new_varray; } @@ -295,15 +293,15 @@ void adapt_mesh_domain_corner_to_face_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_corner_to_face(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_corner_to_face(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totpoly); - adapt_mesh_domain_corner_to_face_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_corner_to_face_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -368,15 +366,15 @@ void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_corner_to_edge(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_corner_to_edge(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totedge); - adapt_mesh_domain_corner_to_edge_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_corner_to_edge_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -424,15 +422,15 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_face_to_point(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_face_to_point(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totvert); - adapt_mesh_domain_face_to_point_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_face_to_point_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -453,15 +451,15 @@ void adapt_mesh_domain_face_to_corner_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_face_to_corner(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_face_to_corner(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totloop); - adapt_mesh_domain_face_to_corner_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_face_to_corner_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -507,15 +505,15 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_face_to_edge(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totedge); - adapt_mesh_domain_face_to_edge_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_face_to_edge_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -567,15 +565,15 @@ void adapt_mesh_domain_point_to_face_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_point_to_face(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totpoly); - adapt_mesh_domain_point_to_face_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_point_to_face_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -617,15 +615,15 @@ void adapt_mesh_domain_point_to_edge_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_point_to_edge(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_point_to_edge(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totedge); - adapt_mesh_domain_point_to_edge_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_point_to_edge_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -678,15 +676,15 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_edge_to_corner(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_edge_to_corner(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totloop); - adapt_mesh_domain_edge_to_corner_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_edge_to_corner_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -728,15 +726,15 @@ void adapt_mesh_domain_edge_to_point_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_edge_to_point(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totvert); - adapt_mesh_domain_edge_to_point_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_edge_to_point_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -788,15 +786,15 @@ void adapt_mesh_domain_edge_to_face_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_edge_to_face(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totpoly); - adapt_mesh_domain_edge_to_face_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_edge_to_face_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -804,15 +802,15 @@ static GVArrayPtr adapt_mesh_domain_edge_to_face(const Mesh &mesh, GVArrayPtr va } // namespace blender::bke -blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain( - blender::fn::GVArrayPtr varray, +blender::fn::GVArray MeshComponent::attribute_try_adapt_domain_impl( + const blender::fn::GVArray &varray, const AttributeDomain from_domain, const AttributeDomain to_domain) const { if (!varray) { return {}; } - if (varray->size() == 0) { + if (varray.size() == 0) { return {}; } if (from_domain == to_domain) { @@ -823,11 +821,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain( case ATTR_DOMAIN_CORNER: { switch (to_domain) { case ATTR_DOMAIN_POINT: - return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, varray); case ATTR_DOMAIN_FACE: - return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, varray); case ATTR_DOMAIN_EDGE: - return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, varray); default: break; } @@ -836,11 +834,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain( case ATTR_DOMAIN_POINT: { switch (to_domain) { case ATTR_DOMAIN_CORNER: - return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, varray); case ATTR_DOMAIN_FACE: - return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, varray); case ATTR_DOMAIN_EDGE: - return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, varray); default: break; } @@ -849,11 +847,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain( case ATTR_DOMAIN_FACE: { switch (to_domain) { case ATTR_DOMAIN_POINT: - return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, varray); case ATTR_DOMAIN_CORNER: - return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, varray); case ATTR_DOMAIN_EDGE: - return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, varray); default: break; } @@ -862,11 +860,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain( case ATTR_DOMAIN_EDGE: { switch (to_domain) { case ATTR_DOMAIN_CORNER: - return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, varray); case ATTR_DOMAIN_POINT: - return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, varray); case ATTR_DOMAIN_FACE: - return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, varray); default: break; } @@ -896,9 +894,9 @@ static const Mesh *get_mesh_from_component_for_read(const GeometryComponent &com namespace blender::bke { template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)> -static GVArrayPtr make_derived_read_attribute(const void *data, const int domain_size) +static GVArray make_derived_read_attribute(const void *data, const int domain_size) { - return std::make_unique<fn::GVArray_For_DerivedSpan<StructT, ElemT, GetFunc>>( + return VArray<ElemT>::template ForDerivedSpan<StructT, GetFunc>( Span<StructT>((const StructT *)data, domain_size)); } @@ -906,23 +904,22 @@ template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &), void (*SetFunc)(StructT &, ElemT)> -static GVMutableArrayPtr make_derived_write_attribute(void *data, const int domain_size) +static GVMutableArray make_derived_write_attribute(void *data, const int domain_size) { - return std::make_unique<fn::GVMutableArray_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc>>( + return VMutableArray<ElemT>::template ForDerivedSpan<StructT, GetFunc, SetFunc>( MutableSpan<StructT>((StructT *)data, domain_size)); } template<typename T> -static GVArrayPtr make_array_read_attribute(const void *data, const int domain_size) +static GVArray make_array_read_attribute(const void *data, const int domain_size) { - return std::make_unique<fn::GVArray_For_Span<T>>(Span<T>((const T *)data, domain_size)); + return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size)); } template<typename T> -static GVMutableArrayPtr make_array_write_attribute(void *data, const int domain_size) +static GVMutableArray make_array_write_attribute(void *data, const int domain_size) { - return std::make_unique<fn::GVMutableArray_For_MutableSpan<T>>( - MutableSpan<T>((T *)data, domain_size)); + return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size)); } static float3 get_vertex_position(const MVert &vert) @@ -999,23 +996,23 @@ static void set_crease(MEdge &edge, float value) edge.crease = round_fl_to_uchar_clamp(value * 255.0f); } -class VMutableArray_For_VertexWeights final : public VMutableArray<float> { +class VMutableArray_For_VertexWeights final : public VMutableArrayImpl<float> { private: MDeformVert *dverts_; const int dvert_index_; public: VMutableArray_For_VertexWeights(MDeformVert *dverts, const int totvert, const int dvert_index) - : VMutableArray<float>(totvert), dverts_(dverts), dvert_index_(dvert_index) + : VMutableArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index) { } - float get_impl(const int64_t index) const override + float get(const int64_t index) const override { return get_internal(dverts_, dvert_index_, index); } - void set_impl(const int64_t index, const float value) override + void set(const int64_t index, const float value) override { MDeformWeight *weight = BKE_defvert_ensure_index(&dverts_[index], dvert_index_); weight->weight = value; @@ -1036,18 +1033,18 @@ class VMutableArray_For_VertexWeights final : public VMutableArray<float> { } }; -class VArray_For_VertexWeights final : public VArray<float> { +class VArray_For_VertexWeights final : public VArrayImpl<float> { private: const MDeformVert *dverts_; const int dvert_index_; public: VArray_For_VertexWeights(const MDeformVert *dverts, const int totvert, const int dvert_index) - : VArray<float>(totvert), dverts_(dverts), dvert_index_(dvert_index) + : VArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index) { } - float get_impl(const int64_t index) const override + float get(const int64_t index) const override { return VMutableArray_For_VertexWeights::get_internal(dverts_, dvert_index_, index); } @@ -1078,12 +1075,10 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider { } if (mesh->dvert == nullptr) { static const float default_value = 0.0f; - return {std::make_unique<fn::GVArray_For_SingleValueRef>( - CPPType::get<float>(), mesh->totvert, &default_value), - ATTR_DOMAIN_POINT}; + return {VArray<float>::ForSingle(default_value, mesh->totvert), ATTR_DOMAIN_POINT}; } - return {std::make_unique<fn::GVArray_For_EmbeddedVArray<float, VArray_For_VertexWeights>>( - mesh->totvert, mesh->dvert, mesh->totvert, vertex_group_index), + return {VArray<float>::For<VArray_For_VertexWeights>( + mesh->dvert, mesh->totvert, vertex_group_index), ATTR_DOMAIN_POINT}; } @@ -1114,11 +1109,9 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider { mesh->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer( &mesh->vdata, CD_MDEFORMVERT, mesh->totvert); } - return { - std::make_unique< - fn::GVMutableArray_For_EmbeddedVMutableArray<float, VMutableArray_For_VertexWeights>>( - mesh->totvert, mesh->dvert, mesh->totvert, vertex_group_index), - ATTR_DOMAIN_POINT}; + return {VMutableArray<float>::For<VMutableArray_For_VertexWeights>( + mesh->dvert, mesh->totvert, vertex_group_index), + ATTR_DOMAIN_POINT}; } bool try_delete(GeometryComponent &component, const AttributeIDRef &attribute_id) const final @@ -1184,7 +1177,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider { { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const final + GVArray try_get_for_read(const GeometryComponent &component) const final { const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component); const Mesh *mesh = mesh_component.get_for_read(); @@ -1197,8 +1190,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider { CustomData_has_layer(&mesh->pdata, CD_NORMAL)) { const void *data = CustomData_get_layer(&mesh->pdata, CD_NORMAL); - return std::make_unique<fn::GVArray_For_Span<float3>>( - Span<float3>((const float3 *)data, mesh->totpoly)); + return VArray<float3>::ForSpan(Span<float3>((const float3 *)data, mesh->totpoly)); } Array<float3> normals(mesh->totpoly); @@ -1207,7 +1199,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider { BKE_mesh_calc_poly_normal(poly, &mesh->mloop[poly->loopstart], mesh->mvert, normals[i]); } - return std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals)); + return VArray<float3>::ForContainer(std::move(normals)); } WriteAttributeLookup try_get_for_write(GeometryComponent &UNUSED(component)) const final diff --git a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc index dfb65a9078d..c6a1c61a96d 100644 --- a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc +++ b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc @@ -141,16 +141,15 @@ int PointCloudComponent::attribute_domain_size(const AttributeDomain domain) con namespace blender::bke { template<typename T> -static GVArrayPtr make_array_read_attribute(const void *data, const int domain_size) +static GVArray make_array_read_attribute(const void *data, const int domain_size) { - return std::make_unique<fn::GVArray_For_Span<T>>(Span<T>((const T *)data, domain_size)); + return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size)); } template<typename T> -static GVMutableArrayPtr make_array_write_attribute(void *data, const int domain_size) +static GVMutableArray make_array_write_attribute(void *data, const int domain_size) { - return std::make_unique<fn::GVMutableArray_For_MutableSpan<T>>( - MutableSpan<T>((T *)data, domain_size)); + return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size)); } /** diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc index cd1bafe445a..c250c14f1d7 100644 --- a/source/blender/blenkernel/intern/geometry_set.cc +++ b/source/blender/blenkernel/intern/geometry_set.cc @@ -610,24 +610,32 @@ bool BKE_object_has_geometry_set_instances(const Object *ob) if (geometry_set == nullptr) { return false; } - if (geometry_set->has_instances()) { - return true; - } - const bool has_mesh = geometry_set->has_mesh(); - const bool has_pointcloud = geometry_set->has_pointcloud(); - const bool has_volume = geometry_set->has_volume(); - const bool has_curve = geometry_set->has_curve(); - if (ob->type == OB_MESH) { - return has_pointcloud || has_volume || has_curve; - } - if (ob->type == OB_POINTCLOUD) { - return has_mesh || has_volume || has_curve; - } - if (ob->type == OB_VOLUME) { - return has_mesh || has_pointcloud || has_curve; - } - if (ELEM(ob->type, OB_CURVE, OB_FONT)) { - return has_mesh || has_pointcloud || has_volume; + for (const GeometryComponent *component : geometry_set->get_components_for_read()) { + if (component->is_empty()) { + continue; + } + const GeometryComponentType type = component->type(); + bool is_instance = false; + switch (type) { + case GEO_COMPONENT_TYPE_MESH: + is_instance = ob->type != OB_MESH; + break; + case GEO_COMPONENT_TYPE_POINT_CLOUD: + is_instance = ob->type != OB_POINTCLOUD; + break; + case GEO_COMPONENT_TYPE_INSTANCES: + is_instance = true; + break; + case GEO_COMPONENT_TYPE_VOLUME: + is_instance = ob->type != OB_VOLUME; + break; + case GEO_COMPONENT_TYPE_CURVE: + is_instance = !ELEM(ob->type, OB_CURVE, OB_FONT); + break; + } + if (is_instance) { + return true; + } } return false; } diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc index 8a7840acd73..c73da7d9659 100644 --- a/source/blender/blenkernel/intern/geometry_set_instances.cc +++ b/source/blender/blenkernel/intern/geometry_set_instances.cc @@ -89,8 +89,7 @@ GeometrySet object_get_evaluated_geometry_set(const Object &object) static void geometry_set_collect_recursive_collection_instance( const Collection &collection, const float4x4 &transform, Vector<GeometryInstanceGroup> &r_sets) { - float4x4 offset_matrix; - unit_m4(offset_matrix.values); + float4x4 offset_matrix = float4x4::identity(); sub_v3_v3(offset_matrix.values[3], collection.instance_offset); const float4x4 instance_transform = transform * offset_matrix; geometry_set_collect_recursive_collection(collection, instance_transform, r_sets); @@ -183,10 +182,7 @@ static void geometry_set_collect_recursive(const GeometrySet &geometry_set, void geometry_set_gather_instances(const GeometrySet &geometry_set, Vector<GeometryInstanceGroup> &r_instance_groups) { - float4x4 unit_transform; - unit_m4(unit_transform.values); - - geometry_set_collect_recursive(geometry_set, unit_transform, r_instance_groups); + geometry_set_collect_recursive(geometry_set, float4x4::identity(), r_instance_groups); } void geometry_set_gather_instances_attribute_info(Span<GeometryInstanceGroup> set_groups, @@ -364,12 +360,12 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups, result.attribute_try_create( entry.key, domain_output, data_type_output, AttributeInitDefault()); WriteAttributeLookup write_attribute = result.attribute_try_get_for_write(attribute_id); - if (!write_attribute || &write_attribute.varray->type() != cpp_type || + if (!write_attribute || &write_attribute.varray.type() != cpp_type || write_attribute.domain != domain_output) { continue; } - fn::GVMutableArray_GSpan dst_span{*write_attribute.varray}; + fn::GVMutableArray_GSpan dst_span{write_attribute.varray}; int offset = 0; for (const GeometryInstanceGroup &set_group : set_groups) { @@ -381,11 +377,11 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups, if (domain_size == 0) { continue; /* Domain size is 0, so no need to increment the offset. */ } - GVArrayPtr source_attribute = component.attribute_try_get_for_read( + GVArray source_attribute = component.attribute_try_get_for_read( attribute_id, domain_output, data_type_output); if (source_attribute) { - fn::GVArray_GSpan src_span{*source_attribute}; + fn::GVArray_GSpan src_span{source_attribute}; const void *src_buffer = src_span.data(); for (const int UNUSED(i) : set_group.transforms.index_range()) { void *dst_buffer = dst_span[offset]; diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc index debdf44b0bb..fffc13c49a8 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.cc +++ b/source/blender/blenkernel/intern/gpencil_geom.cc @@ -3122,8 +3122,9 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, bGPDstroke *gps, bGPDstroke *next_stroke, int tag_flags, - bool select, - int limit) + const bool select, + const bool flat_cap, + const int limit) { tGPDeleteIsland *islands = (tGPDeleteIsland *)MEM_callocN( sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands"); @@ -3171,6 +3172,9 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, for (idx = 0; idx < num_islands; idx++) { tGPDeleteIsland *island = &islands[idx]; new_stroke = BKE_gpencil_stroke_duplicate(gps, false, true); + if (flat_cap) { + new_stroke->caps[1 - (idx % 2)] = GP_STROKE_CAP_FLAT; + } /* if cyclic and first stroke, save to join later */ if ((is_cyclic) && (gps_first == nullptr)) { diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc index f820b345c59..ffc39028400 100644 --- a/source/blender/blenkernel/intern/icons.cc +++ b/source/blender/blenkernel/intern/icons.cc @@ -35,6 +35,7 @@ #include "DNA_gpencil_types.h" #include "DNA_light_types.h" #include "DNA_material_types.h" +#include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -383,6 +384,7 @@ PreviewImage **BKE_previewimg_id_get_p(const ID *id) ID_PRV_CASE(ID_SCE, Scene); ID_PRV_CASE(ID_SCR, bScreen); ID_PRV_CASE(ID_AC, bAction); + ID_PRV_CASE(ID_NT, bNodeTree); #undef ID_PRV_CASE default: break; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 311199f8833..c0efc246567 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -112,12 +112,26 @@ #include "DNA_view3d_types.h" static CLG_LogRef LOG = {"bke.image"}; -static ThreadMutex *image_mutex; static void image_init(Image *ima, short source, short type); static void image_free_packedfiles(Image *ima); static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src); +/* Reset runtime image fields when datablock is being initialized. */ +static void image_runtime_reset(struct Image *image) +{ + memset(&image->runtime, 0, sizeof(image->runtime)); + image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex"); + BLI_mutex_init(image->runtime.cache_mutex); +} + +/* Reset runtime image fields when datablock is being copied. */ +static void image_runtime_reset_on_copy(struct Image *image) +{ + image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex"); + BLI_mutex_init(image->runtime.cache_mutex); +} + static void image_init_data(ID *id) { Image *image = (Image *)id; @@ -167,6 +181,8 @@ static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c else { image_dst->preview = NULL; } + + image_runtime_reset_on_copy(image_dst); } static void image_free_data(ID *id) @@ -194,6 +210,9 @@ static void image_free_data(ID *id) BLI_freelistN(&image->tiles); BLI_freelistN(&image->gpu_refresh_areas); + + BLI_mutex_end(image->runtime.cache_mutex); + MEM_freeN(image->runtime.cache_mutex); } static void image_foreach_cache(ID *id, @@ -325,6 +344,8 @@ static void image_blend_read_data(BlendDataReader *reader, ID *id) ima->lastused = 0; ima->gpuflag = 0; BLI_listbase_clear(&ima->gpu_refresh_areas); + + image_runtime_reset(ima); } static void image_blend_read_lib(BlendLibReader *UNUSED(reader), ID *id) @@ -452,16 +473,6 @@ static struct ImBuf *imagecache_get(Image *image, int index, bool *r_is_cached_e return NULL; } -void BKE_images_init(void) -{ - image_mutex = BLI_mutex_alloc(); -} - -void BKE_images_exit(void) -{ - BLI_mutex_free(image_mutex); -} - /* ***************** ALLOC & FREE, DATA MANAGING *************** */ static void image_free_cached_frames(Image *image) @@ -514,7 +525,7 @@ static void image_free_anims(Image *ima) void BKE_image_free_buffers_ex(Image *ima, bool do_lock) { if (do_lock) { - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(ima->runtime.cache_mutex); } image_free_cached_frames(ima); @@ -528,7 +539,7 @@ void BKE_image_free_buffers_ex(Image *ima, bool do_lock) BKE_image_free_gputextures(ima); if (do_lock) { - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(ima->runtime.cache_mutex); } } @@ -567,6 +578,8 @@ static void image_init(Image *ima, short source, short type) } } + image_runtime_reset(ima); + BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings); ima->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Image Stereo Format"); } @@ -640,7 +653,9 @@ void BKE_image_merge(Main *bmain, Image *dest, Image *source) { /* sanity check */ if (dest && source && dest != source) { - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(source->runtime.cache_mutex); + BLI_mutex_lock(dest->runtime.cache_mutex); + if (source->cache != NULL) { struct MovieCacheIter *iter; iter = IMB_moviecacheIter_new(source->cache); @@ -652,7 +667,9 @@ void BKE_image_merge(Main *bmain, Image *dest, Image *source) } IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(image_mutex); + + BLI_mutex_unlock(dest->runtime.cache_mutex); + BLI_mutex_unlock(source->runtime.cache_mutex); BKE_id_free(bmain, source); } @@ -1243,7 +1260,8 @@ static uintptr_t image_mem_size(Image *image) return 0; } - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(image->runtime.cache_mutex); + if (image->cache != NULL) { struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache); @@ -1277,7 +1295,8 @@ static uintptr_t image_mem_size(Image *image) } IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(image_mutex); + + BLI_mutex_unlock(image->runtime.cache_mutex); return size; } @@ -1361,11 +1380,11 @@ static bool imagecache_check_free_anim(ImBuf *ibuf, void *UNUSED(userkey), void /* except_frame is weak, only works for seqs without offset... */ void BKE_image_free_anim_ibufs(Image *ima, int except_frame) { - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(ima->runtime.cache_mutex); if (ima->cache != NULL) { IMB_moviecache_cleanup(ima->cache, imagecache_check_free_anim, &except_frame); } - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(ima->runtime.cache_mutex); } void BKE_image_all_free_anim_ibufs(Main *bmain, int cfra) @@ -3284,7 +3303,7 @@ void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser * } if (do_reset) { - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(ima->runtime.cache_mutex); image_free_cached_frames(ima); BKE_image_free_views(ima); @@ -3292,7 +3311,7 @@ void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser * /* add new views */ image_viewer_create_views(rd, ima); - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(ima->runtime.cache_mutex); } BLI_thread_unlock(LOCK_DRAW_IMAGE); @@ -3556,7 +3575,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) return; } - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(ima->runtime.cache_mutex); switch (signal) { case IMA_SIGNAL_FREE: @@ -3676,7 +3695,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) break; } - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(ima->runtime.cache_mutex); /* don't use notifiers because they are not 100% sure to succeeded * this also makes sure all scenes are accounted for. */ @@ -5101,11 +5120,11 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) { ImBuf *ibuf; - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(ima->runtime.cache_mutex); ibuf = image_acquire_ibuf(ima, iuser, r_lock); - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(ima->runtime.cache_mutex); return ibuf; } @@ -5124,9 +5143,9 @@ void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock) } if (ibuf) { - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(ima->runtime.cache_mutex); IMB_freeImBuf(ibuf); - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(ima->runtime.cache_mutex); } } @@ -5140,7 +5159,7 @@ bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser) return false; } - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(ima->runtime.cache_mutex); ibuf = image_get_cached_ibuf(ima, iuser, NULL, NULL, NULL); @@ -5148,7 +5167,7 @@ bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser) ibuf = image_acquire_ibuf(ima, iuser, NULL); } - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(ima->runtime.cache_mutex); IMB_freeImBuf(ibuf); @@ -5168,6 +5187,7 @@ typedef struct ImagePoolItem { typedef struct ImagePool { ListBase image_buffers; BLI_mempool *memory_pool; + ThreadMutex mutex; } ImagePool; ImagePool *BKE_image_pool_new(void) @@ -5175,21 +5195,28 @@ ImagePool *BKE_image_pool_new(void) ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool"); pool->memory_pool = BLI_mempool_create(sizeof(ImagePoolItem), 0, 128, BLI_MEMPOOL_NOP); + BLI_mutex_init(&pool->mutex); + return pool; } void BKE_image_pool_free(ImagePool *pool) { /* Use single lock to dereference all the image buffers. */ - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(&pool->mutex); for (ImagePoolItem *item = pool->image_buffers.first; item != NULL; item = item->next) { if (item->ibuf != NULL) { + BLI_mutex_lock(item->image->runtime.cache_mutex); IMB_freeImBuf(item->ibuf); + BLI_mutex_unlock(item->image->runtime.cache_mutex); } } - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(&pool->mutex); BLI_mempool_destroy(pool->memory_pool); + + BLI_mutex_end(&pool->mutex); + MEM_freeN(pool); } @@ -5221,28 +5248,34 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool } if (pool == NULL) { - /* pool could be NULL, in this case use general acquire function */ + /* Pool could be NULL, in this case use general acquire function. */ return BKE_image_acquire_ibuf(ima, iuser, NULL); } image_get_entry_and_index(ima, iuser, &entry, &index); + /* Use double-checked locking, to avoid locking when the requested image buffer is already in the + * pool. */ + ibuf = image_pool_find_item(pool, ima, entry, index, &found); if (found) { return ibuf; } - BLI_mutex_lock(image_mutex); + /* Lock the pool, to allow thread-safe modification of the content of the pool. */ + BLI_mutex_lock(&pool->mutex); ibuf = image_pool_find_item(pool, ima, entry, index, &found); - /* will also create item even in cases image buffer failed to load, - * prevents trying to load the same buggy file multiple times - */ + /* Will also create item even in cases image buffer failed to load, + * prevents trying to load the same buggy file multiple times. */ if (!found) { ImagePoolItem *item; - ibuf = image_acquire_ibuf(ima, iuser, NULL); + /* Thread-safe acquisition of an image buffer from the image. + * The acquisition does not use image pools, so there is no risk of recursive or out-of-order + * mutex locking. */ + ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); item = BLI_mempool_alloc(pool->memory_pool); item->image = ima; @@ -5253,7 +5286,7 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool BLI_addtail(&pool->image_buffers, item); } - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(&pool->mutex); return ibuf; } @@ -5642,7 +5675,7 @@ bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable) bool is_dirty = false; bool is_writable = false; - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(image->runtime.cache_mutex); if (image->cache != NULL) { struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache); @@ -5657,7 +5690,7 @@ bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable) } IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(image->runtime.cache_mutex); if (r_is_writable) { *r_is_writable = is_writable; @@ -5686,7 +5719,7 @@ bool BKE_image_buffer_format_writable(ImBuf *ibuf) void BKE_image_file_format_set(Image *image, int ftype, const ImbFormatOptions *options) { - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(image->runtime.cache_mutex); if (image->cache != NULL) { struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache); @@ -5700,14 +5733,14 @@ void BKE_image_file_format_set(Image *image, int ftype, const ImbFormatOptions * } IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(image->runtime.cache_mutex); } bool BKE_image_has_loaded_ibuf(Image *image) { bool has_loaded_ibuf = false; - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(image->runtime.cache_mutex); if (image->cache != NULL) { struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache); @@ -5717,7 +5750,7 @@ bool BKE_image_has_loaded_ibuf(Image *image) } IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(image->runtime.cache_mutex); return has_loaded_ibuf; } @@ -5730,7 +5763,7 @@ ImBuf *BKE_image_get_ibuf_with_name(Image *image, const char *name) { ImBuf *ibuf = NULL; - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(image->runtime.cache_mutex); if (image->cache != NULL) { struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache); @@ -5745,7 +5778,7 @@ ImBuf *BKE_image_get_ibuf_with_name(Image *image, const char *name) } IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(image->runtime.cache_mutex); return ibuf; } @@ -5763,7 +5796,7 @@ ImBuf *BKE_image_get_first_ibuf(Image *image) { ImBuf *ibuf = NULL; - BLI_mutex_lock(image_mutex); + BLI_mutex_lock(image->runtime.cache_mutex); if (image->cache != NULL) { struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache); @@ -5776,7 +5809,7 @@ ImBuf *BKE_image_get_first_ibuf(Image *image) } IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(image_mutex); + BLI_mutex_unlock(image->runtime.cache_mutex); return ibuf; } diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c index 943909cc90f..bef14b6ad70 100644 --- a/source/blender/blenkernel/intern/image_gen.c +++ b/source/blender/blenkernel/intern/image_gen.c @@ -369,7 +369,7 @@ static void checker_board_text( char text[3] = {'A', '1', '\0'}; const int mono = blf_mono_font_render; - BLF_size(mono, 54, 72); /* hard coded size! */ + BLF_size(mono, 54.0f, 72); /* hard coded size! */ /* OCIO_TODO: using NULL as display will assume using sRGB display * this is correct since currently generated images are assumed to be in sRGB space, diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c index 4165452801c..74750a9b61a 100644 --- a/source/blender/blenkernel/intern/lib_query.c +++ b/source/blender/blenkernel/intern/lib_query.c @@ -76,48 +76,52 @@ typedef struct LibraryForeachIDData { BLI_LINKSTACK_DECLARE(ids_todo, ID *); } LibraryForeachIDData; -bool BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, int cb_flag) +/** Check whether current iteration over ID usages should be stopped or not. + * \return true if the iteration should be stopped, false otherwise. */ +bool BKE_lib_query_foreachid_iter_stop(LibraryForeachIDData *data) { - if (!(data->status & IDWALK_STOP)) { - const int flag = data->flag; - ID *old_id = *id_pp; - - /* Update the callback flags with the ones defined (or forbidden) in `data` by the generic - * caller code. */ - cb_flag = ((cb_flag | data->cb_flag) & ~data->cb_flag_clear); - - /* Update the callback flags with some extra information regarding overrides: all 'loopback', - * 'internal', 'embedded' etc. ID pointers are never overridable. */ - if (cb_flag & - (IDWALK_CB_INTERNAL | IDWALK_CB_LOOPBACK | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) { - cb_flag |= IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE; - } + return (data->status & IDWALK_STOP) != 0; +} - const int callback_return = data->callback( - &(struct LibraryIDLinkCallbackData){.user_data = data->user_data, - .bmain = data->bmain, - .id_owner = data->owner_id, - .id_self = data->self_id, - .id_pointer = id_pp, - .cb_flag = cb_flag}); - if (flag & IDWALK_READONLY) { - BLI_assert(*(id_pp) == old_id); - } - if (old_id && (flag & IDWALK_RECURSE)) { - if (BLI_gset_add((data)->ids_handled, old_id)) { - if (!(callback_return & IDWALK_RET_STOP_RECURSION)) { - BLI_LINKSTACK_PUSH(data->ids_todo, old_id); - } +void BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, int cb_flag) +{ + if (BKE_lib_query_foreachid_iter_stop(data)) { + return; + } + + const int flag = data->flag; + ID *old_id = *id_pp; + + /* Update the callback flags with the ones defined (or forbidden) in `data` by the generic + * caller code. */ + cb_flag = ((cb_flag | data->cb_flag) & ~data->cb_flag_clear); + + /* Update the callback flags with some extra information regarding overrides: all 'loopback', + * 'internal', 'embedded' etc. ID pointers are never overridable. */ + if (cb_flag & (IDWALK_CB_INTERNAL | IDWALK_CB_LOOPBACK | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) { + cb_flag |= IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE; + } + + const int callback_return = data->callback( + &(struct LibraryIDLinkCallbackData){.user_data = data->user_data, + .bmain = data->bmain, + .id_owner = data->owner_id, + .id_self = data->self_id, + .id_pointer = id_pp, + .cb_flag = cb_flag}); + if (flag & IDWALK_READONLY) { + BLI_assert(*(id_pp) == old_id); + } + if (old_id && (flag & IDWALK_RECURSE)) { + if (BLI_gset_add((data)->ids_handled, old_id)) { + if (!(callback_return & IDWALK_RET_STOP_RECURSION)) { + BLI_LINKSTACK_PUSH(data->ids_todo, old_id); } } - if (callback_return & IDWALK_RET_STOP_ITER) { - data->status |= IDWALK_STOP; - return false; - } - return true; } - - return false; + if (callback_return & IDWALK_RET_STOP_ITER) { + data->status |= IDWALK_STOP; + } } int BKE_lib_query_foreachid_process_flags_get(LibraryForeachIDData *data) @@ -139,7 +143,7 @@ int BKE_lib_query_foreachid_process_callback_flag_override(LibraryForeachIDData return cb_flag_backup; } -static void library_foreach_ID_link(Main *bmain, +static bool library_foreach_ID_link(Main *bmain, ID *id_owner, ID *id, LibraryIDLinkCallback callback, @@ -158,19 +162,24 @@ void BKE_lib_query_idpropertiesForeachIDLink_callback(IDProperty *id_prop, void BKE_LIB_FOREACHID_PROCESS_ID(data, id_prop->data.pointer, cb_flag); } -bool BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp) +/** Process embedded ID pointers (root nodetrees, master collections, ...). + * + * Those require specific care, since they are technically sub-data of their owner, yet in some + * cases they still behave as regular IDs. */ +void BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp) { /* Needed e.g. for callbacks handling relationships. This call shall be absolutely read-only. */ ID *id = *id_pp; const int flag = data->flag; - if (!BKE_lib_query_foreachid_process(data, id_pp, IDWALK_CB_EMBEDDED)) { - return false; + BKE_lib_query_foreachid_process(data, id_pp, IDWALK_CB_EMBEDDED); + if (BKE_lib_query_foreachid_iter_stop(data)) { + return; } BLI_assert(id == *id_pp); if (id == NULL) { - return true; + return; } if (flag & IDWALK_IGNORE_EMBEDDED_ID) { @@ -186,14 +195,24 @@ bool BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp) } } else { - library_foreach_ID_link( - data->bmain, data->owner_id, id, data->callback, data->user_data, data->flag, data); + if (!library_foreach_ID_link( + data->bmain, data->owner_id, id, data->callback, data->user_data, data->flag, data)) { + data->status |= IDWALK_STOP; + return; + } } +} - return true; +static void library_foreach_ID_data_cleanup(LibraryForeachIDData *data) +{ + if (data->ids_handled != NULL) { + BLI_gset_free(data->ids_handled, NULL); + BLI_LINKSTACK_FREE(data->ids_todo); + } } -static void library_foreach_ID_link(Main *bmain, +/** \return false in case iteration over ID pointers must be stopped, true otherwise. */ +static bool library_foreach_ID_link(Main *bmain, ID *id_owner, ID *id, LibraryIDLinkCallback callback, @@ -210,6 +229,10 @@ static void library_foreach_ID_link(Main *bmain, flag |= IDWALK_READONLY; flag &= ~IDWALK_DO_INTERNAL_RUNTIME_POINTERS; + /* NOTE: This function itself should never be called recursively when IDWALK_RECURSE is set, + * see also comments in #BKE_library_foreach_ID_embedded. + * This is why we can always create this data here, and do not need to try and re-use it from + * `inherit_data`. */ data.ids_handled = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); BLI_LINKSTACK_INIT(data.ids_todo); @@ -224,10 +247,26 @@ static void library_foreach_ID_link(Main *bmain, data.user_data = user_data; #define CALLBACK_INVOKE_ID(check_id, cb_flag) \ - BKE_LIB_FOREACHID_PROCESS_ID(&data, check_id, cb_flag) + { \ + CHECK_TYPE_ANY((check_id), ID *, void *); \ + BKE_lib_query_foreachid_process(&data, (ID **)&(check_id), (cb_flag)); \ + if (BKE_lib_query_foreachid_iter_stop(&data)) { \ + library_foreach_ID_data_cleanup(&data); \ + return false; \ + } \ + } \ + ((void)0) #define CALLBACK_INVOKE(check_id_super, cb_flag) \ - BKE_LIB_FOREACHID_PROCESS_IDSUPER(&data, check_id_super, cb_flag) + { \ + CHECK_TYPE(&((check_id_super)->id), ID *); \ + BKE_lib_query_foreachid_process(&data, (ID **)&(check_id_super), (cb_flag)); \ + if (BKE_lib_query_foreachid_iter_stop(&data)) { \ + library_foreach_ID_data_cleanup(&data); \ + return false; \ + } \ + } \ + ((void)0) for (; id != NULL; id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL) { data.self_id = id; @@ -269,6 +308,10 @@ static void library_foreach_ID_link(Main *bmain, to_id_entry = to_id_entry->next) { BKE_lib_query_foreachid_process( &data, to_id_entry->id_pointer.to, to_id_entry->usage_flag); + if (BKE_lib_query_foreachid_iter_stop(&data)) { + library_foreach_ID_data_cleanup(&data); + return false; + } } continue; } @@ -292,26 +335,33 @@ static void library_foreach_ID_link(Main *bmain, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, &data); + if (BKE_lib_query_foreachid_iter_stop(&data)) { + library_foreach_ID_data_cleanup(&data); + return false; + } AnimData *adt = BKE_animdata_from_id(id); if (adt) { BKE_animdata_foreach_id(adt, &data); + if (BKE_lib_query_foreachid_iter_stop(&data)) { + library_foreach_ID_data_cleanup(&data); + return false; + } } const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id); if (id_type->foreach_id != NULL) { id_type->foreach_id(id, &data); - if (data.status & IDWALK_STOP) { - break; + if (BKE_lib_query_foreachid_iter_stop(&data)) { + library_foreach_ID_data_cleanup(&data); + return false; } } } - if (data.ids_handled) { - BLI_gset_free(data.ids_handled, NULL); - BLI_LINKSTACK_FREE(data.ids_todo); - } + library_foreach_ID_data_cleanup(&data); + return true; #undef CALLBACK_INVOKE_ID #undef CALLBACK_INVOKE diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c index 905ac5af512..014c923f04f 100644 --- a/source/blender/blenkernel/intern/lib_remap.c +++ b/source/blender/blenkernel/intern/lib_remap.c @@ -132,7 +132,8 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data) const bool is_obj = (GS(id_owner->name) == ID_OB); const bool is_obj_proxy = (is_obj && (((Object *)id_owner)->proxy || ((Object *)id_owner)->proxy_group)); - const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id_owner)); + const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id_owner) && + (id_remap_data->flag & ID_REMAP_FORCE_OBDATA_IN_EDITMODE) == 0); const bool is_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) && (id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0); const bool skip_reference = (id_remap_data->flag & ID_REMAP_SKIP_OVERRIDE_LIBRARY) != 0; @@ -669,57 +670,10 @@ void BKE_libblock_relink_ex( DEG_relations_tag_update(bmain); } +static void libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag); static int id_relink_to_newid_looper(LibraryIDLinkCallbackData *cb_data) { const int cb_flag = cb_data->cb_flag; - if (cb_flag & IDWALK_CB_EMBEDDED) { - return IDWALK_RET_NOP; - } - - ID **id_pointer = cb_data->id_pointer; - ID *id = *id_pointer; - if (id) { - /* See: NEW_ID macro */ - if (id->newid) { - BKE_library_update_ID_link_user(id->newid, id, cb_flag); - id = id->newid; - *id_pointer = id; - } - if (id->tag & LIB_TAG_NEW) { - id->tag &= ~LIB_TAG_NEW; - BKE_libblock_relink_to_newid(id); - } - } - return IDWALK_RET_NOP; -} - -/** - * Similar to #libblock_relink_ex, - * but is remapping IDs to their newid value if non-NULL, in given \a id. - * - * Very specific usage, not sure we'll keep it on the long run, - * currently only used in Object/Collection duplication code... - * - * WARNING: This is a deprecated version of this function, should not be used by new code. See - * #BKE_libblock_relink_to_newid_new below. - */ -void BKE_libblock_relink_to_newid(ID *id) -{ - if (ID_IS_LINKED(id)) { - return; - } - - BKE_library_foreach_ID_link(NULL, id, id_relink_to_newid_looper, NULL, 0); -} - -/* ************************ - * FIXME: Port all usages of #BKE_libblock_relink_to_newid to this - * #BKE_libblock_relink_to_newid_new new code and remove old one. - ************************** */ -static void libblock_relink_to_newid_new(Main *bmain, ID *id); -static int id_relink_to_newid_looper_new(LibraryIDLinkCallbackData *cb_data) -{ - const int cb_flag = cb_data->cb_flag; if (cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) { return IDWALK_RET_NOP; } @@ -729,31 +683,31 @@ static int id_relink_to_newid_looper_new(LibraryIDLinkCallbackData *cb_data) ID **id_pointer = cb_data->id_pointer; ID *id = *id_pointer; if (id) { + const int remap_flag = POINTER_AS_INT(cb_data->user_data); /* See: NEW_ID macro */ if (id->newid != NULL) { - BKE_libblock_relink_ex(bmain, - id_owner, - id, - id->newid, - ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_OVERRIDE_LIBRARY); + const int remap_flag_final = remap_flag | ID_REMAP_SKIP_INDIRECT_USAGE | + ID_REMAP_SKIP_OVERRIDE_LIBRARY; + BKE_libblock_relink_ex(bmain, id_owner, id, id->newid, (short)remap_flag_final); id = id->newid; } if (id->tag & LIB_TAG_NEW) { id->tag &= ~LIB_TAG_NEW; - libblock_relink_to_newid_new(bmain, id); + libblock_relink_to_newid(bmain, id, remap_flag); } } return IDWALK_RET_NOP; } -static void libblock_relink_to_newid_new(Main *bmain, ID *id) +static void libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag) { if (ID_IS_LINKED(id)) { return; } id->tag &= ~LIB_TAG_NEW; - BKE_library_foreach_ID_link(bmain, id, id_relink_to_newid_looper_new, NULL, 0); + BKE_library_foreach_ID_link( + bmain, id, id_relink_to_newid_looper, POINTER_FROM_INT(remap_flag), 0); } /** @@ -765,7 +719,7 @@ static void libblock_relink_to_newid_new(Main *bmain, ID *id) * Very specific usage, not sure we'll keep it on the long run, * currently only used in Object/Collection duplication code... */ -void BKE_libblock_relink_to_newid_new(Main *bmain, ID *id) +void BKE_libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag) { if (ID_IS_LINKED(id)) { return; @@ -774,7 +728,7 @@ void BKE_libblock_relink_to_newid_new(Main *bmain, ID *id) BLI_assert(bmain->relations == NULL); BKE_layer_collection_resync_forbid(); - libblock_relink_to_newid_new(bmain, id); + libblock_relink_to_newid(bmain, id, remap_flag); BKE_layer_collection_resync_allow(); BKE_main_collection_sync_remap(bmain); } diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c index a6150028f46..05e8d4fe978 100644 --- a/source/blender/blenkernel/intern/light.c +++ b/source/blender/blenkernel/intern/light.c @@ -129,7 +129,8 @@ static void light_foreach_id(ID *id, LibraryForeachIDData *data) Light *lamp = (Light *)id; if (lamp->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - BKE_library_foreach_ID_embedded(data, (ID **)&lamp->nodetree); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_library_foreach_ID_embedded(data, (ID **)&lamp->nodetree)); } } diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index a1c93920731..3c305d1fb3f 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -155,12 +155,14 @@ static void linestyle_foreach_id(ID *id, LibraryForeachIDData *data) for (int i = 0; i < MAX_MTEX; i++) { if (linestyle->mtex[i]) { - BKE_texture_mtex_foreach_id(data, linestyle->mtex[i]); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_texture_mtex_foreach_id(data, linestyle->mtex[i])); } } if (linestyle->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - BKE_library_foreach_ID_embedded(data, (ID **)&linestyle->nodetree); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_library_foreach_ID_embedded(data, (ID **)&linestyle->nodetree)); } LISTBASE_FOREACH (LineStyleModifier *, lsm, &linestyle->color_modifiers) { diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index d82559a27cb..3a4e39812ab 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -166,9 +166,8 @@ static void material_foreach_id(ID *id, LibraryForeachIDData *data) { Material *material = (Material *)id; /* Nodetrees **are owned by IDs**, treat them as mere sub-data and not real ID! */ - if (!BKE_library_foreach_ID_embedded(data, (ID **)&material->nodetree)) { - return; - } + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_library_foreach_ID_embedded(data, (ID **)&material->nodetree)); if (material->texpaintslot != NULL) { BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, material->texpaintslot->ima, IDWALK_CB_NOP); } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.cc index f0ba83b396b..73e0c2cfa74 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.cc @@ -124,7 +124,7 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int CustomData_MeshMasks_update(&mask, &CD_MASK_DERIVEDMESH); } - mesh_dst->mat = MEM_dupallocN(mesh_src->mat); + mesh_dst->mat = (Material **)MEM_dupallocN(mesh_src->mat); BKE_defgroup_copy_list(&mesh_dst->vertex_group_names, &mesh_src->vertex_group_names); @@ -142,9 +142,9 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int BKE_mesh_update_customdata_pointers(mesh_dst, do_tessface); - mesh_dst->edit_mesh = NULL; + mesh_dst->edit_mesh = nullptr; - mesh_dst->mselect = MEM_dupallocN(mesh_dst->mselect); + mesh_dst->mselect = (MSelect *)MEM_dupallocN(mesh_dst->mselect); /* TODO: Do we want to add flag to prevent this? */ if (mesh_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) { @@ -165,7 +165,7 @@ static void mesh_free_data(ID *id) BKE_editmesh_free_data(mesh->edit_mesh); } MEM_freeN(mesh->edit_mesh); - mesh->edit_mesh = NULL; + mesh->edit_mesh = nullptr; } BKE_mesh_runtime_free_data(mesh); @@ -188,14 +188,14 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address Mesh *mesh = (Mesh *)id; const bool is_undo = BLO_write_is_undo(writer); - CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE]; - CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE]; - CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE]; - CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE]; - CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; + CustomDataLayer *vlayers = nullptr, vlayers_buff[CD_TEMP_CHUNK_SIZE]; + CustomDataLayer *elayers = nullptr, elayers_buff[CD_TEMP_CHUNK_SIZE]; + CustomDataLayer *flayers = nullptr, flayers_buff[CD_TEMP_CHUNK_SIZE]; + CustomDataLayer *llayers = nullptr, llayers_buff[CD_TEMP_CHUNK_SIZE]; + CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE]; /* cache only - don't write */ - mesh->mface = NULL; + mesh->mface = nullptr; mesh->totface = 0; memset(&mesh->fdata, 0, sizeof(mesh->fdata)); memset(&mesh->runtime, 0, sizeof(mesh->runtime)); @@ -203,22 +203,22 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address /* Do not store actual geometry data in case this is a library override ID. */ if (ID_IS_OVERRIDE_LIBRARY(mesh) && !is_undo) { - mesh->mvert = NULL; + mesh->mvert = nullptr; mesh->totvert = 0; memset(&mesh->vdata, 0, sizeof(mesh->vdata)); vlayers = vlayers_buff; - mesh->medge = NULL; + mesh->medge = nullptr; mesh->totedge = 0; memset(&mesh->edata, 0, sizeof(mesh->edata)); elayers = elayers_buff; - mesh->mloop = NULL; + mesh->mloop = nullptr; mesh->totloop = 0; memset(&mesh->ldata, 0, sizeof(mesh->ldata)); llayers = llayers_buff; - mesh->mpoly = NULL; + mesh->mpoly = nullptr; mesh->totpoly = 0; memset(&mesh->pdata, 0, sizeof(mesh->pdata)); players = players_buff; @@ -307,13 +307,13 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id) CustomData_blend_read(reader, &mesh->pdata, mesh->totpoly); mesh->texflag &= ~ME_AUTOSPACE_EVALUATED; - mesh->edit_mesh = NULL; + mesh->edit_mesh = nullptr; memset(&mesh->runtime, 0, sizeof(mesh->runtime)); BKE_mesh_runtime_init_data(mesh); /* happens with old files */ - if (mesh->mselect == NULL) { + if (mesh->mselect == nullptr) { mesh->totselect = 0; } @@ -355,31 +355,28 @@ static void mesh_read_expand(BlendExpander *expander, ID *id) } IDTypeInfo IDType_ID_ME = { - .id_code = ID_ME, - .id_filter = FILTER_ID_ME, - .main_listbase_index = INDEX_ID_ME, - .struct_size = sizeof(Mesh), - .name = "Mesh", - .name_plural = "meshes", - .translation_context = BLT_I18NCONTEXT_ID_MESH, - .flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE, - - .init_data = mesh_init_data, - .copy_data = mesh_copy_data, - .free_data = mesh_free_data, - .make_local = NULL, - .foreach_id = mesh_foreach_id, - .foreach_cache = NULL, - .owner_get = NULL, - - .blend_write = mesh_blend_write, - .blend_read_data = mesh_blend_read_data, - .blend_read_lib = mesh_blend_read_lib, - .blend_read_expand = mesh_read_expand, - - .blend_read_undo_preserve = NULL, - - .lib_override_apply_post = NULL, + ID_ME, + FILTER_ID_ME, + INDEX_ID_ME, + sizeof(Mesh), + "Mesh", + "meshes", + BLT_I18NCONTEXT_ID_MESH, + IDTYPE_FLAGS_APPEND_IS_REUSABLE, + + mesh_init_data, + mesh_copy_data, + mesh_free_data, + nullptr, + mesh_foreach_id, + nullptr, + nullptr, + mesh_blend_write, + mesh_blend_read_data, + mesh_blend_read_lib, + mesh_read_expand, + nullptr, + nullptr, }; enum { @@ -471,8 +468,8 @@ static int customdata_compare( switch (l1->type) { case CD_MVERT: { - MVert *v1 = l1->data; - MVert *v2 = l2->data; + MVert *v1 = (MVert *)l1->data; + MVert *v2 = (MVert *)l2->data; int vtot = m1->totvert; for (j = 0; j < vtot; j++, v1++, v2++) { @@ -488,8 +485,8 @@ static int customdata_compare( /* We're order-agnostic for edges here. */ case CD_MEDGE: { - MEdge *e1 = l1->data; - MEdge *e2 = l2->data; + MEdge *e1 = (MEdge *)l1->data; + MEdge *e2 = (MEdge *)l2->data; int etot = m1->totedge; EdgeHash *eh = BLI_edgehash_new_ex(__func__, etot); @@ -502,12 +499,12 @@ static int customdata_compare( return MESHCMP_EDGEUNKNOWN; } } - BLI_edgehash_free(eh, NULL); + BLI_edgehash_free(eh, nullptr); break; } case CD_MPOLY: { - MPoly *p1 = l1->data; - MPoly *p2 = l2->data; + MPoly *p1 = (MPoly *)l1->data; + MPoly *p2 = (MPoly *)l2->data; int ptot = m1->totpoly; for (j = 0; j < ptot; j++, p1++, p2++) { @@ -530,8 +527,8 @@ static int customdata_compare( break; } case CD_MLOOP: { - MLoop *lp1 = l1->data; - MLoop *lp2 = l2->data; + MLoop *lp1 = (MLoop *)l1->data; + MLoop *lp2 = (MLoop *)l2->data; int ltot = m1->totloop; for (j = 0; j < ltot; j++, lp1++, lp2++) { @@ -542,8 +539,8 @@ static int customdata_compare( break; } case CD_MLOOPUV: { - MLoopUV *lp1 = l1->data; - MLoopUV *lp2 = l2->data; + MLoopUV *lp1 = (MLoopUV *)l1->data; + MLoopUV *lp2 = (MLoopUV *)l2->data; int ltot = m1->totloop; for (j = 0; j < ltot; j++, lp1++, lp2++) { @@ -554,8 +551,8 @@ static int customdata_compare( break; } case CD_MLOOPCOL: { - MLoopCol *lp1 = l1->data; - MLoopCol *lp2 = l2->data; + MLoopCol *lp1 = (MLoopCol *)l1->data; + MLoopCol *lp2 = (MLoopCol *)l2->data; int ltot = m1->totloop; for (j = 0; j < ltot; j++, lp1++, lp2++) { @@ -566,8 +563,8 @@ static int customdata_compare( break; } case CD_MDEFORMVERT: { - MDeformVert *dv1 = l1->data; - MDeformVert *dv2 = l2->data; + MDeformVert *dv1 = (MDeformVert *)l1->data; + MDeformVert *dv2 = (MDeformVert *)l2->data; int dvtot = m1->totvert; for (j = 0; j < dvtot; j++, dv1++, dv2++) { @@ -590,8 +587,8 @@ static int customdata_compare( break; } case CD_PROP_FLOAT: { - const float *l1_data = l1->data; - const float *l2_data = l2->data; + const float *l1_data = (float *)l1->data; + const float *l2_data = (float *)l2->data; for (int i = 0; i < total_length; i++) { if (compare_threshold_relative(l1_data[i], l2_data[i], thresh)) { @@ -601,8 +598,8 @@ static int customdata_compare( break; } case CD_PROP_FLOAT2: { - const float(*l1_data)[2] = l1->data; - const float(*l2_data)[2] = l2->data; + const float(*l1_data)[2] = (float(*)[2])l1->data; + const float(*l2_data)[2] = (float(*)[2])l2->data; for (int i = 0; i < total_length; i++) { if (compare_threshold_relative(l1_data[i][0], l2_data[i][0], thresh)) { @@ -615,8 +612,8 @@ static int customdata_compare( break; } case CD_PROP_FLOAT3: { - const float(*l1_data)[3] = l1->data; - const float(*l2_data)[3] = l2->data; + const float(*l1_data)[3] = (float(*)[3])l1->data; + const float(*l2_data)[3] = (float(*)[3])l2->data; for (int i = 0; i < total_length; i++) { if (compare_threshold_relative(l1_data[i][0], l2_data[i][0], thresh)) { @@ -632,8 +629,8 @@ static int customdata_compare( break; } case CD_PROP_INT32: { - const int *l1_data = l1->data; - const int *l2_data = l2->data; + const int *l1_data = (int *)l1->data; + const int *l2_data = (int *)l2->data; for (int i = 0; i < total_length; i++) { if (l1_data[i] != l2_data[i]) { @@ -643,8 +640,8 @@ static int customdata_compare( break; } case CD_PROP_BOOL: { - const bool *l1_data = l1->data; - const bool *l2_data = l2->data; + const bool *l1_data = (bool *)l1->data; + const bool *l2_data = (bool *)l2->data; for (int i = 0; i < total_length; i++) { if (l1_data[i] != l2_data[i]) { @@ -654,8 +651,8 @@ static int customdata_compare( break; } case CD_PROP_COLOR: { - const MPropCol *l1_data = l1->data; - const MPropCol *l2_data = l2->data; + const MPropCol *l1_data = (MPropCol *)l1->data; + const MPropCol *l2_data = (MPropCol *)l2->data; for (int i = 0; i < total_length; i++) { for (j = 0; j < 4; j++) { @@ -722,7 +719,7 @@ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh) return cmpcode_to_str(c); } - return NULL; + return nullptr; } static void mesh_ensure_tessellation_customdata(Mesh *me) @@ -767,7 +764,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me) void BKE_mesh_ensure_skin_customdata(Mesh *me) { - BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : NULL; + BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr; MVertSkin *vs; if (bm) { @@ -779,7 +776,7 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me) /* Mark an arbitrary vertex as root */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - vs = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_MVERT_SKIN); + vs = (MVertSkin *)CustomData_bmesh_get(&bm->vdata, v->head.data, CD_MVERT_SKIN); vs->flag |= MVERT_SKIN_ROOT; break; } @@ -787,7 +784,8 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me) } else { if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) { - vs = CustomData_add_layer(&me->vdata, CD_MVERT_SKIN, CD_DEFAULT, NULL, me->totvert); + vs = (MVertSkin *)CustomData_add_layer( + &me->vdata, CD_MVERT_SKIN, CD_DEFAULT, nullptr, me->totvert); /* Mark an arbitrary vertex as root */ if (vs) { @@ -799,7 +797,7 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me) bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me) { - BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : NULL; + BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr; bool changed = false; if (bm) { if (!CustomData_has_layer(&bm->pdata, CD_FACEMAP)) { @@ -809,7 +807,7 @@ bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me) } else { if (!CustomData_has_layer(&me->pdata, CD_FACEMAP)) { - CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, NULL, me->totpoly); + CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, nullptr, me->totpoly); changed = true; } } @@ -818,7 +816,7 @@ bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me) bool BKE_mesh_clear_facemap_customdata(struct Mesh *me) { - BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : NULL; + BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr; bool changed = false; if (bm) { if (CustomData_has_layer(&bm->pdata, CD_FACEMAP)) { @@ -836,12 +834,12 @@ bool BKE_mesh_clear_facemap_customdata(struct Mesh *me) } /** - * This ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or - * mloopcol and mcol) have the same relative active/render/clone/mask indices. + * This ensures grouped custom-data (e.g. #CD_MLOOPUV and #CD_MTFACE, or + * #CD_MLOOPCOL and #CD_MCOL) have the same relative active/render/clone/mask indices. * - * NOTE(campbell): that for undo mesh data we want to skip 'ensure_tess_cd' call since - * we don't want to store memory for tessface when its only used for older - * Versions of the mesh. + * NOTE(@campbellbarton): that for undo mesh data we want to skip 'ensure_tess_cd' call since + * we don't want to store memory for #MFace data when its only used for older + * versions of the mesh. */ static void mesh_update_linked_customdata(Mesh *me, const bool do_ensure_tess_cd) { @@ -856,20 +854,20 @@ void BKE_mesh_update_customdata_pointers(Mesh *me, const bool do_ensure_tess_cd) { mesh_update_linked_customdata(me, do_ensure_tess_cd); - me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT); - me->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT); + me->mvert = (MVert *)CustomData_get_layer(&me->vdata, CD_MVERT); + me->dvert = (MDeformVert *)CustomData_get_layer(&me->vdata, CD_MDEFORMVERT); - me->medge = CustomData_get_layer(&me->edata, CD_MEDGE); + me->medge = (MEdge *)CustomData_get_layer(&me->edata, CD_MEDGE); - me->mface = CustomData_get_layer(&me->fdata, CD_MFACE); - me->mcol = CustomData_get_layer(&me->fdata, CD_MCOL); - me->mtface = CustomData_get_layer(&me->fdata, CD_MTFACE); + me->mface = (MFace *)CustomData_get_layer(&me->fdata, CD_MFACE); + me->mcol = (MCol *)CustomData_get_layer(&me->fdata, CD_MCOL); + me->mtface = (MTFace *)CustomData_get_layer(&me->fdata, CD_MTFACE); - me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY); - me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP); + me->mpoly = (MPoly *)CustomData_get_layer(&me->pdata, CD_MPOLY); + me->mloop = (MLoop *)CustomData_get_layer(&me->ldata, CD_MLOOP); - me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL); - me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV); + me->mloopcol = (MLoopCol *)CustomData_get_layer(&me->ldata, CD_MLOOPCOL); + me->mloopuv = (MLoopUV *)CustomData_get_layer(&me->ldata, CD_MLOOPUV); } bool BKE_mesh_has_custom_loop_normals(Mesh *me) @@ -883,7 +881,7 @@ bool BKE_mesh_has_custom_loop_normals(Mesh *me) /** * Free (or release) any data used by this mesh (does not free the mesh itself). - * Only use for undo, in most cases `BKE_id_free(NULL, me)` should be used. + * Only use for undo, in most cases `BKE_id_free(nullptr, me)` should be used. */ void BKE_mesh_free_data_for_undo(Mesh *me) { @@ -939,15 +937,15 @@ static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata) CustomData_reset(&mesh->fdata); } - mesh->mface = NULL; - mesh->mtface = NULL; - mesh->mcol = NULL; + mesh->mface = nullptr; + mesh->mtface = nullptr; + mesh->mcol = nullptr; mesh->totface = 0; } Mesh *BKE_mesh_add(Main *bmain, const char *name) { - Mesh *me = BKE_id_new(bmain, ID_ME, name); + Mesh *me = (Mesh *)BKE_id_new(bmain, ID_ME, name); return me; } @@ -956,28 +954,28 @@ Mesh *BKE_mesh_add(Main *bmain, const char *name) static void mesh_ensure_cdlayers_primary(Mesh *mesh, bool do_tessface) { if (!CustomData_get_layer(&mesh->vdata, CD_MVERT)) { - CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert); + CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, nullptr, mesh->totvert); } if (!CustomData_get_layer(&mesh->edata, CD_MEDGE)) { - CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge); + CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, nullptr, mesh->totedge); } if (!CustomData_get_layer(&mesh->ldata, CD_MLOOP)) { - CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop); + CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, nullptr, mesh->totloop); } if (!CustomData_get_layer(&mesh->pdata, CD_MPOLY)) { - CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly); + CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, nullptr, mesh->totpoly); } if (do_tessface && !CustomData_get_layer(&mesh->fdata, CD_MFACE)) { - CustomData_add_layer(&mesh->fdata, CD_MFACE, CD_CALLOC, NULL, mesh->totface); + CustomData_add_layer(&mesh->fdata, CD_MFACE, CD_CALLOC, nullptr, mesh->totface); } } Mesh *BKE_mesh_new_nomain( int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len) { - Mesh *mesh = BKE_libblock_alloc( - NULL, ID_ME, BKE_idtype_idcode_to_name(ID_ME), LIB_ID_CREATE_LOCALIZE); + Mesh *mesh = (Mesh *)BKE_libblock_alloc( + nullptr, ID_ME, BKE_idtype_idcode_to_name(ID_ME), LIB_ID_CREATE_LOCALIZE); BKE_libblock_init_empty(&mesh->id); /* Don't use #CustomData_reset because we don't want to touch custom-data. */ @@ -1043,10 +1041,10 @@ void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src) BKE_defgroup_copy_list(&me_dst->vertex_group_names, &me_src->vertex_group_names); /* Copy materials. */ - if (me_dst->mat != NULL) { + if (me_dst->mat != nullptr) { MEM_freeN(me_dst->mat); } - me_dst->mat = MEM_dupallocN(me_src->mat); + me_dst->mat = (Material **)MEM_dupallocN(me_src->mat); me_dst->totcol = me_src->totcol; } @@ -1061,9 +1059,9 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src, /* Only do tessface if we are creating tessfaces or copying from mesh with only tessfaces. */ const bool do_tessface = (tessface_len || ((me_src->totface != 0) && (me_src->totpoly == 0))); - Mesh *me_dst = BKE_id_new_nomain(ID_ME, NULL); + Mesh *me_dst = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr); - me_dst->mselect = MEM_dupallocN(me_src->mselect); + me_dst->mselect = (MSelect *)MEM_dupallocN(me_src->mselect); me_dst->totvert = verts_len; me_dst->totedge = edges_len; @@ -1107,7 +1105,7 @@ Mesh *BKE_mesh_new_nomain_from_template(const Mesh *me_src, void BKE_mesh_eval_delete(struct Mesh *mesh_eval) { /* Evaluated mesh may point to edit mesh, but never owns it. */ - mesh_eval->edit_mesh = NULL; + mesh_eval->edit_mesh = nullptr; mesh_free_data(&mesh_eval->id); BKE_libblock_free_data(&mesh_eval->id, false); MEM_freeN(mesh_eval); @@ -1121,7 +1119,7 @@ Mesh *BKE_mesh_copy_for_eval(const Mesh *source, bool reference) flags |= LIB_ID_COPY_CD_REFERENCE; } - Mesh *result = (Mesh *)BKE_id_copy_ex(NULL, &source->id, NULL, flags); + Mesh *result = (Mesh *)BKE_id_copy_ex(nullptr, &source->id, nullptr, flags); return result; } @@ -1142,14 +1140,12 @@ BMesh *BKE_mesh_to_bmesh(Mesh *me, const bool add_key_index, const struct BMeshCreateParams *params) { - return BKE_mesh_to_bmesh_ex(me, - params, - &(struct BMeshFromMeshParams){ - .calc_face_normal = false, - .add_key_index = add_key_index, - .use_shapekey = true, - .active_shapekey = ob->shapenr, - }); + BMeshFromMeshParams bmesh_from_mesh_params{}; + bmesh_from_mesh_params.calc_face_normal = false; + bmesh_from_mesh_params.add_key_index = add_key_index; + bmesh_from_mesh_params.use_shapekey = true; + bmesh_from_mesh_params.active_shapekey = ob->shapenr; + return BKE_mesh_to_bmesh_ex(me, params, &bmesh_from_mesh_params); } Mesh *BKE_mesh_from_bmesh_nomain(BMesh *bm, @@ -1157,8 +1153,8 @@ Mesh *BKE_mesh_from_bmesh_nomain(BMesh *bm, const Mesh *me_settings) { BLI_assert(params->calc_object_remap == false); - Mesh *mesh = BKE_id_new_nomain(ID_ME, NULL); - BM_mesh_bm_to_me(NULL, bm, mesh, params); + Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr); + BM_mesh_bm_to_me(nullptr, bm, mesh, params); BKE_mesh_copy_parameters_for_eval(mesh, me_settings); return mesh; } @@ -1167,7 +1163,7 @@ Mesh *BKE_mesh_from_bmesh_for_eval_nomain(BMesh *bm, const CustomData_MeshMasks *cd_mask_extra, const Mesh *me_settings) { - Mesh *mesh = BKE_id_new_nomain(ID_ME, NULL); + Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr); BM_mesh_bm_to_me_for_eval(bm, mesh, cd_mask_extra); BKE_mesh_copy_parameters_for_eval(mesh, me_settings); return mesh; @@ -1177,8 +1173,8 @@ BoundBox *BKE_mesh_boundbox_get(Object *ob) { /* This is Object-level data access, * DO NOT touch to Mesh's bb, would be totally thread-unsafe. */ - if (ob->runtime.bb == NULL || ob->runtime.bb->flag & BOUNDBOX_DIRTY) { - Mesh *me = ob->data; + if (ob->runtime.bb == nullptr || ob->runtime.bb->flag & BOUNDBOX_DIRTY) { + Mesh *me = (Mesh *)ob->data; float min[3], max[3]; INIT_MINMAX(min, max); @@ -1187,8 +1183,8 @@ BoundBox *BKE_mesh_boundbox_get(Object *ob) max[0] = max[1] = max[2] = 1.0f; } - if (ob->runtime.bb == NULL) { - ob->runtime.bb = MEM_mallocN(sizeof(*ob->runtime.bb), __func__); + if (ob->runtime.bb == nullptr) { + ob->runtime.bb = (BoundBox *)MEM_mallocN(sizeof(*ob->runtime.bb), __func__); } BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max); ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY; @@ -1257,13 +1253,13 @@ void BKE_mesh_texspace_get_reference(Mesh *me, short **r_texflag, float **r_loc, { BKE_mesh_texspace_ensure(me); - if (r_texflag != NULL) { + if (r_texflag != nullptr) { *r_texflag = &me->texflag; } - if (r_loc != NULL) { + if (r_loc != nullptr) { *r_loc = me->loc; } - if (r_size != NULL) { + if (r_size != nullptr) { *r_size = me->size; } } @@ -1282,11 +1278,11 @@ void BKE_mesh_texspace_copy_from_object(Mesh *me, Object *ob) float (*BKE_mesh_orco_verts_get(Object *ob))[3] { - Mesh *me = ob->data; + Mesh *me = (Mesh *)ob->data; Mesh *tme = me->texcomesh ? me->texcomesh : me; /* Get appropriate vertex coordinates */ - float(*vcos)[3] = MEM_calloc_arrayN(me->totvert, sizeof(*vcos), "orco mesh"); + float(*vcos)[3] = (float(*)[3])MEM_calloc_arrayN(me->totvert, sizeof(*vcos), "orco mesh"); MVert *mvert = tme->mvert; int totvert = min_ii(tme->totvert, me->totvert); @@ -1393,28 +1389,28 @@ int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata, int mfindex, Mesh *BKE_mesh_from_object(Object *ob) { - if (ob == NULL) { - return NULL; + if (ob == nullptr) { + return nullptr; } if (ob->type == OB_MESH) { - return ob->data; + return (Mesh *)ob->data; } - return NULL; + return nullptr; } void BKE_mesh_assign_object(Main *bmain, Object *ob, Mesh *me) { - Mesh *old = NULL; + Mesh *old = nullptr; - if (ob == NULL) { + if (ob == nullptr) { return; } multires_force_sculpt_rebuild(ob); if (ob->type == OB_MESH) { - old = ob->data; + old = (Mesh *)ob->data; if (old) { id_us_min(&old->id); } @@ -1605,8 +1601,9 @@ bool BKE_mesh_minmax(const Mesh *me, float r_min[3], float r_max[3]) void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys) { int i; - MVert *mvert = CustomData_duplicate_referenced_layer(&me->vdata, CD_MVERT, me->totvert); - float(*lnors)[3] = CustomData_duplicate_referenced_layer(&me->ldata, CD_NORMAL, me->totloop); + MVert *mvert = (MVert *)CustomData_duplicate_referenced_layer(&me->vdata, CD_MVERT, me->totvert); + float(*lnors)[3] = (float(*)[3])CustomData_duplicate_referenced_layer( + &me->ldata, CD_NORMAL, me->totloop); /* If the referenced layer has been re-allocated need to update pointers stored in the mesh. */ BKE_mesh_update_customdata_pointers(me, false); @@ -1616,9 +1613,8 @@ void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys) } if (do_keys && me->key) { - KeyBlock *kb; - for (kb = me->key->block.first; kb; kb = kb->next) { - float *fp = kb->data; + LISTBASE_FOREACH (KeyBlock *, kb, &me->key->block) { + float *fp = (float *)kb->data; for (i = kb->totelem; i--; fp += 3) { mul_m4_v3(mat, fp); } @@ -1651,9 +1647,8 @@ void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys) } if (do_keys && me->key) { - KeyBlock *kb; - for (kb = me->key->block.first; kb; kb = kb->next) { - float *fp = kb->data; + LISTBASE_FOREACH (KeyBlock *, kb, &me->key->block) { + float *fp = (float *)kb->data; for (i = kb->totelem; i--; fp += 3) { add_v3_v3(fp, offset); } @@ -1725,7 +1720,8 @@ void BKE_mesh_mselect_validate(Mesh *me) } mselect_src = me->mselect; - mselect_dst = MEM_malloc_arrayN((me->totselect), sizeof(MSelect), "Mesh selection history"); + mselect_dst = (MSelect *)MEM_malloc_arrayN( + (me->totselect), sizeof(MSelect), "Mesh selection history"); for (i_src = 0, i_dst = 0; i_src < me->totselect; i_src++) { int index = mselect_src[i_src].index; @@ -1762,10 +1758,10 @@ void BKE_mesh_mselect_validate(Mesh *me) if (i_dst == 0) { MEM_freeN(mselect_dst); - mselect_dst = NULL; + mselect_dst = nullptr; } else if (i_dst != me->totselect) { - mselect_dst = MEM_reallocN(mselect_dst, sizeof(MSelect) * i_dst); + mselect_dst = (MSelect *)MEM_reallocN(mselect_dst, sizeof(MSelect) * i_dst); } me->totselect = i_dst; @@ -1809,7 +1805,7 @@ void BKE_mesh_mselect_active_set(Mesh *me, int index, int type) if (msel_index == -1) { /* add to the end */ - me->mselect = MEM_reallocN(me->mselect, sizeof(MSelect) * (me->totselect + 1)); + me->mselect = (MSelect *)MEM_reallocN(me->mselect, sizeof(MSelect) * (me->totselect + 1)); me->mselect[me->totselect].index = index; me->mselect[me->totselect].type = type; me->totselect++; @@ -1845,7 +1841,7 @@ void BKE_mesh_vert_coords_get(const Mesh *mesh, float (*vert_coords)[3]) float (*BKE_mesh_vert_coords_alloc(const Mesh *mesh, int *r_vert_len))[3] { - float(*vert_coords)[3] = MEM_mallocN(sizeof(float[3]) * mesh->totvert, __func__); + float(*vert_coords)[3] = (float(*)[3])MEM_mallocN(sizeof(float[3]) * mesh->totvert, __func__); BKE_mesh_vert_coords_get(mesh, vert_coords); if (r_vert_len) { *r_vert_len = mesh->totvert; @@ -1856,7 +1852,8 @@ float (*BKE_mesh_vert_coords_alloc(const Mesh *mesh, int *r_vert_len))[3] void BKE_mesh_vert_coords_apply(Mesh *mesh, const float (*vert_coords)[3]) { /* This will just return the pointer if it wasn't a referenced layer. */ - MVert *mv = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert); + MVert *mv = (MVert *)CustomData_duplicate_referenced_layer( + &mesh->vdata, CD_MVERT, mesh->totvert); mesh->mvert = mv; for (int i = 0; i < mesh->totvert; i++, mv++) { copy_v3_v3(mv->co, vert_coords[i]); @@ -1869,7 +1866,8 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh, const float mat[4][4]) { /* This will just return the pointer if it wasn't a referenced layer. */ - MVert *mv = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert); + MVert *mv = (MVert *)CustomData_duplicate_referenced_layer( + &mesh->vdata, CD_MVERT, mesh->totvert); mesh->mvert = mv; for (int i = 0; i < mesh->totvert; i++, mv++) { mul_v3_m4v3(mv->co, mat, vert_coords[i]); @@ -1880,7 +1878,8 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh, void BKE_mesh_vert_normals_apply(Mesh *mesh, const short (*vert_normals)[3]) { /* This will just return the pointer if it wasn't a referenced layer. */ - MVert *mv = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert); + MVert *mv = (MVert *)CustomData_duplicate_referenced_layer( + &mesh->vdata, CD_MVERT, mesh->totvert); mesh->mvert = mv; for (int i = 0; i < mesh->totvert; i++, mv++) { copy_v3_v3_short(mv->no, vert_normals[i]); @@ -1899,35 +1898,37 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac { float(*r_loopnors)[3]; float(*polynors)[3]; - short(*clnors)[2] = NULL; + short(*clnors)[2] = nullptr; bool free_polynors = false; /* Note that we enforce computing clnors when the clnor space array is requested by caller here. - * However, we obviously only use the autosmooth angle threshold - * only in case autosmooth is enabled. */ - const bool use_split_normals = (r_lnors_spacearr != NULL) || ((mesh->flag & ME_AUTOSMOOTH) != 0); + * However, we obviously only use the auto-smooth angle threshold + * only in case auto-smooth is enabled. */ + const bool use_split_normals = (r_lnors_spacearr != nullptr) || + ((mesh->flag & ME_AUTOSMOOTH) != 0); const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : (float)M_PI; if (CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { - r_loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL); + r_loopnors = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL); memset(r_loopnors, 0, sizeof(float[3]) * mesh->totloop); } else { - r_loopnors = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CALLOC, NULL, mesh->totloop); + r_loopnors = (float(*)[3])CustomData_add_layer( + &mesh->ldata, CD_NORMAL, CD_CALLOC, nullptr, mesh->totloop); CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); } - /* may be NULL */ - clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); + /* may be nullptr */ + clnors = (short(*)[2])CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) { /* This assume that layer is always up to date, not sure this is the case * (esp. in Edit mode?)... */ - polynors = CustomData_get_layer(&mesh->pdata, CD_NORMAL); + polynors = (float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL); free_polynors = false; } else { - polynors = MEM_malloc_arrayN(mesh->totpoly, sizeof(float[3]), __func__); + polynors = (float(*)[3])MEM_malloc_arrayN(mesh->totpoly, sizeof(float[3]), __func__); BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert, mesh->totvert, mesh->mloop, @@ -1935,7 +1936,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac mesh->mpoly, mesh->totpoly, polynors, - NULL); + nullptr); free_polynors = true; } @@ -1953,7 +1954,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac split_angle, r_lnors_spacearr, clnors, - NULL); + nullptr); if (free_polynors) { MEM_freeN(polynors); @@ -1966,25 +1967,25 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac void BKE_mesh_calc_normals_split(Mesh *mesh) { - BKE_mesh_calc_normals_split_ex(mesh, NULL); + BKE_mesh_calc_normals_split_ex(mesh, nullptr); } /* Split faces helper functions. */ -typedef struct SplitFaceNewVert { +struct SplitFaceNewVert { struct SplitFaceNewVert *next; int new_index; int orig_index; float *vnor; -} SplitFaceNewVert; +}; -typedef struct SplitFaceNewEdge { +struct SplitFaceNewEdge { struct SplitFaceNewEdge *next; int new_index; int orig_index; int v1; int v2; -} SplitFaceNewEdge; +}; /* Detect needed new vertices, and update accordingly loops' vertex indices. * WARNING! Leaves mesh in invalid state. */ @@ -1996,7 +1997,7 @@ static int split_faces_prepare_new_verts(const Mesh *mesh, /* This is now mandatory, trying to do the job in simple way without that data is doomed to fail, * even when only dealing with smooth/flat faces one can find cases that no simple algorithm * can handle properly. */ - BLI_assert(lnors_spacearr != NULL); + BLI_assert(lnors_spacearr != nullptr); const int loops_len = mesh->totloop; int verts_len = mesh->totvert; @@ -2049,7 +2050,8 @@ static int split_faces_prepare_new_verts(const Mesh *mesh, } else { /* Add new vert to list. */ - SplitFaceNewVert *new_vert = BLI_memarena_alloc(memarena, sizeof(*new_vert)); + SplitFaceNewVert *new_vert = (SplitFaceNewVert *)BLI_memarena_alloc(memarena, + sizeof(*new_vert)); new_vert->orig_index = vert_idx; new_vert->new_index = new_vert_idx; new_vert->vnor = (*lnor_space)->vec_lnor; /* See note above. */ @@ -2096,7 +2098,8 @@ static int split_faces_prepare_new_edges(const Mesh *mesh, *eval = POINTER_FROM_INT(new_edge_idx); ml_prev->e = new_edge_idx; - SplitFaceNewEdge *new_edge = BLI_memarena_alloc(memarena, sizeof(*new_edge)); + SplitFaceNewEdge *new_edge = (SplitFaceNewEdge *)BLI_memarena_alloc(memarena, + sizeof(*new_edge)); new_edge->orig_index = edge_idx; new_edge->new_index = new_edge_idx; new_edge->v1 = ml_prev->v; @@ -2122,7 +2125,7 @@ static int split_faces_prepare_new_edges(const Mesh *mesh, } MEM_freeN(edges_used); - BLI_edgehash_free(edges_hash, NULL); + BLI_edgehash_free(edges_hash, nullptr); return num_edges - mesh->totedge; } @@ -2181,14 +2184,14 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals) } BKE_mesh_tessface_clear(mesh); - MLoopNorSpaceArray lnors_spacearr = {NULL}; + MLoopNorSpaceArray lnors_spacearr = {nullptr}; /* Compute loop normals and loop normal spaces (a.k.a. smooth fans of faces around vertices). */ BKE_mesh_calc_normals_split_ex(mesh, &lnors_spacearr); /* Stealing memarena from loop normals space array. */ MemArena *memarena = lnors_spacearr.mem; - SplitFaceNewVert *new_verts = NULL; - SplitFaceNewEdge *new_edges = NULL; + SplitFaceNewVert *new_verts = nullptr; + SplitFaceNewEdge *new_edges = nullptr; /* Ensure we own the layers, we need to do this before split_faces_prepare_new_verts as it will * directly assign new indices to existing edges and loops. */ @@ -2252,10 +2255,10 @@ void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh) /* We are here because something did change in the mesh. This means we can not trust the existing * evaluated mesh, and we don't know what parts of the mesh did change. So we simply delete the * evaluated mesh and let objects to re-create it with updated settings. */ - if (mesh->runtime.mesh_eval != NULL) { - mesh->runtime.mesh_eval->edit_mesh = NULL; - BKE_id_free(NULL, mesh->runtime.mesh_eval); - mesh->runtime.mesh_eval = NULL; + if (mesh->runtime.mesh_eval != nullptr) { + mesh->runtime.mesh_eval->edit_mesh = nullptr; + BKE_id_free(nullptr, mesh->runtime.mesh_eval); + mesh->runtime.mesh_eval = nullptr; } if (DEG_is_active(depsgraph)) { Mesh *mesh_orig = (Mesh *)DEG_get_original_id(&mesh->id); diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc index 9f5703a015d..3447185089d 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc @@ -410,7 +410,8 @@ struct Mesh *BKE_mesh_remesh_voxel_fix_poles(const Mesh *mesh) { const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); - const BMeshCreateParams bmesh_create_params = {true}; + BMeshCreateParams bmesh_create_params{}; + bmesh_create_params.use_toolflags = true; BMesh *bm = BM_mesh_create(&allocsize, &bmesh_create_params); BMeshFromMeshParams bmesh_from_mesh_params{}; diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c index ce89c723a61..7b1d5140421 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.c +++ b/source/blender/blenkernel/intern/mesh_runtime.c @@ -113,7 +113,7 @@ void BKE_mesh_runtime_reset_on_copy(Mesh *mesh, const int UNUSED(flag)) /** * \brief This function clears runtime cache of the given mesh. - * + * * Call this function to recalculate runtime data when used. */ void BKE_mesh_runtime_clear_cache(Mesh *mesh) diff --git a/source/blender/blenkernel/intern/mesh_sample.cc b/source/blender/blenkernel/intern/mesh_sample.cc index 2274d34f0f1..a046cc68bf2 100644 --- a/source/blender/blenkernel/intern/mesh_sample.cc +++ b/source/blender/blenkernel/intern/mesh_sample.cc @@ -269,7 +269,7 @@ void MeshAttributeInterpolator::sample_attribute(const ReadAttributeLookup &src_ eAttributeMapMode mode) { if (src_attribute && dst_attribute) { - this->sample_data(*src_attribute.varray, src_attribute.domain, mode, dst_attribute.as_span()); + this->sample_data(src_attribute.varray, src_attribute.domain, mode, dst_attribute.as_span()); } } diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index ef84afd8668..124db07298d 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -491,11 +491,11 @@ void BKE_nla_strip_foreach_id(NlaStrip *strip, LibraryForeachIDData *data) BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, strip->act, IDWALK_CB_USER); LISTBASE_FOREACH (FCurve *, fcu, &strip->fcurves) { - BKE_fcurve_foreach_id(fcu, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, BKE_fcurve_foreach_id(fcu, data)); } LISTBASE_FOREACH (NlaStrip *, substrip, &strip->strips) { - BKE_nla_strip_foreach_id(substrip, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, BKE_nla_strip_foreach_id(substrip, data)); } } diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index ab3132a5d58..98c31eab7cd 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -66,6 +66,7 @@ #include "BKE_colortools.h" #include "BKE_cryptomatte.h" #include "BKE_global.h" +#include "BKE_icons.h" #include "BKE_idprop.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" @@ -129,10 +130,6 @@ static void node_socket_interface_free(bNodeTree *UNUSED(ntree), static void nodeMuteRerouteOutputLinks(struct bNodeTree *ntree, struct bNode *node, const bool mute); -static FieldInferencingInterface *node_field_inferencing_interface_copy( - const FieldInferencingInterface &field_inferencing_interface); -static void node_field_inferencing_interface_free( - const FieldInferencingInterface *field_inferencing_interface); static void ntree_init_data(ID *id) { @@ -245,9 +242,16 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c ntree_dst->interface_type = nullptr; if (ntree_src->field_inferencing_interface) { - ntree_dst->field_inferencing_interface = node_field_inferencing_interface_copy( + ntree_dst->field_inferencing_interface = new FieldInferencingInterface( *ntree_src->field_inferencing_interface); } + + if (flag & LIB_ID_COPY_NO_PREVIEW) { + ntree_dst->preview = nullptr; + } + else { + BKE_previewimg_id_copy(&ntree_dst->id, &ntree_src->id); + } } static void ntree_free_data(ID *id) @@ -293,7 +297,7 @@ static void ntree_free_data(ID *id) MEM_freeN(sock); } - node_field_inferencing_interface_free(ntree->field_inferencing_interface); + delete ntree->field_inferencing_interface; /* free preview hash */ if (ntree->previews) { @@ -303,12 +307,16 @@ static void ntree_free_data(ID *id) if (ntree->id.tag & LIB_TAG_LOCALIZED) { BKE_libblock_free_data(&ntree->id, true); } + + BKE_previewimg_free(&ntree->preview); } static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket *sock) { - IDP_foreach_property( - sock->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, + IDP_foreach_property( + sock->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data)); switch ((eNodeSocketDatatype)sock->type) { case SOCK_OBJECT: { @@ -360,21 +368,25 @@ static void node_foreach_id(ID *id, LibraryForeachIDData *data) LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { BKE_LIB_FOREACHID_PROCESS_ID(data, node->id, IDWALK_CB_USER); - IDP_foreach_property( - node->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, + IDP_foreach_property(node->prop, + IDP_TYPE_FILTER_ID, + BKE_lib_query_idpropertiesForeachIDLink_callback, + data)); LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { - library_foreach_node_socket(data, sock); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(data, sock)); } LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { - library_foreach_node_socket(data, sock); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(data, sock)); } } LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) { - library_foreach_node_socket(data, sock); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(data, sock)); } LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) { - library_foreach_node_socket(data, sock); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(data, sock)); } } @@ -635,6 +647,8 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) { write_node_socket_interface(writer, sock); } + + BKE_previewimg_blend_write(writer, ntree->preview); } static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_address) @@ -665,6 +679,7 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock) BLO_read_data_address(reader, &sock->default_value); sock->total_inputs = 0; /* Clear runtime data set before drawing. */ sock->cache = nullptr; + sock->declaration = nullptr; } /* ntree itself has been read! */ @@ -828,6 +843,9 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) ntree->update |= NTREE_UPDATE_FIELD_INFERENCING; } + BLO_read_data_address(reader, &ntree->preview); + BKE_previewimg_blend_read(reader, ntree->preview); + /* type verification is in lib-link */ } @@ -1051,8 +1069,7 @@ IDTypeInfo IDType_ID_NT = { static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype) { if (ntype->declare != nullptr) { - nodeDeclarationEnsure(ntree, node); - node->declaration->build(*ntree, *node); + node_verify_sockets(ntree, node, true); return; } bNodeSocketTemplate *sockdef; @@ -1141,15 +1158,15 @@ static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo) { if (typeinfo) { ntree->typeinfo = typeinfo; - - /* deprecated integer type */ - ntree->type = typeinfo->type; } else { ntree->typeinfo = &NodeTreeTypeUndefined; ntree->init &= ~NTREE_TYPE_INIT; } + + /* Deprecated integer type. */ + ntree->type = ntree->typeinfo->type; } static void node_set_typeinfo(const struct bContext *C, @@ -1523,7 +1540,7 @@ static bNodeSocket *make_socket(bNodeTree *ntree, } /* make the identifier unique */ BLI_uniquename_cb( - unique_identifier_check, lb, "socket", '.', auto_identifier, sizeof(auto_identifier)); + unique_identifier_check, lb, "socket", '_', auto_identifier, sizeof(auto_identifier)); bNodeSocket *sock = (bNodeSocket *)MEM_callocN(sizeof(bNodeSocket), "sock"); sock->in_out = in_out; @@ -3999,17 +4016,38 @@ int nodeSocketLinkLimit(const bNodeSocket *sock) return sock->limit; } +static void update_socket_declarations(ListBase *sockets, + Span<blender::nodes::SocketDeclarationPtr> declarations) +{ + int index; + LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, sockets, index) { + const SocketDeclaration &socket_decl = *declarations[index]; + socket->declaration = &socket_decl; + } +} + /** - * If the node implements a `declare` function, this function makes sure that `node->declaration` - * is up to date. + * Update `socket->declaration` for all sockets in the node. This assumes that the node declaration + * and sockets are up to date already. + */ +void nodeSocketDeclarationsUpdate(bNode *node) +{ + BLI_assert(node->declaration != nullptr); + update_socket_declarations(&node->inputs, node->declaration->inputs()); + update_socket_declarations(&node->outputs, node->declaration->outputs()); +} + +/** + * Just update `node->declaration` if necessary. This can also be called on nodes that may not be + * up to date (e.g. because the need versioning or are dynamic). */ -void nodeDeclarationEnsure(bNodeTree *UNUSED(ntree), bNode *node) +bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree *UNUSED(ntree), bNode *node) { if (node->declaration != nullptr) { - return; + return false; } if (node->typeinfo->declare == nullptr) { - return; + return false; } if (node->typeinfo->declaration_is_dynamic) { node->declaration = new blender::nodes::NodeDeclaration(); @@ -4021,6 +4059,20 @@ void nodeDeclarationEnsure(bNodeTree *UNUSED(ntree), bNode *node) BLI_assert(node->typeinfo->fixed_declaration != nullptr); node->declaration = node->typeinfo->fixed_declaration; } + return true; +} + +/** + * If the node implements a `declare` function, this function makes sure that `node->declaration` + * is up to date. It is expected that the sockets of the node are up to date already. + */ +bool nodeDeclarationEnsure(bNodeTree *ntree, bNode *node) +{ + if (nodeDeclarationEnsureOnOutdatedNode(ntree, node)) { + nodeSocketDeclarationsUpdate(node); + return true; + } + return false; } /* ************** Node Clipboard *********** */ @@ -4492,18 +4544,6 @@ void ntreeUpdateAllNew(Main *main) FOREACH_NODETREE_END; } -static FieldInferencingInterface *node_field_inferencing_interface_copy( - const FieldInferencingInterface &field_inferencing_interface) -{ - return new FieldInferencingInterface(field_inferencing_interface); -} - -static void node_field_inferencing_interface_free( - const FieldInferencingInterface *field_inferencing_interface) -{ - delete field_inferencing_interface; -} - namespace blender::bke::node_field_inferencing { static bool is_field_socket_type(eNodeSocketDatatype type) @@ -5485,6 +5525,7 @@ static void register_undefined_types() * they are just used as placeholders in case the actual types are not registered. */ + NodeTreeTypeUndefined.type = NTREE_UNDEFINED; strcpy(NodeTreeTypeUndefined.idname, "NodeTreeUndefined"); strcpy(NodeTreeTypeUndefined.ui_name, N_("Undefined")); strcpy(NodeTreeTypeUndefined.ui_description, N_("Undefined Node Tree Type")); diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index deef053b658..d650003afe2 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -160,11 +160,10 @@ static CLG_LogRef LOG = {"bke.object"}; /** - * Vertex parent modifies original BMesh which is not safe for threading. + * NOTE(@sergey): Vertex parent modifies original #BMesh which is not safe for threading. * Ideally such a modification should be handled as a separate DAG update - * callback for mesh datablock, but for until it is actually supported use + * callback for mesh data-block, but for until it is actually supported use * simpler solution with a mutex lock. - * - sergey - */ #define VPARENT_THREADING_HACK @@ -390,7 +389,8 @@ static void library_foreach_modifiersForeachIDLink(void *user_data, int cb_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; - BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag)); } static void library_foreach_gpencil_modifiersForeachIDLink(void *user_data, @@ -399,7 +399,8 @@ static void library_foreach_gpencil_modifiersForeachIDLink(void *user_data, int cb_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; - BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag)); } static void library_foreach_shaderfxForeachIDLink(void *user_data, @@ -408,7 +409,8 @@ static void library_foreach_shaderfxForeachIDLink(void *user_data, int cb_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; - BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag)); } static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), @@ -418,7 +420,8 @@ static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), { LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; const int cb_flag = is_reference ? IDWALK_CB_USER : IDWALK_CB_NOP; - BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag)); } static void library_foreach_particlesystemsObjectLooper(ParticleSystem *UNUSED(psys), @@ -427,7 +430,8 @@ static void library_foreach_particlesystemsObjectLooper(ParticleSystem *UNUSED(p int cb_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; - BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag)); } static void object_foreach_id(ID *id, LibraryForeachIDData *data) @@ -494,10 +498,18 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data) const int cb_flag_orig = BKE_lib_query_foreachid_process_callback_flag_override( data, proxy_cb_flag, false); LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - IDP_foreach_property( - pchan->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, + IDP_foreach_property(pchan->prop, + IDP_TYPE_FILTER_ID, + BKE_lib_query_idpropertiesForeachIDLink_callback, + data)); + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, pchan->custom, IDWALK_CB_USER); - BKE_constraints_id_loop(&pchan->constraints, library_foreach_constraintObjectLooper, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, + BKE_constraints_id_loop( + &pchan->constraints, library_foreach_constraintObjectLooper, data)); } BKE_lib_query_foreachid_process_callback_flag_override(data, cb_flag_orig, true); } @@ -509,14 +521,21 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data) data, object->rigidbody_constraint->ob2, IDWALK_CB_NEVER_SELF); } - BKE_modifiers_foreach_ID_link(object, library_foreach_modifiersForeachIDLink, data); - BKE_gpencil_modifiers_foreach_ID_link( - object, library_foreach_gpencil_modifiersForeachIDLink, data); - BKE_constraints_id_loop(&object->constraints, library_foreach_constraintObjectLooper, data); - BKE_shaderfx_foreach_ID_link(object, library_foreach_shaderfxForeachIDLink, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_modifiers_foreach_ID_link(object, library_foreach_modifiersForeachIDLink, data)); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, + BKE_gpencil_modifiers_foreach_ID_link( + object, library_foreach_gpencil_modifiersForeachIDLink, data)); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, + BKE_constraints_id_loop(&object->constraints, library_foreach_constraintObjectLooper, data)); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_shaderfx_foreach_ID_link(object, library_foreach_shaderfxForeachIDLink, data)); LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) { - BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, data)); } if (object->soft) { @@ -1204,7 +1223,7 @@ static IDProperty *object_asset_dimensions_property(Object *ob) return nullptr; } - IDPropertyTemplate idprop = {0}; + IDPropertyTemplate idprop{}; idprop.array.len = ARRAY_SIZE(dimensions); idprop.array.type = IDP_FLOAT; @@ -1747,24 +1766,24 @@ static void object_update_from_subsurf_ccg(Object *object) /* NOTE: we need to reshape into an original mesh from main database, * allowing: * - * - Update copies of that mesh at any moment. - * - Save the file without doing extra reshape. - * - All the users of the mesh have updated displacement. + * - Update copies of that mesh at any moment. + * - Save the file without doing extra reshape. + * - All the users of the mesh have updated displacement. * * However, the tricky part here is that we only know about sculpted * state of a mesh on an object level, and object is being updated after - * mesh datablock is updated. This forces us to: + * mesh data-block is updated. This forces us to: * - * - Update mesh datablock from object evaluation, which is technically - * forbidden, but there is no other place for this yet. - * - Reshape to the original mesh from main database, and then copy updated - * layer to copy of that mesh (since copy of the mesh has decoupled - * custom data layers). + * - Update mesh data-block from object evaluation, which is technically + * forbidden, but there is no other place for this yet. + * - Reshape to the original mesh from main database, and then copy updated + * layer to copy of that mesh (since copy of the mesh has decoupled + * custom data layers). * * All this is defeating all the designs we need to follow to allow safe * threaded evaluation, but this is as good as we can make it within the * current sculpt/evaluated mesh design. This is also how we've survived - * with old DerivedMesh based solutions. So, while this is all wrong and + * with old #DerivedMesh based solutions. So, while this is all wrong and * needs reconsideration, doesn't seem to be a big stopper for real * production artists. */ @@ -1803,7 +1822,7 @@ void BKE_object_eval_assign_data(Object *object_eval, ID *data_eval, bool is_own object_eval->runtime.data_eval = data_eval; object_eval->runtime.is_data_eval_owned = is_owned; - /* Overwrite data of evaluated object, if the datablock types match. */ + /* Overwrite data of evaluated object, if the data-block types match. */ ID *data = (ID *)object_eval->data; if (GS(data->name) == GS(data_eval->name)) { /* NOTE: we are not supposed to invoke evaluation for original objects, @@ -1845,8 +1864,8 @@ void BKE_object_free_derived_caches(Object *ob) ob->runtime.mesh_deform_eval = nullptr; } - /* Restore initial pointer for copy-on-write datablocks, object->data - * might be pointing to an evaluated datablock data was just freed above. */ + /* Restore initial pointer for copy-on-write data-blocks, object->data + * might be pointing to an evaluated data-block data was just freed above. */ if (ob->runtime.data_orig != nullptr) { ob->data = ob->runtime.data_orig; } @@ -2345,13 +2364,13 @@ Object *BKE_object_add_from( } /** - * Add a new object, but assign the given datablock as the ob->data + * Add a new object, but assign the given data-block as the `ob->data` * for the newly created object. * - * \param data: The datablock to assign as ob->data for the new object. - * This is assumed to be of the correct type. - * \param do_id_user: If true, id_us_plus() will be called on data when - * assigning it to the object. + * \param data: The data-block to assign as `ob->data` for the new object. + * This is assumed to be of the correct type. + * \param do_id_user: If true, #id_us_plus() will be called on data when + * assigning it to the object. */ Object *BKE_object_add_for_data( Main *bmain, ViewLayer *view_layer, int type, const char *name, ID *data, bool do_id_user) @@ -2616,7 +2635,7 @@ Object **BKE_object_pose_array_get_ex(ViewLayer *view_layer, Object *ob_pose = BKE_object_pose_armature_get(ob_active); Object **objects = nullptr; if (ob_pose == ob_active) { - ObjectsInModeParams ob_params = {0}; + ObjectsInModeParams ob_params{}; ob_params.object_mode = OB_MODE_POSE; ob_params.no_dup_data = unique; @@ -2663,7 +2682,7 @@ Base **BKE_object_pose_base_array_get_ex(ViewLayer *view_layer, } if (base_active && (base_pose == base_active)) { - ObjectsInModeParams ob_params = {0}; + ObjectsInModeParams ob_params{}; ob_params.object_mode = OB_MODE_POSE; ob_params.no_dup_data = unique; @@ -2851,7 +2870,7 @@ Object *BKE_object_duplicate(Main *bmain, Object *ob, uint dupflag, uint duplica if (!is_subprocess) { /* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */ - BKE_libblock_relink_to_newid((ID *)&obn->id); + BKE_libblock_relink_to_newid(bmain, &obn->id, 0); #ifndef NDEBUG /* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags. */ @@ -4285,7 +4304,7 @@ void BKE_object_foreach_display_point(Object *ob, } } else if (ob->type == OB_GPENCIL) { - GPencilStrokePointIterData iter_data = {nullptr}; + GPencilStrokePointIterData iter_data{}; iter_data.obmat = obmat; iter_data.point_func_cb = func_cb; iter_data.user_data = user_data; @@ -4323,28 +4342,18 @@ void BKE_scene_foreach_display_point(Depsgraph *depsgraph, } /** - * Struct members from DNA_object_types.h + * See struct members from #Object in DNA_object_types.h */ struct ObTfmBack { float loc[3], dloc[3]; - /** scale and delta scale. */ float scale[3], dscale[3]; - /** euler rotation. */ float rot[3], drot[3]; - /** quaternion rotation. */ float quat[4], dquat[4]; - /** axis angle rotation - axis part. */ float rotAxis[3], drotAxis[3]; - /** axis angle rotation - angle part. */ float rotAngle, drotAngle; - /** final worldspace matrix with constraints & animsys applied. */ float obmat[4][4]; - /** inverse result of parent, so that object doesn't 'stick' to parent. */ float parentinv[4][4]; - /** inverse result of constraints. doesn't include effect of parent or object local transform. - */ float constinv[4][4]; - /** inverse matrix of 'obmat' for during render, temporally: ipokeys of transform. */ float imat[4][4]; }; @@ -5400,7 +5409,7 @@ void BKE_object_groups_clear(Main *bmain, Scene *scene, Object *ob) } /** - * Return a KDTree_3d from the deformed object (in worldspace) + * Return a KDTree_3d from the deformed object (in world-space). * * \note Only mesh objects currently support deforming, others are TODO. * @@ -5426,7 +5435,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot) MVert *mvert = me_eval->mvert; uint totvert = me_eval->totvert; - /* tree over-allocs in case where some verts have ORIGINDEX_NONE */ + /* Tree over-allocates in case where some verts have #ORIGINDEX_NONE. */ tot = 0; tree = BLI_kdtree_3d_new(totvert); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index feb997a4c5d..5b62761bd91 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -180,7 +180,8 @@ static void particle_settings_foreach_id(ID *id, LibraryForeachIDData *data) for (int i = 0; i < MAX_MTEX; i++) { if (psett->mtex[i]) { - BKE_texture_mtex_foreach_id(data, psett->mtex[i]); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, + BKE_texture_mtex_foreach_id(data, psett->mtex[i])); } } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 0aeee11ed17..a0bd3abbc1a 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -471,7 +471,8 @@ static void scene_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSE int cb_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; - BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag)); } /** @@ -522,7 +523,10 @@ static void scene_foreach_toolsettings_id_pointer_process( } } -#define BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS( \ +/* Special handling is needed here, as `scene_foreach_toolsettings` (and its dependency + * `scene_foreach_paint`) are also used by `scene_undo_preserve`, where `LibraryForeachIDData + * *data` is NULL. */ +#define BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER( \ __data, __id, __do_undo_restore, __action, __reader, __id_old, __cb_flag) \ { \ if (__do_undo_restore) { \ @@ -530,24 +534,38 @@ static void scene_foreach_toolsettings_id_pointer_process( (ID **)&(__id), __action, __reader, (ID **)&(__id_old), __cb_flag); \ } \ else { \ + BLI_assert((__data) != NULL); \ BKE_LIB_FOREACHID_PROCESS_IDSUPER(__data, __id, __cb_flag); \ } \ } \ (void)0 +#define BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL( \ + __data, __do_undo_restore, __func_call) \ + { \ + if (__do_undo_restore) { \ + __func_call; \ + } \ + else { \ + BLI_assert((__data) != NULL); \ + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(__data, __func_call); \ + } \ + } \ + (void)0 + static void scene_foreach_paint(LibraryForeachIDData *data, Paint *paint, const bool do_undo_restore, BlendLibReader *reader, Paint *paint_old) { - BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, - paint->brush, - do_undo_restore, - SCENE_FOREACH_UNDO_RESTORE, - reader, - paint_old->brush, - IDWALK_CB_USER); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data, + paint->brush, + do_undo_restore, + SCENE_FOREACH_UNDO_RESTORE, + reader, + paint_old->brush, + IDWALK_CB_USER); for (int i = 0; i < paint_old->tool_slots_len; i++) { /* This is a bit tricky. * - In case we do not do `undo_restore`, `paint` and `paint_old` pointers are the same, so @@ -559,21 +577,21 @@ static void scene_foreach_paint(LibraryForeachIDData *data, */ Brush *brush_tmp = NULL; Brush **brush_p = i < paint->tool_slots_len ? &paint->tool_slots[i].brush : &brush_tmp; - BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, - *brush_p, - do_undo_restore, - SCENE_FOREACH_UNDO_RESTORE, - reader, - paint_old->brush, - IDWALK_CB_USER); - } - BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, - paint->palette, - do_undo_restore, - SCENE_FOREACH_UNDO_RESTORE, - reader, - paint_old->palette, - IDWALK_CB_USER); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data, + *brush_p, + do_undo_restore, + SCENE_FOREACH_UNDO_RESTORE, + reader, + paint_old->brush, + IDWALK_CB_USER); + } + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data, + paint->palette, + do_undo_restore, + SCENE_FOREACH_UNDO_RESTORE, + reader, + paint_old->palette, + IDWALK_CB_USER); } static void scene_foreach_toolsettings(LibraryForeachIDData *data, @@ -582,110 +600,152 @@ static void scene_foreach_toolsettings(LibraryForeachIDData *data, BlendLibReader *reader, ToolSettings *toolsett_old) { - BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, - toolsett->particle.scene, - do_undo_restore, - SCENE_FOREACH_UNDO_NO_RESTORE, - reader, - toolsett_old->particle.scene, - IDWALK_CB_NOP); - BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, - toolsett->particle.object, - do_undo_restore, - SCENE_FOREACH_UNDO_NO_RESTORE, - reader, - toolsett_old->particle.object, - IDWALK_CB_NOP); - BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, - toolsett->particle.shape_object, - do_undo_restore, - SCENE_FOREACH_UNDO_NO_RESTORE, - reader, - toolsett_old->particle.shape_object, - IDWALK_CB_NOP); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data, + toolsett->particle.scene, + do_undo_restore, + SCENE_FOREACH_UNDO_NO_RESTORE, + reader, + toolsett_old->particle.scene, + IDWALK_CB_NOP); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data, + toolsett->particle.object, + do_undo_restore, + SCENE_FOREACH_UNDO_NO_RESTORE, + reader, + toolsett_old->particle.object, + IDWALK_CB_NOP); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data, + toolsett->particle.shape_object, + do_undo_restore, + SCENE_FOREACH_UNDO_NO_RESTORE, + reader, + toolsett_old->particle.shape_object, + IDWALK_CB_NOP); scene_foreach_paint( data, &toolsett->imapaint.paint, do_undo_restore, reader, &toolsett_old->imapaint.paint); - BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, - toolsett->imapaint.stencil, - do_undo_restore, - SCENE_FOREACH_UNDO_RESTORE, - reader, - toolsett_old->imapaint.stencil, - IDWALK_CB_USER); - BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, - toolsett->imapaint.clone, - do_undo_restore, - SCENE_FOREACH_UNDO_RESTORE, - reader, - toolsett_old->imapaint.clone, - IDWALK_CB_USER); - BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, - toolsett->imapaint.canvas, - do_undo_restore, - SCENE_FOREACH_UNDO_RESTORE, - reader, - toolsett_old->imapaint.canvas, - IDWALK_CB_USER); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data, + toolsett->imapaint.stencil, + do_undo_restore, + SCENE_FOREACH_UNDO_RESTORE, + reader, + toolsett_old->imapaint.stencil, + IDWALK_CB_USER); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data, + toolsett->imapaint.clone, + do_undo_restore, + SCENE_FOREACH_UNDO_RESTORE, + reader, + toolsett_old->imapaint.clone, + IDWALK_CB_USER); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data, + toolsett->imapaint.canvas, + do_undo_restore, + SCENE_FOREACH_UNDO_RESTORE, + reader, + toolsett_old->imapaint.canvas, + IDWALK_CB_USER); if (toolsett->vpaint) { - scene_foreach_paint( - data, &toolsett->vpaint->paint, do_undo_restore, reader, &toolsett_old->vpaint->paint); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL( + data, + do_undo_restore, + scene_foreach_paint(data, + &toolsett->vpaint->paint, + do_undo_restore, + reader, + &toolsett_old->vpaint->paint)); } if (toolsett->wpaint) { - scene_foreach_paint( - data, &toolsett->wpaint->paint, do_undo_restore, reader, &toolsett_old->wpaint->paint); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL( + data, + do_undo_restore, + scene_foreach_paint(data, + &toolsett->wpaint->paint, + do_undo_restore, + reader, + &toolsett_old->wpaint->paint)); } if (toolsett->sculpt) { - scene_foreach_paint( - data, &toolsett->sculpt->paint, do_undo_restore, reader, &toolsett_old->sculpt->paint); - BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, - toolsett->sculpt->gravity_object, - do_undo_restore, - SCENE_FOREACH_UNDO_NO_RESTORE, - reader, - toolsett_old->sculpt->gravity_object, - IDWALK_CB_NOP); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL( + data, + do_undo_restore, + scene_foreach_paint(data, + &toolsett->sculpt->paint, + do_undo_restore, + reader, + &toolsett_old->sculpt->paint)); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data, + toolsett->sculpt->gravity_object, + do_undo_restore, + SCENE_FOREACH_UNDO_NO_RESTORE, + reader, + toolsett_old->sculpt->gravity_object, + IDWALK_CB_NOP); } if (toolsett->uvsculpt) { - scene_foreach_paint( - data, &toolsett->uvsculpt->paint, do_undo_restore, reader, &toolsett_old->uvsculpt->paint); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL( + data, + do_undo_restore, + scene_foreach_paint(data, + &toolsett->uvsculpt->paint, + do_undo_restore, + reader, + &toolsett_old->uvsculpt->paint)); } if (toolsett->gp_paint) { - scene_foreach_paint( - data, &toolsett->gp_paint->paint, do_undo_restore, reader, &toolsett_old->gp_paint->paint); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL( + data, + do_undo_restore, + scene_foreach_paint(data, + &toolsett->gp_paint->paint, + do_undo_restore, + reader, + &toolsett_old->gp_paint->paint)); } if (toolsett->gp_vertexpaint) { - scene_foreach_paint(data, - &toolsett->gp_vertexpaint->paint, - do_undo_restore, - reader, - &toolsett_old->gp_vertexpaint->paint); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL( + data, + do_undo_restore, + scene_foreach_paint(data, + &toolsett->gp_vertexpaint->paint, + do_undo_restore, + reader, + &toolsett_old->gp_vertexpaint->paint)); } if (toolsett->gp_sculptpaint) { - scene_foreach_paint(data, - &toolsett->gp_sculptpaint->paint, - do_undo_restore, - reader, - &toolsett_old->gp_sculptpaint->paint); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL( + data, + do_undo_restore, + scene_foreach_paint(data, + &toolsett->gp_sculptpaint->paint, + do_undo_restore, + reader, + &toolsett_old->gp_sculptpaint->paint)); } if (toolsett->gp_weightpaint) { - scene_foreach_paint(data, - &toolsett->gp_weightpaint->paint, - do_undo_restore, - reader, - &toolsett_old->gp_weightpaint->paint); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL( + data, + do_undo_restore, + scene_foreach_paint(data, + &toolsett->gp_weightpaint->paint, + do_undo_restore, + reader, + &toolsett_old->gp_weightpaint->paint)); } - BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, - toolsett->gp_sculpt.guide.reference_object, - do_undo_restore, - SCENE_FOREACH_UNDO_NO_RESTORE, - reader, - toolsett_old->gp_sculpt.guide.reference_object, - IDWALK_CB_NOP); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data, + toolsett->gp_sculpt.guide.reference_object, + do_undo_restore, + SCENE_FOREACH_UNDO_NO_RESTORE, + reader, + toolsett_old->gp_sculpt.guide.reference_object, + IDWALK_CB_NOP); } +#undef BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER +#undef BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL + static void scene_foreach_layer_collection(LibraryForeachIDData *data, ListBase *lb) { LISTBASE_FOREACH (LayerCollection *, lc, lb) { @@ -707,7 +767,8 @@ static bool seq_foreach_member_id_cb(Sequence *seq, void *user_data) #define FOREACHID_PROCESS_IDSUPER(_data, _id_super, _cb_flag) \ { \ CHECK_TYPE(&((_id_super)->id), ID *); \ - if (!BKE_lib_query_foreachid_process((_data), (ID **)&(_id_super), (_cb_flag))) { \ + BKE_lib_query_foreachid_process((_data), (ID **)&(_id_super), (_cb_flag)); \ + if (BKE_lib_query_foreachid_iter_stop((_data))) { \ return false; \ } \ } \ @@ -746,15 +807,18 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data) BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, scene->r.bake.cage_object, IDWALK_CB_NOP); if (scene->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - BKE_library_foreach_ID_embedded(data, (ID **)&scene->nodetree); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_library_foreach_ID_embedded(data, (ID **)&scene->nodetree)); } if (scene->ed) { - SEQ_for_each_callback(&scene->ed->seqbase, seq_foreach_member_id_cb, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, SEQ_for_each_callback(&scene->ed->seqbase, seq_foreach_member_id_cb, data)); } /* This pointer can be NULL during old files reading, better be safe than sorry. */ if (scene->master_collection != NULL) { - BKE_library_foreach_ID_embedded(data, (ID **)&scene->master_collection); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_library_foreach_ID_embedded(data, (ID **)&scene->master_collection)); } LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { @@ -765,7 +829,8 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data) data, base->object, IDWALK_CB_NOP | IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE); } - scene_foreach_layer_collection(data, &view_layer->layer_collections); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, scene_foreach_layer_collection(data, &view_layer->layer_collections)); LISTBASE_FOREACH (FreestyleModuleConfig *, fmc, &view_layer->freestyle_config.modules) { if (fmc->script) { @@ -786,18 +851,25 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data) LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) { BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, marker->camera, IDWALK_CB_NOP); - IDP_foreach_property( - marker->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, + IDP_foreach_property(marker->prop, + IDP_TYPE_FILTER_ID, + BKE_lib_query_idpropertiesForeachIDLink_callback, + data)); } ToolSettings *toolsett = scene->toolsettings; if (toolsett) { - scene_foreach_toolsettings(data, toolsett, false, NULL, toolsett); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, scene_foreach_toolsettings(data, toolsett, false, NULL, toolsett)); } if (scene->rigidbody_world) { - BKE_rigidbody_world_id_loop( - scene->rigidbody_world, scene_foreach_rigidbodyworldSceneLooper, data); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, + BKE_rigidbody_world_id_loop( + scene->rigidbody_world, scene_foreach_rigidbodyworldSceneLooper, data)); } } @@ -1853,7 +1925,7 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) if (!is_subprocess) { /* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */ - BKE_libblock_relink_to_newid(&sce_copy->id); + BKE_libblock_relink_to_newid(bmain, &sce_copy->id, 0); #ifndef NDEBUG /* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 233a4f344b5..6352e08ec4b 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -97,6 +97,10 @@ static void screen_foreach_id_dopesheet(LibraryForeachIDData *data, bDopeSheet * } } +/** + * Callback used by lib_query to walk over all ID usages (mimics `foreach_id` callback of + * `IDTypeInfo` structure). + */ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area) { BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, area->full, IDWALK_CB_NOP); @@ -107,10 +111,8 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area switch (sl->spacetype) { case SPACE_VIEW3D: { View3D *v3d = (View3D *)sl; - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, v3d->camera, IDWALK_CB_NOP); BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, v3d->ob_center, IDWALK_CB_NOP); - if (v3d->localvd) { BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, v3d->localvd->camera, IDWALK_CB_NOP); } @@ -118,13 +120,12 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area } case SPACE_GRAPH: { SpaceGraph *sipo = (SpaceGraph *)sl; - - screen_foreach_id_dopesheet(data, sipo->ads); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, + screen_foreach_id_dopesheet(data, sipo->ads)); break; } case SPACE_PROPERTIES: { SpaceProperties *sbuts = (SpaceProperties *)sl; - BKE_LIB_FOREACHID_PROCESS_ID(data, sbuts->pinid, IDWALK_CB_NOP); break; } @@ -132,14 +133,12 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area break; case SPACE_ACTION: { SpaceAction *saction = (SpaceAction *)sl; - screen_foreach_id_dopesheet(data, &saction->ads); BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, saction->action, IDWALK_CB_NOP); break; } case SPACE_IMAGE: { SpaceImage *sima = (SpaceImage *)sl; - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sima->image, IDWALK_CB_USER_ONE); BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sima->mask_info.mask, IDWALK_CB_USER_ONE); BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sima->gpd, IDWALK_CB_USER); @@ -147,33 +146,28 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area } case SPACE_SEQ: { SpaceSeq *sseq = (SpaceSeq *)sl; - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sseq->gpd, IDWALK_CB_USER); break; } case SPACE_NLA: { SpaceNla *snla = (SpaceNla *)sl; - - screen_foreach_id_dopesheet(data, snla->ads); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, + screen_foreach_id_dopesheet(data, snla->ads)); break; } case SPACE_TEXT: { SpaceText *st = (SpaceText *)sl; - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, st->text, IDWALK_CB_NOP); break; } case SPACE_SCRIPT: { SpaceScript *scpt = (SpaceScript *)sl; - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, scpt->script, IDWALK_CB_NOP); break; } case SPACE_OUTLINER: { SpaceOutliner *space_outliner = (SpaceOutliner *)sl; - BKE_LIB_FOREACHID_PROCESS_ID(data, space_outliner->search_tse.id, IDWALK_CB_NOP); - if (space_outliner->treestore != NULL) { TreeStoreElem *tselem; BLI_mempool_iter iter; @@ -187,13 +181,11 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area } case SPACE_NODE: { SpaceNode *snode = (SpaceNode *)sl; - const bool is_private_nodetree = snode->id != NULL && ntreeFromID(snode->id) == snode->nodetree; BKE_LIB_FOREACHID_PROCESS_ID(data, snode->id, IDWALK_CB_NOP); BKE_LIB_FOREACHID_PROCESS_ID(data, snode->from, IDWALK_CB_NOP); - BKE_LIB_FOREACHID_PROCESS_IDSUPER( data, snode->nodetree, is_private_nodetree ? IDWALK_CB_EMBEDDED : IDWALK_CB_USER_ONE); @@ -219,14 +211,12 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area } case SPACE_CLIP: { SpaceClip *sclip = (SpaceClip *)sl; - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sclip->clip, IDWALK_CB_USER_ONE); BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sclip->mask_info.mask, IDWALK_CB_USER_ONE); break; } case SPACE_SPREADSHEET: { SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; - LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) { if (context->type == SPREADSHEET_CONTEXT_OBJECT) { BKE_LIB_FOREACHID_PROCESS_IDSUPER( @@ -243,12 +233,13 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area static void screen_foreach_id(ID *id, LibraryForeachIDData *data) { - if (BKE_lib_query_foreachid_process_flags_get(data) & IDWALK_INCLUDE_UI) { - bScreen *screen = (bScreen *)id; + if ((BKE_lib_query_foreachid_process_flags_get(data) & IDWALK_INCLUDE_UI) == 0) { + return; + } + bScreen *screen = (bScreen *)id; - LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { - BKE_screen_foreach_id_screen_area(data, area); - } + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, BKE_screen_foreach_id_screen_area(data, area)); } } diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc index 1d297b3ced9..98e7405bde6 100644 --- a/source/blender/blenkernel/intern/simulation.cc +++ b/source/blender/blenkernel/intern/simulation.cc @@ -103,7 +103,8 @@ static void simulation_foreach_id(ID *id, LibraryForeachIDData *data) Simulation *simulation = (Simulation *)id; if (simulation->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - BKE_library_foreach_ID_embedded(data, (ID **)&simulation->nodetree); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_library_foreach_ID_embedded(data, (ID **)&simulation->nodetree)); } } diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc index c2c9d178171..52bbd2bec57 100644 --- a/source/blender/blenkernel/intern/spline_base.cc +++ b/source/blender/blenkernel/intern/spline_base.cc @@ -30,14 +30,12 @@ using blender::float3; using blender::IndexRange; using blender::MutableSpan; using blender::Span; +using blender::VArray; using blender::attribute_math::convert_to_static_type; using blender::bke::AttributeIDRef; using blender::fn::GMutableSpan; using blender::fn::GSpan; using blender::fn::GVArray; -using blender::fn::GVArray_For_GSpan; -using blender::fn::GVArray_Typed; -using blender::fn::GVArrayPtr; Spline::Type Spline::type() const { @@ -416,7 +414,7 @@ Span<float3> Spline::evaluated_normals() const } /* Rotate the generated normals with the interpolated tilt data. */ - GVArray_Typed<float> tilts = this->interpolate_to_evaluated(this->tilts()); + VArray<float> tilts = this->interpolate_to_evaluated(this->tilts()); for (const int i : normals.index_range()) { normals[i] = rotate_direction_around_axis(normals[i], tangents[i], tilts[i]); } @@ -529,9 +527,9 @@ void Spline::bounds_min_max(float3 &min, float3 &max, const bool use_evaluated) } } -GVArrayPtr Spline::interpolate_to_evaluated(GSpan data) const +GVArray Spline::interpolate_to_evaluated(GSpan data) const { - return this->interpolate_to_evaluated(GVArray_For_GSpan(data)); + return this->interpolate_to_evaluated(GVArray::ForSpan(data)); } /** @@ -547,7 +545,7 @@ void Spline::sample_with_index_factors(const GVArray &src, blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); - const GVArray_Typed<T> src_typed = src.typed<T>(); + const VArray<T> src_typed = src.typed<T>(); MutableSpan<T> dst_typed = dst.typed<T>(); if (src.size() == 1) { dst_typed.fill(src_typed[0]); diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc index 166fe0f5464..28db3da65d0 100644 --- a/source/blender/blenkernel/intern/spline_bezier.cc +++ b/source/blender/blenkernel/intern/spline_bezier.cc @@ -25,9 +25,8 @@ using blender::float3; using blender::IndexRange; using blender::MutableSpan; using blender::Span; +using blender::VArray; using blender::fn::GVArray; -using blender::fn::GVArray_For_ArrayContainer; -using blender::fn::GVArrayPtr; void BezierSpline::copy_settings(Spline &dst) const { @@ -702,26 +701,26 @@ static void interpolate_to_evaluated_impl(const BezierSpline &spline, } } -GVArrayPtr BezierSpline::interpolate_to_evaluated(const GVArray &src) const +GVArray BezierSpline::interpolate_to_evaluated(const GVArray &src) const { BLI_assert(src.size() == this->size()); if (src.is_single()) { - return src.shallow_copy(); + return src; } const int eval_size = this->evaluated_points_size(); if (eval_size == 1) { - return src.shallow_copy(); + return src; } - GVArrayPtr new_varray; + GVArray new_varray; blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) { Array<T> values(eval_size); interpolate_to_evaluated_impl<T>(*this, src.typed<T>(), values); - new_varray = std::make_unique<GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc index 6d30d8ba916..7fa332a0330 100644 --- a/source/blender/blenkernel/intern/spline_nurbs.cc +++ b/source/blender/blenkernel/intern/spline_nurbs.cc @@ -26,10 +26,8 @@ using blender::float3; using blender::IndexRange; using blender::MutableSpan; using blender::Span; +using blender::VArray; using blender::fn::GVArray; -using blender::fn::GVArray_For_ArrayContainer; -using blender::fn::GVArray_Typed; -using blender::fn::GVArrayPtr; void NURBSpline::copy_settings(Spline &dst) const { @@ -410,23 +408,23 @@ void interpolate_to_evaluated_impl(Span<NURBSpline::BasisCache> weights, mixer.finalize(); } -GVArrayPtr NURBSpline::interpolate_to_evaluated(const GVArray &src) const +GVArray NURBSpline::interpolate_to_evaluated(const GVArray &src) const { BLI_assert(src.size() == this->size()); if (src.is_single()) { - return src.shallow_copy(); + return src; } Span<BasisCache> basis_cache = this->calculate_basis_cache(); - GVArrayPtr new_varray; + GVArray new_varray; blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) { Array<T> values(this->evaluated_points_size()); interpolate_to_evaluated_impl<T>(basis_cache, src.typed<T>(), values); - new_varray = std::make_unique<GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); @@ -448,8 +446,8 @@ Span<float3> NURBSpline::evaluated_positions() const evaluated_position_cache_.resize(eval_size); /* TODO: Avoid copying the evaluated data from the temporary array. */ - GVArray_Typed<float3> evaluated = Spline::interpolate_to_evaluated(positions_.as_span()); - evaluated->materialize(evaluated_position_cache_); + VArray<float3> evaluated = Spline::interpolate_to_evaluated(positions_.as_span()); + evaluated.materialize(evaluated_position_cache_); position_cache_dirty_ = false; return evaluated_position_cache_; diff --git a/source/blender/blenkernel/intern/spline_poly.cc b/source/blender/blenkernel/intern/spline_poly.cc index 338b5d0ac9e..d495c977285 100644 --- a/source/blender/blenkernel/intern/spline_poly.cc +++ b/source/blender/blenkernel/intern/spline_poly.cc @@ -23,7 +23,6 @@ using blender::float3; using blender::MutableSpan; using blender::Span; using blender::fn::GVArray; -using blender::fn::GVArrayPtr; void PolySpline::copy_settings(Spline &UNUSED(dst)) const { @@ -122,9 +121,8 @@ Span<float3> PolySpline::evaluated_positions() const * the original data. Therefore the lifetime of the returned virtual array must not be longer than * the source data. */ -GVArrayPtr PolySpline::interpolate_to_evaluated(const GVArray &src) const +GVArray PolySpline::interpolate_to_evaluated(const GVArray &src) const { BLI_assert(src.size() == this->size()); - - return src.shallow_copy(); + return src; } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 0c58c8e8a5a..6796b1ac397 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -2020,7 +2020,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm, &dm->loopData, &ccgdm->dm.loopData, loopidx, w2, NULL, numVerts, loopindex2); loopindex2++; - /* Copy over poly data, e.g. mtexpoly. */ + /* Copy over poly data, e.g. #CD_FACEMAP. */ CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1); /* Set original index data. */ diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index c878abf0dff..a8c8eaa6a1c 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -142,7 +142,8 @@ static void texture_foreach_id(ID *id, LibraryForeachIDData *data) Tex *texture = (Tex *)id; if (texture->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - BKE_library_foreach_ID_embedded(data, (ID **)&texture->nodetree); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_library_foreach_ID_embedded(data, (ID **)&texture->nodetree)); } BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, texture->ima, IDWALK_CB_USER); } diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index fe03c5b817a..2f0a282a298 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -131,7 +131,8 @@ static void world_foreach_id(ID *id, LibraryForeachIDData *data) if (world->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - BKE_library_foreach_ID_embedded(data, (ID **)&world->nodetree); + BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( + data, BKE_library_foreach_ID_embedded(data, (ID **)&world->nodetree)); } } |