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. */
47 /* A layer in a grease pencil data-block. */
48 Layer = 6,
49};
50#define ATTR_DOMAIN_NUM 7
51
54
66
71
91
99
106
116
130
136 const void *data = nullptr;
138
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 }
205
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
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:
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 {
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};
857
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,
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)
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 Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture 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
AttrDomain
static const CPPType & get()
const GVMutableArray & varray() 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
static ushort indices[]
#define T
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)
FunctionRef< bool(StringRefNull attribute_id, const AttributeMetaData &meta_data)> AttributeForeachCallback
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)
GPU_SHADER_INTERFACE_INFO(overlay_edit_curve_handle_iface, "vert").flat(Type pos vertex_in(1, Type::UINT, "data") .vertex_out(overlay_edit_curve_handle_iface) .geometry_layout(PrimitiveIn Frequency::GEOMETRY storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY) .push_constant(Type Frequency::GEOMETRY selection[]
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