Blender V4.3
BKE_attribute.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#pragma once
6
7#include <functional>
8#include <optional>
9
10#include "BLI_function_ref.hh"
11#include "BLI_generic_span.hh"
13#include "BLI_offset_indices.hh"
14#include "BLI_set.hh"
16
18#include "BKE_attribute.h"
20
21struct Mesh;
22struct PointCloud;
23namespace blender::fn {
24namespace multi_function {
25class MultiFunction;
26}
27class GField;
28} // namespace blender::fn
29
30namespace blender::bke {
31
32enum class AttrDomain : int8_t {
33 /* Used to choose automatically based on other data. */
34 Auto = -1,
35 /* Mesh, Curve or Point Cloud Point. */
36 Point = 0,
37 /* Mesh Edge. */
38 Edge = 1,
39 /* Mesh Face. */
40 Face = 2,
41 /* Mesh Corner. */
42 Corner = 3,
43 /* A single curve in a larger curve data-block. */
44 Curve = 4,
45 /* Instance. */
46 Instance = 5,
47 /* A layer in a grease pencil data-block. */
48 Layer = 6,
49};
50#define ATTR_DOMAIN_NUM 7
51
54
66
71
76 enum class Type {
82 VArray,
86 Shared,
87 };
89 AttributeInit(const Type type) : type(type) {}
90};
91
99
106
116
126 void *data = nullptr;
127
128 AttributeInitMoveArray(void *data) : AttributeInit(Type::MoveArray), data(data) {}
129};
130
136 const void *data = nullptr;
138
141 {
142 }
143};
144
145/* Returns false when the iteration should be stopped. */
147 FunctionRef<bool(StringRefNull attribute_id, const AttributeMetaData &meta_data)>;
148
153template<typename T> struct AttributeReader {
162
168
169 const VArray<T> &operator*() const &
170 {
171 return this->varray;
172 }
173
175 {
176 return this->varray;
177 }
178
180 {
181 return std::move(this->varray);
182 }
183
184 operator bool() const
185 {
186 return this->varray;
187 }
188};
189
200
201 operator bool() const
202 {
203 return this->function != nullptr;
204 }
209};
210
216template<typename T> struct AttributeWriter {
230 std::function<void()> tag_modified_fn;
231
232 operator bool() const
233 {
234 return this->varray;
235 }
236
240 void finish()
241 {
242 if (this->tag_modified_fn) {
243 this->tag_modified_fn();
244 }
245 }
246};
247
253template<typename T> struct SpanAttributeWriter {
265 std::function<void()> tag_modified_fn;
266
268
269 SpanAttributeWriter(AttributeWriter<T> &&other, const bool copy_values_to_span)
270 : span(std::move(other.varray), copy_values_to_span),
271 domain(other.domain),
272 tag_modified_fn(std::move(other.tag_modified_fn))
273 {
274 }
275
276 operator bool() const
277 {
278 return span.varray();
279 }
280
286 void finish()
287 {
288 if (this->span.varray()) {
289 this->span.save();
290 }
291 if (this->tag_modified_fn) {
292 this->tag_modified_fn();
293 }
294 }
295};
296
304
305 operator bool() const
306 {
307 return this->varray;
308 }
309
310 const GVArray &operator*() const &
311 {
312 return this->varray;
313 }
314
316 {
317 return this->varray;
318 }
319
321 {
322 return std::move(this->varray);
323 }
324
325 template<typename T> AttributeReader<T> typed() const
326 {
327 return {varray.typed<T>(), domain, sharing_info};
328 }
329};
330
337 std::function<void()> tag_modified_fn;
338
339 operator bool() const
340 {
341 return this->varray;
342 }
343
344 void finish()
345 {
346 if (this->tag_modified_fn) {
347 this->tag_modified_fn();
348 }
349 }
350
351 template<typename T> AttributeWriter<T> typed() const
352 {
353 return {varray.typed<T>(), domain, tag_modified_fn};
354 }
355};
356
363 std::function<void()> tag_modified_fn;
364
366
367 GSpanAttributeWriter(GAttributeWriter &&other, const bool copy_values_to_span)
368 : span(std::move(other.varray), copy_values_to_span),
369 domain(other.domain),
370 tag_modified_fn(std::move(other.tag_modified_fn))
371 {
372 }
373
374 operator bool() const
375 {
376 return span.varray();
377 }
378
379 void finish()
380 {
381 if (this->span.varray()) {
382 this->span.save();
383 }
384 if (this->tag_modified_fn) {
385 this->tag_modified_fn();
386 }
387 }
388};
389
395 public:
399 bool is_builtin = false;
400 mutable const AttributeAccessor *accessor = nullptr;
401
402 private:
403 FunctionRef<GAttributeReader()> get_fn_;
404 mutable bool stop_iteration_ = false;
405
406 public:
408 const AttrDomain domain,
410 const FunctionRef<GAttributeReader()> get_fn)
411 : name(name), domain(domain), data_type(data_type), get_fn_(get_fn)
412 {
413 }
414
416 void stop() const
417 {
418 stop_iteration_ = true;
419 }
420
421 bool is_stopped() const
422 {
423 return stop_iteration_;
424 }
425
428 {
429 return get_fn_();
430 }
431
433 GAttributeReader get(std::optional<AttrDomain> domain,
434 std::optional<eCustomDataType> data_type) const;
435
436 GAttributeReader get(const AttrDomain domain) const
437 {
438 return this->get(domain, std::nullopt);
439 }
440
442 {
443 return this->get(std::nullopt, data_type);
444 }
445
446 template<typename T>
447 AttributeReader<T> get(const std::optional<AttrDomain> domain = std::nullopt) const
448 {
449 const CPPType &cpp_type = CPPType::get<T>();
451 return this->get(domain, data_type).typed<T>();
452 }
453};
454
464 bool (*domain_supported)(const void *owner, AttrDomain domain);
465 int (*domain_size)(const void *owner, AttrDomain domain);
466 bool (*is_builtin)(const void *owner, StringRef attribute_id);
467 GAttributeReader (*lookup)(const void *owner, StringRef attribute_id);
468 GVArray (*adapt_domain)(const void *owner,
469 const GVArray &varray,
470 AttrDomain from_domain,
471 AttrDomain to_domain);
472 void (*foreach_attribute)(const void *owner,
473 FunctionRef<void(const AttributeIter &iter)> fn,
474 const AttributeAccessor &accessor);
475 AttributeValidator (*lookup_validator)(const void *owner, StringRef attribute_id);
476 GAttributeWriter (*lookup_for_write)(void *owner, StringRef attribute_id);
477 bool (*remove)(void *owner, StringRef attribute_id);
478 bool (*add)(void *owner,
479 StringRef attribute_id,
480 AttrDomain domain,
481 eCustomDataType data_type,
482 const AttributeInit &initializer);
483};
484
492 protected:
503 void *owner_;
508
509 public:
510 AttributeAccessor(const void *owner, const AttributeAccessorFunctions &fn)
511 : owner_(const_cast<void *>(owner)), fn_(&fn)
512 {
513 }
514
518 static std::optional<AttributeAccessor> from_id(const ID &id);
519
523 bool contains(const StringRef attribute_id) const;
524
528 std::optional<AttributeMetaData> lookup_meta_data(const StringRef attribute_id) const;
529
533 bool domain_supported(const AttrDomain domain) const
534 {
535 return fn_->domain_supported(owner_, domain);
536 }
537
541 int domain_size(const AttrDomain domain) const
542 {
543 return fn_->domain_size(owner_, domain);
544 }
545
550 bool is_builtin(const StringRef attribute_id) const
551 {
552 return fn_->is_builtin(owner_, attribute_id);
553 }
554
559 GAttributeReader lookup(const StringRef attribute_id) const
560 {
561 return fn_->lookup(owner_, attribute_id);
562 }
563
568 GAttributeReader lookup(StringRef attribute_id,
569 std::optional<AttrDomain> domain,
570 std::optional<eCustomDataType> data_type) const;
571
576 GAttributeReader lookup(const StringRef attribute_id, const AttrDomain domain) const
577 {
578 return this->lookup(attribute_id, domain, std::nullopt);
579 }
580
585 GAttributeReader lookup(const StringRef attribute_id, const eCustomDataType data_type) const
586 {
587 return this->lookup(attribute_id, std::nullopt, data_type);
588 }
589
594 template<typename T>
596 const std::optional<AttrDomain> domain = std::nullopt) const
597 {
598 const CPPType &cpp_type = CPPType::get<T>();
599 const eCustomDataType data_type = cpp_type_to_custom_data_type(cpp_type);
600 return this->lookup(attribute_id, domain, data_type).typed<T>();
601 }
602
610 AttrDomain domain,
611 eCustomDataType data_type,
612 const void *default_value = nullptr) const;
613
617 template<typename T>
619 const AttrDomain domain,
620 const T &default_value) const
621 {
622 if (AttributeReader<T> varray = this->lookup<T>(attribute_id, domain)) {
623 return varray;
624 }
625 return {VArray<T>::ForSingle(default_value, this->domain_size(domain)), domain};
626 }
627
632 {
633 return fn_->lookup_validator(owner_, attribute_id);
634 }
635
640 const AttrDomain from_domain,
641 const AttrDomain to_domain) const
642 {
643 return fn_->adapt_domain(owner_, varray, from_domain, to_domain);
644 }
645
649 template<typename T>
651 const AttrDomain from_domain,
652 const AttrDomain to_domain) const
653 {
654 return this->adapt_domain(GVArray(varray), from_domain, to_domain).typed<T>();
655 }
656
661 void foreach_attribute(const FunctionRef<void(const AttributeIter &)> fn) const
662 {
663 if (owner_ != nullptr) {
664 fn_->foreach_attribute(owner_, fn, *this);
665 }
666 }
667
672};
673
679 public:
681 : AttributeAccessor(owner, fn)
682 {
683 }
684
690
695
700 template<typename T> AttributeWriter<T> lookup_for_write(const StringRef attribute_id)
701 {
702 GAttributeWriter attribute = this->lookup_for_write(attribute_id);
703 if (!attribute) {
704 return {};
705 }
706 if (!attribute.varray.type().is<T>()) {
707 return {};
708 }
709 return attribute.typed<T>();
710 }
711
715 template<typename T> SpanAttributeWriter<T> lookup_for_write_span(const StringRef attribute_id)
716 {
717 AttributeWriter<T> attribute = this->lookup_for_write<T>(attribute_id);
718 if (attribute) {
719 return SpanAttributeWriter<T>{std::move(attribute), true};
720 }
721 return {};
722 }
723
727 bool rename(StringRef old_attribute_id, StringRef new_attribute_id);
728
734 bool add(const StringRef attribute_id,
735 const AttrDomain domain,
736 const eCustomDataType data_type,
737 const AttributeInit &initializer)
738 {
739 if (this->contains(attribute_id)) {
740 return false;
741 }
742 return fn_->add(owner_, attribute_id, domain, data_type, initializer);
743 }
744 template<typename T>
745 bool add(const StringRef attribute_id, const AttrDomain domain, const AttributeInit &initializer)
746 {
747 const CPPType &cpp_type = CPPType::get<T>();
748 const eCustomDataType data_type = cpp_type_to_custom_data_type(cpp_type);
749 return this->add(attribute_id, domain, data_type, initializer);
750 }
751
758 StringRef attribute_id,
759 AttrDomain domain,
760 eCustomDataType data_type,
761 const AttributeInit &initializer = AttributeInitDefaultValue());
762
769 StringRef attribute_id,
770 AttrDomain domain,
771 eCustomDataType data_type,
772 const AttributeInit &initializer = AttributeInitDefaultValue());
773
777 template<typename T>
779 const StringRef attribute_id,
780 const AttrDomain domain,
781 const AttributeInit &initializer = AttributeInitDefaultValue())
782 {
783 const CPPType &cpp_type = CPPType::get<T>();
784 const eCustomDataType data_type = cpp_type_to_custom_data_type(cpp_type);
785 return this->lookup_or_add_for_write(attribute_id, domain, data_type, initializer).typed<T>();
786 }
787
791 template<typename T>
793 const StringRef attribute_id,
794 const AttrDomain domain,
795 const AttributeInit &initializer = AttributeInitDefaultValue())
796 {
798 attribute_id, domain, initializer);
799 if (attribute) {
800 return SpanAttributeWriter<T>{std::move(attribute), true};
801 }
802 return {};
803 }
804
816 AttrDomain domain,
817 eCustomDataType data_type);
818
822 template<typename T>
824 const AttrDomain domain)
825 {
827 attribute_id, domain, AttributeInitConstruct());
828
829 if (attribute) {
830 return SpanAttributeWriter<T>{std::move(attribute), false};
831 }
832 return {};
833 }
834
840 bool remove(const StringRef attribute_id)
841 {
842 return fn_->remove(owner_, attribute_id);
843 }
844
848 void remove_anonymous();
849};
850
852 /* Expect that if an attribute exists, it is stored as a contiguous array internally anyway. */
856};
862 const AttributeAccessor src_attributes,
863 MutableAttributeAccessor dst_attributes,
864 AttrDomainMask domain_mask,
865 const AttributeFilter &attribute_filter = {});
866
868extern const char *no_procedural_access_message;
869
876
877void gather_attributes(AttributeAccessor src_attributes,
878 AttrDomain src_domain,
879 AttrDomain dst_domain,
880 const AttributeFilter &attribute_filter,
881 const IndexMask &selection,
882 MutableAttributeAccessor dst_attributes);
883
887void gather_attributes(AttributeAccessor src_attributes,
888 AttrDomain src_domain,
889 AttrDomain dst_domain,
890 const AttributeFilter &attribute_filter,
891 Span<int> indices,
892 MutableAttributeAccessor dst_attributes);
893
899void gather_attributes_group_to_group(AttributeAccessor src_attributes,
900 AttrDomain src_domain,
901 AttrDomain dst_domain,
902 const AttributeFilter &attribute_filter,
903 OffsetIndices<int> src_offsets,
904 OffsetIndices<int> dst_offsets,
905 const IndexMask &selection,
906 MutableAttributeAccessor dst_attributes);
907
908void gather_attributes_to_groups(AttributeAccessor src_attributes,
909 AttrDomain src_domain,
910 AttrDomain dst_domain,
911 const AttributeFilter &attribute_filter,
912 OffsetIndices<int> dst_offsets,
913 const IndexMask &src_selection,
914 MutableAttributeAccessor dst_attributes);
915
916void copy_attributes(const AttributeAccessor src_attributes,
917 AttrDomain src_domain,
918 AttrDomain dst_domain,
919 const AttributeFilter &attribute_filter,
920 MutableAttributeAccessor dst_attributes);
921
922void copy_attributes_group_to_group(AttributeAccessor src_attributes,
923 AttrDomain src_domain,
924 AttrDomain dst_domain,
925 const AttributeFilter &attribute_filter,
926 OffsetIndices<int> src_offsets,
927 OffsetIndices<int> dst_offsets,
928 const IndexMask &selection,
929 MutableAttributeAccessor dst_attributes);
930
931void fill_attribute_range_default(MutableAttributeAccessor dst_attributes,
932 AttrDomain domain,
933 const AttributeFilter &attribute_filter,
934 IndexRange range);
935
936} // namespace blender::bke
Generic geometry attributes built on CustomData.
AttrDomainMask
#define BLI_STRUCT_EQUALITY_OPERATORS_2(Type, m1, m2)
static const CPPType & get()
const GVMutableArray & varray() const
VMutableArray< T > typed() const
const VMutableArray< T > & varray() const
static VArray ForSingle(T value, const int64_t size)
GAttributeReader lookup(const StringRef attribute_id, const eCustomDataType data_type) const
bool is_builtin(const StringRef attribute_id) const
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
AttributeReader< T > lookup(const StringRef attribute_id, const std::optional< AttrDomain > domain=std::nullopt) const
AttributeValidator lookup_validator(const StringRef attribute_id) const
AttributeReader< T > lookup_or_default(const StringRef attribute_id, const AttrDomain domain, const T &default_value) const
static std::optional< AttributeAccessor > from_id(const ID &id)
GVArray adapt_domain(const GVArray &varray, const AttrDomain from_domain, const AttrDomain to_domain) const
GAttributeReader lookup(const StringRef attribute_id) const
VArray< T > adapt_domain(const VArray< T > &varray, const AttrDomain from_domain, const AttrDomain to_domain) const
Set< StringRefNull > all_ids() const
std::optional< AttributeMetaData > lookup_meta_data(const StringRef attribute_id) const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
GAttributeReader lookup(const StringRef attribute_id, const AttrDomain domain) const
bool domain_supported(const AttrDomain domain) const
AttributeAccessor(const void *owner, const AttributeAccessorFunctions &fn)
int domain_size(const AttrDomain domain) const
bool contains(const StringRef attribute_id) const
const AttributeAccessorFunctions * fn_
GAttributeReader get(const AttrDomain domain) const
AttributeReader< T > get(const std::optional< AttrDomain > domain=std::nullopt) const
GAttributeReader get(const eCustomDataType data_type) const
AttributeIter(const StringRefNull name, const AttrDomain domain, const eCustomDataType data_type, const FunctionRef< GAttributeReader()> get_fn)
GAttributeReader get() const
const AttributeAccessor * accessor
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
GAttributeWriter lookup_or_add_for_write(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
SpanAttributeWriter< T > lookup_for_write_span(const StringRef attribute_id)
GAttributeWriter lookup_for_write(StringRef attribute_id)
AttributeWriter< T > lookup_or_add_for_write(const StringRef attribute_id, const AttrDomain domain, const AttributeInit &initializer=AttributeInitDefaultValue())
bool remove(const StringRef attribute_id)
SpanAttributeWriter< T > lookup_or_add_for_write_only_span(const StringRef attribute_id, const AttrDomain domain)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
bool rename(StringRef old_attribute_id, StringRef new_attribute_id)
bool add(const StringRef attribute_id, const AttrDomain domain, const AttributeInit &initializer)
AttributeWriter< T > lookup_for_write(const StringRef attribute_id)
MutableAttributeAccessor(void *owner, const AttributeAccessorFunctions &fn)
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
SpanAttributeWriter< T > lookup_or_add_for_write_span(const StringRef attribute_id, const AttrDomain domain, const AttributeInit &initializer=AttributeInitDefaultValue())
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
Vector< AttributeTransferData > retrieve_attributes_for_transfer(const AttributeAccessor src_attributes, MutableAttributeAccessor dst_attributes, AttrDomainMask domain_mask, const AttributeFilter &attribute_filter={})
void fill_attribute_range_default(MutableAttributeAccessor dst_attributes, AttrDomain domain, const AttributeFilter &attribute_filter, IndexRange range)
void gather_attributes_to_groups(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, OffsetIndices< int > dst_offsets, const IndexMask &src_selection, MutableAttributeAccessor dst_attributes)
bool allow_procedural_attribute_access(StringRef attribute_name)
eCustomDataType cpp_type_to_custom_data_type(const CPPType &type)
void copy_attributes(const AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, MutableAttributeAccessor dst_attributes)
const char * no_procedural_access_message
void gather_attributes(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
eCustomDataType attribute_data_type_highest_complexity(Span< eCustomDataType > data_types)
AttrDomain attribute_domain_highest_priority(Span< AttrDomain > domains)
const CPPType * custom_data_type_to_cpp_type(eCustomDataType type)
void gather_attributes_group_to_group(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
void copy_attributes_group_to_group(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
signed char int8_t
Definition stdint.h:75
Definition DNA_ID.h:413
GVArray(* adapt_domain)(const void *owner, const GVArray &varray, AttrDomain from_domain, AttrDomain to_domain)
void(* foreach_attribute)(const void *owner, FunctionRef< void(const AttributeIter &iter)> fn, const AttributeAccessor &accessor)
bool(* remove)(void *owner, StringRef attribute_id)
bool(* domain_supported)(const void *owner, AttrDomain domain)
GAttributeWriter(* lookup_for_write)(void *owner, StringRef attribute_id)
bool(* is_builtin)(const void *owner, StringRef attribute_id)
AttributeValidator(* lookup_validator)(const void *owner, StringRef attribute_id)
bool(* add)(void *owner, StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer)
int(* domain_size)(const void *owner, AttrDomain domain)
GAttributeReader(* lookup)(const void *owner, StringRef attribute_id)
AttributeInitShared(const void *data, const ImplicitSharingInfo &sharing_info)
const ImplicitSharingInfo * sharing_info
AttributeInit(const Type type)
const VArray< T > & operator*() const &
const ImplicitSharingInfo * sharing_info
const fn::multi_function::MultiFunction * function
fn::GField validate_field_if_necessary(const fn::GField &field) const
std::function< void()> tag_modified_fn
const ImplicitSharingInfo * sharing_info
AttributeReader< T > typed() const
const GVArray & operator*() 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