afef027f7e1a50651c12255b73b0a07e479d67fa
[blender.git] / source / blender / editors / space_node / node_draw.c
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
20 /** \file
21  * \ingroup spnode
22  * \brief higher level node drawing for the node editor.
23  */
24
25 #include "DNA_light_types.h"
26 #include "DNA_node_types.h"
27 #include "DNA_material_types.h"
28 #include "DNA_screen_types.h"
29 #include "DNA_space_types.h"
30 #include "DNA_texture_types.h"
31 #include "DNA_world_types.h"
32 #include "DNA_linestyle_types.h"
33
34 #include "BLI_math.h"
35 #include "BLI_blenlib.h"
36
37 #include "BLT_translation.h"
38
39 #include "BKE_context.h"
40 #include "BKE_library.h"
41 #include "BKE_main.h"
42 #include "BKE_node.h"
43
44 #include "DEG_depsgraph.h"
45
46 #include "BLF_api.h"
47
48 #include "BIF_glutil.h"
49
50 #include "GPU_draw.h"
51 #include "GPU_immediate.h"
52 #include "GPU_immediate_util.h"
53 #include "GPU_matrix.h"
54 #include "GPU_state.h"
55 #include "GPU_framebuffer.h"
56
57 #include "WM_api.h"
58 #include "WM_types.h"
59
60 #include "ED_node.h"
61 #include "ED_gpencil.h"
62 #include "ED_space_api.h"
63
64 #include "UI_resources.h"
65 #include "UI_view2d.h"
66
67 #include "RNA_access.h"
68
69 #include "node_intern.h"  /* own include */
70
71 #ifdef WITH_COMPOSITOR
72 #  include "COM_compositor.h"
73 #endif
74
75 /* XXX interface.h */
76 extern void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
77
78 float ED_node_grid_size(void)
79 {
80         return U.widget_unit;
81 }
82
83 void ED_node_tree_update(const bContext *C)
84 {
85         SpaceNode *snode = CTX_wm_space_node(C);
86         if (snode) {
87                 snode_set_context(C);
88
89                 id_us_ensure_real(&snode->nodetree->id);
90         }
91 }
92
93 /* id is supposed to contain a node tree */
94 static bNodeTree *node_tree_from_ID(ID *id)
95 {
96         if (id) {
97                 short idtype = GS(id->name);
98
99                 switch (idtype) {
100                         case ID_NT:
101                                 return (bNodeTree *)id;
102                         case ID_MA:
103                                 return ((Material *)id)->nodetree;
104                         case ID_LA:
105                                 return ((Light *)id)->nodetree;
106                         case ID_WO:
107                                 return ((World *)id)->nodetree;
108                         case ID_SCE:
109                                 return ((Scene *)id)->nodetree;
110                         case ID_TE:
111                                 return ((Tex *)id)->nodetree;
112                         case ID_LS:
113                                 return ((FreestyleLineStyle *)id)->nodetree;
114                 }
115         }
116
117         return NULL;
118 }
119
120 void ED_node_tag_update_id(ID *id)
121 {
122         bNodeTree *ntree = node_tree_from_ID(id);
123         if (id == NULL || ntree == NULL)
124                 return;
125
126         /* TODO(sergey): With the new dependency graph it
127          * should be just enough to only tag ntree itself,
128          * all the users of this tree will have update
129          * flushed from the tree,
130          */
131         DEG_id_tag_update(&ntree->id, 0);
132
133         if (ntree->type == NTREE_SHADER) {
134                 DEG_id_tag_update(id, 0);
135
136                 if (GS(id->name) == ID_MA)
137                         WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id);
138                 else if (GS(id->name) == ID_LA)
139                         WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id);
140                 else if (GS(id->name) == ID_WO)
141                         WM_main_add_notifier(NC_WORLD | ND_WORLD, id);
142         }
143         else if (ntree->type == NTREE_COMPOSIT) {
144                 WM_main_add_notifier(NC_SCENE | ND_NODES, id);
145         }
146         else if (ntree->type == NTREE_TEXTURE) {
147                 DEG_id_tag_update(id, 0);
148                 WM_main_add_notifier(NC_TEXTURE | ND_NODES, id);
149         }
150         else if (id == &ntree->id) {
151                 /* node groups */
152                 DEG_id_tag_update(id, 0);
153         }
154 }
155
156 void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree, bNode *node)
157 {
158         if (!ntree)
159                 return;
160
161         bool do_tag_update = true;
162         if (node != NULL) {
163                 if (!node_connected_to_output(bmain, ntree, node)) {
164                         do_tag_update = false;
165                 }
166         }
167
168         /* look through all datablocks, to support groups */
169         if (do_tag_update) {
170                 FOREACH_NODETREE_BEGIN(bmain, tntree, id) {
171                         /* check if nodetree uses the group */
172                         if (ntreeHasTree(tntree, ntree))
173                                 ED_node_tag_update_id(id);
174                 } FOREACH_NODETREE_END;
175         }
176
177         if (ntree->type == NTREE_TEXTURE)
178                 ntreeTexCheckCyclics(ntree);
179 }
180
181 static bool compare_nodes(const bNode *a, const bNode *b)
182 {
183         bNode *parent;
184         /* These tell if either the node or any of the parent nodes is selected.
185          * A selected parent means an unselected node is also in foreground!
186          */
187         bool a_select = (a->flag & NODE_SELECT) != 0, b_select = (b->flag & NODE_SELECT) != 0;
188         bool a_active = (a->flag & NODE_ACTIVE) != 0, b_active = (b->flag & NODE_ACTIVE) != 0;
189
190         /* if one is an ancestor of the other */
191         /* XXX there might be a better sorting algorithm for stable topological sort,
192          * this is O(n^2) worst case */
193         for (parent = a->parent; parent; parent = parent->parent) {
194                 /* if b is an ancestor, it is always behind a */
195                 if (parent == b)
196                         return 1;
197                 /* any selected ancestor moves the node forward */
198                 if (parent->flag & NODE_ACTIVE)
199                         a_active = 1;
200                 if (parent->flag & NODE_SELECT)
201                         a_select = 1;
202         }
203         for (parent = b->parent; parent; parent = parent->parent) {
204                 /* if a is an ancestor, it is always behind b */
205                 if (parent == a)
206                         return 0;
207                 /* any selected ancestor moves the node forward */
208                 if (parent->flag & NODE_ACTIVE)
209                         b_active = 1;
210                 if (parent->flag & NODE_SELECT)
211                         b_select = 1;
212         }
213
214         /* if one of the nodes is in the background and the other not */
215         if ((a->flag & NODE_BACKGROUND) && !(b->flag & NODE_BACKGROUND))
216                 return 0;
217         else if (!(a->flag & NODE_BACKGROUND) && (b->flag & NODE_BACKGROUND))
218                 return 1;
219
220         /* if one has a higher selection state (active > selected > nothing) */
221         if (!b_active && a_active)
222                 return 1;
223         else if (!b_select && (a_active || a_select))
224                 return 1;
225
226         return 0;
227 }
228
229 /* Sorts nodes by selection: unselected nodes first, then selected,
230  * then the active node at the very end. Relative order is kept intact!
231  */
232 void ED_node_sort(bNodeTree *ntree)
233 {
234         /* merge sort is the algorithm of choice here */
235         bNode *first_a, *first_b, *node_a, *node_b, *tmp;
236         int totnodes = BLI_listbase_count(&ntree->nodes);
237         int k, a, b;
238
239         k = 1;
240         while (k < totnodes) {
241                 first_a = first_b = ntree->nodes.first;
242
243                 do {
244                         /* setup first_b pointer */
245                         for (b = 0; b < k && first_b; ++b) {
246                                 first_b = first_b->next;
247                         }
248                         /* all batches merged? */
249                         if (first_b == NULL)
250                                 break;
251
252                         /* merge batches */
253                         node_a = first_a;
254                         node_b = first_b;
255                         a = b = 0;
256                         while (a < k && b < k && node_b) {
257                                 if (compare_nodes(node_a, node_b) == 0) {
258                                         node_a = node_a->next;
259                                         a++;
260                                 }
261                                 else {
262                                         tmp = node_b;
263                                         node_b = node_b->next;
264                                         b++;
265                                         BLI_remlink(&ntree->nodes, tmp);
266                                         BLI_insertlinkbefore(&ntree->nodes, node_a, tmp);
267                                 }
268                         }
269
270                         /* setup first pointers for next batch */
271                         first_b = node_b;
272                         for (; b < k; ++b) {
273                                 /* all nodes sorted? */
274                                 if (first_b == NULL)
275                                         break;
276                                 first_b = first_b->next;
277                         }
278                         first_a = first_b;
279                 } while (first_b);
280
281                 k = k << 1;
282         }
283 }
284
285
286 static void do_node_internal_buttons(bContext *C, void *UNUSED(node_v), int event)
287 {
288         if (event == B_NODE_EXEC) {
289                 SpaceNode *snode = CTX_wm_space_node(C);
290                 if (snode && snode->id)
291                         ED_node_tag_update_id(snode->id);
292         }
293 }
294
295 static void node_uiblocks_init(const bContext *C, bNodeTree *ntree)
296 {
297         bNode *node;
298         char uiblockstr[32];
299
300         /* add node uiBlocks in drawing order - prevents events going to overlapping nodes */
301
302         for (node = ntree->nodes.first; node; node = node->next) {
303                 /* ui block */
304                 BLI_snprintf(uiblockstr, sizeof(uiblockstr), "node buttons %p", (void *)node);
305                 node->block = UI_block_begin(C, CTX_wm_region(C), uiblockstr, UI_EMBOSS);
306                 UI_block_func_handle_set(node->block, do_node_internal_buttons, node);
307
308                 /* this cancels events for background nodes */
309                 UI_block_flag_enable(node->block, UI_BLOCK_CLIP_EVENTS);
310         }
311 }
312
313 void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry)
314 {
315         nodeToView(node, x, y, rx, ry);
316         *rx *= UI_DPI_FAC;
317         *ry *= UI_DPI_FAC;
318 }
319
320 void node_to_updated_rect(struct bNode *node, rctf *r_rect)
321 {
322         node_to_view(node, node->offsetx, node->offsety, &r_rect->xmin, &r_rect->ymax);
323         node_to_view(node, node->offsetx + node->width, node->offsety - node->height, &r_rect->xmax, &r_rect->ymin);
324 }
325
326 void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry)
327 {
328         x /= UI_DPI_FAC;
329         y /= UI_DPI_FAC;
330         nodeFromView(node, x, y, rx, ry);
331 }
332
333
334 /* based on settings in node, sets drawing rect info. each redraw! */
335 static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
336 {
337         uiLayout *layout, *row;
338         PointerRNA nodeptr, sockptr;
339         bNodeSocket *nsock;
340         float locx, locy;
341         float dy;
342         int buty;
343
344         RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
345
346         /* get "global" coords */
347         node_to_view(node, 0.0f, 0.0f, &locx, &locy);
348         dy = locy;
349
350         /* header */
351         dy -= NODE_DY;
352
353         /* little bit space in top */
354         if (node->outputs.first)
355                 dy -= NODE_DYS / 2;
356
357         /* output sockets */
358         bool add_output_space = false;
359
360         for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
361                 if (nodeSocketIsHidden(nsock))
362                         continue;
363
364                 RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
365
366                 layout = UI_block_layout(
367                         node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
368                         locx + NODE_DYS, dy, NODE_WIDTH(node) - NODE_DY, NODE_DY, 0, UI_style_get());
369                 /* context pointers for current node and socket */
370                 uiLayoutSetContextPointer(layout, "node", &nodeptr);
371                 uiLayoutSetContextPointer(layout, "socket", &sockptr);
372
373                 /* align output buttons to the right */
374                 row = uiLayoutRow(layout, 1);
375                 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
376
377                 nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(nsock->name));
378
379                 UI_block_align_end(node->block);
380                 UI_block_layout_resolve(node->block, NULL, &buty);
381
382                 /* ensure minimum socket height in case layout is empty */
383                 buty = min_ii(buty, dy - NODE_DY);
384
385                 nsock->locx = locx + NODE_WIDTH(node);
386                 /* place the socket circle in the middle of the layout */
387                 nsock->locy = 0.5f * (dy + buty);
388
389                 dy = buty;
390                 if (nsock->next)
391                         dy -= NODE_SOCKDY;
392
393                 add_output_space = true;
394         }
395
396         if (add_output_space) {
397                 dy -= NODE_DY / 4;
398         }
399
400         node->prvr.xmin = locx + NODE_DYS;
401         node->prvr.xmax = locx + NODE_WIDTH(node) - NODE_DYS;
402
403         /* preview rect? */
404         if (node->flag & NODE_PREVIEW) {
405                 float aspect = 1.0f;
406
407                 if (node->preview_xsize && node->preview_ysize)
408                         aspect = (float)node->preview_ysize / (float)node->preview_xsize;
409
410                 dy -= NODE_DYS / 2;
411                 node->prvr.ymax = dy;
412
413                 if (aspect <= 1.0f)
414                         node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY);
415                 else {
416                         /* width correction of image */
417                         /* XXX huh? (ton) */
418                         float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect;
419
420                         node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY);
421
422                         node->prvr.xmin += 0.5f * dx;
423                         node->prvr.xmax -= 0.5f * dx;
424                 }
425
426                 dy = node->prvr.ymin - NODE_DYS / 2;
427
428                 /* make sure that maximums are bigger or equal to minimums */
429                 if (node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin);
430                 if (node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin);
431         }
432
433         /* buttons rect? */
434         if (node->typeinfo->draw_buttons && (node->flag & NODE_OPTIONS)) {
435                 dy -= NODE_DYS / 2;
436
437                 /* set this for uifunc() that don't use layout engine yet */
438                 node->butr.xmin = 0;
439                 node->butr.xmax = NODE_WIDTH(node) - 2 * NODE_DYS;
440                 node->butr.ymin = 0;
441                 node->butr.ymax = 0;
442
443
444                 layout = UI_block_layout(
445                         node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
446                         locx + NODE_DYS, dy, node->butr.xmax, 0, 0, UI_style_get());
447                 uiLayoutSetContextPointer(layout, "node", &nodeptr);
448
449                 node->typeinfo->draw_buttons(layout, (bContext *)C, &nodeptr);
450
451                 UI_block_align_end(node->block);
452                 UI_block_layout_resolve(node->block, NULL, &buty);
453
454                 dy = buty - NODE_DYS / 2;
455         }
456
457         /* input sockets */
458         for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
459                 if (nodeSocketIsHidden(nsock))
460                         continue;
461
462                 RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
463
464                 layout = UI_block_layout(
465                         node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
466                         locx + NODE_DYS, dy, NODE_WIDTH(node) - NODE_DY, NODE_DY, 0, UI_style_get());
467                 /* context pointers for current node and socket */
468                 uiLayoutSetContextPointer(layout, "node", &nodeptr);
469                 uiLayoutSetContextPointer(layout, "socket", &sockptr);
470
471                 row = uiLayoutRow(layout, 1);
472
473                 nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(nsock->name));
474
475                 UI_block_align_end(node->block);
476                 UI_block_layout_resolve(node->block, NULL, &buty);
477
478                 /* ensure minimum socket height in case layout is empty */
479                 buty = min_ii(buty, dy - NODE_DY);
480
481                 nsock->locx = locx;
482                 /* place the socket circle in the middle of the layout */
483                 nsock->locy = 0.5f * (dy + buty);
484
485                 dy = buty;
486                 if (nsock->next)
487                         dy -= NODE_SOCKDY;
488         }
489
490         /* little bit space in end */
491         if (node->inputs.first || (node->flag & (NODE_OPTIONS | NODE_PREVIEW)) == 0)
492                 dy -= NODE_DYS / 2;
493
494         node->totr.xmin = locx;
495         node->totr.xmax = locx + NODE_WIDTH(node);
496         node->totr.ymax = locy;
497         node->totr.ymin = min_ff(dy, locy - 2 * NODE_DY);
498
499         /* Set the block bounds to clip mouse events from underlying nodes.
500          * Add a margin for sockets on each side.
501          */
502         UI_block_bounds_set_explicit(
503                 node->block,
504                 node->totr.xmin - NODE_SOCKSIZE,
505                 node->totr.ymin,
506                 node->totr.xmax + NODE_SOCKSIZE,
507                 node->totr.ymax);
508 }
509
510 /* based on settings in node, sets drawing rect info. each redraw! */
511 static void node_update_hidden(bNode *node)
512 {
513         bNodeSocket *nsock;
514         float locx, locy;
515         float rad, drad, hiddenrad = HIDDEN_RAD;
516         int totin = 0, totout = 0, tot;
517
518         /* get "global" coords */
519         node_to_view(node, 0.0f, 0.0f, &locx, &locy);
520
521         /* calculate minimal radius */
522         for (nsock = node->inputs.first; nsock; nsock = nsock->next)
523                 if (!nodeSocketIsHidden(nsock))
524                         totin++;
525         for (nsock = node->outputs.first; nsock; nsock = nsock->next)
526                 if (!nodeSocketIsHidden(nsock))
527                         totout++;
528
529         tot = MAX2(totin, totout);
530         if (tot > 4) {
531                 hiddenrad += 5.0f * (float)(tot - 4);
532         }
533
534         node->totr.xmin = locx;
535         node->totr.xmax = locx + 3 * hiddenrad + node->miniwidth;
536         node->totr.ymax = locy + (hiddenrad - 0.5f * NODE_DY);
537         node->totr.ymin = node->totr.ymax - 2 * hiddenrad;
538
539         /* output sockets */
540         rad = drad = (float)M_PI / (1.0f + (float)totout);
541
542         for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
543                 if (!nodeSocketIsHidden(nsock)) {
544                         nsock->locx = node->totr.xmax - hiddenrad + sinf(rad) * hiddenrad;
545                         nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad;
546                         rad += drad;
547                 }
548         }
549
550         /* input sockets */
551         rad = drad = -(float)M_PI / (1.0f + (float)totin);
552
553         for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
554                 if (!nodeSocketIsHidden(nsock)) {
555                         nsock->locx = node->totr.xmin + hiddenrad + sinf(rad) * hiddenrad;
556                         nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad;
557                         rad += drad;
558                 }
559         }
560
561         /* Set the block bounds to clip mouse events from underlying nodes.
562          * Add a margin for sockets on each side.
563          */
564         UI_block_bounds_set_explicit(
565                 node->block,
566                 node->totr.xmin - NODE_SOCKSIZE,
567                 node->totr.ymin,
568                 node->totr.xmax + NODE_SOCKSIZE,
569                 node->totr.ymax);
570 }
571
572 void node_update_default(const bContext *C, bNodeTree *ntree, bNode *node)
573 {
574         if (node->flag & NODE_HIDDEN)
575                 node_update_hidden(node);
576         else
577                 node_update_basis(C, ntree, node);
578 }
579
580 int node_select_area_default(bNode *node, int x, int y)
581 {
582         return BLI_rctf_isect_pt(&node->totr, x, y);
583 }
584
585 int node_tweak_area_default(bNode *node, int x, int y)
586 {
587         return BLI_rctf_isect_pt(&node->totr, x, y);
588 }
589
590 int node_get_colorid(bNode *node)
591 {
592         switch (node->typeinfo->nclass) {
593                 case NODE_CLASS_INPUT:      return TH_NODE_INPUT;
594                 case NODE_CLASS_OUTPUT:     return (node->flag & NODE_DO_OUTPUT) ? TH_NODE_OUTPUT : TH_NODE;
595                 case NODE_CLASS_CONVERTOR:  return TH_NODE_CONVERTOR;
596                 case NODE_CLASS_OP_COLOR:   return TH_NODE_COLOR;
597                 case NODE_CLASS_OP_VECTOR:  return TH_NODE_VECTOR;
598                 case NODE_CLASS_OP_FILTER:  return TH_NODE_FILTER;
599                 case NODE_CLASS_GROUP:      return TH_NODE_GROUP;
600                 case NODE_CLASS_INTERFACE:  return TH_NODE_INTERFACE;
601                 case NODE_CLASS_MATTE:      return TH_NODE_MATTE;
602                 case NODE_CLASS_DISTORT:    return TH_NODE_DISTORT;
603                 case NODE_CLASS_TEXTURE:    return TH_NODE_TEXTURE;
604                 case NODE_CLASS_SHADER:     return TH_NODE_SHADER;
605                 case NODE_CLASS_SCRIPT:     return TH_NODE_SCRIPT;
606                 case NODE_CLASS_PATTERN:    return TH_NODE_PATTERN;
607                 case NODE_CLASS_LAYOUT:     return TH_NODE_LAYOUT;
608                 default:                    return TH_NODE;
609         }
610 }
611
612 /* note: in cmp_util.c is similar code, for node_compo_pass_on()
613  *       the same goes for shader and texture nodes. */
614 /* note: in node_edit.c is similar code, for untangle node */
615 static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
616 {
617         bNodeLink *link;
618
619         GPU_blend(true);
620
621         for (link = node->internal_links.first; link; link = link->next)
622                 node_draw_link_bezier(v2d, snode, link, TH_REDALERT, TH_REDALERT, -1);
623
624         GPU_blend(false);
625 }
626
627 static void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, PointerRNA node_ptr, bNodeSocket *sock, unsigned pos, unsigned col)
628 {
629         PointerRNA ptr;
630         float color[4];
631
632         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
633         sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
634
635         immAttr4fv(col, color);
636         immVertex2f(pos, sock->locx, sock->locy);
637 }
638
639 /* **************  Socket callbacks *********** */
640
641 static void node_draw_preview_background(float tile, rctf *rect)
642 {
643         float x, y;
644
645         GPUVertFormat *format = immVertexFormat();
646         uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
647
648         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
649
650         /* draw checkerboard backdrop to show alpha */
651         immUniformColor3ub(120, 120, 120);
652         immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
653         immUniformColor3ub(160, 160, 160);
654
655         for (y = rect->ymin; y < rect->ymax; y += tile * 2) {
656                 for (x = rect->xmin; x < rect->xmax; x += tile * 2) {
657                         float tilex = tile, tiley = tile;
658
659                         if (x + tile > rect->xmax)
660                                 tilex = rect->xmax - x;
661                         if (y + tile > rect->ymax)
662                                 tiley = rect->ymax - y;
663
664                         immRectf(pos, x, y, x + tilex, y + tiley);
665                 }
666         }
667         for (y = rect->ymin + tile; y < rect->ymax; y += tile * 2) {
668                 for (x = rect->xmin + tile; x < rect->xmax; x += tile * 2) {
669                         float tilex = tile, tiley = tile;
670
671                         if (x + tile > rect->xmax)
672                                 tilex = rect->xmax - x;
673                         if (y + tile > rect->ymax)
674                                 tiley = rect->ymax - y;
675
676                         immRectf(pos, x, y, x + tilex, y + tiley);
677                 }
678         }
679         immUnbindProgram();
680 }
681
682 /* not a callback */
683 static void node_draw_preview(bNodePreview *preview, rctf *prv)
684 {
685         float xrect = BLI_rctf_size_x(prv);
686         float yrect = BLI_rctf_size_y(prv);
687         float xscale = xrect / ((float)preview->xsize);
688         float yscale = yrect / ((float)preview->ysize);
689         float scale;
690         rctf draw_rect;
691
692         /* uniform scale and offset */
693         draw_rect = *prv;
694         if (xscale < yscale) {
695                 float offset = 0.5f * (yrect - ((float)preview->ysize) * xscale);
696                 draw_rect.ymin += offset;
697                 draw_rect.ymax -= offset;
698                 scale = xscale;
699         }
700         else {
701                 float offset = 0.5f * (xrect - ((float)preview->xsize) * yscale);
702                 draw_rect.xmin += offset;
703                 draw_rect.xmax -= offset;
704                 scale = yscale;
705         }
706
707         node_draw_preview_background(BLI_rctf_size_x(prv) / 10.0f, &draw_rect);
708
709         GPU_blend(true);
710         /* premul graphics */
711         GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
712
713         IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
714         immDrawPixelsTex(&state, draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect,
715                          scale, scale, NULL);
716
717         GPU_blend(false);
718
719         uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
720         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
721         immUniformThemeColorShadeAlpha(TH_BACK, -15, +100);
722         imm_draw_box_wire_2d(pos, draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
723         immUnbindProgram();
724 }
725
726 /* common handle function for operator buttons that need to select the node first */
727 static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_argv)
728 {
729         bNode *node = (bNode *)node_argv;
730         const char *opname = (const char *)op_argv;
731
732         /* select & activate only the button's node */
733         node_select_single(C, node);
734
735         WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, NULL);
736 }
737
738 void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha)
739 {
740         rctf *rct = &node->totr;
741
742         UI_draw_roundbox_corner_set(UI_CNR_ALL);
743         if (node->parent == NULL)
744                 ui_draw_dropshadow(rct, radius, snode->aspect, alpha, node->flag & SELECT);
745         else {
746                 const float margin = 3.0f;
747
748                 float color[4] = {0.0f, 0.0f, 0.0f, 0.33f};
749                 UI_draw_roundbox_aa(true, rct->xmin - margin, rct->ymin - margin,
750                                     rct->xmax + margin, rct->ymax + margin, radius + margin, color);
751         }
752 }
753
754 void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *node, bool draw_outputs, bool select_all)
755 {
756         const uint total_input_len = BLI_listbase_count(&node->inputs);
757         const uint total_output_len = BLI_listbase_count(&node->outputs);
758
759         if (total_input_len + total_output_len == 0) {
760                 return;
761         }
762
763         PointerRNA node_ptr;
764         RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
765
766         float scale;
767         UI_view2d_scale_get(v2d, &scale, NULL);
768
769         GPUVertFormat *format = immVertexFormat();
770         uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
771         uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
772
773         GPU_blend(true);
774         GPU_enable_program_point_size();
775
776         immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA);
777
778         /* set handle size */
779         immUniform1f("size", 2.0f * NODE_SOCKSIZE * scale); /* 2 * size to have diameter */
780
781         if (!select_all) {
782                 /* outline for unselected sockets */
783                 immUniform1f("outlineWidth", 1.0f);
784                 immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 0.6f);
785
786                 immBeginAtMost(GPU_PRIM_POINTS, total_input_len + total_output_len);
787         }
788
789         /* socket inputs */
790         short selected_input_len = 0;
791         bNodeSocket *sock;
792         for (sock = node->inputs.first; sock; sock = sock->next) {
793                 if (nodeSocketIsHidden(sock))
794                         continue;
795                 if (select_all || (sock->flag & SELECT)) {
796                         ++selected_input_len;
797                         continue;
798                 }
799
800                 node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
801         }
802
803         /* socket outputs */
804         short selected_output_len = 0;
805         if (draw_outputs) {
806                 for (sock = node->outputs.first; sock; sock = sock->next) {
807                         if (nodeSocketIsHidden(sock))
808                                 continue;
809                         if (select_all || (sock->flag & SELECT)) {
810                                 ++selected_output_len;
811                                 continue;
812                         }
813
814                         node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
815                 }
816         }
817
818         if (!select_all) {
819                 immEnd();
820         }
821
822         /* go back and draw selected sockets */
823         if (selected_input_len + selected_output_len > 0) {
824                 /* outline for selected sockets */
825                 float c[3];
826                 UI_GetThemeColor3fv(TH_TEXT_HI, c);
827                 immUniform4f("outlineColor", c[0], c[1], c[2], 1.0f);
828                 immUniform1f("outlineWidth", 1.5f);
829
830                 immBegin(GPU_PRIM_POINTS, selected_input_len + selected_output_len);
831
832                 if (selected_input_len) {
833                         /* socket inputs */
834                         for (sock = node->inputs.first; sock; sock = sock->next) {
835                                 if (nodeSocketIsHidden(sock))
836                                         continue;
837                                 if (select_all || (sock->flag & SELECT)) {
838                                         node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
839                                         if (--selected_input_len == 0)
840                                                 break; /* stop as soon as last one is drawn */
841                                 }
842                         }
843                 }
844
845                 if (selected_output_len) {
846                         /* socket outputs */
847                         for (sock = node->outputs.first; sock; sock = sock->next) {
848                                 if (nodeSocketIsHidden(sock))
849                                         continue;
850                                 if (select_all || (sock->flag & SELECT)) {
851                                         node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
852                                         if (--selected_output_len == 0)
853                                                 break; /* stop as soon as last one is drawn */
854                                 }
855                         }
856                 }
857
858                 immEnd();
859         }
860
861         immUnbindProgram();
862
863         GPU_disable_program_point_size();
864         GPU_blend(false);
865 }
866
867 static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
868 {
869         bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data;
870         rctf *rct = &node->totr;
871         float iconofs;
872         /* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */
873         float iconbutw = 0.8f * UI_UNIT_X;
874         int color_id = node_get_colorid(node);
875         float color[4];
876         char showname[128]; /* 128 used below */
877         View2D *v2d = &ar->v2d;
878
879         /* skip if out of view */
880         if (BLI_rctf_isect(&node->totr, &v2d->cur, NULL) == false) {
881                 UI_block_end(C, node->block);
882                 node->block = NULL;
883                 return;
884         }
885
886         /* shadow */
887         node_draw_shadow(snode, node, BASIS_RAD, 1.0f);
888
889         if (node->flag & NODE_MUTED) {
890                 UI_GetThemeColorBlendShade4fv(color_id, TH_REDALERT, 0.5f, 0, color);
891         }
892         else {
893                 /* header uses color from backdrop, but we make it opaque */
894                 if (color_id == TH_NODE) {
895                         UI_GetThemeColorShade3fv(color_id, -20, color);
896                 }
897                 else {
898                         UI_GetThemeColor3fv(color_id, color);
899                 }
900                 color[3] = 1.0f;
901         }
902
903         GPU_line_width(1.0f);
904
905         UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
906         UI_draw_roundbox_aa(true, rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD, color);
907
908         /* show/hide icons */
909         iconofs = rct->xmax - 0.35f * U.widget_unit;
910
911         /* preview */
912         if (node->typeinfo->flag & NODE_PREVIEW) {
913                 uiBut *but;
914                 iconofs -= iconbutw;
915                 UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
916                 but = uiDefIconBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, ICON_MATERIAL,
917                                    iconofs, rct->ymax - NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
918                 UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_preview_toggle");
919                 /* XXX this does not work when node is activated and the operator called right afterwards,
920                  * since active ID is not updated yet (needs to process the notifier).
921                  * This can only work as visual indicator!
922                  */
923 //              if (!(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT)))
924 //                      UI_but_flag_enable(but, UI_BUT_DISABLED);
925                 UI_block_emboss_set(node->block, UI_EMBOSS);
926         }
927         /* group edit */
928         if (node->type == NODE_GROUP) {
929                 uiBut *but;
930                 iconofs -= iconbutw;
931                 UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
932                 but = uiDefIconBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, ICON_NODETREE,
933                                    iconofs, rct->ymax - NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
934                 UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_group_edit");
935                 UI_block_emboss_set(node->block, UI_EMBOSS);
936         }
937
938         /* title */
939         if (node->flag & SELECT) {
940                 UI_GetThemeColor4fv(TH_SELECT, color);
941         }
942         else {
943                 UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
944         }
945
946         /* open/close entirely? */
947         {
948                 uiBut *but;
949                 int but_size = U.widget_unit * 0.8f;
950                 /* XXX button uses a custom triangle draw below, so make it invisible without icon */
951                 UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
952                 but = uiDefBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, "",
953                                rct->xmin + 0.35f * U.widget_unit, rct->ymax - NODE_DY / 2.2f - but_size / 2,
954                                but_size, but_size, NULL, 0, 0, 0, 0, "");
955                 UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
956                 UI_block_emboss_set(node->block, UI_EMBOSS);
957
958                 UI_GetThemeColor4fv(TH_TEXT, color);
959                 /* custom draw function for this button */
960                 UI_draw_icon_tri(rct->xmin + 0.65f * U.widget_unit, rct->ymax - NODE_DY / 2.2f, 'v', color);
961         }
962
963         nodeLabel(ntree, node, showname, sizeof(showname));
964
965         /* XXX - don't print into self! */
966         //if (node->flag & NODE_MUTED)
967         //      BLI_snprintf(showname, sizeof(showname), "[%s]", showname);
968
969         uiDefBut(node->block, UI_BTYPE_LABEL, 0, showname,
970                  (int)(rct->xmin + (NODE_MARGIN_X)), (int)(rct->ymax - NODE_DY),
971                  (short)(iconofs - rct->xmin - 18.0f), (short)NODE_DY,
972                  NULL, 0, 0, 0, 0, "");
973
974         /* body */
975         if (!nodeIsRegistered(node)) {
976                 /* use warning color to indicate undefined types */
977                 UI_GetThemeColor4fv(TH_REDALERT, color);
978         }
979         else if (node->flag & NODE_CUSTOM_COLOR) {
980                 rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], 1.0f);
981         }
982         else
983                 UI_GetThemeColor4fv(TH_NODE, color);
984
985         UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT);
986         UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD, color);
987
988         /* outline active and selected emphasis */
989         if (node->flag & SELECT) {
990                 UI_GetThemeColorShadeAlpha4fv((node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
991
992                 UI_draw_roundbox_corner_set(UI_CNR_ALL);
993                 UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
994         }
995
996         /* disable lines */
997         if (node->flag & NODE_MUTED)
998                 node_draw_mute_line(v2d, snode, node);
999
1000         node_draw_sockets(v2d, C, ntree, node, true, false);
1001
1002         /* preview */
1003         if (node->flag & NODE_PREVIEW && previews) {
1004                 bNodePreview *preview = BKE_node_instance_hash_lookup(previews, key);
1005                 if (preview && (preview->xsize && preview->ysize)) {
1006                         if (preview->rect && !BLI_rctf_is_empty(&node->prvr)) {
1007                                 node_draw_preview(preview, &node->prvr);
1008                         }
1009                 }
1010         }
1011
1012         UI_ThemeClearColor(color_id);
1013
1014         UI_block_end(C, node->block);
1015         UI_block_draw(C, node->block);
1016         node->block = NULL;
1017 }
1018
1019 static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
1020 {
1021         rctf *rct = &node->totr;
1022         float dx, centy = BLI_rctf_cent_y(rct);
1023         float hiddenrad = BLI_rctf_size_y(rct) / 2.0f;
1024         int color_id = node_get_colorid(node);
1025         float color[4];
1026         char showname[128]; /* 128 is used below */
1027         View2D *v2d = &ar->v2d;
1028         float scale;
1029
1030         UI_view2d_scale_get(v2d, &scale, NULL);
1031
1032         /* shadow */
1033         node_draw_shadow(snode, node, hiddenrad, 1.0f);
1034
1035         /* body */
1036         if (node->flag & NODE_MUTED)
1037                 UI_GetThemeColorBlendShade4fv(color_id, TH_REDALERT, 0.5f, 0, color);
1038         else
1039                 UI_GetThemeColor4fv(color_id, color);
1040
1041         UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color);
1042
1043         /* outline active and selected emphasis */
1044         if (node->flag & SELECT) {
1045                 UI_GetThemeColorShadeAlpha4fv((node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
1046
1047                 UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color);
1048         }
1049
1050         /* custom color inline */
1051         if (node->flag & NODE_CUSTOM_COLOR) {
1052                 GPU_blend(true);
1053                 GPU_line_smooth(true);
1054
1055                 UI_draw_roundbox_3fvAlpha(false, rct->xmin + 1, rct->ymin + 1, rct->xmax -1, rct->ymax - 1, hiddenrad, node->color, 1.0f);
1056
1057                 GPU_line_smooth(false);
1058                 GPU_blend(false);
1059         }
1060
1061         /* title */
1062         if (node->flag & SELECT) {
1063                 UI_GetThemeColor4fv(TH_SELECT, color);
1064         }
1065         else {
1066                 UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
1067         }
1068
1069         /* open entirely icon */
1070         {
1071                 uiBut *but;
1072                 int but_size = U.widget_unit * 0.8f;
1073                 /* XXX button uses a custom triangle draw below, so make it invisible without icon */
1074                 UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
1075                 but = uiDefBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, "",
1076                                rct->xmin + 0.35f * U.widget_unit, centy - but_size / 2,
1077                                but_size, but_size, NULL, 0, 0, 0, 0, "");
1078                 UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
1079                 UI_block_emboss_set(node->block, UI_EMBOSS);
1080
1081                 UI_GetThemeColor4fv(TH_TEXT, color);
1082                 /* custom draw function for this button */
1083                 UI_draw_icon_tri(rct->xmin + 0.65f * U.widget_unit, centy, 'h', color);
1084         }
1085
1086         /* disable lines */
1087         if (node->flag & NODE_MUTED)
1088                 node_draw_mute_line(&ar->v2d, snode, node);
1089
1090         if (node->miniwidth > 0.0f) {
1091                 nodeLabel(ntree, node, showname, sizeof(showname));
1092
1093                 /* XXX - don't print into self! */
1094                 //if (node->flag & NODE_MUTED)
1095                 //      BLI_snprintf(showname, sizeof(showname), "[%s]", showname);
1096
1097                 uiDefBut(node->block, UI_BTYPE_LABEL, 0, showname,
1098                          round_fl_to_int(rct->xmin + NODE_MARGIN_X), round_fl_to_int(centy - NODE_DY * 0.5f),
1099                          (short)(BLI_rctf_size_x(rct) - 18.0f - 12.0f), (short)NODE_DY,
1100                          NULL, 0, 0, 0, 0, "");
1101         }
1102
1103         /* scale widget thing */
1104         uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1105         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1106
1107         immUniformThemeColorShade(color_id, -10);
1108         dx = 10.0f;
1109
1110         immBegin(GPU_PRIM_LINES, 4);
1111         immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
1112         immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
1113
1114         immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f);
1115         immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
1116         immEnd();
1117
1118         immUniformThemeColorShade(color_id, 30);
1119         dx -= snode->aspect;
1120
1121         immBegin(GPU_PRIM_LINES, 4);
1122         immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
1123         immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
1124
1125         immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f);
1126         immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
1127         immEnd();
1128
1129         immUnbindProgram();
1130
1131         node_draw_sockets(v2d, C, ntree, node, true, false);
1132
1133         UI_block_end(C, node->block);
1134         UI_block_draw(C, node->block);
1135         node->block = NULL;
1136 }
1137
1138 int node_get_resize_cursor(int directions)
1139 {
1140         if (directions == 0)
1141                 return CURSOR_STD;
1142         else if ((directions & ~(NODE_RESIZE_TOP | NODE_RESIZE_BOTTOM)) == 0)
1143                 return CURSOR_Y_MOVE;
1144         else if ((directions & ~(NODE_RESIZE_RIGHT | NODE_RESIZE_LEFT)) == 0)
1145                 return CURSOR_X_MOVE;
1146         else
1147                 return CURSOR_EDIT;
1148 }
1149
1150 void node_set_cursor(wmWindow *win, SpaceNode *snode, float cursor[2])
1151 {
1152         bNodeTree *ntree = snode->edittree;
1153         bNode *node;
1154         bNodeSocket *sock;
1155         int wmcursor = CURSOR_STD;
1156
1157         if (ntree) {
1158                 if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN | SOCK_OUT)) {
1159                         /* pass */
1160                 }
1161                 else {
1162                         /* check nodes front to back */
1163                         for (node = ntree->nodes.last; node; node = node->prev) {
1164                                 if (BLI_rctf_isect_pt(&node->totr, cursor[0], cursor[1]))
1165                                         break;  /* first hit on node stops */
1166                         }
1167                         if (node) {
1168                                 int dir = node->typeinfo->resize_area_func(node, cursor[0], cursor[1]);
1169                                 wmcursor = node_get_resize_cursor(dir);
1170                         }
1171                 }
1172         }
1173
1174         WM_cursor_set(win, wmcursor);
1175 }
1176
1177 void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
1178 {
1179         if (node->flag & NODE_HIDDEN)
1180                 node_draw_hidden(C, ar, snode, ntree, node, key);
1181         else
1182                 node_draw_basis(C, ar, snode, ntree, node, key);
1183 }
1184
1185 static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
1186 {
1187         if (node->typeinfo->draw_nodetype_prepare)
1188                 node->typeinfo->draw_nodetype_prepare(C, ntree, node);
1189 }
1190
1191 void node_update_nodetree(const bContext *C, bNodeTree *ntree)
1192 {
1193         bNode *node;
1194
1195         /* make sure socket "used" tags are correct, for displaying value buttons */
1196         ntreeTagUsedSockets(ntree);
1197
1198         /* update nodes front to back, so children sizes get updated before parents */
1199         for (node = ntree->nodes.last; node; node = node->prev) {
1200                 node_update(C, ntree, node);
1201         }
1202 }
1203
1204 static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
1205 {
1206         if (node->typeinfo->draw_nodetype)
1207                 node->typeinfo->draw_nodetype(C, ar, snode, ntree, node, key);
1208 }
1209
1210 #define USE_DRAW_TOT_UPDATE
1211
1212 void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNodeInstanceKey parent_key)
1213 {
1214         bNode *node;
1215         bNodeLink *link;
1216         int a;
1217
1218         if (ntree == NULL) return;      /* groups... */
1219
1220 #ifdef USE_DRAW_TOT_UPDATE
1221         if (ntree->nodes.first) {
1222                 BLI_rctf_init_minmax(&ar->v2d.tot);
1223         }
1224 #endif
1225
1226         /* draw background nodes, last nodes in front */
1227         for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) {
1228                 bNodeInstanceKey key;
1229
1230 #ifdef USE_DRAW_TOT_UPDATE
1231                 /* unrelated to background nodes, update the v2d->tot,
1232                  * can be anywhere before we draw the scroll bars */
1233                 BLI_rctf_union(&ar->v2d.tot, &node->totr);
1234 #endif
1235
1236                 if (!(node->flag & NODE_BACKGROUND))
1237                         continue;
1238
1239                 key = BKE_node_instance_key(parent_key, ntree, node);
1240                 node->nr = a;        /* index of node in list, used for exec event code */
1241                 node_draw(C, ar, snode, ntree, node, key);
1242         }
1243
1244         /* node lines */
1245         GPU_blend(true);
1246         nodelink_batch_start(snode);
1247         for (link = ntree->links.first; link; link = link->next) {
1248                 if (!nodeLinkIsHidden(link))
1249                         node_draw_link(&ar->v2d, snode, link);
1250         }
1251         nodelink_batch_end(snode);
1252         GPU_blend(false);
1253
1254         /* draw foreground nodes, last nodes in front */
1255         for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) {
1256                 bNodeInstanceKey key;
1257                 if (node->flag & NODE_BACKGROUND)
1258                         continue;
1259
1260                 key = BKE_node_instance_key(parent_key, ntree, node);
1261                 node->nr = a;        /* index of node in list, used for exec event code */
1262                 node_draw(C, ar, snode, ntree, node, key);
1263         }
1264 }
1265
1266 /* draw tree path info in lower left corner */
1267 static void draw_tree_path(SpaceNode *snode)
1268 {
1269         char info[256];
1270
1271         ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info));
1272
1273         UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
1274         BLF_draw_default(1.5f * UI_UNIT_X, 1.5f * UI_UNIT_Y, 0.0f, info, sizeof(info));
1275 }
1276
1277 static void snode_setup_v2d(SpaceNode *snode, ARegion *ar, const float center[2])
1278 {
1279         View2D *v2d = &ar->v2d;
1280
1281         /* shift view to node tree center */
1282         UI_view2d_center_set(v2d, center[0], center[1]);
1283         UI_view2d_view_ortho(v2d);
1284
1285         /* aspect+font, set each time */
1286         snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx;
1287         // XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
1288 }
1289
1290 static void draw_nodetree(const bContext *C, ARegion *ar, bNodeTree *ntree, bNodeInstanceKey parent_key)
1291 {
1292         SpaceNode *snode = CTX_wm_space_node(C);
1293
1294         node_uiblocks_init(C, ntree);
1295
1296         node_update_nodetree(C, ntree);
1297         node_draw_nodetree(C, ar, snode, ntree, parent_key);
1298 }
1299
1300 /* shade the parent node group and add a uiBlock to clip mouse events */
1301 static void draw_group_overlay(const bContext *C, ARegion *ar)
1302 {
1303         View2D *v2d = &ar->v2d;
1304         rctf rect = v2d->cur;
1305         uiBlock *block;
1306         float color[4];
1307
1308         /* shade node groups to separate them visually */
1309         GPU_blend(true);
1310
1311         UI_GetThemeColorShadeAlpha4fv(TH_NODE_GROUP, 0, 0, color);
1312         UI_draw_roundbox_corner_set(UI_CNR_NONE);
1313         UI_draw_roundbox_4fv(true, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0, color);
1314         GPU_blend(false);
1315
1316         /* set the block bounds to clip mouse events from underlying nodes */
1317         block = UI_block_begin(C, ar, "node tree bounds block", UI_EMBOSS);
1318         UI_block_bounds_set_explicit(block, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
1319         UI_block_flag_enable(block, UI_BLOCK_CLIP_EVENTS);
1320         UI_block_end(C, block);
1321 }
1322
1323 void drawnodespace(const bContext *C, ARegion *ar)
1324 {
1325         wmWindow *win = CTX_wm_window(C);
1326         View2DScrollers *scrollers;
1327         SpaceNode *snode = CTX_wm_space_node(C);
1328         View2D *v2d = &ar->v2d;
1329
1330         UI_ThemeClearColor(TH_BACK);
1331         GPU_clear(GPU_COLOR_BIT);
1332
1333         UI_view2d_view_ortho(v2d);
1334
1335         /* XXX snode->cursor set in coordspace for placing new nodes, used for drawing noodles too */
1336         UI_view2d_region_to_view(&ar->v2d, win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin,
1337                                  &snode->cursor[0], &snode->cursor[1]);
1338         snode->cursor[0] /= UI_DPI_FAC;
1339         snode->cursor[1] /= UI_DPI_FAC;
1340
1341         ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
1342
1343         /* only set once */
1344         GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
1345
1346         /* nodes */
1347         snode_set_context(C);
1348
1349         /* draw parent node trees */
1350         if (snode->treepath.last) {
1351                 static const int max_depth = 2;
1352                 bNodeTreePath *path;
1353                 int depth, curdepth;
1354                 float center[2];
1355                 bNodeTree *ntree;
1356                 bNodeLinkDrag *nldrag;
1357                 LinkData *linkdata;
1358
1359                 path = snode->treepath.last;
1360
1361                 /* update tree path name (drawn in the bottom left) */
1362                 ID *name_id = (path->nodetree && path->nodetree != snode->nodetree) ? &path->nodetree->id : snode->id;
1363
1364                 if (name_id && UNLIKELY(!STREQ(path->node_name, name_id->name + 2))) {
1365                         BLI_strncpy(path->node_name, name_id->name + 2, sizeof(path->node_name));
1366                 }
1367
1368                 /* current View2D center, will be set temporarily for parent node trees */
1369                 UI_view2d_center_get(v2d, &center[0], &center[1]);
1370
1371                 /* store new view center in path and current edittree */
1372                 copy_v2_v2(path->view_center, center);
1373                 if (snode->edittree)
1374                         copy_v2_v2(snode->edittree->view_center, center);
1375
1376                 depth = 0;
1377                 while (path->prev && depth < max_depth) {
1378                         path = path->prev;
1379                         ++depth;
1380                 }
1381
1382                 /* parent node trees in the background */
1383                 for (curdepth = depth; curdepth > 0; path = path->next, --curdepth) {
1384                         ntree = path->nodetree;
1385                         if (ntree) {
1386                                 snode_setup_v2d(snode, ar, path->view_center);
1387
1388                                 draw_nodetree(C, ar, ntree, path->parent_key);
1389
1390                                 draw_group_overlay(C, ar);
1391                         }
1392                 }
1393
1394                 /* top-level edit tree */
1395                 ntree = path->nodetree;
1396                 if (ntree) {
1397                         snode_setup_v2d(snode, ar, center);
1398
1399                         /* grid, uses theme color based on node path depth */
1400                         UI_view2d_multi_grid_draw(v2d, (depth > 0 ? TH_NODE_GROUP : TH_BACK), ED_node_grid_size(), NODE_GRID_STEPS, 2);
1401
1402                         /* backdrop */
1403                         draw_nodespace_back_pix(C, ar, snode, path->parent_key);
1404
1405                         {
1406                                 float original_proj[4][4];
1407                                 GPU_matrix_projection_get(original_proj);
1408
1409                                 GPU_matrix_push();
1410                                 GPU_matrix_identity_set();
1411
1412                                 wmOrtho2_pixelspace(ar->winx, ar->winy);
1413
1414                                 WM_gizmomap_draw(ar->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
1415
1416                                 GPU_matrix_pop();
1417                                 GPU_matrix_projection_set(original_proj);
1418                         }
1419
1420                         draw_nodetree(C, ar, ntree, path->parent_key);
1421                 }
1422
1423                 /* temporary links */
1424                 GPU_blend(true);
1425                 GPU_line_smooth(true);
1426                 for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) {
1427                         for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next)
1428                                 node_draw_link(v2d, snode, (bNodeLink *)linkdata->data);
1429                 }
1430                 GPU_line_smooth(false);
1431                 GPU_blend(false);
1432
1433                 if (snode->flag & SNODE_SHOW_GPENCIL) {
1434                         /* draw grease-pencil ('canvas' strokes) */
1435                         ED_annotation_draw_view2d(C, true);
1436                 }
1437         }
1438         else {
1439                 /* default grid */
1440                 UI_view2d_multi_grid_draw(v2d, TH_BACK, ED_node_grid_size(), NODE_GRID_STEPS, 2);
1441
1442                 /* backdrop */
1443                 draw_nodespace_back_pix(C, ar, snode, NODE_INSTANCE_KEY_NONE);
1444         }
1445
1446         ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
1447
1448         /* reset view matrix */
1449         UI_view2d_view_restore(C);
1450
1451         if (snode->treepath.last) {
1452                 if (snode->flag & SNODE_SHOW_GPENCIL) {
1453                         /* draw grease-pencil (screen strokes, and also paintbuffer) */
1454                         ED_annotation_draw_view2d(C, false);
1455                 }
1456         }
1457
1458         /* tree path info */
1459         draw_tree_path(snode);
1460
1461         /* scrollers */
1462         scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, 10, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
1463         UI_view2d_scrollers_draw(C, v2d, scrollers);
1464         UI_view2d_scrollers_free(scrollers);
1465 }