Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/attribute_access.cc
| Show First 20 Lines • Show All 354 Lines • ▼ Show 20 Lines | GVArrayPtr BuiltinCustomDataLayerProvider::try_get_for_read( | ||||
| if (data == nullptr) { | if (data == nullptr) { | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| const int domain_size = component.attribute_domain_size(domain_); | const int domain_size = component.attribute_domain_size(domain_); | ||||
| return as_read_attribute_(data, domain_size); | return as_read_attribute_(data, domain_size); | ||||
| } | } | ||||
| GVMutableArrayPtr BuiltinCustomDataLayerProvider::try_get_for_write( | WriteAttributeLookup BuiltinCustomDataLayerProvider::try_get_for_write( | ||||
| GeometryComponent &component) const | GeometryComponent &component) const | ||||
| { | { | ||||
| if (writable_ != Writable) { | if (writable_ != Writable) { | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| CustomData *custom_data = custom_data_access_.get_custom_data(component); | CustomData *custom_data = custom_data_access_.get_custom_data(component); | ||||
| if (custom_data == nullptr) { | if (custom_data == nullptr) { | ||||
| return {}; | return {}; | ||||
| Show All 20 Lines | else { | ||||
| new_data = CustomData_duplicate_referenced_layer(custom_data, stored_type_, domain_size); | new_data = CustomData_duplicate_referenced_layer(custom_data, stored_type_, domain_size); | ||||
| } | } | ||||
| if (data != new_data) { | if (data != new_data) { | ||||
| custom_data_access_.update_custom_data_pointers(component); | custom_data_access_.update_custom_data_pointers(component); | ||||
| data = new_data; | data = new_data; | ||||
| } | } | ||||
| std::function<void()> tag_modified_fn; | |||||
| if (update_on_write_ != nullptr) { | if (update_on_write_ != nullptr) { | ||||
| update_on_write_(component); | tag_modified_fn = [component = &component, update = update_on_write_]() { | ||||
| update(*component); | |||||
| }; | |||||
| } | } | ||||
| return as_write_attribute_(data, domain_size); | |||||
| return {as_write_attribute_(data, domain_size), domain_, std::move(tag_modified_fn)}; | |||||
| } | } | ||||
| bool BuiltinCustomDataLayerProvider::try_delete(GeometryComponent &component) const | bool BuiltinCustomDataLayerProvider::try_delete(GeometryComponent &component) const | ||||
| { | { | ||||
| if (deletable_ != Deletable) { | if (deletable_ != Deletable) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| CustomData *custom_data = custom_data_access_.get_custom_data(component); | CustomData *custom_data = custom_data_access_.get_custom_data(component); | ||||
| ▲ Show 20 Lines • Show All 508 Lines • ▼ Show 20 Lines | blender::bke::WriteAttributeLookup GeometryComponent::attribute_try_get_for_write( | ||||
| const ComponentAttributeProviders *providers = this->get_attribute_providers(); | const ComponentAttributeProviders *providers = this->get_attribute_providers(); | ||||
| if (providers == nullptr) { | if (providers == nullptr) { | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| if (attribute_id.is_named()) { | if (attribute_id.is_named()) { | ||||
| const BuiltinAttributeProvider *builtin_provider = | const BuiltinAttributeProvider *builtin_provider = | ||||
| providers->builtin_attribute_providers().lookup_default_as(attribute_id.name(), nullptr); | providers->builtin_attribute_providers().lookup_default_as(attribute_id.name(), nullptr); | ||||
| if (builtin_provider != nullptr) { | if (builtin_provider != nullptr) { | ||||
| return {builtin_provider->try_get_for_write(*this), builtin_provider->domain()}; | return builtin_provider->try_get_for_write(*this); | ||||
| } | } | ||||
| } | } | ||||
| for (const DynamicAttributesProvider *dynamic_provider : | for (const DynamicAttributesProvider *dynamic_provider : | ||||
| providers->dynamic_attribute_providers()) { | providers->dynamic_attribute_providers()) { | ||||
| WriteAttributeLookup attribute = dynamic_provider->try_get_for_write(*this, attribute_id); | WriteAttributeLookup attribute = dynamic_provider->try_get_for_write(*this, attribute_id); | ||||
| if (attribute) { | if (attribute) { | ||||
| return attribute; | return attribute; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 307 Lines • ▼ Show 20 Lines | if (!component.attribute_try_create(attribute_id, domain, data_type, AttributeInitDefault())) { | ||||
| return; | return; | ||||
| } | } | ||||
| WriteAttributeLookup write_attribute = component.attribute_try_get_for_write(attribute_id); | WriteAttributeLookup write_attribute = component.attribute_try_get_for_write(attribute_id); | ||||
| BUFFER_FOR_CPP_TYPE_VALUE(varray.type(), buffer); | BUFFER_FOR_CPP_TYPE_VALUE(varray.type(), buffer); | ||||
| for (const int i : IndexRange(varray.size())) { | for (const int i : IndexRange(varray.size())) { | ||||
| varray.get(i, buffer); | 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(); | |||||
| } | |||||
| } | |||||
| static std::function<void(OutputAttribute &)> get_simple_output_attribute_save_method( | |||||
| const blender::bke::WriteAttributeLookup &attribute) | |||||
| { | |||||
| if (!attribute.tag_modified_fn) { | |||||
| return {}; | |||||
| } | |||||
| return [tag_modified_fn = attribute.tag_modified_fn](OutputAttribute &UNUSED(attribute)) { | |||||
| tag_modified_fn(); | |||||
| }; | |||||
| } | } | ||||
| static OutputAttribute create_output_attribute(GeometryComponent &component, | static OutputAttribute create_output_attribute(GeometryComponent &component, | ||||
| const AttributeIDRef &attribute_id, | const AttributeIDRef &attribute_id, | ||||
| const AttributeDomain domain, | const AttributeDomain domain, | ||||
| const CustomDataType data_type, | const CustomDataType data_type, | ||||
| const bool ignore_old_values, | const bool ignore_old_values, | ||||
| const void *default_value) | const void *default_value) | ||||
| Show All 28 Lines | if (!attribute) { | ||||
| /* Builtin attribute does not exist and can't be created. */ | /* Builtin attribute does not exist and can't be created. */ | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| } | } | ||||
| if (attribute.domain != domain) { | if (attribute.domain != domain) { | ||||
| /* Builtin attribute is on different domain. */ | /* Builtin attribute is on different domain. */ | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| GVMutableArrayPtr varray = std::move(attribute.varray); | GVMutableArrayPtr varray = std::move(attribute.varray); | ||||
| if (varray->type() == *cpp_type) { | if (varray->type() == *cpp_type) { | ||||
| /* Builtin attribute matches exactly. */ | /* Builtin attribute matches exactly. */ | ||||
| return OutputAttribute(std::move(varray), domain, {}, ignore_old_values); | return OutputAttribute(std::move(varray), | ||||
| domain, | |||||
| get_simple_output_attribute_save_method(attribute), | |||||
| ignore_old_values); | |||||
| } | } | ||||
| /* Builtin attribute is on the same domain but has a different data type. */ | /* Builtin attribute is on the same domain but has a different data type. */ | ||||
| varray = conversions.try_convert(std::move(varray), *cpp_type); | varray = conversions.try_convert(std::move(varray), *cpp_type); | ||||
| return OutputAttribute(std::move(varray), domain, {}, ignore_old_values); | return OutputAttribute(std::move(varray), | ||||
| domain, | |||||
| get_simple_output_attribute_save_method(attribute), | |||||
| ignore_old_values); | |||||
| } | } | ||||
| const int domain_size = component.attribute_domain_size(domain); | const int domain_size = component.attribute_domain_size(domain); | ||||
| WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_id); | WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_id); | ||||
| if (!attribute) { | if (!attribute) { | ||||
| if (default_value) { | if (default_value) { | ||||
| const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value}; | const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value}; | ||||
| component.attribute_try_create( | component.attribute_try_create( | ||||
| attribute_id, domain, data_type, AttributeInitVArray(&default_varray)); | attribute_id, domain, data_type, AttributeInitVArray(&default_varray)); | ||||
| } | } | ||||
| else { | else { | ||||
| component.attribute_try_create(attribute_id, domain, data_type, AttributeInitDefault()); | component.attribute_try_create(attribute_id, domain, data_type, AttributeInitDefault()); | ||||
| } | } | ||||
| attribute = component.attribute_try_get_for_write(attribute_id); | attribute = component.attribute_try_get_for_write(attribute_id); | ||||
| if (!attribute) { | if (!attribute) { | ||||
| /* Can't create the attribute. */ | /* Can't create the attribute. */ | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| } | } | ||||
| if (attribute.domain == domain && attribute.varray->type() == *cpp_type) { | if (attribute.domain == domain && attribute.varray->type() == *cpp_type) { | ||||
| /* Existing generic attribute matches exactly. */ | /* Existing generic attribute matches exactly. */ | ||||
| return OutputAttribute(std::move(attribute.varray), domain, {}, ignore_old_values); | |||||
| return OutputAttribute(std::move(attribute.varray), | |||||
| domain, | |||||
| get_simple_output_attribute_save_method(attribute), | |||||
| ignore_old_values); | |||||
| } | } | ||||
| /* Allocate a new array that lives next to the existing attribute. It will overwrite the existing | /* Allocate a new array that lives next to the existing attribute. It will overwrite the existing | ||||
| * attribute after processing is done. */ | * attribute after processing is done. */ | ||||
| void *data = MEM_mallocN_aligned( | void *data = MEM_mallocN_aligned( | ||||
| cpp_type->size() * domain_size, cpp_type->alignment(), __func__); | cpp_type->size() * domain_size, cpp_type->alignment(), __func__); | ||||
| if (ignore_old_values) { | if (ignore_old_values) { | ||||
| /* This does nothing for trivially constructible types, but is necessary for correctness. */ | /* This does nothing for trivially constructible types, but is necessary for correctness. */ | ||||
| ▲ Show 20 Lines • Show All 154 Lines • Show Last 20 Lines | |||||