Blender V5.0
NOD_geometry_nodes_bundle.hh
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#pragma once
6
7#include "BKE_node.hh"
8
12
13#include "DNA_node_types.h"
14
15namespace blender::nodes {
16
22
27 public:
29 virtual StringRefNull type_name() const = 0;
30};
31
35
37 std::variant<BundleItemSocketValue, BundleItemInternalValue> value;
38
42 template<typename T>
43 std::optional<T> as_socket_value(const bke::bNodeSocketType &socket_type) const;
44 template<typename T> std::optional<T> as() const;
45};
46
53 public:
54 struct StoredItem {
55 std::string key;
57 };
58
59 private:
60 Vector<StoredItem> items_;
61
62 public:
63 static BundlePtr create();
64
65 bool add(StringRef key, const BundleItemValue &value);
66 void add_new(StringRef key, const BundleItemValue &value);
67 void add_override(StringRef key, const BundleItemValue &value);
68 bool add_path(StringRef path, const BundleItemValue &value);
69 void add_path_new(StringRef path, const BundleItemValue &value);
70 void add_path_override(StringRef path, const BundleItemValue &value);
71
72 template<typename T> void add(StringRef key, T value);
73 template<typename T> void add_override(StringRef key, T value);
74 template<typename T> void add_path(StringRef path, T value);
75 template<typename T> void add_path_override(StringRef path, T value);
76
77 bool remove(StringRef key);
78 bool contains(StringRef key) const;
79 bool contains_path(StringRef path) const;
80
81 const BundleItemValue *lookup(StringRef key) const;
83 const BundleItemValue *lookup_path(StringRef path) const;
84 template<typename T> std::optional<T> lookup(StringRef key) const;
85 template<typename T> std::optional<T> lookup_path(StringRef path) const;
86
87 bool is_empty() const;
88 int64_t size() const;
89
90 Span<StoredItem> items() const;
91
92 BundlePtr copy() const;
93
94 void delete_self() override;
95
97 static std::string combine_path(const Span<StringRef> path);
98};
99
100template<typename T>
101inline std::optional<T> BundleItemValue::as_socket_value(
102 const bke::bNodeSocketType &dst_socket_type) const
103{
104 const BundleItemSocketValue *socket_value = std::get_if<BundleItemSocketValue>(&this->value);
105 if (!socket_value) {
106 return std::nullopt;
107 }
108 if (socket_value->type->type == dst_socket_type.type) {
109 return socket_value->value.get<T>();
110 }
111 if (std::optional<bke::SocketValueVariant> converted_value = implicitly_convert_socket_value(
112 *socket_value->type, socket_value->value, dst_socket_type))
113 {
114 return converted_value->get<T>();
115 }
116 return std::nullopt;
117}
118
119template<typename T> inline const bke::bNodeSocketType *socket_type_info_by_static_type()
120{
121 if constexpr (fn::is_field_v<T>) {
122 const std::optional<eNodeSocketDatatype> socket_type =
124 BLI_assert(socket_type);
125 const bke::bNodeSocketType *socket_type_info = bke::node_socket_type_find_static(*socket_type);
126 BLI_assert(socket_type_info);
127 return socket_type_info;
128 }
129 else {
130 const std::optional<eNodeSocketDatatype> socket_type =
132 if (!socket_type) {
133 return nullptr;
134 }
135 return bke::node_socket_type_find_static(*socket_type);
136 }
137}
138
139template<typename T> constexpr bool is_valid_internal_bundle_item_type()
140{
141 if constexpr (is_ImplicitSharingPtr_strong_v<T>) {
142 if constexpr (std::is_base_of_v<BundleItemInternalValueMixin, typename T::element_type>) {
143 return true;
144 }
145 }
146 return false;
147}
148
149template<typename T> inline std::optional<T> BundleItemValue::as() const
150{
152 using SharingInfoT = typename T::element_type;
153 const auto *internal_value = std::get_if<BundleItemInternalValue>(&this->value);
154 if (!internal_value) {
155 return std::nullopt;
156 }
157 const BundleItemInternalValueMixin *sharing_info = internal_value->value.get();
158 const SharingInfoT *converted_value = dynamic_cast<const SharingInfoT *>(sharing_info);
159 if (!converted_value) {
160 return std::nullopt;
161 }
162 sharing_info->add_user();
163 return ImplicitSharingPtr<SharingInfoT>{converted_value};
164 }
165 else if constexpr (std::is_same_v<T, ListPtr>) {
166 const BundleItemSocketValue *socket_value = std::get_if<BundleItemSocketValue>(&this->value);
167 if (!socket_value) {
168 return std::nullopt;
169 }
170 if (socket_value->value.is_list()) {
171 return socket_value->value.get<ListPtr>();
172 }
173 return std::nullopt;
174 }
175 else if (const bke::bNodeSocketType *dst_socket_type = socket_type_info_by_static_type<T>()) {
176 return this->as_socket_value<T>(*dst_socket_type);
177 }
178 /* Can't lookup this type directly currently. */
180 return std::nullopt;
181}
182
183template<typename T> inline std::optional<T> Bundle::lookup(const StringRef key) const
184{
185 const BundleItemValue *item = this->lookup(key);
186 if (!item) {
187 return std::nullopt;
188 }
189 return item->as<T>();
190}
191
192template<typename T> inline std::optional<T> Bundle::lookup_path(const StringRef path) const
193{
194 const BundleItemValue *item = this->lookup_path(path);
195 if (!item) {
196 return std::nullopt;
197 }
198 return item->as<T>();
199}
200
201template<typename T, typename Fn> inline void to_stored_type(T &&value, Fn &&fn)
202{
203 using DecayT = std::decay_t<T>;
204 if constexpr (std::is_same_v<DecayT, BundleItemValue>) {
205 fn(std::forward<T>(value));
206 }
207 else if constexpr (std::is_same_v<DecayT, BundleItemSocketValue>) {
208 fn(BundleItemValue{std::forward<T>(value)});
209 }
210 else if constexpr (std::is_same_v<DecayT, BundleItemInternalValue>) {
211 fn(BundleItemValue{std::forward<T>(value)});
212 }
213 else if constexpr (is_valid_internal_bundle_item_type<DecayT>()) {
214 const BundleItemInternalValueMixin *sharing_info = value.get();
215 if (sharing_info) {
216 sharing_info->add_user();
217 }
219 }
220 else if (const bke::bNodeSocketType *socket_type = socket_type_info_by_static_type<DecayT>()) {
221 auto value_variant = bke::SocketValueVariant::From(std::forward<T>(value));
222 fn(BundleItemValue{BundleItemSocketValue{socket_type, value_variant}});
223 }
224 else {
225 /* All allowed types should be handled above already. */
227 }
228}
229
230template<typename T> inline void Bundle::add(const StringRef key, T value)
231{
232 to_stored_type(value, [&](const BundleItemValue &item_value) { this->add(key, item_value); });
233}
234
235template<typename T> inline void Bundle::add_path(const StringRef path, T value)
236{
237 to_stored_type(value,
238 [&](const BundleItemValue &item_value) { this->add_path(path, item_value); });
239}
240
241template<typename T> inline void Bundle::add_override(const StringRef key, T value)
242{
243 to_stored_type(value,
244 [&](const BundleItemValue &item_value) { this->add_override(key, item_value); });
245}
246
247template<typename T> inline void Bundle::add_path_override(const StringRef path, T value)
248{
249 to_stored_type(value, [&](const BundleItemValue &item_value) {
250 this->add_path_override(path, item_value);
251 });
252}
253
255{
256 return items_;
257}
258
259inline bool Bundle::is_empty() const
260{
261 return items_.is_empty();
262}
263
264inline int64_t Bundle::size() const
265{
266 return items_.size();
267}
268
269} // namespace blender::nodes
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
long long int int64_t
static const CPPType & get()
constexpr bool is_empty() const
Definition BLI_span.hh:260
static SocketValueVariant From(T &&value)
virtual StringRefNull type_name() const =0
Span< StoredItem > items() const
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
#define T
std::optional< eNodeSocketDatatype > geo_nodes_base_cpp_type_to_socket_type(const CPPType &type)
Definition node.cc:5241
bNodeSocketType * node_socket_type_find_static(int type, int subtype=0)
Definition node.cc:2471
static constexpr bool is_field_v
Definition FN_field.hh:215
const bke::bNodeSocketType * socket_type_info_by_static_type()
ImplicitSharingPtr< Bundle > BundlePtr
ImplicitSharingPtr< List > ListPtr
constexpr bool is_valid_internal_bundle_item_type()
std::optional< SocketValueVariant > implicitly_convert_socket_value(const bke::bNodeSocketType &from_type, const SocketValueVariant &from_value, const bke::bNodeSocketType &to_type)
void to_stored_type(T &&value, Fn &&fn)
static constexpr bool is_ImplicitSharingPtr_strong_v
Defines a socket type.
Definition BKE_node.hh:158
eNodeSocketDatatype type
Definition BKE_node.hh:193
ImplicitSharingPtr< BundleItemInternalValueMixin > value
std::variant< BundleItemSocketValue, BundleItemInternalValue > value
std::optional< T > as_socket_value(const bke::bNodeSocketType &socket_type) const