Blender V5.0
attribute_access_intern.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <functional>
6
8#include "BLI_map.hh"
9#include "BLI_span.hh"
10#include "BLI_string_ref.hh"
11#include "BLI_vector.hh"
12#include "BLI_vector_set.hh"
13
15#include "BKE_geometry_set.hh"
16
17namespace blender::bke {
18
34
42 public:
47
48 protected:
49 const std::string name_;
55
56 public:
58 const AttrDomain domain,
60 const DeletableEnum deletable,
62 const GPointer default_value = {})
63 : name_(std::move(name)),
66 deletable_(deletable),
69 {
70 }
71
72 virtual GAttributeReader try_get_for_read(const void *owner) const = 0;
73 virtual GAttributeWriter try_get_for_write(void *owner) const = 0;
74 virtual bool try_delete(void *owner) const = 0;
75 virtual bool try_create(void *owner, const AttributeInit &initializer) const = 0;
76 virtual bool exists(const void *owner) const = 0;
77
79 {
80 return name_;
81 }
82
84 {
85 return domain_;
86 }
87
89 {
90 return data_type_;
91 }
92
94 {
95 return validator_;
96 }
97
99 {
100 return default_value_;
101 }
102};
103
109 public:
110 virtual GAttributeReader try_get_for_read(const void *owner, StringRef attribute_id) const = 0;
111 virtual GAttributeWriter try_get_for_write(void *owner, StringRef attribute_id) const = 0;
112 virtual bool try_delete(void *owner, StringRef attribute_id) const = 0;
113 virtual bool try_create(void *owner,
114 const StringRef attribute_id,
115 const AttrDomain domain,
116 const eCustomDataType data_type,
117 const AttributeInit &initializer) const
118 {
119 UNUSED_VARS(owner, attribute_id, domain, data_type, initializer);
120 /* Some providers should not create new attributes. */
121 return false;
122 };
123
127 virtual bool foreach_attribute(const void *owner,
128 FunctionRef<void(const AttributeIter &)> fn) const = 0;
129 virtual void foreach_domain(const FunctionRef<void(AttrDomain)> callback) const = 0;
130};
131
136 private:
137 static constexpr uint64_t supported_types_mask = CD_MASK_PROP_ALL;
138 AttrDomain domain_;
139 CustomDataAccessInfo custom_data_access_;
140
141 public:
143 const CustomDataAccessInfo custom_data_access)
144 : domain_(domain), custom_data_access_(custom_data_access)
145 {
146 }
147
148 GAttributeReader try_get_for_read(const void *owner, StringRef attribute_id) const final;
149
150 GAttributeWriter try_get_for_write(void *owner, StringRef attribute_id) const final;
151
152 bool try_delete(void *owner, StringRef attribute_id) const final;
153
154 bool try_create(void *owner,
155 StringRef attribute_id,
156 AttrDomain domain,
157 const eCustomDataType data_type,
158 const AttributeInit &initializer) const final;
159
160 bool foreach_attribute(const void *owner,
161 FunctionRef<void(const AttributeIter &)> fn) const final;
162
163 void foreach_domain(const FunctionRef<void(AttrDomain)> callback) const final
164 {
165 callback(domain_);
166 }
167
168 private:
169 bool type_is_supported(eCustomDataType data_type) const
170 {
171 return ((1ULL << data_type) & supported_types_mask) != 0;
172 }
173};
174
183 using AttrUpdateOnChange = void (*)(void *owner);
184 const CustomDataAccessInfo custom_data_access_;
185 const AttrUpdateOnChange update_on_change_;
186
187 public:
188 BuiltinCustomDataLayerProvider(std::string attribute_name,
189 const AttrDomain domain,
191 const DeletableEnum deletable,
192 const CustomDataAccessInfo custom_data_access,
193 const AttrUpdateOnChange update_on_change,
194 const AttributeValidator validator = {},
195 const GPointer default_value = {})
197 std::move(attribute_name), domain, data_type, deletable, validator, default_value),
198 custom_data_access_(custom_data_access),
199 update_on_change_(update_on_change)
200 {
201 }
202
203 GAttributeReader try_get_for_read(const void *owner) const final;
204 GAttributeWriter try_get_for_write(void *owner) const final;
205 bool try_delete(void *owner) const final;
206 bool try_create(void *owner, const AttributeInit &initializer) const final;
207 bool exists(const void *owner) const final;
208
209 private:
210 bool layer_exists(const CustomData &custom_data) const;
211};
212
218 private:
225 Map<std::string, const BuiltinAttributeProvider *> builtin_attribute_providers_;
230 Vector<const DynamicAttributesProvider *> dynamic_attribute_providers_;
234 VectorSet<AttrDomain> supported_domains_;
235
236 public:
239 : dynamic_attribute_providers_(dynamic_attribute_providers)
240 {
242 /* Use #add_new to make sure that no two builtin attributes have the same name. */
243 builtin_attribute_providers_.add_new(provider->name(), provider);
244 supported_domains_.add(provider->domain());
245 }
247 provider->foreach_domain([&](AttrDomain domain) { supported_domains_.add(domain); });
248 }
249 }
250
252 {
253 return builtin_attribute_providers_;
254 }
255
257 {
258 return dynamic_attribute_providers_;
259 }
260
262 {
263 return supported_domains_;
264 }
265};
266
268
269template<const GeometryAttributeProviders &providers>
270inline std::optional<AttributeDomainAndType> builtin_domain_and_type(const void * /*owner*/,
271 const StringRef name)
272{
273 if (const BuiltinAttributeProvider *provider =
274 providers.builtin_attribute_providers().lookup_default_as(name, nullptr))
275 {
276 const AttrType data_type = *custom_data_type_to_attr_type(provider->data_type());
277 return AttributeDomainAndType{provider->domain(), data_type};
278 }
279 return std::nullopt;
280}
281
282template<const GeometryAttributeProviders &providers>
283inline GPointer builtin_default_value(const void * /*owner*/, const StringRef attribute_id)
284{
285 if (const BuiltinAttributeProvider *provider =
286 providers.builtin_attribute_providers().lookup_default_as(attribute_id, nullptr))
287 {
288 return provider->default_value();
289 }
290 return {};
291}
292
293template<const GeometryAttributeProviders &providers>
294inline GAttributeReader lookup(const void *owner, const StringRef name)
295{
296 if (const BuiltinAttributeProvider *provider =
297 providers.builtin_attribute_providers().lookup_default_as(name, nullptr))
298 {
299 return provider->try_get_for_read(owner);
300 }
301 for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
302 GAttributeReader attribute = provider->try_get_for_read(owner, name);
303 if (attribute) {
304 return attribute;
305 }
306 }
307 return {};
308}
309
310template<const GeometryAttributeProviders &providers>
311inline void foreach_attribute(const void *owner,
312 const FunctionRef<void(const AttributeIter &)> fn,
313 const AttributeAccessor &accessor)
314{
315 Set<StringRef, 16> handled_attribute_ids;
316 for (const BuiltinAttributeProvider *provider : providers.builtin_attribute_providers().values())
317 {
318 if (provider->exists(owner)) {
319 const auto get_fn = [&]() { return provider->try_get_for_read(owner); };
320 AttributeIter iter{provider->name(),
321 provider->domain(),
322 *custom_data_type_to_attr_type(provider->data_type()),
323 get_fn};
324 iter.is_builtin = true;
325 iter.accessor = &accessor;
326 fn(iter);
327 if (iter.is_stopped()) {
328 return;
329 }
330 handled_attribute_ids.add(iter.name);
331 }
332 }
333 for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
334 const bool continue_loop = provider->foreach_attribute(owner, [&](const AttributeIter &iter) {
335 if (handled_attribute_ids.add(iter.name)) {
336 iter.accessor = &accessor;
337 fn(iter);
338 }
339 });
340 if (!continue_loop) {
341 return;
342 }
343 }
344}
345
346template<const GeometryAttributeProviders &providers>
347inline AttributeValidator lookup_validator(const void * /*owner*/, const blender::StringRef name)
348{
349 const BuiltinAttributeProvider *provider =
350 providers.builtin_attribute_providers().lookup_default_as(name, nullptr);
351 if (!provider) {
352 return {};
353 }
354 return provider->validator();
355}
356
357template<const GeometryAttributeProviders &providers>
359{
360 if (const BuiltinAttributeProvider *provider =
361 providers.builtin_attribute_providers().lookup_default_as(name, nullptr))
362 {
363 return provider->try_get_for_write(owner);
364 }
365 for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
366 GAttributeWriter attribute = provider->try_get_for_write(owner, name);
367 if (attribute) {
368 return attribute;
369 }
370 }
371 return {};
372}
373
374template<const GeometryAttributeProviders &providers>
375inline bool remove(void *owner, const StringRef name)
376{
377 if (const BuiltinAttributeProvider *provider =
378 providers.builtin_attribute_providers().lookup_default_as(name, nullptr))
379 {
380 return provider->try_delete(owner);
381 }
382 for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
383 if (provider->try_delete(owner, name)) {
384 return true;
385 }
386 }
387 return false;
388}
389
390template<const GeometryAttributeProviders &providers>
391inline bool add(void *owner,
392 const StringRef name,
393 const AttrDomain domain,
394 const AttrType data_type,
395 const AttributeInit &initializer)
396{
397 const eCustomDataType custom_data_type = *attr_type_to_custom_data_type(data_type);
398 if (const BuiltinAttributeProvider *provider =
399 providers.builtin_attribute_providers().lookup_default_as(name, nullptr))
400 {
401 if (provider->domain() != domain) {
402 return false;
403 }
404 if (provider->data_type() != custom_data_type) {
405 return false;
406 }
407 return provider->try_create(owner, initializer);
408 }
409 for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
410 if (provider->try_create(owner, name, domain, custom_data_type, initializer)) {
411 return true;
412 }
413 }
414 return false;
415}
416
417template<const GeometryAttributeProviders &providers>
432
433} // namespace attribute_accessor_functions
434
435} // namespace blender::bke
#define final(a, b, c)
Definition BLI_hash.h:19
#define UNUSED_VARS(...)
#define CD_MASK_PROP_ALL
unsigned long long int uint64_t
bool add(const Key &key)
Definition BLI_set.hh:248
const AttributeAccessor * accessor
virtual bool try_delete(void *owner) const =0
virtual bool try_create(void *owner, const AttributeInit &initializer) const =0
virtual GAttributeReader try_get_for_read(const void *owner) const =0
virtual GAttributeWriter try_get_for_write(void *owner) const =0
virtual bool exists(const void *owner) const =0
BuiltinAttributeProvider(std::string name, const AttrDomain domain, const eCustomDataType data_type, const DeletableEnum deletable, AttributeValidator validator={}, const GPointer default_value={})
GAttributeWriter try_get_for_write(void *owner) const final
bool try_create(void *owner, const AttributeInit &initializer) const final
BuiltinCustomDataLayerProvider(std::string attribute_name, const AttrDomain domain, const eCustomDataType data_type, const DeletableEnum deletable, const CustomDataAccessInfo custom_data_access, const AttrUpdateOnChange update_on_change, const AttributeValidator validator={}, const GPointer default_value={})
bool exists(const void *owner) const final
GAttributeReader try_get_for_read(const void *owner) const final
GAttributeWriter try_get_for_write(void *owner, StringRef attribute_id) const final
CustomDataAttributeProvider(const AttrDomain domain, const CustomDataAccessInfo custom_data_access)
bool try_delete(void *owner, StringRef attribute_id) const final
GAttributeReader try_get_for_read(const void *owner, StringRef attribute_id) const final
bool foreach_attribute(const void *owner, FunctionRef< void(const AttributeIter &)> fn) const final
bool try_create(void *owner, StringRef attribute_id, AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer) const final
void foreach_domain(const FunctionRef< void(AttrDomain)> callback) const final
virtual bool try_create(void *owner, const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer) const
virtual GAttributeReader try_get_for_read(const void *owner, StringRef attribute_id) const =0
virtual GAttributeWriter try_get_for_write(void *owner, StringRef attribute_id) const =0
virtual bool try_delete(void *owner, StringRef attribute_id) const =0
virtual void foreach_domain(const FunctionRef< void(AttrDomain)> callback) const =0
virtual bool foreach_attribute(const void *owner, FunctionRef< void(const AttributeIter &)> fn) const =0
const Map< std::string, const BuiltinAttributeProvider * > & builtin_attribute_providers() const
Span< const DynamicAttributesProvider * > dynamic_attribute_providers() const
GeometryAttributeProviders(Span< const BuiltinAttributeProvider * > builtin_attribute_providers, Span< const DynamicAttributesProvider * > dynamic_attribute_providers)
AttributeAccessorFunctions accessor_functions_for_providers()
GAttributeWriter lookup_for_write(void *owner, const StringRef name)
GPointer builtin_default_value(const void *, const StringRef attribute_id)
bool remove(void *owner, const StringRef name)
void foreach_attribute(const void *owner, const FunctionRef< void(const AttributeIter &)> fn, const AttributeAccessor &accessor)
std::optional< AttributeDomainAndType > builtin_domain_and_type(const void *, const StringRef name)
AttributeValidator lookup_validator(const void *, const blender::StringRef name)
bool add(void *owner, const StringRef name, const AttrDomain domain, const AttrType data_type, const AttributeInit &initializer)
GAttributeReader lookup(const void *owner, const StringRef name)
std::optional< eCustomDataType > attr_type_to_custom_data_type(AttrType attr_type)
std::optional< AttrType > custom_data_type_to_attr_type(eCustomDataType data_type)
const char * name
CustomData *(*)(void *owner) CustomDataGetter
std::function< void()>(*)(void *owner, StringRef name) GetTagModifiedFunction
const CustomData *(*)(const void *owner) ConstCustomDataGetter