Blender V5.0
attribute_storage_access.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BKE_attribute.hh"
7
9
10namespace blender::bke {
11
13 const AttrDomain domain,
14 const int64_t domain_size)
15{
16 const CPPType &cpp_type = attribute_type_to_cpp_type(attribute.data_type());
17 switch (attribute.storage_type()) {
19 const auto &data = std::get<Attribute::ArrayData>(attribute.data());
20 return GAttributeReader{GVArray::from_span(GSpan(cpp_type, data.data, data.size)),
21 domain,
22 data.sharing_info.get()};
23 }
25 const auto &data = std::get<Attribute::SingleData>(attribute.data());
26 return GAttributeReader{GVArray::from_single_ref(cpp_type, domain_size, data.value),
27 domain,
28 data.sharing_info.get()};
29 }
30 }
32 return {};
33}
34
37 const int64_t domain_size,
38 Attribute &attribute)
39{
40 const CPPType &cpp_type = attribute_type_to_cpp_type(attribute.data_type());
41 switch (attribute.storage_type()) {
43 auto &data = std::get<Attribute::ArrayData>(attribute.data_for_write());
44 BLI_assert(data.size == domain_size);
45
46 std::function<void()> tag_modified_fn;
47 if (const AttrUpdateOnChange update_fn = changed_tags.lookup_default(attribute.name(),
48 nullptr))
49 {
50 tag_modified_fn = [owner, update_fn]() { update_fn(owner); };
51 };
52
53 return GAttributeWriter{
54 GVMutableArray::from_span(GMutableSpan(cpp_type, data.data, domain_size)),
55 attribute.domain(),
56 std::move(tag_modified_fn)};
57 }
59 /* Not yet implemented. */
61 }
62 }
64 return {};
65}
66
68 const int64_t domain_size,
69 const AttributeInit &initializer)
70{
71 switch (initializer.type) {
73 const CPPType &type = bke::attribute_type_to_cpp_type(data_type);
74 return Attribute::ArrayData::from_constructed(type, domain_size);
75 }
77 const CPPType &type = bke::attribute_type_to_cpp_type(data_type);
78 return Attribute::ArrayData::from_default_value(type, domain_size);
79 }
81 const auto &init = static_cast<const AttributeInitVArray &>(initializer);
82 const GVArray &varray = init.varray;
83 BLI_assert(varray.size() == domain_size);
84 const CPPType &type = varray.type();
86 data.data = MEM_malloc_arrayN_aligned(domain_size, type.size, type.alignment, __func__);
87 varray.materialize_to_uninitialized(varray.index_range(), data.data);
88 data.size = domain_size;
90 return data;
91 }
93 const auto &init = static_cast<const AttributeInitMoveArray &>(initializer);
95 data.data = init.data;
96 data.size = domain_size;
98 return data;
99 }
101 const auto &init = static_cast<const AttributeInitShared &>(initializer);
103 data.data = const_cast<void *>(init.data);
104 data.size = domain_size;
105 data.sharing_info = ImplicitSharingPtr<>(init.sharing_info);
106 data.sharing_info->add_user();
107 return data;
108 }
109 }
111 return {};
112}
113
115 AttrDomain domain,
116 const CPPType &cpp_type,
118 int64_t domain_size,
119 const void *default_value)
120{
121 const bke::Attribute *attr = storage.wrap().lookup(name);
122
123 const auto return_default = [&]() {
124 return GVArray::from_single(cpp_type, domain_size, default_value);
125 };
126
127 if (!attr) {
128 return return_default();
129 }
130 if (attr->domain() != domain) {
131 return return_default();
132 }
133 if (attr->data_type() != cpp_type_to_attribute_type(cpp_type)) {
134 return return_default();
135 }
136 switch (attr->storage_type()) {
138 const auto &data = std::get<bke::Attribute::ArrayData>(attr->data());
139 const GSpan span(cpp_type, data.data, data.size);
140 return GVArray::from_span(span);
141 }
143 const auto &data = std::get<bke::Attribute::SingleData>(attr->data());
144 return GVArray::from_single(cpp_type, domain_size, data.value);
145 }
146 }
147 return return_default();
148}
149
150std::optional<GSpan> get_span_attribute(const AttributeStorage &storage,
151 const AttrDomain domain,
152 const CPPType &cpp_type,
153 const StringRef name,
154 const int64_t domain_size)
155{
156 const bke::Attribute *attr = storage.wrap().lookup(name);
157 if (!attr) {
158 return {};
159 }
160 if (attr->domain() != domain) {
161 return {};
162 }
163 if (const auto *array_data = std::get_if<bke::Attribute::ArrayData>(&attr->data())) {
164 BLI_assert(array_data->size == domain_size);
165 UNUSED_VARS_NDEBUG(domain_size);
166 return GSpan(cpp_type, array_data->data, array_data->size);
167 }
168 return {};
169}
170
172 const AttrDomain domain,
173 const CPPType &cpp_type,
174 const StringRef name,
175 const int64_t domain_size,
176 const void *custom_default_value)
177{
178 if (domain_size <= 0) {
179 return {};
180 }
181 const bke::AttrType type = bke::cpp_type_to_attribute_type(cpp_type);
182 if (bke::Attribute *attr = storage.wrap().lookup(name)) {
183 if (attr->data_type() == type) {
184 if (const auto *single_data = std::get_if<bke::Attribute::SingleData>(&attr->data())) {
185 /* Convert single value storage to array storage. */
186 const GPointer g_value(cpp_type, single_data->value);
187 attr->assign_data(bke::Attribute::ArrayData::from_value(g_value, domain_size));
188 }
189 auto &array_data = std::get<bke::Attribute::ArrayData>(attr->data_for_write());
190 return GMutableSpan(cpp_type, array_data.data, domain_size);
191 }
192 /* The attribute has the wrong type. This shouldn't happen for builtin attributes, but just
193 * in case, remove it. */
194 storage.wrap().remove(name);
195 }
196 const void *default_value = custom_default_value ? custom_default_value :
197 cpp_type.default_value();
198 bke::Attribute &attr = storage.wrap().add(
199 name,
200 domain,
201 type,
202 bke::Attribute::ArrayData::from_value({cpp_type, default_value}, domain_size));
203 auto &array_data = std::get<bke::Attribute::ArrayData>(attr.data_for_write());
204 BLI_assert(array_data.size == domain_size);
205 return GMutableSpan(cpp_type, array_data.data, domain_size);
206}
207
208} // namespace blender::bke
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define UNUSED_VARS_NDEBUG(...)
BMesh const char void * data
long long int int64_t
const void * default_value() const
void materialize_to_uninitialized(void *dst) const
static GVArray from_single(const CPPType &type, int64_t size, const void *value)
static GVArray from_span(GSpan span)
static GVArray from_single_ref(const CPPType &type, int64_t size, const void *value)
static GVMutableArray from_span(GMutableSpan span)
Attribute & add(std::string name, bke::AttrDomain domain, bke::AttrType data_type, Attribute::DataVariant data)
Attribute * lookup(StringRef name)
AttrStorageType storage_type() const
const DataVariant & data() const
std::variant< ArrayData, SingleData > DataVariant
void *(* MEM_malloc_arrayN_aligned)(size_t len, size_t size, size_t alignment, const char *str)
Definition mallocn.cc:55
GMutableSpan get_mutable_attribute(AttributeStorage &storage, const AttrDomain domain, const CPPType &cpp_type, const StringRef name, const int64_t domain_size, const void *custom_default_value)
GAttributeReader attribute_to_reader(const Attribute &attribute, const AttrDomain domain, const int64_t domain_size)
std::optional< GSpan > get_span_attribute(const AttributeStorage &storage, const AttrDomain domain, const CPPType &cpp_type, const StringRef name, const int64_t domain_size)
Attribute::DataVariant attribute_init_to_data(const bke::AttrType data_type, const int64_t domain_size, const AttributeInit &initializer)
GAttributeWriter attribute_to_writer(void *owner, const Map< StringRef, AttrUpdateOnChange > &changed_tags, const int64_t domain_size, Attribute &attribute)
GVArray get_varray_attribute(const AttributeStorage &storage, AttrDomain domain, const CPPType &cpp_type, StringRef name, int64_t domain_size, const void *default_value)
void(*)(void *owner) AttrUpdateOnChange
static const auto & changed_tags()
AttrType cpp_type_to_attribute_type(const CPPType &type)
const CPPType & attribute_type_to_cpp_type(AttrType type)
const ImplicitSharingInfo * info_for_mem_free(void *data)
static void init(bNodeTree *, bNode *node)
const char * name
static ArrayData from_default_value(const CPPType &type, int64_t domain_size)
static ArrayData from_value(const GPointer &value, int64_t domain_size)
static ArrayData from_constructed(const CPPType &type, int64_t domain_size)