Blender  V3.3
BKE_attribute.hh
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #pragma once
4 
5 #include "BLI_color.hh"
6 #include "BLI_function_ref.hh"
7 #include "BLI_generic_span.hh"
9 #include "BLI_math_vec_types.hh"
10 #include "BLI_set.hh"
11 
13 #include "BKE_attribute.h"
14 
15 struct Mesh;
16 struct PointCloud;
17 
18 namespace blender::bke {
19 
25  private:
26  StringRef name_;
27  const AnonymousAttributeID *anonymous_id_ = nullptr;
28 
29  public:
33  AttributeIDRef(const char *name);
34  AttributeIDRef(const std::string &name);
36 
37  operator bool() const;
38  uint64_t hash() const;
39  bool is_named() const;
40  bool is_anonymous() const;
41  StringRef name() const;
42  const AnonymousAttributeID &anonymous_id() const;
43  bool should_be_kept() const;
44 
45  friend bool operator==(const AttributeIDRef &a, const AttributeIDRef &b);
46  friend std::ostream &operator<<(std::ostream &stream, const AttributeIDRef &attribute_id);
47 };
48 
57 
59  {
60  return (a.domain == b.domain) && (a.data_type == b.data_type);
61  }
62 };
63 
64 struct AttributeKind {
67 };
68 
72 struct AttributeInit {
73  enum class Type {
74  Default,
75  VArray,
76  MoveArray,
77  };
80  {
81  }
82 };
83 
90  {
91  }
92 };
93 
102 
105  {
106  }
107 };
108 
121  void *data = nullptr;
122 
124  {
125  }
126 };
127 
128 /* Returns false when the iteration should be stopped. */
130  FunctionRef<bool(const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data)>;
131 
136 template<typename T> struct AttributeReader {
145 
146  operator bool() const
147  {
148  return this->varray;
149  }
150 };
151 
157 template<typename T> struct AttributeWriter {
171  std::function<void()> tag_modified_fn;
172 
173  operator bool() const
174  {
175  return this->varray;
176  }
177 
181  void finish()
182  {
183  if (this->tag_modified_fn) {
184  this->tag_modified_fn();
185  }
186  }
187 };
188 
194 template<typename T> struct SpanAttributeWriter {
206  std::function<void()> tag_modified_fn;
207 
208  SpanAttributeWriter() = default;
209 
210  SpanAttributeWriter(AttributeWriter<T> &&other, const bool copy_values_to_span)
211  : span(std::move(other.varray), copy_values_to_span),
212  domain(other.domain),
213  tag_modified_fn(std::move(other.tag_modified_fn))
214  {
215  }
216 
217  operator bool() const
218  {
219  return span.varray();
220  }
221 
227  void finish()
228  {
229  this->span.save();
230  if (this->tag_modified_fn) {
231  this->tag_modified_fn();
232  }
233  }
234 };
235 
242 
243  operator bool() const
244  {
245  return this->varray;
246  }
247 
248  template<typename T> AttributeReader<T> typed() const
249  {
250  return {varray.typed<T>(), domain};
251  }
252 };
253 
260  std::function<void()> tag_modified_fn;
261 
262  operator bool() const
263  {
264  return this->varray;
265  }
266 
267  void finish()
268  {
269  if (this->tag_modified_fn) {
270  this->tag_modified_fn();
271  }
272  }
273 
274  template<typename T> AttributeWriter<T> typed() const
275  {
276  return {varray.typed<T>(), domain, tag_modified_fn};
277  }
278 };
279 
286  std::function<void()> tag_modified_fn;
287 
288  GSpanAttributeWriter() = default;
289 
290  GSpanAttributeWriter(GAttributeWriter &&other, const bool copy_values_to_span)
291  : span(std::move(other.varray), copy_values_to_span),
292  domain(other.domain),
293  tag_modified_fn(std::move(other.tag_modified_fn))
294  {
295  }
296 
297  operator bool() const
298  {
299  return span.varray();
300  }
301 
302  void finish()
303  {
304  this->span.save();
305  if (this->tag_modified_fn) {
306  this->tag_modified_fn();
307  }
308  }
309 };
310 
320  bool (*contains)(const void *owner, const AttributeIDRef &attribute_id);
321  std::optional<AttributeMetaData> (*lookup_meta_data)(const void *owner,
322  const AttributeIDRef &attribute_id);
323  bool (*domain_supported)(const void *owner, eAttrDomain domain);
324  int (*domain_size)(const void *owner, eAttrDomain domain);
325  bool (*is_builtin)(const void *owner, const AttributeIDRef &attribute_id);
326  GAttributeReader (*lookup)(const void *owner, const AttributeIDRef &attribute_id);
327  GVArray (*adapt_domain)(const void *owner,
328  const GVArray &varray,
329  eAttrDomain from_domain,
330  eAttrDomain to_domain);
331  bool (*for_all)(const void *owner,
332  FunctionRef<bool(const AttributeIDRef &, const AttributeMetaData &)> fn);
333 
334  GAttributeWriter (*lookup_for_write)(void *owner, const AttributeIDRef &attribute_id);
335  bool (*remove)(void *owner, const AttributeIDRef &attribute_id);
336  bool (*add)(void *owner,
337  const AttributeIDRef &attribute_id,
338  eAttrDomain domain,
339  eCustomDataType data_type,
340  const AttributeInit &initializer);
341 };
342 
350  protected:
361  void *owner_;
366 
367  public:
368  AttributeAccessor(const void *owner, const AttributeAccessorFunctions &fn)
369  : owner_(const_cast<void *>(owner)), fn_(&fn)
370  {
371  }
372 
376  bool contains(const AttributeIDRef &attribute_id) const
377  {
378  return fn_->contains(owner_, attribute_id);
379  }
380 
384  std::optional<AttributeMetaData> lookup_meta_data(const AttributeIDRef &attribute_id) const
385  {
386  return fn_->lookup_meta_data(owner_, attribute_id);
387  }
388 
392  bool domain_supported(const eAttrDomain domain) const
393  {
394  return fn_->domain_supported(owner_, domain);
395  }
396 
400  int domain_size(const eAttrDomain domain) const
401  {
402  return fn_->domain_size(owner_, domain);
403  }
404 
409  bool is_builtin(const AttributeIDRef &attribute_id) const
410  {
411  return fn_->is_builtin(owner_, attribute_id);
412  }
413 
418  GAttributeReader lookup(const AttributeIDRef &attribute_id) const
419  {
420  return fn_->lookup(owner_, attribute_id);
421  }
422 
427  GVArray lookup(const AttributeIDRef &attribute_id,
428  const std::optional<eAttrDomain> domain,
429  const std::optional<eCustomDataType> data_type) const;
430 
435  GVArray lookup(const AttributeIDRef &attribute_id, const eAttrDomain domain) const
436  {
437  return this->lookup(attribute_id, domain, std::nullopt);
438  }
439 
444  GVArray lookup(const AttributeIDRef &attribute_id, const eCustomDataType data_type) const
445  {
446  return this->lookup(attribute_id, std::nullopt, data_type);
447  }
448 
453  template<typename T>
454  VArray<T> lookup(const AttributeIDRef &attribute_id,
455  const std::optional<eAttrDomain> domain = std::nullopt) const
456  {
457  const CPPType &cpp_type = CPPType::get<T>();
458  const eCustomDataType data_type = cpp_type_to_custom_data_type(cpp_type);
459  return this->lookup(attribute_id, domain, data_type).typed<T>();
460  }
461 
468  GVArray lookup_or_default(const AttributeIDRef &attribute_id,
469  const eAttrDomain domain,
470  const eCustomDataType data_type,
471  const void *default_value = nullptr) const;
472 
476  template<typename T>
478  const eAttrDomain domain,
479  const T &default_value) const
480  {
481  if (VArray<T> varray = this->lookup<T>(attribute_id, domain)) {
482  return varray;
483  }
484  return VArray<T>::ForSingle(default_value, this->domain_size(domain));
485  }
486 
490  GVArray adapt_domain(const GVArray &varray,
491  const eAttrDomain from_domain,
492  const eAttrDomain to_domain) const
493  {
494  return fn_->adapt_domain(owner_, varray, from_domain, to_domain);
495  }
496 
500  template<typename T>
502  const eAttrDomain from_domain,
503  const eAttrDomain to_domain) const
504  {
505  return this->adapt_domain(GVArray(varray), from_domain, to_domain).typed<T>();
506  }
507 
511  bool for_all(const AttributeForeachCallback fn) const
512  {
513  if (owner_ != nullptr) {
514  return fn_->for_all(owner_, fn);
515  }
516  return true;
517  }
518 
523 };
524 
530  public:
532  : AttributeAccessor(owner, fn)
533  {
534  }
535 
540  GAttributeWriter lookup_for_write(const AttributeIDRef &attribute_id);
541 
546  template<typename T> AttributeWriter<T> lookup_for_write(const AttributeIDRef &attribute_id)
547  {
548  GAttributeWriter attribute = this->lookup_for_write(attribute_id);
549  if (!attribute) {
550  return {};
551  }
552  if (!attribute.varray.type().is<T>()) {
553  return {};
554  }
555  return attribute.typed<T>();
556  }
557 
563  bool add(const AttributeIDRef &attribute_id,
564  const eAttrDomain domain,
565  const eCustomDataType data_type,
566  const AttributeInit &initializer)
567  {
568  return fn_->add(owner_, attribute_id, domain, data_type, initializer);
569  }
570 
577  const AttributeIDRef &attribute_id,
578  const eAttrDomain domain,
579  const eCustomDataType data_type,
580  const AttributeInit &initializer = AttributeInitDefault());
581 
588  const AttributeIDRef &attribute_id,
589  const eAttrDomain domain,
590  const eCustomDataType data_type,
591  const AttributeInit &initializer = AttributeInitDefault());
592 
596  template<typename T>
598  const AttributeIDRef &attribute_id,
599  const eAttrDomain domain,
600  const AttributeInit &initializer = AttributeInitDefault())
601  {
602  const CPPType &cpp_type = CPPType::get<T>();
603  const eCustomDataType data_type = cpp_type_to_custom_data_type(cpp_type);
604  return this->lookup_or_add_for_write(attribute_id, domain, data_type, initializer).typed<T>();
605  }
606 
610  template<typename T>
612  const AttributeIDRef &attribute_id,
613  const eAttrDomain domain,
614  const AttributeInit &initializer = AttributeInitDefault())
615  {
616  AttributeWriter<T> attribute = this->lookup_or_add_for_write<T>(
617  attribute_id, domain, initializer);
618  if (attribute) {
619  return SpanAttributeWriter<T>{std::move(attribute), true};
620  }
621  return {};
622  }
623 
633  const eAttrDomain domain,
634  const eCustomDataType data_type);
635 
639  template<typename T>
641  const eAttrDomain domain)
642  {
643  AttributeWriter<T> attribute = this->lookup_or_add_for_write<T>(attribute_id, domain);
644  if (attribute) {
645  return SpanAttributeWriter<T>{std::move(attribute), false};
646  }
647  return {};
648  }
649 
655  bool remove(const AttributeIDRef &attribute_id)
656  {
657  return fn_->remove(owner_, attribute_id);
658  }
659 
663  void remove_anonymous();
664 };
665 
667  /* Expect that if an attribute exists, it is stored as a contiguous array internally anyway. */
671 };
677  const bke::AttributeAccessor src_attributes,
678  bke::MutableAttributeAccessor dst_attributes,
679  eAttrDomainMask domain_mask,
680  const Set<std::string> &skip = {});
681 
682 bool allow_procedural_attribute_access(StringRef attribute_name);
683 extern const char *no_procedural_access_message;
684 
691 
702  int size_;
703 
704  public:
706 
712 
713  void reallocate(int size);
714 
715  void clear();
716 
717  std::optional<blender::GSpan> get_for_read(const AttributeIDRef &attribute_id) const;
718 
724  blender::GVArray get_for_read(const AttributeIDRef &attribute_id,
725  eCustomDataType data_type,
726  const void *default_value) const;
727 
728  template<typename T>
729  blender::VArray<T> get_for_read(const AttributeIDRef &attribute_id, const T &default_value) const
730  {
731  const blender::CPPType &cpp_type = blender::CPPType::get<T>();
733  GVArray varray = this->get_for_read(attribute_id, type, &default_value);
734  return varray.typed<T>();
735  }
736 
737  std::optional<blender::GMutableSpan> get_for_write(const AttributeIDRef &attribute_id);
738  bool create(const AttributeIDRef &attribute_id, eCustomDataType data_type);
739  bool create_by_move(const AttributeIDRef &attribute_id, eCustomDataType data_type, void *buffer);
740  bool remove(const AttributeIDRef &attribute_id);
741 
745  void reorder(Span<AttributeIDRef> new_order);
746 
748 };
749 
750 AttributeAccessor mesh_attributes(const Mesh &mesh);
751 MutableAttributeAccessor mesh_attributes_for_write(Mesh &mesh);
752 
753 AttributeAccessor pointcloud_attributes(const PointCloud &pointcloud);
754 MutableAttributeAccessor pointcloud_attributes_for_write(PointCloud &pointcloud);
755 
756 /* -------------------------------------------------------------------- */
760 inline AttributeIDRef::AttributeIDRef() = default;
761 
762 inline AttributeIDRef::AttributeIDRef(StringRef name) : name_(name)
763 {
764 }
765 
767 {
768 }
769 
770 inline AttributeIDRef::AttributeIDRef(const char *name) : name_(name)
771 {
772 }
773 
774 inline AttributeIDRef::AttributeIDRef(const std::string &name) : name_(name)
775 {
776 }
777 
778 /* The anonymous id is only borrowed, the caller has to keep a reference to it. */
780  : anonymous_id_(anonymous_id)
781 {
782 }
783 
784 inline bool operator==(const AttributeIDRef &a, const AttributeIDRef &b)
785 {
786  return a.anonymous_id_ == b.anonymous_id_ && a.name_ == b.name_;
787 }
788 
789 inline AttributeIDRef::operator bool() const
790 {
791  return this->is_named() || this->is_anonymous();
792 }
793 
795 {
796  return get_default_hash_2(name_, anonymous_id_);
797 }
798 
799 inline bool AttributeIDRef::is_named() const
800 {
801  return !name_.is_empty();
802 }
803 
804 inline bool AttributeIDRef::is_anonymous() const
805 {
806  return anonymous_id_ != nullptr;
807 }
808 
810 {
811  BLI_assert(this->is_named());
812  return name_;
813 }
814 
816 {
817  BLI_assert(this->is_anonymous());
818  return *anonymous_id_;
819 }
820 
827 {
828  return this->is_named() || BKE_anonymous_attribute_id_has_strong_references(anonymous_id_);
829 }
830 
831 } // namespace blender::bke
bool BKE_anonymous_attribute_id_has_strong_references(const AnonymousAttributeID *anonymous_id)
Generic geometry attributes built on CustomData.
eAttrDomain
Definition: BKE_attribute.h:25
eAttrDomainMask
Definition: BKE_attribute.h:36
#define BLI_assert(a)
Definition: BLI_assert.h:46
eCustomDataType
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
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
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
const GVMutableArray & varray() const
VArray< T > typed() const
VMutableArray< T > typed() const
constexpr bool is_empty() const
static VArray ForSingle(T value, const int64_t size)
bool is_builtin(const AttributeIDRef &attribute_id) const
GVArray lookup(const AttributeIDRef &attribute_id, const eAttrDomain domain) const
GVArray adapt_domain(const GVArray &varray, const eAttrDomain from_domain, const eAttrDomain to_domain) const
VArray< T > lookup_or_default(const AttributeIDRef &attribute_id, const eAttrDomain domain, const T &default_value) const
int domain_size(const eAttrDomain domain) const
VArray< T > adapt_domain(const VArray< T > &varray, const eAttrDomain from_domain, const eAttrDomain to_domain) const
VArray< T > lookup(const AttributeIDRef &attribute_id, const std::optional< eAttrDomain > domain=std::nullopt) const
Set< AttributeIDRef > all_ids() const
bool contains(const AttributeIDRef &attribute_id) const
std::optional< AttributeMetaData > lookup_meta_data(const AttributeIDRef &attribute_id) const
AttributeAccessor(const void *owner, const AttributeAccessorFunctions &fn)
GVArray lookup(const AttributeIDRef &attribute_id, const eCustomDataType data_type) const
GAttributeReader lookup(const AttributeIDRef &attribute_id) const
GVArray lookup_or_default(const AttributeIDRef &attribute_id, const eAttrDomain domain, const eCustomDataType data_type, const void *default_value=nullptr) const
bool domain_supported(const eAttrDomain domain) const
bool for_all(const AttributeForeachCallback fn) const
const AttributeAccessorFunctions * fn_
friend std::ostream & operator<<(std::ostream &stream, const AttributeIDRef &attribute_id)
friend bool operator==(const AttributeIDRef &a, const AttributeIDRef &b)
const AnonymousAttributeID & anonymous_id() const
std::optional< blender::GSpan > get_for_read(const AttributeIDRef &attribute_id) const
bool create(const AttributeIDRef &attribute_id, eCustomDataType data_type)
blender::VArray< T > get_for_read(const AttributeIDRef &attribute_id, const T &default_value) const
CustomDataAttributes & operator=(const CustomDataAttributes &other)
std::optional< blender::GMutableSpan > get_for_write(const AttributeIDRef &attribute_id)
bool create_by_move(const AttributeIDRef &attribute_id, eCustomDataType data_type, void *buffer)
void reorder(Span< AttributeIDRef > new_order)
bool foreach_attribute(const AttributeForeachCallback callback, eAttrDomain domain) const
bool remove(const AttributeIDRef &attribute_id)
bool add(const AttributeIDRef &attribute_id, const eAttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
GAttributeWriter lookup_for_write(const AttributeIDRef &attribute_id)
AttributeWriter< T > lookup_or_add_for_write(const AttributeIDRef &attribute_id, const eAttrDomain domain, const AttributeInit &initializer=AttributeInitDefault())
GSpanAttributeWriter lookup_or_add_for_write_only_span(const AttributeIDRef &attribute_id, const eAttrDomain domain, const eCustomDataType data_type)
SpanAttributeWriter< T > lookup_or_add_for_write_only_span(const AttributeIDRef &attribute_id, const eAttrDomain domain)
bool remove(const AttributeIDRef &attribute_id)
GAttributeWriter lookup_or_add_for_write(const AttributeIDRef &attribute_id, const eAttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefault())
AttributeWriter< T > lookup_for_write(const AttributeIDRef &attribute_id)
GSpanAttributeWriter lookup_or_add_for_write_span(const AttributeIDRef &attribute_id, const eAttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefault())
MutableAttributeAccessor(void *owner, const AttributeAccessorFunctions &fn)
SpanAttributeWriter< T > lookup_or_add_for_write_span(const AttributeIDRef &attribute_id, const eAttrDomain domain, const AttributeInit &initializer=AttributeInitDefault())
DEGForeachIDComponentCallback callback
SyclQueue void void size_t num_bytes void
ccl_global float * buffer
#define T
static unsigned a[3]
Definition: RandGen.cpp:78
Vector< AttributeTransferData > retrieve_attributes_for_transfer(const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes, eAttrDomainMask domain_mask, const Set< std::string > &skip={})
eAttrDomain attribute_domain_highest_priority(Span< eAttrDomain > domains)
bool allow_procedural_attribute_access(StringRef attribute_name)
const char * no_procedural_access_message
AttributeAccessor pointcloud_attributes(const PointCloud &pointcloud)
eCustomDataType attribute_data_type_highest_complexity(Span< eCustomDataType > data_types)
MutableAttributeAccessor pointcloud_attributes_for_write(PointCloud &pointcloud)
AttributeAccessor mesh_attributes(const Mesh &mesh)
bool operator==(const AttributeIDRef &a, const AttributeIDRef &b)
eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
Definition: customdata.cc:5337
MutableAttributeAccessor mesh_attributes_for_write(Mesh &mesh)
uint64_t get_default_hash_2(const T1 &v1, const T2 &v2)
Definition: BLI_hash.hh:223
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
unsigned __int64 uint64_t
Definition: stdint.h:90
bool(* contains)(const void *owner, const AttributeIDRef &attribute_id)
bool(* is_builtin)(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(* add)(void *owner, const AttributeIDRef &attribute_id, eAttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer)
bool(* domain_supported)(const void *owner, eAttrDomain domain)
GVArray(* adapt_domain)(const void *owner, const GVArray &varray, eAttrDomain from_domain, eAttrDomain to_domain)
GAttributeWriter(* lookup_for_write)(void *owner, const AttributeIDRef &attribute_id)
int(* domain_size)(const void *owner, eAttrDomain domain)
bool(* for_all)(const void *owner, FunctionRef< bool(const AttributeIDRef &, const AttributeMetaData &)> fn)
GAttributeReader(* lookup)(const void *owner, const AttributeIDRef &attribute_id)
AttributeInitVArray(blender::GVArray varray)
AttributeInit(const Type type)
constexpr friend bool operator==(AttributeMetaData a, AttributeMetaData b)
bke::GSpanAttributeWriter dst
std::function< void()> tag_modified_fn
AttributeReader< T > typed() const
AttributeWriter< T > typed() const
std::function< void()> tag_modified_fn
GSpanAttributeWriter(GAttributeWriter &&other, const bool copy_values_to_span)
std::function< void()> tag_modified_fn
SpanAttributeWriter(AttributeWriter< T > &&other, const bool copy_values_to_span)
std::function< void()> tag_modified_fn