Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/attribute_access.cc')
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc977
1 files changed, 269 insertions, 708 deletions
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index e86bac21084..a834b77d65e 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -2,7 +2,6 @@
#include <utility>
-#include "BKE_attribute_access.hh"
#include "BKE_attribute_math.hh"
#include "BKE_customdata.h"
#include "BKE_deform.h"
@@ -26,8 +25,6 @@
#include "attribute_access_intern.hh"
-static CLG_LogRef LOG = {"bke.attribute_access"};
-
using blender::float3;
using blender::GMutableSpan;
using blender::GSpan;
@@ -36,7 +33,6 @@ using blender::Set;
using blender::StringRef;
using blender::StringRefNull;
using blender::bke::AttributeIDRef;
-using blender::bke::OutputAttribute;
namespace blender::bke {
@@ -55,7 +51,15 @@ std::ostream &operator<<(std::ostream &stream, const AttributeIDRef &attribute_i
return stream;
}
-static int attribute_data_type_complexity(const CustomDataType data_type)
+const char *no_procedural_access_message =
+ "This attribute can not be accessed in a procedural context";
+
+bool allow_procedural_attribute_access(StringRef attribute_name)
+{
+ return !attribute_name.startswith(".selection");
+}
+
+static int attribute_data_type_complexity(const eCustomDataType data_type)
{
switch (data_type) {
case CD_PROP_BOOL:
@@ -85,12 +89,12 @@ static int attribute_data_type_complexity(const CustomDataType data_type)
}
}
-CustomDataType attribute_data_type_highest_complexity(Span<CustomDataType> data_types)
+eCustomDataType attribute_data_type_highest_complexity(Span<eCustomDataType> data_types)
{
int highest_complexity = INT_MIN;
- CustomDataType most_complex_type = CD_PROP_COLOR;
+ eCustomDataType most_complex_type = CD_PROP_COLOR;
- for (const CustomDataType data_type : data_types) {
+ for (const eCustomDataType data_type : data_types) {
const int complexity = attribute_data_type_complexity(data_type);
if (complexity > highest_complexity) {
highest_complexity = complexity;
@@ -105,7 +109,7 @@ CustomDataType attribute_data_type_highest_complexity(Span<CustomDataType> data_
* \note Generally the order should mirror the order of the domains
* established in each component's ComponentAttributeProviders.
*/
-static int attribute_domain_priority(const AttributeDomain domain)
+static int attribute_domain_priority(const eAttrDomain domain)
{
switch (domain) {
case ATTR_DOMAIN_INSTANCE:
@@ -127,12 +131,12 @@ static int attribute_domain_priority(const AttributeDomain domain)
}
}
-AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains)
+eAttrDomain attribute_domain_highest_priority(Span<eAttrDomain> domains)
{
int highest_priority = INT_MIN;
- AttributeDomain highest_priority_domain = ATTR_DOMAIN_CORNER;
+ eAttrDomain highest_priority_domain = ATTR_DOMAIN_CORNER;
- for (const AttributeDomain domain : domains) {
+ for (const eAttrDomain domain : domains) {
const int priority = attribute_domain_priority(domain);
if (priority > highest_priority) {
highest_priority = priority;
@@ -143,37 +147,6 @@ AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains)
return highest_priority_domain;
}
-GMutableSpan OutputAttribute::as_span()
-{
- if (!optional_span_varray_) {
- const bool materialize_old_values = !ignore_old_values_;
- optional_span_varray_ = std::make_unique<GVMutableArray_GSpan>(varray_,
- materialize_old_values);
- }
- GVMutableArray_GSpan &span_varray = *optional_span_varray_;
- return span_varray;
-}
-
-void OutputAttribute::save()
-{
- save_has_been_called_ = true;
- if (optional_span_varray_) {
- optional_span_varray_->save();
- }
- if (save_) {
- save_(*this);
- }
-}
-
-OutputAttribute::~OutputAttribute()
-{
- if (!save_has_been_called_) {
- if (varray_) {
- std::cout << "Warning: Call `save()` to make sure that changes persist in all cases.\n";
- }
- }
-}
-
static AttributeIDRef attribute_id_from_custom_data_layer(const CustomDataLayer &layer)
{
if (layer.anonymous_id != nullptr) {
@@ -183,7 +156,7 @@ static AttributeIDRef attribute_id_from_custom_data_layer(const CustomDataLayer
}
static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data,
- const CustomDataType data_type,
+ const eCustomDataType data_type,
const int domain_num,
const AttributeInit &initializer)
{
@@ -218,7 +191,7 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
}
static void *add_generic_custom_data_layer(CustomData &custom_data,
- const CustomDataType data_type,
+ const eCustomDataType data_type,
const eCDAllocType alloctype,
void *layer_data,
const int domain_num,
@@ -237,7 +210,7 @@ static void *add_generic_custom_data_layer(CustomData &custom_data,
static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attribute_id,
CustomData &custom_data,
- const CustomDataType data_type,
+ const eCustomDataType data_type,
const int domain_num,
const AttributeInit &initializer)
{
@@ -285,9 +258,9 @@ static bool custom_data_layer_matches_attribute_id(const CustomDataLayer &layer,
return layer.name == attribute_id.name();
}
-GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const GeometryComponent &component) const
+GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const void *owner) const
{
- const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
+ const CustomData *custom_data = custom_data_access_.get_const_custom_data(owner);
if (custom_data == nullptr) {
return {};
}
@@ -303,21 +276,20 @@ GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const GeometryComponent
return {};
}
- const int domain_num = component.attribute_domain_num(domain_);
- return as_read_attribute_(data, domain_num);
+ const int element_num = custom_data_access_.get_element_num(owner);
+ return as_read_attribute_(data, element_num);
}
-WriteAttributeLookup BuiltinCustomDataLayerProvider::try_get_for_write(
- GeometryComponent &component) const
+GAttributeWriter BuiltinCustomDataLayerProvider::try_get_for_write(void *owner) const
{
if (writable_ != Writable) {
return {};
}
- CustomData *custom_data = custom_data_access_.get_custom_data(component);
+ CustomData *custom_data = custom_data_access_.get_custom_data(owner);
if (custom_data == nullptr) {
return {};
}
- const int domain_num = component.attribute_domain_num(domain_);
+ const int element_num = custom_data_access_.get_element_num(owner);
void *data;
if (stored_as_named_attribute_) {
@@ -333,75 +305,70 @@ WriteAttributeLookup BuiltinCustomDataLayerProvider::try_get_for_write(
void *new_data;
if (stored_as_named_attribute_) {
new_data = CustomData_duplicate_referenced_layer_named(
- custom_data, stored_type_, name_.c_str(), domain_num);
+ custom_data, stored_type_, name_.c_str(), element_num);
}
else {
- new_data = CustomData_duplicate_referenced_layer(custom_data, stored_type_, domain_num);
+ new_data = CustomData_duplicate_referenced_layer(custom_data, stored_type_, element_num);
}
if (data != new_data) {
if (custom_data_access_.update_custom_data_pointers) {
- custom_data_access_.update_custom_data_pointers(component);
+ custom_data_access_.update_custom_data_pointers(owner);
}
data = new_data;
}
std::function<void()> tag_modified_fn;
if (update_on_write_ != nullptr) {
- tag_modified_fn = [component = &component, update = update_on_write_]() {
- update(*component);
- };
+ tag_modified_fn = [owner, update = update_on_write_]() { update(owner); };
}
- return {as_write_attribute_(data, domain_num), domain_, std::move(tag_modified_fn)};
+ return {as_write_attribute_(data, element_num), domain_, std::move(tag_modified_fn)};
}
-bool BuiltinCustomDataLayerProvider::try_delete(GeometryComponent &component) const
+bool BuiltinCustomDataLayerProvider::try_delete(void *owner) const
{
if (deletable_ != Deletable) {
return false;
}
- CustomData *custom_data = custom_data_access_.get_custom_data(component);
+ CustomData *custom_data = custom_data_access_.get_custom_data(owner);
if (custom_data == nullptr) {
return {};
}
- const int domain_num = component.attribute_domain_num(domain_);
- int layer_index;
+ const int element_num = custom_data_access_.get_element_num(owner);
if (stored_as_named_attribute_) {
- for (const int i : IndexRange(custom_data->totlayer)) {
- if (custom_data_layer_matches_attribute_id(custom_data->layers[i], name_)) {
- layer_index = i;
- break;
+ if (CustomData_free_layer_named(custom_data, name_.c_str(), element_num)) {
+ if (custom_data_access_.update_custom_data_pointers) {
+ custom_data_access_.update_custom_data_pointers(owner);
}
+ return true;
}
- }
- else {
- layer_index = CustomData_get_layer_index(custom_data, stored_type_);
+ return false;
}
- const bool delete_success = CustomData_free_layer(
- custom_data, stored_type_, domain_num, layer_index);
- if (delete_success) {
+ const int layer_index = CustomData_get_layer_index(custom_data, stored_type_);
+ if (CustomData_free_layer(custom_data, stored_type_, element_num, layer_index)) {
if (custom_data_access_.update_custom_data_pointers) {
- custom_data_access_.update_custom_data_pointers(component);
+ custom_data_access_.update_custom_data_pointers(owner);
}
+ return true;
}
- return delete_success;
+ return false;
}
-bool BuiltinCustomDataLayerProvider::try_create(GeometryComponent &component,
+bool BuiltinCustomDataLayerProvider::try_create(void *owner,
const AttributeInit &initializer) const
{
if (createable_ != Creatable) {
return false;
}
- CustomData *custom_data = custom_data_access_.get_custom_data(component);
+ CustomData *custom_data = custom_data_access_.get_custom_data(owner);
if (custom_data == nullptr) {
return false;
}
- const int domain_num = component.attribute_domain_num(domain_);
+ const int element_num = custom_data_access_.get_element_num(owner);
bool success;
if (stored_as_named_attribute_) {
if (CustomData_get_layer_named(custom_data, data_type_, name_.c_str())) {
@@ -409,7 +376,7 @@ bool BuiltinCustomDataLayerProvider::try_create(GeometryComponent &component,
return false;
}
success = add_custom_data_layer_from_attribute_init(
- name_, *custom_data, stored_type_, domain_num, initializer);
+ name_, *custom_data, stored_type_, element_num, initializer);
}
else {
if (CustomData_get_layer(custom_data, stored_type_) != nullptr) {
@@ -417,19 +384,19 @@ bool BuiltinCustomDataLayerProvider::try_create(GeometryComponent &component,
return false;
}
success = add_builtin_type_custom_data_layer_from_init(
- *custom_data, stored_type_, domain_num, initializer);
+ *custom_data, stored_type_, element_num, initializer);
}
if (success) {
if (custom_data_access_.update_custom_data_pointers) {
- custom_data_access_.update_custom_data_pointers(component);
+ custom_data_access_.update_custom_data_pointers(owner);
}
}
return success;
}
-bool BuiltinCustomDataLayerProvider::exists(const GeometryComponent &component) const
+bool BuiltinCustomDataLayerProvider::exists(const void *owner) const
{
- const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
+ const CustomData *custom_data = custom_data_access_.get_const_custom_data(owner);
if (custom_data == nullptr) {
return false;
}
@@ -439,80 +406,81 @@ bool BuiltinCustomDataLayerProvider::exists(const GeometryComponent &component)
return CustomData_get_layer(custom_data, stored_type_) != nullptr;
}
-ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read(
- const GeometryComponent &component, const AttributeIDRef &attribute_id) const
+GAttributeReader CustomDataAttributeProvider::try_get_for_read(
+ const void *owner, const AttributeIDRef &attribute_id) const
{
- const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
+ const CustomData *custom_data = custom_data_access_.get_const_custom_data(owner);
if (custom_data == nullptr) {
return {};
}
- const int domain_num = component.attribute_domain_num(domain_);
+ const int element_num = custom_data_access_.get_element_num(owner);
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
if (!custom_data_layer_matches_attribute_id(layer, attribute_id)) {
continue;
}
- const CPPType *type = custom_data_type_to_cpp_type((CustomDataType)layer.type);
+ const CPPType *type = custom_data_type_to_cpp_type((eCustomDataType)layer.type);
if (type == nullptr) {
continue;
}
- GSpan data{*type, layer.data, domain_num};
+ GSpan data{*type, layer.data, element_num};
return {GVArray::ForSpan(data), domain_};
}
return {};
}
-WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write(
- GeometryComponent &component, const AttributeIDRef &attribute_id) const
+GAttributeWriter CustomDataAttributeProvider::try_get_for_write(
+ void *owner, const AttributeIDRef &attribute_id) const
{
- CustomData *custom_data = custom_data_access_.get_custom_data(component);
+ CustomData *custom_data = custom_data_access_.get_custom_data(owner);
if (custom_data == nullptr) {
return {};
}
- const int domain_num = component.attribute_domain_num(domain_);
+ const int element_num = custom_data_access_.get_element_num(owner);
for (CustomDataLayer &layer : MutableSpan(custom_data->layers, custom_data->totlayer)) {
if (!custom_data_layer_matches_attribute_id(layer, attribute_id)) {
continue;
}
if (attribute_id.is_named()) {
- CustomData_duplicate_referenced_layer_named(custom_data, layer.type, layer.name, domain_num);
+ CustomData_duplicate_referenced_layer_named(
+ custom_data, layer.type, layer.name, element_num);
}
else {
CustomData_duplicate_referenced_layer_anonymous(
- custom_data, layer.type, &attribute_id.anonymous_id(), domain_num);
+ custom_data, layer.type, &attribute_id.anonymous_id(), element_num);
}
- const CPPType *type = custom_data_type_to_cpp_type((CustomDataType)layer.type);
+ const CPPType *type = custom_data_type_to_cpp_type((eCustomDataType)layer.type);
if (type == nullptr) {
continue;
}
- GMutableSpan data{*type, layer.data, domain_num};
+ GMutableSpan data{*type, layer.data, element_num};
return {GVMutableArray::ForSpan(data), domain_};
}
return {};
}
-bool CustomDataAttributeProvider::try_delete(GeometryComponent &component,
- const AttributeIDRef &attribute_id) const
+bool CustomDataAttributeProvider::try_delete(void *owner, const AttributeIDRef &attribute_id) const
{
- CustomData *custom_data = custom_data_access_.get_custom_data(component);
+ CustomData *custom_data = custom_data_access_.get_custom_data(owner);
if (custom_data == nullptr) {
return false;
}
- const int domain_num = component.attribute_domain_num(domain_);
+ const int element_num = custom_data_access_.get_element_num(owner);
+ ;
for (const int i : IndexRange(custom_data->totlayer)) {
const CustomDataLayer &layer = custom_data->layers[i];
- if (this->type_is_supported((CustomDataType)layer.type) &&
+ if (this->type_is_supported((eCustomDataType)layer.type) &&
custom_data_layer_matches_attribute_id(layer, attribute_id)) {
- CustomData_free_layer(custom_data, layer.type, domain_num, i);
+ CustomData_free_layer(custom_data, layer.type, element_num, i);
return true;
}
}
return false;
}
-bool CustomDataAttributeProvider::try_create(GeometryComponent &component,
+bool CustomDataAttributeProvider::try_create(void *owner,
const AttributeIDRef &attribute_id,
- const AttributeDomain domain,
- const CustomDataType data_type,
+ const eAttrDomain domain,
+ const eCustomDataType data_type,
const AttributeInit &initializer) const
{
if (domain_ != domain) {
@@ -521,7 +489,7 @@ bool CustomDataAttributeProvider::try_create(GeometryComponent &component,
if (!this->type_is_supported(data_type)) {
return false;
}
- CustomData *custom_data = custom_data_access_.get_custom_data(component);
+ CustomData *custom_data = custom_data_access_.get_custom_data(owner);
if (custom_data == nullptr) {
return false;
}
@@ -530,21 +498,21 @@ bool CustomDataAttributeProvider::try_create(GeometryComponent &component,
return false;
}
}
- const int domain_num = component.attribute_domain_num(domain_);
+ const int element_num = custom_data_access_.get_element_num(owner);
add_custom_data_layer_from_attribute_init(
- attribute_id, *custom_data, data_type, domain_num, initializer);
+ attribute_id, *custom_data, data_type, element_num, initializer);
return true;
}
-bool CustomDataAttributeProvider::foreach_attribute(const GeometryComponent &component,
+bool CustomDataAttributeProvider::foreach_attribute(const void *owner,
const AttributeForeachCallback callback) const
{
- const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
+ const CustomData *custom_data = custom_data_access_.get_const_custom_data(owner);
if (custom_data == nullptr) {
return true;
}
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
- const CustomDataType data_type = (CustomDataType)layer.type;
+ const eCustomDataType data_type = (eCustomDataType)layer.type;
if (this->type_is_supported(data_type)) {
AttributeMetaData meta_data{domain_, data_type};
const AttributeIDRef attribute_id = attribute_id_from_custom_data_layer(layer);
@@ -556,17 +524,17 @@ bool CustomDataAttributeProvider::foreach_attribute(const GeometryComponent &com
return true;
}
-ReadAttributeLookup NamedLegacyCustomDataProvider::try_get_for_read(
- const GeometryComponent &component, const AttributeIDRef &attribute_id) const
+GAttributeReader NamedLegacyCustomDataProvider::try_get_for_read(
+ const void *owner, const AttributeIDRef &attribute_id) const
{
- const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
+ const CustomData *custom_data = custom_data_access_.get_const_custom_data(owner);
if (custom_data == nullptr) {
return {};
}
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
if (layer.type == stored_type_) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
- const int domain_num = component.attribute_domain_num(domain_);
+ const int domain_num = custom_data_access_.get_element_num(owner);
return {as_read_attribute_(layer.data, domain_num), domain_};
}
}
@@ -574,36 +542,36 @@ ReadAttributeLookup NamedLegacyCustomDataProvider::try_get_for_read(
return {};
}
-WriteAttributeLookup NamedLegacyCustomDataProvider::try_get_for_write(
- GeometryComponent &component, const AttributeIDRef &attribute_id) const
+GAttributeWriter NamedLegacyCustomDataProvider::try_get_for_write(
+ void *owner, const AttributeIDRef &attribute_id) const
{
- CustomData *custom_data = custom_data_access_.get_custom_data(component);
+ CustomData *custom_data = custom_data_access_.get_custom_data(owner);
if (custom_data == nullptr) {
return {};
}
for (CustomDataLayer &layer : MutableSpan(custom_data->layers, custom_data->totlayer)) {
if (layer.type == stored_type_) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
- const int domain_num = component.attribute_domain_num(domain_);
+ const int element_num = custom_data_access_.get_element_num(owner);
void *data_old = layer.data;
void *data_new = CustomData_duplicate_referenced_layer_named(
- custom_data, stored_type_, layer.name, domain_num);
+ custom_data, stored_type_, layer.name, element_num);
if (data_old != data_new) {
if (custom_data_access_.update_custom_data_pointers) {
- custom_data_access_.update_custom_data_pointers(component);
+ custom_data_access_.update_custom_data_pointers(owner);
}
}
- return {as_write_attribute_(layer.data, domain_num), domain_};
+ return {as_write_attribute_(layer.data, element_num), domain_};
}
}
}
return {};
}
-bool NamedLegacyCustomDataProvider::try_delete(GeometryComponent &component,
+bool NamedLegacyCustomDataProvider::try_delete(void *owner,
const AttributeIDRef &attribute_id) const
{
- CustomData *custom_data = custom_data_access_.get_custom_data(component);
+ CustomData *custom_data = custom_data_access_.get_custom_data(owner);
if (custom_data == nullptr) {
return false;
}
@@ -611,10 +579,10 @@ bool NamedLegacyCustomDataProvider::try_delete(GeometryComponent &component,
const CustomDataLayer &layer = custom_data->layers[i];
if (layer.type == stored_type_) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
- const int domain_num = component.attribute_domain_num(domain_);
- CustomData_free_layer(custom_data, stored_type_, domain_num, i);
+ const int element_num = custom_data_access_.get_element_num(owner);
+ CustomData_free_layer(custom_data, stored_type_, element_num, i);
if (custom_data_access_.update_custom_data_pointers) {
- custom_data_access_.update_custom_data_pointers(component);
+ custom_data_access_.update_custom_data_pointers(owner);
}
return true;
}
@@ -624,9 +592,9 @@ bool NamedLegacyCustomDataProvider::try_delete(GeometryComponent &component,
}
bool NamedLegacyCustomDataProvider::foreach_attribute(
- const GeometryComponent &component, const AttributeForeachCallback callback) const
+ const void *owner, const AttributeForeachCallback callback) const
{
- const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
+ const CustomData *custom_data = custom_data_access_.get_const_custom_data(owner);
if (custom_data == nullptr) {
return true;
}
@@ -642,7 +610,7 @@ bool NamedLegacyCustomDataProvider::foreach_attribute(
}
void NamedLegacyCustomDataProvider::foreach_domain(
- const FunctionRef<void(AttributeDomain)> callback) const
+ const FunctionRef<void(eAttrDomain)> callback) const
{
callback(domain_);
}
@@ -685,7 +653,7 @@ std::optional<GSpan> CustomDataAttributes::get_for_read(const AttributeIDRef &at
{
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
- const CPPType *cpp_type = custom_data_type_to_cpp_type((CustomDataType)layer.type);
+ const CPPType *cpp_type = custom_data_type_to_cpp_type((eCustomDataType)layer.type);
BLI_assert(cpp_type != nullptr);
return GSpan(*cpp_type, layer.data, size_);
}
@@ -694,7 +662,7 @@ std::optional<GSpan> CustomDataAttributes::get_for_read(const AttributeIDRef &at
}
GVArray CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id,
- const CustomDataType data_type,
+ const eCustomDataType data_type,
const void *default_value) const
{
const CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
@@ -718,7 +686,7 @@ std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const AttributeI
{
for (CustomDataLayer &layer : MutableSpan(data.layers, data.totlayer)) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
- const CPPType *cpp_type = custom_data_type_to_cpp_type((CustomDataType)layer.type);
+ const CPPType *cpp_type = custom_data_type_to_cpp_type((eCustomDataType)layer.type);
BLI_assert(cpp_type != nullptr);
return GMutableSpan(*cpp_type, layer.data, size_);
}
@@ -727,7 +695,7 @@ std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const AttributeI
}
bool CustomDataAttributes::create(const AttributeIDRef &attribute_id,
- const CustomDataType data_type)
+ const eCustomDataType data_type)
{
void *result = add_generic_custom_data_layer(
data, data_type, CD_DEFAULT, nullptr, size_, attribute_id);
@@ -735,7 +703,7 @@ bool CustomDataAttributes::create(const AttributeIDRef &attribute_id,
}
bool CustomDataAttributes::create_by_move(const AttributeIDRef &attribute_id,
- const CustomDataType data_type,
+ const eCustomDataType data_type,
void *buffer)
{
void *result = add_generic_custom_data_layer(
@@ -768,10 +736,10 @@ void CustomDataAttributes::clear()
}
bool CustomDataAttributes::foreach_attribute(const AttributeForeachCallback callback,
- const AttributeDomain domain) const
+ const eAttrDomain domain) const
{
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
- AttributeMetaData meta_data{domain, (CustomDataType)layer.type};
+ AttributeMetaData meta_data{domain, (eCustomDataType)layer.type};
const AttributeIDRef attribute_id = attribute_id_from_custom_data_layer(layer);
if (!callback(attribute_id, meta_data)) {
return false;
@@ -800,275 +768,10 @@ void CustomDataAttributes::reorder(Span<AttributeIDRef> new_order)
CustomData_update_typemap(&data);
}
-} // namespace blender::bke
-
/* -------------------------------------------------------------------- */
/** \name Geometry Component
* \{ */
-const blender::bke::ComponentAttributeProviders *GeometryComponent::get_attribute_providers() const
-{
- return nullptr;
-}
-
-bool GeometryComponent::attribute_domain_supported(const AttributeDomain domain) const
-{
- using namespace blender::bke;
- const ComponentAttributeProviders *providers = this->get_attribute_providers();
- if (providers == nullptr) {
- return false;
- }
- return providers->supported_domains().contains(domain);
-}
-
-int GeometryComponent::attribute_domain_num(const AttributeDomain UNUSED(domain)) const
-{
- return 0;
-}
-
-bool GeometryComponent::attribute_is_builtin(const blender::StringRef attribute_name) const
-{
- using namespace blender::bke;
- const ComponentAttributeProviders *providers = this->get_attribute_providers();
- if (providers == nullptr) {
- return false;
- }
- return providers->builtin_attribute_providers().contains_as(attribute_name);
-}
-
-bool GeometryComponent::attribute_is_builtin(const AttributeIDRef &attribute_id) const
-{
- /* Anonymous attributes cannot be built-in. */
- return attribute_id.is_named() && this->attribute_is_builtin(attribute_id.name());
-}
-
-blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
- const AttributeIDRef &attribute_id) const
-{
- using namespace blender::bke;
- const ComponentAttributeProviders *providers = this->get_attribute_providers();
- if (providers == nullptr) {
- return {};
- }
- if (attribute_id.is_named()) {
- const BuiltinAttributeProvider *builtin_provider =
- providers->builtin_attribute_providers().lookup_default_as(attribute_id.name(), nullptr);
- if (builtin_provider != nullptr) {
- return {builtin_provider->try_get_for_read(*this), builtin_provider->domain()};
- }
- }
- for (const DynamicAttributesProvider *dynamic_provider :
- providers->dynamic_attribute_providers()) {
- ReadAttributeLookup attribute = dynamic_provider->try_get_for_read(*this, attribute_id);
- if (attribute) {
- return attribute;
- }
- }
- return {};
-}
-
-blender::GVArray GeometryComponent::attribute_try_adapt_domain_impl(
- const blender::GVArray &varray,
- const AttributeDomain from_domain,
- const AttributeDomain to_domain) const
-{
- if (from_domain == to_domain) {
- return varray;
- }
- return {};
-}
-
-blender::bke::WriteAttributeLookup GeometryComponent::attribute_try_get_for_write(
- const AttributeIDRef &attribute_id)
-{
- using namespace blender::bke;
- const ComponentAttributeProviders *providers = this->get_attribute_providers();
- if (providers == nullptr) {
- return {};
- }
- if (attribute_id.is_named()) {
- const BuiltinAttributeProvider *builtin_provider =
- providers->builtin_attribute_providers().lookup_default_as(attribute_id.name(), nullptr);
- if (builtin_provider != nullptr) {
- return builtin_provider->try_get_for_write(*this);
- }
- }
- for (const DynamicAttributesProvider *dynamic_provider :
- providers->dynamic_attribute_providers()) {
- WriteAttributeLookup attribute = dynamic_provider->try_get_for_write(*this, attribute_id);
- if (attribute) {
- return attribute;
- }
- }
- return {};
-}
-
-bool GeometryComponent::attribute_try_delete(const AttributeIDRef &attribute_id)
-{
- using namespace blender::bke;
- const ComponentAttributeProviders *providers = this->get_attribute_providers();
- if (providers == nullptr) {
- return {};
- }
- if (attribute_id.is_named()) {
- const BuiltinAttributeProvider *builtin_provider =
- providers->builtin_attribute_providers().lookup_default_as(attribute_id.name(), nullptr);
- if (builtin_provider != nullptr) {
- return builtin_provider->try_delete(*this);
- }
- }
- bool success = false;
- for (const DynamicAttributesProvider *dynamic_provider :
- providers->dynamic_attribute_providers()) {
- success = dynamic_provider->try_delete(*this, attribute_id) || success;
- }
- return success;
-}
-
-void GeometryComponent::attributes_remove_anonymous()
-{
- using namespace blender;
- Vector<const AnonymousAttributeID *> anonymous_ids;
- for (const AttributeIDRef &id : this->attribute_ids()) {
- if (id.is_anonymous()) {
- anonymous_ids.append(&id.anonymous_id());
- }
- }
-
- while (!anonymous_ids.is_empty()) {
- this->attribute_try_delete(anonymous_ids.pop_last());
- }
-}
-
-bool GeometryComponent::attribute_try_create(const AttributeIDRef &attribute_id,
- const AttributeDomain domain,
- const CustomDataType data_type,
- const AttributeInit &initializer)
-{
- using namespace blender::bke;
- if (!attribute_id) {
- return false;
- }
- const ComponentAttributeProviders *providers = this->get_attribute_providers();
- if (providers == nullptr) {
- return false;
- }
- if (this->attribute_exists(attribute_id)) {
- return false;
- }
- if (attribute_id.is_named()) {
- const BuiltinAttributeProvider *builtin_provider =
- providers->builtin_attribute_providers().lookup_default_as(attribute_id.name(), nullptr);
- if (builtin_provider != nullptr) {
- if (builtin_provider->domain() != domain) {
- return false;
- }
- if (builtin_provider->data_type() != data_type) {
- return false;
- }
- return builtin_provider->try_create(*this, initializer);
- }
- }
- for (const DynamicAttributesProvider *dynamic_provider :
- providers->dynamic_attribute_providers()) {
- if (dynamic_provider->try_create(*this, attribute_id, domain, data_type, initializer)) {
- return true;
- }
- }
- return false;
-}
-
-bool GeometryComponent::attribute_try_create_builtin(const blender::StringRef attribute_name,
- const AttributeInit &initializer)
-{
- using namespace blender::bke;
- if (attribute_name.is_empty()) {
- return false;
- }
- const ComponentAttributeProviders *providers = this->get_attribute_providers();
- if (providers == nullptr) {
- return false;
- }
- const BuiltinAttributeProvider *builtin_provider =
- providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr);
- if (builtin_provider == nullptr) {
- return false;
- }
- return builtin_provider->try_create(*this, initializer);
-}
-
-Set<AttributeIDRef> GeometryComponent::attribute_ids() const
-{
- Set<AttributeIDRef> attributes;
- this->attribute_foreach(
- [&](const AttributeIDRef &attribute_id, const AttributeMetaData &UNUSED(meta_data)) {
- attributes.add(attribute_id);
- return true;
- });
- return attributes;
-}
-
-bool GeometryComponent::attribute_foreach(const AttributeForeachCallback callback) const
-{
- using namespace blender::bke;
- const ComponentAttributeProviders *providers = this->get_attribute_providers();
- if (providers == nullptr) {
- return true;
- }
-
- /* Keep track handled attribute names to make sure that we do not return the same name twice. */
- Set<std::string> handled_attribute_names;
-
- for (const BuiltinAttributeProvider *provider :
- providers->builtin_attribute_providers().values()) {
- if (provider->exists(*this)) {
- AttributeMetaData meta_data{provider->domain(), provider->data_type()};
- if (!callback(provider->name(), meta_data)) {
- return false;
- }
- handled_attribute_names.add_new(provider->name());
- }
- }
- for (const DynamicAttributesProvider *provider : providers->dynamic_attribute_providers()) {
- const bool continue_loop = provider->foreach_attribute(
- *this, [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
- if (attribute_id.is_anonymous() || handled_attribute_names.add(attribute_id.name())) {
- return callback(attribute_id, meta_data);
- }
- return true;
- });
- if (!continue_loop) {
- return false;
- }
- }
-
- return true;
-}
-
-bool GeometryComponent::attribute_exists(const AttributeIDRef &attribute_id) const
-{
- blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_id);
- if (attribute) {
- return true;
- }
- return false;
-}
-
-std::optional<AttributeMetaData> GeometryComponent::attribute_get_meta_data(
- const AttributeIDRef &attribute_id) const
-{
- std::optional<AttributeMetaData> result{std::nullopt};
- this->attribute_foreach(
- [&](const AttributeIDRef &current_attribute_id, const AttributeMetaData &meta_data) {
- if (attribute_id == current_attribute_id) {
- result = meta_data;
- return false;
- }
- return true;
- });
- return result;
-}
-
static blender::GVArray try_adapt_data_type(blender::GVArray varray,
const blender::CPPType &to_type)
{
@@ -1077,296 +780,6 @@ static blender::GVArray try_adapt_data_type(blender::GVArray varray,
return conversions.try_convert(std::move(varray), to_type);
}
-blender::GVArray GeometryComponent::attribute_try_get_for_read(
- const AttributeIDRef &attribute_id,
- const AttributeDomain domain,
- const CustomDataType data_type) const
-{
- blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_id);
- if (!attribute) {
- return {};
- }
-
- blender::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) {
- return {};
- }
- }
-
- const blender::CPPType *cpp_type = blender::bke::custom_data_type_to_cpp_type(data_type);
- BLI_assert(cpp_type != nullptr);
- if (varray.type() != *cpp_type) {
- varray = try_adapt_data_type(std::move(varray), *cpp_type);
- if (!varray) {
- return {};
- }
- }
-
- return varray;
-}
-
-blender::GVArray GeometryComponent::attribute_try_get_for_read(const AttributeIDRef &attribute_id,
- const AttributeDomain domain) const
-{
- if (!this->attribute_domain_supported(domain)) {
- return {};
- }
-
- blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_id);
- if (!attribute) {
- return {};
- }
-
- if (attribute.domain != domain) {
- return this->attribute_try_adapt_domain(std::move(attribute.varray), attribute.domain, domain);
- }
-
- return std::move(attribute.varray);
-}
-
-blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
- const AttributeIDRef &attribute_id, const CustomDataType data_type) const
-{
- blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_id);
- if (!attribute) {
- return {};
- }
- const blender::CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
- BLI_assert(type != nullptr);
- if (attribute.varray.type() == *type) {
- return attribute;
- }
- const blender::bke::DataTypeConversions &conversions =
- blender::bke::get_implicit_type_conversions();
- return {conversions.try_convert(std::move(attribute.varray), *type), attribute.domain};
-}
-
-blender::GVArray GeometryComponent::attribute_get_for_read(const AttributeIDRef &attribute_id,
- const AttributeDomain domain,
- const CustomDataType data_type,
- const void *default_value) const
-{
- blender::GVArray varray = this->attribute_try_get_for_read(attribute_id, domain, data_type);
- if (varray) {
- return varray;
- }
- const blender::CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
- if (default_value == nullptr) {
- default_value = type->default_value();
- }
- const int domain_num = this->attribute_domain_num(domain);
- return blender::GVArray::ForSingle(*type, domain_num, default_value);
-}
-
-class GVMutableAttribute_For_OutputAttribute : public blender::GVArrayImpl_For_GSpan {
- public:
- GeometryComponent *component;
- std::string attribute_name;
- blender::bke::WeakAnonymousAttributeID anonymous_attribute_id;
-
- GVMutableAttribute_For_OutputAttribute(GMutableSpan data,
- GeometryComponent &component,
- const AttributeIDRef &attribute_id)
- : blender::GVArrayImpl_For_GSpan(data), component(&component)
- {
- if (attribute_id.is_named()) {
- this->attribute_name = attribute_id.name();
- }
- else {
- const AnonymousAttributeID *anonymous_id = &attribute_id.anonymous_id();
- BKE_anonymous_attribute_id_increment_weak(anonymous_id);
- this->anonymous_attribute_id = blender::bke::WeakAnonymousAttributeID{anonymous_id};
- }
- }
-
- ~GVMutableAttribute_For_OutputAttribute() override
- {
- type_->destruct_n(data_, size_);
- MEM_freeN(data_);
- }
-};
-
-static void save_output_attribute(OutputAttribute &output_attribute)
-{
- using namespace blender;
- using namespace blender::fn;
- using namespace blender::bke;
-
- GVMutableAttribute_For_OutputAttribute &varray =
- dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(
- *output_attribute.varray().get_implementation());
-
- GeometryComponent &component = *varray.component;
- AttributeIDRef attribute_id;
- if (!varray.attribute_name.empty()) {
- attribute_id = varray.attribute_name;
- }
- else {
- attribute_id = varray.anonymous_attribute_id.extract();
- }
- const AttributeDomain domain = output_attribute.domain();
- const CustomDataType data_type = output_attribute.custom_data_type();
- const CPPType &cpp_type = output_attribute.cpp_type();
-
- component.attribute_try_delete(attribute_id);
- if (!component.attribute_try_create(attribute_id, domain, data_type, AttributeInitDefault())) {
- if (!varray.attribute_name.empty()) {
- CLOG_WARN(&LOG,
- "Could not create the '%s' attribute with type '%s'.",
- varray.attribute_name.c_str(),
- cpp_type.name().c_str());
- }
- return;
- }
- WriteAttributeLookup write_attribute = component.attribute_try_get_for_write(attribute_id);
- 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);
- }
- 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,
- const AttributeIDRef &attribute_id,
- const AttributeDomain domain,
- const CustomDataType data_type,
- const bool ignore_old_values,
- const void *default_value)
-{
- using namespace blender;
- using namespace blender::fn;
- using namespace blender::bke;
-
- if (!attribute_id) {
- return {};
- }
-
- const CPPType *cpp_type = custom_data_type_to_cpp_type(data_type);
- BLI_assert(cpp_type != nullptr);
- const DataTypeConversions &conversions = get_implicit_type_conversions();
-
- if (component.attribute_is_builtin(attribute_id)) {
- const StringRef attribute_name = attribute_id.name();
- WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_name);
- if (!attribute) {
- if (default_value) {
- const int64_t domain_num = component.attribute_domain_num(domain);
- component.attribute_try_create_builtin(
- attribute_name,
- AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_num, default_value)));
- }
- else {
- component.attribute_try_create_builtin(attribute_name, AttributeInitDefault());
- }
- attribute = component.attribute_try_get_for_write(attribute_name);
- if (!attribute) {
- /* Builtin attribute does not exist and can't be created. */
- return {};
- }
- }
- if (attribute.domain != domain) {
- /* Builtin attribute is on different domain. */
- return {};
- }
- GVMutableArray varray = std::move(attribute.varray);
- if (varray.type() == *cpp_type) {
- /* Builtin attribute matches exactly. */
- 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. */
- varray = conversions.try_convert(std::move(varray), *cpp_type);
- return OutputAttribute(std::move(varray),
- domain,
- get_simple_output_attribute_save_method(attribute),
- ignore_old_values);
- }
-
- const int domain_num = component.attribute_domain_num(domain);
-
- WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_id);
- if (!attribute) {
- if (default_value) {
- component.attribute_try_create(
- attribute_id,
- domain,
- data_type,
- AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_num, default_value)));
- }
- else {
- component.attribute_try_create(attribute_id, domain, data_type, AttributeInitDefault());
- }
-
- attribute = component.attribute_try_get_for_write(attribute_id);
- if (!attribute) {
- /* Can't create the attribute. */
- return {};
- }
- }
- if (attribute.domain == domain && attribute.varray.type() == *cpp_type) {
- /* Existing generic attribute matches exactly. */
-
- 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
- * attribute after processing is done. */
- void *data = MEM_mallocN_aligned(cpp_type->size() * domain_num, cpp_type->alignment(), __func__);
- if (ignore_old_values) {
- /* This does nothing for trivially constructible types, but is necessary for correctness. */
- cpp_type->default_construct_n(data, domain);
- }
- else {
- /* Fill the temporary array with values from the existing attribute. */
- GVArray old_varray = component.attribute_get_for_read(
- attribute_id, domain, data_type, default_value);
- old_varray.materialize_to_uninitialized(IndexRange(domain_num), data);
- }
- GVMutableArray varray = GVMutableArray::For<GVMutableAttribute_For_OutputAttribute>(
- GMutableSpan{*cpp_type, data, domain_num}, component, attribute_id);
-
- return OutputAttribute(std::move(varray), domain, save_output_attribute, true);
-}
-
-OutputAttribute GeometryComponent::attribute_try_get_for_output(const AttributeIDRef &attribute_id,
- const AttributeDomain domain,
- const CustomDataType data_type,
- const void *default_value)
-{
- return create_output_attribute(*this, attribute_id, domain, data_type, false, default_value);
-}
-
-OutputAttribute GeometryComponent::attribute_try_get_for_output_only(
- const AttributeIDRef &attribute_id,
- const AttributeDomain domain,
- const CustomDataType data_type)
-{
- return create_output_attribute(*this, attribute_id, domain, data_type, true, nullptr);
-}
-
-namespace blender::bke {
-
GVArray GeometryFieldInput::get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &UNUSED(scope)) const
@@ -1374,18 +787,21 @@ GVArray GeometryFieldInput::get_varray_for_context(const fn::FieldContext &conte
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
- const AttributeDomain domain = geometry_context->domain();
+ const eAttrDomain domain = geometry_context->domain();
return this->get_varray_for_context(component, domain, mask);
}
return {};
}
GVArray AttributeFieldInput::get_varray_for_context(const GeometryComponent &component,
- const AttributeDomain domain,
+ const eAttrDomain domain,
IndexMask UNUSED(mask)) const
{
- const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
- return component.attribute_try_get_for_read(name_, domain, data_type);
+ const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_);
+ if (auto attributes = component.attributes()) {
+ return attributes->lookup(name_, domain, data_type);
+ }
+ return {};
}
std::string AttributeFieldInput::socket_inspection_name() const
@@ -1408,7 +824,7 @@ bool AttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
return false;
}
-static StringRef get_random_id_attribute_name(const AttributeDomain domain)
+static StringRef get_random_id_attribute_name(const eAttrDomain domain)
{
switch (domain) {
case ATTR_DOMAIN_POINT:
@@ -1420,15 +836,15 @@ static StringRef get_random_id_attribute_name(const AttributeDomain domain)
}
GVArray IDAttributeFieldInput::get_varray_for_context(const GeometryComponent &component,
- const AttributeDomain domain,
+ const eAttrDomain domain,
IndexMask mask) const
{
const StringRef name = get_random_id_attribute_name(domain);
- GVArray attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32);
- if (attribute) {
- BLI_assert(attribute.size() == component.attribute_domain_num(domain));
- return attribute;
+ if (auto attributes = component.attributes()) {
+ if (GVArray attribute = attributes->lookup(name, domain, CD_PROP_INT32)) {
+ return attribute;
+ }
}
/* Use the index as the fallback if no random ID attribute exists. */
@@ -1453,11 +869,11 @@ bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
}
GVArray AnonymousAttributeFieldInput::get_varray_for_context(const GeometryComponent &component,
- const AttributeDomain domain,
+ const eAttrDomain domain,
IndexMask UNUSED(mask)) const
{
- const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
- return component.attribute_try_get_for_read(anonymous_id_.get(), domain, data_type);
+ const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_);
+ return component.attributes()->lookup(anonymous_id_.get(), domain, data_type);
}
std::string AnonymousAttributeFieldInput::socket_inspection_name() const
@@ -1481,6 +897,151 @@ bool AnonymousAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
return false;
}
+GVArray AttributeAccessor::lookup(const AttributeIDRef &attribute_id,
+ const std::optional<eAttrDomain> domain,
+ const std::optional<eCustomDataType> data_type) const
+{
+ GAttributeReader attribute = this->lookup(attribute_id);
+ if (!attribute) {
+ return {};
+ }
+ GVArray varray = std::move(attribute.varray);
+ if (domain.has_value()) {
+ if (attribute.domain != domain) {
+ varray = this->adapt_domain(varray, attribute.domain, *domain);
+ if (!varray) {
+ return {};
+ }
+ }
+ }
+ if (data_type.has_value()) {
+ const CPPType &type = *custom_data_type_to_cpp_type(*data_type);
+ if (varray.type() != type) {
+ varray = try_adapt_data_type(std::move(varray), type);
+ if (!varray) {
+ return {};
+ }
+ }
+ }
+ return varray;
+}
+
+GVArray AttributeAccessor::lookup_or_default(const AttributeIDRef &attribute_id,
+ const eAttrDomain domain,
+ const eCustomDataType data_type,
+ const void *default_value) const
+{
+ GVArray varray = this->lookup(attribute_id, domain, data_type);
+ if (varray) {
+ return varray;
+ }
+ const CPPType &type = *custom_data_type_to_cpp_type(data_type);
+ const int64_t domain_size = this->domain_size(domain);
+ if (default_value == nullptr) {
+ return GVArray::ForSingleRef(type, domain_size, type.default_value());
+ }
+ return GVArray::ForSingle(type, domain_size, default_value);
+}
+
+Set<AttributeIDRef> AttributeAccessor::all_ids() const
+{
+ Set<AttributeIDRef> ids;
+ this->for_all(
+ [&](const AttributeIDRef &attribute_id, const AttributeMetaData & /* meta_data */) {
+ ids.add(attribute_id);
+ return true;
+ });
+ return ids;
+}
+
+void MutableAttributeAccessor::remove_anonymous()
+{
+ Vector<const AnonymousAttributeID *> anonymous_ids;
+ for (const AttributeIDRef &id : this->all_ids()) {
+ if (id.is_anonymous()) {
+ anonymous_ids.append(&id.anonymous_id());
+ }
+ }
+
+ while (!anonymous_ids.is_empty()) {
+ this->remove(anonymous_ids.pop_last());
+ }
+}
+
+GAttributeWriter MutableAttributeAccessor::lookup_or_add_for_write(
+ const AttributeIDRef &attribute_id,
+ const eAttrDomain domain,
+ const eCustomDataType data_type,
+ const AttributeInit &initializer)
+{
+ std::optional<AttributeMetaData> meta_data = this->lookup_meta_data(attribute_id);
+ if (meta_data.has_value()) {
+ if (meta_data->domain == domain && meta_data->data_type == data_type) {
+ return this->lookup_for_write(attribute_id);
+ }
+ return {};
+ }
+ if (this->add(attribute_id, domain, data_type, initializer)) {
+ return this->lookup_for_write(attribute_id);
+ }
+ return {};
+}
+
+GSpanAttributeWriter MutableAttributeAccessor::lookup_or_add_for_write_span(
+ const AttributeIDRef &attribute_id,
+ const eAttrDomain domain,
+ const eCustomDataType data_type,
+ const AttributeInit &initializer)
+{
+ GAttributeWriter attribute = this->lookup_or_add_for_write(
+ attribute_id, domain, data_type, initializer);
+ if (attribute) {
+ return GSpanAttributeWriter{std::move(attribute), true};
+ }
+ return {};
+}
+
+GSpanAttributeWriter MutableAttributeAccessor::lookup_or_add_for_write_only_span(
+ const AttributeIDRef &attribute_id, const eAttrDomain domain, const eCustomDataType data_type)
+{
+ GAttributeWriter attribute = this->lookup_or_add_for_write(attribute_id, domain, data_type);
+ if (attribute) {
+ return GSpanAttributeWriter{std::move(attribute), false};
+ }
+ return {};
+}
+
+Vector<AttributeTransferData> retrieve_attributes_for_transfer(
+ const bke::AttributeAccessor &src_attributes,
+ bke::MutableAttributeAccessor &dst_attributes,
+ const eAttrDomainMask domain_mask,
+ const Set<std::string> &skip)
+{
+ Vector<AttributeTransferData> attributes;
+ src_attributes.for_all(
+ [&](const bke::AttributeIDRef &id, const bke::AttributeMetaData meta_data) {
+ if (!(ATTR_DOMAIN_AS_MASK(meta_data.domain) & domain_mask)) {
+ return true;
+ }
+ if (id.is_named() && skip.contains(id.name())) {
+ return true;
+ }
+ if (!id.should_be_kept()) {
+ return true;
+ }
+
+ GVArray src = src_attributes.lookup(id, meta_data.domain);
+ BLI_assert(src);
+ bke::GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
+ id, meta_data.domain, meta_data.data_type);
+ BLI_assert(dst);
+ attributes.append({std::move(src), meta_data, std::move(dst)});
+
+ return true;
+ });
+ return attributes;
+}
+
} // namespace blender::bke
/** \} */