Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / space_node / node_edit.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) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): David Millan Escriva, Juho Vepsäläinen, Nathan Letwory
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_node/node_edit.c
29  *  \ingroup spnode
30  */
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_lamp_types.h"
35 #include "DNA_material_types.h"
36 #include "DNA_node_types.h"
37 #include "DNA_text_types.h"
38 #include "DNA_world_types.h"
39
40 #include "BLI_math.h"
41 #include "BLI_blenlib.h"
42
43 #include "BKE_context.h"
44 #include "BKE_global.h"
45 #include "BKE_image.h"
46 #include "BKE_library.h"
47 #include "BKE_main.h"
48 #include "BKE_node.h"
49 #include "BKE_report.h"
50 #include "BKE_scene.h"
51
52 #include "DEG_depsgraph.h"
53
54 #include "RE_engine.h"
55 #include "RE_pipeline.h"
56
57
58 #include "ED_node.h"  /* own include */
59 #include "ED_screen.h"
60 #include "ED_render.h"
61
62 #include "RNA_access.h"
63 #include "RNA_define.h"
64 #include "RNA_enum_types.h"
65
66 #include "WM_api.h"
67 #include "WM_types.h"
68
69 #include "UI_view2d.h"
70
71 #include "GPU_material.h"
72
73 #include "IMB_imbuf_types.h"
74
75 #include "node_intern.h"  /* own include */
76 #include "NOD_composite.h"
77 #include "NOD_shader.h"
78 #include "NOD_texture.h"
79
80
81 #define USE_ESC_COMPO
82
83 /* ***************** composite job manager ********************** */
84
85 enum {
86         COM_RECALC_COMPOSITE = 1,
87         COM_RECALC_VIEWER    = 2
88 };
89
90 typedef struct CompoJob {
91         Scene *scene;
92         bNodeTree *ntree;
93         bNodeTree *localtree;
94         const short *stop;
95         short *do_update;
96         float *progress;
97         int recalc_flags;
98 } CompoJob;
99
100 static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags)
101 {
102         bNode *node;
103
104         for (node = nodetree->nodes.first; node; node = node->next) {
105                 if (node->type == CMP_NODE_COMPOSITE) {
106                         if (recalc_flags & COM_RECALC_COMPOSITE)
107                                 node->flag |= NODE_DO_OUTPUT_RECALC;
108                 }
109                 else if (node->type == CMP_NODE_VIEWER || node->type == CMP_NODE_SPLITVIEWER) {
110                         if (recalc_flags & COM_RECALC_VIEWER)
111                                 node->flag |= NODE_DO_OUTPUT_RECALC;
112                 }
113                 else if (node->type == NODE_GROUP) {
114                         if (node->id)
115                                 compo_tag_output_nodes((bNodeTree *)node->id, recalc_flags);
116                 }
117         }
118 }
119
120 static int compo_get_recalc_flags(const bContext *C)
121 {
122         wmWindowManager *wm = CTX_wm_manager(C);
123         wmWindow *win;
124         int recalc_flags = 0;
125
126         for (win = wm->windows.first; win; win = win->next) {
127                 const bScreen *sc = WM_window_get_active_screen(win);
128                 ScrArea *sa;
129
130                 for (sa = sc->areabase.first; sa; sa = sa->next) {
131                         if (sa->spacetype == SPACE_IMAGE) {
132                                 SpaceImage *sima = sa->spacedata.first;
133                                 if (sima->image) {
134                                         if (sima->image->type == IMA_TYPE_R_RESULT)
135                                                 recalc_flags |= COM_RECALC_COMPOSITE;
136                                         else if (sima->image->type == IMA_TYPE_COMPOSITE)
137                                                 recalc_flags |= COM_RECALC_VIEWER;
138                                 }
139                         }
140                         else if (sa->spacetype == SPACE_NODE) {
141                                 SpaceNode *snode = sa->spacedata.first;
142                                 if (snode->flag & SNODE_BACKDRAW)
143                                         recalc_flags |= COM_RECALC_VIEWER;
144                         }
145                 }
146         }
147
148         return recalc_flags;
149 }
150
151 /* called by compo, only to check job 'stop' value */
152 static int compo_breakjob(void *cjv)
153 {
154         CompoJob *cj = cjv;
155         
156         /* without G.is_break 'ESC' wont quit - which annoys users */
157         return (*(cj->stop)
158 #ifdef USE_ESC_COMPO
159                 ||
160                 G.is_break
161 #endif
162                 );
163 }
164
165 /* called by compo, wmJob sends notifier */
166 static void compo_statsdrawjob(void *cjv, const char *UNUSED(str))
167 {
168         CompoJob *cj = cjv;
169         
170         *(cj->do_update) = true;
171 }
172
173 /* called by compo, wmJob sends notifier */
174 static void compo_redrawjob(void *cjv)
175 {
176         CompoJob *cj = cjv;
177         
178         *(cj->do_update) = true;
179 }
180
181 static void compo_freejob(void *cjv)
182 {
183         CompoJob *cj = cjv;
184
185         if (cj->localtree) {
186                 ntreeLocalMerge(cj->localtree, cj->ntree);
187         }
188         MEM_freeN(cj);
189 }
190
191 /* only now we copy the nodetree, so adding many jobs while
192  * sliding buttons doesn't frustrate */
193 static void compo_initjob(void *cjv)
194 {
195         CompoJob *cj = cjv;
196
197         cj->localtree = ntreeLocalize(cj->ntree);
198
199         if (cj->recalc_flags)
200                 compo_tag_output_nodes(cj->localtree, cj->recalc_flags);
201 }
202
203 /* called before redraw notifiers, it moves finished previews over */
204 static void compo_updatejob(void *UNUSED(cjv))
205 {
206         WM_main_add_notifier(NC_SCENE | ND_COMPO_RESULT, NULL);
207 }
208
209 static void compo_progressjob(void *cjv, float progress)
210 {
211         CompoJob *cj = cjv;
212         
213         *(cj->progress) = progress;
214 }
215
216 /* only this runs inside thread */
217 static void compo_startjob(void *cjv, short *stop, short *do_update, float *progress)
218 {
219         CompoJob *cj = cjv;
220         bNodeTree *ntree = cj->localtree;
221         Scene *scene = cj->scene;
222         SceneRenderView *srv;
223
224         if (scene->use_nodes == false)
225                 return;
226         
227         cj->stop = stop;
228         cj->do_update = do_update;
229         cj->progress = progress;
230
231         ntree->test_break = compo_breakjob;
232         ntree->tbh = cj;
233         ntree->stats_draw = compo_statsdrawjob;
234         ntree->sdh = cj;
235         ntree->progress = compo_progressjob;
236         ntree->prh = cj;
237         ntree->update_draw = compo_redrawjob;
238         ntree->udh = cj;
239
240         // XXX BIF_store_spare();
241         /* 1 is do_previews */
242
243         if ((cj->scene->r.scemode & R_MULTIVIEW) == 0) {
244                 ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings, "");
245         }
246         else {
247                 for (srv = scene->r.views.first; srv; srv = srv->next) {
248                         if (BKE_scene_multiview_is_render_view_active(&scene->r, srv) == false) continue;
249                         ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings, srv->name);
250                 }
251         }
252
253         ntree->test_break = NULL;
254         ntree->stats_draw = NULL;
255         ntree->progress = NULL;
256
257 }
258
259 /**
260  * \param scene_owner is the owner of the job,
261  * we don't use it for anything else currently so could also be a void pointer,
262  * but for now keep it an 'Scene' for consistency.
263  *
264  * \note only call from spaces `refresh` callbacks, not direct! - use with care.
265  */
266 void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene *scene_owner)
267 {
268         wmJob *wm_job;
269         CompoJob *cj;
270         Scene *scene = CTX_data_scene(C);
271
272         /* to fix bug: [#32272] */
273         if (G.is_rendering) {
274                 return;
275         }
276
277 #ifdef USE_ESC_COMPO
278         G.is_break = false;
279 #endif
280
281         BKE_image_backup_render(scene, BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), false);
282
283         wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene_owner, "Compositing",
284                              WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS, WM_JOB_TYPE_COMPOSITE);
285         cj = MEM_callocN(sizeof(CompoJob), "compo job");
286
287         /* customdata for preview thread */
288         cj->scene = scene;
289         cj->ntree = nodetree;
290         cj->recalc_flags = compo_get_recalc_flags(C);
291
292         /* setup job */
293         WM_jobs_customdata_set(wm_job, cj, compo_freejob);
294         WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_COMPO_RESULT, NC_SCENE | ND_COMPO_RESULT);
295         WM_jobs_callbacks(wm_job, compo_startjob, compo_initjob, compo_updatejob, NULL);
296
297         WM_jobs_start(CTX_wm_manager(C), wm_job);
298 }
299
300 /* ***************************************** */
301
302 /* operator poll callback */
303 int composite_node_active(bContext *C)
304 {
305         if (ED_operator_node_active(C)) {
306                 SpaceNode *snode = CTX_wm_space_node(C);
307                 if (ED_node_is_compositor(snode))
308                         return 1;
309         }
310         return 0;
311 }
312
313 /* operator poll callback */
314 int composite_node_editable(bContext *C)
315 {
316         if (ED_operator_node_editable(C)) {
317                 SpaceNode *snode = CTX_wm_space_node(C);
318                 if (ED_node_is_compositor(snode))
319                         return 1;
320         }
321         return 0;
322 }
323
324 void snode_dag_update(bContext *C, SpaceNode *snode)
325 {
326         Main *bmain = CTX_data_main(C);
327
328         /* for groups, update all ID's using this */
329         if (snode->edittree != snode->nodetree) {
330                 FOREACH_NODETREE(bmain, tntree, id) {
331                         if (ntreeHasTree(tntree, snode->edittree))
332                                 DEG_id_tag_update(id, 0);
333                 } FOREACH_NODETREE_END
334         }
335
336         DEG_id_tag_update(snode->id, 0);
337 }
338
339 void snode_notify(bContext *C, SpaceNode *snode)
340 {
341         ID *id = snode->id;
342
343         WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL);
344
345         if (ED_node_is_shader(snode)) {
346                 if (GS(id->name) == ID_MA)
347                         WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id);
348                 else if (GS(id->name) == ID_LA)
349                         WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id);
350                 else if (GS(id->name) == ID_WO)
351                         WM_main_add_notifier(NC_WORLD | ND_WORLD, id);
352         }
353         else if (ED_node_is_compositor(snode))
354                 WM_event_add_notifier(C, NC_SCENE | ND_NODES, id);
355         else if (ED_node_is_texture(snode))
356                 WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, id);
357 }
358
359 void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo)
360 {
361         if (typeinfo)
362                 BLI_strncpy(snode->tree_idname, typeinfo->idname, sizeof(snode->tree_idname));
363         else
364                 snode->tree_idname[0] = '\0';
365 }
366
367 bool ED_node_is_compositor(struct SpaceNode *snode)
368 {
369         return STREQ(snode->tree_idname, ntreeType_Composite->idname);
370 }
371
372 bool ED_node_is_shader(struct SpaceNode *snode)
373 {
374         return STREQ(snode->tree_idname, ntreeType_Shader->idname);
375 }
376
377 bool ED_node_is_texture(struct SpaceNode *snode)
378 {
379         return STREQ(snode->tree_idname, ntreeType_Texture->idname);
380 }
381
382 /* assumes nothing being done in ntree yet, sets the default in/out node */
383 /* called from shading buttons or header */
384 void ED_node_shader_default(const bContext *C, ID *id)
385 {
386         bNode *in, *out;
387         bNodeSocket *fromsock, *tosock, *sock;
388         bNodeTree *ntree;
389         int output_type, shader_type;
390         float color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }, strength = 1.0f;
391         
392         ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
393
394         switch (GS(id->name)) {
395                 case ID_MA:
396                 {
397                         Material *ma = (Material *)id;
398                         ma->nodetree = ntree;
399
400                         output_type = SH_NODE_OUTPUT_MATERIAL;
401                         shader_type = SH_NODE_BSDF_PRINCIPLED;
402
403                         copy_v3_v3(color, &ma->r);
404                         strength = 0.0f;
405                         break;
406                 }
407                 case ID_WO:
408                 {
409                         World *wo = (World *)id;
410                         wo->nodetree = ntree;
411
412                         output_type = SH_NODE_OUTPUT_WORLD;
413                         shader_type = SH_NODE_BACKGROUND;
414
415                         copy_v3_v3(color, &wo->horr);
416                         strength = 1.0f;
417                         break;
418                 }
419                 case ID_LA:
420                 {
421                         Lamp *la = (Lamp *)id;
422                         la->nodetree = ntree;
423
424                         output_type = SH_NODE_OUTPUT_LAMP;
425                         shader_type = SH_NODE_EMISSION;
426
427                         copy_v3_v3(color, &la->r);
428                         if (la->type == LA_LOCAL || la->type == LA_SPOT || la->type == LA_AREA)
429                                 strength = 100.0f;
430                         else
431                                 strength = 1.0f;
432                         break;
433                 }
434                 default:
435                         printf("ED_node_shader_default called on wrong ID type.\n");
436                         return;
437         }
438         
439         out = nodeAddStaticNode(C, ntree, output_type);
440         out->locx = 300.0f; out->locy = 300.0f;
441         
442         in = nodeAddStaticNode(C, ntree, shader_type);
443         in->locx = 10.0f; in->locy = 300.0f;
444         nodeSetActive(ntree, in);
445         
446         /* only a link from color to color */
447         fromsock = in->outputs.first;
448         tosock = out->inputs.first;
449         nodeAddLink(ntree, in, fromsock, out, tosock);
450
451         /* default values */
452         PointerRNA sockptr;
453         sock = in->inputs.first;
454         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
455         
456         RNA_float_set_array(&sockptr, "default_value", color);
457
458         if (strength != 0.0f) {
459                 sock = in->inputs.last;
460                 RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
461                 RNA_float_set(&sockptr, "default_value", strength);
462         }
463         
464         ntreeUpdateTree(CTX_data_main(C), ntree);
465 }
466
467 /* assumes nothing being done in ntree yet, sets the default in/out node */
468 /* called from shading buttons or header */
469 void ED_node_composit_default(const bContext *C, struct Scene *sce)
470 {
471         bNode *in, *out;
472         bNodeSocket *fromsock, *tosock;
473         
474         /* but lets check it anyway */
475         if (sce->nodetree) {
476                 if (G.debug & G_DEBUG)
477                         printf("error in composite initialize\n");
478                 return;
479         }
480         
481         sce->nodetree = ntreeAddTree(NULL, "Compositing Nodetree", ntreeType_Composite->idname);
482         
483         sce->nodetree->chunksize = 256;
484         sce->nodetree->edit_quality = NTREE_QUALITY_HIGH;
485         sce->nodetree->render_quality = NTREE_QUALITY_HIGH;
486         
487         out = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_COMPOSITE);
488         out->locx = 300.0f; out->locy = 400.0f;
489         
490         in = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_R_LAYERS);
491         in->locx = 10.0f; in->locy = 400.0f;
492         nodeSetActive(sce->nodetree, in);
493         
494         /* links from color to color */
495         fromsock = in->outputs.first;
496         tosock = out->inputs.first;
497         nodeAddLink(sce->nodetree, in, fromsock, out, tosock);
498         
499         ntreeUpdateTree(CTX_data_main(C), sce->nodetree);
500 }
501
502 /* assumes nothing being done in ntree yet, sets the default in/out node */
503 /* called from shading buttons or header */
504 void ED_node_texture_default(const bContext *C, Tex *tx)
505 {
506         bNode *in, *out;
507         bNodeSocket *fromsock, *tosock;
508         
509         /* but lets check it anyway */
510         if (tx->nodetree) {
511                 if (G.debug & G_DEBUG)
512                         printf("error in texture initialize\n");
513                 return;
514         }
515         
516         tx->nodetree = ntreeAddTree(NULL, "Texture Nodetree", ntreeType_Texture->idname);
517         
518         out = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_OUTPUT);
519         out->locx = 300.0f; out->locy = 300.0f;
520         
521         in = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_CHECKER);
522         in->locx = 10.0f; in->locy = 300.0f;
523         nodeSetActive(tx->nodetree, in);
524         
525         fromsock = in->outputs.first;
526         tosock = out->inputs.first;
527         nodeAddLink(tx->nodetree, in, fromsock, out, tosock);
528         
529         ntreeUpdateTree(CTX_data_main(C), tx->nodetree);
530 }
531
532 /* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
533 void snode_set_context(const bContext *C)
534 {
535         SpaceNode *snode = CTX_wm_space_node(C);
536         bNodeTreeType *treetype = ntreeTypeFind(snode->tree_idname);
537         bNodeTree *ntree = snode->nodetree;
538         ID *id = snode->id, *from = snode->from;
539         
540         /* check the tree type */
541         if (!treetype ||
542             (treetype->poll && !treetype->poll(C, treetype)))
543         {
544                 /* invalid tree type, skip
545                  * NB: not resetting the node path here, invalid bNodeTreeType
546                  * may still be registered at a later point.
547                  */
548                 return;
549         }
550         
551         if (snode->nodetree && !STREQ(snode->nodetree->idname, snode->tree_idname)) {
552                 /* current tree does not match selected type, clear tree path */
553                 ntree = NULL;
554                 id = NULL;
555                 from = NULL;
556         }
557         
558         if (!(snode->flag & SNODE_PIN) || ntree == NULL) {
559                 if (treetype->get_from_context) {
560                         /* reset and update from context */
561                         ntree = NULL;
562                         id = NULL;
563                         from = NULL;
564                         
565                         treetype->get_from_context(C, treetype, &ntree, &id, &from);
566                 }
567         }
568         
569         if (snode->nodetree != ntree || snode->id != id || snode->from != from ||
570             (snode->treepath.last == NULL && ntree))
571         {
572                 ED_node_tree_start(snode, ntree, id, from);
573         }
574 }
575
576 void snode_update(SpaceNode *snode, bNode *node)
577 {
578         bNodeTreePath *path;
579         
580         /* XXX this only updates nodes in the current node space tree path.
581          * The function supposedly should update any potential group node linking to changed tree,
582          * this really requires a working depsgraph ...
583          */
584         
585         /* update all edited group nodes */
586         path = snode->treepath.last;
587         if (path) {
588                 bNodeTree *ngroup = path->nodetree;
589                 for (path = path->prev; path; path = path->prev) {
590                         nodeUpdateID(path->nodetree, (ID *)ngroup);
591                         ngroup = path->nodetree;
592                 }
593         }
594
595         if (node)
596                 nodeUpdate(snode->edittree, node);
597 }
598
599 void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
600 {
601         const bool was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE) != 0;
602
603         nodeSetActive(ntree, node);
604         
605         if (node->type != NODE_GROUP) {
606                 const bool was_output = (node->flag & NODE_DO_OUTPUT) != 0;
607                 bool do_update = false;
608                 
609                 /* generic node group output: set node as active output */
610                 if (node->type == NODE_GROUP_OUTPUT) {
611                         bNode *tnode;
612                         for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
613                                 if (tnode->type == NODE_GROUP_OUTPUT)
614                                         tnode->flag &= ~NODE_DO_OUTPUT;
615                         
616                         node->flag |= NODE_DO_OUTPUT;
617                         if (!was_output)
618                                 do_update = 1;
619                 }
620                 
621                 /* tree specific activate calls */
622                 if (ntree->type == NTREE_SHADER) {
623                         /* when we select a material, active texture is cleared, for buttons */
624                         if (node->id && ELEM(GS(node->id->name), ID_MA, ID_LA, ID_WO))
625                                 nodeClearActiveID(ntree, ID_TE);
626                         
627                         if (ELEM(node->type, SH_NODE_OUTPUT_MATERIAL,
628                                  SH_NODE_OUTPUT_WORLD, SH_NODE_OUTPUT_LAMP, SH_NODE_OUTPUT_LINESTYLE))
629                         {
630                                 bNode *tnode;
631                                 
632                                 for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
633                                         if (tnode->type == node->type)
634                                                 tnode->flag &= ~NODE_DO_OUTPUT;
635                                 
636                                 node->flag |= NODE_DO_OUTPUT;
637                                 if (was_output == 0)
638                                         ED_node_tag_update_nodetree(bmain, ntree, node);
639                         }
640                         else if (do_update)
641                                 ED_node_tag_update_nodetree(bmain, ntree, node);
642
643                         /* if active texture changed, free glsl materials */
644                         if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
645                                 Material *ma;
646                                 World *wo;
647
648                                 for (ma = bmain->mat.first; ma; ma = ma->id.next)
649                                         if (ma->nodetree && ma->use_nodes && ntreeHasTree(ma->nodetree, ntree))
650                                                 GPU_material_free(&ma->gpumaterial);
651
652                                 for (wo = bmain->world.first; wo; wo = wo->id.next)
653                                         if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree))
654                                                 GPU_material_free(&wo->gpumaterial);
655                                 
656                                 WM_main_add_notifier(NC_IMAGE, NULL);
657                         }
658
659                         WM_main_add_notifier(NC_MATERIAL | ND_NODES, node->id);
660                 }
661                 else if (ntree->type == NTREE_COMPOSIT) {
662                         /* make active viewer, currently only 1 supported... */
663                         if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
664                                 bNode *tnode;
665                                 
666
667                                 for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
668                                         if (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
669                                                 tnode->flag &= ~NODE_DO_OUTPUT;
670                                 
671                                 node->flag |= NODE_DO_OUTPUT;
672                                 if (was_output == 0)
673                                         ED_node_tag_update_nodetree(bmain, ntree, node);
674                                 
675                                 /* addnode() doesnt link this yet... */
676                                 node->id = (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
677                         }
678                         else if (node->type == CMP_NODE_COMPOSITE) {
679                                 if (was_output == 0) {
680                                         bNode *tnode;
681                                         
682                                         for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
683                                                 if (tnode->type == CMP_NODE_COMPOSITE)
684                                                         tnode->flag &= ~NODE_DO_OUTPUT;
685                                         
686                                         node->flag |= NODE_DO_OUTPUT;
687                                         ED_node_tag_update_nodetree(bmain, ntree, node);
688                                 }
689                         }
690                         else if (do_update)
691                                 ED_node_tag_update_nodetree(bmain, ntree, node);
692                 }
693                 else if (ntree->type == NTREE_TEXTURE) {
694                         // XXX
695 #if 0
696                         if (node->id)
697                                 ;  // XXX BIF_preview_changed(-1);
698                         // allqueue(REDRAWBUTSSHADING, 1);
699                         // allqueue(REDRAWIPO, 0);
700 #endif
701                 }
702         }
703 }
704
705 void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree))
706 {
707         /* XXX This does not work due to layout functions relying on node->block,
708          * which only exists during actual drawing. Can we rely on valid totr rects?
709          */
710         /* make sure nodes have correct bounding boxes after transform */
711         /* node_update_nodetree(C, ntree, 0.0f, 0.0f); */
712 }
713
714 /* ***************** generic operator functions for nodes ***************** */
715
716 #if 0 /* UNUSED */
717
718 static int edit_node_poll(bContext *C)
719 {
720         return ED_operator_node_active(C);
721 }
722
723 static void edit_node_properties(wmOperatorType *ot)
724 {
725         /* XXX could node be a context pointer? */
726         RNA_def_string(ot->srna, "node", NULL, MAX_NAME, "Node", "");
727         RNA_def_int(ot->srna, "socket", 0, 0, MAX_SOCKET, "Socket", "", 0, MAX_SOCKET);
728         RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Side", "");
729 }
730
731 static int edit_node_invoke_properties(bContext *C, wmOperator *op)
732 {
733         if (!RNA_struct_property_is_set(op->ptr, "node")) {
734                 bNode *node = CTX_data_pointer_get_type(C, "node", &RNA_Node).data;
735                 if (!node)
736                         return 0;
737                 else
738                         RNA_string_set(op->ptr, "node", node->name);
739         }
740         
741         if (!RNA_struct_property_is_set(op->ptr, "in_out"))
742                 RNA_enum_set(op->ptr, "in_out", SOCK_IN);
743         
744         if (!RNA_struct_property_is_set(op->ptr, "socket"))
745                 RNA_int_set(op->ptr, "socket", 0);
746         
747         return 1;
748 }
749
750 static void edit_node_properties_get(wmOperator *op, bNodeTree *ntree, bNode **rnode, bNodeSocket **rsock, int *rin_out)
751 {
752         bNode *node;
753         bNodeSocket *sock = NULL;
754         char nodename[MAX_NAME];
755         int sockindex;
756         int in_out;
757         
758         RNA_string_get(op->ptr, "node", nodename);
759         node = nodeFindNodebyName(ntree, nodename);
760         
761         in_out = RNA_enum_get(op->ptr, "in_out");
762         
763         sockindex = RNA_int_get(op->ptr, "socket");
764         switch (in_out) {
765                 case SOCK_IN:   sock = BLI_findlink(&node->inputs, sockindex);  break;
766                 case SOCK_OUT:  sock = BLI_findlink(&node->outputs, sockindex); break;
767         }
768         
769         if (rnode)
770                 *rnode = node;
771         if (rsock)
772                 *rsock = sock;
773         if (rin_out)
774                 *rin_out = in_out;
775 }
776 #endif
777
778 /* ************************** Node generic ************** */
779
780 /* is rct in visible part of node? */
781 static bNode *visible_node(SpaceNode *snode, const rctf *rct)
782 {
783         bNode *node;
784         
785         for (node = snode->edittree->nodes.last; node; node = node->prev) {
786                 if (BLI_rctf_isect(&node->totr, rct, NULL))
787                         break;
788         }
789         return node;
790 }
791
792 /* ********************** size widget operator ******************** */
793
794 typedef struct NodeSizeWidget {
795         float mxstart, mystart;
796         float oldlocx, oldlocy;
797         float oldoffsetx, oldoffsety;
798         float oldwidth, oldheight;
799         float oldminiwidth;
800         int directions;
801 } NodeSizeWidget;
802
803 static void node_resize_init(bContext *C, wmOperator *op, const wmEvent *UNUSED(event), bNode *node, int dir)
804 {
805         SpaceNode *snode = CTX_wm_space_node(C);
806         
807         NodeSizeWidget *nsw = MEM_callocN(sizeof(NodeSizeWidget), "size widget op data");
808         
809         op->customdata = nsw;
810         nsw->mxstart = snode->cursor[0];
811         nsw->mystart = snode->cursor[1];
812         
813         /* store old */
814         nsw->oldlocx = node->locx;
815         nsw->oldlocy = node->locy;
816         nsw->oldoffsetx = node->offsetx;
817         nsw->oldoffsety = node->offsety;
818         nsw->oldwidth = node->width;
819         nsw->oldheight = node->height;
820         nsw->oldminiwidth = node->miniwidth;
821         nsw->directions = dir;
822         
823         WM_cursor_modal_set(CTX_wm_window(C), node_get_resize_cursor(dir));
824         /* add modal handler */
825         WM_event_add_modal_handler(C, op);
826 }
827
828 static void node_resize_exit(bContext *C, wmOperator *op, bool UNUSED(cancel))
829 {
830         WM_cursor_modal_restore(CTX_wm_window(C));
831         
832         MEM_freeN(op->customdata);
833         op->customdata = NULL;
834 }
835
836 static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
837 {
838         SpaceNode *snode = CTX_wm_space_node(C);
839         ARegion *ar = CTX_wm_region(C);
840         bNode *node = nodeGetActive(snode->edittree);
841         NodeSizeWidget *nsw = op->customdata;
842         float mx, my, dx, dy;
843         
844         switch (event->type) {
845                 case MOUSEMOVE:
846                         
847                         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mx, &my);
848                         dx = (mx - nsw->mxstart) / UI_DPI_FAC;
849                         dy = (my - nsw->mystart) / UI_DPI_FAC;
850                         
851                         if (node) {
852                                 /* width can use node->width or node->miniwidth (hidden nodes) */
853                                 float *pwidth;
854                                 float oldwidth, widthmin, widthmax;
855                                 /* ignore hidden flag for frame nodes */
856                                 bool use_hidden = (node->type != NODE_FRAME);
857                                 if (use_hidden && node->flag & NODE_HIDDEN) {
858                                         pwidth = &node->miniwidth;
859                                         oldwidth = nsw->oldminiwidth;
860                                         widthmin = 0.0f;
861                                 }
862                                 else {
863                                         pwidth = &node->width;
864                                         oldwidth = nsw->oldwidth;
865                                         widthmin = node->typeinfo->minwidth;
866                                 }
867                                 widthmax = node->typeinfo->maxwidth;
868                                 
869                                 {
870                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
871                                                 *pwidth = oldwidth + dx;
872                                                 CLAMP(*pwidth, widthmin, widthmax);
873                                         }
874                                         if (nsw->directions & NODE_RESIZE_LEFT) {
875                                                 float locmax = nsw->oldlocx + oldwidth;
876                                                 
877                                                 node->locx = nsw->oldlocx + dx;
878                                                 CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
879                                                 *pwidth = locmax - node->locx;
880                                         }
881                                 }
882                                 
883                                 /* height works the other way round ... */
884                                 {
885                                         float heightmin = UI_DPI_FAC * node->typeinfo->minheight;
886                                         float heightmax = UI_DPI_FAC * node->typeinfo->maxheight;
887                                         if (nsw->directions & NODE_RESIZE_TOP) {
888                                                 float locmin = nsw->oldlocy - nsw->oldheight;
889                                                 
890                                                 node->locy = nsw->oldlocy + dy;
891                                                 CLAMP(node->locy, locmin + heightmin, locmin + heightmax);
892                                                 node->height = node->locy - locmin;
893                                         }
894                                         if (nsw->directions & NODE_RESIZE_BOTTOM) {
895                                                 node->height = nsw->oldheight - dy;
896                                                 CLAMP(node->height, heightmin, heightmax);
897                                         }
898                                 }
899                                 
900                                 /* XXX make callback? */
901                                 if (node->type == NODE_FRAME) {
902                                         /* keep the offset symmetric around center point */
903                                         if (nsw->directions & NODE_RESIZE_LEFT) {
904                                                 node->locx = nsw->oldlocx + 0.5f * dx;
905                                                 node->offsetx = nsw->oldoffsetx + 0.5f * dx;
906                                         }
907                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
908                                                 node->locx = nsw->oldlocx + 0.5f * dx;
909                                                 node->offsetx = nsw->oldoffsetx - 0.5f * dx;
910                                         }
911                                         if (nsw->directions & NODE_RESIZE_TOP) {
912                                                 node->locy = nsw->oldlocy + 0.5f * dy;
913                                                 node->offsety = nsw->oldoffsety + 0.5f * dy;
914                                         }
915                                         if (nsw->directions & NODE_RESIZE_BOTTOM) {
916                                                 node->locy = nsw->oldlocy + 0.5f * dy;
917                                                 node->offsety = nsw->oldoffsety - 0.5f * dy;
918                                         }
919                                 }
920                         }
921                                 
922                         ED_region_tag_redraw(ar);
923
924                         break;
925                         
926                 case LEFTMOUSE:
927                 case MIDDLEMOUSE:
928                 case RIGHTMOUSE:
929                         
930                         node_resize_exit(C, op, false);
931                         ED_node_post_apply_transform(C, snode->edittree);
932                         
933                         return OPERATOR_FINISHED;
934         }
935         
936         return OPERATOR_RUNNING_MODAL;
937 }
938
939 static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event)
940 {
941         SpaceNode *snode = CTX_wm_space_node(C);
942         ARegion *ar = CTX_wm_region(C);
943         bNode *node = nodeGetActive(snode->edittree);
944         int dir;
945         
946         if (node) {
947                 /* convert mouse coordinates to v2d space */
948                 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
949                                          &snode->cursor[0], &snode->cursor[1]);
950                 dir = node->typeinfo->resize_area_func(node, snode->cursor[0], snode->cursor[1]);
951                 if (dir != 0) {
952                         node_resize_init(C, op, event, node, dir);
953                         return OPERATOR_RUNNING_MODAL;
954                 }
955         }
956         return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
957 }
958
959 static void node_resize_cancel(bContext *C, wmOperator *op)
960 {
961         node_resize_exit(C, op, true);
962 }
963
964 void NODE_OT_resize(wmOperatorType *ot)
965 {
966         /* identifiers */
967         ot->name = "Resize Node";
968         ot->idname = "NODE_OT_resize";
969         ot->description = "Resize a node";
970         
971         /* api callbacks */
972         ot->invoke = node_resize_invoke;
973         ot->modal = node_resize_modal;
974         ot->poll = ED_operator_node_active;
975         ot->cancel = node_resize_cancel;
976         
977         /* flags */
978         ot->flag = OPTYPE_BLOCKING;
979 }
980
981
982 /* ********************** hidden sockets ******************** */
983
984 int node_has_hidden_sockets(bNode *node)
985 {
986         bNodeSocket *sock;
987         
988         for (sock = node->inputs.first; sock; sock = sock->next)
989                 if (sock->flag & SOCK_HIDDEN)
990                         return 1;
991         for (sock = node->outputs.first; sock; sock = sock->next)
992                 if (sock->flag & SOCK_HIDDEN)
993                         return 1;
994         return 0;
995 }
996
997 void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
998 {
999         bNodeSocket *sock;
1000
1001         if (set == 0) {
1002                 for (sock = node->inputs.first; sock; sock = sock->next)
1003                         sock->flag &= ~SOCK_HIDDEN;
1004                 for (sock = node->outputs.first; sock; sock = sock->next)
1005                         sock->flag &= ~SOCK_HIDDEN;
1006         }
1007         else {
1008                 /* hide unused sockets */
1009                 for (sock = node->inputs.first; sock; sock = sock->next) {
1010                         if (sock->link == NULL)
1011                                 sock->flag |= SOCK_HIDDEN;
1012                 }
1013                 for (sock = node->outputs.first; sock; sock = sock->next) {
1014                         if (nodeCountSocketLinks(snode->edittree, sock) == 0)
1015                                 sock->flag |= SOCK_HIDDEN;
1016                 }
1017         }
1018 }
1019
1020
1021 /* checks snode->mouse position, and returns found node/socket */
1022 /* type is SOCK_IN and/or SOCK_OUT */
1023 int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, float cursor[2], int in_out)
1024 {
1025         bNode *node;
1026         bNodeSocket *sock;
1027         rctf rect;
1028         
1029         *nodep = NULL;
1030         *sockp = NULL;
1031         
1032         /* check if we click in a socket */
1033         for (node = snode->edittree->nodes.first; node; node = node->next) {
1034
1035                 BLI_rctf_init_pt_radius(&rect, cursor, NODE_SOCKSIZE + 4);
1036
1037                 if (!(node->flag & NODE_HIDDEN)) {
1038                         /* extra padding inside and out - allow dragging on the text areas too */
1039                         if (in_out == SOCK_IN) {
1040                                 rect.xmax += NODE_SOCKSIZE;
1041                                 rect.xmin -= NODE_SOCKSIZE * 4;
1042                         }
1043                         else if (in_out == SOCK_OUT) {
1044                                 rect.xmax += NODE_SOCKSIZE * 4;
1045                                 rect.xmin -= NODE_SOCKSIZE;
1046                         }
1047                 }
1048                 
1049                 if (in_out & SOCK_IN) {
1050                         for (sock = node->inputs.first; sock; sock = sock->next) {
1051                                 if (!nodeSocketIsHidden(sock)) {
1052                                         if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
1053                                                 if (node == visible_node(snode, &rect)) {
1054                                                         *nodep = node;
1055                                                         *sockp = sock;
1056                                                         return 1;
1057                                                 }
1058                                         }
1059                                 }
1060                         }
1061                 }
1062                 if (in_out & SOCK_OUT) {
1063                         for (sock = node->outputs.first; sock; sock = sock->next) {
1064                                 if (!nodeSocketIsHidden(sock)) {
1065                                         if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
1066                                                 if (node == visible_node(snode, &rect)) {
1067                                                         *nodep = node;
1068                                                         *sockp = sock;
1069                                                         return 1;
1070                                                 }
1071                                         }
1072                                 }
1073                         }
1074                 }
1075         }
1076         
1077         return 0;
1078 }
1079
1080 /* ****************** Duplicate *********************** */
1081
1082 static void node_duplicate_reparent_recursive(bNode *node)
1083 {
1084         bNode *parent;
1085         
1086         node->flag |= NODE_TEST;
1087         
1088         /* find first selected parent */
1089         for (parent = node->parent; parent; parent = parent->parent) {
1090                 if (parent->flag & SELECT) {
1091                         if (!(parent->flag & NODE_TEST))
1092                                 node_duplicate_reparent_recursive(parent);
1093                         break;
1094                 }
1095         }
1096         /* reparent node copy to parent copy */
1097         if (parent) {
1098                 nodeDetachNode(node->new_node);
1099                 nodeAttachNode(node->new_node, parent->new_node);
1100         }
1101 }
1102
1103 static int node_duplicate_exec(bContext *C, wmOperator *op)
1104 {
1105         SpaceNode *snode = CTX_wm_space_node(C);
1106         bNodeTree *ntree = snode->edittree;
1107         bNode *node, *newnode, *lastnode;
1108         bNodeLink *link, *newlink, *lastlink;
1109         const bool keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
1110         bool do_tag_update = false;
1111
1112         ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
1113         
1114         lastnode = ntree->nodes.last;
1115         for (node = ntree->nodes.first; node; node = node->next) {
1116                 if (node->flag & SELECT) {
1117                         newnode = nodeCopyNode(ntree, node);
1118                         
1119                         if (newnode->id) {
1120                                 /* simple id user adjustment, node internal functions don't touch this
1121                                  * but operators and readfile.c do. */
1122                                 id_us_plus(newnode->id);
1123                                 /* to ensure redraws or rerenders happen */
1124                                 ED_node_tag_update_id(snode->id);
1125                         }
1126                 }
1127                 
1128                 /* make sure we don't copy new nodes again! */
1129                 if (node == lastnode)
1130                         break;
1131         }
1132         
1133         /* copy links between selected nodes
1134          * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
1135          */
1136         lastlink = ntree->links.last;
1137         for (link = ntree->links.first; link; link = link->next) {
1138                 /* This creates new links between copied nodes.
1139                  * If keep_inputs is set, also copies input links from unselected (when fromnode==NULL)!
1140                  */
1141                 if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
1142                     (keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT))))
1143                 {
1144                         newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
1145                         newlink->flag = link->flag;
1146                         newlink->tonode = link->tonode->new_node;
1147                         newlink->tosock = link->tosock->new_sock;
1148                         if (link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
1149                                 newlink->fromnode = link->fromnode->new_node;
1150                                 newlink->fromsock = link->fromsock->new_sock;
1151                         }
1152                         else {
1153                                 /* input node not copied, this keeps the original input linked */
1154                                 newlink->fromnode = link->fromnode;
1155                                 newlink->fromsock = link->fromsock;
1156                         }
1157                         
1158                         BLI_addtail(&ntree->links, newlink);
1159                 }
1160                 
1161                 /* make sure we don't copy new links again! */
1162                 if (link == lastlink)
1163                         break;
1164         }
1165         
1166         /* clear flags for recursive depth-first iteration */
1167         for (node = ntree->nodes.first; node; node = node->next)
1168                 node->flag &= ~NODE_TEST;
1169         /* reparent copied nodes */
1170         for (node = ntree->nodes.first; node; node = node->next) {
1171                 if ((node->flag & SELECT) && !(node->flag & NODE_TEST))
1172                         node_duplicate_reparent_recursive(node);
1173                 
1174                 /* only has to check old nodes */
1175                 if (node == lastnode)
1176                         break;
1177         }
1178         
1179         /* deselect old nodes, select the copies instead */
1180         for (node = ntree->nodes.first; node; node = node->next) {
1181                 if (node->flag & SELECT) {
1182                         /* has been set during copy above */
1183                         newnode = node->new_node;
1184                         
1185                         nodeSetSelected(node, false);
1186                         node->flag &= ~NODE_ACTIVE;
1187                         nodeSetSelected(newnode, true);
1188
1189                         do_tag_update |= (do_tag_update || node_connected_to_output(ntree, newnode));
1190                 }
1191                 
1192                 /* make sure we don't copy new nodes again! */
1193                 if (node == lastnode)
1194                         break;
1195         }
1196         
1197         ntreeUpdateTree(CTX_data_main(C), snode->edittree);
1198         
1199         snode_notify(C, snode);
1200         if (do_tag_update) {
1201                 snode_dag_update(C, snode);
1202         }
1203
1204         return OPERATOR_FINISHED;
1205 }
1206
1207 void NODE_OT_duplicate(wmOperatorType *ot)
1208 {
1209         /* identifiers */
1210         ot->name = "Duplicate Nodes";
1211         ot->description = "Duplicate selected nodes";
1212         ot->idname = "NODE_OT_duplicate";
1213         
1214         /* api callbacks */
1215         ot->exec = node_duplicate_exec;
1216         ot->poll = ED_operator_node_editable;
1217         
1218         /* flags */
1219         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1220         
1221         RNA_def_boolean(ot->srna, "keep_inputs", 0, "Keep Inputs", "Keep the input links to duplicated nodes");
1222 }
1223
1224 bool ED_node_select_check(ListBase *lb)
1225
1226
1227 {
1228         bNode *node;
1229
1230         for (node = lb->first; node; node = node->next) {
1231                 if (node->flag & NODE_SELECT) {
1232                         return true;
1233                 }
1234         }
1235
1236         return false;
1237 }
1238
1239 /* ******************************** */
1240 // XXX some code needing updating to operators...
1241
1242
1243 /* goes over all scenes, reads render layers */
1244 static int node_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op))
1245 {
1246         Main *bmain = CTX_data_main(C);
1247         SpaceNode *snode = CTX_wm_space_node(C);
1248         Scene *curscene = CTX_data_scene(C), *scene;
1249         bNode *node;
1250
1251         ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
1252
1253         /* first tag scenes unread */
1254         for (scene = bmain->scene.first; scene; scene = scene->id.next)
1255                 scene->id.tag |= LIB_TAG_DOIT;
1256
1257         for (node = snode->edittree->nodes.first; node; node = node->next) {
1258                 if (node->type == CMP_NODE_R_LAYERS) {
1259                         ID *id = node->id;
1260                         if (id->tag & LIB_TAG_DOIT) {
1261                                 RE_ReadRenderResult(curscene, (Scene *)id);
1262                                 ntreeCompositTagRender((Scene *)id);
1263                                 id->tag &= ~LIB_TAG_DOIT;
1264                         }
1265                 }
1266         }
1267         
1268         snode_notify(C, snode);
1269         snode_dag_update(C, snode);
1270
1271         return OPERATOR_FINISHED;
1272 }
1273
1274 void NODE_OT_read_viewlayers(wmOperatorType *ot)
1275 {
1276         
1277         ot->name = "Read View Layers";
1278         ot->idname = "NODE_OT_read_viewlayers";
1279         ot->description = "Read all render layers of all used scenes";
1280         
1281         ot->exec = node_read_viewlayers_exec;
1282         
1283         ot->poll = composite_node_active;
1284         
1285         /* flags */
1286         ot->flag = 0;
1287 }
1288
1289 int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op))
1290 {
1291         Scene *sce = CTX_data_scene(C);
1292         bNode *node;
1293         
1294         for (node = sce->nodetree->nodes.first; node; node = node->next) {
1295                 if (node->id == (ID *)sce && node->need_exec) {
1296                         break;
1297                 }
1298         }
1299         if (node) {
1300                 ViewLayer *view_layer = BLI_findlink(&sce->view_layers, node->custom1);
1301                 
1302                 if (view_layer) {
1303                         PointerRNA op_ptr;
1304                         
1305                         WM_operator_properties_create(&op_ptr, "RENDER_OT_render");
1306                         RNA_string_set(&op_ptr, "layer", view_layer->name);
1307                         RNA_string_set(&op_ptr, "scene", sce->id.name + 2);
1308                         
1309                         /* to keep keypositions */
1310                         sce->r.scemode |= R_NO_FRAME_UPDATE;
1311                         
1312                         WM_operator_name_call(C, "RENDER_OT_render", WM_OP_INVOKE_DEFAULT, &op_ptr);
1313
1314                         WM_operator_properties_free(&op_ptr);
1315                         
1316                         return OPERATOR_FINISHED;
1317                 }
1318         }
1319         return OPERATOR_CANCELLED;
1320 }
1321
1322 void NODE_OT_render_changed(wmOperatorType *ot)
1323 {
1324         ot->name = "Render Changed Layer";
1325         ot->idname = "NODE_OT_render_changed";
1326         ot->description = "Render current scene, when input node's layer has been changed";
1327         
1328         ot->exec = node_render_changed_exec;
1329         
1330         ot->poll = composite_node_active;
1331         
1332         /* flags */
1333         ot->flag = 0;
1334 }
1335
1336
1337 /* ****************** Hide operator *********************** */
1338
1339 static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
1340 {
1341         bNode *node;
1342         int tot_eq = 0, tot_neq = 0;
1343
1344         /* Toggles the flag on all selected nodes.
1345          * If the flag is set on all nodes it is unset.
1346          * If the flag is not set on all nodes, it is set.
1347          */
1348         for (node = snode->edittree->nodes.first; node; node = node->next) {
1349                 if (node->flag & SELECT) {
1350                         
1351                         if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0)
1352                                 continue;
1353                         if (toggle_flag == NODE_OPTIONS && !(node->typeinfo->draw_buttons || node->typeinfo->draw_buttons_ex))
1354                                 continue;
1355                         
1356                         if (node->flag & toggle_flag)
1357                                 tot_eq++;
1358                         else
1359                                 tot_neq++;
1360                 }
1361         }
1362         for (node = snode->edittree->nodes.first; node; node = node->next) {
1363                 if (node->flag & SELECT) {
1364                         
1365                         if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0)
1366                                 continue;
1367                         if (toggle_flag == NODE_OPTIONS && !(node->typeinfo->draw_buttons || node->typeinfo->draw_buttons_ex))
1368                                 continue;
1369                         
1370                         if ((tot_eq && tot_neq) || tot_eq == 0)
1371                                 node->flag |= toggle_flag;
1372                         else
1373                                 node->flag &= ~toggle_flag;
1374                 }
1375         }
1376 }
1377
1378 static int node_hide_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1379 {
1380         SpaceNode *snode = CTX_wm_space_node(C);
1381         
1382         /* sanity checking (poll callback checks this already) */
1383         if ((snode == NULL) || (snode->edittree == NULL))
1384                 return OPERATOR_CANCELLED;
1385         
1386         node_flag_toggle_exec(snode, NODE_HIDDEN);
1387
1388         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1389
1390         return OPERATOR_FINISHED;
1391 }
1392
1393 void NODE_OT_hide_toggle(wmOperatorType *ot)
1394 {
1395         /* identifiers */
1396         ot->name = "Hide";
1397         ot->description = "Toggle hiding of selected nodes";
1398         ot->idname = "NODE_OT_hide_toggle";
1399         
1400         /* callbacks */
1401         ot->exec = node_hide_toggle_exec;
1402         ot->poll = ED_operator_node_active;
1403
1404         /* flags */
1405         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1406 }
1407
1408 static int node_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1409 {
1410         SpaceNode *snode = CTX_wm_space_node(C);
1411
1412         /* sanity checking (poll callback checks this already) */
1413         if ((snode == NULL) || (snode->edittree == NULL))
1414                 return OPERATOR_CANCELLED;
1415
1416         ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
1417
1418         node_flag_toggle_exec(snode, NODE_PREVIEW);
1419
1420         snode_notify(C, snode);
1421
1422         return OPERATOR_FINISHED;
1423 }
1424
1425 void NODE_OT_preview_toggle(wmOperatorType *ot)
1426 {
1427         /* identifiers */
1428         ot->name = "Toggle Node Preview";
1429         ot->description = "Toggle preview display for selected nodes";
1430         ot->idname = "NODE_OT_preview_toggle";
1431
1432         /* callbacks */
1433         ot->exec = node_preview_toggle_exec;
1434         ot->poll = ED_operator_node_active;
1435
1436         /* flags */
1437         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1438 }
1439
1440 static int node_options_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1441 {
1442         SpaceNode *snode = CTX_wm_space_node(C);
1443
1444         /* sanity checking (poll callback checks this already) */
1445         if ((snode == NULL) || (snode->edittree == NULL))
1446                 return OPERATOR_CANCELLED;
1447
1448         node_flag_toggle_exec(snode, NODE_OPTIONS);
1449
1450         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1451
1452         return OPERATOR_FINISHED;
1453 }
1454
1455 void NODE_OT_options_toggle(wmOperatorType *ot)
1456 {
1457         /* identifiers */
1458         ot->name = "Toggle Node Options";
1459         ot->description = "Toggle option buttons display for selected nodes";
1460         ot->idname = "NODE_OT_options_toggle";
1461
1462         /* callbacks */
1463         ot->exec = node_options_toggle_exec;
1464         ot->poll = ED_operator_node_active;
1465
1466         /* flags */
1467         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1468 }
1469
1470 static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1471 {
1472         SpaceNode *snode = CTX_wm_space_node(C);
1473         bNode *node;
1474         int hidden;
1475
1476         /* sanity checking (poll callback checks this already) */
1477         if ((snode == NULL) || (snode->edittree == NULL))
1478                 return OPERATOR_CANCELLED;
1479
1480         ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
1481
1482         /* Toggle for all selected nodes */
1483         hidden = 0;
1484         for (node = snode->edittree->nodes.first; node; node = node->next) {
1485                 if (node->flag & SELECT) {
1486                         if (node_has_hidden_sockets(node)) {
1487                                 hidden = 1;
1488                                 break;
1489                         }
1490                 }
1491         }
1492         
1493         for (node = snode->edittree->nodes.first; node; node = node->next) {
1494                 if (node->flag & SELECT) {
1495                         node_set_hidden_sockets(snode, node, !hidden);
1496                 }
1497         }
1498
1499         ntreeUpdateTree(CTX_data_main(C), snode->edittree);
1500
1501         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1502
1503         return OPERATOR_FINISHED;
1504 }
1505
1506 void NODE_OT_hide_socket_toggle(wmOperatorType *ot)
1507 {
1508         /* identifiers */
1509         ot->name = "Toggle Hidden Node Sockets";
1510         ot->description = "Toggle unused node socket display";
1511         ot->idname = "NODE_OT_hide_socket_toggle";
1512
1513         /* callbacks */
1514         ot->exec = node_socket_toggle_exec;
1515         ot->poll = ED_operator_node_active;
1516
1517         /* flags */
1518         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1519 }
1520
1521 /* ****************** Mute operator *********************** */
1522
1523 static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
1524 {
1525         SpaceNode *snode = CTX_wm_space_node(C);
1526         bNode *node;
1527         bool do_tag_update = false;
1528
1529         ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
1530
1531         for (node = snode->edittree->nodes.first; node; node = node->next) {
1532                 /* Only allow muting of nodes having a mute func! */
1533                 if ((node->flag & SELECT) && node->typeinfo->update_internal_links) {
1534                         node->flag ^= NODE_MUTED;
1535                         snode_update(snode, node);
1536                         do_tag_update |= (do_tag_update || node_connected_to_output(snode->edittree, node));
1537                 }
1538         }
1539         
1540         snode_notify(C, snode);
1541         if (do_tag_update) {
1542                 snode_dag_update(C, snode);
1543         }
1544         
1545         return OPERATOR_FINISHED;
1546 }
1547
1548 void NODE_OT_mute_toggle(wmOperatorType *ot)
1549 {
1550         /* identifiers */
1551         ot->name = "Toggle Node Mute";
1552         ot->description = "Toggle muting of the nodes";
1553         ot->idname = "NODE_OT_mute_toggle";
1554         
1555         /* callbacks */
1556         ot->exec = node_mute_exec;
1557         ot->poll = ED_operator_node_editable;
1558         
1559         /* flags */
1560         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1561 }
1562
1563 /* ****************** Delete operator ******************* */
1564
1565 static int node_delete_exec(bContext *C, wmOperator *UNUSED(op))
1566 {
1567         SpaceNode *snode = CTX_wm_space_node(C);
1568         bNode *node, *next;
1569         bool do_tag_update = false;
1570
1571         ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
1572
1573         for (node = snode->edittree->nodes.first; node; node = next) {
1574                 next = node->next;
1575                 if (node->flag & SELECT) {
1576                         /* check id user here, nodeFreeNode is called for free dbase too */
1577                         do_tag_update |= (do_tag_update || node_connected_to_output(snode->edittree, node));
1578                         if (node->id)
1579                                 id_us_min(node->id);
1580                         nodeFreeNode(snode->edittree, node);
1581                 }
1582         }
1583         
1584         ntreeUpdateTree(CTX_data_main(C), snode->edittree);
1585
1586         snode_notify(C, snode);
1587         if (do_tag_update) {
1588                 snode_dag_update(C, snode);
1589         }
1590         
1591         return OPERATOR_FINISHED;
1592 }
1593
1594 void NODE_OT_delete(wmOperatorType *ot)
1595 {
1596         /* identifiers */
1597         ot->name = "Delete";
1598         ot->description = "Delete selected nodes";
1599         ot->idname = "NODE_OT_delete";
1600         
1601         /* api callbacks */
1602         ot->exec = node_delete_exec;
1603         ot->poll = ED_operator_node_editable;
1604         
1605         /* flags */
1606         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1607 }
1608
1609 /* ****************** Switch View ******************* */
1610
1611 static int node_switch_view_poll(bContext *C)
1612 {
1613         SpaceNode *snode = CTX_wm_space_node(C);
1614
1615         if (snode && snode->edittree)
1616                 return true;
1617
1618         return false;
1619 }
1620
1621 static int node_switch_view_exec(bContext *C, wmOperator *UNUSED(op))
1622 {
1623         SpaceNode *snode = CTX_wm_space_node(C);
1624         bNode *node, *next;
1625
1626         for (node = snode->edittree->nodes.first; node; node = next) {
1627                 next = node->next;
1628                 if (node->flag & SELECT) {
1629                         /* call the update function from the Switch View node */
1630                         node->update = NODE_UPDATE_OPERATOR;
1631                 }
1632         }
1633
1634         ntreeUpdateTree(CTX_data_main(C), snode->edittree);
1635
1636         snode_notify(C, snode);
1637         snode_dag_update(C, snode);
1638
1639         return OPERATOR_FINISHED;
1640 }
1641
1642 void NODE_OT_switch_view_update(wmOperatorType *ot)
1643 {
1644         /* identifiers */
1645         ot->name = "Update Views";
1646         ot->description = "Update views of selected node";
1647         ot->idname = "NODE_OT_switch_view_update";
1648
1649         /* api callbacks */
1650         ot->exec = node_switch_view_exec;
1651         ot->poll = node_switch_view_poll;
1652
1653         /* flags */
1654         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1655 }
1656
1657 /* ****************** Delete with reconnect ******************* */
1658 static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
1659 {
1660         SpaceNode *snode = CTX_wm_space_node(C);
1661         bNode *node, *next;
1662
1663         ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
1664
1665         for (node = snode->edittree->nodes.first; node; node = next) {
1666                 next = node->next;
1667                 if (node->flag & SELECT) {
1668                         nodeInternalRelink(snode->edittree, node);
1669                         
1670                         /* check id user here, nodeFreeNode is called for free dbase too */
1671                         if (node->id)
1672                                 id_us_min(node->id);
1673                         nodeFreeNode(snode->edittree, node);
1674                 }
1675         }
1676
1677         ntreeUpdateTree(CTX_data_main(C), snode->edittree);
1678
1679         snode_notify(C, snode);
1680         snode_dag_update(C, snode);
1681
1682         return OPERATOR_FINISHED;
1683 }
1684
1685 void NODE_OT_delete_reconnect(wmOperatorType *ot)
1686 {
1687         /* identifiers */
1688         ot->name = "Delete with Reconnect";
1689         ot->description = "Delete nodes; will reconnect nodes as if deletion was muted";
1690         ot->idname = "NODE_OT_delete_reconnect";
1691
1692         /* api callbacks */
1693         ot->exec = node_delete_reconnect_exec;
1694         ot->poll = ED_operator_node_editable;
1695
1696         /* flags */
1697         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1698 }
1699
1700
1701 /* ****************** File Output Add Socket  ******************* */
1702
1703 static int node_output_file_add_socket_exec(bContext *C, wmOperator *op)
1704 {
1705         Scene *scene = CTX_data_scene(C);
1706         SpaceNode *snode = CTX_wm_space_node(C);
1707         PointerRNA ptr = CTX_data_pointer_get(C, "node");
1708         bNodeTree *ntree = NULL;
1709         bNode *node = NULL;
1710         char file_path[MAX_NAME];
1711
1712         if (ptr.data) {
1713                 node = ptr.data;
1714                 ntree = ptr.id.data;
1715         }
1716         else if (snode && snode->edittree) {
1717                 ntree = snode->edittree;
1718                 node = nodeGetActive(snode->edittree);
1719         }
1720
1721         if (!node || node->type != CMP_NODE_OUTPUT_FILE)
1722                 return OPERATOR_CANCELLED;
1723
1724         RNA_string_get(op->ptr, "file_path", file_path);
1725         ntreeCompositOutputFileAddSocket(ntree, node, file_path, &scene->r.im_format);
1726
1727         snode_notify(C, snode);
1728
1729         return OPERATOR_FINISHED;
1730 }
1731
1732 void NODE_OT_output_file_add_socket(wmOperatorType *ot)
1733 {
1734         /* identifiers */
1735         ot->name = "Add File Node Socket";
1736         ot->description = "Add a new input to a file output node";
1737         ot->idname = "NODE_OT_output_file_add_socket";
1738
1739         /* callbacks */
1740         ot->exec = node_output_file_add_socket_exec;
1741         ot->poll = composite_node_editable;
1742
1743         /* flags */
1744         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1745
1746         RNA_def_string(ot->srna, "file_path", "Image", MAX_NAME, "File Path", "Sub-path of the output file");
1747 }
1748
1749 /* ****************** Multi File Output Remove Socket  ******************* */
1750
1751 static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *UNUSED(op))
1752 {
1753         SpaceNode *snode = CTX_wm_space_node(C);
1754         PointerRNA ptr = CTX_data_pointer_get(C, "node");
1755         bNodeTree *ntree = NULL;
1756         bNode *node = NULL;
1757         
1758         if (ptr.data) {
1759                 node = ptr.data;
1760                 ntree = ptr.id.data;
1761         }
1762         else if (snode && snode->edittree) {
1763                 ntree = snode->edittree;
1764                 node = nodeGetActive(snode->edittree);
1765         }
1766
1767         if (!node || node->type != CMP_NODE_OUTPUT_FILE)
1768                 return OPERATOR_CANCELLED;
1769         
1770         if (!ntreeCompositOutputFileRemoveActiveSocket(ntree, node))
1771                 return OPERATOR_CANCELLED;
1772         
1773         snode_notify(C, snode);
1774         
1775         return OPERATOR_FINISHED;
1776 }
1777
1778 void NODE_OT_output_file_remove_active_socket(wmOperatorType *ot)
1779 {
1780         /* identifiers */
1781         ot->name = "Remove File Node Socket";
1782         ot->description = "Remove active input from a file output node";
1783         ot->idname = "NODE_OT_output_file_remove_active_socket";
1784         
1785         /* callbacks */
1786         ot->exec = node_output_file_remove_active_socket_exec;
1787         ot->poll = composite_node_editable;
1788         
1789         /* flags */
1790         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1791 }
1792
1793 /* ****************** Multi File Output Move Socket  ******************* */
1794
1795 static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
1796 {
1797         SpaceNode *snode = CTX_wm_space_node(C);
1798         PointerRNA ptr = CTX_data_pointer_get(C, "node");
1799         bNode *node = NULL;
1800         NodeImageMultiFile *nimf;
1801         bNodeSocket *sock;
1802         int direction;
1803         
1804         if (ptr.data)
1805                 node = ptr.data;
1806         else if (snode && snode->edittree)
1807                 node = nodeGetActive(snode->edittree);
1808
1809         if (!node || node->type != CMP_NODE_OUTPUT_FILE)
1810                 return OPERATOR_CANCELLED;
1811
1812         nimf = node->storage;
1813         
1814         sock = BLI_findlink(&node->inputs, nimf->active_input);
1815         if (!sock)
1816                 return OPERATOR_CANCELLED;
1817         
1818         direction = RNA_enum_get(op->ptr, "direction");
1819         
1820         if (direction == 1) {
1821                 bNodeSocket *before = sock->prev;
1822                 if (!before)
1823                         return OPERATOR_CANCELLED;
1824                 BLI_remlink(&node->inputs, sock);
1825                 BLI_insertlinkbefore(&node->inputs, before, sock);
1826                 nimf->active_input--;
1827         }
1828         else {
1829                 bNodeSocket *after = sock->next;
1830                 if (!after)
1831                         return OPERATOR_CANCELLED;
1832                 BLI_remlink(&node->inputs, sock);
1833                 BLI_insertlinkafter(&node->inputs, after, sock);
1834                 nimf->active_input++;
1835         }
1836         
1837         snode_notify(C, snode);
1838         
1839         return OPERATOR_FINISHED;
1840 }
1841
1842 void NODE_OT_output_file_move_active_socket(wmOperatorType *ot)
1843 {
1844         static const EnumPropertyItem direction_items[] = {
1845                 {1, "UP", 0, "Up", ""},
1846                 {2, "DOWN", 0, "Down", ""},
1847                 { 0, NULL, 0, NULL, NULL }
1848         };
1849         
1850         /* identifiers */
1851         ot->name = "Move File Node Socket";
1852         ot->description = "Move the active input of a file output node up or down the list";
1853         ot->idname = "NODE_OT_output_file_move_active_socket";
1854         
1855         /* callbacks */
1856         ot->exec = node_output_file_move_active_socket_exec;
1857         ot->poll = composite_node_editable;
1858         
1859         /* flags */
1860         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1861         
1862         RNA_def_enum(ot->srna, "direction", direction_items, 2, "Direction", "");
1863 }
1864
1865 /* ****************** Copy Node Color ******************* */
1866
1867 static int node_copy_color_exec(bContext *C, wmOperator *UNUSED(op))
1868 {
1869         SpaceNode *snode = CTX_wm_space_node(C);
1870         bNodeTree *ntree = snode->edittree;
1871         bNode *node, *tnode;
1872         
1873         if (!ntree)
1874                 return OPERATOR_CANCELLED;
1875         node = nodeGetActive(ntree);
1876         if (!node)
1877                 return OPERATOR_CANCELLED;
1878         
1879         for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
1880                 if (tnode->flag & NODE_SELECT && tnode != node) {
1881                         if (node->flag & NODE_CUSTOM_COLOR) {
1882                                 tnode->flag |= NODE_CUSTOM_COLOR;
1883                                 copy_v3_v3(tnode->color, node->color);
1884                         }
1885                         else
1886                                 tnode->flag &= ~NODE_CUSTOM_COLOR;
1887                 }
1888         }
1889
1890         ED_node_sort(ntree);
1891         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1892
1893         return OPERATOR_FINISHED;
1894 }
1895
1896 void NODE_OT_node_copy_color(wmOperatorType *ot)
1897 {
1898         /* identifiers */
1899         ot->name = "Copy Color";
1900         ot->description = "Copy color to all selected nodes";
1901         ot->idname = "NODE_OT_node_copy_color";
1902
1903         /* api callbacks */
1904         ot->exec = node_copy_color_exec;
1905         ot->poll = ED_operator_node_editable;
1906
1907         /* flags */
1908         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1909 }
1910
1911 /* ****************** Copy to clipboard ******************* */
1912
1913 static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
1914 {
1915         SpaceNode *snode = CTX_wm_space_node(C);
1916         bNodeTree *ntree = snode->edittree;
1917         bNode *node;
1918         bNodeLink *link, *newlink;
1919
1920         ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
1921
1922         /* clear current clipboard */
1923         BKE_node_clipboard_clear();
1924         BKE_node_clipboard_init(ntree);
1925
1926         for (node = ntree->nodes.first; node; node = node->next) {
1927                 if (node->flag & SELECT) {
1928                         bNode *new_node;
1929                         new_node = nodeCopyNode(NULL, node);
1930                         BKE_node_clipboard_add_node(new_node);
1931                 }
1932         }
1933
1934         for (node = ntree->nodes.first; node; node = node->next) {
1935                 if (node->flag & SELECT) {
1936                         bNode *new_node = node->new_node;
1937                         
1938                         /* ensure valid pointers */
1939                         if (new_node->parent) {
1940                                 /* parent pointer must be redirected to new node or detached if parent is not copied */
1941                                 if (new_node->parent->flag & NODE_SELECT) {
1942                                         new_node->parent = new_node->parent->new_node;
1943                                 }
1944                                 else {
1945                                         nodeDetachNode(new_node);
1946                                 }
1947                         }
1948                 }
1949         }
1950
1951         /* copy links between selected nodes
1952          * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
1953          */
1954         for (link = ntree->links.first; link; link = link->next) {
1955                 /* This creates new links between copied nodes. */
1956                 if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
1957                     link->fromnode && (link->fromnode->flag & NODE_SELECT))
1958                 {
1959                         newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
1960                         newlink->flag = link->flag;
1961                         newlink->tonode = link->tonode->new_node;
1962                         newlink->tosock = link->tosock->new_sock;
1963                         newlink->fromnode = link->fromnode->new_node;
1964                         newlink->fromsock = link->fromsock->new_sock;
1965
1966                         BKE_node_clipboard_add_link(newlink);
1967                 }
1968         }
1969
1970         return OPERATOR_FINISHED;
1971 }
1972
1973 void NODE_OT_clipboard_copy(wmOperatorType *ot)
1974 {
1975         /* identifiers */
1976         ot->name = "Copy to Clipboard";
1977         ot->description = "Copies selected nodes to the clipboard";
1978         ot->idname = "NODE_OT_clipboard_copy";
1979
1980         /* api callbacks */
1981         ot->exec = node_clipboard_copy_exec;
1982         ot->poll = ED_operator_node_active;
1983
1984         /* flags */
1985         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1986 }
1987
1988 /* ****************** Paste from clipboard ******************* */
1989
1990 static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
1991 {
1992         SpaceNode *snode = CTX_wm_space_node(C);
1993         bNodeTree *ntree = snode->edittree;
1994         const ListBase *clipboard_nodes_lb;
1995         const ListBase *clipboard_links_lb;
1996         bNode *node;
1997         bNodeLink *link;
1998         int num_nodes;
1999         float center[2];
2000         bool is_clipboard_valid, all_nodes_valid;
2001
2002         /* validate pointers in the clipboard */
2003         is_clipboard_valid = BKE_node_clipboard_validate();
2004         clipboard_nodes_lb = BKE_node_clipboard_get_nodes();
2005         clipboard_links_lb = BKE_node_clipboard_get_links();
2006
2007         if (BLI_listbase_is_empty(clipboard_nodes_lb)) {
2008                 BKE_report(op->reports, RPT_ERROR, "Clipboard is empty");
2009                 return OPERATOR_CANCELLED;
2010         }
2011
2012         if (BKE_node_clipboard_get_type() != ntree->type) {
2013                 BKE_report(op->reports, RPT_ERROR, "Clipboard nodes are an incompatible type");
2014                 return OPERATOR_CANCELLED;
2015         }
2016
2017         /* only warn */
2018         if (is_clipboard_valid == false) {
2019                 BKE_report(op->reports, RPT_WARNING, "Some nodes references could not be restored, will be left empty");
2020         }
2021
2022         /* make sure all clipboard nodes would be valid in the target tree */
2023         all_nodes_valid = true;
2024         for (node = clipboard_nodes_lb->first; node; node = node->next) {
2025                 if (!node->typeinfo->poll_instance || !node->typeinfo->poll_instance(node, ntree)) {
2026                         all_nodes_valid = false;
2027                         BKE_reportf(op->reports, RPT_ERROR, "Cannot add node %s into node tree %s", node->name, ntree->id.name + 2);
2028                 }
2029         }
2030         if (!all_nodes_valid)
2031                 return OPERATOR_CANCELLED;
2032
2033         ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
2034
2035         /* deselect old nodes */
2036         node_deselect_all(snode);
2037
2038         /* calculate "barycenter" for placing on mouse cursor */
2039         zero_v2(center);
2040         for (node = clipboard_nodes_lb->first, num_nodes = 0; node; node = node->next, num_nodes++) {
2041                 center[0] += BLI_rctf_cent_x(&node->totr);
2042                 center[1] += BLI_rctf_cent_y(&node->totr);
2043         }
2044         mul_v2_fl(center, 1.0 / num_nodes);
2045
2046         /* copy nodes from clipboard */
2047         for (node = clipboard_nodes_lb->first; node; node = node->next) {
2048                 bNode *new_node = nodeCopyNode(ntree, node);
2049
2050                 /* needed since nodeCopyNode() doesn't increase ID's */
2051                 id_us_plus(node->id);
2052
2053                 /* pasted nodes are selected */
2054                 nodeSetSelected(new_node, true);
2055         }
2056         
2057         /* reparent copied nodes */
2058         for (node = clipboard_nodes_lb->first; node; node = node->next) {
2059                 bNode *new_node = node->new_node;
2060                 if (new_node->parent)
2061                         new_node->parent = new_node->parent->new_node;
2062         }
2063
2064         for (link = clipboard_links_lb->first; link; link = link->next) {
2065                 nodeAddLink(ntree, link->fromnode->new_node, link->fromsock->new_sock,
2066                             link->tonode->new_node, link->tosock->new_sock);
2067         }
2068
2069         ntreeUpdateTree(CTX_data_main(C), snode->edittree);
2070
2071         snode_notify(C, snode);
2072         snode_dag_update(C, snode);
2073
2074         return OPERATOR_FINISHED;
2075 }
2076
2077 void NODE_OT_clipboard_paste(wmOperatorType *ot)
2078 {
2079         /* identifiers */
2080         ot->name = "Paste from Clipboard";
2081         ot->description = "Pastes nodes from the clipboard to the active node tree";
2082         ot->idname = "NODE_OT_clipboard_paste";
2083
2084         /* api callbacks */
2085         ot->exec = node_clipboard_paste_exec;
2086         ot->poll = ED_operator_node_editable;
2087
2088         /* flags */
2089         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2090 }
2091
2092 /********************** Add interface socket operator *********************/
2093
2094 static bNodeSocket *ntree_get_active_interface_socket(ListBase *lb)
2095 {
2096         bNodeSocket *sock;
2097         for (sock = lb->first; sock; sock = sock->next)
2098                 if (sock->flag & SELECT)
2099                         return sock;
2100         return NULL;
2101 }
2102
2103 static int ntree_socket_add_exec(bContext *C, wmOperator *op)
2104 {
2105         SpaceNode *snode = CTX_wm_space_node(C);
2106         bNodeTree *ntree = snode->edittree;
2107         int in_out = RNA_enum_get(op->ptr, "in_out");
2108         PointerRNA ntree_ptr;
2109         bNodeSocket *sock, *tsock, *active_sock;
2110         const char *default_name;
2111         
2112         RNA_id_pointer_create((ID *)ntree, &ntree_ptr);
2113         
2114         if (in_out == SOCK_IN) {
2115                 active_sock = ntree_get_active_interface_socket(&ntree->inputs);
2116                 default_name = "Input";
2117         }
2118         else {
2119                 active_sock = ntree_get_active_interface_socket(&ntree->outputs);
2120                 default_name = "Output";
2121         }
2122         
2123         if (active_sock) {
2124                 /* insert a copy of the active socket right after it */
2125                 sock = ntreeInsertSocketInterface(ntree, in_out, active_sock->idname, active_sock->next, active_sock->name);
2126                 /* XXX this only works for actual sockets, not interface templates! */
2127                 /*nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr);*/
2128         }
2129         else {
2130                 /* XXX TODO define default socket type for a tree! */
2131                 sock = ntreeAddSocketInterface(ntree, in_out, "NodeSocketFloat", default_name);
2132         }
2133         
2134         /* deactivate sockets (has to check both lists) */
2135         for (tsock = ntree->inputs.first; tsock; tsock = tsock->next)
2136                 tsock->flag &= ~SELECT;
2137         for (tsock = ntree->outputs.first; tsock; tsock = tsock->next)
2138                 tsock->flag &= ~SELECT;
2139         /* make the new socket active */
2140         sock->flag |= SELECT;
2141         
2142         ntreeUpdateTree(CTX_data_main(C), ntree);
2143
2144         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
2145         
2146         return OPERATOR_FINISHED;
2147 }
2148
2149 void NODE_OT_tree_socket_add(wmOperatorType *ot)
2150 {
2151         /* identifiers */
2152         ot->name = "Add Node Tree Interface Socket";
2153         ot->description = "Add an input or output socket to the current node tree";
2154         ot->idname = "NODE_OT_tree_socket_add";
2155         
2156         /* api callbacks */
2157         ot->exec = ntree_socket_add_exec;
2158         ot->poll = ED_operator_node_editable;
2159         
2160         /* flags */
2161         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2162         
2163         RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", "");
2164 }
2165
2166 /********************** Remove interface socket operator *********************/
2167
2168 static int ntree_socket_remove_exec(bContext *C, wmOperator *UNUSED(op))
2169 {
2170         SpaceNode *snode = CTX_wm_space_node(C);
2171         bNodeTree *ntree = snode->edittree;
2172         bNodeSocket *iosock, *active_sock;
2173         
2174         iosock = ntree_get_active_interface_socket(&ntree->inputs);
2175         if (!iosock)
2176                 iosock = ntree_get_active_interface_socket(&ntree->outputs);
2177         if (!iosock)
2178                 return OPERATOR_CANCELLED;
2179         
2180         /* preferably next socket becomes active, otherwise try previous socket */
2181         active_sock = (iosock->next ? iosock->next : iosock->prev);
2182         ntreeRemoveSocketInterface(ntree, iosock);
2183         
2184         /* set active socket */
2185         if (active_sock)
2186                 active_sock->flag |= SELECT;
2187         
2188         ntreeUpdateTree(CTX_data_main(C), ntree);
2189
2190         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
2191         
2192         return OPERATOR_FINISHED;
2193 }
2194
2195 void NODE_OT_tree_socket_remove(wmOperatorType *ot)
2196 {
2197         /* identifiers */
2198         ot->name = "Remove Node Tree Interface Socket";
2199         ot->description = "Remove an input or output socket to the current node tree";
2200         ot->idname = "NODE_OT_tree_socket_remove";
2201         
2202         /* api callbacks */
2203         ot->exec = ntree_socket_remove_exec;
2204         ot->poll = ED_operator_node_editable;
2205         
2206         /* flags */
2207         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2208 }
2209
2210 /********************** Move interface socket operator *********************/
2211
2212 static const EnumPropertyItem move_direction_items[] = {
2213         { 1, "UP", 0, "Up", "" },
2214         { 2, "DOWN", 0, "Down", "" },
2215         { 0, NULL, 0, NULL, NULL },
2216 };
2217
2218 static int ntree_socket_move_exec(bContext *C, wmOperator *op)
2219 {
2220         SpaceNode *snode = CTX_wm_space_node(C);
2221         bNodeTree *ntree = snode->edittree;
2222         int direction = RNA_enum_get(op->ptr, "direction");
2223         bNodeSocket *iosock;
2224         ListBase *lb;
2225         
2226         lb = &ntree->inputs;
2227         iosock = ntree_get_active_interface_socket(lb);
2228         if (!iosock) {
2229                 lb = &ntree->outputs;
2230                 iosock = ntree_get_active_interface_socket(lb);
2231         }
2232         if (!iosock)
2233                 return OPERATOR_CANCELLED;
2234         
2235         switch (direction) {
2236                 case 1:
2237                 {       /* up */
2238                         bNodeSocket *before = iosock->prev;
2239                         BLI_remlink(lb, iosock);
2240                         if (before)
2241                                 BLI_insertlinkbefore(lb, before, iosock);
2242                         else
2243                                 BLI_addhead(lb, iosock);
2244                         break;
2245                 }
2246                 case 2:
2247                 {       /* down */
2248                         bNodeSocket *after = iosock->next;
2249                         BLI_remlink(lb, iosock);
2250                         if (after)
2251                                 BLI_insertlinkafter(lb, after, iosock);
2252                         else
2253                                 BLI_addtail(lb, iosock);
2254                         break;
2255                 }
2256         }
2257         
2258         ntreeUpdateTree(CTX_data_main(C), ntree);
2259
2260         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
2261         
2262         return OPERATOR_FINISHED;
2263 }
2264
2265 void NODE_OT_tree_socket_move(wmOperatorType *ot)
2266 {
2267         /* identifiers */
2268         ot->name = "Move Node Tree Socket";
2269         ot->description = "Move a socket up or down in the current node tree's sockets stack";
2270         ot->idname = "NODE_OT_tree_socket_move";
2271         
2272         /* api callbacks */
2273         ot->exec = ntree_socket_move_exec;
2274         ot->poll = ED_operator_node_editable;
2275         
2276         /* flags */
2277         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2278         
2279         RNA_def_enum(ot->srna, "direction", move_direction_items, 1, "Direction", "");
2280 }
2281
2282 /* ********************** Shader Script Update ******************/
2283
2284 static int node_shader_script_update_poll(bContext *C)
2285 {
2286         Scene *scene = CTX_data_scene(C);
2287         RenderEngineType *type = RE_engines_find(scene->r.engine);
2288         SpaceNode *snode = CTX_wm_space_node(C);
2289         bNode *node;
2290         Text *text;
2291
2292         /* test if we have a render engine that supports shaders scripts */
2293         if (!(type && type->update_script_node))
2294                 return 0;
2295
2296         /* see if we have a shader script node in context */
2297         node = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data;
2298
2299         if (!node && snode && snode->edittree)
2300                 node = nodeGetActive(snode->edittree);
2301
2302         if (node && node->type == SH_NODE_SCRIPT) {
2303                 NodeShaderScript *nss = node->storage;
2304
2305                 if (node->id || nss->filepath[0]) {
2306                         return ED_operator_node_editable(C);
2307                 }
2308         }
2309
2310         /* see if we have a text datablock in context */
2311         text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
2312         if (text)
2313                 return 1;
2314
2315         /* we don't check if text datablock is actually in use, too slow for poll */
2316
2317         return 0;
2318 }
2319
2320 /* recursively check for script nodes in groups using this text and update */
2321 static bool node_shader_script_update_text_recursive(RenderEngine *engine, RenderEngineType *type, bNodeTree *ntree, Text *text)
2322 {
2323         bool found = false;
2324         bNode *node;
2325         
2326         ntree->done = true;
2327         
2328         /* update each script that is using this text datablock */
2329         for (node = ntree->nodes.first; node; node = node->next) {
2330                 if (node->type == NODE_GROUP) {
2331                         bNodeTree *ngroup = (bNodeTree *)node->id;
2332                         if (ngroup && !ngroup->done)
2333                                 found |= node_shader_script_update_text_recursive(engine, type, ngroup, text);
2334                 }
2335                 else if (node->type == SH_NODE_SCRIPT && node->id == &text->id) {
2336                         type->update_script_node(engine, ntree, node);
2337                         found = true;
2338                 }
2339         }
2340         
2341         return found;
2342 }
2343
2344 static int node_shader_script_update_exec(bContext *C, wmOperator *op)
2345 {
2346         Main *bmain = CTX_data_main(C);
2347         Scene *scene = CTX_data_scene(C);
2348         SpaceNode *snode = CTX_wm_space_node(C);
2349         PointerRNA nodeptr = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript);
2350         bNodeTree *ntree_base = NULL;
2351         bNode *node = NULL;
2352         RenderEngine *engine;
2353         RenderEngineType *type;
2354         bool found = false;
2355
2356         /* setup render engine */
2357         type = RE_engines_find(scene->r.engine);
2358         engine = RE_engine_create(type);
2359         engine->reports = op->reports;
2360
2361         /* get node */
2362         if (nodeptr.data) {
2363                 ntree_base = nodeptr.id.data;
2364                 node = nodeptr.data;
2365         }
2366         else if (snode && snode->edittree) {
2367                 ntree_base = snode->edittree;
2368                 node = nodeGetActive(snode->edittree);
2369         }
2370
2371         if (node) {
2372                 /* update single node */
2373                 type->update_script_node(engine, ntree_base, node);
2374
2375                 found = true;
2376         }
2377         else {
2378                 /* update all nodes using text datablock */
2379                 Text *text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
2380
2381                 if (text) {
2382                         /* clear flags for recursion check */
2383                         FOREACH_NODETREE(bmain, ntree, id) {
2384                                 if (ntree->type == NTREE_SHADER)
2385                                         ntree->done = false;
2386                         } FOREACH_NODETREE_END
2387                         
2388                         FOREACH_NODETREE(bmain, ntree, id) {
2389                                 if (ntree->type == NTREE_SHADER) {
2390                                         if (!ntree->done)
2391                                                 found |= node_shader_script_update_text_recursive(engine, type, ntree, text);
2392                                 }
2393                         } FOREACH_NODETREE_END
2394
2395                         if (!found)
2396                                 BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done");
2397                 }
2398         }
2399
2400         RE_engine_free(engine);
2401
2402         return (found) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
2403 }
2404
2405 void NODE_OT_shader_script_update(wmOperatorType *ot)
2406 {
2407         /* identifiers */
2408         ot->name = "Script Node Update";
2409         ot->description = "Update shader script node with new sockets and options from the script";
2410         ot->idname = "NODE_OT_shader_script_update";
2411
2412         /* api callbacks */
2413         ot->exec = node_shader_script_update_exec;
2414         ot->poll = node_shader_script_update_poll;
2415
2416         /* flags */
2417         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2418 }
2419
2420 /* ********************** Viewer border ******************/
2421
2422 static void viewer_border_corner_to_backdrop(SpaceNode *snode, ARegion *ar, int x, int y,
2423                                              int backdrop_width, int backdrop_height,
2424                                              float *fx, float *fy)
2425 {
2426         float bufx, bufy;
2427
2428         bufx = backdrop_width * snode->zoom;
2429         bufy = backdrop_height * snode->zoom;
2430
2431         *fx = (bufx > 0.0f ? ((float) x - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f);
2432         *fy = (bufy > 0.0f ? ((float) y - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f);
2433 }
2434
2435 static int viewer_border_exec(bContext *C, wmOperator *op)
2436 {
2437         Image *ima;
2438         void *lock;
2439         ImBuf *ibuf;
2440
2441         ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
2442
2443         ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
2444         ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
2445
2446         if (ibuf) {
2447                 ARegion *ar = CTX_wm_region(C);
2448                 SpaceNode *snode = CTX_wm_space_node(C);
2449                 bNodeTree *btree = snode->nodetree;
2450                 rcti rect;
2451                 rctf rectf;
2452
2453                 /* get border from operator */
2454                 WM_operator_properties_border_to_rcti(op, &rect);
2455
2456                 /* convert border to unified space within backdrop image */
2457                 viewer_border_corner_to_backdrop(snode, ar, rect.xmin, rect.ymin, ibuf->x, ibuf->y,
2458                                                  &rectf.xmin, &rectf.ymin);
2459
2460                 viewer_border_corner_to_backdrop(snode, ar, rect.xmax, rect.ymax, ibuf->x, ibuf->y,
2461                                                  &rectf.xmax, &rectf.ymax);
2462
2463                 /* clamp coordinates */
2464                 rectf.xmin = max_ff(rectf.xmin, 0.0f);
2465                 rectf.ymin = max_ff(rectf.ymin, 0.0f);
2466                 rectf.xmax = min_ff(rectf.xmax, 1.0f);
2467                 rectf.ymax = min_ff(rectf.ymax, 1.0f);
2468
2469                 if (rectf.xmin < rectf.xmax && rectf.ymin < rectf.ymax) {
2470                         btree->viewer_border = rectf;
2471
2472                         if (rectf.xmin == 0.0f && rectf.ymin == 0.0f &&
2473                             rectf.xmax == 1.0f && rectf.ymax == 1.0f)
2474                         {
2475                                 btree->flag &= ~NTREE_VIEWER_BORDER;
2476                         }
2477                         else {
2478                                 btree->flag |= NTREE_VIEWER_BORDER;
2479                         }
2480
2481                         snode_notify(C, snode);
2482                         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
2483                 }
2484                 else {
2485                         btree->flag &= ~NTREE_VIEWER_BORDER;
2486                 }
2487         }
2488
2489         BKE_image_release_ibuf(ima, ibuf, lock);
2490
2491         return OPERATOR_FINISHED;
2492 }
2493
2494 void NODE_OT_viewer_border(wmOperatorType *ot)
2495 {
2496         /* identifiers */
2497         ot->name = "Viewer Border";
2498         ot->description = "Set the boundaries for viewer operations";
2499         ot->idname = "NODE_OT_viewer_border";
2500
2501         /* api callbacks */
2502         ot->invoke = WM_gesture_border_invoke;
2503         ot->exec = viewer_border_exec;
2504         ot->modal = WM_gesture_border_modal;
2505         ot->cancel = WM_gesture_border_cancel;
2506         ot->poll = composite_node_active;
2507
2508         /* flags */
2509         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2510
2511         /* properties */
2512         WM_operator_properties_gesture_border_select(ot);
2513 }
2514
2515 static int clear_viewer_border_exec(bContext *C, wmOperator *UNUSED(op))
2516 {
2517         SpaceNode *snode = CTX_wm_space_node(C);
2518         bNodeTree *btree = snode->nodetree;
2519
2520         btree->flag &= ~NTREE_VIEWER_BORDER;
2521         snode_notify(C, snode);
2522         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
2523
2524         return OPERATOR_FINISHED;
2525 }
2526
2527 void NODE_OT_clear_viewer_border(wmOperatorType *ot)
2528 {
2529         /* identifiers */
2530         ot->name = "Clear Viewer Border";
2531         ot->description = "Clear the boundaries for viewer operations";
2532         ot->idname = "NODE_OT_clear_viewer_border";
2533
2534         /* api callbacks */
2535         ot->exec = clear_viewer_border_exec;
2536         ot->poll = composite_node_active;
2537
2538         /* flags */
2539         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2540 }