Blender V4.5
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.hh"
9
10#include "FN_field.hh"
11#include "FN_lazy_function.hh"
13
17#include "BKE_geometry_set.hh"
22
23#include "DNA_node_types.h"
24
27
28namespace blender::nodes {
29
30using bke::AttrDomain;
31using bke::AttributeAccessor;
32using bke::AttributeDomainAndType;
33using bke::AttributeFieldInput;
34using bke::AttributeFilter;
35using bke::AttributeIter;
36using bke::AttributeMetaData;
37using bke::AttributeReader;
38using bke::AttributeWriter;
39using bke::CurveComponent;
40using bke::GAttributeReader;
41using bke::GAttributeWriter;
42using bke::GeometryComponent;
43using bke::GeometryComponentEditData;
44using bke::GeometryNodesReferenceSet;
45using bke::GeometrySet;
46using bke::GreasePencilComponent;
47using bke::GSpanAttributeWriter;
48using bke::InstancesComponent;
49using bke::MeshComponent;
50using bke::MutableAttributeAccessor;
51using bke::PointCloudComponent;
52using bke::SocketValueVariant;
53using bke::SpanAttributeWriter;
54using bke::VolumeComponent;
55using fn::Field;
56using fn::FieldContext;
57using fn::FieldEvaluator;
58using fn::FieldInput;
59using fn::FieldOperation;
60using fn::GField;
62
64 private:
65 const GeometryNodesReferenceSet &set_;
66
67 public:
69
70 Result filter(StringRef attribute_name) const override;
71};
72
74 private:
75 const bNode &node_;
76 lf::Params &params_;
77 const lf::Context &lf_context_;
78 const Span<int> lf_input_for_output_bsocket_usage_;
79 const Span<int> lf_input_for_attribute_propagation_to_output_;
80 const FunctionRef<std::string(int)> get_output_attribute_id_;
81
82 public:
85 const lf::Context &lf_context,
86 const Span<int> lf_input_for_output_bsocket_usage,
87 const Span<int> lf_input_for_attribute_propagation_to_output,
88 const FunctionRef<std::string(int)> get_output_attribute_id)
89 : node_(node),
90 params_(params),
91 lf_context_(lf_context),
92 lf_input_for_output_bsocket_usage_(lf_input_for_output_bsocket_usage),
93 lf_input_for_attribute_propagation_to_output_(
94 lf_input_for_attribute_propagation_to_output),
95 get_output_attribute_id_(get_output_attribute_id)
96 {
97 }
98
99 template<typename T>
100 static constexpr bool is_field_base_type_v = is_same_any_v<T,
101 float,
102 int,
103 bool,
105 float3,
106 std::string,
108 float4x4>;
109
110 template<typename T>
111 static constexpr bool stored_as_SocketValueVariant_v =
114
120 template<typename T> T extract_input(StringRef identifier)
121 {
122 if constexpr (stored_as_SocketValueVariant_v<T>) {
123 SocketValueVariant value_variant = this->extract_input<SocketValueVariant>(identifier);
124 return value_variant.extract<T>();
125 }
126 else {
127#ifndef NDEBUG
128 this->check_input_access(identifier, &CPPType::get<T>());
129#endif
130 const int index = this->get_input_index(identifier);
131 T value = params_.extract_input<T>(index);
132 if constexpr (std::is_same_v<T, GeometrySet>) {
133 this->check_input_geometry_set(identifier, value);
134 }
135 if constexpr (std::is_same_v<T, SocketValueVariant>) {
136 BLI_assert(value.valid_for_socket(
137 eNodeSocketDatatype(node_.input_by_identifier(identifier).type)));
138 }
139 return value;
140 }
141 }
142
143 void check_input_geometry_set(StringRef identifier, const GeometrySet &geometry_set) const;
144 void check_output_geometry_set(const GeometrySet &geometry_set) const;
145
149 template<typename T> T get_input(StringRef identifier) const
150 {
151 if constexpr (stored_as_SocketValueVariant_v<T>) {
152 auto value_variant = this->get_input<SocketValueVariant>(identifier);
153 return value_variant.extract<T>();
154 }
155 else {
156#ifndef NDEBUG
157 this->check_input_access(identifier, &CPPType::get<T>());
158#endif
159 const int index = this->get_input_index(identifier);
160 const T &value = params_.get_input<T>(index);
161 if constexpr (std::is_same_v<T, GeometrySet>) {
162 this->check_input_geometry_set(identifier, value);
163 }
164 if constexpr (std::is_same_v<T, SocketValueVariant>) {
165 BLI_assert(value.valid_for_socket(
166 eNodeSocketDatatype(node_.input_by_identifier(identifier).type)));
167 }
168 return value;
169 }
170 }
171
178 {
179 return params_;
180 }
181
185 template<typename T> void set_output(StringRef identifier, T &&value)
186 {
187 using StoredT = std::decay_t<T>;
189 SocketValueVariant value_variant(std::forward<T>(value));
190 this->set_output(identifier, std::move(value_variant));
191 }
192 else {
193#ifndef NDEBUG
194 const CPPType &type = CPPType::get<StoredT>();
195 this->check_output_access(identifier, type);
196 if constexpr (std::is_same_v<StoredT, SocketValueVariant>) {
197 BLI_assert(value.valid_for_socket(
198 eNodeSocketDatatype(node_.output_by_identifier(identifier).type)));
199 }
200#endif
201 if constexpr (std::is_same_v<StoredT, GeometrySet>) {
202 this->check_output_geometry_set(value);
203 }
204 const int index = this->get_output_index(identifier);
205 params_.set_output(index, std::forward<T>(value));
206 }
207 }
208
213
218 {
219 const int index = this->get_input_index(identifier);
220 params_.set_input_unused(index);
221 }
222
226 bool output_is_required(StringRef identifier) const
227 {
228 const int index = this->get_output_index(identifier);
229 return params_.get_output_usage(index) != lf::ValueUsage::Unused;
230 }
231
235 const bNode &node() const
236 {
237 return node_;
238 }
239
240 const Object *self_object() const
241 {
242 if (const auto *data = this->user_data()) {
243 return data->call_data->self_object();
244 }
245 return nullptr;
246 }
247
248 const Depsgraph *depsgraph() const
249 {
250 if (const auto *data = this->user_data()) {
251 if (data->call_data->modifier_data) {
252 return data->call_data->modifier_data->depsgraph;
253 }
254 if (data->call_data->operator_data) {
255 return data->call_data->operator_data->depsgraphs->active;
256 }
257 }
258 return nullptr;
259 }
260
261 Main *bmain() const;
262
264 {
265 return static_cast<GeoNodesUserData *>(lf_context_.user_data);
266 }
267
269 {
270 return static_cast<GeoNodesLocalUserData *>(lf_context_.local_user_data);
271 }
272
277 void error_message_add(const NodeWarningType type, StringRef message) const;
278
280
281 void used_named_attribute(StringRef attribute_name, NamedAttributeUsage usage);
282
287 {
288 const int lf_index =
289 lf_input_for_output_bsocket_usage_[node_.output_by_identifier(output_identifier)
290 .index_in_all_outputs()];
291 return params_.get_input<bool>(lf_index);
292 }
293
299 const StringRef output_identifier, const bool force_create = false)
300 {
301 if (!this->anonymous_attribute_output_is_required(output_identifier) && !force_create) {
302 return std::nullopt;
303 }
304 const bNodeSocket &output_socket = node_.output_by_identifier(output_identifier);
305 return get_output_attribute_id_(output_socket.index());
306 }
307
312 {
313 const int lf_index =
314 lf_input_for_attribute_propagation_to_output_[node_.output_by_identifier(output_identifier)
315 .index_in_all_outputs()];
316 const GeometryNodesReferenceSet &set = params_.get_input<GeometryNodesReferenceSet>(lf_index);
317 return NodeAttributeFilter(set);
318 }
319
324 std::optional<std::string> ensure_absolute_path(StringRefNull path) const;
325
326 private:
327 /* Utilities for detecting common errors at when using this class. */
328 void check_input_access(StringRef identifier, const CPPType *requested_type = nullptr) const;
329 void check_output_access(StringRef identifier, const CPPType &value_type) const;
330
331 /* Find the active socket with the input name (not the identifier). */
332 const bNodeSocket *find_available_socket(const StringRef name) const;
333
334 int get_input_index(const StringRef identifier) const
335 {
336 int counter = 0;
337 for (const bNodeSocket *socket : node_.input_sockets()) {
338 if (!socket->is_available()) {
339 continue;
340 }
341 if (socket->identifier == identifier) {
342 return counter;
343 }
344 counter++;
345 }
347 return -1;
348 }
349
350 int get_output_index(const StringRef identifier) const
351 {
352 int counter = 0;
353 for (const bNodeSocket *socket : node_.output_sockets()) {
354 if (!socket->is_available()) {
355 continue;
356 }
357 if (socket->identifier == identifier) {
358 return counter;
359 }
360 counter++;
361 }
363 return -1;
364 }
365};
366
367} // namespace blender::nodes
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
eNodeSocketDatatype
struct bNodeSocket bNodeSocket
BMesh const char void * data
static const CPPType & get()
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
static constexpr bool is_field_base_type_v
static constexpr bool stored_as_SocketValueVariant_v
NodeAttributeFilter(const GeometryNodesReferenceSet &set)
#define filter
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define T
static constexpr bool is_VolumeGrid_v
static constexpr bool is_field_v
Definition FN_field.hh:215
QuaternionBase< float > Quaternion
constexpr bool is_same_any_v
MatBase< float, 4, 4 > float4x4
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:342
VecBase< float, 3 > float3
geo_eval_log::GeoTreeLogger * try_get_tree_logger(const GeoNodesUserData &user_data) const