Blender V5.0
instances_attributes.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BKE_instances.hh"
6
9
10namespace blender::bke {
11
13{
14 Instances &instances = *static_cast<Instances *>(owner);
16}
17
18static const auto &changed_tags()
19{
20 static Map<StringRef, AttrUpdateOnChange> attributes{
21 {".reference_index", tag_component_reference_index_changed},
22 };
23 return attributes;
24}
25
26static const auto &builtin_attributes()
27{
28 static auto attributes = []() {
30
32 instance_transform.deletable = false;
33 map.add_new("instance_transform", std::move(instance_transform));
34
37 reference_index.deletable = false;
38 map.add_new(".reference_index", std::move(reference_index));
39
40 return map;
41 }();
42 return attributes;
43}
44
46{
48 fn.domain_supported = [](const void * /*owner*/, const AttrDomain domain) {
49 return domain == AttrDomain::Instance;
50 };
51 fn.domain_size = [](const void *owner, const AttrDomain domain) {
52 return domain == AttrDomain::Instance ?
53 static_cast<const Instances *>(owner)->instances_num() :
54 0;
55 };
56 fn.builtin_domain_and_type = [](const void * /*owner*/,
57 const StringRef name) -> std::optional<AttributeDomainAndType> {
58 const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name);
59 if (!info) {
60 return std::nullopt;
61 }
62 return AttributeDomainAndType{info->domain, info->type};
63 };
64 fn.get_builtin_default = [](const void * /*owner*/, StringRef name) -> GPointer {
65 const AttrBuiltinInfo &info = builtin_attributes().lookup(name);
66 return info.default_value;
67 };
68 fn.lookup = [](const void *owner, const StringRef name) -> GAttributeReader {
69 const Instances &instances = *static_cast<const Instances *>(owner);
70 const AttributeStorage &storage = instances.attribute_storage();
71 const Attribute *attribute = storage.lookup(name);
72 if (!attribute) {
73 return {};
74 }
75 return attribute_to_reader(*attribute, AttrDomain::Instance, instances.instances_num());
76 };
77 fn.adapt_domain = [](const void * /*owner*/,
78 const GVArray &varray,
79 const AttrDomain from_domain,
80 const AttrDomain to_domain) {
81 if (from_domain == to_domain && from_domain == AttrDomain::Instance) {
82 return varray;
83 }
84 return GVArray{};
85 };
86 fn.foreach_attribute = [](const void *owner,
87 const FunctionRef<void(const AttributeIter &)> fn,
88 const AttributeAccessor &accessor) {
89 const Instances &instances = *static_cast<const Instances *>(owner);
90 const AttributeStorage &storage = instances.attribute_storage();
91 storage.foreach_with_stop([&](const Attribute &attribute) {
92 const auto get_fn = [&]() {
93 return attribute_to_reader(attribute, AttrDomain::Instance, instances.instances_num());
94 };
95 AttributeIter iter(attribute.name(), attribute.domain(), attribute.data_type(), get_fn);
96 iter.is_builtin = builtin_attributes().contains(attribute.name());
97 iter.accessor = &accessor;
98 fn(iter);
99 return !iter.is_stopped();
100 });
101 };
102 fn.lookup_validator = [](const void * /*owner*/, const StringRef name) -> AttributeValidator {
103 const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name);
104 if (!info) {
105 return {};
106 }
107 return info->validator;
108 };
109 fn.lookup_for_write = [](void *owner, const StringRef name) -> GAttributeWriter {
110 Instances &instances = *static_cast<Instances *>(owner);
111 AttributeStorage &storage = instances.attribute_storage();
112 Attribute *attribute = storage.lookup(name);
113 if (!attribute) {
114 return {};
115 }
116 return attribute_to_writer(&instances, changed_tags(), instances.instances_num(), *attribute);
117 };
118 fn.remove = [](void *owner, const StringRef name) -> bool {
119 Instances &instances = *static_cast<Instances *>(owner);
120 AttributeStorage &storage = instances.attribute_storage();
121 if (const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name)) {
122 if (!info->deletable) {
123 return false;
124 }
125 }
126 const std::optional<AttrUpdateOnChange> fn = changed_tags().lookup_try(name);
127 const bool removed = storage.remove(name);
128 if (!removed) {
129 return false;
130 }
131 if (fn) {
132 (*fn)(owner);
133 }
134 return true;
135 };
136 fn.add = [](void *owner,
137 const StringRef name,
138 const AttrDomain domain,
139 const AttrType type,
140 const AttributeInit &initializer) {
141 Instances &instances = *static_cast<Instances *>(owner);
142 const int domain_size = instances.instances_num();
143 AttributeStorage &storage = instances.attribute_storage();
144 if (const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name)) {
145 if (info->domain != domain || info->type != type) {
146 return false;
147 }
148 }
149 if (storage.lookup(name)) {
150 return false;
151 }
152 storage.add(name, domain, type, attribute_init_to_data(type, domain_size, initializer));
153 if (initializer.type != AttributeInit::Type::Construct) {
154 if (const std::optional<AttrUpdateOnChange> fn = changed_tags().lookup_try(name)) {
155 (*fn)(owner);
156 }
157 }
158 return true;
159 };
160
161 return fn;
162}
163
169
170} // namespace blender::bke
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:265
const AttributeAccessor * accessor
Attribute & add(std::string name, bke::AttrDomain domain, bke::AttrType data_type, Attribute::DataVariant data)
Attribute * lookup(StringRef name)
void foreach_with_stop(FunctionRef< bool(Attribute &)> fn)
int instances_num() const
Definition instances.cc:393
bke::AttributeStorage & attribute_storage()
GAttributeReader attribute_to_reader(const Attribute &attribute, const AttrDomain domain, const int64_t domain_size)
Attribute::DataVariant attribute_init_to_data(const bke::AttrType data_type, const int64_t domain_size, const AttributeInit &initializer)
GAttributeWriter attribute_to_writer(void *owner, const Map< StringRef, AttrUpdateOnChange > &changed_tags, const int64_t domain_size, Attribute &attribute)
static const auto & builtin_attributes()
static void tag_component_reference_index_changed(void *owner)
static constexpr AttributeAccessorFunctions get_instances_accessor_functions()
const AttributeAccessorFunctions & instance_attribute_accessor_functions()
static const auto & changed_tags()
const char * name