Blender V4.3
node_geometry_exec.cc
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#include "DNA_curves_types.h"
7#include "DNA_mesh_types.h"
10
12
13#include "BKE_curves.hh"
15
16#include "BLT_translation.hh"
17
18#include "NOD_geometry_exec.hh"
19
20#include "node_geometry_util.hh"
21
22namespace blender::nodes {
23
25{
26 return DEG_get_bmain(this->depsgraph());
27}
28
29void GeoNodeExecParams::error_message_add(const NodeWarningType type,
30 const StringRef message) const
31{
32 if (geo_eval_log::GeoTreeLogger *tree_logger = this->get_local_tree_logger()) {
33 tree_logger->node_warnings.append(
34 *tree_logger->allocator,
35 {node_.identifier, {type, tree_logger->allocator->copy_string(message)}});
36 }
37}
38
39void GeoNodeExecParams::used_named_attribute(const StringRef attribute_name,
40 const NamedAttributeUsage usage)
41{
42 if (geo_eval_log::GeoTreeLogger *tree_logger = this->get_local_tree_logger()) {
43 tree_logger->used_named_attributes.append(
44 *tree_logger->allocator,
45 {node_.identifier, tree_logger->allocator->copy_string(attribute_name), usage});
46 }
47}
48
49void GeoNodeExecParams::check_input_geometry_set(StringRef identifier,
50 const GeometrySet &geometry_set) const
51{
52 const SocketDeclaration &decl = *node_.input_by_identifier(identifier).runtime->declaration;
53 const decl::Geometry *geo_decl = dynamic_cast<const decl::Geometry *>(&decl);
54 if (geo_decl == nullptr) {
55 return;
56 }
57
58 const bool only_realized_data = geo_decl->only_realized_data();
59 const bool only_instances = geo_decl->only_instances();
60 const Span<GeometryComponent::Type> supported_types = geo_decl->supported_types();
61
62 if (only_realized_data) {
63 if (geometry_set.has_instances()) {
64 this->error_message_add(NodeWarningType::Info,
65 TIP_("Instances in input geometry are ignored"));
66 }
67 }
68 if (only_instances) {
69 if (geometry_set.has_realized_data()) {
70 this->error_message_add(NodeWarningType::Info,
71 TIP_("Realized data in input geometry is ignored"));
72 }
73 }
74 if (supported_types.is_empty()) {
75 /* Assume all types are supported. */
76 return;
77 }
78 const Vector<GeometryComponent::Type> types_in_geometry = geometry_set.gather_component_types(
79 true, true);
80 for (const GeometryComponent::Type type : types_in_geometry) {
81 if (type == GeometryComponent::Type::Instance) {
82 continue;
83 }
84 if (supported_types.contains(type)) {
85 continue;
86 }
87 std::string message = RPT_("Input geometry has unsupported type: ");
88 switch (type) {
89 case GeometryComponent::Type::Mesh: {
90 if (const Mesh *mesh = geometry_set.get_mesh()) {
91 if (mesh->verts_num == 0) {
92 continue;
93 }
94 }
95 message += RPT_("Mesh");
96 break;
97 }
98 case GeometryComponent::Type::PointCloud: {
99 if (const PointCloud *pointcloud = geometry_set.get_pointcloud()) {
100 if (pointcloud->totpoint == 0) {
101 continue;
102 }
103 }
104 message += RPT_("Point Cloud");
105 break;
106 }
107 case GeometryComponent::Type::Instance: {
109 break;
110 }
111 case GeometryComponent::Type::Volume: {
112 message += CTX_RPT_(BLT_I18NCONTEXT_ID_ID, "Volume");
113 break;
114 }
115 case GeometryComponent::Type::Curve: {
116 if (const Curves *curves = geometry_set.get_curves()) {
117 if (curves->geometry.point_num == 0) {
118 continue;
119 }
120 }
121 message += RPT_("Curve");
122 break;
123 }
124 case GeometryComponent::Type::Edit: {
125 continue;
126 }
127 case GeometryComponent::Type::GreasePencil: {
128 if (const GreasePencil *grease_pencil = geometry_set.get_grease_pencil()) {
129 if (grease_pencil->drawing_array_num == 0) {
130 continue;
131 }
132 }
133 message += RPT_("Grease Pencil");
134 break;
135 }
136 }
137 this->error_message_add(NodeWarningType::Info, std::move(message));
138 }
139}
140
141void GeoNodeExecParams::check_output_geometry_set(const GeometrySet &geometry_set) const
142{
143 UNUSED_VARS_NDEBUG(geometry_set);
144#ifndef NDEBUG
145 if (const bke::CurvesEditHints *curve_edit_hints = geometry_set.get_curve_edit_hints()) {
146 /* If this is not valid, it's likely that the number of stored deformed points does not match
147 * the number of points in the original data. */
148 BLI_assert(curve_edit_hints->is_valid());
149 }
150#endif
151}
152
153const bNodeSocket *GeoNodeExecParams::find_available_socket(const StringRef name) const
154{
155 for (const bNodeSocket *socket : node_.input_sockets()) {
156 if (socket->is_available() && socket->name == name) {
157 return socket;
158 }
159 }
160
161 return nullptr;
162}
163
164void GeoNodeExecParams::set_default_remaining_outputs()
165{
167}
168
169void GeoNodeExecParams::check_input_access(StringRef identifier,
170 const CPPType *requested_type) const
171{
172 const bNodeSocket *found_socket = nullptr;
173 for (const bNodeSocket *socket : node_.input_sockets()) {
174 if (socket->identifier == identifier) {
175 found_socket = socket;
176 break;
177 }
178 }
179
180 if (found_socket == nullptr) {
181 std::cout << "Did not find an input socket with the identifier '" << identifier << "'.\n";
182 std::cout << "Possible identifiers are: ";
183 for (const bNodeSocket *socket : node_.input_sockets()) {
184 if (socket->is_available()) {
185 std::cout << "'" << socket->identifier << "', ";
186 }
187 }
188 std::cout << "\n";
190 }
191 else if (found_socket->flag & SOCK_UNAVAIL) {
192 std::cout << "The socket corresponding to the identifier '" << identifier
193 << "' is disabled.\n";
195 }
196 else if (requested_type != nullptr && (found_socket->flag & SOCK_MULTI_INPUT) == 0) {
197 const CPPType &expected_type = *found_socket->typeinfo->geometry_nodes_cpp_type;
198 if (*requested_type != expected_type) {
199 std::cout << "The requested type '" << requested_type->name() << "' is incorrect. Expected '"
200 << expected_type.name() << "'.\n";
202 }
203 }
204}
205
206void GeoNodeExecParams::check_output_access(StringRef identifier, const CPPType &value_type) const
207{
208 const bNodeSocket *found_socket = nullptr;
209 for (const bNodeSocket *socket : node_.output_sockets()) {
210 if (socket->identifier == identifier) {
211 found_socket = socket;
212 break;
213 }
214 }
215
216 if (found_socket == nullptr) {
217 std::cout << "Did not find an output socket with the identifier '" << identifier << "'.\n";
218 std::cout << "Possible identifiers are: ";
219 for (const bNodeSocket *socket : node_.output_sockets()) {
220 if (socket->is_available()) {
221 std::cout << "'" << socket->identifier << "', ";
222 }
223 }
224 std::cout << "\n";
226 }
227 else if (found_socket->flag & SOCK_UNAVAIL) {
228 std::cout << "The socket corresponding to the identifier '" << identifier
229 << "' is disabled.\n";
231 }
232 else if (params_.output_was_set(this->get_output_index(identifier))) {
233 std::cout << "The identifier '" << identifier << "' has been set already.\n";
235 }
236 else {
237 const CPPType &expected_type = *found_socket->typeinfo->geometry_nodes_cpp_type;
238 if (value_type != expected_type) {
239 std::cout << "The value type '" << value_type.name() << "' is incorrect. Expected '"
240 << expected_type.name() << "'.\n";
242 }
243 }
244}
245
246AttributeFilter::Result NodeAttributeFilter::filter(const StringRef attribute_name) const
247{
248 if (!bke::attribute_name_is_anonymous(attribute_name)) {
249 return AttributeFilter::Result::Process;
250 }
251 if (!set_.names) {
252 return AttributeFilter::Result::AllowSkip;
253 }
254 if (set_.names->contains(attribute_name)) {
255 return AttributeFilter::Result::Process;
256 }
257 return AttributeFilter::Result::AllowSkip;
258}
259
260} // namespace blender::nodes
Low-level operations for curves.
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define UNUSED_VARS_NDEBUG(...)
#define RPT_(msgid)
#define BLT_I18NCONTEXT_ID_ID
#define TIP_(msgid)
#define CTX_RPT_(context, msgid)
Main * DEG_get_bmain(const Depsgraph *graph)
@ SOCK_MULTI_INPUT
@ SOCK_UNAVAIL
StringRefNull name() const
constexpr bool is_empty() const
Definition BLI_span.hh:261
constexpr bool contains(const T &value) const
Definition BLI_span.hh:278
geo_eval_log::GeoTreeLogger * get_local_tree_logger() const
void error_message_add(const NodeWarningType type, StringRef message) const
const Depsgraph * depsgraph() const
Span< bke::GeometryComponent::Type > supported_types() const
bool attribute_name_is_anonymous(const StringRef name)
void set_default_remaining_node_outputs(lf::Params &params, const bNode &node)
bNodeSocketTypeHandle * typeinfo
char identifier[64]
const CurvesEditHints * get_curve_edit_hints() const
const GreasePencil * get_grease_pencil() const
const Curves * get_curves() const
const PointCloud * get_pointcloud() const
const Mesh * get_mesh() const
Vector< GeometryComponent::Type > gather_component_types(bool include_instances, bool ignore_empty) const