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