Blender  V3.3
node_util.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2007 Blender Foundation. All rights reserved. */
3 
8 #include <ctype.h>
9 #include <limits.h>
10 #include <string.h>
11 
12 #include "DNA_node_types.h"
13 
14 #include "BLI_listbase.h"
15 #include "BLI_string.h"
16 #include "BLI_utildefines.h"
17 
18 #include "BLT_translation.h"
19 
20 #include "BKE_colortools.h"
21 #include "BKE_node.h"
22 #include "BKE_node_tree_update.h"
23 
24 #include "RNA_access.h"
25 #include "RNA_enum_types.h"
26 #include "RNA_prototypes.h"
27 
28 #include "MEM_guardedalloc.h"
29 
30 #include "NOD_common.h"
31 
32 #include "node_util.h"
33 
34 /* -------------------------------------------------------------------- */
39 {
40  BKE_curvemapping_free(node->storage);
41 }
42 
44 {
45  if (node->storage) {
46  MEM_freeN(node->storage);
47  }
48 }
49 
50 void node_copy_curves(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
51 {
52  dest_node->storage = BKE_curvemapping_copy(src_node->storage);
53 }
54 
56  bNode *dest_node,
57  const bNode *src_node)
58 {
59  dest_node->storage = MEM_dupallocN(src_node->storage);
60 }
61 
63  bNode *node,
65 {
66  BKE_curvemapping_init(node->storage);
67  return NULL; /* unused return */
68 }
69 
72 /* -------------------------------------------------------------------- */
76 void node_sock_label(bNodeSocket *sock, const char *name)
77 {
78  BLI_strncpy(sock->label, name, MAX_NAME);
79 }
80 
82 {
83  if (sock->label[0] != '\0') {
84  sock->label[0] = '\0';
85  }
86 }
87 
89 {
90  bNodeSocket *sock1 = BLI_findlink(&node->inputs, 0);
91  bNodeSocket *sock2 = BLI_findlink(&node->inputs, 1);
92  bNodeSocket *sock3 = BLI_findlink(&node->inputs, 2);
94  sock2,
95  !ELEM(node->custom1,
111  !ELEM(node->custom1,
117  NODE_MATH_TANH));
119  sock3,
120  ELEM(node->custom1,
126 
127  node_sock_label_clear(sock1);
128  node_sock_label_clear(sock2);
129  node_sock_label_clear(sock3);
130 
131  switch (node->custom1) {
132  case NODE_MATH_WRAP:
133  node_sock_label(sock2, "Max");
134  node_sock_label(sock3, "Min");
135  break;
137  node_sock_label(sock2, "Multiplier");
138  node_sock_label(sock3, "Addend");
139  break;
140  case NODE_MATH_LESS_THAN:
142  node_sock_label(sock2, "Threshold");
143  break;
144  case NODE_MATH_PINGPONG:
145  node_sock_label(sock2, "Scale");
146  break;
147  case NODE_MATH_SNAP:
148  node_sock_label(sock2, "Increment");
149  break;
150  case NODE_MATH_POWER:
151  node_sock_label(sock1, "Base");
152  node_sock_label(sock2, "Exponent");
153  break;
154  case NODE_MATH_LOGARITHM:
155  node_sock_label(sock2, "Base");
156  break;
157  case NODE_MATH_DEGREES:
158  node_sock_label(sock1, "Radians");
159  break;
160  case NODE_MATH_RADIANS:
161  node_sock_label(sock1, "Degrees");
162  break;
163  case NODE_MATH_COMPARE:
164  node_sock_label(sock3, "Epsilon");
165  break;
168  node_sock_label(sock3, "Distance");
169  break;
170  }
171 }
172 
175 /* -------------------------------------------------------------------- */
179 void node_blend_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
180 {
181  const char *name;
182  bool enum_label = RNA_enum_name(rna_enum_ramp_blend_items, node->custom1, &name);
183  if (!enum_label) {
184  name = "Unknown";
185  }
186  BLI_strncpy(label, IFACE_(name), maxlen);
187 }
188 
189 void node_image_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
190 {
191  /* If there is no loaded image, return an empty string,
192  * and let nodeLabel() fill in the proper type translation. */
193  BLI_strncpy(label, (node->id) ? node->id->name + 2 : "", maxlen);
194 }
195 
196 void node_math_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
197 {
198  const char *name;
199  bool enum_label = RNA_enum_name(rna_enum_node_math_items, node->custom1, &name);
200  if (!enum_label) {
201  name = "Unknown";
202  }
204 }
205 
207  const bNode *node,
208  char *label,
209  int maxlen)
210 {
211  const char *name;
212  bool enum_label = RNA_enum_name(rna_enum_node_vec_math_items, node->custom1, &name);
213  if (!enum_label) {
214  name = "Unknown";
215  }
216  BLI_strncpy(label, IFACE_(name), maxlen);
217 }
218 
219 void node_filter_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
220 {
221  const char *name;
222  bool enum_label = RNA_enum_name(rna_enum_node_filter_items, node->custom1, &name);
223  if (!enum_label) {
224  name = "Unknown";
225  }
226  BLI_strncpy(label, IFACE_(name), maxlen);
227 }
228 
230 {
231  bNodeSocket *sock1 = (bNodeSocket *)sockets->first;
232  bNodeSocket *sock2 = sock1->next;
233  bNodeSocket *sock3 = sock2->next;
234 
235  node_sock_label_clear(sock1);
236  node_sock_label_clear(sock2);
237  node_sock_label_clear(sock3);
238 
239  switch (mode) {
241  node_sock_label(sock1, "Red");
242  node_sock_label(sock2, "Green");
243  node_sock_label(sock3, "Blue");
244  break;
246  node_sock_label(sock1, "Hue");
247  node_sock_label(sock2, "Saturation");
248  node_sock_label(sock3, "Lightness");
249  break;
251  node_sock_label(sock1, "Hue");
252  node_sock_label(sock2, "Saturation");
253  node_sock_label(sock3, "Value");
254  break;
255  default: {
257  break;
258  }
259  }
260 }
261 
264 /* -------------------------------------------------------------------- */
268 static bool node_link_socket_match(const bNodeSocket *a, const bNodeSocket *b)
269 {
270  /* Check if sockets are of the same type. */
271  if (a->typeinfo != b->typeinfo) {
272  return false;
273  }
274 
275  /* Test if alphabetic prefix matches, allowing for imperfect matches, such as numeric suffixes
276  * like Color1/Color2. */
277  int prefix_len = 0;
278  const char *ca = a->name, *cb = b->name;
279  for (; *ca != '\0' && *cb != '\0'; ca++, cb++) {
280  /* End of common prefix? */
281  if (*ca != *cb) {
282  /* Prefix delimited by non-alphabetic char. */
283  if (isalpha(*ca) || isalpha(*cb)) {
284  return false;
285  }
286  break;
287  }
288  prefix_len++;
289  }
290  return prefix_len > 0;
291 }
292 
293 static int node_count_links(const bNodeTree *ntree, const bNodeSocket *socket)
294 {
295  int count = 0;
296  LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
297  if (ELEM(socket, link->fromsock, link->tosock)) {
298  count++;
299  }
300  }
301  return count;
302 }
303 
305  bNode *node,
306  bNodeSocket *to_socket)
307 {
308  bNodeSocket *first = to_socket->in_out == SOCK_IN ? node->inputs.first : node->outputs.first;
309 
310  /* Wrap around the list end. */
311  bNodeSocket *socket_iter = to_socket->next ? to_socket->next : first;
312  while (socket_iter != to_socket) {
313  if (!nodeSocketIsHidden(socket_iter) && node_link_socket_match(socket_iter, to_socket)) {
314  const int link_count = node_count_links(ntree, socket_iter);
315  /* Add one to account for the new link being added. */
316  if (link_count + 1 <= nodeSocketLinkLimit(socket_iter)) {
317  return socket_iter; /* Found a valid free socket we can swap to. */
318  }
319  }
320  socket_iter = socket_iter->next ? socket_iter->next : first; /* Wrap around the list end. */
321  }
322 
323  return NULL;
324 }
325 
327 {
328  bNodeSocket *socket = link->tosock;
329 
330  if (node != link->tonode) {
331  return;
332  }
333 
334  /* If we're not at the link limit of the target socket, we can skip
335  * trying to move existing links to another socket. */
336  const int to_link_limit = nodeSocketLinkLimit(socket);
337  if (socket->total_inputs + 1 < to_link_limit) {
338  return;
339  }
340 
342  if (socket == to_link->tosock) {
343  bNodeSocket *new_socket = node_find_linkable_socket(ntree, node, socket);
344  if (new_socket && new_socket != socket) {
345  /* Attempt to redirect the existing link to the new socket. */
346  to_link->tosock = new_socket;
347  return;
348  }
349 
350  if (new_socket == NULL) {
351  /* No possible replacement, remove the existing link. */
352  nodeRemLink(ntree, to_link);
353  return;
354  }
355  }
356  }
357 }
358 
361 /* -------------------------------------------------------------------- */
366 {
367  PointerRNA ptr;
368  RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
369  return RNA_float_get(&ptr, "default_value");
370 }
371 
373 {
374  PointerRNA ptr;
375  RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
376  RNA_float_set(&ptr, "default_value", value);
377 }
378 
380 {
381  PointerRNA ptr;
382  RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
383  RNA_float_get_array(&ptr, "default_value", value);
384 }
385 
387  bNode *UNUSED(node),
388  bNodeSocket *sock,
389  const float *value)
390 {
391  PointerRNA ptr;
392  RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
393  RNA_float_set_array(&ptr, "default_value", value);
394 }
395 
397 {
398  PointerRNA ptr;
399  RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
400  RNA_float_get_array(&ptr, "default_value", value);
401 }
402 
404  bNode *UNUSED(node),
405  bNodeSocket *sock,
406  const float *value)
407 {
408  PointerRNA ptr;
409  RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
410  RNA_float_set_array(&ptr, "default_value", value);
411 }
412 
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1235
struct CurveMapping * BKE_curvemapping_copy(const struct CurveMapping *cumap)
void BKE_curvemapping_free(struct CurveMapping *cumap)
Definition: colortools.c:103
void nodeSetSocketAvailability(struct bNodeTree *ntree, struct bNodeSocket *sock, bool is_available)
Definition: node.cc:3664
void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link)
Definition: node.cc:2338
int nodeSocketIsHidden(const struct bNodeSocket *sock)
int nodeSocketLinkLimit(const struct bNodeSocket *sock)
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
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 BLT_I18NCONTEXT_ID_NODETREE
#define CTX_IFACE_(context, msgid)
#define IFACE_(msgid)
#define MAX_NAME
Definition: DNA_defs.h:48
@ NODE_MATH_SINH
@ NODE_MATH_SMOOTH_MIN
@ NODE_MATH_TRUNC
@ NODE_MATH_COSH
@ NODE_MATH_SIGN
@ NODE_MATH_DEGREES
@ NODE_MATH_ABSOLUTE
@ NODE_MATH_SINE
@ NODE_MATH_ARCCOSINE
@ NODE_MATH_MULTIPLY_ADD
@ NODE_MATH_POWER
@ NODE_MATH_WRAP
@ NODE_MATH_ARCTANGENT
@ NODE_MATH_SQRT
@ NODE_MATH_CEIL
@ NODE_MATH_TANH
@ NODE_MATH_GREATER_THAN
@ NODE_MATH_FRACTION
@ NODE_MATH_EXPONENT
@ NODE_MATH_LESS_THAN
@ NODE_MATH_ARCSINE
@ NODE_MATH_LOGARITHM
@ NODE_MATH_COMPARE
@ NODE_MATH_INV_SQRT
@ NODE_MATH_PINGPONG
@ NODE_MATH_ROUND
@ NODE_MATH_FLOOR
@ NODE_MATH_COSINE
@ NODE_MATH_SNAP
@ NODE_MATH_TANGENT
@ NODE_MATH_SMOOTH_MAX
@ NODE_MATH_RADIANS
@ SOCK_IN
NodeCombSepColorMode
@ NODE_COMBSEP_COLOR_RGB
@ NODE_COMBSEP_COLOR_HSV
@ NODE_COMBSEP_COLOR_HSL
Read Guarded memory(de)allocation.
OperationNode * node
const char * label
bNodeTree * ntree
int count
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
static unsigned a[3]
Definition: RandGen.cpp:78
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
void node_sock_label_clear(bNodeSocket *sock)
Definition: node_util.c:81
void node_sock_label(bNodeSocket *sock, const char *name)
Definition: node_util.c:76
void node_copy_curves(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
Definition: node_util.c:50
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
void node_image_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
Definition: node_util.c:189
void node_socket_set_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, const float *value)
Definition: node_util.c:403
void node_filter_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
Definition: node_util.c:219
void node_socket_get_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value)
Definition: node_util.c:379
void * node_initexec_curves(bNodeExecContext *UNUSED(context), bNode *node, bNodeInstanceKey UNUSED(key))
Definition: node_util.c:62
static int node_count_links(const bNodeTree *ntree, const bNodeSocket *socket)
Definition: node_util.c:293
void node_free_curves(bNode *node)
Definition: node_util.c:38
void node_socket_set_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float value)
Definition: node_util.c:372
void node_math_update(bNodeTree *ntree, bNode *node)
Definition: node_util.c:88
float node_socket_get_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock)
Definition: node_util.c:365
void node_socket_get_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value)
Definition: node_util.c:396
void node_combsep_color_label(const ListBase *sockets, NodeCombSepColorMode mode)
Definition: node_util.c:229
void node_insert_link_default(bNodeTree *ntree, bNode *node, bNodeLink *link)
Definition: node_util.c:326
static bool node_link_socket_match(const bNodeSocket *a, const bNodeSocket *b)
Definition: node_util.c:268
static bNodeSocket * node_find_linkable_socket(bNodeTree *ntree, bNode *node, bNodeSocket *to_socket)
Definition: node_util.c:304
void node_blend_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
Definition: node_util.c:179
void node_socket_set_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, const float *value)
Definition: node_util.c:386
void node_vector_math_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
Definition: node_util.c:206
void node_math_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *label, int maxlen)
Definition: node_util.c:196
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:136
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
Definition: rna_access.c:4980
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4957
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:4968
bool RNA_enum_name(const EnumPropertyItem *item, const int value, const char **r_name)
Definition: rna_access.c:1692
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
Definition: rna_access.c:4992
const EnumPropertyItem rna_enum_ramp_blend_items[]
Definition: rna_material.c:26
const EnumPropertyItem rna_enum_node_math_items[]
Definition: rna_nodetree.c:166
const EnumPropertyItem rna_enum_node_vec_math_items[]
Definition: rna_nodetree.c:235
const EnumPropertyItem rna_enum_node_filter_items[]
Definition: rna_nodetree.c:452
Definition: DNA_ID.h:368
void * first
Definition: DNA_listBase.h:31
struct bNodeSocket * next
short total_inputs
char label[64]
ListBase links
void * storage
PointerRNA * ptr
Definition: wm_files.c:3480