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