Cleanup: Move RNA Manual References to Modules
[blender.git] / source / blender / editors / space_node / space_node.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  */
23
24 #include "DNA_gpencil_types.h"
25 #include "DNA_light_types.h"
26 #include "DNA_material_types.h"
27 #include "DNA_node_types.h"
28 #include "DNA_world_types.h"
29
30 #include "MEM_guardedalloc.h"
31
32 #include "BLI_blenlib.h"
33 #include "BLI_math.h"
34
35 #include "BKE_context.h"
36 #include "BKE_library.h"
37 #include "BKE_scene.h"
38 #include "BKE_screen.h"
39 #include "BKE_node.h"
40
41 #include "ED_space_api.h"
42 #include "ED_node.h"
43 #include "ED_render.h"
44 #include "ED_screen.h"
45
46 #include "UI_resources.h"
47 #include "UI_view2d.h"
48
49 #include "RNA_access.h"
50 #include "RNA_define.h"
51 #include "RNA_enum_types.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #include "node_intern.h" /* own include */
57
58 /* ******************** tree path ********************* */
59
60 void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from)
61 {
62   bNodeTreePath *path, *path_next;
63   for (path = snode->treepath.first; path; path = path_next) {
64     path_next = path->next;
65     MEM_freeN(path);
66   }
67   BLI_listbase_clear(&snode->treepath);
68
69   if (ntree) {
70     path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
71     path->nodetree = ntree;
72     path->parent_key = NODE_INSTANCE_KEY_BASE;
73
74     /* copy initial offset from bNodeTree */
75     copy_v2_v2(path->view_center, ntree->view_center);
76
77     if (id) {
78       BLI_strncpy(path->node_name, id->name + 2, sizeof(path->node_name));
79     }
80
81     BLI_addtail(&snode->treepath, path);
82
83     id_us_ensure_real(&ntree->id);
84   }
85
86   /* update current tree */
87   snode->nodetree = snode->edittree = ntree;
88   snode->id = id;
89   snode->from = from;
90
91   ED_node_set_active_viewer_key(snode);
92
93   WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
94 }
95
96 void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
97 {
98   bNodeTreePath *path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
99   bNodeTreePath *prev_path = snode->treepath.last;
100   path->nodetree = ntree;
101   if (gnode) {
102     if (prev_path) {
103       path->parent_key = BKE_node_instance_key(prev_path->parent_key, prev_path->nodetree, gnode);
104     }
105     else {
106       path->parent_key = NODE_INSTANCE_KEY_BASE;
107     }
108
109     BLI_strncpy(path->node_name, gnode->name, sizeof(path->node_name));
110   }
111   else {
112     path->parent_key = NODE_INSTANCE_KEY_BASE;
113   }
114
115   /* copy initial offset from bNodeTree */
116   copy_v2_v2(path->view_center, ntree->view_center);
117
118   BLI_addtail(&snode->treepath, path);
119
120   id_us_ensure_real(&ntree->id);
121
122   /* update current tree */
123   snode->edittree = ntree;
124
125   ED_node_set_active_viewer_key(snode);
126
127   WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
128 }
129
130 void ED_node_tree_pop(SpaceNode *snode)
131 {
132   bNodeTreePath *path = snode->treepath.last;
133
134   /* don't remove root */
135   if (path == snode->treepath.first) {
136     return;
137   }
138
139   BLI_remlink(&snode->treepath, path);
140   MEM_freeN(path);
141
142   /* update current tree */
143   path = snode->treepath.last;
144   snode->edittree = path->nodetree;
145
146   ED_node_set_active_viewer_key(snode);
147
148   /* listener updates the View2D center from edittree */
149   WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
150 }
151
152 int ED_node_tree_depth(SpaceNode *snode)
153 {
154   return BLI_listbase_count(&snode->treepath);
155 }
156
157 bNodeTree *ED_node_tree_get(SpaceNode *snode, int level)
158 {
159   bNodeTreePath *path;
160   int i;
161   for (path = snode->treepath.last, i = 0; path; path = path->prev, ++i) {
162     if (i == level) {
163       return path->nodetree;
164     }
165   }
166   return NULL;
167 }
168
169 int ED_node_tree_path_length(SpaceNode *snode)
170 {
171   bNodeTreePath *path;
172   int length = 0;
173   int i;
174   for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
175     length += strlen(path->node_name);
176     if (i > 0) {
177       length += 1; /* for separator char */
178     }
179   }
180   return length;
181 }
182
183 void ED_node_tree_path_get(SpaceNode *snode, char *value)
184 {
185   bNodeTreePath *path;
186   int i;
187
188   value[0] = '\0';
189   for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
190     if (i == 0) {
191       strcpy(value, path->node_name);
192       value += strlen(path->node_name);
193     }
194     else {
195       sprintf(value, "/%s", path->node_name);
196       value += strlen(path->node_name) + 1;
197     }
198   }
199 }
200
201 void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_length)
202 {
203   bNodeTreePath *path;
204   int size, i;
205
206   value[0] = '\0';
207   for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
208     if (i == 0) {
209       size = BLI_strncpy_rlen(value, path->node_name, max_length);
210     }
211     else {
212       size = BLI_snprintf_rlen(value, max_length, "/%s", path->node_name);
213     }
214     max_length -= size;
215     if (max_length <= 0) {
216       break;
217     }
218     value += size;
219   }
220 }
221
222 void ED_node_set_active_viewer_key(SpaceNode *snode)
223 {
224   bNodeTreePath *path = snode->treepath.last;
225   if (snode->nodetree && path) {
226     snode->nodetree->active_viewer_key = path->parent_key;
227   }
228 }
229
230 void snode_group_offset(SpaceNode *snode, float *x, float *y)
231 {
232   bNodeTreePath *path = snode->treepath.last;
233
234   if (path && path->prev) {
235     float dcenter[2];
236     sub_v2_v2v2(dcenter, path->view_center, path->prev->view_center);
237     *x = dcenter[0];
238     *y = dcenter[1];
239   }
240   else {
241     *x = *y = 0.0f;
242   }
243 }
244
245 /* ******************** default callbacks for node space ***************** */
246
247 static SpaceLink *node_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
248 {
249   ARegion *ar;
250   SpaceNode *snode;
251
252   snode = MEM_callocN(sizeof(SpaceNode), "initnode");
253   snode->spacetype = SPACE_NODE;
254
255   snode->flag = SNODE_SHOW_GPENCIL | SNODE_USE_ALPHA;
256
257   /* backdrop */
258   snode->zoom = 1.0f;
259
260   /* select the first tree type for valid type */
261   NODE_TREE_TYPES_BEGIN (treetype) {
262     strcpy(snode->tree_idname, treetype->idname);
263     break;
264   }
265   NODE_TREE_TYPES_END;
266
267   /* header */
268   ar = MEM_callocN(sizeof(ARegion), "header for node");
269
270   BLI_addtail(&snode->regionbase, ar);
271   ar->regiontype = RGN_TYPE_HEADER;
272   ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
273
274   /* buttons/list view */
275   ar = MEM_callocN(sizeof(ARegion), "buttons for node");
276
277   BLI_addtail(&snode->regionbase, ar);
278   ar->regiontype = RGN_TYPE_UI;
279   ar->alignment = RGN_ALIGN_RIGHT;
280
281   /* toolbar */
282   ar = MEM_callocN(sizeof(ARegion), "node tools");
283
284   BLI_addtail(&snode->regionbase, ar);
285   ar->regiontype = RGN_TYPE_TOOLS;
286   ar->alignment = RGN_ALIGN_LEFT;
287
288   ar->flag = RGN_FLAG_HIDDEN;
289
290   /* main region */
291   ar = MEM_callocN(sizeof(ARegion), "main region for node");
292
293   BLI_addtail(&snode->regionbase, ar);
294   ar->regiontype = RGN_TYPE_WINDOW;
295
296   ar->v2d.tot.xmin = -12.8f * U.widget_unit;
297   ar->v2d.tot.ymin = -12.8f * U.widget_unit;
298   ar->v2d.tot.xmax = 38.4f * U.widget_unit;
299   ar->v2d.tot.ymax = 38.4f * U.widget_unit;
300
301   ar->v2d.cur = ar->v2d.tot;
302
303   ar->v2d.min[0] = 1.0f;
304   ar->v2d.min[1] = 1.0f;
305
306   ar->v2d.max[0] = 32000.0f;
307   ar->v2d.max[1] = 32000.0f;
308
309   ar->v2d.minzoom = 0.09f;
310   ar->v2d.maxzoom = 2.31f;
311
312   ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
313   ar->v2d.keepzoom = V2D_LIMITZOOM | V2D_KEEPASPECT;
314   ar->v2d.keeptot = 0;
315
316   return (SpaceLink *)snode;
317 }
318
319 static void node_free(SpaceLink *sl)
320 {
321   SpaceNode *snode = (SpaceNode *)sl;
322   bNodeTreePath *path, *path_next;
323
324   for (path = snode->treepath.first; path; path = path_next) {
325     path_next = path->next;
326     MEM_freeN(path);
327   }
328 }
329
330 /* spacetype; init callback */
331 static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
332 {
333 }
334
335 static void node_area_listener(wmWindow *UNUSED(win),
336                                ScrArea *sa,
337                                wmNotifier *wmn,
338                                Scene *UNUSED(scene))
339 {
340   /* note, ED_area_tag_refresh will re-execute compositor */
341   SpaceNode *snode = sa->spacedata.first;
342   /* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */
343   short shader_type = snode->shaderfrom;
344
345   /* preview renders */
346   switch (wmn->category) {
347     case NC_SCENE:
348       switch (wmn->data) {
349         case ND_NODES: {
350           ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
351           bNodeTreePath *path = snode->treepath.last;
352           /* shift view to node tree center */
353           if (ar && path) {
354             UI_view2d_center_set(&ar->v2d, path->view_center[0], path->view_center[1]);
355           }
356
357           ED_area_tag_refresh(sa);
358           break;
359         }
360         case ND_FRAME:
361           ED_area_tag_refresh(sa);
362           break;
363         case ND_COMPO_RESULT:
364           ED_area_tag_redraw(sa);
365           break;
366         case ND_TRANSFORM_DONE:
367           if (ED_node_is_compositor(snode)) {
368             if (snode->flag & SNODE_AUTO_RENDER) {
369               snode->recalc = 1;
370               ED_area_tag_refresh(sa);
371             }
372           }
373           break;
374         case ND_LAYER_CONTENT:
375           ED_area_tag_refresh(sa);
376           break;
377       }
378       break;
379
380     /* future: add ID checks? */
381     case NC_MATERIAL:
382       if (ED_node_is_shader(snode)) {
383         if (wmn->data == ND_SHADING) {
384           ED_area_tag_refresh(sa);
385         }
386         else if (wmn->data == ND_SHADING_DRAW) {
387           ED_area_tag_refresh(sa);
388         }
389         else if (wmn->data == ND_SHADING_LINKS) {
390           ED_area_tag_refresh(sa);
391         }
392         else if (wmn->action == NA_ADDED && snode->edittree) {
393           nodeSetActiveID(snode->edittree, ID_MA, wmn->reference);
394         }
395       }
396       break;
397     case NC_TEXTURE:
398       if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) {
399         if (wmn->data == ND_NODES) {
400           ED_area_tag_refresh(sa);
401         }
402       }
403       break;
404     case NC_WORLD:
405       if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) {
406         ED_area_tag_refresh(sa);
407       }
408       break;
409     case NC_OBJECT:
410       if (ED_node_is_shader(snode)) {
411         if (wmn->data == ND_OB_SHADING) {
412           ED_area_tag_refresh(sa);
413         }
414       }
415       break;
416     case NC_SPACE:
417       if (wmn->data == ND_SPACE_NODE) {
418         ED_area_tag_refresh(sa);
419       }
420       else if (wmn->data == ND_SPACE_NODE_VIEW) {
421         ED_area_tag_redraw(sa);
422       }
423       break;
424     case NC_NODE:
425       if (wmn->action == NA_EDITED) {
426         ED_area_tag_refresh(sa);
427       }
428       else if (wmn->action == NA_SELECTED) {
429         ED_area_tag_redraw(sa);
430       }
431       break;
432     case NC_SCREEN:
433       switch (wmn->data) {
434         case ND_ANIMPLAY:
435           ED_area_tag_refresh(sa);
436           break;
437       }
438       break;
439     case NC_MASK:
440       if (wmn->action == NA_EDITED) {
441         if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) {
442           ED_area_tag_refresh(sa);
443         }
444       }
445       break;
446
447     case NC_IMAGE:
448       if (wmn->action == NA_EDITED) {
449         if (ED_node_is_compositor(snode)) {
450           /* note that nodeUpdateID is already called by BKE_image_signal() on all
451            * scenes so really this is just to know if the images is used in the compo else
452            * painting on images could become very slow when the compositor is open. */
453           if (nodeUpdateID(snode->nodetree, wmn->reference)) {
454             ED_area_tag_refresh(sa);
455           }
456         }
457       }
458       break;
459
460     case NC_MOVIECLIP:
461       if (wmn->action == NA_EDITED) {
462         if (ED_node_is_compositor(snode)) {
463           if (nodeUpdateID(snode->nodetree, wmn->reference)) {
464             ED_area_tag_refresh(sa);
465           }
466         }
467       }
468       break;
469
470     case NC_LINESTYLE:
471       if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_LINESTYLE) {
472         ED_area_tag_refresh(sa);
473       }
474       break;
475     case NC_WM:
476       if (wmn->data == ND_UNDO) {
477         ED_area_tag_refresh(sa);
478       }
479       break;
480     case NC_GPENCIL:
481       if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
482         ED_area_tag_redraw(sa);
483       }
484       break;
485   }
486 }
487
488 static void node_area_refresh(const struct bContext *C, ScrArea *sa)
489 {
490   /* default now: refresh node is starting preview */
491   SpaceNode *snode = sa->spacedata.first;
492
493   snode_set_context(C);
494
495   if (snode->nodetree) {
496     if (snode->nodetree->type == NTREE_SHADER) {
497       if (GS(snode->id->name) == ID_MA) {
498         Material *ma = (Material *)snode->id;
499         if (ma->use_nodes) {
500           ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
501         }
502       }
503       else if (GS(snode->id->name) == ID_LA) {
504         Light *la = (Light *)snode->id;
505         if (la->use_nodes) {
506           ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
507         }
508       }
509       else if (GS(snode->id->name) == ID_WO) {
510         World *wo = (World *)snode->id;
511         if (wo->use_nodes) {
512           ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
513         }
514       }
515     }
516     else if (snode->nodetree->type == NTREE_COMPOSIT) {
517       Scene *scene = (Scene *)snode->id;
518       if (scene->use_nodes) {
519         /* recalc is set on 3d view changes for auto compo */
520         if (snode->recalc) {
521           snode->recalc = 0;
522           node_render_changed_exec((struct bContext *)C, NULL);
523         }
524         else {
525           ED_node_composite_job(C, snode->nodetree, scene);
526         }
527       }
528     }
529     else if (snode->nodetree->type == NTREE_TEXTURE) {
530       Tex *tex = (Tex *)snode->id;
531       if (tex->use_nodes) {
532         ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
533       }
534     }
535   }
536 }
537
538 static SpaceLink *node_duplicate(SpaceLink *sl)
539 {
540   SpaceNode *snode = (SpaceNode *)sl;
541   SpaceNode *snoden = MEM_dupallocN(snode);
542
543   BLI_duplicatelist(&snoden->treepath, &snode->treepath);
544
545   /* clear or remove stuff from old */
546   BLI_listbase_clear(&snoden->linkdrag);
547
548   /* Note: no need to set node tree user counts,
549    * the editor only keeps at least 1 (id_us_ensure_real),
550    * which is already done by the original SpaceNode.
551    */
552
553   return (SpaceLink *)snoden;
554 }
555
556 /* add handlers, stuff you only do once or on area/region changes */
557 static void node_buttons_region_init(wmWindowManager *wm, ARegion *ar)
558 {
559   wmKeyMap *keymap;
560
561   ED_region_panels_init(wm, ar);
562
563   keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
564   WM_event_add_keymap_handler(&ar->handlers, keymap);
565 }
566
567 static void node_buttons_region_draw(const bContext *C, ARegion *ar)
568 {
569   ED_region_panels(C, ar);
570 }
571
572 /* add handlers, stuff you only do once or on area/region changes */
573 static void node_toolbar_region_init(wmWindowManager *wm, ARegion *ar)
574 {
575   wmKeyMap *keymap;
576
577   ED_region_panels_init(wm, ar);
578
579   keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
580   WM_event_add_keymap_handler(&ar->handlers, keymap);
581 }
582
583 static void node_toolbar_region_draw(const bContext *C, ARegion *ar)
584 {
585   ED_region_panels(C, ar);
586 }
587
588 static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
589 {
590   SpaceNode *snode = sa->spacedata.first;
591
592   /* convert mouse coordinates to v2d space */
593   UI_view2d_region_to_view(&ar->v2d,
594                            win->eventstate->x - ar->winrct.xmin,
595                            win->eventstate->y - ar->winrct.ymin,
596                            &snode->cursor[0],
597                            &snode->cursor[1]);
598
599   /* here snode->cursor is used to detect the node edge for sizing */
600   node_set_cursor(win, snode, snode->cursor);
601
602   /* XXX snode->cursor is in placing new nodes space */
603   snode->cursor[0] /= UI_DPI_FAC;
604   snode->cursor[1] /= UI_DPI_FAC;
605 }
606
607 /* Initialize main region, setting handlers. */
608 static void node_main_region_init(wmWindowManager *wm, ARegion *ar)
609 {
610   wmKeyMap *keymap;
611   ListBase *lb;
612
613   UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
614
615   /* own keymaps */
616   keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
617   WM_event_add_keymap_handler(&ar->handlers, keymap);
618
619   keymap = WM_keymap_ensure(wm->defaultconf, "Node Editor", SPACE_NODE, 0);
620   WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
621
622   /* add drop boxes */
623   lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
624
625   WM_event_add_dropbox_handler(&ar->handlers, lb);
626 }
627
628 static void node_main_region_draw(const bContext *C, ARegion *ar)
629 {
630   drawnodespace(C, ar);
631 }
632
633 /* ************* dropboxes ************* */
634
635 static bool node_ima_drop_poll(bContext *UNUSED(C),
636                                wmDrag *drag,
637                                const wmEvent *UNUSED(event),
638                                const char **UNUSED(tooltip))
639 {
640   if (drag->type == WM_DRAG_PATH) {
641     /* rule might not work? */
642     return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE));
643   }
644   else {
645     return WM_drag_ID(drag, ID_IM) != NULL;
646   }
647 }
648
649 static bool node_mask_drop_poll(bContext *UNUSED(C),
650                                 wmDrag *drag,
651                                 const wmEvent *UNUSED(event),
652                                 const char **UNUSED(tooltip))
653 {
654   return WM_drag_ID(drag, ID_MSK) != NULL;
655 }
656
657 static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop)
658 {
659   ID *id = WM_drag_ID(drag, 0);
660
661   RNA_string_set(drop->ptr, "name", id->name + 2);
662 }
663
664 static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
665 {
666   ID *id = WM_drag_ID(drag, 0);
667
668   if (id) {
669     RNA_string_set(drop->ptr, "name", id->name + 2);
670     RNA_struct_property_unset(drop->ptr, "filepath");
671   }
672   else if (drag->path[0]) {
673     RNA_string_set(drop->ptr, "filepath", drag->path);
674     RNA_struct_property_unset(drop->ptr, "name");
675   }
676 }
677
678 /* this region dropbox definition */
679 static void node_dropboxes(void)
680 {
681   ListBase *lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
682
683   WM_dropbox_add(lb, "NODE_OT_add_file", node_ima_drop_poll, node_id_path_drop_copy);
684   WM_dropbox_add(lb, "NODE_OT_add_mask", node_mask_drop_poll, node_id_drop_copy);
685 }
686
687 /* ************* end drop *********** */
688
689 /* add handlers, stuff you only do once or on area/region changes */
690 static void node_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
691 {
692   ED_region_header_init(ar);
693 }
694
695 static void node_header_region_draw(const bContext *C, ARegion *ar)
696 {
697   /* find and set the context */
698   snode_set_context(C);
699
700   ED_region_header(C, ar);
701 }
702
703 /* used for header + main region */
704 static void node_region_listener(wmWindow *UNUSED(win),
705                                  ScrArea *UNUSED(sa),
706                                  ARegion *ar,
707                                  wmNotifier *wmn,
708                                  const Scene *UNUSED(scene))
709 {
710   wmGizmoMap *gzmap = ar->gizmo_map;
711
712   /* context changes */
713   switch (wmn->category) {
714     case NC_SPACE:
715       switch (wmn->data) {
716         case ND_SPACE_NODE:
717           ED_region_tag_redraw(ar);
718           break;
719         case ND_SPACE_NODE_VIEW:
720           WM_gizmomap_tag_refresh(gzmap);
721           break;
722       }
723       break;
724     case NC_SCREEN:
725       if (wmn->data == ND_LAYOUTSET || wmn->action == NA_EDITED) {
726         WM_gizmomap_tag_refresh(gzmap);
727       }
728       switch (wmn->data) {
729         case ND_ANIMPLAY:
730         case ND_LAYER:
731           ED_region_tag_redraw(ar);
732           break;
733       }
734       break;
735     case NC_WM:
736       if (wmn->data == ND_JOB) {
737         ED_region_tag_redraw(ar);
738       }
739       break;
740     case NC_SCENE:
741       ED_region_tag_redraw(ar);
742       if (wmn->data == ND_RENDER_RESULT) {
743         WM_gizmomap_tag_refresh(gzmap);
744       }
745       break;
746     case NC_NODE:
747       ED_region_tag_redraw(ar);
748       if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
749         WM_gizmomap_tag_refresh(gzmap);
750       }
751       break;
752     case NC_MATERIAL:
753     case NC_TEXTURE:
754     case NC_WORLD:
755     case NC_LINESTYLE:
756       ED_region_tag_redraw(ar);
757       break;
758     case NC_OBJECT:
759       if (wmn->data == ND_OB_SHADING) {
760         ED_region_tag_redraw(ar);
761       }
762       break;
763     case NC_ID:
764       if (wmn->action == NA_RENAME) {
765         ED_region_tag_redraw(ar);
766       }
767       break;
768     case NC_GPENCIL:
769       if (wmn->action == NA_EDITED) {
770         ED_region_tag_redraw(ar);
771       }
772       else if (wmn->data & ND_GPENCIL_EDITMODE) {
773         ED_region_tag_redraw(ar);
774       }
775       break;
776   }
777 }
778
779 const char *node_context_dir[] = {
780     "selected_nodes", "active_node", "light", "material", "world", NULL};
781
782 static int node_context(const bContext *C, const char *member, bContextDataResult *result)
783 {
784   SpaceNode *snode = CTX_wm_space_node(C);
785
786   if (CTX_data_dir(member)) {
787     CTX_data_dir_set(result, node_context_dir);
788     return 1;
789   }
790   else if (CTX_data_equals(member, "selected_nodes")) {
791     bNode *node;
792
793     if (snode->edittree) {
794       for (node = snode->edittree->nodes.last; node; node = node->prev) {
795         if (node->flag & NODE_SELECT) {
796           CTX_data_list_add(result, &snode->edittree->id, &RNA_Node, node);
797         }
798       }
799     }
800     CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
801     return 1;
802   }
803   else if (CTX_data_equals(member, "active_node")) {
804     if (snode->edittree) {
805       bNode *node = nodeGetActive(snode->edittree);
806       CTX_data_pointer_set(result, &snode->edittree->id, &RNA_Node, node);
807     }
808
809     CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
810     return 1;
811   }
812   else if (CTX_data_equals(member, "node_previews")) {
813     if (snode->nodetree) {
814       CTX_data_pointer_set(
815           result, &snode->nodetree->id, &RNA_NodeInstanceHash, snode->nodetree->previews);
816     }
817
818     CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
819     return 1;
820   }
821   else if (CTX_data_equals(member, "material")) {
822     if (snode->id && GS(snode->id->name) == ID_MA) {
823       CTX_data_id_pointer_set(result, snode->id);
824     }
825     return 1;
826   }
827   else if (CTX_data_equals(member, "light")) {
828     if (snode->id && GS(snode->id->name) == ID_LA) {
829       CTX_data_id_pointer_set(result, snode->id);
830     }
831     return 1;
832   }
833   else if (CTX_data_equals(member, "world")) {
834     if (snode->id && GS(snode->id->name) == ID_WO) {
835       CTX_data_id_pointer_set(result, snode->id);
836     }
837     return 1;
838   }
839
840   return 0;
841 }
842
843 static void node_widgets(void)
844 {
845   /* create the widgetmap for the area here */
846   wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(
847       &(const struct wmGizmoMapType_Params){SPACE_NODE, RGN_TYPE_WINDOW});
848   WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_transform);
849   WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_crop);
850   WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_sun_beams);
851   WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_corner_pin);
852 }
853
854 static void node_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
855 {
856   SpaceNode *snode = (SpaceNode *)slink;
857
858   if (GS(old_id->name) == ID_SCE) {
859     if (snode->id == old_id) {
860       /* nasty DNA logic for SpaceNode:
861        * ideally should be handled by editor code, but would be bad level call
862        */
863       BLI_freelistN(&snode->treepath);
864
865       /* XXX Untested in case new_id != NULL... */
866       snode->id = new_id;
867       snode->from = NULL;
868       snode->nodetree = NULL;
869       snode->edittree = NULL;
870     }
871   }
872   else if (GS(old_id->name) == ID_OB) {
873     if (snode->from == old_id) {
874       if (new_id == NULL) {
875         snode->flag &= ~SNODE_PIN;
876       }
877       snode->from = new_id;
878     }
879   }
880   else if (GS(old_id->name) == ID_GD) {
881     if ((ID *)snode->gpd == old_id) {
882       snode->gpd = (bGPdata *)new_id;
883       id_us_min(old_id);
884       id_us_plus(new_id);
885     }
886   }
887   else if (GS(old_id->name) == ID_NT) {
888     bNodeTreePath *path, *path_next;
889
890     for (path = snode->treepath.first; path; path = path->next) {
891       if ((ID *)path->nodetree == old_id) {
892         path->nodetree = (bNodeTree *)new_id;
893         id_us_min(old_id);
894         id_us_plus(new_id);
895       }
896       if (path == snode->treepath.first) {
897         /* first nodetree in path is same as snode->nodetree */
898         snode->nodetree = path->nodetree;
899       }
900       if (path->nodetree == NULL) {
901         break;
902       }
903     }
904
905     /* remaining path entries are invalid, remove */
906     for (; path; path = path_next) {
907       path_next = path->next;
908
909       BLI_remlink(&snode->treepath, path);
910       MEM_freeN(path);
911     }
912
913     /* edittree is just the last in the path,
914      * set this directly since the path may have been shortened above */
915     if (snode->treepath.last) {
916       path = snode->treepath.last;
917       snode->edittree = path->nodetree;
918     }
919     else {
920       snode->edittree = NULL;
921     }
922   }
923 }
924
925 static int node_space_subtype_get(ScrArea *sa)
926 {
927   SpaceNode *snode = sa->spacedata.first;
928   return rna_node_tree_idname_to_enum(snode->tree_idname);
929 }
930
931 static void node_space_subtype_set(ScrArea *sa, int value)
932 {
933   SpaceNode *snode = sa->spacedata.first;
934   ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value));
935 }
936
937 static void node_space_subtype_item_extend(bContext *C, EnumPropertyItem **item, int *totitem)
938 {
939   bool free;
940   const EnumPropertyItem *item_src = RNA_enum_node_tree_types_itemf_impl(C, &free);
941   for (const EnumPropertyItem *item_iter = item_src; item_iter->identifier; item_iter++) {
942     RNA_enum_item_add(item, totitem, item_iter);
943   }
944   if (free) {
945     MEM_freeN((void *)item_src);
946   }
947 }
948
949 /* only called once, from space/spacetypes.c */
950 void ED_spacetype_node(void)
951 {
952   SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype node");
953   ARegionType *art;
954
955   st->spaceid = SPACE_NODE;
956   strncpy(st->name, "Node", BKE_ST_MAXNAME);
957
958   st->new = node_new;
959   st->free = node_free;
960   st->init = node_init;
961   st->duplicate = node_duplicate;
962   st->operatortypes = node_operatortypes;
963   st->keymap = node_keymap;
964   st->listener = node_area_listener;
965   st->refresh = node_area_refresh;
966   st->context = node_context;
967   st->dropboxes = node_dropboxes;
968   st->gizmos = node_widgets;
969   st->id_remap = node_id_remap;
970   st->space_subtype_item_extend = node_space_subtype_item_extend;
971   st->space_subtype_get = node_space_subtype_get;
972   st->space_subtype_set = node_space_subtype_set;
973
974   /* regions: main window */
975   art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
976   art->regionid = RGN_TYPE_WINDOW;
977   art->init = node_main_region_init;
978   art->draw = node_main_region_draw;
979   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_VIEW2D |
980                     ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
981   art->listener = node_region_listener;
982   art->cursor = node_cursor;
983   art->event_cursor = true;
984
985   BLI_addhead(&st->regiontypes, art);
986
987   /* regions: header */
988   art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
989   art->regionid = RGN_TYPE_HEADER;
990   art->prefsizey = HEADERY;
991   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
992   art->listener = node_region_listener;
993   art->init = node_header_region_init;
994   art->draw = node_header_region_draw;
995
996   BLI_addhead(&st->regiontypes, art);
997
998   /* regions: listview/buttons */
999   art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
1000   art->regionid = RGN_TYPE_UI;
1001   art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
1002   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1003   art->listener = node_region_listener;
1004   art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui;
1005   art->init = node_buttons_region_init;
1006   art->draw = node_buttons_region_draw;
1007   BLI_addhead(&st->regiontypes, art);
1008
1009   node_buttons_register(art);
1010
1011   /* regions: toolbar */
1012   art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
1013   art->regionid = RGN_TYPE_TOOLS;
1014   art->prefsizex = 58; /* XXX */
1015   art->prefsizey = 50; /* XXX */
1016   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1017   art->listener = node_region_listener;
1018   art->message_subscribe = ED_region_generic_tools_region_message_subscribe;
1019   art->snap_size = ED_region_generic_tools_region_snap_size;
1020   art->init = node_toolbar_region_init;
1021   art->draw = node_toolbar_region_draw;
1022   BLI_addhead(&st->regiontypes, art);
1023
1024   node_toolbar_register(art);
1025
1026   BKE_spacetype_register(st);
1027 }