Blender V4.5
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
14#include "BKE_geometry_set.hh"
15
16namespace blender::bke {
17
33
41 public:
46
47 protected:
48 const std::string name_;
54
55 public:
57 const AttrDomain domain,
59 const DeletableEnum deletable,
61 const GPointer default_value = {})
62 : name_(std::move(name)),
65 deletable_(deletable),
68 {
69 }
70
71 virtual GAttributeReader try_get_for_read(const void *owner) const = 0;
72 virtual GAttributeWriter try_get_for_write(void *owner) const = 0;
73 virtual bool try_delete(void *owner) const = 0;
74 virtual bool try_create(void *owner, const AttributeInit &initializer) const = 0;
75 virtual bool exists(const void *owner) const = 0;
76
78 {
79 return name_;
80 }
81
83 {
84 return domain_;
85 }
86
88 {
89 return data_type_;
90 }
91
93 {
94 return validator_;
95 }
96
98 {
99 return default_value_;
100 }
101};
102
108 public:
109 virtual GAttributeReader try_get_for_read(const void *owner, StringRef attribute_id) const = 0;
110 virtual GAttributeWriter try_get_for_write(void *owner, StringRef attribute_id) const = 0;
111 virtual bool try_delete(void *owner, StringRef attribute_id) const = 0;
112 virtual bool try_create(void *owner,
113 const StringRef attribute_id,
114 const AttrDomain domain,
115 const eCustomDataType data_type,
116 const AttributeInit &initializer) const
117 {
118 UNUSED_VARS(owner, attribute_id, domain, data_type, initializer);
119 /* Some providers should not create new attributes. */
120 return false;
121 };
122
126 virtual bool foreach_attribute(const void *owner,
127 FunctionRef<void(const AttributeIter &)> fn) const = 0;
128 virtual void foreach_domain(const FunctionRef<void(AttrDomain)> callback) const = 0;
129};
130
135 private:
136 static constexpr uint64_t supported_types_mask = CD_MASK_PROP_ALL;
137 AttrDomain domain_;
138 CustomDataAccessInfo custom_data_access_;
139
140 public:
142 const CustomDataAccessInfo custom_data_access)
143 : domain_(domain), custom_data_access_(custom_data_access)
144 {
145 }
146
147 GAttributeReader try_get_for_read(const void *owner, StringRef attribute_id) const final;
148
149 GAttributeWriter try_get_for_write(void *owner, StringRef attribute_id) const final;
150
151 bool try_delete(void *owner, StringRef attribute_id) const final;
152
153 bool try_create(void *owner,
154 StringRef attribute_id,
155 AttrDomain domain,
156 const eCustomDataType data_type,
157 const AttributeInit &initializer) const final;
158
159 bool foreach_attribute(const void *owner,
160 FunctionRef<void(const AttributeIter &)> fn) const final;
161
162 void foreach_domain(const FunctionRef<void(AttrDomain)> callback) const final
163 {
164 callback(domain_);
165 }
166
167 private:
168 bool type_is_supported(eCustomDataType data_type) const
169 {
170 return ((1ULL << data_type) & supported_types_mask) != 0;
171 }
172};
173
182 using UpdateOnChange = void (*)(void *owner);
183 const CustomDataAccessInfo custom_data_access_;
184 const UpdateOnChange update_on_change_;
185
186 public:
187 BuiltinCustomDataLayerProvider(std::string attribute_name,
188 const AttrDomain domain,
190 const DeletableEnum deletable,
191 const CustomDataAccessInfo custom_data_access,
192 const UpdateOnChange update_on_change,
193 const AttributeValidator validator = {},
194 const GPointer default_value = {})
196 std::move(attribute_name), domain, data_type, deletable, validator, default_value),
197 custom_data_access_(custom_data_access),
198 update_on_change_(update_on_change)
199 {
200 }
201
202 GAttributeReader try_get_for_read(const void *owner) const final;
203 GAttributeWriter try_get_for_write(void *owner) const final;
204 bool try_delete(void *owner) const final;
205 bool try_create(void *owner, const AttributeInit &initializer) const final;
206 bool exists(const void *owner) const final;
207
208 private:
209 bool layer_exists(const CustomData &custom_data) const;
210};
211
217 private:
224 Map<std::string, const BuiltinAttributeProvider *> builtin_attribute_providers_;
229 Vector<const DynamicAttributesProvider *> dynamic_attribute_providers_;
233 VectorSet<AttrDomain> supported_domains_;
234
235 public:
238 : dynamic_attribute_providers_(dynamic_attribute_providers)
239 {
241 /* Use #add_new to make sure that no two builtin attributes have the same name. */
242 builtin_attribute_providers_.add_new(provider->name(), provider);
243 supported_domains_.add(provider->domain());
244 }
246 provider->foreach_domain([&](AttrDomain domain) { supported_domains_.add(domain); });
247 }
248 }
249
251 {
252 return builtin_attribute_providers_;
253 }
254
256 {
257 return dynamic_attribute_providers_;
258 }
259
261 {
262 return supported_domains_;
263 }
264};
265
267
268template<const GeometryAttributeProviders &providers>
269inline std::optional<AttributeDomainAndType> builtin_domain_and_type(const void * /*owner*/,
270 const StringRef name)
271{
272 if (const BuiltinAttributeProvider *provider =
273 providers.builtin_attribute_providers().lookup_default_as(name, nullptr))
274 {
275 return AttributeDomainAndType{provider->domain(), provider->data_type()};
276 }
277 return std::nullopt;
278}
279
280template<const GeometryAttributeProviders &providers>
281inline GPointer builtin_default_value(const void * /*owner*/, const StringRef attribute_id)
282{
283 if (const BuiltinAttributeProvider *provider =
284 providers.builtin_attribute_providers().lookup_default_as(attribute_id, nullptr))
285 {
286 return provider->default_value();
287 }
288 return {};
289}
290
291template<const GeometryAttributeProviders &providers>
292inline GAttributeReader lookup(const void *owner, const StringRef name)
293{
294 if (const BuiltinAttributeProvider *provider =
295 providers.builtin_attribute_providers().lookup_default_as(name, nullptr))
296 {
297 return provider->try_get_for_read(owner);
298 }
299 for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
300 GAttributeReader attribute = provider->try_get_for_read(owner, name);
301 if (attribute) {
302 return attribute;
303 }
304 }
305 return {};
306}
307
308template<const GeometryAttributeProviders &providers>
309inline void foreach_attribute(const void *owner,
310 const FunctionRef<void(const AttributeIter &)> fn,
311 const AttributeAccessor &accessor)
312{
313 Set<StringRef, 16> handled_attribute_ids;
314 for (const BuiltinAttributeProvider *provider : providers.builtin_attribute_providers().values())
315 {
316 if (provider->exists(owner)) {
317 const auto get_fn = [&]() { return provider->try_get_for_read(owner); };
318 AttributeIter iter{provider->name(), provider->domain(), provider->data_type(), get_fn};
319 iter.is_builtin = true;
320 iter.accessor = &accessor;
321 fn(iter);
322 if (iter.is_stopped()) {
323 return;
324 }
325 handled_attribute_ids.add(iter.name);
326 }
327 }
328 for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
329 const bool continue_loop = provider->foreach_attribute(owner, [&](const AttributeIter &iter) {
330 if (handled_attribute_ids.add(iter.name)) {
331 iter.accessor = &accessor;
332 fn(iter);
333 }
334 });
335 if (!continue_loop) {
336 return;
337 }
338 }
339}
340
341template<const GeometryAttributeProviders &providers>
342inline AttributeValidator lookup_validator(const void * /*owner*/, const blender::StringRef name)
343{
344 const BuiltinAttributeProvider *provider =
345 providers.builtin_attribute_providers().lookup_default_as(name, nullptr);
346 if (!provider) {
347 return {};
348 }
349 return provider->validator();
350}
351
352template<const GeometryAttributeProviders &providers>
353inline GAttributeWriter lookup_for_write(void *owner, const StringRef name)
354{
355 if (const BuiltinAttributeProvider *provider =
356 providers.builtin_attribute_providers().lookup_default_as(name, nullptr))
357 {
358 return provider->try_get_for_write(owner);
359 }
360 for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
361 GAttributeWriter attribute = provider->try_get_for_write(owner, name);
362 if (attribute) {
363 return attribute;
364 }
365 }
366 return {};
367}
368
369template<const GeometryAttributeProviders &providers>
370inline bool remove(void *owner, const StringRef name)
371{
372 if (const BuiltinAttributeProvider *provider =
373 providers.builtin_attribute_providers().lookup_default_as(name, nullptr))
374 {
375 return provider->try_delete(owner);
376 }
377 for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
378 if (provider->try_delete(owner, name)) {
379 return true;
380 }
381 }
382 return false;
383}
384
385template<const GeometryAttributeProviders &providers>
386inline bool add(void *owner,
387 const StringRef name,
388 AttrDomain domain,
389 eCustomDataType data_type,
390 const AttributeInit &initializer)
391{
392 if (const BuiltinAttributeProvider *provider =
393 providers.builtin_attribute_providers().lookup_default_as(name, nullptr))
394 {
395 if (provider->domain() != domain) {
396 return false;
397 }
398 if (provider->data_type() != data_type) {
399 return false;
400 }
401 return provider->try_create(owner, initializer);
402 }
403 for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
404 if (provider->try_create(owner, name, domain, data_type, initializer)) {
405 return true;
406 }
407 }
408 return false;
409}
410
411template<const GeometryAttributeProviders &providers>
426
427} // namespace attribute_accessor_functions
428
429} // namespace blender::bke
#define final(a, b, c)
Definition BLI_hash.h:19
#define UNUSED_VARS(...)
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 UpdateOnChange 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)
#define CD_MASK_PROP_ALL
AttributeAccessorFunctions accessor_functions_for_providers()
bool add(void *owner, const StringRef name, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer)
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)
GAttributeReader lookup(const void *owner, const StringRef name)
CustomData *(*)(void *owner) CustomDataGetter
std::function< void()>(*)(void *owner, StringRef name) GetTagModifiedFunction
const CustomData *(*)(const void *owner) ConstCustomDataGetter