Blender  V3.3
attribute_access_intern.hh
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "BLI_map.hh"
4 #include "BLI_span.hh"
5 #include "BLI_string_ref.hh"
6 #include "BLI_vector.hh"
7 #include "BLI_vector_set.hh"
8 
9 #include "BKE_geometry_set.hh"
10 
11 namespace blender::bke {
12 
18  using CustomDataGetter = CustomData *(*)(void *owner);
19  using ConstCustomDataGetter = const CustomData *(*)(const void *owner);
20  using GetElementNum = int (*)(const void *owner);
21  using UpdateCustomDataPointers = void (*)(void *owner);
22 
27 };
28 
35  public:
36  /* Some utility enums to avoid hard to read booleans in function calls. */
40  };
41  enum WritableEnum {
44  };
48  };
49 
50  protected:
51  const std::string name_;
57 
58  public:
60  const eAttrDomain domain,
62  const CreatableEnum createable,
63  const WritableEnum writable,
64  const DeletableEnum deletable)
65  : name_(std::move(name)),
66  domain_(domain),
68  createable_(createable),
69  writable_(writable),
70  deletable_(deletable)
71  {
72  }
73 
74  virtual GVArray try_get_for_read(const void *owner) const = 0;
75  virtual GAttributeWriter try_get_for_write(void *owner) const = 0;
76  virtual bool try_delete(void *owner) const = 0;
77  virtual bool try_create(void *onwer, const AttributeInit &initializer) const = 0;
78  virtual bool exists(const void *owner) const = 0;
79 
81  {
82  return name_;
83  }
84 
86  {
87  return domain_;
88  }
89 
91  {
92  return data_type_;
93  }
94 };
95 
101  public:
102  virtual GAttributeReader try_get_for_read(const void *owner,
103  const AttributeIDRef &attribute_id) const = 0;
104  virtual GAttributeWriter try_get_for_write(void *owner,
105  const AttributeIDRef &attribute_id) const = 0;
106  virtual bool try_delete(void *owner, const AttributeIDRef &attribute_id) const = 0;
107  virtual bool try_create(void *owner,
108  const AttributeIDRef &attribute_id,
109  const eAttrDomain domain,
110  const eCustomDataType data_type,
111  const AttributeInit &initializer) const
112  {
113  UNUSED_VARS(owner, attribute_id, domain, data_type, initializer);
114  /* Some providers should not create new attributes. */
115  return false;
116  };
117 
118  virtual bool foreach_attribute(const void *owner,
119  const AttributeForeachCallback callback) const = 0;
120  virtual void foreach_domain(const FunctionRef<void(eAttrDomain)> callback) const = 0;
121 };
122 
127  private:
128  static constexpr uint64_t supported_types_mask = CD_MASK_PROP_ALL;
129  const eAttrDomain domain_;
130  const CustomDataAccessInfo custom_data_access_;
131 
132  public:
134  const CustomDataAccessInfo custom_data_access)
135  : domain_(domain), custom_data_access_(custom_data_access)
136  {
137  }
138 
139  GAttributeReader try_get_for_read(const void *owner,
140  const AttributeIDRef &attribute_id) const final;
141 
142  GAttributeWriter try_get_for_write(void *owner, const AttributeIDRef &attribute_id) const final;
143 
144  bool try_delete(void *owner, const AttributeIDRef &attribute_id) const final;
145 
146  bool try_create(void *owner,
147  const AttributeIDRef &attribute_id,
148  eAttrDomain domain,
149  const eCustomDataType data_type,
150  const AttributeInit &initializer) const final;
151 
152  bool foreach_attribute(const void *owner, const AttributeForeachCallback callback) const final;
153 
154  void foreach_domain(const FunctionRef<void(eAttrDomain)> callback) const final
155  {
156  callback(domain_);
157  }
158 
159  private:
160  bool type_is_supported(eCustomDataType data_type) const
161  {
162  return ((1ULL << data_type) & supported_types_mask) != 0;
163  }
164 };
165 
170  private:
171  using AsReadAttribute = GVArray (*)(const void *data, int domain_num);
172  using AsWriteAttribute = GVMutableArray (*)(void *data, int domain_num);
173  const eAttrDomain domain_;
174  const eCustomDataType attribute_type_;
175  const eCustomDataType stored_type_;
176  const CustomDataAccessInfo custom_data_access_;
177  const AsReadAttribute as_read_attribute_;
178  const AsWriteAttribute as_write_attribute_;
179 
180  public:
182  const eCustomDataType attribute_type,
183  const eCustomDataType stored_type,
184  const CustomDataAccessInfo custom_data_access,
185  const AsReadAttribute as_read_attribute,
186  const AsWriteAttribute as_write_attribute)
187  : domain_(domain),
188  attribute_type_(attribute_type),
189  stored_type_(stored_type),
190  custom_data_access_(custom_data_access),
191  as_read_attribute_(as_read_attribute),
192  as_write_attribute_(as_write_attribute)
193  {
194  }
195 
196  GAttributeReader try_get_for_read(const void *owner,
197  const AttributeIDRef &attribute_id) const final;
198  GAttributeWriter try_get_for_write(void *owner, const AttributeIDRef &attribute_id) const final;
199  bool try_delete(void *owner, const AttributeIDRef &attribute_id) const final;
200  bool foreach_attribute(const void *owner, const AttributeForeachCallback callback) const final;
201  void foreach_domain(const FunctionRef<void(eAttrDomain)> callback) const final;
202 };
203 
204 template<typename T> GVArray make_array_read_attribute(const void *data, const int domain_num)
205 {
206  return VArray<T>::ForSpan(Span<T>((const T *)data, domain_num));
207 }
208 
209 template<typename T> GVMutableArray make_array_write_attribute(void *data, const int domain_num)
210 {
212 }
213 
223  using AsReadAttribute = GVArray (*)(const void *data, int element_num);
224  using AsWriteAttribute = GVMutableArray (*)(void *data, int element_num);
225  using UpdateOnRead = void (*)(const void *owner);
226  using UpdateOnChange = void (*)(void *owner);
227  const eCustomDataType stored_type_;
228  const CustomDataAccessInfo custom_data_access_;
229  const AsReadAttribute as_read_attribute_;
230  const AsWriteAttribute as_write_attribute_;
231  const UpdateOnChange update_on_change_;
232  bool stored_as_named_attribute_;
233 
234  public:
235  BuiltinCustomDataLayerProvider(std::string attribute_name,
236  const eAttrDomain domain,
237  const eCustomDataType attribute_type,
238  const eCustomDataType stored_type,
239  const CreatableEnum creatable,
240  const WritableEnum writable,
241  const DeletableEnum deletable,
242  const CustomDataAccessInfo custom_data_access,
243  const AsReadAttribute as_read_attribute,
244  const AsWriteAttribute as_write_attribute,
245  const UpdateOnChange update_on_write)
247  std::move(attribute_name), domain, attribute_type, creatable, writable, deletable),
248  stored_type_(stored_type),
249  custom_data_access_(custom_data_access),
250  as_read_attribute_(as_read_attribute),
251  as_write_attribute_(as_write_attribute),
252  update_on_change_(update_on_write),
253  stored_as_named_attribute_(data_type_ == stored_type_)
254  {
255  }
256 
257  GVArray try_get_for_read(const void *owner) const final;
258  GAttributeWriter try_get_for_write(void *owner) const final;
259  bool try_delete(void *owner) const final;
260  bool try_create(void *owner, const AttributeInit &initializer) const final;
261  bool exists(const void *owner) const final;
262 };
263 
269  private:
276  Map<std::string, const BuiltinAttributeProvider *> builtin_attribute_providers_;
281  Vector<const DynamicAttributesProvider *> dynamic_attribute_providers_;
285  VectorSet<eAttrDomain> supported_domains_;
286 
287  public:
290  : dynamic_attribute_providers_(dynamic_attribute_providers)
291  {
292  for (const BuiltinAttributeProvider *provider : builtin_attribute_providers) {
293  /* Use #add_new to make sure that no two builtin attributes have the same name. */
294  builtin_attribute_providers_.add_new(provider->name(), provider);
295  supported_domains_.add(provider->domain());
296  }
298  provider->foreach_domain([&](eAttrDomain domain) { supported_domains_.add(domain); });
299  }
300  }
301 
303  {
304  return builtin_attribute_providers_;
305  }
306 
308  {
309  return dynamic_attribute_providers_;
310  }
311 
313  {
314  return supported_domains_;
315  }
316 };
317 
318 namespace attribute_accessor_functions {
319 
320 template<const ComponentAttributeProviders &providers>
321 inline bool is_builtin(const void *UNUSED(owner), const AttributeIDRef &attribute_id)
322 {
323  if (!attribute_id.is_named()) {
324  return false;
325  }
326  const StringRef name = attribute_id.name();
327  return providers.builtin_attribute_providers().contains_as(name);
328 }
329 
330 template<const ComponentAttributeProviders &providers>
331 inline GAttributeReader lookup(const void *owner, const AttributeIDRef &attribute_id)
332 {
333  if (attribute_id.is_named()) {
334  const StringRef name = attribute_id.name();
335  if (const BuiltinAttributeProvider *provider =
336  providers.builtin_attribute_providers().lookup_default_as(name, nullptr)) {
337  return {provider->try_get_for_read(owner), provider->domain()};
338  }
339  }
340  for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
341  GAttributeReader attribute = provider->try_get_for_read(owner, attribute_id);
342  if (attribute) {
343  return attribute;
344  }
345  }
346  return {};
347 }
348 
349 template<const ComponentAttributeProviders &providers>
350 inline bool for_all(const void *owner,
351  FunctionRef<bool(const AttributeIDRef &, const AttributeMetaData &)> fn)
352 {
353  Set<AttributeIDRef> handled_attribute_ids;
354  for (const BuiltinAttributeProvider *provider :
355  providers.builtin_attribute_providers().values()) {
356  if (provider->exists(owner)) {
357  AttributeMetaData meta_data{provider->domain(), provider->data_type()};
358  if (!fn(provider->name(), meta_data)) {
359  return false;
360  }
361  handled_attribute_ids.add_new(provider->name());
362  }
363  }
364  for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
365  const bool continue_loop = provider->foreach_attribute(
366  owner, [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
367  if (handled_attribute_ids.add(attribute_id)) {
368  return fn(attribute_id, meta_data);
369  }
370  return true;
371  });
372  if (!continue_loop) {
373  return false;
374  }
375  }
376  return true;
377 }
378 
379 template<const ComponentAttributeProviders &providers>
380 inline bool contains(const void *owner, const blender::bke::AttributeIDRef &attribute_id)
381 {
382  bool found = false;
383  for_all<providers>(
384  owner,
385  [&](const AttributeIDRef &other_attribute_id, const AttributeMetaData & /* meta_data */) {
386  if (attribute_id == other_attribute_id) {
387  found = true;
388  return false;
389  }
390  return true;
391  });
392  return found;
393 }
394 
395 template<const ComponentAttributeProviders &providers>
396 inline std::optional<AttributeMetaData> lookup_meta_data(const void *owner,
397  const AttributeIDRef &attribute_id)
398 {
399  std::optional<AttributeMetaData> meta_data;
400  for_all<providers>(
401  owner,
402  [&](const AttributeIDRef &other_attribute_id, const AttributeMetaData &other_meta_data) {
403  if (attribute_id == other_attribute_id) {
404  meta_data = other_meta_data;
405  return false;
406  }
407  return true;
408  });
409  return meta_data;
410 }
411 
412 template<const ComponentAttributeProviders &providers>
413 inline GAttributeWriter lookup_for_write(void *owner, const AttributeIDRef &attribute_id)
414 {
415  if (attribute_id.is_named()) {
416  const StringRef name = attribute_id.name();
417  if (const BuiltinAttributeProvider *provider =
418  providers.builtin_attribute_providers().lookup_default_as(name, nullptr)) {
419  return provider->try_get_for_write(owner);
420  }
421  }
422  for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
423  GAttributeWriter attribute = provider->try_get_for_write(owner, attribute_id);
424  if (attribute) {
425  return attribute;
426  }
427  }
428  return {};
429 }
430 
431 template<const ComponentAttributeProviders &providers>
432 inline bool remove(void *owner, const AttributeIDRef &attribute_id)
433 {
434  if (attribute_id.is_named()) {
435  const StringRef name = attribute_id.name();
436  if (const BuiltinAttributeProvider *provider =
437  providers.builtin_attribute_providers().lookup_default_as(name, nullptr)) {
438  return provider->try_delete(owner);
439  }
440  }
441  bool success = false;
442  for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
443  success = provider->try_delete(owner, attribute_id) || success;
444  }
445  return success;
446 }
447 
448 template<const ComponentAttributeProviders &providers>
449 inline bool add(void *owner,
450  const AttributeIDRef &attribute_id,
451  eAttrDomain domain,
452  eCustomDataType data_type,
453  const AttributeInit &initializer)
454 {
455  if (contains<providers>(owner, attribute_id)) {
456  return false;
457  }
458  if (attribute_id.is_named()) {
459  const StringRef name = attribute_id.name();
460  if (const BuiltinAttributeProvider *provider =
461  providers.builtin_attribute_providers().lookup_default_as(name, nullptr)) {
462  if (provider->domain() != domain) {
463  return false;
464  }
465  if (provider->data_type() != data_type) {
466  return false;
467  }
468  return provider->try_create(owner, initializer);
469  }
470  }
471  for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
472  if (provider->try_create(owner, attribute_id, domain, data_type, initializer)) {
473  return true;
474  }
475  }
476  return false;
477 }
478 
479 template<const ComponentAttributeProviders &providers>
481 {
482  return AttributeAccessorFunctions{contains<providers>,
483  lookup_meta_data<providers>,
484  nullptr,
485  nullptr,
486  is_builtin<providers>,
487  lookup<providers>,
488  nullptr,
489  for_all<providers>,
490  lookup_for_write<providers>,
491  remove<providers>,
492  add<providers>};
493 }
494 
495 } // namespace attribute_accessor_functions
496 
497 } // namespace blender::bke
eAttrDomain
Definition: BKE_attribute.h:25
#define final(a, b, c)
Definition: BLI_hash.h:21
#define UNUSED_VARS(...)
#define UNUSED(x)
#define CD_MASK_PROP_ALL
eCustomDataType
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
void add_new(const Key &key, const Value &value)
Definition: BLI_map.hh:220
bool add(const Key &key)
Definition: BLI_set.hh:253
void add_new(const Key &key)
Definition: BLI_set.hh:238
static VArray ForSpan(Span< T > values)
static VMutableArray ForSpan(MutableSpan< T > values)
bool add(const Key &key)
virtual bool try_delete(void *owner) const =0
BuiltinAttributeProvider(std::string name, const eAttrDomain domain, const eCustomDataType data_type, const CreatableEnum createable, const WritableEnum writable, const DeletableEnum deletable)
virtual bool try_create(void *onwer, const AttributeInit &initializer) const =0
virtual GAttributeWriter try_get_for_write(void *owner) const =0
virtual bool exists(const void *owner) const =0
virtual GVArray try_get_for_read(const void *owner) const =0
BuiltinCustomDataLayerProvider(std::string attribute_name, const eAttrDomain domain, const eCustomDataType attribute_type, const eCustomDataType stored_type, const CreatableEnum creatable, const WritableEnum writable, const DeletableEnum deletable, const CustomDataAccessInfo custom_data_access, const AsReadAttribute as_read_attribute, const AsWriteAttribute as_write_attribute, const UpdateOnChange update_on_write)
GAttributeWriter try_get_for_write(void *owner) const final
bool try_create(void *owner, const AttributeInit &initializer) const final
bool exists(const void *owner) const final
GVArray try_get_for_read(const void *owner) const final
Span< const DynamicAttributesProvider * > dynamic_attribute_providers() const
const Map< std::string, const BuiltinAttributeProvider * > & builtin_attribute_providers() const
ComponentAttributeProviders(Span< const BuiltinAttributeProvider * > builtin_attribute_providers, Span< const DynamicAttributesProvider * > dynamic_attribute_providers)
CustomDataAttributeProvider(const eAttrDomain domain, const CustomDataAccessInfo custom_data_access)
bool try_delete(void *owner, const AttributeIDRef &attribute_id) const final
GAttributeWriter try_get_for_write(void *owner, const AttributeIDRef &attribute_id) const final
void foreach_domain(const FunctionRef< void(eAttrDomain)> callback) const final
bool try_create(void *owner, const AttributeIDRef &attribute_id, eAttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer) const final
bool foreach_attribute(const void *owner, const AttributeForeachCallback callback) const final
GAttributeReader try_get_for_read(const void *owner, const AttributeIDRef &attribute_id) const final
virtual bool try_create(void *owner, const AttributeIDRef &attribute_id, const eAttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer) const
virtual bool try_delete(void *owner, const AttributeIDRef &attribute_id) const =0
virtual bool foreach_attribute(const void *owner, const AttributeForeachCallback callback) const =0
virtual GAttributeReader try_get_for_read(const void *owner, const AttributeIDRef &attribute_id) const =0
virtual GAttributeWriter try_get_for_write(void *owner, const AttributeIDRef &attribute_id) const =0
virtual void foreach_domain(const FunctionRef< void(eAttrDomain)> callback) const =0
GAttributeWriter try_get_for_write(void *owner, const AttributeIDRef &attribute_id) const final
void foreach_domain(const FunctionRef< void(eAttrDomain)> callback) const final
GAttributeReader try_get_for_read(const void *owner, const AttributeIDRef &attribute_id) const final
bool foreach_attribute(const void *owner, const AttributeForeachCallback callback) const final
bool try_delete(void *owner, const AttributeIDRef &attribute_id) const final
NamedLegacyCustomDataProvider(const eAttrDomain domain, const eCustomDataType attribute_type, const eCustomDataType stored_type, const CustomDataAccessInfo custom_data_access, const AsReadAttribute as_read_attribute, const AsWriteAttribute as_write_attribute)
DEGForeachIDComponentCallback callback
SyclQueue void void size_t num_bytes void
#define T
AttributeAccessorFunctions accessor_functions_for_providers()
bool contains(const void *owner, const blender::bke::AttributeIDRef &attribute_id)
bool is_builtin(const void *UNUSED(owner), const AttributeIDRef &attribute_id)
GAttributeWriter lookup_for_write(void *owner, const AttributeIDRef &attribute_id)
bool add(void *owner, const AttributeIDRef &attribute_id, eAttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer)
GAttributeReader lookup(const void *owner, const AttributeIDRef &attribute_id)
std::optional< AttributeMetaData > lookup_meta_data(const void *owner, const AttributeIDRef &attribute_id)
bool remove(void *owner, const AttributeIDRef &attribute_id)
bool for_all(const void *owner, FunctionRef< bool(const AttributeIDRef &, const AttributeMetaData &)> fn)
static int domain_num(const CurvesGeometry &curves, const eAttrDomain domain)
GVArray make_array_read_attribute(const void *data, const int domain_num)
GVMutableArray make_array_write_attribute(void *data, const int domain_num)
unsigned __int64 uint64_t
Definition: stdint.h:90
CustomData *(*)(void *owner) CustomDataGetter
const CustomData *(*)(const void *owner) ConstCustomDataGetter
UpdateCustomDataPointers update_custom_data_pointers