Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/attribute_access_intern.hh
| Show All 18 Lines | |||||
| #include "BLI_string_ref.hh" | #include "BLI_string_ref.hh" | ||||
| #include "BLI_vector.hh" | #include "BLI_vector.hh" | ||||
| #include "BLI_vector_set.hh" | #include "BLI_vector_set.hh" | ||||
| #include "BKE_geometry_set.hh" | #include "BKE_geometry_set.hh" | ||||
| namespace blender::bke { | namespace blender::bke { | ||||
| class ConstantReadAttribute final : public ReadAttribute { | using fn::GVArrayPtr; | ||||
| private: | using fn::GVMutableArrayPtr; | ||||
| void *value_; | |||||
| public: | |||||
| ConstantReadAttribute(AttributeDomain domain, | |||||
| const int64_t size, | |||||
| const CPPType &type, | |||||
| const void *value) | |||||
| : ReadAttribute(domain, type, size) | |||||
| { | |||||
| value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__); | |||||
| type.copy_to_uninitialized(value, value_); | |||||
| } | |||||
| ~ConstantReadAttribute() override | |||||
| { | |||||
| this->cpp_type_.destruct(value_); | |||||
| MEM_freeN(value_); | |||||
| } | |||||
| void get_internal(const int64_t UNUSED(index), void *r_value) const override | |||||
| { | |||||
| this->cpp_type_.copy_to_uninitialized(value_, r_value); | |||||
| } | |||||
| void initialize_span() const override | |||||
| { | |||||
| const int element_size = cpp_type_.size(); | |||||
| array_buffer_ = MEM_mallocN_aligned(size_ * element_size, cpp_type_.alignment(), __func__); | |||||
| array_is_temporary_ = true; | |||||
| cpp_type_.fill_uninitialized(value_, array_buffer_, size_); | |||||
| } | |||||
| }; | |||||
| template<typename T> class ArrayReadAttribute final : public ReadAttribute { | |||||
| private: | |||||
| Span<T> data_; | |||||
| public: | |||||
| ArrayReadAttribute(AttributeDomain domain, Span<T> data) | |||||
| : ReadAttribute(domain, CPPType::get<T>(), data.size()), data_(data) | |||||
| { | |||||
| } | |||||
| void get_internal(const int64_t index, void *r_value) const override | |||||
| { | |||||
| new (r_value) T(data_[index]); | |||||
| } | |||||
| void initialize_span() const override | |||||
| { | |||||
| /* The data will not be modified, so this const_cast is fine. */ | |||||
| array_buffer_ = const_cast<T *>(data_.data()); | |||||
| array_is_temporary_ = false; | |||||
| } | |||||
| }; | |||||
| template<typename T> class OwnedArrayReadAttribute final : public ReadAttribute { | |||||
| private: | |||||
| Array<T> data_; | |||||
| public: | |||||
| OwnedArrayReadAttribute(AttributeDomain domain, Array<T> data) | |||||
| : ReadAttribute(domain, CPPType::get<T>(), data.size()), data_(std::move(data)) | |||||
| { | |||||
| } | |||||
| void get_internal(const int64_t index, void *r_value) const override | |||||
| { | |||||
| new (r_value) T(data_[index]); | |||||
| } | |||||
| void initialize_span() const override | |||||
| { | |||||
| /* The data will not be modified, so this const_cast is fine. */ | |||||
| array_buffer_ = const_cast<T *>(data_.data()); | |||||
| array_is_temporary_ = false; | |||||
| } | |||||
| }; | |||||
| template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)> | |||||
| class DerivedArrayReadAttribute final : public ReadAttribute { | |||||
| private: | |||||
| Span<StructT> data_; | |||||
| public: | |||||
| DerivedArrayReadAttribute(AttributeDomain domain, Span<StructT> data) | |||||
| : ReadAttribute(domain, CPPType::get<ElemT>(), data.size()), data_(data) | |||||
| { | |||||
| } | |||||
| void get_internal(const int64_t index, void *r_value) const override | |||||
| { | |||||
| const StructT &struct_value = data_[index]; | |||||
| const ElemT value = GetFunc(struct_value); | |||||
| new (r_value) ElemT(value); | |||||
| } | |||||
| }; | |||||
| template<typename T> class ArrayWriteAttribute final : public WriteAttribute { | |||||
| private: | |||||
| MutableSpan<T> data_; | |||||
| public: | |||||
| ArrayWriteAttribute(AttributeDomain domain, MutableSpan<T> data) | |||||
| : WriteAttribute(domain, CPPType::get<T>(), data.size()), data_(data) | |||||
| { | |||||
| } | |||||
| void get_internal(const int64_t index, void *r_value) const override | |||||
| { | |||||
| new (r_value) T(data_[index]); | |||||
| } | |||||
| void set_internal(const int64_t index, const void *value) override | |||||
| { | |||||
| data_[index] = *reinterpret_cast<const T *>(value); | |||||
| } | |||||
| void initialize_span(const bool UNUSED(write_only)) override | |||||
| { | |||||
| array_buffer_ = data_.data(); | |||||
| array_is_temporary_ = false; | |||||
| } | |||||
| void apply_span_if_necessary() override | |||||
| { | |||||
| /* Do nothing, because the span contains the attribute itself already. */ | |||||
| } | |||||
| }; | |||||
| template<typename StructT, | |||||
| typename ElemT, | |||||
| ElemT (*GetFunc)(const StructT &), | |||||
| void (*SetFunc)(StructT &, const ElemT &)> | |||||
| class DerivedArrayWriteAttribute final : public WriteAttribute { | |||||
| private: | |||||
| MutableSpan<StructT> data_; | |||||
| public: | |||||
| DerivedArrayWriteAttribute(AttributeDomain domain, MutableSpan<StructT> data) | |||||
| : WriteAttribute(domain, CPPType::get<ElemT>(), data.size()), data_(data) | |||||
| { | |||||
| } | |||||
| void get_internal(const int64_t index, void *r_value) const override | |||||
| { | |||||
| const StructT &struct_value = data_[index]; | |||||
| const ElemT value = GetFunc(struct_value); | |||||
| new (r_value) ElemT(value); | |||||
| } | |||||
| void set_internal(const int64_t index, const void *value) override | |||||
| { | |||||
| StructT &struct_value = data_[index]; | |||||
| const ElemT &typed_value = *reinterpret_cast<const ElemT *>(value); | |||||
| SetFunc(struct_value, typed_value); | |||||
| } | |||||
| }; | |||||
| /** | /** | ||||
| * Utility to group together multiple functions that are used to access custom data on geometry | * Utility to group together multiple functions that are used to access custom data on geometry | ||||
| * components in a generic way. | * components in a generic way. | ||||
| */ | */ | ||||
| struct CustomDataAccessInfo { | struct CustomDataAccessInfo { | ||||
| using CustomDataGetter = CustomData *(*)(GeometryComponent &component); | using CustomDataGetter = CustomData *(*)(GeometryComponent &component); | ||||
| using ConstCustomDataGetter = const CustomData *(*)(const GeometryComponent &component); | using ConstCustomDataGetter = const CustomData *(*)(const GeometryComponent &component); | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | BuiltinAttributeProvider(std::string name, | ||||
| domain_(domain), | domain_(domain), | ||||
| data_type_(data_type), | data_type_(data_type), | ||||
| createable_(createable), | createable_(createable), | ||||
| writable_(writable), | writable_(writable), | ||||
| deletable_(deletable) | deletable_(deletable) | ||||
| { | { | ||||
| } | } | ||||
| virtual ReadAttributePtr try_get_for_read(const GeometryComponent &component) const = 0; | virtual GVArrayPtr try_get_for_read(const GeometryComponent &component) const = 0; | ||||
| virtual WriteAttributePtr try_get_for_write(GeometryComponent &component) const = 0; | virtual GVMutableArrayPtr try_get_for_write(GeometryComponent &component) const = 0; | ||||
| virtual bool try_delete(GeometryComponent &component) const = 0; | virtual bool try_delete(GeometryComponent &component) const = 0; | ||||
| virtual bool try_create(GeometryComponent &UNUSED(component)) const = 0; | virtual bool try_create(GeometryComponent &UNUSED(component), | ||||
| const AttributeInit &UNUSED(initializer)) const = 0; | |||||
| virtual bool exists(const GeometryComponent &component) const = 0; | virtual bool exists(const GeometryComponent &component) const = 0; | ||||
| StringRefNull name() const | StringRefNull name() const | ||||
| { | { | ||||
| return name_; | return name_; | ||||
| } | } | ||||
| AttributeDomain domain() const | AttributeDomain domain() const | ||||
| { | { | ||||
| return domain_; | return domain_; | ||||
| } | } | ||||
| CustomDataType data_type() const | CustomDataType data_type() const | ||||
| { | { | ||||
| return data_type_; | return data_type_; | ||||
| } | } | ||||
| }; | }; | ||||
| /** | /** | ||||
| * A #DynamicAttributesProvider manages a set of named attributes on a geometry component. Each | * A #DynamicAttributesProvider manages a set of named attributes on a geometry component. Each | ||||
| * attribute has a name, domain and type. | * attribute has a name, domain and type. | ||||
| */ | */ | ||||
| class DynamicAttributesProvider { | class DynamicAttributesProvider { | ||||
| public: | public: | ||||
| virtual ReadAttributePtr try_get_for_read(const GeometryComponent &component, | virtual ReadAttributeLookup try_get_for_read(const GeometryComponent &component, | ||||
| const StringRef attribute_name) const = 0; | const StringRef attribute_name) const = 0; | ||||
| virtual WriteAttributePtr try_get_for_write(GeometryComponent &component, | virtual WriteAttributeLookup try_get_for_write(GeometryComponent &component, | ||||
| const StringRef attribute_name) const = 0; | const StringRef attribute_name) const = 0; | ||||
| virtual bool try_delete(GeometryComponent &component, const StringRef attribute_name) const = 0; | virtual bool try_delete(GeometryComponent &component, const StringRef attribute_name) const = 0; | ||||
| virtual bool try_create(GeometryComponent &UNUSED(component), | virtual bool try_create(GeometryComponent &UNUSED(component), | ||||
| const StringRef UNUSED(attribute_name), | const StringRef UNUSED(attribute_name), | ||||
| const AttributeDomain UNUSED(domain), | const AttributeDomain UNUSED(domain), | ||||
| const CustomDataType UNUSED(data_type)) const | const CustomDataType UNUSED(data_type), | ||||
| const AttributeInit &UNUSED(initializer)) const | |||||
| { | { | ||||
| /* Some providers should not create new attributes. */ | /* Some providers should not create new attributes. */ | ||||
| return false; | return false; | ||||
| }; | }; | ||||
| virtual bool foreach_attribute(const GeometryComponent &component, | virtual bool foreach_attribute(const GeometryComponent &component, | ||||
| const AttributeForeachCallback callback) const = 0; | const AttributeForeachCallback callback) const = 0; | ||||
| virtual void foreach_domain(const FunctionRef<void(AttributeDomain)> callback) const = 0; | virtual void foreach_domain(const FunctionRef<void(AttributeDomain)> callback) const = 0; | ||||
| Show All 12 Lines | |||||
| public: | public: | ||||
| CustomDataAttributeProvider(const AttributeDomain domain, | CustomDataAttributeProvider(const AttributeDomain domain, | ||||
| const CustomDataAccessInfo custom_data_access) | const CustomDataAccessInfo custom_data_access) | ||||
| : domain_(domain), custom_data_access_(custom_data_access) | : domain_(domain), custom_data_access_(custom_data_access) | ||||
| { | { | ||||
| } | } | ||||
| ReadAttributePtr try_get_for_read(const GeometryComponent &component, | ReadAttributeLookup try_get_for_read(const GeometryComponent &component, | ||||
| const StringRef attribute_name) const final; | const StringRef attribute_name) const final; | ||||
| WriteAttributePtr try_get_for_write(GeometryComponent &component, | WriteAttributeLookup try_get_for_write(GeometryComponent &component, | ||||
| const StringRef attribute_name) const final; | const StringRef attribute_name) const final; | ||||
| bool try_delete(GeometryComponent &component, const StringRef attribute_name) const final; | bool try_delete(GeometryComponent &component, const StringRef attribute_name) const final; | ||||
| bool try_create(GeometryComponent &component, | bool try_create(GeometryComponent &component, | ||||
| const StringRef attribute_name, | const StringRef attribute_name, | ||||
| const AttributeDomain domain, | const AttributeDomain domain, | ||||
| const CustomDataType data_type) const final; | const CustomDataType data_type, | ||||
| const AttributeInit &initializer) const final; | |||||
| bool foreach_attribute(const GeometryComponent &component, | bool foreach_attribute(const GeometryComponent &component, | ||||
| const AttributeForeachCallback callback) const final; | const AttributeForeachCallback callback) const final; | ||||
| void foreach_domain(const FunctionRef<void(AttributeDomain)> callback) const final | void foreach_domain(const FunctionRef<void(AttributeDomain)> callback) const final | ||||
| { | { | ||||
| callback(domain_); | callback(domain_); | ||||
| } | } | ||||
| private: | private: | ||||
| template<typename T> | template<typename T> | ||||
| ReadAttributePtr layer_to_read_attribute(const CustomDataLayer &layer, | ReadAttributeLookup layer_to_read_attribute(const CustomDataLayer &layer, | ||||
| const int domain_size) const | const int domain_size) const | ||||
| { | { | ||||
| return std::make_unique<ArrayReadAttribute<T>>( | return {std::make_unique<fn::GVArray_For_Span<T>>( | ||||
| domain_, Span(static_cast<const T *>(layer.data), domain_size)); | Span(static_cast<const T *>(layer.data), domain_size)), | ||||
| domain_}; | |||||
| } | } | ||||
| template<typename T> | template<typename T> | ||||
| WriteAttributePtr layer_to_write_attribute(CustomDataLayer &layer, const int domain_size) const | WriteAttributeLookup layer_to_write_attribute(CustomDataLayer &layer, | ||||
| const int domain_size) const | |||||
| { | { | ||||
| return std::make_unique<ArrayWriteAttribute<T>>( | return {std::make_unique<fn::GVMutableArray_For_MutableSpan<T>>( | ||||
| domain_, MutableSpan(static_cast<T *>(layer.data), domain_size)); | MutableSpan(static_cast<T *>(layer.data), domain_size)), | ||||
| domain_}; | |||||
| } | } | ||||
| bool type_is_supported(CustomDataType data_type) const | bool type_is_supported(CustomDataType data_type) const | ||||
| { | { | ||||
| return ((1ULL << data_type) & supported_types_mask) != 0; | return ((1ULL << data_type) & supported_types_mask) != 0; | ||||
| } | } | ||||
| }; | }; | ||||
| /** | /** | ||||
| * This attribute provider is used for uv maps and vertex colors. | * This attribute provider is used for uv maps and vertex colors. | ||||
| */ | */ | ||||
| class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider { | class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider { | ||||
| private: | private: | ||||
| using AsReadAttribute = ReadAttributePtr (*)(const void *data, const int domain_size); | using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size); | ||||
| using AsWriteAttribute = WriteAttributePtr (*)(void *data, const int domain_size); | using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size); | ||||
| const AttributeDomain domain_; | const AttributeDomain domain_; | ||||
| const CustomDataType attribute_type_; | const CustomDataType attribute_type_; | ||||
| const CustomDataType stored_type_; | const CustomDataType stored_type_; | ||||
| const CustomDataAccessInfo custom_data_access_; | const CustomDataAccessInfo custom_data_access_; | ||||
| const AsReadAttribute as_read_attribute_; | const AsReadAttribute as_read_attribute_; | ||||
| const AsWriteAttribute as_write_attribute_; | const AsWriteAttribute as_write_attribute_; | ||||
| public: | public: | ||||
| NamedLegacyCustomDataProvider(const AttributeDomain domain, | NamedLegacyCustomDataProvider(const AttributeDomain domain, | ||||
| const CustomDataType attribute_type, | const CustomDataType attribute_type, | ||||
| const CustomDataType stored_type, | const CustomDataType stored_type, | ||||
| const CustomDataAccessInfo custom_data_access, | const CustomDataAccessInfo custom_data_access, | ||||
| const AsReadAttribute as_read_attribute, | const AsReadAttribute as_read_attribute, | ||||
| const AsWriteAttribute as_write_attribute) | const AsWriteAttribute as_write_attribute) | ||||
| : domain_(domain), | : domain_(domain), | ||||
| attribute_type_(attribute_type), | attribute_type_(attribute_type), | ||||
| stored_type_(stored_type), | stored_type_(stored_type), | ||||
| custom_data_access_(custom_data_access), | custom_data_access_(custom_data_access), | ||||
| as_read_attribute_(as_read_attribute), | as_read_attribute_(as_read_attribute), | ||||
| as_write_attribute_(as_write_attribute) | as_write_attribute_(as_write_attribute) | ||||
| { | { | ||||
| } | } | ||||
| ReadAttributePtr try_get_for_read(const GeometryComponent &component, | ReadAttributeLookup try_get_for_read(const GeometryComponent &component, | ||||
| const StringRef attribute_name) const final; | const StringRef attribute_name) const final; | ||||
| WriteAttributePtr try_get_for_write(GeometryComponent &component, | WriteAttributeLookup try_get_for_write(GeometryComponent &component, | ||||
| const StringRef attribute_name) const final; | const StringRef attribute_name) const final; | ||||
| bool try_delete(GeometryComponent &component, const StringRef attribute_name) const final; | bool try_delete(GeometryComponent &component, const StringRef attribute_name) const final; | ||||
| bool foreach_attribute(const GeometryComponent &component, | bool foreach_attribute(const GeometryComponent &component, | ||||
| const AttributeForeachCallback callback) const final; | const AttributeForeachCallback callback) const final; | ||||
| void foreach_domain(const FunctionRef<void(AttributeDomain)> callback) const final; | void foreach_domain(const FunctionRef<void(AttributeDomain)> callback) const final; | ||||
| }; | }; | ||||
| /** | /** | ||||
| * This provider is used to provide access to builtin attributes. It supports making internal types | * This provider is used to provide access to builtin attributes. It supports making internal types | ||||
| * available as different types. For example, the vertex position attribute is stored as part of | * available as different types. For example, the vertex position attribute is stored as part of | ||||
| * the #MVert struct, but is exposed as float3 attribute. | * the #MVert struct, but is exposed as float3 attribute. | ||||
| */ | */ | ||||
| class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider { | class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider { | ||||
| using AsReadAttribute = ReadAttributePtr (*)(const void *data, const int domain_size); | using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size); | ||||
| using AsWriteAttribute = WriteAttributePtr (*)(void *data, const int domain_size); | using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size); | ||||
| using UpdateOnRead = void (*)(const GeometryComponent &component); | using UpdateOnRead = void (*)(const GeometryComponent &component); | ||||
| using UpdateOnWrite = void (*)(GeometryComponent &component); | using UpdateOnWrite = void (*)(GeometryComponent &component); | ||||
| const CustomDataType stored_type_; | const CustomDataType stored_type_; | ||||
| const CustomDataAccessInfo custom_data_access_; | const CustomDataAccessInfo custom_data_access_; | ||||
| const AsReadAttribute as_read_attribute_; | const AsReadAttribute as_read_attribute_; | ||||
| const AsWriteAttribute as_write_attribute_; | const AsWriteAttribute as_write_attribute_; | ||||
| const UpdateOnWrite update_on_write_; | const UpdateOnWrite update_on_write_; | ||||
| Show All 14 Lines | BuiltinCustomDataLayerProvider(std::string attribute_name, | ||||
| stored_type_(stored_type), | stored_type_(stored_type), | ||||
| custom_data_access_(custom_data_access), | custom_data_access_(custom_data_access), | ||||
| as_read_attribute_(as_read_attribute), | as_read_attribute_(as_read_attribute), | ||||
| as_write_attribute_(as_write_attribute), | as_write_attribute_(as_write_attribute), | ||||
| update_on_write_(update_on_write) | update_on_write_(update_on_write) | ||||
| { | { | ||||
| } | } | ||||
| ReadAttributePtr try_get_for_read(const GeometryComponent &component) const final; | GVArrayPtr try_get_for_read(const GeometryComponent &component) const final; | ||||
| WriteAttributePtr try_get_for_write(GeometryComponent &component) const final; | GVMutableArrayPtr try_get_for_write(GeometryComponent &component) const final; | ||||
| bool try_delete(GeometryComponent &component) const final; | bool try_delete(GeometryComponent &component) const final; | ||||
| bool try_create(GeometryComponent &component) const final; | bool try_create(GeometryComponent &component, const AttributeInit &initializer) const final; | ||||
| bool exists(const GeometryComponent &component) const final; | bool exists(const GeometryComponent &component) const final; | ||||
| }; | }; | ||||
| /** | /** | ||||
| * This is a container for multiple attribute providers that are used by one geometry component | * This is a container for multiple attribute providers that are used by one geometry component | ||||
| * type (e.g. there is a set of attribute providers for mesh components). | * type (e.g. there is a set of attribute providers for mesh components). | ||||
| */ | */ | ||||
| class ComponentAttributeProviders { | class ComponentAttributeProviders { | ||||
| ▲ Show 20 Lines • Show All 50 Lines • Show Last 20 Lines | |||||