Blender V5.0
NOD_geometry_exec.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 "BLI_color_types.hh"
9
10#include "FN_field.hh"
11#include "FN_lazy_function.hh"
13
17#include "BKE_geometry_set.hh"
23
24#include "DNA_node_types.h"
25
29#include "NOD_menu_value.hh"
30
31namespace blender::nodes {
32
33using bke::AttrDomain;
34using bke::AttributeAccessor;
35using bke::AttributeDomainAndType;
36using bke::AttributeFieldInput;
37using bke::AttributeFilter;
38using bke::AttributeIter;
39using bke::AttributeMetaData;
40using bke::AttributeReader;
41using bke::AttributeWriter;
42using bke::CurveComponent;
43using bke::GAttributeReader;
44using bke::GAttributeWriter;
45using bke::GeometryComponent;
46using bke::GeometryComponentEditData;
47using bke::GeometryNodesReferenceSet;
48using bke::GeometrySet;
49using bke::GreasePencilComponent;
50using bke::GSpanAttributeWriter;
51using bke::InstancesComponent;
52using bke::MeshComponent;
53using bke::MutableAttributeAccessor;
54using bke::PointCloudComponent;
55using bke::SocketValueVariant;
56using bke::SpanAttributeWriter;
57using bke::VolumeComponent;
58using fn::Field;
59using fn::FieldContext;
60using fn::FieldEvaluator;
61using fn::FieldInput;
62using fn::FieldOperation;
63using fn::GField;
65
67 private:
68 const GeometryNodesReferenceSet &set_;
69
70 public:
72
73 Result filter(StringRef attribute_name) const override;
74};
75
77 private:
78 const bNode &node_;
79 lf::Params &params_;
80 const lf::Context &lf_context_;
81 const Span<int> lf_input_for_output_bsocket_usage_;
82 const Span<int> lf_input_for_attribute_propagation_to_output_;
83 const FunctionRef<std::string(int)> get_output_attribute_id_;
84
85 public:
88 const lf::Context &lf_context,
89 const Span<int> lf_input_for_output_bsocket_usage,
90 const Span<int> lf_input_for_attribute_propagation_to_output,
91 const FunctionRef<std::string(int)> get_output_attribute_id)
92 : node_(node),
93 params_(params),
94 lf_context_(lf_context),
95 lf_input_for_output_bsocket_usage_(lf_input_for_output_bsocket_usage),
96 lf_input_for_attribute_propagation_to_output_(
97 lf_input_for_attribute_propagation_to_output),
98 get_output_attribute_id_(get_output_attribute_id)
99 {
100 }
101
107 template<typename T> T extract_input(StringRef identifier)
108 {
109#ifndef NDEBUG
110 this->check_input_access(identifier);
111#endif
112 const int index = this->get_input_index(identifier);
113 if constexpr (is_GeoNodesMultiInput_v<T>) {
114 using ValueT = typename T::value_type;
115 BLI_assert(node_.input_by_identifier(identifier)->is_multi_input());
116 if constexpr (std::is_same_v<ValueT, SocketValueVariant>) {
117 return params_.extract_input<T>(index);
118 }
119 else {
120 auto values_variants = params_.extract_input<GeoNodesMultiInput<SocketValueVariant>>(
121 index);
123 values.values.reserve(values_variants.values.size());
124 for (const int i : values_variants.values.index_range()) {
125 values.values.append(values_variants.values[i].extract<ValueT>());
126 }
127 return values;
128 }
129 }
130 else {
131 SocketValueVariant value_variant = params_.extract_input<SocketValueVariant>(index);
132 if constexpr (std::is_same_v<T, SocketValueVariant>) {
133 return value_variant;
134 }
135 else if constexpr (std::is_enum_v<T>) {
136 return T(value_variant.extract<MenuValue>().value);
137 }
138 else {
139 T value = value_variant.extract<T>();
140 if constexpr (std::is_same_v<T, GeometrySet>) {
141 this->check_input_geometry_set(identifier, value);
142 }
143 return value;
144 }
145 }
146 }
147
148 void check_input_geometry_set(StringRef identifier, const GeometrySet &geometry_set) const;
149 void check_output_geometry_set(const GeometrySet &geometry_set) const;
150
154 template<typename T> T get_input(StringRef identifier) const
155 {
156#ifndef NDEBUG
157 this->check_input_access(identifier);
158#endif
159 const int index = this->get_input_index(identifier);
160 if constexpr (is_GeoNodesMultiInput_v<T>) {
161 using ValueT = typename T::value_type;
162 BLI_assert(node_.input_by_identifier(identifier)->is_multi_input());
163 if constexpr (std::is_same_v<ValueT, SocketValueVariant>) {
164 return params_.get_input<T>(index);
165 }
166 else {
167 auto values_variants = params_.get_input<GeoNodesMultiInput<SocketValueVariant>>(index);
168 Vector<ValueT> values(values_variants.values.size());
169 for (const int i : values_variants.values.index_range()) {
170 values[i] = values_variants.values[i].extract<ValueT>();
171 }
172 return values;
173 }
174 }
175 else {
176 const SocketValueVariant &value_variant = params_.get_input<SocketValueVariant>(index);
177 if constexpr (std::is_same_v<T, SocketValueVariant>) {
178 return value_variant;
179 }
180 else if constexpr (std::is_enum_v<T>) {
181 return T(value_variant.get<MenuValue>().value);
182 }
183 else {
184 T value = value_variant.get<T>();
185 if constexpr (std::is_same_v<T, GeometrySet>) {
186 this->check_input_geometry_set(identifier, value);
187 }
188 return value;
189 }
190 }
191 }
192
199 {
200 return params_;
201 }
202
206 template<typename T> void set_output(StringRef identifier, T &&value)
207 {
208 using StoredT = std::decay_t<T>;
209#ifndef NDEBUG
210 this->check_output_access(identifier);
211#endif
212 if constexpr (std::is_same_v<StoredT, GeometrySet>) {
213 this->check_output_geometry_set(value);
214 }
215 const int index = this->get_output_index(identifier);
216 if constexpr (std::is_same_v<StoredT, SocketValueVariant>) {
217 params_.set_output(index, std::forward<T>(value));
218 }
219 else {
220 params_.set_output(index, SocketValueVariant::From(std::forward<T>(value)));
221 }
222 }
223
228
233 {
234 const int index = this->get_input_index(identifier);
235 params_.set_input_unused(index);
236 }
237
241 bool output_is_required(StringRef identifier) const
242 {
243 const int index = this->get_output_index(identifier);
244 return params_.get_output_usage(index) != lf::ValueUsage::Unused;
245 }
246
250 const bNode &node() const
251 {
252 return node_;
253 }
254
255 const Object *self_object() const
256 {
257 if (const auto *data = this->user_data()) {
258 return data->call_data->self_object();
259 }
260 return nullptr;
261 }
262
263 const Depsgraph *depsgraph() const
264 {
265 if (const auto *data = this->user_data()) {
266 if (data->call_data->modifier_data) {
267 return data->call_data->modifier_data->depsgraph;
268 }
269 if (data->call_data->operator_data) {
270 return data->call_data->operator_data->depsgraphs->active;
271 }
272 }
273 return nullptr;
274 }
275
276 Main *bmain() const;
277
279 {
280 return static_cast<GeoNodesUserData *>(lf_context_.user_data);
281 }
282
284 {
285 return static_cast<GeoNodesLocalUserData *>(lf_context_.local_user_data);
286 }
287
292 void error_message_add(const NodeWarningType type, StringRef message) const;
293
295
296 void used_named_attribute(StringRef attribute_name, NamedAttributeUsage usage);
297
302 {
303 const int lf_index =
304 lf_input_for_output_bsocket_usage_[node_.output_by_identifier(output_identifier)
305 ->index_in_all_outputs()];
306 return params_.get_input<bool>(lf_index);
307 }
308
314 const StringRef output_identifier, const bool force_create = false)
315 {
316 if (!this->anonymous_attribute_output_is_required(output_identifier) && !force_create) {
317 return std::nullopt;
318 }
319 const bNodeSocket &output_socket = *node_.output_by_identifier(output_identifier);
320 return get_output_attribute_id_(output_socket.index());
321 }
322
327 {
328 const int lf_index = lf_input_for_attribute_propagation_to_output_
329 [node_.output_by_identifier(output_identifier)->index_in_all_outputs()];
330 const GeometryNodesReferenceSet &set = params_.get_input<GeometryNodesReferenceSet>(lf_index);
331 return NodeAttributeFilter(set);
332 }
333
338 std::optional<std::string> ensure_absolute_path(StringRefNull path) const;
339
340 private:
341 /* Utilities for detecting common errors at when using this class. */
342 void check_input_access(StringRef identifier) const;
343 void check_output_access(StringRef identifier) const;
344
345 /* Find the active socket with the input name (not the identifier). */
346 const bNodeSocket *find_available_socket(const StringRef name) const;
347
348 int get_input_index(const StringRef identifier) const
349 {
350 int counter = 0;
351 for (const bNodeSocket *socket : node_.input_sockets()) {
352 if (!socket->is_available()) {
353 continue;
354 }
355 if (socket->identifier == identifier) {
356 return counter;
357 }
358 counter++;
359 }
361 return -1;
362 }
363
364 int get_output_index(const StringRef identifier) const
365 {
366 int counter = 0;
367 for (const bNodeSocket *socket : node_.output_sockets()) {
368 if (!socket->is_available()) {
369 continue;
370 }
371 if (socket->identifier == identifier) {
372 return counter;
373 }
374 counter++;
375 }
377 return -1;
378 }
379};
380
381} // namespace blender::nodes
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
struct bNodeSocket bNodeSocket
BMesh const char void * data
T extract_input(StringRef identifier)
GeoNodesLocalUserData * local_user_data() const
geo_eval_log::GeoTreeLogger * get_local_tree_logger() const
void error_message_add(const NodeWarningType type, StringRef message) const
void set_output(StringRef identifier, T &&value)
void set_input_unused(StringRef identifier)
void check_output_geometry_set(const GeometrySet &geometry_set) const
bool output_is_required(StringRef identifier) const
GeoNodeExecParams(const bNode &node, lf::Params &params, const lf::Context &lf_context, const Span< int > lf_input_for_output_bsocket_usage, const Span< int > lf_input_for_attribute_propagation_to_output, const FunctionRef< std::string(int)> get_output_attribute_id)
T get_input(StringRef identifier) const
GeoNodesUserData * user_data() const
void check_input_geometry_set(StringRef identifier, const GeometrySet &geometry_set) const
std::optional< std::string > ensure_absolute_path(StringRefNull path) const
bool anonymous_attribute_output_is_required(const StringRef output_identifier)
void used_named_attribute(StringRef attribute_name, NamedAttributeUsage usage)
std::optional< std::string > get_output_anonymous_attribute_id_if_needed(const StringRef output_identifier, const bool force_create=false)
NodeAttributeFilter get_attribute_filter(const StringRef output_identifier) const
const Depsgraph * depsgraph() const
NodeAttributeFilter(const GeometryNodesReferenceSet &set)
static SocketValueVariant From(T &&value)
#define filter
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define T
constexpr bool is_GeoNodesMultiInput_v
const char * name
geo_eval_log::GeoTreeLogger * try_get_tree_logger(const GeoNodesUserData &user_data) const
i
Definition text_draw.cc:230