Blender  V2.93
node_draw.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2008 Blender Foundation.
17  * All rights reserved.
18  */
19 
25 #include "MEM_guardedalloc.h"
26 
27 #include "DNA_light_types.h"
28 #include "DNA_linestyle_types.h"
29 #include "DNA_material_types.h"
30 #include "DNA_modifier_types.h"
31 #include "DNA_node_types.h"
32 #include "DNA_screen_types.h"
33 #include "DNA_space_types.h"
34 #include "DNA_texture_types.h"
35 #include "DNA_world_types.h"
36 
37 #include "BLI_blenlib.h"
38 #include "BLI_map.hh"
39 #include "BLI_math.h"
40 #include "BLI_set.hh"
41 #include "BLI_span.hh"
42 #include "BLI_string_ref.hh"
43 #include "BLI_vector.hh"
44 
45 #include "BLT_translation.h"
46 
47 #include "BKE_context.h"
48 #include "BKE_lib_id.h"
49 #include "BKE_main.h"
50 #include "BKE_node.h"
51 #include "BKE_node_ui_storage.hh"
52 #include "BKE_object.h"
53 
54 #include "DEG_depsgraph.h"
55 
56 #include "BLF_api.h"
57 
58 #include "BIF_glutil.h"
59 
60 #include "GPU_framebuffer.h"
61 #include "GPU_immediate.h"
62 #include "GPU_immediate_util.h"
63 #include "GPU_matrix.h"
64 #include "GPU_state.h"
65 #include "GPU_viewport.h"
66 
67 #include "WM_api.h"
68 #include "WM_types.h"
69 
70 #include "ED_gpencil.h"
71 #include "ED_node.h"
72 #include "ED_space_api.h"
73 
74 #include "UI_resources.h"
75 #include "UI_view2d.h"
76 
77 #include "RNA_access.h"
78 
79 #include "node_intern.h" /* own include */
80 
81 #ifdef WITH_COMPOSITOR
82 # include "COM_compositor.h"
83 #endif
84 
85 using blender::Map;
86 using blender::Set;
87 using blender::Span;
88 using blender::Vector;
89 
90 extern "C" {
91 /* XXX interface.h */
92 extern void ui_draw_dropshadow(
93  const rctf *rct, float radius, float aspect, float alpha, int select);
94 }
95 
96 float ED_node_grid_size(void)
97 {
98  return U.widget_unit;
99 }
100 
102 {
103  SpaceNode *snode = CTX_wm_space_node(C);
104  if (snode) {
106 
107  id_us_ensure_real(&snode->nodetree->id);
108  }
109 }
110 
111 /* id is supposed to contain a node tree */
113 {
114  if (id) {
115  if (GS(id->name) == ID_NT) {
116  return (bNodeTree *)id;
117  }
118  return ntreeFromID(id);
119  }
120 
121  return nullptr;
122 }
123 
125 {
127  if (id == nullptr || ntree == nullptr) {
128  return;
129  }
130 
131  /* TODO(sergey): With the new dependency graph it should be just enough to only tag ntree itself.
132  * All the users of this tree will have update flushed from the tree. */
133  DEG_id_tag_update(&ntree->id, 0);
134 
135  if (ntree->type == NTREE_SHADER) {
136  DEG_id_tag_update(id, 0);
137 
138  if (GS(id->name) == ID_MA) {
140  }
141  else if (GS(id->name) == ID_LA) {
143  }
144  else if (GS(id->name) == ID_WO) {
146  }
147  }
148  else if (ntree->type == NTREE_COMPOSIT) {
150  }
151  else if (ntree->type == NTREE_TEXTURE) {
152  DEG_id_tag_update(id, 0);
154  }
155  else if (ntree->type == NTREE_GEOMETRY) {
157  }
158  else if (id == &ntree->id) {
159  /* Node groups. */
160  DEG_id_tag_update(id, 0);
161  }
162 }
163 
165 {
166  if (!ntree) {
167  return;
168  }
169 
170  bool do_tag_update = true;
171  if (node != nullptr) {
172  if (!node_connected_to_output(bmain, ntree, node)) {
173  do_tag_update = false;
174  }
175  }
176 
177  /* Look through all datablocks to support groups. */
178  if (do_tag_update) {
179  FOREACH_NODETREE_BEGIN (bmain, tntree, id) {
180  /* Check if nodetree uses the group. */
181  if (ntreeHasTree(tntree, ntree)) {
183  }
184  }
186  }
187 
188  if (ntree->type == NTREE_TEXTURE) {
190  }
191 }
192 
193 static bool compare_nodes(const bNode *a, const bNode *b)
194 {
195  /* These tell if either the node or any of the parent nodes is selected.
196  * A selected parent means an unselected node is also in foreground! */
197  bool a_select = (a->flag & NODE_SELECT) != 0, b_select = (b->flag & NODE_SELECT) != 0;
198  bool a_active = (a->flag & NODE_ACTIVE) != 0, b_active = (b->flag & NODE_ACTIVE) != 0;
199 
200  /* If one is an ancestor of the other. */
201  /* XXX there might be a better sorting algorithm for stable topological sort,
202  * this is O(n^2) worst case. */
203  for (bNode *parent = a->parent; parent; parent = parent->parent) {
204  /* If B is an ancestor, it is always behind A. */
205  if (parent == b) {
206  return true;
207  }
208  /* Any selected ancestor moves the node forward. */
209  if (parent->flag & NODE_ACTIVE) {
210  a_active = true;
211  }
212  if (parent->flag & NODE_SELECT) {
213  a_select = true;
214  }
215  }
216  for (bNode *parent = b->parent; parent; parent = parent->parent) {
217  /* If A is an ancestor, it is always behind B. */
218  if (parent == a) {
219  return false;
220  }
221  /* Any selected ancestor moves the node forward. */
222  if (parent->flag & NODE_ACTIVE) {
223  b_active = true;
224  }
225  if (parent->flag & NODE_SELECT) {
226  b_select = true;
227  }
228  }
229 
230  /* One of the nodes is in the background and the other not. */
231  if ((a->flag & NODE_BACKGROUND) && !(b->flag & NODE_BACKGROUND)) {
232  return false;
233  }
234  if (!(a->flag & NODE_BACKGROUND) && (b->flag & NODE_BACKGROUND)) {
235  return true;
236  }
237 
238  /* One has a higher selection state (active > selected > nothing). */
239  if (!b_active && a_active) {
240  return true;
241  }
242  if (!b_select && (a_active || a_select)) {
243  return true;
244  }
245 
246  return false;
247 }
248 
254 {
255  /* Merge sort is the algorithm of choice here. */
256  int totnodes = BLI_listbase_count(&ntree->nodes);
257 
258  int k = 1;
259  while (k < totnodes) {
260  bNode *first_a = (bNode *)ntree->nodes.first;
261  bNode *first_b = first_a;
262 
263  do {
264  /* Set up first_b pointer. */
265  for (int b = 0; b < k && first_b; b++) {
266  first_b = first_b->next;
267  }
268  /* All batches merged? */
269  if (first_b == nullptr) {
270  break;
271  }
272 
273  /* Merge batches. */
274  bNode *node_a = first_a;
275  bNode *node_b = first_b;
276  int a = 0;
277  int b = 0;
278  while (a < k && b < k && node_b) {
279  if (compare_nodes(node_a, node_b) == 0) {
280  node_a = node_a->next;
281  a++;
282  }
283  else {
284  bNode *tmp = node_b;
285  node_b = node_b->next;
286  b++;
287  BLI_remlink(&ntree->nodes, tmp);
288  BLI_insertlinkbefore(&ntree->nodes, node_a, tmp);
289  }
290  }
291 
292  /* Set up first pointers for next batch. */
293  first_b = node_b;
294  for (; b < k; b++) {
295  /* All nodes sorted? */
296  if (first_b == nullptr) {
297  break;
298  }
299  first_b = first_b->next;
300  }
301  first_a = first_b;
302  } while (first_b);
303 
304  k = k << 1;
305  }
306 }
307 
309 {
310  /* Add node uiBlocks in drawing order - prevents events going to overlapping nodes. */
311 
313  /* ui block */
314  char uiblockstr[32];
315  BLI_snprintf(uiblockstr, sizeof(uiblockstr), "node buttons %p", (void *)node);
316  node->block = UI_block_begin(C, CTX_wm_region(C), uiblockstr, UI_EMBOSS);
317 
318  /* this cancels events for background nodes */
320  }
321 }
322 
323 void node_to_view(const bNode *node, float x, float y, float *rx, float *ry)
324 {
325  nodeToView(node, x, y, rx, ry);
326  *rx *= UI_DPI_FAC;
327  *ry *= UI_DPI_FAC;
328 }
329 
330 void node_to_updated_rect(const bNode *node, rctf *r_rect)
331 {
332  node_to_view(node, node->offsetx, node->offsety, &r_rect->xmin, &r_rect->ymax);
334  node->offsetx + node->width,
335  node->offsety - node->height,
336  &r_rect->xmax,
337  &r_rect->ymin);
338 }
339 
340 void node_from_view(const bNode *node, float x, float y, float *rx, float *ry)
341 {
342  x /= UI_DPI_FAC;
343  y /= UI_DPI_FAC;
344  nodeFromView(node, x, y, rx, ry);
345 }
346 
351 {
352  PointerRNA nodeptr;
353  RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
354 
355  /* Get "global" coordinates. */
356  float locx, locy;
357  node_to_view(node, 0.0f, 0.0f, &locx, &locy);
358  float dy = locy;
359 
360  /* Header. */
361  dy -= NODE_DY;
362 
363  /* Little bit of space in top. */
364  if (node->outputs.first) {
365  dy -= NODE_DYS / 2;
366  }
367 
368  /* Output sockets. */
369  bool add_output_space = false;
370 
371  int buty;
372  LISTBASE_FOREACH (bNodeSocket *, nsock, &node->outputs) {
373  if (nodeSocketIsHidden(nsock)) {
374  continue;
375  }
376 
377  PointerRNA sockptr;
378  RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
379 
380  uiLayout *layout = UI_block_layout(node->block,
383  locx + NODE_DYS,
384  dy,
386  NODE_DY,
387  0,
388  UI_style_get_dpi());
389 
390  if (node->flag & NODE_MUTED) {
391  uiLayoutSetActive(layout, false);
392  }
393 
394  /* Context pointers for current node and socket. */
395  uiLayoutSetContextPointer(layout, "node", &nodeptr);
396  uiLayoutSetContextPointer(layout, "socket", &sockptr);
397 
398  /* Align output buttons to the right. */
399  uiLayout *row = uiLayoutRow(layout, true);
401  const char *socket_label = nodeSocketLabel(nsock);
402  nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
403 
404  UI_block_align_end(node->block);
405  UI_block_layout_resolve(node->block, nullptr, &buty);
406 
407  /* Ensure minimum socket height in case layout is empty. */
408  buty = min_ii(buty, dy - NODE_DY);
409 
410  nsock->locx = locx + NODE_WIDTH(node);
411  /* Place the socket circle in the middle of the layout. */
412  nsock->locy = 0.5f * (dy + buty);
413 
414  dy = buty;
415  if (nsock->next) {
416  dy -= NODE_SOCKDY;
417  }
418 
419  add_output_space = true;
420  }
421 
422  if (add_output_space) {
423  dy -= NODE_DY / 4;
424  }
425 
426  node->prvr.xmin = locx + NODE_DYS;
427  node->prvr.xmax = locx + NODE_WIDTH(node) - NODE_DYS;
428 
429  /* preview rect? */
430  if (node->flag & NODE_PREVIEW) {
431  float aspect = 1.0f;
432 
433  if (node->preview_xsize && node->preview_ysize) {
434  aspect = (float)node->preview_ysize / (float)node->preview_xsize;
435  }
436 
437  dy -= NODE_DYS / 2;
438  node->prvr.ymax = dy;
439 
440  if (aspect <= 1.0f) {
441  node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY);
442  }
443  else {
444  /* Width correction of image. XXX huh? (ton) */
445  float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect;
446 
447  node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY);
448 
449  node->prvr.xmin += 0.5f * dx;
450  node->prvr.xmax -= 0.5f * dx;
451  }
452 
453  dy = node->prvr.ymin - NODE_DYS / 2;
454 
455  /* Make sure that maximums are bigger or equal to minimums. */
456  if (node->prvr.xmax < node->prvr.xmin) {
457  SWAP(float, node->prvr.xmax, node->prvr.xmin);
458  }
459  if (node->prvr.ymax < node->prvr.ymin) {
460  SWAP(float, node->prvr.ymax, node->prvr.ymin);
461  }
462  }
463 
464  /* Buttons rect? */
465  if (node->typeinfo->draw_buttons && (node->flag & NODE_OPTIONS)) {
466  dy -= NODE_DYS / 2;
467 
468  /* Set this for `uifunc()` that don't use layout engine yet. */
469  node->butr.xmin = 0;
470  node->butr.xmax = NODE_WIDTH(node) - 2 * NODE_DYS;
471  node->butr.ymin = 0;
472  node->butr.ymax = 0;
473 
474  uiLayout *layout = UI_block_layout(node->block,
477  locx + NODE_DYS,
478  dy,
479  node->butr.xmax,
480  0,
481  0,
482  UI_style_get_dpi());
483 
484  if (node->flag & NODE_MUTED) {
485  uiLayoutSetActive(layout, false);
486  }
487 
488  uiLayoutSetContextPointer(layout, "node", &nodeptr);
489 
490  node->typeinfo->draw_buttons(layout, (bContext *)C, &nodeptr);
491 
492  UI_block_align_end(node->block);
493  UI_block_layout_resolve(node->block, nullptr, &buty);
494 
495  dy = buty - NODE_DYS / 2;
496  }
497 
498  /* Input sockets. */
499  LISTBASE_FOREACH (bNodeSocket *, nsock, &node->inputs) {
500  if (nodeSocketIsHidden(nsock)) {
501  continue;
502  }
503 
504  PointerRNA sockptr;
505  RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
506 
507  /* Add the half the height of a multi-input socket to cursor Y
508  * to account for the increased height of the taller sockets. */
509  float multi_input_socket_offset = 0.0f;
510  if (nsock->flag & SOCK_MULTI_INPUT) {
511  if (nsock->total_inputs > 2) {
512  multi_input_socket_offset = (nsock->total_inputs - 2) * NODE_MULTI_INPUT_LINK_GAP;
513  }
514  }
515  dy -= multi_input_socket_offset * 0.5f;
516 
517  uiLayout *layout = UI_block_layout(node->block,
520  locx + NODE_DYS,
521  dy,
523  NODE_DY,
524  0,
525  UI_style_get_dpi());
526 
527  if (node->flag & NODE_MUTED) {
528  uiLayoutSetActive(layout, false);
529  }
530 
531  /* Context pointers for current node and socket. */
532  uiLayoutSetContextPointer(layout, "node", &nodeptr);
533  uiLayoutSetContextPointer(layout, "socket", &sockptr);
534 
535  uiLayout *row = uiLayoutRow(layout, true);
536 
537  const char *socket_label = nodeSocketLabel(nsock);
538  nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
539 
540  UI_block_align_end(node->block);
541  UI_block_layout_resolve(node->block, nullptr, &buty);
542 
543  /* Ensure minimum socket height in case layout is empty. */
544  buty = min_ii(buty, dy - NODE_DY);
545 
546  nsock->locx = locx;
547  /* Place the socket circle in the middle of the layout. */
548  nsock->locy = 0.5f * (dy + buty);
549 
550  dy = buty - multi_input_socket_offset * 0.5;
551  if (nsock->next) {
552  dy -= NODE_SOCKDY;
553  }
554  }
555 
556  /* Little bit of space in end. */
557  if (node->inputs.first || (node->flag & (NODE_OPTIONS | NODE_PREVIEW)) == 0) {
558  dy -= NODE_DYS / 2;
559  }
560 
561  node->totr.xmin = locx;
562  node->totr.xmax = locx + NODE_WIDTH(node);
563  node->totr.ymax = locy;
564  node->totr.ymin = min_ff(dy, locy - 2 * NODE_DY);
565 
566  /* Set the block bounds to clip mouse events from underlying nodes.
567  * Add a margin for sockets on each side. */
569  node->totr.xmin - NODE_SOCKSIZE,
570  node->totr.ymin,
571  node->totr.xmax + NODE_SOCKSIZE,
572  node->totr.ymax);
573 }
574 
579 {
580  int totin = 0, totout = 0;
581 
582  /* Get "global" coords. */
583  float locx, locy;
584  node_to_view(node, 0.0f, 0.0f, &locx, &locy);
585 
586  /* Calculate minimal radius. */
587  LISTBASE_FOREACH (bNodeSocket *, nsock, &node->inputs) {
588  if (!nodeSocketIsHidden(nsock)) {
589  totin++;
590  }
591  }
592  LISTBASE_FOREACH (bNodeSocket *, nsock, &node->outputs) {
593  if (!nodeSocketIsHidden(nsock)) {
594  totout++;
595  }
596  }
597 
598  float hiddenrad = HIDDEN_RAD;
599  float tot = MAX2(totin, totout);
600  if (tot > 4) {
601  hiddenrad += 5.0f * (float)(tot - 4);
602  }
603 
604  node->totr.xmin = locx;
605  node->totr.xmax = locx + max_ff(NODE_WIDTH(node), 2 * hiddenrad);
606  node->totr.ymax = locy + (hiddenrad - 0.5f * NODE_DY);
607  node->totr.ymin = node->totr.ymax - 2 * hiddenrad;
608 
609  /* Output sockets. */
610  float rad = (float)M_PI / (1.0f + (float)totout);
611  float drad = rad;
612 
613  LISTBASE_FOREACH (bNodeSocket *, nsock, &node->outputs) {
614  if (!nodeSocketIsHidden(nsock)) {
615  nsock->locx = node->totr.xmax - hiddenrad + sinf(rad) * hiddenrad;
616  nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad;
617  rad += drad;
618  }
619  }
620 
621  /* Input sockets. */
622  rad = drad = -(float)M_PI / (1.0f + (float)totin);
623 
624  LISTBASE_FOREACH (bNodeSocket *, nsock, &node->inputs) {
625  if (!nodeSocketIsHidden(nsock)) {
626  nsock->locx = node->totr.xmin + hiddenrad + sinf(rad) * hiddenrad;
627  nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad;
628  rad += drad;
629  }
630  }
631 
632  /* Set the block bounds to clip mouse events from underlying nodes.
633  * Add a margin for sockets on each side. */
635  node->totr.xmin - NODE_SOCKSIZE,
636  node->totr.ymin,
637  node->totr.xmax + NODE_SOCKSIZE,
638  node->totr.ymax);
639 }
640 
642 {
643  if (node->flag & NODE_HIDDEN) {
645  }
646  else {
648  }
649 }
650 
652 {
653  return BLI_rctf_isect_pt(&node->totr, x, y);
654 }
655 
657 {
658  return BLI_rctf_isect_pt(&node->totr, x, y);
659 }
660 
662 {
663  switch (node->typeinfo->nclass) {
664  case NODE_CLASS_INPUT:
665  return TH_NODE_INPUT;
666  case NODE_CLASS_OUTPUT:
667  return (node->flag & NODE_DO_OUTPUT) ? TH_NODE_OUTPUT : TH_NODE;
669  return TH_NODE_CONVERTOR;
670  case NODE_CLASS_OP_COLOR:
671  return TH_NODE_COLOR;
673  return TH_NODE_VECTOR;
675  return TH_NODE_FILTER;
676  case NODE_CLASS_GROUP:
677  return TH_NODE_GROUP;
679  return TH_NODE_INTERFACE;
680  case NODE_CLASS_MATTE:
681  return TH_NODE_MATTE;
682  case NODE_CLASS_DISTORT:
683  return TH_NODE_DISTORT;
684  case NODE_CLASS_TEXTURE:
685  return TH_NODE_TEXTURE;
686  case NODE_CLASS_SHADER:
687  return TH_NODE_SHADER;
688  case NODE_CLASS_SCRIPT:
689  return TH_NODE_SCRIPT;
690  case NODE_CLASS_PATTERN:
691  return TH_NODE_PATTERN;
692  case NODE_CLASS_LAYOUT:
693  return TH_NODE_LAYOUT;
694  case NODE_CLASS_GEOMETRY:
695  return TH_NODE_GEOMETRY;
697  return TH_NODE_ATTRIBUTE;
698  default:
699  return TH_NODE;
700  }
701 }
702 
703 static void node_draw_mute_line(const View2D *v2d, const SpaceNode *snode, const bNode *node)
704 {
706 
707  LISTBASE_FOREACH (const bNodeLink *, link, &node->internal_links) {
708  node_draw_link_bezier(v2d, snode, link, TH_REDALERT, TH_REDALERT, -1);
709  }
710 
712 }
713 
714 /* Flags used in gpu_shader_keyframe_diamond_frag.glsl. */
715 #define MARKER_SHAPE_DIAMOND 0x1
716 #define MARKER_SHAPE_SQUARE 0xC
717 #define MARKER_SHAPE_CIRCLE 0x2
718 #define MARKER_SHAPE_INNER_DOT 0x10
719 
720 static void node_socket_draw(const bNodeSocket *sock,
721  const float color[4],
722  const float color_outline[4],
723  float size,
724  int locx,
725  int locy,
726  uint pos_id,
727  uint col_id,
728  uint shape_id,
729  uint size_id,
730  uint outline_col_id)
731 {
732  int flags;
733 
734  /* Set shape flags. */
735  switch (sock->display_shape) {
738  flags = MARKER_SHAPE_DIAMOND;
739  break;
742  flags = MARKER_SHAPE_SQUARE;
743  break;
744  default:
747  flags = MARKER_SHAPE_CIRCLE;
748  break;
749  }
750 
751  if (ELEM(sock->display_shape,
755  flags |= MARKER_SHAPE_INNER_DOT;
756  }
757 
758  immAttr4fv(col_id, color);
759  immAttr1u(shape_id, flags);
760  immAttr1f(size_id, size);
761  immAttr4fv(outline_col_id, color_outline);
762  immVertex2f(pos_id, locx, locy);
763 }
764 
765 static void node_socket_draw_multi_input(const float color[4],
766  const float color_outline[4],
767  const float width,
768  const float height,
769  const int locx,
770  const int locy)
771 {
772  const float outline_width = 1.0f;
773  /* UI_draw_roundbox draws the outline on the outer side, so compensate for the outline width. */
774  const rctf rect = {
775  locx - width + outline_width * 0.5f,
776  locx + width - outline_width * 0.5f,
777  locy - height + outline_width * 0.5f,
778  locy + height - outline_width * 0.5f,
779  };
780 
783  &rect, color, nullptr, 1.0f, color_outline, outline_width, width - outline_width * 0.5f);
784 }
785 
786 static const float virtual_node_socket_outline_color[4] = {0.5, 0.5, 0.5, 1.0};
787 
788 static void node_socket_outline_color_get(const bool selected,
789  const int socket_type,
790  float r_outline_color[4])
791 {
792  if (selected) {
793  UI_GetThemeColor4fv(TH_TEXT_HI, r_outline_color);
794  r_outline_color[3] = 0.9f;
795  }
796  else {
797  copy_v4_fl(r_outline_color, 0.0f);
798  r_outline_color[3] = 0.6f;
799  }
800 
801  /* Until there is a better place for per socket color,
802  * the outline color for virtual sockets is set here. */
803  if (socket_type == SOCK_CUSTOM) {
805  }
806 }
807 
808 /* Usual convention here would be node_socket_get_color(), but that's already used (for setting a
809  * color property socket). */
811  bContext *C, bNodeTree *ntree, PointerRNA *node_ptr, bNodeSocket *sock, float r_color[4])
812 {
813  PointerRNA ptr;
814  BLI_assert(RNA_struct_is_a(node_ptr->type, &RNA_Node));
816 
817  sock->typeinfo->draw_color(C, &ptr, node_ptr, r_color);
818 
819  bNode *node = (bNode *)node_ptr->data;
820  if (node->flag & NODE_MUTED) {
821  r_color[3] *= 0.25f;
822  }
823 }
824 
825 static void node_socket_draw_nested(const bContext *C,
826  bNodeTree *ntree,
827  PointerRNA *node_ptr,
828  bNodeSocket *sock,
829  uint pos_id,
830  uint col_id,
831  uint shape_id,
832  uint size_id,
833  uint outline_col_id,
834  float size,
835  bool selected)
836 {
837  float color[4];
838  float outline_color[4];
839 
840  node_socket_color_get((bContext *)C, ntree, node_ptr, sock, color);
841  node_socket_outline_color_get(selected, sock->type, outline_color);
842 
843  node_socket_draw(sock,
844  color,
845  outline_color,
846  size,
847  sock->locx,
848  sock->locy,
849  pos_id,
850  col_id,
851  shape_id,
852  size_id,
853  outline_col_id);
854 }
855 
861 void ED_node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], float scale)
862 {
863  const float size = 2.25f * NODE_SOCKSIZE * scale;
864  rcti draw_rect = *rect;
865  float outline_color[4] = {0};
866 
867  node_socket_outline_color_get(sock->flag & SELECT, sock->type, outline_color);
868 
869  BLI_rcti_resize(&draw_rect, size, size);
870 
876  uint outline_col_id = GPU_vertformat_attr_add(
877  format, "outlineColor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
878 
882 
884  immUniform1f("outline_scale", 0.7f);
885  immUniform2f("ViewportSize", -1.0f, -1.0f);
886 
887  /* Single point. */
889  node_socket_draw(sock,
890  color,
891  outline_color,
892  BLI_rcti_size_y(&draw_rect),
893  BLI_rcti_cent_x(&draw_rect),
894  BLI_rcti_cent_y(&draw_rect),
895  pos_id,
896  col_id,
897  shape_id,
898  size_id,
899  outline_col_id);
900  immEnd();
901 
903  GPU_program_point_size(false);
904 
905  /* Restore. */
906  GPU_blend(state);
907 }
908 
909 /* ************** Socket callbacks *********** */
910 
912 {
915 
917 
918  /* Drawing the checkerboard. */
919  const float checker_dark = UI_ALPHA_CHECKER_DARK / 255.0f;
920  const float checker_light = UI_ALPHA_CHECKER_LIGHT / 255.0f;
921  immUniform4f("color1", checker_dark, checker_dark, checker_dark, 1.0f);
922  immUniform4f("color2", checker_light, checker_light, checker_light, 1.0f);
923  immUniform1i("size", 8);
924  immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
926 }
927 
928 /* Not a callback. */
929 static void node_draw_preview(bNodePreview *preview, rctf *prv)
930 {
931  float xrect = BLI_rctf_size_x(prv);
932  float yrect = BLI_rctf_size_y(prv);
933  float xscale = xrect / ((float)preview->xsize);
934  float yscale = yrect / ((float)preview->ysize);
935  float scale;
936 
937  /* Uniform scale and offset. */
938  rctf draw_rect = *prv;
939  if (xscale < yscale) {
940  float offset = 0.5f * (yrect - ((float)preview->ysize) * xscale);
941  draw_rect.ymin += offset;
942  draw_rect.ymax -= offset;
943  scale = xscale;
944  }
945  else {
946  float offset = 0.5f * (xrect - ((float)preview->xsize) * yscale);
947  draw_rect.xmin += offset;
948  draw_rect.xmax -= offset;
949  scale = yscale;
950  }
951 
952  node_draw_preview_background(&draw_rect);
953 
955  /* Premul graphics. */
957 
960  draw_rect.xmin,
961  draw_rect.ymin,
962  preview->xsize,
963  preview->ysize,
964  GPU_RGBA8,
965  true,
966  preview->rect,
967  scale,
968  scale,
969  nullptr);
970 
972 
976  imm_draw_box_wire_2d(pos, draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
978 }
979 
980 /* Common handle function for operator buttons that need to select the node first. */
981 static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_argv)
982 {
983  bNode *node = (bNode *)node_argv;
984  const char *opname = (const char *)op_argv;
985 
986  /* Select & activate only the button's node. */
988 
989  WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, nullptr);
990 }
991 
992 void node_draw_shadow(const SpaceNode *snode, const bNode *node, float radius, float alpha)
993 {
994  const rctf *rct = &node->totr;
996  ui_draw_dropshadow(rct, radius, snode->runtime->aspect, alpha, node->flag & SELECT);
997 }
998 
999 void node_draw_sockets(const View2D *v2d,
1000  const bContext *C,
1001  bNodeTree *ntree,
1002  bNode *node,
1003  bool draw_outputs,
1004  bool select_all)
1005 {
1006  const uint total_input_len = BLI_listbase_count(&node->inputs);
1007  const uint total_output_len = BLI_listbase_count(&node->outputs);
1008 
1009  if (total_input_len + total_output_len == 0) {
1010  return;
1011  }
1012 
1013  PointerRNA node_ptr;
1014  RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
1015 
1016  bool selected = false;
1017 
1021  uint shape_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
1023  uint outline_col_id = GPU_vertformat_attr_add(
1024  format, "outlineColor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
1025 
1027  GPU_program_point_size(true);
1029  immUniform1f("outline_scale", 0.7f);
1030  immUniform2f("ViewportSize", -1.0f, -1.0f);
1031 
1032  /* Set handle size. */
1033  float scale;
1034  UI_view2d_scale_get(v2d, &scale, nullptr);
1035  scale *= 2.25f * NODE_SOCKSIZE;
1036 
1037  if (!select_all) {
1038  immBeginAtMost(GPU_PRIM_POINTS, total_input_len + total_output_len);
1039  }
1040 
1041  /* Socket inputs. */
1042  short selected_input_len = 0;
1043  LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
1044  if (nodeSocketIsHidden(sock)) {
1045  continue;
1046  }
1047  if (select_all || (sock->flag & SELECT)) {
1048  selected_input_len++;
1049  continue;
1050  }
1051  /* Don't draw multi-input sockets here since they are drawn in a different batch. */
1052  if (sock->flag & SOCK_MULTI_INPUT) {
1053  continue;
1054  }
1055 
1057  ntree,
1058  &node_ptr,
1059  sock,
1060  pos_id,
1061  col_id,
1062  shape_id,
1063  size_id,
1064  outline_col_id,
1065  scale,
1066  selected);
1067  }
1068 
1069  /* Socket outputs. */
1070  short selected_output_len = 0;
1071  if (draw_outputs) {
1072  LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
1073  if (nodeSocketIsHidden(sock)) {
1074  continue;
1075  }
1076  if (select_all || (sock->flag & SELECT)) {
1077  selected_output_len++;
1078  continue;
1079  }
1080 
1082  ntree,
1083  &node_ptr,
1084  sock,
1085  pos_id,
1086  col_id,
1087  shape_id,
1088  size_id,
1089  outline_col_id,
1090  scale,
1091  selected);
1092  }
1093  }
1094 
1095  if (!select_all) {
1096  immEnd();
1097  }
1098 
1099  /* Go back and draw selected sockets. */
1100  if (selected_input_len + selected_output_len > 0) {
1101  /* Outline for selected sockets. */
1102 
1103  selected = true;
1104 
1105  immBegin(GPU_PRIM_POINTS, selected_input_len + selected_output_len);
1106 
1107  if (selected_input_len) {
1108  /* Socket inputs. */
1109  LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
1110  if (nodeSocketIsHidden(sock)) {
1111  continue;
1112  }
1113  if (select_all || (sock->flag & SELECT)) {
1115  ntree,
1116  &node_ptr,
1117  sock,
1118  pos_id,
1119  col_id,
1120  shape_id,
1121  size_id,
1122  outline_col_id,
1123  scale,
1124  selected);
1125  if (--selected_input_len == 0) {
1126  break; /* Stop as soon as last one is drawn. */
1127  }
1128  }
1129  }
1130  }
1131 
1132  if (selected_output_len) {
1133  /* Socket outputs. */
1134  LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
1135  if (nodeSocketIsHidden(sock)) {
1136  continue;
1137  }
1138  if (select_all || (sock->flag & SELECT)) {
1140  ntree,
1141  &node_ptr,
1142  sock,
1143  pos_id,
1144  col_id,
1145  shape_id,
1146  size_id,
1147  outline_col_id,
1148  scale,
1149  selected);
1150  if (--selected_output_len == 0) {
1151  break; /* Stop as soon as last one is drawn. */
1152  }
1153  }
1154  }
1155  }
1156 
1157  immEnd();
1158  }
1159 
1160  immUnbindProgram();
1161 
1162  GPU_program_point_size(false);
1164 
1165  /* Draw multi-input sockets after the others because they are drawn with `UI_draw_roundbox`
1166  * rather than with `GL_POINT`. */
1167  LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
1168  if (nodeSocketIsHidden(socket)) {
1169  continue;
1170  }
1171  if (!(socket->flag & SOCK_MULTI_INPUT)) {
1172  continue;
1173  }
1174 
1175  const bool is_node_hidden = (node->flag & NODE_HIDDEN);
1176  const float width = NODE_SOCKSIZE;
1177  float height = is_node_hidden ? width : node_socket_calculate_height(socket) - width;
1178 
1179  float color[4];
1180  float outline_color[4];
1181  node_socket_color_get((bContext *)C, ntree, &node_ptr, socket, color);
1182  node_socket_outline_color_get(selected, socket->type, outline_color);
1183 
1184  node_socket_draw_multi_input(color, outline_color, width, height, socket->locx, socket->locy);
1185  }
1186 }
1187 
1189 {
1190  switch (type) {
1192  return ICON_ERROR;
1194  return ICON_ERROR;
1195  case NodeWarningType::Info:
1196  return ICON_INFO;
1197  }
1198 
1199  BLI_assert(false);
1200  return ICON_ERROR;
1201 }
1202 
1204 {
1205  switch (type) {
1207  return 3;
1209  return 2;
1210  case NodeWarningType::Info:
1211  return 1;
1212  }
1213 
1214  BLI_assert(false);
1215  return 0;
1216 }
1217 
1219 {
1220  uint8_t highest_priority = 0;
1221  NodeWarningType highest_priority_type = NodeWarningType::Info;
1222  for (const NodeWarning &warning : warnings) {
1223  const uint8_t priority = node_error_type_priority(warning.type);
1224  if (priority > highest_priority) {
1225  highest_priority = priority;
1226  highest_priority_type = warning.type;
1227  }
1228  }
1229  return highest_priority_type;
1230 }
1231 
1232 static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char *UNUSED(tip))
1233 {
1234  const NodeUIStorage **storage_pointer_alloc = static_cast<const NodeUIStorage **>(argN);
1235  const NodeUIStorage *node_ui_storage = *storage_pointer_alloc;
1236  Span<NodeWarning> warnings = node_ui_storage->warnings;
1237 
1238  std::string complete_string;
1239 
1240  for (const NodeWarning &warning : warnings.drop_back(1)) {
1241  complete_string += warning.message;
1242  /* Adding the period is not ideal for multi-line messages, but it is consistent
1243  * with other tooltip implementations in Blender, so it is added here. */
1244  complete_string += '.';
1245  complete_string += '\n';
1246  }
1247 
1248  /* Let the tooltip system automatically add the last period. */
1249  complete_string += warnings.last().message;
1250 
1251  return BLI_strdupn(complete_string.c_str(), complete_string.size());
1252 }
1253 
1254 #define NODE_HEADER_ICON_SIZE (0.8f * U.widget_unit)
1255 
1257  const bContext *C, bNodeTree &ntree, bNode &node, const rctf &rect, float &icon_offset)
1258 {
1260  if (node_ui_storage == nullptr || node_ui_storage->warnings.is_empty()) {
1261  return;
1262  }
1263 
1264  /* The UI API forces us to allocate memory for each error button, because the
1265  * ownership of #UI_but_func_tooltip_set's argument is transferred to the button. */
1266  const NodeUIStorage **storage_pointer_alloc = (const NodeUIStorage **)MEM_mallocN(
1267  sizeof(NodeUIStorage *), __func__);
1268  *storage_pointer_alloc = node_ui_storage;
1269 
1270  const NodeWarningType display_type = node_error_highest_priority(node_ui_storage->warnings);
1271 
1272  icon_offset -= NODE_HEADER_ICON_SIZE;
1274  uiBut *but = uiDefIconBut(node.block,
1275  UI_BTYPE_BUT,
1276  0,
1277  node_error_type_to_icon(display_type),
1278  icon_offset,
1279  rect.ymax - NODE_DY,
1281  UI_UNIT_Y,
1282  nullptr,
1283  0,
1284  0,
1285  0,
1286  0,
1287  nullptr);
1288  UI_but_func_tooltip_set(but, node_errors_tooltip_fn, storage_pointer_alloc);
1290 }
1291 
1292 static void node_draw_basis(const bContext *C,
1293  const View2D *v2d,
1294  const SpaceNode *snode,
1295  bNodeTree *ntree,
1296  bNode *node,
1297  bNodeInstanceKey key)
1298 {
1299  const float iconbutw = NODE_HEADER_ICON_SIZE;
1300 
1301  /* Skip if out of view. */
1302  if (BLI_rctf_isect(&node->totr, &v2d->cur, nullptr) == false) {
1303  UI_block_end(C, node->block);
1304  node->block = nullptr;
1305  return;
1306  }
1307 
1308  /* Shadow. */
1309  node_draw_shadow(snode, node, BASIS_RAD, 1.0f);
1310 
1311  float color[4];
1312  int color_id = node_get_colorid(node);
1313  if (node->flag & NODE_MUTED) {
1314  /* Muted nodes are semi-transparent and colorless. */
1315  UI_GetThemeColor3fv(TH_NODE, color);
1316  color[3] = 0.25f;
1317  }
1318  else {
1319  /* Opaque headers for regular nodes. */
1320  UI_GetThemeColor3fv(color_id, color);
1321  color[3] = 1.0f;
1322  }
1323 
1324  GPU_line_width(1.0f);
1325 
1326  rctf *rct = &node->totr;
1328 
1329  {
1330  const rctf rect = {
1331  rct->xmin,
1332  rct->xmax,
1333  rct->ymax - NODE_DY,
1334  rct->ymax,
1335  };
1336  UI_draw_roundbox_aa(&rect, true, BASIS_RAD, color);
1337  }
1338 
1339  /* Show/hide icons. */
1340  float iconofs = rct->xmax - 0.35f * U.widget_unit;
1341 
1342  /* Preview. */
1343  if (node->typeinfo->flag & NODE_PREVIEW) {
1344  iconofs -= iconbutw;
1346  uiBut *but = uiDefIconBut(node->block,
1348  0,
1349  ICON_MATERIAL,
1350  iconofs,
1351  rct->ymax - NODE_DY,
1352  iconbutw,
1353  UI_UNIT_Y,
1354  nullptr,
1355  0,
1356  0,
1357  0,
1358  0,
1359  "");
1360  UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_preview_toggle");
1361  /* XXX this does not work when node is activated and the operator called right afterwards,
1362  * since active ID is not updated yet (needs to process the notifier).
1363  * This can only work as visual indicator! */
1364  // if (!(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT)))
1365  // UI_but_flag_enable(but, UI_BUT_DISABLED);
1367  }
1368  /* Group edit. */
1369  if (node->type == NODE_GROUP) {
1370  iconofs -= iconbutw;
1372  uiBut *but = uiDefIconBut(node->block,
1374  0,
1375  ICON_NODETREE,
1376  iconofs,
1377  rct->ymax - NODE_DY,
1378  iconbutw,
1379  UI_UNIT_Y,
1380  nullptr,
1381  0,
1382  0,
1383  0,
1384  0,
1385  "");
1386  UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_group_edit");
1388  }
1389  if (node->type == NODE_CUSTOM && node->typeinfo->ui_icon != ICON_NONE) {
1390  iconofs -= iconbutw;
1392  uiDefIconBut(node->block,
1393  UI_BTYPE_BUT,
1394  0,
1395  node->typeinfo->ui_icon,
1396  iconofs,
1397  rct->ymax - NODE_DY,
1398  iconbutw,
1399  UI_UNIT_Y,
1400  nullptr,
1401  0,
1402  0,
1403  0,
1404  0,
1405  "");
1407  }
1408  if (ntree->type == NTREE_GEOMETRY) {
1409  /* Active preview toggle. */
1410  iconofs -= iconbutw;
1412  int icon = (node->flag & NODE_ACTIVE_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON;
1413  uiBut *but = uiDefIconBut(node->block,
1415  0,
1416  icon,
1417  iconofs,
1418  rct->ymax - NODE_DY,
1419  iconbutw,
1420  UI_UNIT_Y,
1421  nullptr,
1422  0,
1423  0,
1424  0,
1425  0,
1426  "Show this node's geometry output in the spreadsheet");
1427  UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_active_preview_toggle");
1429  }
1430 
1431  node_add_error_message_button(C, *ntree, *node, *rct, iconofs);
1432 
1433  /* Title. */
1434  if (node->flag & SELECT) {
1436  }
1437  else {
1438  UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
1439  }
1440 
1441  /* Open/close entirely. */
1442  {
1443  int but_size = U.widget_unit * 0.8f;
1444  /* XXX button uses a custom triangle draw below, so make it invisible without icon. */
1446  uiBut *but = uiDefBut(node->block,
1448  0,
1449  "",
1450  rct->xmin + 0.35f * U.widget_unit,
1451  rct->ymax - NODE_DY / 2.2f - but_size / 2,
1452  but_size,
1453  but_size,
1454  nullptr,
1455  0,
1456  0,
1457  0,
1458  0,
1459  "");
1460  UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
1462 
1463  UI_GetThemeColor4fv(TH_TEXT, color);
1464  /* Custom draw function for this button. */
1465  UI_draw_icon_tri(rct->xmin + 0.65f * U.widget_unit, rct->ymax - NODE_DY / 2.2f, 'v', color);
1466  }
1467 
1468  char showname[128];
1469  nodeLabel(ntree, node, showname, sizeof(showname));
1470 
1471  uiBut *but = uiDefBut(node->block,
1473  0,
1474  showname,
1475  (int)(rct->xmin + NODE_MARGIN_X),
1476  (int)(rct->ymax - NODE_DY),
1477  (short)(iconofs - rct->xmin - (18.0f * U.dpi_fac)),
1478  (short)NODE_DY,
1479  nullptr,
1480  0,
1481  0,
1482  0,
1483  0,
1484  "");
1485  if (node->flag & NODE_MUTED) {
1487  }
1488 
1489  /* Body. */
1490  if (nodeTypeUndefined(node)) {
1491  /* Use warning color to indicate undefined types. */
1493  }
1494  else if (node->flag & NODE_MUTED) {
1495  /* Muted nodes are semi-transparent and colorless. */
1496  UI_GetThemeColor4fv(TH_NODE, color);
1497  }
1498  else if (node->flag & NODE_CUSTOM_COLOR) {
1499  rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], 1.0f);
1500  }
1501  else {
1502  UI_GetThemeColor4fv(TH_NODE, color);
1503  }
1504 
1505  if (node->flag & NODE_MUTED) {
1506  color[3] = 0.5f;
1507  }
1508 
1509  {
1511  const rctf rect = {
1512  rct->xmin,
1513  rct->xmax,
1514  rct->ymin,
1515  rct->ymax - NODE_DY,
1516  };
1517  UI_draw_roundbox_aa(&rect, true, BASIS_RAD, color);
1518  }
1519 
1520  /* Outline active and selected emphasis. */
1521  if (node->flag & SELECT) {
1523  (node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
1524 
1526  UI_draw_roundbox_aa(rct, false, BASIS_RAD, color);
1527  }
1528 
1529  /* Disable lines. */
1530  if (node->flag & NODE_MUTED) {
1531  node_draw_mute_line(v2d, snode, node);
1532  }
1533 
1534  node_draw_sockets(v2d, C, ntree, node, true, false);
1535 
1536  /* Preview. */
1537  bNodeInstanceHash *previews = (bNodeInstanceHash *)CTX_data_pointer_get(C, "node_previews").data;
1538  if (node->flag & NODE_PREVIEW && previews) {
1539  bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_lookup(previews, key);
1540  if (preview && (preview->xsize && preview->ysize)) {
1541  if (preview->rect && !BLI_rctf_is_empty(&node->prvr)) {
1542  node_draw_preview(preview, &node->prvr);
1543  }
1544  }
1545  }
1546 
1547  UI_block_end(C, node->block);
1548  UI_block_draw(C, node->block);
1549  node->block = nullptr;
1550 }
1551 
1552 static void node_draw_hidden(const bContext *C,
1553  const View2D *v2d,
1554  const SpaceNode *snode,
1555  bNodeTree *ntree,
1556  bNode *node,
1557  bNodeInstanceKey UNUSED(key))
1558 {
1559  rctf *rct = &node->totr;
1560  float centy = BLI_rctf_cent_y(rct);
1561  float hiddenrad = BLI_rctf_size_y(rct) / 2.0f;
1562 
1563  float scale;
1564  UI_view2d_scale_get(v2d, &scale, nullptr);
1565 
1566  /* Shadow. */
1567  node_draw_shadow(snode, node, hiddenrad, 1.0f);
1568 
1569  /* Body. */
1570  float color[4];
1571  int color_id = node_get_colorid(node);
1572  if (node->flag & NODE_MUTED) {
1573  /* Muted nodes are semi-transparent and colorless. */
1574  UI_GetThemeColor4fv(TH_NODE, color);
1575  color[3] = 0.25f;
1576  }
1577  else {
1578  UI_GetThemeColor4fv(color_id, color);
1579  }
1580 
1581  UI_draw_roundbox_aa(rct, true, hiddenrad, color);
1582 
1583  /* Outline active and selected emphasis. */
1584  if (node->flag & SELECT) {
1586  (node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
1587 
1588  UI_draw_roundbox_aa(rct, false, hiddenrad, color);
1589  }
1590 
1591  /* Custom color inline. */
1592  if (node->flag & NODE_CUSTOM_COLOR) {
1594  GPU_line_smooth(true);
1595 
1596  const rctf rect = {
1597  rct->xmin + 1,
1598  rct->xmax - 1,
1599  rct->ymin + 1,
1600  rct->ymax - 1,
1601  };
1602  UI_draw_roundbox_3fv_alpha(&rect, false, hiddenrad, node->color, 1.0f);
1603 
1604  GPU_line_smooth(false);
1606  }
1607 
1608  /* Title. */
1609  if (node->flag & SELECT) {
1611  }
1612  else {
1613  UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
1614  }
1615 
1616  /* Open / collapse icon. */
1617  {
1618  int but_size = U.widget_unit * 0.8f;
1619  /* XXX button uses a custom triangle draw below, so make it invisible without icon */
1621  uiBut *but = uiDefBut(node->block,
1623  0,
1624  "",
1625  rct->xmin + 0.35f * U.widget_unit,
1626  centy - but_size / 2,
1627  but_size,
1628  but_size,
1629  nullptr,
1630  0,
1631  0,
1632  0,
1633  0,
1634  "");
1635  UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
1637 
1638  UI_GetThemeColor4fv(TH_TEXT, color);
1639  /* Custom draw function for this button. */
1640  UI_draw_icon_tri(rct->xmin + 0.65f * U.widget_unit, centy, 'h', color);
1641  }
1642 
1643  /* Disable lines. */
1644  if (node->flag & NODE_MUTED) {
1645  node_draw_mute_line(v2d, snode, node);
1646  }
1647 
1648  char showname[128];
1649  nodeLabel(ntree, node, showname, sizeof(showname));
1650 
1651  uiBut *but = uiDefBut(node->block,
1653  0,
1654  showname,
1656  round_fl_to_int(centy - NODE_DY * 0.5f),
1657  (short)(BLI_rctf_size_x(rct) - ((18.0f + 12.0f) * U.dpi_fac)),
1658  (short)NODE_DY,
1659  nullptr,
1660  0,
1661  0,
1662  0,
1663  0,
1664  "");
1665  if (node->flag & NODE_MUTED) {
1667  }
1668 
1669  /* Scale widget thing. */
1672 
1673  immUniformThemeColorShade(color_id, -10);
1674  float dx = 10.0f;
1675 
1677  immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
1678  immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
1679 
1680  immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy - 4.0f);
1681  immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy + 4.0f);
1682  immEnd();
1683 
1684  immUniformThemeColorShade(color_id, 30);
1685  dx -= snode->runtime->aspect;
1686 
1688  immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
1689  immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
1690 
1691  immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy - 4.0f);
1692  immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy + 4.0f);
1693  immEnd();
1694 
1695  immUnbindProgram();
1696 
1697  node_draw_sockets(v2d, C, ntree, node, true, false);
1698 
1699  UI_block_end(C, node->block);
1700  UI_block_draw(C, node->block);
1701  node->block = nullptr;
1702 }
1703 
1704 int node_get_resize_cursor(int directions)
1705 {
1706  if (directions == 0) {
1707  return WM_CURSOR_DEFAULT;
1708  }
1709  if ((directions & ~(NODE_RESIZE_TOP | NODE_RESIZE_BOTTOM)) == 0) {
1710  return WM_CURSOR_Y_MOVE;
1711  }
1712  if ((directions & ~(NODE_RESIZE_RIGHT | NODE_RESIZE_LEFT)) == 0) {
1713  return WM_CURSOR_X_MOVE;
1714  }
1715  return WM_CURSOR_EDIT;
1716 }
1717 
1718 void node_set_cursor(wmWindow *win, SpaceNode *snode, float cursor[2])
1719 {
1720  bNodeTree *ntree = snode->edittree;
1721  bNode *node;
1722  bNodeSocket *sock;
1723  int wmcursor = WM_CURSOR_DEFAULT;
1724 
1725  if (ntree) {
1726  if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN | SOCK_OUT)) {
1727  /* Pass. */
1728  }
1729  else {
1730  /* Check nodes front to back. */
1731  for (node = (bNode *)ntree->nodes.last; node; node = node->prev) {
1732  if (BLI_rctf_isect_pt(&node->totr, cursor[0], cursor[1])) {
1733  break; /* First hit on node stops. */
1734  }
1735  }
1736  if (node) {
1737  int dir = node->typeinfo->resize_area_func(node, cursor[0], cursor[1]);
1738  wmcursor = node_get_resize_cursor(dir);
1739  }
1740  }
1741  }
1742 
1743  WM_cursor_set(win, wmcursor);
1744 }
1745 
1747  ARegion *region,
1748  SpaceNode *snode,
1749  bNodeTree *ntree,
1750  bNode *node,
1751  bNodeInstanceKey key)
1752 {
1753  const View2D *v2d = &region->v2d;
1754  if (node->flag & NODE_HIDDEN) {
1755  node_draw_hidden(C, v2d, snode, ntree, node, key);
1756  }
1757  else {
1758  node_draw_basis(C, v2d, snode, ntree, node, key);
1759  }
1760 }
1761 
1762 static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
1763 {
1764  if (node->typeinfo->draw_nodetype_prepare) {
1765  node->typeinfo->draw_nodetype_prepare(C, ntree, node);
1766  }
1767 }
1768 
1770 {
1771  Map<bNodeSocket *, int> counts;
1772  LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
1773  if (link->tosock->flag & SOCK_MULTI_INPUT) {
1774  int &count = counts.lookup_or_add(link->tosock, 0);
1775  count++;
1776  }
1777  }
1778  /* Count temporary links going into this socket. */
1779  LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) {
1780  LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
1781  bNodeLink *link = (bNodeLink *)linkdata->data;
1782  if (link->tosock && (link->tosock->flag & SOCK_MULTI_INPUT)) {
1783  int &count = counts.lookup_or_add(link->tosock, 0);
1784  count++;
1785  }
1786  }
1787  }
1789  LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
1790  if (socket->flag & SOCK_MULTI_INPUT) {
1791  socket->total_inputs = counts.lookup_default(socket, 0);
1792  }
1793  }
1794  }
1795 }
1796 
1798 {
1799  /* Make sure socket "used" tags are correct, for displaying value buttons. */
1800  SpaceNode *snode = CTX_wm_space_node(C);
1802 
1804 
1805  /* Update nodes front to back, so children sizes get updated before parents. */
1807  node_update(C, ntree, node);
1808  }
1809 }
1810 
1811 static void node_draw(const bContext *C,
1812  ARegion *region,
1813  SpaceNode *snode,
1814  bNodeTree *ntree,
1815  bNode *node,
1816  bNodeInstanceKey key)
1817 {
1818  if (node->typeinfo->draw_nodetype) {
1819  node->typeinfo->draw_nodetype(C, region, snode, ntree, node, key);
1820  }
1821 }
1822 
1823 #define USE_DRAW_TOT_UPDATE
1824 
1826  ARegion *region,
1827  SpaceNode *snode,
1828  bNodeTree *ntree,
1829  bNodeInstanceKey parent_key)
1830 {
1831  if (ntree == nullptr) {
1832  return; /* Groups. */
1833  }
1834 
1835 #ifdef USE_DRAW_TOT_UPDATE
1836  if (ntree->nodes.first) {
1837  BLI_rctf_init_minmax(&region->v2d.tot);
1838  }
1839 #endif
1840 
1841  /* Draw background nodes, last nodes in front. */
1843 #ifdef USE_DRAW_TOT_UPDATE
1844  /* Unrelated to background nodes, update the v2d->tot,
1845  * can be anywhere before we draw the scroll bars. */
1846  BLI_rctf_union(&region->v2d.tot, &node->totr);
1847 #endif
1848 
1849  if (!(node->flag & NODE_BACKGROUND)) {
1850  continue;
1851  }
1852 
1853  bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
1854  node_draw(C, region, snode, ntree, node, key);
1855  }
1856 
1857  /* Node lines. */
1859  nodelink_batch_start(snode);
1860 
1861  LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
1862  if (!nodeLinkIsHidden(link)) {
1863  node_draw_link(&region->v2d, snode, link);
1864  }
1865  }
1866  nodelink_batch_end(snode);
1868 
1869  /* Draw foreground nodes, last nodes in front. */
1871  if (node->flag & NODE_BACKGROUND) {
1872  continue;
1873  }
1874 
1875  bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
1876  node_draw(C, region, snode, ntree, node, key);
1877  }
1878 }
1879 
1880 /* Draw tree path info in lower left corner. */
1881 static void draw_tree_path(SpaceNode *snode)
1882 {
1883  char info[256];
1884 
1885  ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info));
1886 
1888  BLF_draw_default(1.5f * UI_UNIT_X, 1.5f * UI_UNIT_Y, 0.0f, info, sizeof(info));
1889 }
1890 
1891 static void snode_setup_v2d(SpaceNode *snode, ARegion *region, const float center[2])
1892 {
1893  View2D *v2d = &region->v2d;
1894 
1895  /* Shift view to node tree center. */
1896  UI_view2d_center_set(v2d, center[0], center[1]);
1897  UI_view2d_view_ortho(v2d);
1898 
1899  /* Aspect + font, set each time. */
1900  snode->runtime->aspect = BLI_rctf_size_x(&v2d->cur) / (float)region->winx;
1901  // XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
1902 }
1903 
1904 static void draw_nodetree(const bContext *C,
1905  ARegion *region,
1906  bNodeTree *ntree,
1907  bNodeInstanceKey parent_key)
1908 {
1909  SpaceNode *snode = CTX_wm_space_node(C);
1910 
1912 
1914  node_draw_nodetree(C, region, snode, ntree, parent_key);
1915 }
1916 
1917 /* Shade the parent node group and add a `uiBlock` to clip mouse events. */
1918 static void draw_group_overlay(const bContext *C, ARegion *region)
1919 {
1920  const View2D *v2d = &region->v2d;
1921  const rctf rect = v2d->cur;
1922  float color[4];
1923 
1924  /* Shade node groups to separate them visually. */
1926 
1929  UI_draw_roundbox_4fv(&rect, true, 0, color);
1931 
1932  /* Set the block bounds to clip mouse events from underlying nodes. */
1933  uiBlock *block = UI_block_begin(C, region, "node tree bounds block", UI_EMBOSS);
1934  UI_block_bounds_set_explicit(block, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
1936  UI_block_end(C, block);
1937 }
1938 
1939 void node_draw_space(const bContext *C, ARegion *region)
1940 {
1941  wmWindow *win = CTX_wm_window(C);
1942  SpaceNode *snode = CTX_wm_space_node(C);
1943  View2D *v2d = &region->v2d;
1944 
1945  /* Setup offscreen buffers. */
1946  GPUViewport *viewport = WM_draw_region_get_viewport(region);
1947 
1948  GPUFrameBuffer *framebuffer_overlay = GPU_viewport_framebuffer_overlay_get(viewport);
1949  GPU_framebuffer_bind_no_srgb(framebuffer_overlay);
1950 
1951  UI_view2d_view_ortho(v2d);
1954  GPU_scissor_test(true);
1955 
1956  /* XXX `snode->runtime->cursor` set in coordinate-space for placing new nodes,
1957  * used for drawing noodles too. */
1958  UI_view2d_region_to_view(&region->v2d,
1959  win->eventstate->x - region->winrct.xmin,
1960  win->eventstate->y - region->winrct.ymin,
1961  &snode->runtime->cursor[0],
1962  &snode->runtime->cursor[1]);
1963  snode->runtime->cursor[0] /= UI_DPI_FAC;
1964  snode->runtime->cursor[1] /= UI_DPI_FAC;
1965 
1967 
1969 
1970  /* Only set once. */
1972 
1973  /* Nodes. */
1975 
1976  /* Draw parent node trees. */
1977  if (snode->treepath.last) {
1978  static const int max_depth = 2;
1979 
1980  bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last;
1981 
1982  /* Update tree path name (drawn in the bottom left). */
1983  ID *name_id = (path->nodetree && path->nodetree != snode->nodetree) ? &path->nodetree->id :
1984  snode->id;
1985 
1986  if (name_id && UNLIKELY(!STREQ(path->display_name, name_id->name + 2))) {
1987  BLI_strncpy(path->display_name, name_id->name + 2, sizeof(path->display_name));
1988  }
1989 
1990  /* Current View2D center, will be set temporarily for parent node trees. */
1991  float center[2];
1992  UI_view2d_center_get(v2d, &center[0], &center[1]);
1993 
1994  /* Store new view center in path and current edit tree. */
1995  copy_v2_v2(path->view_center, center);
1996  if (snode->edittree) {
1998  }
1999 
2000  int depth = 0;
2001  while (path->prev && depth < max_depth) {
2002  path = path->prev;
2003  depth++;
2004  }
2005 
2006  /* Parent node trees in the background. */
2007  for (int curdepth = depth; curdepth > 0; path = path->next, curdepth--) {
2008  bNodeTree *ntree = path->nodetree;
2009  if (ntree) {
2010  snode_setup_v2d(snode, region, path->view_center);
2011 
2012  draw_nodetree(C, region, ntree, path->parent_key);
2013 
2014  draw_group_overlay(C, region);
2015  }
2016  }
2017 
2018  /* Top-level edit tree. */
2019  bNodeTree *ntree = path->nodetree;
2020  if (ntree) {
2021  snode_setup_v2d(snode, region, center);
2022 
2023  /* Grid, uses theme color based on node path depth. */
2025  (depth > 0 ? TH_NODE_GROUP : TH_GRID),
2028  grid_levels);
2029 
2030  /* Backdrop. */
2031  draw_nodespace_back_pix(C, region, snode, path->parent_key);
2032 
2033  {
2034  float original_proj[4][4];
2035  GPU_matrix_projection_get(original_proj);
2036 
2037  GPU_matrix_push();
2039 
2040  wmOrtho2_pixelspace(region->winx, region->winy);
2041 
2043 
2044  GPU_matrix_pop();
2045  GPU_matrix_projection_set(original_proj);
2046  }
2047 
2048  draw_nodetree(C, region, ntree, path->parent_key);
2049  }
2050 
2051  /* Temporary links. */
2053  GPU_line_smooth(true);
2054  LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) {
2055  LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
2056  node_draw_link(v2d, snode, (bNodeLink *)linkdata->data);
2057  }
2058  }
2059  GPU_line_smooth(false);
2061 
2062  if (snode->flag & SNODE_SHOW_GPENCIL) {
2063  /* Draw grease-pencil annotations. */
2065  }
2066  }
2067  else {
2068  /* Default grid. */
2070 
2071  /* Backdrop. */
2073  }
2074 
2076 
2077  /* Reset view matrix. */
2079 
2080  if (snode->treepath.last) {
2081  if (snode->flag & SNODE_SHOW_GPENCIL) {
2082  /* Draw grease-pencil (screen strokes, and also paint-buffer). */
2083  ED_annotation_draw_view2d(C, false);
2084  }
2085  }
2086 
2087  /* Tree path info. */
2088  draw_tree_path(snode);
2089 
2090  /* Scrollers. */
2091  UI_view2d_scrollers_draw(v2d, nullptr);
2092 }
typedef float(TangentPoint)[2]
void immDrawPixelsTex(IMMDrawPixelsTexState *state, float x, float y, int img_w, int img_h, eGPUTextureFormat gpu_format, bool use_filter, void *rect, float xzoom, float yzoom, const float color[4])
Definition: glutil.c:298
IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin)
Definition: glutil.c:66
PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
Definition: context.c:445
struct SpaceNode * CTX_wm_space_node(const bContext *C)
Definition: context.c:854
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
void id_us_ensure_real(struct ID *id)
Definition: lib_id.c:238
void nodeFromView(const struct bNode *node, float x, float y, float *rx, float *ry)
#define NODE_CLASS_OUTPUT
Definition: BKE_node.h:335
struct bNodeTree * ntreeFromID(struct ID *id)
Definition: node.cc:3147
void ntreeTagUsedSockets(struct bNodeTree *ntree)
Definition: node.cc:4149
bool nodeLinkIsHidden(const struct bNodeLink *link)
#define NODE_CLASS_INTERFACE
Definition: BKE_node.h:357
bool nodeTypeUndefined(struct bNode *node)
Definition: node.cc:1316
#define NODE_CLASS_MATTE
Definition: BKE_node.h:342
bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup)
#define NODE_RESIZE_TOP
Definition: BKE_node.h:364
#define NODE_CUSTOM
Definition: BKE_node.h:868
#define NODE_CLASS_PATTERN
Definition: BKE_node.h:345
#define NODE_CLASS_CONVERTOR
Definition: BKE_node.h:341
int nodeSocketIsHidden(const struct bNodeSocket *sock)
#define NODE_CLASS_GEOMETRY
Definition: BKE_node.h:359
void nodeLabel(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen)
Definition: node.cc:4391
#define NODE_CLASS_DISTORT
Definition: BKE_node.h:343
void ntreeTexCheckCyclics(struct bNodeTree *ntree)
#define FOREACH_NODETREE_END
Definition: BKE_node.h:945
#define NODE_CLASS_OP_VECTOR
Definition: BKE_node.h:337
#define NODE_CLASS_LAYOUT
Definition: BKE_node.h:361
#define NODE_RESIZE_BOTTOM
Definition: BKE_node.h:365
#define FOREACH_NODETREE_BEGIN(bmain, _nodetree, _id)
Definition: BKE_node.h:935
#define NODE_CLASS_OP_COLOR
Definition: BKE_node.h:336
#define NODE_CLASS_INPUT
Definition: BKE_node.h:334
#define NODE_CLASS_OP_FILTER
Definition: BKE_node.h:338
const bNodeInstanceKey NODE_INSTANCE_KEY_NONE
Definition: node.cc:3909
#define NODE_CLASS_GROUP
Definition: BKE_node.h:339
#define NODE_CLASS_ATTRIBUTE
Definition: BKE_node.h:360
#define NODE_CLASS_TEXTURE
Definition: BKE_node.h:346
void nodeToView(const struct bNode *node, float x, float y, float *rx, float *ry)
#define NODE_CLASS_SHADER
Definition: BKE_node.h:358
void * BKE_node_instance_hash_lookup(bNodeInstanceHash *hash, bNodeInstanceKey key)
Definition: node.cc:3977
#define NODE_RESIZE_RIGHT
Definition: BKE_node.h:366
#define NODE_RESIZE_LEFT
Definition: BKE_node.h:367
const char * nodeSocketLabel(const struct bNodeSocket *sock)
bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, const struct bNodeTree *ntree, const struct bNode *node)
#define NODE_CLASS_SCRIPT
Definition: BKE_node.h:356
const NodeUIStorage * BKE_node_tree_ui_storage_get_from_context(const bContext *C, const bNodeTree &ntree, const bNode &node)
NodeWarningType
General operations, lookup, etc. for blender objects.
void BLF_draw_default(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL()
Definition: blf_default.c:71
int BLF_default(void)
Definition: blf_default.c:55
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
Definition: BLI_listbase.h:184
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:395
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int round_fl_to_int(float a)
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float min_ff(float a, float b)
#define M_PI
Definition: BLI_math_base.h:38
MINLINE void rgba_float_args_set(float col[4], const float r, const float g, const float b, const float a)
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v4_fl(float r[4], float f)
bool BLI_rctf_is_empty(const struct rctf *rect)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:157
bool BLI_rctf_isect_pt(const struct rctf *rect, const float x, const float y)
BLI_INLINE float BLI_rctf_cent_y(const struct rctf *rct)
Definition: BLI_rect.h:148
bool BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest)
void BLI_rcti_resize(struct rcti *rect, int x, int y)
Definition: rct.c:638
BLI_INLINE int BLI_rcti_cent_y(const struct rcti *rct)
Definition: BLI_rect.h:140
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:161
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition: BLI_rect.h:165
BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct)
Definition: BLI_rect.h:136
void BLI_rctf_union(struct rctf *rct1, const struct rctf *rct2)
void BLI_rctf_init_minmax(struct rctf *rect)
Definition: rct.c:522
char * BLI_strdupn(const char *str, const size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:54
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned int uint
Definition: BLI_sys_types.h:83
#define SWAP(type, a, b)
#define UNUSED(x)
#define MAX2(a, b)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
#define IFACE_(msgid)
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_NT
Definition: DNA_ID_enums.h:80
@ ID_LA
Definition: DNA_ID_enums.h:67
@ ID_WO
Definition: DNA_ID_enums.h:71
@ ID_MA
Definition: DNA_ID_enums.h:63
#define NODE_OPTIONS
#define NODE_ACTIVE_PREVIEW
#define NODE_CUSTOM_COLOR
#define NTREE_TEXTURE
#define NODE_BACKGROUND
#define NODE_DO_OUTPUT
#define NTREE_GEOMETRY
#define NODE_MUTED
#define NTREE_COMPOSIT
#define NODE_HIDDEN
@ SOCK_OUT
@ SOCK_IN
#define NODE_PREVIEW
@ SOCK_MULTI_INPUT
@ SOCK_DISPLAY_SHAPE_CIRCLE_DOT
@ SOCK_DISPLAY_SHAPE_CIRCLE
@ SOCK_DISPLAY_SHAPE_SQUARE_DOT
@ SOCK_DISPLAY_SHAPE_SQUARE
@ SOCK_DISPLAY_SHAPE_DIAMOND
@ SOCK_DISPLAY_SHAPE_DIAMOND_DOT
@ SOCK_CUSTOM
#define NODE_SELECT
#define NTREE_SHADER
#define NODE_ACTIVE
@ SNODE_SHOW_GPENCIL
@ SPACE_NODE
void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length)
Definition: space_node.c:204
#define NODE_GRID_STEPS
Definition: ED_node.h:51
#define REGION_DRAW_POST_VIEW
Definition: ED_space_api.h:66
void ED_region_draw_cb_draw(const struct bContext *, struct ARegion *, int)
#define REGION_DRAW_PRE_VIEW
Definition: ED_space_api.h:68
NSNotificationCenter * center
struct GPUFrameBuffer GPUFrameBuffer
void GPU_framebuffer_bind_no_srgb(GPUFrameBuffer *fb)
void immUniform4f(const char *name, float x, float y, float z, float w)
void immAttr4fv(uint attr_id, const float data[4])
void immUniform2f(const char *name, float x, float y)
void immUniformThemeColorShadeAlpha(int color_id, int color_offset, int alpha_offset)
void immUnbindProgram(void)
void immVertex2f(uint attr_id, float x, float y)
void immAttr1f(uint attr_id, float x)
void immUniformThemeColorShade(int color_id, int offset)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immUniform1i(const char *name, int x)
void immBeginAtMost(GPUPrimType, uint max_vertex_len)
void immAttr1u(uint attr_id, uint x)
void immUniform1f(const char *name, float x)
GPUVertFormat * immVertexFormat(void)
void immBegin(GPUPrimType, uint vertex_len)
void immEnd(void)
void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2)
void immRectf(uint pos, float x1, float y1, float x2, float y2)
_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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_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
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
void GPU_matrix_pop(void)
Definition: gpu_matrix.cc:142
void GPU_matrix_push(void)
Definition: gpu_matrix.cc:135
#define GPU_matrix_projection_get(x)
Definition: GPU_matrix.h:227
#define GPU_matrix_projection_set(x)
Definition: GPU_matrix.h:225
void GPU_matrix_identity_set(void)
Definition: gpu_matrix.cc:184
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:36
@ GPU_PRIM_POINTS
Definition: GPU_primitive.h:35
@ GPU_SHADER_2D_CHECKER
Definition: GPU_shader.h:191
@ GPU_SHADER_2D_UNIFORM_COLOR
Definition: GPU_shader.h:171
@ GPU_SHADER_KEYFRAME_DIAMOND
Definition: GPU_shader.h:162
@ GPU_SHADER_2D_IMAGE_COLOR
Definition: GPU_shader.h:187
void GPU_program_point_size(bool enable)
Definition: gpu_state.cc:191
eGPUBlend
Definition: GPU_state.h:54
@ GPU_BLEND_NONE
Definition: GPU_state.h:55
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:57
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:55
void GPU_scissor_test(bool enable)
Definition: gpu_state.cc:199
void GPU_line_width(float width)
Definition: gpu_state.cc:173
void GPU_line_smooth(bool enable)
Definition: gpu_state.cc:85
eGPUBlend GPU_blend_get(void)
Definition: gpu_state.cc:237
@ GPU_DEPTH_NONE
Definition: GPU_state.h:78
void GPU_depth_test(eGPUDepthTest test)
Definition: gpu_state.cc:75
@ GPU_RGBA8
Definition: GPU_texture.h:88
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
@ GPU_COMP_U32
struct GPUFrameBuffer * GPU_viewport_framebuffer_overlay_get(GPUViewport *viewport)
Read Guarded memory(de)allocation.
NODE_GROUP
StructRNA RNA_Node
StructRNA RNA_NodeSocket
#define C
Definition: RandGen.cpp:39
#define UI_ALPHA_CHECKER_LIGHT
#define UI_UNIT_Y
void uiLayoutSetActive(uiLayout *layout, bool active)
void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *argN)
Definition: interface.c:6323
@ UI_EMBOSS_NONE
Definition: UI_interface.h:108
@ UI_EMBOSS
Definition: UI_interface.h:107
const struct uiStyle * UI_style_get_dpi(void)
uiBut * uiDefIconBut(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.c:5223
@ UI_BUT_INACTIVE
Definition: UI_interface.h:206
void UI_draw_icon_tri(float x, float y, char dir, const float[4])
@ UI_CNR_BOTTOM_LEFT
@ UI_CNR_BOTTOM_RIGHT
@ UI_CNR_ALL
@ UI_CNR_TOP_LEFT
@ UI_CNR_TOP_RIGHT
@ UI_CNR_NONE
void UI_draw_roundbox_4fv(const struct rctf *rect, bool filled, float rad, const float col[4])
@ UI_LAYOUT_PANEL
uiBut * uiDefBut(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.c:4687
#define UI_ALPHA_CHECKER_DARK
void UI_draw_roundbox_3fv_alpha(const struct rctf *rect, bool filled, float rad, const float col[3], float alpha)
void uiLayoutSetAlignment(uiLayout *layout, char alignment)
void UI_draw_roundbox_corner_set(int type)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
@ UI_LAYOUT_ALIGN_RIGHT
void UI_block_end(const struct bContext *C, uiBlock *block)
void UI_block_emboss_set(uiBlock *block, eUIEmbossType emboss)
Definition: interface.c:3542
void UI_block_draw(const struct bContext *C, struct uiBlock *block)
#define UI_DPI_FAC
Definition: UI_interface.h:309
@ UI_BLOCK_CLIP_EVENTS
Definition: UI_interface.h:155
uiLayout * UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, const struct uiStyle *style)
void UI_but_func_set(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2)
Definition: interface.c:6294
void UI_draw_roundbox_aa(const struct rctf *rect, bool filled, float rad, const float color[4])
void uiLayoutSetContextPointer(uiLayout *layout, const char *name, struct PointerRNA *ptr)
uiBlock * UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, eUIEmbossType emboss)
void UI_draw_roundbox_4fv_ex(const struct rctf *rect, const float inner1[4], const float inner2[4], float shade_dir, const float outline[4], float outline_width, float rad)
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
#define UI_UNIT_X
@ UI_LAYOUT_VERTICAL
void UI_block_flag_enable(uiBlock *block, int flag)
Definition: interface.c:6067
@ UI_BTYPE_BUT
Definition: UI_interface.h:334
@ UI_BTYPE_BUT_TOGGLE
Definition: UI_interface.h:349
@ UI_BTYPE_LABEL
Definition: UI_interface.h:358
void UI_but_flag_enable(uiBut *but, int flag)
Definition: interface.c:6077
void UI_block_bounds_set_explicit(uiBlock *block, int minx, int miny, int maxx, int maxy)
Definition: interface.c:632
void UI_block_align_end(uiBlock *block)
Definition: interface.c:3834
void UI_GetThemeColor3fv(int colorid, float col[3])
Definition: resources.c:1191
int UI_GetThemeValueType(int colorid, int spacetype)
Definition: resources.c:1184
@ TH_NODE_INPUT
Definition: UI_resources.h:177
@ TH_NODE
Definition: UI_resources.h:176
@ TH_NODE_FILTER
Definition: UI_resources.h:180
@ TH_NODE_GROUP
Definition: UI_resources.h:189
@ TH_GRID
Definition: UI_resources.h:84
@ TH_NODE_SCRIPT
Definition: UI_resources.h:184
@ TH_BACK
Definition: UI_resources.h:55
@ TH_NODE_GEOMETRY
Definition: UI_resources.h:193
@ TH_NODE_OUTPUT
Definition: UI_resources.h:178
@ TH_NODE_COLOR
Definition: UI_resources.h:179
@ TH_NODE_PATTERN
Definition: UI_resources.h:183
@ TH_NODE_ATTRIBUTE
Definition: UI_resources.h:194
@ TH_NODE_DISTORT
Definition: UI_resources.h:192
@ TH_REDALERT
Definition: UI_resources.h:50
@ TH_NODE_MATTE
Definition: UI_resources.h:191
@ TH_NODE_GRID_LEVELS
Definition: UI_resources.h:242
@ TH_NODE_TEXTURE
Definition: UI_resources.h:182
@ TH_NODE_VECTOR
Definition: UI_resources.h:181
@ TH_SELECT
Definition: UI_resources.h:88
@ TH_NODE_LAYOUT
Definition: UI_resources.h:185
@ TH_TEXT
Definition: UI_resources.h:58
@ TH_NODE_SHADER
Definition: UI_resources.h:186
@ TH_NODE_INTERFACE
Definition: UI_resources.h:187
@ TH_ACTIVE
Definition: UI_resources.h:89
@ TH_NODE_CONVERTOR
Definition: UI_resources.h:188
@ TH_TEXT_HI
Definition: UI_resources.h:59
void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4])
Definition: resources.c:1326
void UI_ThemeClearColor(int colorid)
Definition: resources.c:1478
void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4])
Definition: resources.c:1286
void UI_GetThemeColor4fv(int colorid, float col[4])
Definition: resources.c:1199
void UI_FontThemeColor(int fontid, int colorid)
Definition: resources.c:1156
void UI_view2d_center_set(struct View2D *v2d, float x, float y)
Definition: view2d.c:1950
void UI_view2d_scale_get(const struct View2D *v2d, float *r_x, float *r_y)
void UI_view2d_view_restore(const struct bContext *C)
void UI_view2d_multi_grid_draw(const struct View2D *v2d, int colorid, float step, int level_size, int totlevels)
void UI_view2d_view_ortho(const struct View2D *v2d)
void UI_view2d_region_to_view(const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
void UI_view2d_scrollers_draw(struct View2D *v2d, const struct rcti *mask_custom)
void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y)
Definition: view2d.c:1940
@ WM_GIZMOMAP_DRAWSTEP_2D
#define NC_WORLD
Definition: WM_types.h:288
#define ND_SHADING
Definition: WM_types.h:377
#define ND_WORLD
Definition: WM_types.h:353
@ WM_OP_INVOKE_DEFAULT
Definition: WM_types.h:197
#define NC_SCENE
Definition: WM_types.h:279
#define ND_NODES
Definition: WM_types.h:336
#define ND_MODIFIER
Definition: WM_types.h:363
#define NC_MATERIAL
Definition: WM_types.h:281
#define NC_LAMP
Definition: WM_types.h:283
#define NC_TEXTURE
Definition: WM_types.h:282
#define ND_LIGHTING
Definition: WM_types.h:383
#define NC_OBJECT
Definition: WM_types.h:280
void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
unsigned int U
Definition: btGjkEpa3.h:78
Value lookup_default(const Key &key, const Value &default_value) const
Definition: BLI_map.hh:524
Value & lookup_or_add(const Key &key, const Value &value)
Definition: BLI_map.hh:544
constexpr const T & last() const
Definition: BLI_span.hh:327
constexpr Span drop_back(int64_t n) const
Definition: BLI_span.hh:184
bool is_empty() const
Definition: BLI_vector.hh:674
#define SELECT
OperationNode * node
static CCL_NAMESPACE_BEGIN const double alpha
void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
Definition: drawnode.c:4068
void node_draw_link_bezier(const View2D *v2d, const SpaceNode *snode, const bNodeLink *link, int th_col1, int th_col2, int th_col3)
Definition: drawnode.c:4017
void nodelink_batch_start(SpaceNode *UNUSED(snode))
Definition: drawnode.c:3971
void nodelink_batch_end(SpaceNode *snode)
Definition: drawnode.c:3976
void draw_nodespace_back_pix(const bContext *C, ARegion *region, SpaceNode *snode, bNodeInstanceKey parent_key)
Definition: drawnode.c:3550
bNodeTree * ntree
uint pos
int count
#define GS(x)
Definition: iris.c:241
#define sinf(x)
#define cosf(x)
format
Definition: logImageCore.h:47
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static ulong state[N]
static unsigned a[3]
Definition: RandGen.cpp:92
#define NODE_HEADER_ICON_SIZE
Definition: node_draw.cc:1254
#define MARKER_SHAPE_SQUARE
Definition: node_draw.cc:716
static NodeWarningType node_error_highest_priority(Span< NodeWarning > warnings)
Definition: node_draw.cc:1218
static void count_mutli_input_socket_links(bNodeTree *ntree, SpaceNode *snode)
Definition: node_draw.cc:1769
#define MARKER_SHAPE_DIAMOND
Definition: node_draw.cc:715
void node_from_view(const bNode *node, float x, float y, float *rx, float *ry)
Definition: node_draw.cc:340
static void draw_group_overlay(const bContext *C, ARegion *region)
Definition: node_draw.cc:1918
static int node_error_type_to_icon(const NodeWarningType type)
Definition: node_draw.cc:1188
float ED_node_grid_size(void)
Definition: node_draw.cc:96
static void snode_setup_v2d(SpaceNode *snode, ARegion *region, const float center[2])
Definition: node_draw.cc:1891
#define MARKER_SHAPE_INNER_DOT
Definition: node_draw.cc:718
static void draw_nodetree(const bContext *C, ARegion *region, bNodeTree *ntree, bNodeInstanceKey parent_key)
Definition: node_draw.cc:1904
static void node_draw_preview_background(rctf *rect)
Definition: node_draw.cc:911
void node_set_cursor(wmWindow *win, SpaceNode *snode, float cursor[2])
Definition: node_draw.cc:1718
static void node_add_error_message_button(const bContext *C, bNodeTree &ntree, bNode &node, const rctf &rect, float &icon_offset)
Definition: node_draw.cc:1256
static void node_socket_draw(const bNodeSocket *sock, const float color[4], const float color_outline[4], float size, int locx, int locy, uint pos_id, uint col_id, uint shape_id, uint size_id, uint outline_col_id)
Definition: node_draw.cc:720
static void node_draw_preview(bNodePreview *preview, rctf *prv)
Definition: node_draw.cc:929
void node_update_nodetree(const bContext *C, bNodeTree *ntree)
Definition: node_draw.cc:1797
void node_draw_default(const bContext *C, ARegion *region, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
Definition: node_draw.cc:1746
static void node_draw_basis(const bContext *C, const View2D *v2d, const SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
Definition: node_draw.cc:1292
int node_get_resize_cursor(int directions)
Definition: node_draw.cc:1704
void node_draw_nodetree(const bContext *C, ARegion *region, SpaceNode *snode, bNodeTree *ntree, bNodeInstanceKey parent_key)
Definition: node_draw.cc:1825
int node_get_colorid(bNode *node)
Definition: node_draw.cc:661
void node_socket_color_get(bContext *C, bNodeTree *ntree, PointerRNA *node_ptr, bNodeSocket *sock, float r_color[4])
Definition: node_draw.cc:810
static char * node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char *UNUSED(tip))
Definition: node_draw.cc:1232
static void node_socket_draw_nested(const bContext *C, bNodeTree *ntree, PointerRNA *node_ptr, bNodeSocket *sock, uint pos_id, uint col_id, uint shape_id, uint size_id, uint outline_col_id, float size, bool selected)
Definition: node_draw.cc:825
void node_to_view(const bNode *node, float x, float y, float *rx, float *ry)
Definition: node_draw.cc:323
void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree, bNode *node)
Definition: node_draw.cc:164
void ED_node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], float scale)
Definition: node_draw.cc:861
static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_argv)
Definition: node_draw.cc:981
void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select)
static void node_draw(const bContext *C, ARegion *region, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
Definition: node_draw.cc:1811
static bool compare_nodes(const bNode *a, const bNode *b)
Definition: node_draw.cc:193
static uint8_t node_error_type_priority(const NodeWarningType type)
Definition: node_draw.cc:1203
static void node_draw_mute_line(const View2D *v2d, const SpaceNode *snode, const bNode *node)
Definition: node_draw.cc:703
static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
Definition: node_draw.cc:350
static const float virtual_node_socket_outline_color[4]
Definition: node_draw.cc:786
int node_tweak_area_default(bNode *node, int x, int y)
Definition: node_draw.cc:656
void node_draw_sockets(const View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *node, bool draw_outputs, bool select_all)
Definition: node_draw.cc:999
static void node_draw_hidden(const bContext *C, const View2D *v2d, const SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
Definition: node_draw.cc:1552
static void node_uiblocks_init(const bContext *C, bNodeTree *ntree)
Definition: node_draw.cc:308
static void node_socket_draw_multi_input(const float color[4], const float color_outline[4], const float width, const float height, const int locx, const int locy)
Definition: node_draw.cc:765
void ED_node_tag_update_id(ID *id)
Definition: node_draw.cc:124
static void node_socket_outline_color_get(const bool selected, const int socket_type, float r_outline_color[4])
Definition: node_draw.cc:788
void node_draw_shadow(const SpaceNode *snode, const bNode *node, float radius, float alpha)
Definition: node_draw.cc:992
void node_to_updated_rect(const bNode *node, rctf *r_rect)
Definition: node_draw.cc:330
void node_draw_space(const bContext *C, ARegion *region)
Definition: node_draw.cc:1939
static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
Definition: node_draw.cc:1762
static void node_update_hidden(bNode *node)
Definition: node_draw.cc:578
#define MARKER_SHAPE_CIRCLE
Definition: node_draw.cc:717
int node_select_area_default(bNode *node, int x, int y)
Definition: node_draw.cc:651
static bNodeTree * node_tree_from_ID(ID *id)
Definition: node_draw.cc:112
void ED_node_sort(bNodeTree *ntree)
Definition: node_draw.cc:253
void ED_node_tree_update(const bContext *C)
Definition: node_draw.cc:101
void node_update_default(const bContext *C, bNodeTree *ntree, bNode *node)
Definition: node_draw.cc:641
static void draw_tree_path(SpaceNode *snode)
Definition: node_draw.cc:1881
void snode_set_context(const bContext *C)
Definition: node_edit.c:603
float node_socket_calculate_height(const bNodeSocket *socket)
Definition: node_edit.c:102
int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, const float cursor[2], int in_out)
Definition: node_edit.c:1149
#define NODE_MULTI_INPUT_LINK_GAP
Definition: node_intern.h:333
#define BASIS_RAD
Definition: node_intern.h:325
#define NODE_SOCKSIZE
Definition: node_intern.h:332
#define NODE_WIDTH(node)
Definition: node_intern.h:329
#define NODE_DYS
Definition: node_intern.h:326
#define NODE_SOCKDY
Definition: node_intern.h:328
#define NODE_MARGIN_X
Definition: node_intern.h:331
#define HIDDEN_RAD
Definition: node_intern.h:324
bool node_connected_to_output(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node)
#define NODE_DY
Definition: node_intern.h:327
void node_select_single(struct bContext *C, struct bNode *node)
Definition: node_select.c:454
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
Definition: rna_access.c:844
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
unsigned char uint8_t
Definition: stdint.h:81
struct wmGizmoMap * gizmo_map
Definition: DNA_ID.h:273
char name[66]
Definition: DNA_ID.h:283
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
blender::Vector< NodeWarning > warnings
struct StructRNA * type
Definition: RNA_types.h:51
void * data
Definition: RNA_types.h:52
struct ListBase linkdrag
Definition: node_intern.h:79
SpaceNode_Runtime * runtime
ListBase treepath
struct bNodeTree * edittree
struct ID * id
struct bNodeTree * nodetree
unsigned char * rect
void(* draw_color)(struct bContext *C, struct PointerRNA *ptr, struct PointerRNA *node_ptr, float *r_color)
Definition: BKE_node.h:151
struct bNodeSocketType * typeinfo
struct bNodeTree * nodetree
struct bNodeTreePath * next
struct bNodeTreePath * prev
bNodeInstanceKey parent_key
float view_center[2]
char display_name[64]
float view_center[2]
ListBase nodes
ListBase links
struct bNode * parent
struct bNode * next
float xmax
Definition: DNA_vec_types.h:85
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
int ymin
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
int y
Definition: WM_types.h:581
int x
Definition: WM_types.h:581
struct wmEvent * eventstate
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: util_avxb.h:167
void WM_cursor_set(wmWindow *win, int curs)
Definition: wm_cursors.c:142
@ WM_CURSOR_DEFAULT
Definition: wm_cursors.h:34
@ WM_CURSOR_Y_MOVE
Definition: wm_cursors.h:55
@ WM_CURSOR_EDIT
Definition: wm_cursors.h:38
@ WM_CURSOR_X_MOVE
Definition: wm_cursors.h:54
GPUViewport * WM_draw_region_get_viewport(ARegion *region)
Definition: wm_draw.c:634
void WM_main_add_notifier(unsigned int type, void *reference)
int WM_operator_name_call(bContext *C, const char *opstring, short context, PointerRNA *properties)
PointerRNA * ptr
Definition: wm_files.c:3157
void WM_gizmomap_draw(wmGizmoMap *gzmap, const bContext *C, const eWM_GizmoFlagMapDrawStep drawstep)
Definition: wm_gizmo_map.c:498
void wmOrtho2_pixelspace(const float x, const float y)
Definition: wm_subwindow.c:125