Blender V5.0
geometry_nodes_bundle.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <fmt/format.h>
6
8#include "BLI_cpp_type.hh"
9
10#include "BKE_node_runtime.hh"
11
14
15namespace blender::nodes {
16
18{
19 return a.items.as_span() == b.items.as_span();
20}
21
23{
24 return !(a == b);
25}
26
28{
29 for (const BundleSignature::Item &item : this->items) {
30 const_cast<BundleSignature::Item &>(item).structure_type =
32 }
33}
34
36{
37 return BundlePtr(MEM_new<Bundle>(__func__));
38}
39
40[[maybe_unused]] static bool is_valid_key(const StringRef key)
41{
42 return key.find('/') == StringRef::not_found;
43}
44
45void Bundle::add_new(const StringRef key, const BundleItemValue &value)
46{
48 items_.append(StoredItem{std::move(key), value});
49}
50
51void Bundle::add_override(const StringRef key, const BundleItemValue &value)
52{
53 this->remove(key);
54 this->add_new(key, value);
55}
56
57bool Bundle::add(const StringRef key, const BundleItemValue &value)
58{
59 if (this->contains(key)) {
60 return false;
61 }
62 this->add_new(key, value);
63 return true;
64}
65
67{
68 BLI_assert(!path.is_empty());
69 BLI_assert(!path.endswith("/"));
70 BLI_assert(this->is_mutable());
71 const int sep = path.find_first_of('/');
72 if (sep == StringRef::not_found) {
73 const StringRef key = path;
74 this->remove(key);
75 this->add_new(key, value);
76 return;
77 }
78 const StringRef first_part = path.substr(0, sep);
79 BundlePtr child_bundle = this->lookup<BundlePtr>(first_part).value_or(nullptr);
80 if (!child_bundle) {
81 child_bundle = Bundle::create();
82 }
83 this->remove(first_part);
84 if (!child_bundle->is_mutable()) {
85 child_bundle = child_bundle->copy();
86 }
87 child_bundle->tag_ensured_mutable();
88 const_cast<Bundle &>(*child_bundle).add_path_override(path.substr(sep + 1), value);
90 std::move(child_bundle));
91 this->add(
92 first_part,
94}
95
97{
98 if (this->contains_path(path)) {
99 return false;
100 }
101 this->add_path_new(path, value);
102 return true;
103}
104
106{
107 BLI_assert(!this->contains_path(path));
108 this->add_path_override(path, value);
109}
110
112{
113 for (const StoredItem &item : items_) {
114 if (item.key == key) {
115 return &item.value;
116 }
117 }
118 return nullptr;
119}
120
122{
123 BLI_assert(!path.is_empty());
124 const StringRef first_elem = path[0];
125 const BundleItemValue *item = this->lookup(first_elem);
126 if (!item) {
127 return nullptr;
128 }
129 if (path.size() == 1) {
130 return item;
131 }
132 const BundlePtr child_bundle = item->as<BundlePtr>().value_or(nullptr);
133 if (!child_bundle) {
134 return nullptr;
135 }
136 return child_bundle->lookup_path(path.drop_front(1));
137}
138
140{
141 Vector<StringRef> path_elems;
142 StringRef remaining = path;
143 while (!remaining.is_empty()) {
144 const int sep = remaining.find_first_of('/');
145 if (sep == StringRef::not_found) {
146 path_elems.append(remaining);
147 break;
148 }
149 path_elems.append(remaining.substr(0, sep));
150 remaining = remaining.substr(sep + 1);
151 }
152 return path_elems;
153}
154
156{
157 const Vector<StringRef> path_elems = split_path(path);
158 return this->lookup_path(path_elems);
159}
160
162{
163 BundlePtr copy_ptr = Bundle::create();
164 Bundle &copy = const_cast<Bundle &>(*copy_ptr);
165 for (const StoredItem &item : items_) {
166 copy.add_new(item.key, item.value);
167 }
168 return copy_ptr;
169}
170
172{
174 const int removed_num = items_.remove_if([&key](StoredItem &item) { return item.key == key; });
175 return removed_num >= 1;
176}
177
178bool Bundle::contains(const StringRef key) const
179{
181 for (const StoredItem &item : items_) {
182 if (item.key == key) {
183 return true;
184 }
185 }
186 return false;
187}
188
189bool Bundle::contains_path(const StringRef path) const
190{
191 return this->lookup_path(path) != nullptr;
192}
193
195{
196 return fmt::format("{}", fmt::join(path, "/"));
197}
198
200{
201 MEM_delete(this);
202}
203
205 const bNodeSocket &socket,
206 const NodeSocketInterfaceStructureType stored_structure_type,
207 const bool allow_auto_structure_type)
208{
209 if (stored_structure_type != NODE_INTERFACE_SOCKET_STRUCTURE_TYPE_AUTO) {
210 return stored_structure_type;
211 }
212 if (allow_auto_structure_type) {
214 }
215 return NodeSocketInterfaceStructureType(socket.runtime->inferred_structure_type);
216}
217
219 const bool allow_auto_structure_type)
220{
221 BLI_assert(node.is_type("NodeCombineBundle"));
222 const auto &storage = *static_cast<const NodeCombineBundle *>(node.storage);
223 BundleSignature signature;
224 for (const int i : IndexRange(storage.items_num)) {
225 const NodeCombineBundleItem &item = storage.items[i];
226 const bNodeSocket &socket = node.input_socket(i);
228 const NodeSocketInterfaceStructureType structure_type =
230 socket,
232 allow_auto_structure_type);
233 signature.items.add({item.name, stype, structure_type});
234 }
235 }
236 return signature;
237}
238
240 const bool allow_auto_structure_type)
241{
242 BLI_assert(node.is_type("NodeSeparateBundle"));
243 const auto &storage = *static_cast<const NodeSeparateBundle *>(node.storage);
244 BundleSignature signature;
245 for (const int i : IndexRange(storage.items_num)) {
246 const NodeSeparateBundleItem &item = storage.items[i];
247 const bNodeSocket &socket = node.output_socket(i);
249 const NodeSocketInterfaceStructureType structure_type =
251 socket,
253 allow_auto_structure_type);
254 signature.items.add({item.name, stype, structure_type});
255 }
256 }
257 return signature;
258}
259
261{
262 for (const Item &item : this->items) {
263 if (item.is_signature_definition) {
264 return true;
265 }
266 }
267 return false;
268}
269
270std::optional<BundleSignature> LinkedBundleSignatures::get_merged_signature() const
271{
272 BundleSignature signature;
273 for (const Item &src_signature : this->items) {
274 for (const BundleSignature::Item &item : src_signature.signature.items) {
275 if (!signature.items.add(item)) {
276 const BundleSignature::Item &existing_item = *signature.items.lookup_key_ptr_as(item.key);
277 if (item.type->type != existing_item.type->type) {
278 return std::nullopt;
279 }
280 if (existing_item.structure_type != item.structure_type) {
281 const_cast<BundleSignature::Item &>(existing_item).structure_type =
283 }
284 }
285 }
286 }
287 return signature;
288}
289
290} // namespace blender::nodes
#define BLI_assert(a)
Definition BLI_assert.h:46
@ NODE_INTERFACE_SOCKET_STRUCTURE_TYPE_DYNAMIC
@ NODE_INTERFACE_SOCKET_STRUCTURE_TYPE_AUTO
@ SOCK_BUNDLE
constexpr Span drop_front(int64_t n) const
Definition BLI_span.hh:171
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr bool is_empty() const
Definition BLI_span.hh:260
static constexpr int64_t not_found
constexpr int64_t find(char c, int64_t pos=0) const
constexpr bool is_empty() const
constexpr StringRef substr(int64_t start, int64_t size) const
constexpr bool endswith(StringRef suffix) const
constexpr int64_t find_first_of(StringRef chars, int64_t pos=0) const
void append(const T &value)
static SocketValueVariant From(T &&value)
void add_path_new(StringRef path, const BundleItemValue &value)
void add_new(StringRef key, const BundleItemValue &value)
bool contains_path(StringRef path) const
void add_override(StringRef key, const BundleItemValue &value)
const BundleItemValue * lookup(StringRef key) const
void add_path_override(StringRef path, const BundleItemValue &value)
bool add(StringRef key, const BundleItemValue &value)
static std::string combine_path(const Span< StringRef > path)
const BundleItemValue * lookup_path(Span< StringRef > path) const
bool add_path(StringRef path, const BundleItemValue &value)
bool contains(StringRef key) const
bNodeSocketType * node_socket_type_find_static(int type, int subtype=0)
Definition node.cc:2471
bool operator==(const BokehKernelKey &a, const BokehKernelKey &b)
bool operator!=(const Domain &a, const Domain &b)
Definition domain.cc:51
ImplicitSharingPtr< Bundle > BundlePtr
static bool is_valid_key(const StringRef key)
NodeSocketInterfaceStructureType get_structure_type_for_bundle_signature(const bNodeSocket &socket, const NodeSocketInterfaceStructureType stored_structure_type, const bool allow_auto_structure_type)
static Vector< StringRef > split_path(const StringRef path)
bNodeSocketRuntimeHandle * runtime
void * storage
Defines a socket type.
Definition BKE_node.hh:158
eNodeSocketDatatype type
Definition BKE_node.hh:193
static BundleSignature from_separate_bundle_node(const bNode &node, bool allow_auto_structure_type)
CustomIDVectorSet< Item, ItemKeyGetter > items
static BundleSignature from_combine_bundle_node(const bNode &node, bool allow_auto_structure_type)
std::optional< BundleSignature > get_merged_signature() const
i
Definition text_draw.cc:230