Blender  V3.3
node_fn_compare.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <cmath>
4 
5 #include "BLI_listbase.h"
6 #include "BLI_math_vector.h"
7 #include "BLI_string.h"
8 
9 #include "UI_interface.h"
10 #include "UI_resources.h"
11 
12 #include "RNA_enum_types.h"
13 
14 #include "node_function_util.hh"
15 
17 
19 
21 
23 {
24  b.is_function_node();
25  b.add_input<decl::Float>(N_("A")).min(-10000.0f).max(10000.0f);
26  b.add_input<decl::Float>(N_("B")).min(-10000.0f).max(10000.0f);
27 
28  b.add_input<decl::Int>(N_("A"), "A_INT");
29  b.add_input<decl::Int>(N_("B"), "B_INT");
30 
31  b.add_input<decl::Vector>(N_("A"), "A_VEC3");
32  b.add_input<decl::Vector>(N_("B"), "B_VEC3");
33 
34  b.add_input<decl::Color>(N_("A"), "A_COL");
35  b.add_input<decl::Color>(N_("B"), "B_COL");
36 
37  b.add_input<decl::String>(N_("A"), "A_STR");
38  b.add_input<decl::String>(N_("B"), "B_STR");
39 
40  b.add_input<decl::Float>(N_("C")).default_value(0.9f);
41  b.add_input<decl::Float>(N_("Angle")).default_value(0.0872665f).subtype(PROP_ANGLE);
42  b.add_input<decl::Float>(N_("Epsilon")).default_value(0.001).min(-10000.0f).max(10000.0f);
43 
44  b.add_output<decl::Bool>(N_("Result"));
45 }
46 
48 {
49  const NodeFunctionCompare &data = node_storage(*static_cast<const bNode *>(ptr->data));
50  uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
51  if (data.data_type == SOCK_VECTOR) {
52  uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
53  }
54  uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
55 }
56 
58 {
60 
61  bNodeSocket *sock_comp = (bNodeSocket *)BLI_findlink(&node->inputs, 10);
62  bNodeSocket *sock_angle = (bNodeSocket *)BLI_findlink(&node->inputs, 11);
63  bNodeSocket *sock_epsilon = (bNodeSocket *)BLI_findlink(&node->inputs, 12);
64 
65  LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
66  nodeSetSocketAvailability(ntree, socket, socket->type == (eNodeSocketDatatype)data->data_type);
67  }
68 
70  sock_epsilon,
72  !ELEM(data->data_type, SOCK_INT, SOCK_STRING));
73 
75  sock_comp,
77  data->data_type == SOCK_VECTOR);
78 
80  sock_angle,
82  data->data_type == SOCK_VECTOR);
83 }
84 
86 {
87  NodeFunctionCompare *data = MEM_cnew<NodeFunctionCompare>(__func__);
88  data->operation = NODE_COMPARE_GREATER_THAN;
89  data->data_type = SOCK_FLOAT;
91  node->storage = data;
92 }
93 
95  public:
96  std::string socket_name;
101  {
102  bNode &node = params.add_node("FunctionNodeCompare");
103  node_storage(node).data_type = data_type;
104  node_storage(node).operation = operation;
105  node_storage(node).mode = mode;
106  params.update_and_connect_available_socket(node, socket_name);
107  }
108 };
109 
111 {
112  const eNodeSocketDatatype type = static_cast<eNodeSocketDatatype>(params.other_socket().type);
114  return;
115  }
116 
117  const eNodeSocketDatatype mode_type = (type == SOCK_BOOLEAN) ? SOCK_INT : type;
118  const bool string_type = (type == SOCK_STRING);
119 
120  const std::string socket_name = params.in_out() == SOCK_IN ? "A" : "Result";
121 
123  item->identifier != nullptr;
124  item++) {
125  if (item->name != nullptr && item->identifier[0] != '\0') {
126  if (!string_type &&
128  params.add_item(IFACE_(item->name),
129  SocketSearchOp{socket_name,
130  SOCK_RGBA,
131  static_cast<NodeCompareOperation>(item->value)});
132  }
133  else if ((!string_type) ||
134  (string_type && ELEM(item->value, NODE_COMPARE_EQUAL, NODE_COMPARE_NOT_EQUAL))) {
135  params.add_item(IFACE_(item->name),
136  SocketSearchOp{socket_name,
137  mode_type,
138  static_cast<NodeCompareOperation>(item->value)});
139  }
140  }
141  }
142  /* Add Angle socket. */
143  if (!string_type && params.in_out() == SOCK_IN) {
144  params.add_item(
145  IFACE_("Angle"),
148  }
149 }
150 
152  const bNode *node,
153  char *label,
154  int maxlen)
155 {
156  const NodeFunctionCompare *data = (NodeFunctionCompare *)node->storage;
157  const char *name;
158  bool enum_label = RNA_enum_name(rna_enum_node_compare_operation_items, data->operation, &name);
159  if (!enum_label) {
160  name = "Unknown";
161  }
162  BLI_strncpy(label, IFACE_(name), maxlen);
163 }
164 
166 {
167  return (a.x + a.y + a.z) / 3.0f;
168 }
169 
171 {
172  const NodeFunctionCompare *data = (NodeFunctionCompare *)node.storage;
173 
174  static auto exec_preset_all = fn::CustomMF_presets::AllSpanOrSingle();
175  static auto exec_preset_first_two = fn::CustomMF_presets::SomeSpanOrSingle<0, 1>();
176 
177  switch (data->data_type) {
178  case SOCK_FLOAT:
179  switch (data->operation) {
180  case NODE_COMPARE_LESS_THAN: {
182  "Less Than", [](float a, float b) { return a < b; }, exec_preset_all};
183  return &fn;
184  }
187  "Less Equal", [](float a, float b) { return a <= b; }, exec_preset_all};
188  return &fn;
189  }
192  "Greater Than", [](float a, float b) { return a > b; }, exec_preset_all};
193  return &fn;
194  }
197  "Greater Equal", [](float a, float b) { return a >= b; }, exec_preset_all};
198  return &fn;
199  }
200  case NODE_COMPARE_EQUAL: {
202  "Equal",
203  [](float a, float b, float epsilon) { return std::abs(a - b) <= epsilon; },
204  exec_preset_first_two};
205  return &fn;
206  }
209  "Not Equal",
210  [](float a, float b, float epsilon) { return std::abs(a - b) > epsilon; },
211  exec_preset_first_two};
212  return &fn;
213  }
214  break;
215  case SOCK_INT:
216  switch (data->operation) {
217  case NODE_COMPARE_LESS_THAN: {
219  "Less Than", [](int a, int b) { return a < b; }, exec_preset_all};
220  return &fn;
221  }
224  "Less Equal", [](int a, int b) { return a <= b; }, exec_preset_all};
225  return &fn;
226  }
229  "Greater Than", [](int a, int b) { return a > b; }, exec_preset_all};
230  return &fn;
231  }
234  "Greater Equal", [](int a, int b) { return a >= b; }, exec_preset_all};
235  return &fn;
236  }
237  case NODE_COMPARE_EQUAL: {
239  "Equal", [](int a, int b) { return a == b; }, exec_preset_all};
240  return &fn;
241  }
242  case NODE_COMPARE_NOT_EQUAL: {
244  "Not Equal", [](int a, int b) { return a != b; }, exec_preset_all};
245  return &fn;
246  }
247  }
248  break;
249  case SOCK_VECTOR:
250  switch (data->operation) {
252  switch (data->mode) {
255  "Less Than - Average",
256  [](float3 a, float3 b) { return component_average(a) < component_average(b); },
257  exec_preset_all};
258  return &fn;
259  }
262  "Less Than - Dot Product",
263  [](float3 a, float3 b, float comp) { return math::dot(a, b) < comp; },
264  exec_preset_first_two};
265  return &fn;
266  }
269  "Less Than - Direction",
270  [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) < angle; },
271  exec_preset_first_two};
272  return &fn;
273  }
276  "Less Than - Element-wise",
277  [](float3 a, float3 b) { return a.x < b.x && a.y < b.y && a.z < b.z; },
278  exec_preset_all};
279  return &fn;
280  }
283  "Less Than - Length",
284  [](float3 a, float3 b) { return math::length(a) < math::length(b); },
285  exec_preset_all};
286  return &fn;
287  }
288  }
289  break;
291  switch (data->mode) {
294  "Less Equal - Average",
295  [](float3 a, float3 b) { return component_average(a) <= component_average(b); },
296  exec_preset_all};
297  return &fn;
298  }
301  "Less Equal - Dot Product",
302  [](float3 a, float3 b, float comp) { return math::dot(a, b) <= comp; },
303  exec_preset_first_two};
304  return &fn;
305  }
308  "Less Equal - Direction",
309  [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) <= angle; },
310  exec_preset_first_two};
311  return &fn;
312  }
315  "Less Equal - Element-wise",
316  [](float3 a, float3 b) { return a.x <= b.x && a.y <= b.y && a.z <= b.z; },
317  exec_preset_all};
318  return &fn;
319  }
322  "Less Equal - Length",
323  [](float3 a, float3 b) { return math::length(a) <= math::length(b); },
324  exec_preset_all};
325  return &fn;
326  }
327  }
328  break;
330  switch (data->mode) {
333  "Greater Than - Average",
334  [](float3 a, float3 b) { return component_average(a) > component_average(b); },
335  exec_preset_all};
336  return &fn;
337  }
340  "Greater Than - Dot Product",
341  [](float3 a, float3 b, float comp) { return math::dot(a, b) > comp; },
342  exec_preset_first_two};
343  return &fn;
344  }
347  "Greater Than - Direction",
348  [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) > angle; },
349  exec_preset_first_two};
350  return &fn;
351  }
354  "Greater Than - Element-wise",
355  [](float3 a, float3 b) { return a.x > b.x && a.y > b.y && a.z > b.z; },
356  exec_preset_all};
357  return &fn;
358  }
361  "Greater Than - Length",
362  [](float3 a, float3 b) { return math::length(a) > math::length(b); },
363  exec_preset_all};
364  return &fn;
365  }
366  }
367  break;
369  switch (data->mode) {
372  "Greater Equal - Average",
373  [](float3 a, float3 b) { return component_average(a) >= component_average(b); },
374  exec_preset_all};
375  return &fn;
376  }
379  "Greater Equal - Dot Product",
380  [](float3 a, float3 b, float comp) { return math::dot(a, b) >= comp; },
381  exec_preset_first_two};
382  return &fn;
383  }
386  "Greater Equal - Direction",
387  [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) >= angle; },
388  exec_preset_first_two};
389  return &fn;
390  }
393  "Greater Equal - Element-wise",
394  [](float3 a, float3 b) { return a.x >= b.x && a.y >= b.y && a.z >= b.z; },
395  exec_preset_all};
396  return &fn;
397  }
400  "Greater Equal - Length",
401  [](float3 a, float3 b) { return math::length(a) >= math::length(b); },
402  exec_preset_all};
403  return &fn;
404  }
405  }
406  break;
407  case NODE_COMPARE_EQUAL:
408  switch (data->mode) {
411  "Equal - Average",
412  [](float3 a, float3 b, float epsilon) {
414  },
415  exec_preset_first_two};
416  return &fn;
417  }
420  "Equal - Dot Product",
421  [](float3 a, float3 b, float comp, float epsilon) {
422  return abs(math::dot(a, b) - comp) <= epsilon;
423  },
424  exec_preset_first_two};
425  return &fn;
426  }
429  "Equal - Direction",
430  [](float3 a, float3 b, float angle, float epsilon) {
431  return abs(angle_v3v3(a, b) - angle) <= epsilon;
432  },
433  exec_preset_first_two};
434  return &fn;
435  }
438  "Equal - Element-wise",
439  [](float3 a, float3 b, float epsilon) {
440  return abs(a.x - b.x) <= epsilon && abs(a.y - b.y) <= epsilon &&
441  abs(a.z - b.z) <= epsilon;
442  },
443  exec_preset_first_two};
444  return &fn;
445  }
448  "Equal - Length",
449  [](float3 a, float3 b, float epsilon) {
450  return abs(math::length(a) - math::length(b)) <= epsilon;
451  },
452  exec_preset_first_two};
453  return &fn;
454  }
455  }
456  break;
458  switch (data->mode) {
461  "Not Equal - Average",
462  [](float3 a, float3 b, float epsilon) {
464  },
465  exec_preset_first_two};
466  return &fn;
467  }
470  "Not Equal - Dot Product",
471  [](float3 a, float3 b, float comp, float epsilon) {
472  return abs(math::dot(a, b) - comp) >= epsilon;
473  },
474  exec_preset_first_two};
475  return &fn;
476  }
479  "Not Equal - Direction",
480  [](float3 a, float3 b, float angle, float epsilon) {
481  return abs(angle_v3v3(a, b) - angle) > epsilon;
482  },
483  exec_preset_first_two};
484  return &fn;
485  }
488  "Not Equal - Element-wise",
489  [](float3 a, float3 b, float epsilon) {
490  return abs(a.x - b.x) > epsilon || abs(a.y - b.y) > epsilon ||
491  abs(a.z - b.z) > epsilon;
492  },
493  exec_preset_first_two};
494  return &fn;
495  }
498  "Not Equal - Length",
499  [](float3 a, float3 b, float epsilon) {
500  return abs(math::length(a) - math::length(b)) > epsilon;
501  },
502  exec_preset_first_two};
503  return &fn;
504  }
505  }
506  break;
507  }
508  break;
509  case SOCK_RGBA:
510  switch (data->operation) {
511  case NODE_COMPARE_EQUAL: {
513  "Equal",
515  return abs(a.r - b.r) <= epsilon && abs(a.g - b.g) <= epsilon &&
516  abs(a.b - b.b) <= epsilon;
517  },
518  exec_preset_first_two};
519  return &fn;
520  }
521  case NODE_COMPARE_NOT_EQUAL: {
523  "Not Equal",
525  return abs(a.r - b.r) > epsilon || abs(a.g - b.g) > epsilon ||
526  abs(a.b - b.b) > epsilon;
527  },
528  exec_preset_first_two};
529  return &fn;
530  }
533  "Brighter",
536  },
537  exec_preset_all};
538  return &fn;
539  }
542  "Darker",
545  },
546  exec_preset_all};
547  return &fn;
548  }
549  }
550  break;
551  case SOCK_STRING:
552  switch (data->operation) {
553  case NODE_COMPARE_EQUAL: {
555  "Equal", [](std::string a, std::string b) { return a == b; }};
556  return &fn;
557  }
558  case NODE_COMPARE_NOT_EQUAL: {
560  "Not Equal", [](std::string a, std::string b) { return a != b; }};
561  return &fn;
562  }
563  }
564  break;
565  }
566  return nullptr;
567 }
568 
570 {
571  const fn::MultiFunction *fn = get_multi_function(builder.node());
572  builder.set_matching_fn(fn);
573 }
574 
575 } // namespace blender::nodes::node_fn_compare_cc
576 
578 {
579  namespace file_ns = blender::nodes::node_fn_compare_cc;
580 
581  static bNodeType ntype;
588  &ntype, "NodeFunctionCompare", node_free_standard_storage, node_copy_standard_storage);
592  nodeRegisterType(&ntype);
593 }
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 FN_NODE_COMPARE
Definition: BKE_node.h:1520
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 LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float rgb_to_grayscale(const float rgb[3])
float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:385
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#define UNUSED(x)
#define ELEM(...)
#define IFACE_(msgid)
@ SOCK_IN
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_FLOAT
@ SOCK_STRING
@ SOCK_RGBA
NodeCompareMode
@ NODE_COMPARE_MODE_ELEMENT
@ NODE_COMPARE_MODE_LENGTH
@ NODE_COMPARE_MODE_DOT_PRODUCT
@ NODE_COMPARE_MODE_AVERAGE
@ NODE_COMPARE_MODE_DIRECTION
NodeCompareOperation
@ NODE_COMPARE_NOT_EQUAL
@ NODE_COMPARE_LESS_EQUAL
@ NODE_COMPARE_COLOR_BRIGHTER
@ NODE_COMPARE_EQUAL
@ NODE_COMPARE_GREATER_EQUAL
@ NODE_COMPARE_GREATER_THAN
@ NODE_COMPARE_COLOR_DARKER
@ NODE_COMPARE_LESS_THAN
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
@ PROP_ANGLE
Definition: RNA_types.h:145
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
void set_matching_fn(const MultiFunction *fn)
OperationNode * node
const char * label
void * tree
bNodeTree * ntree
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
static unsigned a[3]
Definition: RandGen.cpp:78
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
T length(const vec_base< T, Size > &a)
T abs(const T &a)
static void fn_node_compare_declare(NodeDeclarationBuilder &b)
static void node_compare_init(bNodeTree *UNUSED(tree), bNode *node)
static void node_compare_update(bNodeTree *ntree, bNode *node)
static const fn::MultiFunction * get_multi_function(bNode &node)
static void node_compare_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
static void geo_node_compare_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
static void node_compare_gather_link_searches(GatherLinkSearchOpParams &params)
static float component_average(float3 a)
static void fn_node_compare_build_multi_function(NodeMultiFunctionBuilder &builder)
static double epsilon
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
void register_node_type_fn_compare()
void fn_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
bool RNA_enum_name(const EnumPropertyItem *item, const int value, const char **r_name)
Definition: rna_access.c:1692
const EnumPropertyItem rna_enum_node_compare_operation_items[]
Definition: rna_nodetree.c:349
#define min(a, b)
Definition: sort.c:35
const char * identifier
Definition: RNA_types.h:461
void * data
Definition: RNA_types.h:38
Defines a node type.
Definition: BKE_node.h:226
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition: BKE_node.h:335
void(* labelfunc)(const struct bNodeTree *ntree, const struct bNode *node, char *label, int maxlen)
Definition: BKE_node.h:256
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
Definition: BKE_node.h:244
NodeMultiFunctionBuildFunction build_multi_function
Definition: BKE_node.h:313
NodeDeclareFunction declare
Definition: BKE_node.h:324
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480