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