Fix for #34739 and #35060, avoid ambiguity in compositor viewer nodes.
[blender.git] / source / blender / editors / space_node / space_node.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_node/space_node.c
28  *  \ingroup spnode
29  */
30
31
32
33 #include "DNA_lamp_types.h"
34 #include "DNA_material_types.h"
35 #include "DNA_node_types.h"
36 #include "DNA_world_types.h"
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_math.h"
42
43 #include "BKE_context.h"
44 #include "BKE_screen.h"
45 #include "BKE_node.h"
46
47 #include "ED_space_api.h"
48 #include "ED_node.h"
49 #include "ED_render.h"
50 #include "ED_screen.h"
51 #include "ED_node.h"
52 #include "WM_api.h"
53 #include "WM_types.h"
54
55 #include "UI_resources.h"
56 #include "UI_view2d.h"
57
58 #include "RNA_access.h"
59
60 #include "node_intern.h"  /* own include */
61
62
63 /* ******************** tree path ********************* */
64
65 void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from)
66 {
67         bNodeTreePath *path, *path_next;
68         for (path = snode->treepath.first; path; path = path_next) {
69                 path_next = path->next;
70                 MEM_freeN(path);
71         }
72         snode->treepath.first = snode->treepath.last = NULL;
73         
74         if (ntree) {
75                 path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
76                 path->nodetree = ntree;
77                 path->parent_key = NODE_INSTANCE_KEY_BASE;
78                 
79                 /* copy initial offset from bNodeTree */
80                 copy_v2_v2(path->view_center, ntree->view_center);
81                 
82                 if (id)
83                         BLI_strncpy(path->node_name, id->name + 2, sizeof(path->node_name));
84                 
85                 BLI_addtail(&snode->treepath, path);
86         }
87         
88         /* update current tree */
89         snode->nodetree = snode->edittree = ntree;
90         snode->id = id;
91         snode->from = from;
92         
93         ED_node_set_active_viewer_key(snode);
94         
95         WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
96 }
97
98 void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
99 {
100         bNodeTreePath *path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
101         bNodeTreePath *prev_path = snode->treepath.last;
102         path->nodetree = ntree;
103         if (gnode) {
104                 if (prev_path)
105                         path->parent_key = BKE_node_instance_key(prev_path->parent_key, prev_path->nodetree, gnode);
106                 else
107                         path->parent_key = NODE_INSTANCE_KEY_BASE;
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         /* copy initial offset from bNodeTree */
115         copy_v2_v2(path->view_center, ntree->view_center);
116         
117         BLI_addtail(&snode->treepath, path);
118         
119         /* update current tree */
120         snode->edittree = ntree;
121         
122         ED_node_set_active_viewer_key(snode);
123         
124         WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
125 }
126
127 void ED_node_tree_pop(SpaceNode *snode)
128 {
129         bNodeTreePath *path = snode->treepath.last;
130         
131         /* don't remove root */
132         if (path == snode->treepath.first)
133                 return;
134         
135         BLI_remlink(&snode->treepath, path);
136         MEM_freeN(path);
137         
138         /* update current tree */
139         path = snode->treepath.last;
140         snode->edittree = path->nodetree;
141         
142         ED_node_set_active_viewer_key(snode);
143         
144         /* listener updates the View2D center from edittree */
145         WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
146 }
147
148 int ED_node_tree_depth(SpaceNode *snode)
149 {
150         return BLI_countlist(&snode->treepath);
151 }
152
153 bNodeTree *ED_node_tree_get(SpaceNode *snode, int level)
154 {
155         bNodeTreePath *path;
156         int i;
157         for (path = snode->treepath.last, i = 0; path; path = path->prev, ++i) {
158                 if (i == level)
159                         return path->nodetree;
160         }
161         return NULL;
162 }
163
164 int ED_node_tree_path_length(SpaceNode *snode)
165 {
166         bNodeTreePath *path;
167         int length = 0;
168         int i;
169         for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
170                 length += strlen(path->node_name);
171                 if (i > 0)
172                         length += 1;    /* for separator char */
173         }
174         return length;
175 }
176
177 void ED_node_tree_path_get(SpaceNode *snode, char *value)
178 {
179         bNodeTreePath *path;
180         int i;
181         
182         value[0] = '\0';
183         for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
184                 if (i == 0) {
185                         strcpy(value, path->node_name);
186                         value += strlen(path->node_name);
187                 }
188                 else {
189                         sprintf(value, "/%s", path->node_name);
190                         value += strlen(path->node_name) + 1;
191                 }
192         }
193 }
194
195 void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_length)
196 {
197         bNodeTreePath *path;
198         int size, i;
199         
200         value[0] = '\0';
201         for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
202                 if (i == 0) {
203                         BLI_strncpy(value, path->node_name, max_length);
204                         size = strlen(path->node_name);
205                 }
206                 else {
207                         BLI_snprintf(value, max_length, "/%s", path->node_name);
208                         size = strlen(path->node_name) + 1;
209                 }
210                 max_length -= size;
211                 if (max_length <= 0)
212                         break;
213                 value += size;
214         }
215 }
216
217 void ED_node_set_active_viewer_key(SpaceNode *snode)
218 {
219         bNodeTreePath *path = snode->treepath.last;
220         if (snode->nodetree && path) {
221                 snode->nodetree->active_viewer_key = path->parent_key;
222         }
223 }
224
225 void snode_group_offset(SpaceNode *snode, float *x, float *y)
226 {
227         bNodeTreePath *path = snode->treepath.last;
228         
229         if (path && path->prev) {
230                 float dcenter[2];
231                 sub_v2_v2v2(dcenter, path->view_center, path->prev->view_center);
232                 *x = dcenter[0];
233                 *y = dcenter[1];
234         }
235         else
236                 *x = *y = 0.0f;
237 }
238
239 /* ******************** manage regions ********************* */
240
241 ARegion *node_has_buttons_region(ScrArea *sa)
242 {
243         ARegion *ar, *arnew;
244
245         ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
246         if (ar) return ar;
247
248         /* add subdiv level; after header */
249         ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
250
251         /* is error! */
252         if (ar == NULL) return NULL;
253
254         arnew = MEM_callocN(sizeof(ARegion), "buttons for node");
255
256         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
257         arnew->regiontype = RGN_TYPE_UI;
258         arnew->alignment = RGN_ALIGN_RIGHT;
259
260         arnew->flag = RGN_FLAG_HIDDEN;
261
262         return arnew;
263 }
264
265 ARegion *node_has_tools_region(ScrArea *sa)
266 {
267         ARegion *ar, *arnew;
268         
269         ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
270         if (ar) return ar;
271         
272         /* add subdiv level; after header */
273         ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
274         
275         /* is error! */
276         if (ar == NULL) return NULL;
277         
278         arnew = MEM_callocN(sizeof(ARegion), "node tools");
279         
280         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
281         arnew->regiontype = RGN_TYPE_TOOLS;
282         arnew->alignment = RGN_ALIGN_LEFT;
283         
284         arnew->flag = RGN_FLAG_HIDDEN;
285         
286         return arnew;
287 }
288
289 /* ******************** default callbacks for node space ***************** */
290
291 static SpaceLink *node_new(const bContext *UNUSED(C))
292 {
293         ARegion *ar;
294         SpaceNode *snode;
295
296         snode = MEM_callocN(sizeof(SpaceNode), "initnode");
297         snode->spacetype = SPACE_NODE;
298
299         snode->flag = SNODE_SHOW_GPENCIL | SNODE_USE_ALPHA;
300
301         /* backdrop */
302         snode->zoom = 1.0f;
303
304         /* select the first tree type for valid type */
305         NODE_TREE_TYPES_BEGIN(treetype)
306                 strcpy(snode->tree_idname, treetype->idname);
307                 break;
308         NODE_TREE_TYPES_END
309
310         /* header */
311         ar = MEM_callocN(sizeof(ARegion), "header for node");
312
313         BLI_addtail(&snode->regionbase, ar);
314         ar->regiontype = RGN_TYPE_HEADER;
315         ar->alignment = RGN_ALIGN_BOTTOM;
316
317         /* buttons/list view */
318         ar = MEM_callocN(sizeof(ARegion), "buttons for node");
319
320         BLI_addtail(&snode->regionbase, ar);
321         ar->regiontype = RGN_TYPE_UI;
322         ar->alignment = RGN_ALIGN_RIGHT;
323
324         /* toolbar */
325         ar = MEM_callocN(sizeof(ARegion), "node tools");
326
327         BLI_addtail(&snode->regionbase, ar);
328         ar->regiontype = RGN_TYPE_TOOLS;
329         ar->alignment = RGN_ALIGN_LEFT;
330
331         ar->flag = RGN_FLAG_HIDDEN;
332
333         /* main area */
334         ar = MEM_callocN(sizeof(ARegion), "main area for node");
335
336         BLI_addtail(&snode->regionbase, ar);
337         ar->regiontype = RGN_TYPE_WINDOW;
338
339         ar->v2d.tot.xmin =  -12.8f * U.widget_unit;
340         ar->v2d.tot.ymin =  -12.8f * U.widget_unit;
341         ar->v2d.tot.xmax = 38.4f * U.widget_unit;
342         ar->v2d.tot.ymax = 38.4f * U.widget_unit;
343
344         ar->v2d.cur =  ar->v2d.tot;
345
346         ar->v2d.min[0] = 1.0f;
347         ar->v2d.min[1] = 1.0f;
348
349         ar->v2d.max[0] = 32000.0f;
350         ar->v2d.max[1] = 32000.0f;
351
352         ar->v2d.minzoom = 0.09f;
353         ar->v2d.maxzoom = 2.31f;
354
355         ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
356         ar->v2d.keepzoom = V2D_LIMITZOOM | V2D_KEEPASPECT;
357         ar->v2d.keeptot = 0;
358
359         return (SpaceLink *)snode;
360 }
361
362 static void node_free(SpaceLink *sl)
363 {
364         SpaceNode *snode = (SpaceNode *)sl;
365         bNodeTreePath *path, *path_next;
366
367         for (path = snode->treepath.first; path; path = path_next) {
368                 path_next = path->next;
369                 MEM_freeN(path);
370         }
371 }
372
373
374 /* spacetype; init callback */
375 static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
376 {
377
378 }
379
380 static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
381 {
382         /* note, ED_area_tag_refresh will re-execute compositor */
383         SpaceNode *snode = sa->spacedata.first;
384         short shader_type = snode->shaderfrom;
385
386         /* preview renders */
387         switch (wmn->category) {
388                 case NC_SCENE:
389                         switch (wmn->data) {
390                                 case ND_NODES: {
391                                         ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
392                                         bNodeTreePath *path = snode->treepath.last;
393                                         /* shift view to node tree center */
394                                         if (ar && path)
395                                                 UI_view2d_setcenter(&ar->v2d, path->view_center[0], path->view_center[1]);
396                                         
397                                         ED_area_tag_refresh(sa);
398                                         break;
399                                 }
400                                 case ND_FRAME:
401                                         ED_area_tag_refresh(sa);
402                                         break;
403                                 case ND_COMPO_RESULT:
404                                         ED_area_tag_redraw(sa);
405                                         break;
406                                 case ND_TRANSFORM_DONE:
407                                         if (ED_node_is_compositor(snode)) {
408                                                 if (snode->flag & SNODE_AUTO_RENDER) {
409                                                         snode->recalc = 1;
410                                                         ED_area_tag_refresh(sa);
411                                                 }
412                                         }
413                                         break;
414                         }
415                         break;
416
417                 /* future: add ID checks? */
418                 case NC_MATERIAL:
419                         if (ED_node_is_shader(snode)) {
420                                 if (wmn->data == ND_SHADING)
421                                         ED_area_tag_refresh(sa);
422                                 else if (wmn->data == ND_SHADING_DRAW)
423                                         ED_area_tag_refresh(sa);
424                                 else if (wmn->data == ND_SHADING_LINKS)
425                                         ED_area_tag_refresh(sa);
426                                 else if (wmn->action == NA_ADDED && snode->edittree)
427                                         nodeSetActiveID(snode->edittree, ID_MA, wmn->reference);
428
429                         }
430                         break;
431                 case NC_TEXTURE:
432                         if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) {
433                                 if (wmn->data == ND_NODES)
434                                         ED_area_tag_refresh(sa);
435                         }
436                         break;
437                 case NC_WORLD:
438                         if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) {
439                                 ED_area_tag_refresh(sa);
440                         }
441                         break;
442                 case NC_OBJECT:
443                         if (ED_node_is_shader(snode)) {
444                                 if (wmn->data == ND_OB_SHADING)
445                                         ED_area_tag_refresh(sa);
446                         }
447                         break;
448                 case NC_SPACE:
449                         if (wmn->data == ND_SPACE_NODE)
450                                 ED_area_tag_refresh(sa);
451                         else if (wmn->data == ND_SPACE_NODE_VIEW)
452                                 ED_area_tag_redraw(sa);
453                         break;
454                 case NC_NODE:
455                         if (wmn->action == NA_EDITED)
456                                 ED_area_tag_refresh(sa);
457                         else if (wmn->action == NA_SELECTED)
458                                 ED_area_tag_redraw(sa);
459                         break;
460                 case NC_SCREEN:
461                         switch (wmn->data) {
462                                 case ND_ANIMPLAY:
463                                         ED_area_tag_refresh(sa);
464                                         break;
465                         }
466                         break;
467                 case NC_MASK:
468                         if (wmn->action == NA_EDITED) {
469                                 if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) {
470                                         ED_area_tag_refresh(sa);
471                                 }
472                         }
473                         break;
474
475                 case NC_IMAGE:
476                         if (wmn->action == NA_EDITED) {
477                                 if (ED_node_is_compositor(snode)) {
478                                         /* note that nodeUpdateID is already called by BKE_image_signal() on all
479                                          * scenes so really this is just to know if the images is used in the compo else
480                                          * painting on images could become very slow when the compositor is open. */
481                                         if (nodeUpdateID(snode->nodetree, wmn->reference))
482                                                 ED_area_tag_refresh(sa);
483                                 }
484                         }
485                         break;
486
487                 case NC_MOVIECLIP:
488                         if (wmn->action == NA_EDITED) {
489                                 if (ED_node_is_compositor(snode)) {
490                                         if (nodeUpdateID(snode->nodetree, wmn->reference))
491                                                 ED_area_tag_refresh(sa);
492                                 }
493                         }
494                         break;
495         }
496 }
497
498 static void node_area_refresh(const struct bContext *C, ScrArea *sa)
499 {
500         /* default now: refresh node is starting preview */
501         SpaceNode *snode = sa->spacedata.first;
502         
503         ED_preview_kill_jobs(C);
504         
505         snode_set_context(C);
506
507         if (snode->nodetree) {
508                 if (snode->nodetree->type == NTREE_SHADER) {
509                         if (GS(snode->id->name) == ID_MA) {
510                                 Material *ma = (Material *)snode->id;
511                                 if (ma->use_nodes)
512                                         ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
513                         }
514                         else if (GS(snode->id->name) == ID_LA) {
515                                 Lamp *la = (Lamp *)snode->id;
516                                 if (la->use_nodes)
517                                         ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
518                         }
519                         else if (GS(snode->id->name) == ID_WO) {
520                                 World *wo = (World *)snode->id;
521                                 if (wo->use_nodes)
522                                         ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
523                         }
524                 }
525                 else if (snode->nodetree->type == NTREE_COMPOSIT) {
526                         Scene *scene = (Scene *)snode->id;
527                         if (scene->use_nodes) {
528                                 /* recalc is set on 3d view changes for auto compo */
529                                 if (snode->recalc) {
530                                         snode->recalc = 0;
531                                         node_render_changed_exec((struct bContext *)C, NULL);
532                                 }
533                                 else {
534                                         ED_node_composite_job(C, snode->nodetree, scene);
535                                 }
536                         }
537                 }
538                 else if (snode->nodetree->type == NTREE_TEXTURE) {
539                         Tex *tex = (Tex *)snode->id;
540                         if (tex->use_nodes) {
541                                 ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
542                         }
543                 }
544         }
545 }
546
547 static SpaceLink *node_duplicate(SpaceLink *sl)
548 {
549         SpaceNode *snode = (SpaceNode *)sl;
550         SpaceNode *snoden = MEM_dupallocN(snode);
551
552         /* clear or remove stuff from old */
553         snoden->nodetree = NULL;
554         snoden->linkdrag.first = snoden->linkdrag.last = NULL;
555         
556         BLI_duplicatelist(&snoden->treepath, &snode->treepath);
557
558         return (SpaceLink *)snoden;
559 }
560
561
562 /* add handlers, stuff you only do once or on area/region changes */
563 static void node_buttons_area_init(wmWindowManager *wm, ARegion *ar)
564 {
565         wmKeyMap *keymap;
566
567         ED_region_panels_init(wm, ar);
568
569         keymap = WM_keymap_find(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
570         WM_event_add_keymap_handler(&ar->handlers, keymap);
571 }
572
573 static void node_buttons_area_draw(const bContext *C, ARegion *ar)
574 {
575         ED_region_panels(C, ar, 1, NULL, -1);
576 }
577
578 /* add handlers, stuff you only do once or on area/region changes */
579 static void node_toolbar_area_init(wmWindowManager *wm, ARegion *ar)
580 {
581         wmKeyMap *keymap;
582
583         ED_region_panels_init(wm, ar);
584
585         keymap = WM_keymap_find(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
586         WM_event_add_keymap_handler(&ar->handlers, keymap);
587 }
588
589 static void node_toolbar_area_draw(const bContext *C, ARegion *ar)
590 {
591         ED_region_panels(C, ar, 1, NULL, -1);
592 }
593
594 static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
595 {
596         SpaceNode *snode = sa->spacedata.first;
597
598         /* convert mouse coordinates to v2d space */
599         UI_view2d_region_to_view(&ar->v2d, win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin,
600                                  &snode->cursor[0], &snode->cursor[1]);
601
602         node_set_cursor(win, snode);
603 }
604
605 /* Initialize main area, setting handlers. */
606 static void node_main_area_init(wmWindowManager *wm, ARegion *ar)
607 {
608         wmKeyMap *keymap;
609         ListBase *lb;
610
611         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
612
613         /* own keymaps */
614         keymap = WM_keymap_find(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
615         WM_event_add_keymap_handler(&ar->handlers, keymap);
616
617         keymap = WM_keymap_find(wm->defaultconf, "Node Editor", SPACE_NODE, 0);
618         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
619
620         /* add drop boxes */
621         lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
622
623         WM_event_add_dropbox_handler(&ar->handlers, lb);
624 }
625
626 static void node_main_area_draw(const bContext *C, ARegion *ar)
627 {
628         drawnodespace(C, ar);
629 }
630
631
632 /* ************* dropboxes ************* */
633
634 static int node_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
635 {
636         if (drag->type == WM_DRAG_ID) {
637                 ID *id = (ID *)drag->poin;
638                 if (GS(id->name) == ID_IM)
639                         return 1;
640         }
641         else if (drag->type == WM_DRAG_PATH) {
642                 if (ELEM(drag->icon, 0, ICON_FILE_IMAGE))   /* rule might not work? */
643                         return 1;
644         }
645         return 0;
646 }
647
648 static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
649 {
650         ID *id = (ID *)drag->poin;
651
652         if (id) {
653                 RNA_string_set(drop->ptr, "name", id->name + 2);
654         }
655         if (drag->path[0]) {
656                 RNA_string_set(drop->ptr, "filepath", drag->path);
657         }
658 }
659
660 /* this region dropbox definition */
661 static void node_dropboxes(void)
662 {
663         ListBase *lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
664
665         WM_dropbox_add(lb, "NODE_OT_add_file", node_drop_poll, node_id_path_drop_copy);
666
667 }
668
669 /* ************* end drop *********** */
670
671
672 /* add handlers, stuff you only do once or on area/region changes */
673 static void node_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
674 {
675         ED_region_header_init(ar);
676 }
677
678 static void node_header_area_draw(const bContext *C, ARegion *ar)
679 {
680         /* find and set the context */
681         snode_set_context(C);
682
683         ED_region_header(C, ar);
684 }
685
686 /* used for header + main area */
687 static void node_region_listener(ARegion *ar, wmNotifier *wmn)
688 {
689         /* context changes */
690         switch (wmn->category) {
691                 case NC_SPACE:
692                         if (wmn->data == ND_SPACE_NODE)
693                                 ED_region_tag_redraw(ar);
694                         break;
695                 case NC_SCREEN:
696                         switch (wmn->data) {
697                                 case ND_SCREENCAST:
698                                 case ND_ANIMPLAY:
699                                         ED_region_tag_redraw(ar);
700                                         break;
701                         }
702                         break;
703                 case NC_SCENE:
704                 case NC_MATERIAL:
705                 case NC_TEXTURE:
706                 case NC_WORLD:
707                 case NC_NODE:
708                         ED_region_tag_redraw(ar);
709                         break;
710                 case NC_OBJECT:
711                         if (wmn->data == ND_OB_SHADING)
712                                 ED_region_tag_redraw(ar);
713                         break;
714                 case NC_ID:
715                         if (wmn->action == NA_RENAME)
716                                 ED_region_tag_redraw(ar);
717                         break;
718                 case NC_GPENCIL:
719                         if (wmn->action == NA_EDITED)
720                                 ED_region_tag_redraw(ar);
721                         break;
722         }
723 }
724
725 const char *node_context_dir[] = {"selected_nodes", "active_node", NULL};
726
727 static int node_context(const bContext *C, const char *member, bContextDataResult *result)
728 {
729         SpaceNode *snode = CTX_wm_space_node(C);
730
731         if (CTX_data_dir(member)) {
732                 CTX_data_dir_set(result, node_context_dir);
733                 return 1;
734         }
735         else if (CTX_data_equals(member, "selected_nodes")) {
736                 bNode *node;
737
738                 if (snode->edittree) {
739                         for (node = snode->edittree->nodes.last; node; node = node->prev) {
740                                 if (node->flag & NODE_SELECT) {
741                                         CTX_data_list_add(result, &snode->edittree->id, &RNA_Node, node);
742                                 }
743                         }
744                 }
745                 CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
746                 return 1;
747         }
748         else if (CTX_data_equals(member, "active_node")) {
749                 if (snode->edittree) {
750                         bNode *node = nodeGetActive(snode->edittree);
751                         CTX_data_pointer_set(result, &snode->edittree->id, &RNA_Node, node);
752                 }
753
754                 CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
755                 return 1;
756         }
757         else if (CTX_data_equals(member, "node_previews")) {
758                 if (snode->nodetree) {
759                         CTX_data_pointer_set(result, &snode->nodetree->id, &RNA_NodeInstanceHash, snode->nodetree->previews);
760                 }
761
762                 CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
763                 return 1;
764         }
765
766         return 0;
767 }
768
769 /* only called once, from space/spacetypes.c */
770 void ED_spacetype_node(void)
771 {
772         SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype node");
773         ARegionType *art;
774
775         st->spaceid = SPACE_NODE;
776         strncpy(st->name, "Node", BKE_ST_MAXNAME);
777
778         st->new = node_new;
779         st->free = node_free;
780         st->init = node_init;
781         st->duplicate = node_duplicate;
782         st->operatortypes = node_operatortypes;
783         st->keymap = node_keymap;
784         st->listener = node_area_listener;
785         st->refresh = node_area_refresh;
786         st->context = node_context;
787         st->dropboxes = node_dropboxes;
788
789         /* regions: main window */
790         art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
791         art->regionid = RGN_TYPE_WINDOW;
792         art->init = node_main_area_init;
793         art->draw = node_main_area_draw;
794         art->listener = node_region_listener;
795         art->cursor = node_cursor;
796         art->event_cursor = TRUE;
797         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
798
799         BLI_addhead(&st->regiontypes, art);
800
801         /* regions: header */
802         art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
803         art->regionid = RGN_TYPE_HEADER;
804         art->prefsizey = HEADERY;
805         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
806         art->listener = node_region_listener;
807         art->init = node_header_area_init;
808         art->draw = node_header_area_draw;
809
810         BLI_addhead(&st->regiontypes, art);
811
812         /* regions: listview/buttons */
813         art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
814         art->regionid = RGN_TYPE_UI;
815         art->prefsizex = 180; // XXX
816         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
817         art->listener = node_region_listener;
818         art->init = node_buttons_area_init;
819         art->draw = node_buttons_area_draw;
820         BLI_addhead(&st->regiontypes, art);
821
822         node_buttons_register(art);
823
824         /* regions: toolbar */
825         art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
826         art->regionid = RGN_TYPE_TOOLS;
827         art->prefsizex = 160; /* XXX */
828         art->prefsizey = 50; /* XXX */
829         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
830         art->listener = node_region_listener;
831         art->init = node_toolbar_area_init;
832         art->draw = node_toolbar_area_draw;
833         BLI_addhead(&st->regiontypes, art);
834         
835         node_toolbar_register(art);
836
837         BKE_spacetype_register(st);
838 }
839