52dab2a44a8393eb7699e4f84bb3932cbcee31cd
[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 /* ******************** manage regions ********************* */
246
247 ARegion *node_has_buttons_region(ScrArea *sa)
248 {
249   ARegion *ar, *arnew;
250
251   ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
252   if (ar) {
253     return ar;
254   }
255
256   /* add subdiv level; after header */
257   ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
258
259   /* is error! */
260   if (ar == NULL) {
261     return NULL;
262   }
263
264   arnew = MEM_callocN(sizeof(ARegion), "buttons for node");
265
266   BLI_insertlinkafter(&sa->regionbase, ar, arnew);
267   arnew->regiontype = RGN_TYPE_UI;
268   arnew->alignment = RGN_ALIGN_RIGHT;
269
270   arnew->flag = RGN_FLAG_HIDDEN;
271
272   return arnew;
273 }
274
275 ARegion *node_has_tools_region(ScrArea *sa)
276 {
277   ARegion *ar, *arnew;
278
279   ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
280   if (ar) {
281     return ar;
282   }
283
284   /* add subdiv level; after header */
285   ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
286
287   /* is error! */
288   if (ar == NULL) {
289     return NULL;
290   }
291
292   arnew = MEM_callocN(sizeof(ARegion), "node tools");
293
294   BLI_insertlinkafter(&sa->regionbase, ar, arnew);
295   arnew->regiontype = RGN_TYPE_TOOLS;
296   arnew->alignment = RGN_ALIGN_LEFT;
297
298   arnew->flag = RGN_FLAG_HIDDEN;
299
300   return arnew;
301 }
302
303 /* ******************** default callbacks for node space ***************** */
304
305 static SpaceLink *node_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
306 {
307   ARegion *ar;
308   SpaceNode *snode;
309
310   snode = MEM_callocN(sizeof(SpaceNode), "initnode");
311   snode->spacetype = SPACE_NODE;
312
313   snode->flag = SNODE_SHOW_GPENCIL | SNODE_USE_ALPHA;
314
315   /* backdrop */
316   snode->zoom = 1.0f;
317
318   /* select the first tree type for valid type */
319   NODE_TREE_TYPES_BEGIN (treetype) {
320     strcpy(snode->tree_idname, treetype->idname);
321     break;
322   }
323   NODE_TREE_TYPES_END;
324
325   /* header */
326   ar = MEM_callocN(sizeof(ARegion), "header for node");
327
328   BLI_addtail(&snode->regionbase, ar);
329   ar->regiontype = RGN_TYPE_HEADER;
330   ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
331
332   /* buttons/list view */
333   ar = MEM_callocN(sizeof(ARegion), "buttons for node");
334
335   BLI_addtail(&snode->regionbase, ar);
336   ar->regiontype = RGN_TYPE_UI;
337   ar->alignment = RGN_ALIGN_RIGHT;
338
339   /* toolbar */
340   ar = MEM_callocN(sizeof(ARegion), "node tools");
341
342   BLI_addtail(&snode->regionbase, ar);
343   ar->regiontype = RGN_TYPE_TOOLS;
344   ar->alignment = RGN_ALIGN_LEFT;
345
346   ar->flag = RGN_FLAG_HIDDEN;
347
348   /* main region */
349   ar = MEM_callocN(sizeof(ARegion), "main region for node");
350
351   BLI_addtail(&snode->regionbase, ar);
352   ar->regiontype = RGN_TYPE_WINDOW;
353
354   ar->v2d.tot.xmin = -12.8f * U.widget_unit;
355   ar->v2d.tot.ymin = -12.8f * U.widget_unit;
356   ar->v2d.tot.xmax = 38.4f * U.widget_unit;
357   ar->v2d.tot.ymax = 38.4f * U.widget_unit;
358
359   ar->v2d.cur = ar->v2d.tot;
360
361   ar->v2d.min[0] = 1.0f;
362   ar->v2d.min[1] = 1.0f;
363
364   ar->v2d.max[0] = 32000.0f;
365   ar->v2d.max[1] = 32000.0f;
366
367   ar->v2d.minzoom = 0.09f;
368   ar->v2d.maxzoom = 2.31f;
369
370   ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
371   ar->v2d.keepzoom = V2D_LIMITZOOM | V2D_KEEPASPECT;
372   ar->v2d.keeptot = 0;
373
374   return (SpaceLink *)snode;
375 }
376
377 static void node_free(SpaceLink *sl)
378 {
379   SpaceNode *snode = (SpaceNode *)sl;
380   bNodeTreePath *path, *path_next;
381
382   for (path = snode->treepath.first; path; path = path_next) {
383     path_next = path->next;
384     MEM_freeN(path);
385   }
386 }
387
388 /* spacetype; init callback */
389 static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
390 {
391 }
392
393 static void node_area_listener(wmWindow *UNUSED(win),
394                                ScrArea *sa,
395                                wmNotifier *wmn,
396                                Scene *UNUSED(scene))
397 {
398   /* note, ED_area_tag_refresh will re-execute compositor */
399   SpaceNode *snode = sa->spacedata.first;
400   /* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */
401   short shader_type = snode->shaderfrom;
402
403   /* preview renders */
404   switch (wmn->category) {
405     case NC_SCENE:
406       switch (wmn->data) {
407         case ND_NODES: {
408           ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
409           bNodeTreePath *path = snode->treepath.last;
410           /* shift view to node tree center */
411           if (ar && path) {
412             UI_view2d_center_set(&ar->v2d, path->view_center[0], path->view_center[1]);
413           }
414
415           ED_area_tag_refresh(sa);
416           break;
417         }
418         case ND_FRAME:
419           ED_area_tag_refresh(sa);
420           break;
421         case ND_COMPO_RESULT:
422           ED_area_tag_redraw(sa);
423           break;
424         case ND_TRANSFORM_DONE:
425           if (ED_node_is_compositor(snode)) {
426             if (snode->flag & SNODE_AUTO_RENDER) {
427               snode->recalc = 1;
428               ED_area_tag_refresh(sa);
429             }
430           }
431           break;
432         case ND_LAYER_CONTENT:
433           ED_area_tag_refresh(sa);
434           break;
435       }
436       break;
437
438     /* future: add ID checks? */
439     case NC_MATERIAL:
440       if (ED_node_is_shader(snode)) {
441         if (wmn->data == ND_SHADING) {
442           ED_area_tag_refresh(sa);
443         }
444         else if (wmn->data == ND_SHADING_DRAW) {
445           ED_area_tag_refresh(sa);
446         }
447         else if (wmn->data == ND_SHADING_LINKS) {
448           ED_area_tag_refresh(sa);
449         }
450         else if (wmn->action == NA_ADDED && snode->edittree) {
451           nodeSetActiveID(snode->edittree, ID_MA, wmn->reference);
452         }
453       }
454       break;
455     case NC_TEXTURE:
456       if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) {
457         if (wmn->data == ND_NODES) {
458           ED_area_tag_refresh(sa);
459         }
460       }
461       break;
462     case NC_WORLD:
463       if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) {
464         ED_area_tag_refresh(sa);
465       }
466       break;
467     case NC_OBJECT:
468       if (ED_node_is_shader(snode)) {
469         if (wmn->data == ND_OB_SHADING) {
470           ED_area_tag_refresh(sa);
471         }
472       }
473       break;
474     case NC_SPACE:
475       if (wmn->data == ND_SPACE_NODE) {
476         ED_area_tag_refresh(sa);
477       }
478       else if (wmn->data == ND_SPACE_NODE_VIEW) {
479         ED_area_tag_redraw(sa);
480       }
481       break;
482     case NC_NODE:
483       if (wmn->action == NA_EDITED) {
484         ED_area_tag_refresh(sa);
485       }
486       else if (wmn->action == NA_SELECTED) {
487         ED_area_tag_redraw(sa);
488       }
489       break;
490     case NC_SCREEN:
491       switch (wmn->data) {
492         case ND_ANIMPLAY:
493           ED_area_tag_refresh(sa);
494           break;
495       }
496       break;
497     case NC_MASK:
498       if (wmn->action == NA_EDITED) {
499         if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) {
500           ED_area_tag_refresh(sa);
501         }
502       }
503       break;
504
505     case NC_IMAGE:
506       if (wmn->action == NA_EDITED) {
507         if (ED_node_is_compositor(snode)) {
508           /* note that nodeUpdateID is already called by BKE_image_signal() on all
509            * scenes so really this is just to know if the images is used in the compo else
510            * painting on images could become very slow when the compositor is open. */
511           if (nodeUpdateID(snode->nodetree, wmn->reference)) {
512             ED_area_tag_refresh(sa);
513           }
514         }
515       }
516       break;
517
518     case NC_MOVIECLIP:
519       if (wmn->action == NA_EDITED) {
520         if (ED_node_is_compositor(snode)) {
521           if (nodeUpdateID(snode->nodetree, wmn->reference)) {
522             ED_area_tag_refresh(sa);
523           }
524         }
525       }
526       break;
527
528     case NC_LINESTYLE:
529       if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_LINESTYLE) {
530         ED_area_tag_refresh(sa);
531       }
532       break;
533     case NC_WM:
534       if (wmn->data == ND_UNDO) {
535         ED_area_tag_refresh(sa);
536       }
537       break;
538     case NC_GPENCIL:
539       if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
540         ED_area_tag_redraw(sa);
541       }
542       break;
543   }
544 }
545
546 static void node_area_refresh(const struct bContext *C, ScrArea *sa)
547 {
548   /* default now: refresh node is starting preview */
549   SpaceNode *snode = sa->spacedata.first;
550
551   snode_set_context(C);
552
553   if (snode->nodetree) {
554     if (snode->nodetree->type == NTREE_SHADER) {
555       if (GS(snode->id->name) == ID_MA) {
556         Material *ma = (Material *)snode->id;
557         if (ma->use_nodes) {
558           ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
559         }
560       }
561       else if (GS(snode->id->name) == ID_LA) {
562         Light *la = (Light *)snode->id;
563         if (la->use_nodes) {
564           ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
565         }
566       }
567       else if (GS(snode->id->name) == ID_WO) {
568         World *wo = (World *)snode->id;
569         if (wo->use_nodes) {
570           ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
571         }
572       }
573     }
574     else if (snode->nodetree->type == NTREE_COMPOSIT) {
575       Scene *scene = (Scene *)snode->id;
576       if (scene->use_nodes) {
577         /* recalc is set on 3d view changes for auto compo */
578         if (snode->recalc) {
579           snode->recalc = 0;
580           node_render_changed_exec((struct bContext *)C, NULL);
581         }
582         else {
583           ED_node_composite_job(C, snode->nodetree, scene);
584         }
585       }
586     }
587     else if (snode->nodetree->type == NTREE_TEXTURE) {
588       Tex *tex = (Tex *)snode->id;
589       if (tex->use_nodes) {
590         ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
591       }
592     }
593   }
594 }
595
596 static SpaceLink *node_duplicate(SpaceLink *sl)
597 {
598   SpaceNode *snode = (SpaceNode *)sl;
599   SpaceNode *snoden = MEM_dupallocN(snode);
600
601   BLI_duplicatelist(&snoden->treepath, &snode->treepath);
602
603   /* clear or remove stuff from old */
604   BLI_listbase_clear(&snoden->linkdrag);
605
606   /* Note: no need to set node tree user counts,
607    * the editor only keeps at least 1 (id_us_ensure_real),
608    * which is already done by the original SpaceNode.
609    */
610
611   return (SpaceLink *)snoden;
612 }
613
614 /* add handlers, stuff you only do once or on area/region changes */
615 static void node_buttons_region_init(wmWindowManager *wm, ARegion *ar)
616 {
617   wmKeyMap *keymap;
618
619   ED_region_panels_init(wm, ar);
620
621   keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
622   WM_event_add_keymap_handler(&ar->handlers, keymap);
623 }
624
625 static void node_buttons_region_draw(const bContext *C, ARegion *ar)
626 {
627   ED_region_panels(C, ar);
628 }
629
630 /* add handlers, stuff you only do once or on area/region changes */
631 static void node_toolbar_region_init(wmWindowManager *wm, ARegion *ar)
632 {
633   wmKeyMap *keymap;
634
635   ED_region_panels_init(wm, ar);
636
637   keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
638   WM_event_add_keymap_handler(&ar->handlers, keymap);
639 }
640
641 static void node_toolbar_region_draw(const bContext *C, ARegion *ar)
642 {
643   ED_region_panels(C, ar);
644 }
645
646 static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
647 {
648   SpaceNode *snode = sa->spacedata.first;
649
650   /* convert mouse coordinates to v2d space */
651   UI_view2d_region_to_view(&ar->v2d,
652                            win->eventstate->x - ar->winrct.xmin,
653                            win->eventstate->y - ar->winrct.ymin,
654                            &snode->cursor[0],
655                            &snode->cursor[1]);
656
657   /* here snode->cursor is used to detect the node edge for sizing */
658   node_set_cursor(win, snode, snode->cursor);
659
660   /* XXX snode->cursor is in placing new nodes space */
661   snode->cursor[0] /= UI_DPI_FAC;
662   snode->cursor[1] /= UI_DPI_FAC;
663 }
664
665 /* Initialize main region, setting handlers. */
666 static void node_main_region_init(wmWindowManager *wm, ARegion *ar)
667 {
668   wmKeyMap *keymap;
669   ListBase *lb;
670
671   UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
672
673   /* own keymaps */
674   keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
675   WM_event_add_keymap_handler(&ar->handlers, keymap);
676
677   keymap = WM_keymap_ensure(wm->defaultconf, "Node Editor", SPACE_NODE, 0);
678   WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
679
680   /* add drop boxes */
681   lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
682
683   WM_event_add_dropbox_handler(&ar->handlers, lb);
684 }
685
686 static void node_main_region_draw(const bContext *C, ARegion *ar)
687 {
688   drawnodespace(C, ar);
689 }
690
691 /* ************* dropboxes ************* */
692
693 static bool node_ima_drop_poll(bContext *UNUSED(C),
694                                wmDrag *drag,
695                                const wmEvent *UNUSED(event),
696                                const char **UNUSED(tooltip))
697 {
698   if (drag->type == WM_DRAG_PATH) {
699     /* rule might not work? */
700     return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE));
701   }
702   else {
703     return WM_drag_ID(drag, ID_IM) != NULL;
704   }
705 }
706
707 static bool node_mask_drop_poll(bContext *UNUSED(C),
708                                 wmDrag *drag,
709                                 const wmEvent *UNUSED(event),
710                                 const char **UNUSED(tooltip))
711 {
712   return WM_drag_ID(drag, ID_MSK) != NULL;
713 }
714
715 static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop)
716 {
717   ID *id = WM_drag_ID(drag, 0);
718
719   RNA_string_set(drop->ptr, "name", id->name + 2);
720 }
721
722 static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
723 {
724   ID *id = WM_drag_ID(drag, 0);
725
726   if (id) {
727     RNA_string_set(drop->ptr, "name", id->name + 2);
728     RNA_struct_property_unset(drop->ptr, "filepath");
729   }
730   else if (drag->path[0]) {
731     RNA_string_set(drop->ptr, "filepath", drag->path);
732     RNA_struct_property_unset(drop->ptr, "name");
733   }
734 }
735
736 /* this region dropbox definition */
737 static void node_dropboxes(void)
738 {
739   ListBase *lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
740
741   WM_dropbox_add(lb, "NODE_OT_add_file", node_ima_drop_poll, node_id_path_drop_copy);
742   WM_dropbox_add(lb, "NODE_OT_add_mask", node_mask_drop_poll, node_id_drop_copy);
743 }
744
745 /* ************* end drop *********** */
746
747 /* add handlers, stuff you only do once or on area/region changes */
748 static void node_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
749 {
750   ED_region_header_init(ar);
751 }
752
753 static void node_header_region_draw(const bContext *C, ARegion *ar)
754 {
755   /* find and set the context */
756   snode_set_context(C);
757
758   ED_region_header(C, ar);
759 }
760
761 /* used for header + main region */
762 static void node_region_listener(wmWindow *UNUSED(win),
763                                  ScrArea *UNUSED(sa),
764                                  ARegion *ar,
765                                  wmNotifier *wmn,
766                                  const Scene *UNUSED(scene))
767 {
768   wmGizmoMap *gzmap = ar->gizmo_map;
769
770   /* context changes */
771   switch (wmn->category) {
772     case NC_SPACE:
773       switch (wmn->data) {
774         case ND_SPACE_NODE:
775           ED_region_tag_redraw(ar);
776           break;
777         case ND_SPACE_NODE_VIEW:
778           WM_gizmomap_tag_refresh(gzmap);
779           break;
780       }
781       break;
782     case NC_SCREEN:
783       if (wmn->data == ND_LAYOUTSET || wmn->action == NA_EDITED) {
784         WM_gizmomap_tag_refresh(gzmap);
785       }
786       switch (wmn->data) {
787         case ND_ANIMPLAY:
788         case ND_LAYER:
789           ED_region_tag_redraw(ar);
790           break;
791       }
792       break;
793     case NC_WM:
794       if (wmn->data == ND_JOB) {
795         ED_region_tag_redraw(ar);
796       }
797       break;
798     case NC_SCENE:
799       ED_region_tag_redraw(ar);
800       if (wmn->data == ND_RENDER_RESULT) {
801         WM_gizmomap_tag_refresh(gzmap);
802       }
803       break;
804     case NC_NODE:
805       ED_region_tag_redraw(ar);
806       if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
807         WM_gizmomap_tag_refresh(gzmap);
808       }
809       break;
810     case NC_MATERIAL:
811     case NC_TEXTURE:
812     case NC_WORLD:
813     case NC_LINESTYLE:
814       ED_region_tag_redraw(ar);
815       break;
816     case NC_OBJECT:
817       if (wmn->data == ND_OB_SHADING) {
818         ED_region_tag_redraw(ar);
819       }
820       break;
821     case NC_ID:
822       if (wmn->action == NA_RENAME) {
823         ED_region_tag_redraw(ar);
824       }
825       break;
826     case NC_GPENCIL:
827       if (wmn->action == NA_EDITED) {
828         ED_region_tag_redraw(ar);
829       }
830       else if (wmn->data & ND_GPENCIL_EDITMODE) {
831         ED_region_tag_redraw(ar);
832       }
833       break;
834   }
835 }
836
837 const char *node_context_dir[] = {
838     "selected_nodes", "active_node", "light", "material", "world", NULL};
839
840 static int node_context(const bContext *C, const char *member, bContextDataResult *result)
841 {
842   SpaceNode *snode = CTX_wm_space_node(C);
843
844   if (CTX_data_dir(member)) {
845     CTX_data_dir_set(result, node_context_dir);
846     return 1;
847   }
848   else if (CTX_data_equals(member, "selected_nodes")) {
849     bNode *node;
850
851     if (snode->edittree) {
852       for (node = snode->edittree->nodes.last; node; node = node->prev) {
853         if (node->flag & NODE_SELECT) {
854           CTX_data_list_add(result, &snode->edittree->id, &RNA_Node, node);
855         }
856       }
857     }
858     CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
859     return 1;
860   }
861   else if (CTX_data_equals(member, "active_node")) {
862     if (snode->edittree) {
863       bNode *node = nodeGetActive(snode->edittree);
864       CTX_data_pointer_set(result, &snode->edittree->id, &RNA_Node, node);
865     }
866
867     CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
868     return 1;
869   }
870   else if (CTX_data_equals(member, "node_previews")) {
871     if (snode->nodetree) {
872       CTX_data_pointer_set(
873           result, &snode->nodetree->id, &RNA_NodeInstanceHash, snode->nodetree->previews);
874     }
875
876     CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
877     return 1;
878   }
879   else if (CTX_data_equals(member, "material")) {
880     if (snode->id && GS(snode->id->name) == ID_MA) {
881       CTX_data_id_pointer_set(result, snode->id);
882     }
883     return 1;
884   }
885   else if (CTX_data_equals(member, "light")) {
886     if (snode->id && GS(snode->id->name) == ID_LA) {
887       CTX_data_id_pointer_set(result, snode->id);
888     }
889     return 1;
890   }
891   else if (CTX_data_equals(member, "world")) {
892     if (snode->id && GS(snode->id->name) == ID_WO) {
893       CTX_data_id_pointer_set(result, snode->id);
894     }
895     return 1;
896   }
897
898   return 0;
899 }
900
901 static void node_widgets(void)
902 {
903   /* create the widgetmap for the area here */
904   wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(
905       &(const struct wmGizmoMapType_Params){SPACE_NODE, RGN_TYPE_WINDOW});
906   WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_transform);
907   WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_crop);
908   WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_sun_beams);
909   WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_corner_pin);
910 }
911
912 static void node_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
913 {
914   SpaceNode *snode = (SpaceNode *)slink;
915
916   if (GS(old_id->name) == ID_SCE) {
917     if (snode->id == old_id) {
918       /* nasty DNA logic for SpaceNode:
919        * ideally should be handled by editor code, but would be bad level call
920        */
921       BLI_freelistN(&snode->treepath);
922
923       /* XXX Untested in case new_id != NULL... */
924       snode->id = new_id;
925       snode->from = NULL;
926       snode->nodetree = NULL;
927       snode->edittree = NULL;
928     }
929   }
930   else if (GS(old_id->name) == ID_OB) {
931     if (snode->from == old_id) {
932       if (new_id == NULL) {
933         snode->flag &= ~SNODE_PIN;
934       }
935       snode->from = new_id;
936     }
937   }
938   else if (GS(old_id->name) == ID_GD) {
939     if ((ID *)snode->gpd == old_id) {
940       snode->gpd = (bGPdata *)new_id;
941       id_us_min(old_id);
942       id_us_plus(new_id);
943     }
944   }
945   else if (GS(old_id->name) == ID_NT) {
946     bNodeTreePath *path, *path_next;
947
948     for (path = snode->treepath.first; path; path = path->next) {
949       if ((ID *)path->nodetree == old_id) {
950         path->nodetree = (bNodeTree *)new_id;
951         id_us_min(old_id);
952         id_us_plus(new_id);
953       }
954       if (path == snode->treepath.first) {
955         /* first nodetree in path is same as snode->nodetree */
956         snode->nodetree = path->nodetree;
957       }
958       if (path->nodetree == NULL) {
959         break;
960       }
961     }
962
963     /* remaining path entries are invalid, remove */
964     for (; path; path = path_next) {
965       path_next = path->next;
966
967       BLI_remlink(&snode->treepath, path);
968       MEM_freeN(path);
969     }
970
971     /* edittree is just the last in the path,
972      * set this directly since the path may have been shortened above */
973     if (snode->treepath.last) {
974       path = snode->treepath.last;
975       snode->edittree = path->nodetree;
976     }
977     else {
978       snode->edittree = NULL;
979     }
980   }
981 }
982
983 static int node_space_subtype_get(ScrArea *sa)
984 {
985   SpaceNode *snode = sa->spacedata.first;
986   return rna_node_tree_idname_to_enum(snode->tree_idname);
987 }
988
989 static void node_space_subtype_set(ScrArea *sa, int value)
990 {
991   SpaceNode *snode = sa->spacedata.first;
992   ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value));
993 }
994
995 static void node_space_subtype_item_extend(bContext *C, EnumPropertyItem **item, int *totitem)
996 {
997   bool free;
998   const EnumPropertyItem *item_src = RNA_enum_node_tree_types_itemf_impl(C, &free);
999   for (const EnumPropertyItem *item_iter = item_src; item_iter->identifier; item_iter++) {
1000     RNA_enum_item_add(item, totitem, item_iter);
1001   }
1002   if (free) {
1003     MEM_freeN((void *)item_src);
1004   }
1005 }
1006
1007 /* only called once, from space/spacetypes.c */
1008 void ED_spacetype_node(void)
1009 {
1010   SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype node");
1011   ARegionType *art;
1012
1013   st->spaceid = SPACE_NODE;
1014   strncpy(st->name, "Node", BKE_ST_MAXNAME);
1015
1016   st->new = node_new;
1017   st->free = node_free;
1018   st->init = node_init;
1019   st->duplicate = node_duplicate;
1020   st->operatortypes = node_operatortypes;
1021   st->keymap = node_keymap;
1022   st->listener = node_area_listener;
1023   st->refresh = node_area_refresh;
1024   st->context = node_context;
1025   st->dropboxes = node_dropboxes;
1026   st->gizmos = node_widgets;
1027   st->id_remap = node_id_remap;
1028   st->space_subtype_item_extend = node_space_subtype_item_extend;
1029   st->space_subtype_get = node_space_subtype_get;
1030   st->space_subtype_set = node_space_subtype_set;
1031
1032   /* regions: main window */
1033   art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
1034   art->regionid = RGN_TYPE_WINDOW;
1035   art->init = node_main_region_init;
1036   art->draw = node_main_region_draw;
1037   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_VIEW2D |
1038                     ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
1039   art->listener = node_region_listener;
1040   art->cursor = node_cursor;
1041   art->event_cursor = true;
1042
1043   BLI_addhead(&st->regiontypes, art);
1044
1045   /* regions: header */
1046   art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
1047   art->regionid = RGN_TYPE_HEADER;
1048   art->prefsizey = HEADERY;
1049   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
1050   art->listener = node_region_listener;
1051   art->init = node_header_region_init;
1052   art->draw = node_header_region_draw;
1053
1054   BLI_addhead(&st->regiontypes, art);
1055
1056   /* regions: listview/buttons */
1057   art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
1058   art->regionid = RGN_TYPE_UI;
1059   art->prefsizex = 180;  // XXX
1060   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1061   art->listener = node_region_listener;
1062   art->init = node_buttons_region_init;
1063   art->draw = node_buttons_region_draw;
1064   BLI_addhead(&st->regiontypes, art);
1065
1066   node_buttons_register(art);
1067
1068   /* regions: toolbar */
1069   art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
1070   art->regionid = RGN_TYPE_TOOLS;
1071   art->prefsizex = 58; /* XXX */
1072   art->prefsizey = 50; /* XXX */
1073   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1074   art->listener = node_region_listener;
1075   art->message_subscribe = ED_region_generic_tools_region_message_subscribe;
1076   art->snap_size = ED_region_generic_tools_region_snap_size;
1077   art->init = node_toolbar_region_init;
1078   art->draw = node_toolbar_region_draw;
1079   BLI_addhead(&st->regiontypes, art);
1080
1081   node_toolbar_register(art);
1082
1083   BKE_spacetype_register(st);
1084 }