Blender  V3.3
node_geo_switch.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "node_geometry_util.hh"
4 
5 #include "UI_interface.h"
6 #include "UI_resources.h"
7 
8 #include "DNA_mesh_types.h"
9 #include "DNA_meshdata_types.h"
10 
11 #include "BKE_material.h"
12 
14 
16 
18 
20 
22 {
23  b.add_input<decl::Bool>(N_("Switch")).default_value(false).supports_field();
24  b.add_input<decl::Bool>(N_("Switch"), "Switch_001").default_value(false);
25 
26  b.add_input<decl::Float>(N_("False")).supports_field();
27  b.add_input<decl::Float>(N_("True")).supports_field();
28  b.add_input<decl::Int>(N_("False"), "False_001").min(-100000).max(100000).supports_field();
29  b.add_input<decl::Int>(N_("True"), "True_001").min(-100000).max(100000).supports_field();
30  b.add_input<decl::Bool>(N_("False"), "False_002")
31  .default_value(false)
32  .hide_value()
33  .supports_field();
34  b.add_input<decl::Bool>(N_("True"), "True_002")
35  .default_value(true)
36  .hide_value()
37  .supports_field();
38  b.add_input<decl::Vector>(N_("False"), "False_003").supports_field();
39  b.add_input<decl::Vector>(N_("True"), "True_003").supports_field();
40  b.add_input<decl::Color>(N_("False"), "False_004")
41  .default_value({0.8f, 0.8f, 0.8f, 1.0f})
42  .supports_field();
43  b.add_input<decl::Color>(N_("True"), "True_004")
44  .default_value({0.8f, 0.8f, 0.8f, 1.0f})
45  .supports_field();
46  b.add_input<decl::String>(N_("False"), "False_005").supports_field();
47  b.add_input<decl::String>(N_("True"), "True_005").supports_field();
48 
49  b.add_input<decl::Geometry>(N_("False"), "False_006");
50  b.add_input<decl::Geometry>(N_("True"), "True_006");
51  b.add_input<decl::Object>(N_("False"), "False_007");
52  b.add_input<decl::Object>(N_("True"), "True_007");
53  b.add_input<decl::Collection>(N_("False"), "False_008");
54  b.add_input<decl::Collection>(N_("True"), "True_008");
55  b.add_input<decl::Texture>(N_("False"), "False_009");
56  b.add_input<decl::Texture>(N_("True"), "True_009");
57  b.add_input<decl::Material>(N_("False"), "False_010");
58  b.add_input<decl::Material>(N_("True"), "True_010");
59  b.add_input<decl::Image>(N_("False"), "False_011");
60  b.add_input<decl::Image>(N_("True"), "True_011");
61 
62  b.add_output<decl::Float>(N_("Output")).dependent_field();
63  b.add_output<decl::Int>(N_("Output"), "Output_001").dependent_field();
64  b.add_output<decl::Bool>(N_("Output"), "Output_002").dependent_field();
65  b.add_output<decl::Vector>(N_("Output"), "Output_003").dependent_field();
66  b.add_output<decl::Color>(N_("Output"), "Output_004").dependent_field();
67  b.add_output<decl::String>(N_("Output"), "Output_005").dependent_field();
68  b.add_output<decl::Geometry>(N_("Output"), "Output_006");
69  b.add_output<decl::Object>(N_("Output"), "Output_007");
70  b.add_output<decl::Collection>(N_("Output"), "Output_008");
71  b.add_output<decl::Texture>(N_("Output"), "Output_009");
72  b.add_output<decl::Material>(N_("Output"), "Output_010");
73  b.add_output<decl::Image>(N_("Output"), "Output_011");
74 }
75 
76 static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
77 {
78  uiItemR(layout, ptr, "input_type", 0, "", ICON_NONE);
79 }
80 
82 {
83  NodeSwitch *data = MEM_cnew<NodeSwitch>(__func__);
84  data->input_type = SOCK_GEOMETRY;
85  node->storage = data;
86 }
87 
89 {
90  const NodeSwitch &storage = node_storage(*node);
91  int index = 0;
92  bNodeSocket *field_switch = (bNodeSocket *)node->inputs.first;
93  bNodeSocket *non_field_switch = (bNodeSocket *)field_switch->next;
94 
95  const bool fields_type = ELEM(
97 
98  nodeSetSocketAvailability(ntree, field_switch, fields_type);
99  nodeSetSocketAvailability(ntree, non_field_switch, !fields_type);
100 
101  LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, &node->inputs, index) {
102  if (index <= 1) {
103  continue;
104  }
105  nodeSetSocketAvailability(ntree, socket, socket->type == storage.input_type);
106  }
107 
108  LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
109  nodeSetSocketAvailability(ntree, socket, socket->type == storage.input_type);
110  }
111 }
112 
114 {
115  if (params.in_out() == SOCK_OUT) {
116  params.add_item(IFACE_("Output"), [](LinkSearchOpParams &params) {
117  bNode &node = params.add_node("GeometryNodeSwitch");
118  node_storage(node).input_type = params.socket.type;
119  params.update_and_connect_available_socket(node, "Output");
120  });
121  }
122  else {
123  if (params.other_socket().type == SOCK_BOOLEAN) {
124  params.add_item(IFACE_("Switch"), [](LinkSearchOpParams &params) {
125  bNode &node = params.add_node("GeometryNodeSwitch");
126  params.update_and_connect_available_socket(node, "Switch");
127  });
128  }
129  params.add_item(IFACE_("False"), [](LinkSearchOpParams &params) {
130  bNode &node = params.add_node("GeometryNodeSwitch");
131  node_storage(node).input_type = params.socket.type;
132  params.update_and_connect_available_socket(node, "False");
133  });
134  params.add_item(IFACE_("True"), [](LinkSearchOpParams &params) {
135  bNode &node = params.add_node("GeometryNodeSwitch");
136  node_storage(node).input_type = params.socket.type;
137  params.update_and_connect_available_socket(node, "True");
138  });
139  }
140 }
141 
142 template<typename T> void switch_fields(GeoNodeExecParams &params, const StringRef suffix)
143 {
144  if (params.lazy_require_input("Switch")) {
145  return;
146  }
147 
148  const std::string name_false = "False" + suffix;
149  const std::string name_true = "True" + suffix;
150  const std::string name_output = "Output" + suffix;
151 
152  Field<bool> switches_field = params.get_input<Field<bool>>("Switch");
153  if (switches_field.node().depends_on_input()) {
154  /* The switch has to be incorporated into the field. Both inputs have to be evaluated. */
155  const bool require_false = params.lazy_require_input(name_false);
156  const bool require_true = params.lazy_require_input(name_true);
157  if (require_false | require_true) {
158  return;
159  }
160 
161  Field<T> falses_field = params.extract_input<Field<T>>(name_false);
162  Field<T> trues_field = params.extract_input<Field<T>>(name_true);
163 
165  "Switch", [](bool condition, const T &false_value, const T &true_value) {
166  return condition ? true_value : false_value;
167  }};
168 
169  auto switch_op = std::make_shared<FieldOperation>(FieldOperation(
170  std::move(switch_fn),
171  {std::move(switches_field), std::move(falses_field), std::move(trues_field)}));
172 
173  params.set_output(name_output, Field<T>(switch_op, 0));
174  }
175  else {
176  /* The switch input is constant, so just evaluate and forward one of the inputs. */
177  const bool switch_value = fn::evaluate_constant_field(switches_field);
178  if (switch_value) {
179  params.set_input_unused(name_false);
180  if (params.lazy_require_input(name_true)) {
181  return;
182  }
183  params.set_output(name_output, params.extract_input<Field<T>>(name_true));
184  }
185  else {
186  params.set_input_unused(name_true);
187  if (params.lazy_require_input(name_false)) {
188  return;
189  }
190  params.set_output(name_output, params.extract_input<Field<T>>(name_false));
191  }
192  }
193 }
194 
195 template<typename T> void switch_no_fields(GeoNodeExecParams &params, const StringRef suffix)
196 {
197  if (params.lazy_require_input("Switch_001")) {
198  return;
199  }
200  bool switch_value = params.get_input<bool>("Switch_001");
201 
202  const std::string name_false = "False" + suffix;
203  const std::string name_true = "True" + suffix;
204  const std::string name_output = "Output" + suffix;
205 
206  if (switch_value) {
207  params.set_input_unused(name_false);
208  if (params.lazy_require_input(name_true)) {
209  return;
210  }
211  params.set_output(name_output, params.extract_input<T>(name_true));
212  }
213  else {
214  params.set_input_unused(name_true);
215  if (params.lazy_require_input(name_false)) {
216  return;
217  }
218  params.set_output(name_output, params.extract_input<T>(name_false));
219  }
220 }
221 
223 {
224  const NodeSwitch &storage = node_storage(params.node());
225  const eNodeSocketDatatype data_type = static_cast<eNodeSocketDatatype>(storage.input_type);
226 
227  switch (data_type) {
228 
229  case SOCK_FLOAT: {
230  switch_fields<float>(params, "");
231  break;
232  }
233  case SOCK_INT: {
234  switch_fields<int>(params, "_001");
235  break;
236  }
237  case SOCK_BOOLEAN: {
238  switch_fields<bool>(params, "_002");
239  break;
240  }
241  case SOCK_VECTOR: {
242  switch_fields<float3>(params, "_003");
243  break;
244  }
245  case SOCK_RGBA: {
246  switch_fields<ColorGeometry4f>(params, "_004");
247  break;
248  }
249  case SOCK_STRING: {
250  switch_fields<std::string>(params, "_005");
251  break;
252  }
253  case SOCK_GEOMETRY: {
254  switch_no_fields<GeometrySet>(params, "_006");
255  break;
256  }
257  case SOCK_OBJECT: {
258  switch_no_fields<Object *>(params, "_007");
259  break;
260  }
261  case SOCK_COLLECTION: {
262  switch_no_fields<Collection *>(params, "_008");
263  break;
264  }
265  case SOCK_TEXTURE: {
266  switch_no_fields<Tex *>(params, "_009");
267  break;
268  }
269  case SOCK_MATERIAL: {
270  switch_no_fields<Material *>(params, "_010");
271  break;
272  }
273  case SOCK_IMAGE: {
274  switch_no_fields<Image *>(params, "_011");
275  break;
276  }
277  default:
279  break;
280  }
281 }
282 
283 } // namespace blender::nodes::node_geo_switch_cc
284 
286 {
287  namespace file_ns = blender::nodes::node_geo_switch_cc;
288 
289  static bNodeType ntype;
290 
300  nodeRegisterType(&ntype);
301 }
General operations, lookup, etc. for materials.
void node_type_update(struct bNodeType *ntype, void(*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4443
#define NODE_CLASS_CONVERTER
Definition: BKE_node.h:351
#define NODE_STORAGE_FUNCS(StorageT)
Definition: BKE_node.h:1563
void nodeSetSocketAvailability(struct bNodeTree *ntree, struct bNodeSocket *sock, bool is_available)
Definition: node.cc:3664
void node_type_init(struct bNodeType *ntype, void(*initfunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4390
#define GEO_NODE_SWITCH
Definition: BKE_node.h:1400
void node_type_storage(struct bNodeType *ntype, const char *storagename, void(*freefunc)(struct bNode *node), void(*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, const struct bNode *src_node))
Definition: node.cc:4426
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:344
#define UNUSED(x)
#define ELEM(...)
#define IFACE_(msgid)
@ SOCK_OUT
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_TEXTURE
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_MATERIAL
@ SOCK_FLOAT
@ SOCK_IMAGE
@ SOCK_COLLECTION
@ SOCK_GEOMETRY
@ SOCK_OBJECT
@ SOCK_STRING
@ SOCK_RGBA
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
bool depends_on_input() const
Definition: FN_field.hh:585
const FieldNode & node() const
Definition: FN_field.hh:127
OperationNode * node
void * tree
bNodeTree * ntree
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define T
void evaluate_constant_field(const GField &field, void *r_value)
Definition: field.cc:494
static void node_gather_link_searches(GatherLinkSearchOpParams &params)
static void node_update(bNodeTree *ntree, bNode *node)
static void node_geo_exec(GeoNodeExecParams params)
void switch_fields(GeoNodeExecParams &params, const StringRef suffix)
static void node_declare(NodeDeclarationBuilder &b)
static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
void switch_no_fields(GeoNodeExecParams &params, const StringRef suffix)
static void node_init(bNodeTree *UNUSED(tree), bNode *node)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
Definition: node.cc:1082
void register_node_type_geo_switch()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
Definition: node_util.c:55
void node_free_standard_storage(bNode *node)
Definition: node_util.c:43
#define min(a, b)
Definition: sort.c:35
uint8_t input_type
struct bNodeSocket * next
Defines a node type.
Definition: BKE_node.h:226
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:316
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition: BKE_node.h:335
bool geometry_node_execute_supports_laziness
Definition: BKE_node.h:321
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
Definition: BKE_node.h:244
NodeDeclareFunction declare
Definition: BKE_node.h:324
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480