69 if (type.is<
float>()) {
81 if (type.is<
int2>()) {
87 if (type.is<
bool>()) {
109 "This attribute cannot be accessed in a procedural context");
131 if (attribute_name ==
".reference_index") {
184 int highest_complexity = INT_MIN;
189 if (complexity > highest_complexity) {
190 highest_complexity = complexity;
191 most_complex_type = data_type;
195 return most_complex_type;
228 int highest_priority = INT_MIN;
233 if (priority > highest_priority) {
234 highest_priority = priority;
235 highest_priority_domain = domain;
239 return highest_priority_domain;
245 const int domain_size,
255 const int domain_size,
260 &custom_data, data_type, layer_data, domain_size, attribute_id, sharing_info);
268 const GPointer custom_default_value_ptr)
270 const int old_layer_num = custom_data.
totlayer;
271 switch (initializer.
type) {
278 if (
const void *default_value = custom_default_value_ptr.
get()) {
279 const CPPType &type = *custom_default_value_ptr.
type();
282 type.fill_assign_n(default_value, data,
domain_num);
293 if (data !=
nullptr) {
302 custom_data, data_type, attribute_id,
domain_num, data,
nullptr);
311 const_cast<void *
>(
init.data),
316 return old_layer_num < custom_data.
totlayer;
322 return layer.name == attribute_id;
325bool BuiltinCustomDataLayerProvider::layer_exists(
const CustomData &custom_data)
const
333 if (custom_data ==
nullptr) {
340 if (element_num == 0) {
341 if (this->layer_exists(*custom_data)) {
358 if (custom_data ==
nullptr) {
362 std::function<void()> tag_modified_fn;
363 if (update_on_change_ !=
nullptr) {
364 tag_modified_fn = [owner,
update = update_on_change_]() {
update(owner); };
370 if (element_num == 0) {
371 if (this->layer_exists(*custom_data)) {
378 if (data ==
nullptr) {
390 if (custom_data ==
nullptr) {
396 if (update_on_change_ !=
nullptr) {
397 update_on_change_(owner);
408 if (custom_data ==
nullptr) {
423 if (update_on_change_ !=
nullptr) {
424 update_on_change_(owner);
435 if (custom_data ==
nullptr) {
445 if (custom_data ==
nullptr) {
454 if (type ==
nullptr) {
457 GSpan data{*type, layer.
data, element_num};
467 if (custom_data ==
nullptr) {
479 if (type ==
nullptr) {
491 if (custom_data ==
nullptr) {
513 if (domain_ != domain) {
516 if (!this->type_is_supported(data_type)) {
520 if (custom_data ==
nullptr) {
530 attribute_id, *custom_data, data_type, element_num, initializer, {});
538 if (custom_data ==
nullptr) {
543 if (this->type_is_supported(data_type)) {
544 const auto get_fn = [&]() {
553 if (iter.is_stopped()) {
568 return conversions.
try_convert(std::move(varray), to_type);
573 switch (
GS(
id.name)) {
575 return reinterpret_cast<const Mesh &
>(id).attributes();
577 return reinterpret_cast<const PointCloud &
>(id).attributes();
579 return reinterpret_cast<const Curves &
>(id).geometry.wrap().attributes();
581 return reinterpret_cast<const GreasePencil &
>(id).attributes();
590 const std::optional<AttrDomain> domain,
591 const std::optional<eCustomDataType> data_type,
597 if (domain.has_value()) {
598 if (attribute.domain != domain) {
599 attribute.
varray = accessor.
adapt_domain(attribute.varray, attribute.domain, *domain);
600 attribute.domain = *domain;
601 attribute.sharing_info =
nullptr;
602 if (!attribute.varray) {
607 if (data_type.has_value()) {
609 if (attribute.varray.type() != type) {
611 attribute.sharing_info =
nullptr;
612 if (!attribute.varray) {
621 const std::optional<AttrDomain> domain,
622 const std::optional<eCustomDataType> data_type)
const
628 std::optional<eCustomDataType> data_type)
const
636 const void *default_value)
const
644 if (default_value ==
nullptr) {
654 if (attribute_id == iter.
name) {
665 std::optional<AttributeMetaData> meta_data;
667 if (attribute_id == iter.
name) {
668 meta_data = AttributeMetaData{iter.domain, iter.data_type};
682void MutableAttributeAccessor::remove_anonymous()
685 for (
const StringRef id : this->all_ids()) {
692 this->remove(anonymous_ids.
pop_last());
702 bool finish_called =
false;
707 if (!this->finish_called) {
708 std::cerr <<
"Forgot to call `finish()` for '" << this->name <<
"'.\n";
720 auto checker = std::make_shared<FinishCallChecker>();
721 checker->name = attribute_id;
722 checker->real_finish_fn = attribute.tag_modified_fn;
723 attribute.tag_modified_fn = [checker]() {
724 if (checker->real_finish_fn) {
725 checker->real_finish_fn();
727 checker->finish_called =
true;
749 std::optional<AttributeMetaData> meta_data = this->lookup_meta_data(attribute_id);
750 if (meta_data.has_value()) {
751 if (meta_data->domain == domain && meta_data->data_type == data_type) {
752 return this->lookup_for_write(attribute_id);
756 if (this->
add(attribute_id, domain, data_type, initializer)) {
757 return this->lookup_for_write(attribute_id);
769 attribute_id, domain, data_type, initializer);
787bool MutableAttributeAccessor::rename(
const StringRef old_attribute_id,
790 if (old_attribute_id == new_attribute_id) {
793 if (this->contains(new_attribute_id)) {
797 if (!old_attribute) {
802 if (!this->
add(new_attribute_id,
806 *old_attribute.sharing_info}))
812 if (!this->
add(new_attribute_id,
820 this->remove(old_attribute_id);
850 attributes.append({std::move(src), {iter.
domain, iter.
data_type}, std::move(dst)});
864 const int src_size = src_attributes.
domain_size(src_domain);
866 if (iter.
domain != src_domain) {
876 if (selection.size() == src_size && src.sharing_info && src.varray.is_span()) {
901 copy_attributes(src_attributes, src_domain, dst_domain, attribute_filter, dst_attributes);
905 if (iter.
domain != src_domain) {
920 attribute_math::gather(src.varray, indices, dst.
span);
936 if (iter.
domain != src_domain) {
951 attribute_math::gather_group_to_group(src_offsets, dst_offsets, selection, src, dst.
span);
965 if (iter.
domain != src_domain) {
980 attribute_math::gather_to_groups(dst_offsets, src_selection, src, dst.
span);
1009 if (selection.is_empty()) {
1013 if (iter.
domain != src_domain) {
1038 attributes.foreach_attribute([&](
const AttributeIter &iter) {
1039 if (iter.
domain != domain) {
1049 const CPPType &type = attribute.span.type();
1051 type.fill_assign_n(type.default_value(), data.data(), data.size());
#define ATTR_DOMAIN_AS_MASK(domain)
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
void * CustomData_get_layer_named_for_write(CustomData *data, eCustomDataType type, blender::StringRef name, int totelem)
bool CustomData_free_layer_named(CustomData *data, blender::StringRef name, const int totelem)
void * CustomData_add_layer_named(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem, blender::StringRef name)
int CustomData_get_named_layer_index(const CustomData *data, eCustomDataType type, blender::StringRef name)
bool CustomData_has_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
bool CustomData_free_layer(CustomData *data, eCustomDataType type, int totelem, int index)
const void * CustomData_add_layer_named_with_data(CustomData *data, eCustomDataType type, void *layer_data, int totelem, blender::StringRef name, const blender::ImplicitSharingInfo *sharing_info)
#define BLI_assert_unreachable()
ID and Library types, which are fundamental for SDNA.
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
static void copy_attributes(PointCloud *pointcloud, const ::PointCloud &b_pointcloud, const bool need_motion, const float motion_scale)
static const CPPType & get()
GMutableSpan slice(const int64_t start, int64_t size) const
const CPPType * type() const
const void * data() const
const CPPType & type() const
void materialize_to_uninitialized(void *dst) const
IndexRange index_range() const
static GVArray ForSingleRef(const CPPType &type, int64_t size, const void *value)
static GVArray ForSpan(GSpan span)
static GVArray ForSingle(const CPPType &type, int64_t size, const void *value)
static GVMutableArray ForSpan(GMutableSpan span)
constexpr bool startswith(StringRef prefix) const
void append(const T &value)
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) 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
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
int domain_size(const AttrDomain domain) const
bool contains(const StringRef attribute_id) const
eCustomDataType data_type
GAttributeReader get() const
const AttributeAccessor * accessor
const eCustomDataType data_type_
const GPointer default_value_
const DeletableEnum deletable_
GAttributeWriter try_get_for_write(void *owner) const final
bool try_create(void *owner, const AttributeInit &initializer) const final
bool try_delete(void *owner) const final
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
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
GVArray try_convert(GVArray varray, const CPPType &to_type) const
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
static std::shared_ptr< FieldOperation > Create(std::shared_ptr< const mf::MultiFunction > function, Vector< GField > inputs={})
static void add(blender::Map< std::string, std::string > &messages, Message &msg)
bool indices_are_range(Span< int > indices, IndexRange range)
void copy_group_to_group(OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, GSpan src, GMutableSpan dst)
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
bool attribute_name_is_anonymous(const StringRef name)
Vector< AttributeTransferData > retrieve_attributes_for_transfer(const AttributeAccessor src_attributes, MutableAttributeAccessor dst_attributes, AttrDomainMask domain_mask, const AttributeFilter &attribute_filter={})
static GAttributeReader adapt_domain_and_type_if_necessary(GAttributeReader attribute, const std::optional< AttrDomain > domain, const std::optional< eCustomDataType > data_type, const AttributeAccessor &accessor)
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)
static GVArray try_adapt_data_type(GVArray varray, const CPPType &to_type)
const DataTypeConversions & get_implicit_type_conversions()
static int attribute_domain_priority(const AttrDomain domain)
bool allow_procedural_attribute_access(StringRef attribute_name)
eCustomDataType cpp_type_to_custom_data_type(const CPPType &type)
static bool add_custom_data_layer_from_attribute_init(const StringRef attribute_id, CustomData &custom_data, const eCustomDataType data_type, const int domain_num, const AttributeInit &initializer, const GPointer custom_default_value_ptr)
const char * no_procedural_access_message
static bool custom_data_layer_matches_attribute_id(const CustomDataLayer &layer, const StringRef attribute_id)
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)
static void * add_generic_custom_data_layer(CustomData &custom_data, const eCustomDataType data_type, const eCDAllocType alloctype, const int domain_size, const StringRef attribute_id)
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)
static int domain_num(const CurvesGeometry &curves, const AttrDomain domain)
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)
static const void * add_generic_custom_data_layer_with_existing_data(CustomData &custom_data, const eCustomDataType data_type, const StringRef attribute_id, const int domain_size, void *layer_data, const ImplicitSharingInfo *sharing_info)
static int attribute_data_type_complexity(const eCustomDataType data_type)
static void update(bNodeTree *ntree)
bool allow_skip(const StringRef name) const
GetElementNum get_element_num
ConstCustomDataGetter get_const_custom_data
CustomDataGetter get_custom_data
std::function< void()> real_finish_fn
const ImplicitSharingInfo * sharing_info