code cleanup
[blender-staging.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                         treetype->get_from_context(C, treetype, &ntree, &id, &from);
535         }
536         
537         if (snode->nodetree != ntree || snode->id != id || snode->from != snode->from) {
538                 ED_node_tree_start(snode, ntree, id, from);
539         }
540 }
541
542 void snode_update(SpaceNode *snode, bNode *node)
543 {
544         bNodeTreePath *path;
545         
546         /* XXX this only updates nodes in the current node space tree path.
547          * The function supposedly should update any potential group node linking to changed tree,
548          * this really requires a working depsgraph ...
549          */
550         
551         /* update all edited group nodes */
552         path = snode->treepath.last;
553         if (path) {
554                 bNodeTree *ngroup = path->nodetree;
555                 for (path = path->prev; path; path = path->prev) {
556                         nodeUpdateID(path->nodetree, (ID *)ngroup);
557                         ngroup = path->nodetree;
558                 }
559         }
560
561         if (node)
562                 nodeUpdate(snode->edittree, node);
563 }
564
565 void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
566 {
567         int was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE);
568
569         nodeSetActive(ntree, node);
570         
571         if (node->type != NODE_GROUP) {
572                 int was_output = (node->flag & NODE_DO_OUTPUT);
573                 int do_update = 0;
574                 
575                 /* generic node group output: set node as active output */
576                 if (node->type == NODE_GROUP_OUTPUT) {
577                         bNode *tnode;
578                         for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
579                                 if (tnode->type == NODE_GROUP_OUTPUT)
580                                         tnode->flag &= ~NODE_DO_OUTPUT;
581                         
582                         node->flag |= NODE_DO_OUTPUT;
583                         if (!was_output)
584                                 do_update = 1;
585                 }
586                 
587                 /* tree specific activate calls */
588                 if (ntree->type == NTREE_SHADER) {
589                         /* when we select a material, active texture is cleared, for buttons */
590                         if (node->id && ELEM3(GS(node->id->name), ID_MA, ID_LA, ID_WO))
591                                 nodeClearActiveID(ntree, ID_TE);
592                         
593                         if (node->type == SH_NODE_OUTPUT) {
594                                 bNode *tnode;
595                                 
596                                 for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
597                                         if (tnode->type == SH_NODE_OUTPUT)
598                                                 tnode->flag &= ~NODE_DO_OUTPUT;
599                                 
600                                 node->flag |= NODE_DO_OUTPUT;
601                                 if (was_output == 0)
602                                         ED_node_tag_update_nodetree(bmain, ntree);
603                         }
604                         else if (do_update)
605                                 ED_node_tag_update_nodetree(bmain, ntree);
606
607                         /* if active texture changed, free glsl materials */
608                         if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
609                                 Material *ma;
610
611                                 for (ma = bmain->mat.first; ma; ma = ma->id.next)
612                                         if (ma->nodetree && ma->use_nodes && has_nodetree(ma->nodetree, ntree))
613                                                 GPU_material_free(ma);
614
615                                 WM_main_add_notifier(NC_IMAGE, NULL);
616                         }
617
618                         WM_main_add_notifier(NC_MATERIAL | ND_NODES, node->id);
619                 }
620                 else if (ntree->type == NTREE_COMPOSIT) {
621                         /* make active viewer, currently only 1 supported... */
622                         if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
623                                 bNode *tnode;
624                                 
625
626                                 for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
627                                         if (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
628                                                 tnode->flag &= ~NODE_DO_OUTPUT;
629                                 
630                                 node->flag |= NODE_DO_OUTPUT;
631                                 if (was_output == 0)
632                                         ED_node_tag_update_nodetree(bmain, ntree);
633                                 
634                                 /* addnode() doesnt link this yet... */
635                                 node->id = (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
636                         }
637                         else if (node->type == CMP_NODE_R_LAYERS) {
638                                 Scene *scene;
639
640                                 for (scene = bmain->scene.first; scene; scene = scene->id.next) {
641                                         if (scene->nodetree && scene->use_nodes && has_nodetree(scene->nodetree, ntree)) {
642                                                 if (node->id == NULL || node->id == (ID *)scene) {
643                                                         scene->r.actlay = node->custom1;
644                                                 }
645                                         }
646                                 }
647                         }
648                         else if (node->type == CMP_NODE_COMPOSITE) {
649                                 if (was_output == 0) {
650                                         bNode *tnode;
651                                         
652                                         for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
653                                                 if (tnode->type == CMP_NODE_COMPOSITE)
654                                                         tnode->flag &= ~NODE_DO_OUTPUT;
655                                         
656                                         node->flag |= NODE_DO_OUTPUT;
657                                         ED_node_tag_update_nodetree(bmain, ntree);
658                                 }
659                         }
660                         else if (do_update)
661                                 ED_node_tag_update_nodetree(bmain, ntree);
662                 }
663                 else if (ntree->type == NTREE_TEXTURE) {
664                         // XXX
665 #if 0
666                         if (node->id)
667                                 ;  // XXX BIF_preview_changed(-1);
668                         // allqueue(REDRAWBUTSSHADING, 1);
669                         // allqueue(REDRAWIPO, 0);
670 #endif
671                 }
672         }
673 }
674
675 void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree))
676 {
677         /* XXX This does not work due to layout functions relying on node->block,
678          * which only exists during actual drawing. Can we rely on valid totr rects?
679          */
680         /* make sure nodes have correct bounding boxes after transform */
681         /* node_update_nodetree(C, ntree, 0.0f, 0.0f); */
682 }
683
684 /* ***************** generic operator functions for nodes ***************** */
685
686 #if 0 /* UNUSED */
687
688 static int edit_node_poll(bContext *C)
689 {
690         return ED_operator_node_active(C);
691 }
692
693 static void edit_node_properties(wmOperatorType *ot)
694 {
695         /* XXX could node be a context pointer? */
696         RNA_def_string(ot->srna, "node", "", MAX_NAME, "Node", "");
697         RNA_def_int(ot->srna, "socket", 0, 0, MAX_SOCKET, "Socket", "", 0, MAX_SOCKET);
698         RNA_def_enum(ot->srna, "in_out", node_socket_in_out_items, SOCK_IN, "Socket Side", "");
699 }
700
701 static int edit_node_invoke_properties(bContext *C, wmOperator *op)
702 {
703         if (!RNA_struct_property_is_set(op->ptr, "node")) {
704                 bNode *node = CTX_data_pointer_get_type(C, "node", &RNA_Node).data;
705                 if (!node)
706                         return 0;
707                 else
708                         RNA_string_set(op->ptr, "node", node->name);
709         }
710         
711         if (!RNA_struct_property_is_set(op->ptr, "in_out"))
712                 RNA_enum_set(op->ptr, "in_out", SOCK_IN);
713         
714         if (!RNA_struct_property_is_set(op->ptr, "socket"))
715                 RNA_int_set(op->ptr, "socket", 0);
716         
717         return 1;
718 }
719
720 static void edit_node_properties_get(wmOperator *op, bNodeTree *ntree, bNode **rnode, bNodeSocket **rsock, int *rin_out)
721 {
722         bNode *node;
723         bNodeSocket *sock = NULL;
724         char nodename[MAX_NAME];
725         int sockindex;
726         int in_out;
727         
728         RNA_string_get(op->ptr, "node", nodename);
729         node = nodeFindNodebyName(ntree, nodename);
730         
731         in_out = RNA_enum_get(op->ptr, "in_out");
732         
733         sockindex = RNA_int_get(op->ptr, "socket");
734         switch (in_out) {
735                 case SOCK_IN:   sock = BLI_findlink(&node->inputs, sockindex);  break;
736                 case SOCK_OUT:  sock = BLI_findlink(&node->outputs, sockindex); break;
737         }
738         
739         if (rnode)
740                 *rnode = node;
741         if (rsock)
742                 *rsock = sock;
743         if (rin_out)
744                 *rin_out = in_out;
745 }
746 #endif
747
748 /* ************************** Node generic ************** */
749
750 /* is rct in visible part of node? */
751 static bNode *visible_node(SpaceNode *snode, const rctf *rct)
752 {
753         bNode *node;
754         
755         for (node = snode->edittree->nodes.last; node; node = node->prev) {
756                 if (BLI_rctf_isect(&node->totr, rct, NULL))
757                         break;
758         }
759         return node;
760 }
761
762 /* ********************** size widget operator ******************** */
763
764 typedef struct NodeSizeWidget {
765         float mxstart, mystart;
766         float oldlocx, oldlocy;
767         float oldoffsetx, oldoffsety;
768         float oldwidth, oldheight;
769         float oldminiwidth;
770         int directions;
771 } NodeSizeWidget;
772
773 static void node_resize_init(bContext *C, wmOperator *op, const wmEvent *UNUSED(event), bNode *node, int dir)
774 {
775         SpaceNode *snode = CTX_wm_space_node(C);
776         
777         NodeSizeWidget *nsw = MEM_callocN(sizeof(NodeSizeWidget), "size widget op data");
778         
779         op->customdata = nsw;
780         nsw->mxstart = snode->cursor[0];
781         nsw->mystart = snode->cursor[1];
782         
783         /* store old */
784         nsw->oldlocx = node->locx;
785         nsw->oldlocy = node->locy;
786         nsw->oldoffsetx = node->offsetx;
787         nsw->oldoffsety = node->offsety;
788         nsw->oldwidth = node->width;
789         nsw->oldheight = node->height;
790         nsw->oldminiwidth = node->miniwidth;
791         nsw->directions = dir;
792         
793         WM_cursor_modal(CTX_wm_window(C), node_get_resize_cursor(dir));
794         /* add modal handler */
795         WM_event_add_modal_handler(C, op);
796 }
797
798 static void node_resize_exit(bContext *C, wmOperator *op, int UNUSED(cancel))
799 {
800         WM_cursor_restore(CTX_wm_window(C));
801         
802         MEM_freeN(op->customdata);
803         op->customdata = NULL;
804 }
805
806 static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
807 {
808         SpaceNode *snode = CTX_wm_space_node(C);
809         ARegion *ar = CTX_wm_region(C);
810         bNode *node = nodeGetActive(snode->edittree);
811         NodeSizeWidget *nsw = op->customdata;
812         float mx, my, dx, dy;
813         
814         switch (event->type) {
815                 case MOUSEMOVE:
816                         
817                         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mx, &my);
818                         dx = (mx - nsw->mxstart) / UI_DPI_FAC;
819                         dy = (my - nsw->mystart) / UI_DPI_FAC;
820                         
821                         if (node) {
822                                 if (node->flag & NODE_HIDDEN) {
823                                         float widthmin = 0.0f;
824                                         float widthmax = 100.0f;
825                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
826                                                 node->miniwidth = nsw->oldminiwidth + dx;
827                                                 CLAMP(node->miniwidth, widthmin, widthmax);
828                                         }
829                                         if (nsw->directions & NODE_RESIZE_LEFT) {
830                                                 float locmax = nsw->oldlocx + nsw->oldminiwidth;
831                                                 
832                                                 node->locx = nsw->oldlocx + dx;
833                                                 CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
834                                                 node->miniwidth = locmax - node->locx;
835                                         }
836                                 }
837                                 else {
838                                         float widthmin = node->typeinfo->minwidth;
839                                         float widthmax = node->typeinfo->maxwidth;
840                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
841                                                 node->width = nsw->oldwidth + dx;
842                                                 CLAMP(node->width, widthmin, widthmax);
843                                         }
844                                         if (nsw->directions & NODE_RESIZE_LEFT) {
845                                                 float locmax = nsw->oldlocx + nsw->oldwidth;
846                                                 
847                                                 node->locx = nsw->oldlocx + dx;
848                                                 CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
849                                                 node->width = locmax - node->locx;
850                                         }
851                                 }
852                         
853                                 /* height works the other way round ... */
854                                 {
855                                         float heightmin = UI_DPI_FAC * node->typeinfo->minheight;
856                                         float heightmax = UI_DPI_FAC * node->typeinfo->maxheight;
857                                         if (nsw->directions & NODE_RESIZE_TOP) {
858                                                 float locmin = nsw->oldlocy - nsw->oldheight;
859                                                 
860                                                 node->locy = nsw->oldlocy + dy;
861                                                 CLAMP(node->locy, locmin + heightmin, locmin + heightmax);
862                                                 node->height = node->locy - locmin;
863                                         }
864                                         if (nsw->directions & NODE_RESIZE_BOTTOM) {
865                                                 node->height = nsw->oldheight - dy;
866                                                 CLAMP(node->height, heightmin, heightmax);
867                                         }
868                                 }
869                                 
870                                 /* XXX make callback? */
871                                 if (node->type == NODE_FRAME) {
872                                         /* keep the offset symmetric around center point */
873                                         if (nsw->directions & NODE_RESIZE_LEFT) {
874                                                 node->locx = nsw->oldlocx + 0.5f * dx;
875                                                 node->offsetx = nsw->oldoffsetx + 0.5f * dx;
876                                         }
877                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
878                                                 node->locx = nsw->oldlocx + 0.5f * dx;
879                                                 node->offsetx = nsw->oldoffsetx - 0.5f * dx;
880                                         }
881                                         if (nsw->directions & NODE_RESIZE_TOP) {
882                                                 node->locy = nsw->oldlocy + 0.5f * dy;
883                                                 node->offsety = nsw->oldoffsety + 0.5f * dy;
884                                         }
885                                         if (nsw->directions & NODE_RESIZE_BOTTOM) {
886                                                 node->locy = nsw->oldlocy + 0.5f * dy;
887                                                 node->offsety = nsw->oldoffsety - 0.5f * dy;
888                                         }
889                                 }
890                         }
891                                 
892                         ED_region_tag_redraw(ar);
893
894                         break;
895                         
896                 case LEFTMOUSE:
897                 case MIDDLEMOUSE:
898                 case RIGHTMOUSE:
899                         
900                         node_resize_exit(C, op, 0);
901                         ED_node_post_apply_transform(C, snode->edittree);
902                         
903                         return OPERATOR_FINISHED;
904         }
905         
906         return OPERATOR_RUNNING_MODAL;
907 }
908
909 static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event)
910 {
911         SpaceNode *snode = CTX_wm_space_node(C);
912         ARegion *ar = CTX_wm_region(C);
913         bNode *node = nodeGetActive(snode->edittree);
914         int dir;
915         
916         if (node) {
917                 /* convert mouse coordinates to v2d space */
918                 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
919                                          &snode->cursor[0], &snode->cursor[1]);
920                 dir = node->typeinfo->resize_area_func(node, snode->cursor[0], snode->cursor[1]);
921                 if (dir != 0) {
922                         node_resize_init(C, op, event, node, dir);
923                         return OPERATOR_RUNNING_MODAL;
924                 }
925         }
926         return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
927 }
928
929 static int node_resize_cancel(bContext *C, wmOperator *op)
930 {
931         node_resize_exit(C, op, 1);
932
933         return OPERATOR_CANCELLED;
934 }
935
936 void NODE_OT_resize(wmOperatorType *ot)
937 {
938         /* identifiers */
939         ot->name = "Resize Node";
940         ot->idname = "NODE_OT_resize";
941         ot->description = "Resize a node";
942         
943         /* api callbacks */
944         ot->invoke = node_resize_invoke;
945         ot->modal = node_resize_modal;
946         ot->poll = ED_operator_node_active;
947         ot->cancel = node_resize_cancel;
948         
949         /* flags */
950         ot->flag = OPTYPE_BLOCKING;
951 }
952
953
954 /* ********************** hidden sockets ******************** */
955
956 int node_has_hidden_sockets(bNode *node)
957 {
958         bNodeSocket *sock;
959         
960         for (sock = node->inputs.first; sock; sock = sock->next)
961                 if (sock->flag & SOCK_HIDDEN)
962                         return 1;
963         for (sock = node->outputs.first; sock; sock = sock->next)
964                 if (sock->flag & SOCK_HIDDEN)
965                         return 1;
966         return 0;
967 }
968
969 void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
970 {
971         bNodeSocket *sock;
972
973         if (set == 0) {
974                 for (sock = node->inputs.first; sock; sock = sock->next)
975                         sock->flag &= ~SOCK_HIDDEN;
976                 for (sock = node->outputs.first; sock; sock = sock->next)
977                         sock->flag &= ~SOCK_HIDDEN;
978         }
979         else {
980                 /* hide unused sockets */
981                 for (sock = node->inputs.first; sock; sock = sock->next) {
982                         if (sock->link == NULL)
983                                 sock->flag |= SOCK_HIDDEN;
984                 }
985                 for (sock = node->outputs.first; sock; sock = sock->next) {
986                         if (nodeCountSocketLinks(snode->edittree, sock) == 0)
987                                 sock->flag |= SOCK_HIDDEN;
988                 }
989         }
990 }
991
992
993 /* checks snode->mouse position, and returns found node/socket */
994 /* type is SOCK_IN and/or SOCK_OUT */
995 int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, int in_out)
996 {
997         bNode *node;
998         bNodeSocket *sock;
999         rctf rect;
1000         
1001         *nodep = NULL;
1002         *sockp = NULL;
1003         
1004         /* check if we click in a socket */
1005         for (node = snode->edittree->nodes.first; node; node = node->next) {
1006                 
1007                 rect.xmin = snode->cursor[0] - (NODE_SOCKSIZE + 4);
1008                 rect.ymin = snode->cursor[1] - (NODE_SOCKSIZE + 4);
1009                 rect.xmax = snode->cursor[0] + (NODE_SOCKSIZE + 4);
1010                 rect.ymax = snode->cursor[1] + (NODE_SOCKSIZE + 4);
1011                 
1012                 if (!(node->flag & NODE_HIDDEN)) {
1013                         /* extra padding inside and out - allow dragging on the text areas too */
1014                         if (in_out == SOCK_IN) {
1015                                 rect.xmax += NODE_SOCKSIZE;
1016                                 rect.xmin -= NODE_SOCKSIZE * 4;
1017                         }
1018                         else if (in_out == SOCK_OUT) {
1019                                 rect.xmax += NODE_SOCKSIZE * 4;
1020                                 rect.xmin -= NODE_SOCKSIZE;
1021                         }
1022                 }
1023                 
1024                 if (in_out & SOCK_IN) {
1025                         for (sock = node->inputs.first; sock; sock = sock->next) {
1026                                 if (!nodeSocketIsHidden(sock)) {
1027                                         if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
1028                                                 if (node == visible_node(snode, &rect)) {
1029                                                         *nodep = node;
1030                                                         *sockp = sock;
1031                                                         return 1;
1032                                                 }
1033                                         }
1034                                 }
1035                         }
1036                 }
1037                 if (in_out & SOCK_OUT) {
1038                         for (sock = node->outputs.first; sock; sock = sock->next) {
1039                                 if (!nodeSocketIsHidden(sock)) {
1040                                         if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
1041                                                 if (node == visible_node(snode, &rect)) {
1042                                                         *nodep = node;
1043                                                         *sockp = sock;
1044                                                         return 1;
1045                                                 }
1046                                         }
1047                                 }
1048                         }
1049                 }
1050         }
1051         
1052         return 0;
1053 }
1054
1055 /* ****************** Duplicate *********************** */
1056
1057 static void node_duplicate_reparent_recursive(bNode *node)
1058 {
1059         bNode *parent;
1060         
1061         node->flag |= NODE_TEST;
1062         
1063         /* find first selected parent */
1064         for (parent = node->parent; parent; parent = parent->parent) {
1065                 if (parent->flag & SELECT) {
1066                         if (!(parent->flag & NODE_TEST))
1067                                 node_duplicate_reparent_recursive(parent);
1068                         break;
1069                 }
1070         }
1071         /* reparent node copy to parent copy */
1072         if (parent) {
1073                 nodeDetachNode(node->new_node);
1074                 nodeAttachNode(node->new_node, parent->new_node);
1075         }
1076 }
1077
1078 static int node_duplicate_exec(bContext *C, wmOperator *op)
1079 {
1080         SpaceNode *snode = CTX_wm_space_node(C);
1081         bNodeTree *ntree = snode->edittree;
1082         bNode *node, *newnode, *lastnode;
1083         bNodeLink *link, *newlink, *lastlink;
1084         int keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
1085         
1086         ED_preview_kill_jobs(C);
1087         
1088         lastnode = ntree->nodes.last;
1089         for (node = ntree->nodes.first; node; node = node->next) {
1090                 if (node->flag & SELECT) {
1091                         newnode = nodeCopyNode(ntree, node);
1092                         
1093                         if (newnode->id) {
1094                                 /* simple id user adjustment, node internal functions don't touch this
1095                                  * but operators and readfile.c do. */
1096                                 id_us_plus(newnode->id);
1097                                 /* to ensure redraws or rerenders happen */
1098                                 ED_node_tag_update_id(snode->id);
1099                         }
1100                 }
1101                 
1102                 /* make sure we don't copy new nodes again! */
1103                 if (node == lastnode)
1104                         break;
1105         }
1106         
1107         /* copy links between selected nodes
1108          * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
1109          */
1110         lastlink = ntree->links.last;
1111         for (link = ntree->links.first; link; link = link->next) {
1112                 /* This creates new links between copied nodes.
1113                  * If keep_inputs is set, also copies input links from unselected (when fromnode==NULL)!
1114                  */
1115                 if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
1116                     (keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT))))
1117                 {
1118                         newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
1119                         newlink->flag = link->flag;
1120                         newlink->tonode = link->tonode->new_node;
1121                         newlink->tosock = link->tosock->new_sock;
1122                         if (link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
1123                                 newlink->fromnode = link->fromnode->new_node;
1124                                 newlink->fromsock = link->fromsock->new_sock;
1125                         }
1126                         else {
1127                                 /* input node not copied, this keeps the original input linked */
1128                                 newlink->fromnode = link->fromnode;
1129                                 newlink->fromsock = link->fromsock;
1130                         }
1131                         
1132                         BLI_addtail(&ntree->links, newlink);
1133                 }
1134                 
1135                 /* make sure we don't copy new links again! */
1136                 if (link == lastlink)
1137                         break;
1138         }
1139         
1140         /* clear flags for recursive depth-first iteration */
1141         for (node = ntree->nodes.first; node; node = node->next)
1142                 node->flag &= ~NODE_TEST;
1143         /* reparent copied nodes */
1144         for (node = ntree->nodes.first; node; node = node->next) {
1145                 if ((node->flag & SELECT) && !(node->flag & NODE_TEST))
1146                         node_duplicate_reparent_recursive(node);
1147                 
1148                 /* only has to check old nodes */
1149                 if (node == lastnode)
1150                         break;
1151         }
1152         
1153         /* deselect old nodes, select the copies instead */
1154         for (node = ntree->nodes.first; node; node = node->next) {
1155                 if (node->flag & SELECT) {
1156                         /* has been set during copy above */
1157                         newnode = node->new_node;
1158                         
1159                         nodeSetSelected(node, FALSE);
1160                         node->flag &= ~NODE_ACTIVE;
1161                         nodeSetSelected(newnode, TRUE);
1162                 }
1163                 
1164                 /* make sure we don't copy new nodes again! */
1165                 if (node == lastnode)
1166                         break;
1167         }
1168         
1169         ntreeUpdateTree(snode->edittree);
1170         
1171         snode_notify(C, snode);
1172         snode_dag_update(C, snode);
1173
1174         return OPERATOR_FINISHED;
1175 }
1176
1177 void NODE_OT_duplicate(wmOperatorType *ot)
1178 {
1179         /* identifiers */
1180         ot->name = "Duplicate Nodes";
1181         ot->description = "Duplicate selected nodes";
1182         ot->idname = "NODE_OT_duplicate";
1183         
1184         /* api callbacks */
1185         ot->exec = node_duplicate_exec;
1186         ot->poll = ED_operator_node_active;
1187         
1188         /* flags */
1189         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1190         
1191         RNA_def_boolean(ot->srna, "keep_inputs", 0, "Keep Inputs", "Keep the input links to duplicated nodes");
1192 }
1193
1194 int ED_node_select_check(ListBase *lb)
1195
1196
1197 {
1198         bNode *node;
1199
1200         for (node = lb->first; node; node = node->next) {
1201                 if (node->flag & NODE_SELECT) {
1202                         return TRUE;
1203                 }
1204         }
1205
1206         return FALSE;
1207 }
1208
1209 /* ******************************** */
1210 // XXX some code needing updating to operators...
1211
1212
1213 /* goes over all scenes, reads render layers */
1214 static int node_read_renderlayers_exec(bContext *C, wmOperator *UNUSED(op))
1215 {
1216         Main *bmain = CTX_data_main(C);
1217         SpaceNode *snode = CTX_wm_space_node(C);
1218         Scene *curscene = CTX_data_scene(C), *scene;
1219         bNode *node;
1220
1221         ED_preview_kill_jobs(C);
1222
1223         /* first tag scenes unread */
1224         for (scene = bmain->scene.first; scene; scene = scene->id.next)
1225                 scene->id.flag |= LIB_DOIT;
1226
1227         for (node = snode->edittree->nodes.first; node; node = node->next) {
1228                 if (node->type == CMP_NODE_R_LAYERS) {
1229                         ID *id = node->id;
1230                         if (id->flag & LIB_DOIT) {
1231                                 RE_ReadRenderResult(curscene, (Scene *)id);
1232                                 ntreeCompositTagRender((Scene *)id);
1233                                 id->flag &= ~LIB_DOIT;
1234                         }
1235                 }
1236         }
1237         
1238         snode_notify(C, snode);
1239         snode_dag_update(C, snode);
1240
1241         return OPERATOR_FINISHED;
1242 }
1243
1244 void NODE_OT_read_renderlayers(wmOperatorType *ot)
1245 {
1246         
1247         ot->name = "Read Render Layers";
1248         ot->idname = "NODE_OT_read_renderlayers";
1249         ot->description = "Read all render layers of all used scenes";
1250         
1251         ot->exec = node_read_renderlayers_exec;
1252         
1253         ot->poll = composite_node_active;
1254         
1255         /* flags */
1256         ot->flag = 0;
1257 }
1258
1259 static int node_read_fullsamplelayers_exec(bContext *C, wmOperator *UNUSED(op))
1260 {
1261         Main *bmain = CTX_data_main(C);
1262         SpaceNode *snode = CTX_wm_space_node(C);
1263         Scene *curscene = CTX_data_scene(C);
1264         Render *re = RE_NewRender(curscene->id.name);
1265
1266         WM_cursor_wait(1);
1267         RE_MergeFullSample(re, bmain, curscene, snode->nodetree);
1268         WM_cursor_wait(0);
1269
1270         /* note we are careful to send the right notifier, as otherwise the
1271          * compositor would reexecute and overwrite the full sample result */
1272         WM_event_add_notifier(C, NC_SCENE | ND_COMPO_RESULT, NULL);
1273
1274         return OPERATOR_FINISHED;
1275 }
1276
1277
1278 void NODE_OT_read_fullsamplelayers(wmOperatorType *ot)
1279 {
1280         
1281         ot->name = "Read Full Sample Layers";
1282         ot->idname = "NODE_OT_read_fullsamplelayers";
1283         ot->description = "Read all render layers of current scene, in full sample";
1284         
1285         ot->exec = node_read_fullsamplelayers_exec;
1286         
1287         ot->poll = composite_node_active;
1288         
1289         /* flags */
1290         ot->flag = 0;
1291 }
1292
1293 int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op))
1294 {
1295         Scene *sce = CTX_data_scene(C);
1296         bNode *node;
1297         
1298         for (node = sce->nodetree->nodes.first; node; node = node->next) {
1299                 if (node->id == (ID *)sce && node->need_exec) {
1300                         break;
1301                 }
1302         }
1303         if (node) {
1304                 SceneRenderLayer *srl = BLI_findlink(&sce->r.layers, node->custom1);
1305                 
1306                 if (srl) {
1307                         PointerRNA op_ptr;
1308                         
1309                         WM_operator_properties_create(&op_ptr, "RENDER_OT_render");
1310                         RNA_string_set(&op_ptr, "layer", srl->name);
1311                         RNA_string_set(&op_ptr, "scene", sce->id.name + 2);
1312                         
1313                         /* to keep keypositions */
1314                         sce->r.scemode |= R_NO_FRAME_UPDATE;
1315                         
1316                         WM_operator_name_call(C, "RENDER_OT_render", WM_OP_INVOKE_DEFAULT, &op_ptr);
1317
1318                         WM_operator_properties_free(&op_ptr);
1319                         
1320                         return OPERATOR_FINISHED;
1321                 }
1322                    
1323         }
1324         return OPERATOR_CANCELLED;
1325 }
1326
1327 void NODE_OT_render_changed(wmOperatorType *ot)
1328 {
1329         ot->name = "Render Changed Layer";
1330         ot->idname = "NODE_OT_render_changed";
1331         ot->description = "Render current scene, when input node's layer has been changed";
1332         
1333         ot->exec = node_render_changed_exec;
1334         
1335         ot->poll = composite_node_active;
1336         
1337         /* flags */
1338         ot->flag = 0;
1339 }
1340
1341
1342 /* ****************** Hide operator *********************** */
1343
1344 static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
1345 {
1346         bNode *node;
1347         int tot_eq = 0, tot_neq = 0;
1348
1349         /* Toggles the flag on all selected nodes.
1350          * If the flag is set on all nodes it is unset.
1351          * If the flag is not set on all nodes, it is set.
1352          */
1353         for (node = snode->edittree->nodes.first; node; node = node->next) {
1354                 if (node->flag & SELECT) {
1355                         
1356                         if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0)
1357                                 continue;
1358                         if (toggle_flag == NODE_OPTIONS && (node->typeinfo->flag & NODE_OPTIONS) == 0)
1359                                 continue;
1360                         
1361                         if (node->flag & toggle_flag)
1362                                 tot_eq++;
1363                         else
1364                                 tot_neq++;
1365                 }
1366         }
1367         for (node = snode->edittree->nodes.first; node; node = node->next) {
1368                 if (node->flag & SELECT) {
1369                         
1370                         if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0)
1371                                 continue;
1372                         if (toggle_flag == NODE_OPTIONS && (node->typeinfo->flag & NODE_OPTIONS) == 0)
1373                                 continue;
1374                         
1375                         if ((tot_eq && tot_neq) || tot_eq == 0)
1376                                 node->flag |= toggle_flag;
1377                         else
1378                                 node->flag &= ~toggle_flag;
1379                 }
1380         }
1381 }
1382
1383 static int node_hide_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1384 {
1385         SpaceNode *snode = CTX_wm_space_node(C);
1386         
1387         /* sanity checking (poll callback checks this already) */
1388         if ((snode == NULL) || (snode->edittree == NULL))
1389                 return OPERATOR_CANCELLED;
1390         
1391         node_flag_toggle_exec(snode, NODE_HIDDEN);
1392
1393         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1394
1395         return OPERATOR_FINISHED;
1396 }
1397
1398 void NODE_OT_hide_toggle(wmOperatorType *ot)
1399 {
1400         /* identifiers */
1401         ot->name = "Hide";
1402         ot->description = "Toggle hiding of selected nodes";
1403         ot->idname = "NODE_OT_hide_toggle";
1404         
1405         /* callbacks */
1406         ot->exec = node_hide_toggle_exec;
1407         ot->poll = ED_operator_node_active;
1408
1409         /* flags */
1410         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1411 }
1412
1413 static int node_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1414 {
1415         SpaceNode *snode = CTX_wm_space_node(C);
1416
1417         /* sanity checking (poll callback checks this already) */
1418         if ((snode == NULL) || (snode->edittree == NULL))
1419                 return OPERATOR_CANCELLED;
1420
1421         ED_preview_kill_jobs(C);
1422
1423         node_flag_toggle_exec(snode, NODE_PREVIEW);
1424
1425         snode_notify(C, snode);
1426
1427         return OPERATOR_FINISHED;
1428 }
1429
1430 void NODE_OT_preview_toggle(wmOperatorType *ot)
1431 {
1432         /* identifiers */
1433         ot->name = "Toggle Node Preview";
1434         ot->description = "Toggle preview display for selected nodes";
1435         ot->idname = "NODE_OT_preview_toggle";
1436
1437         /* callbacks */
1438         ot->exec = node_preview_toggle_exec;
1439         ot->poll = ED_operator_node_active;
1440
1441         /* flags */
1442         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1443 }
1444
1445 static int node_options_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1446 {
1447         SpaceNode *snode = CTX_wm_space_node(C);
1448
1449         /* sanity checking (poll callback checks this already) */
1450         if ((snode == NULL) || (snode->edittree == NULL))
1451                 return OPERATOR_CANCELLED;
1452
1453         node_flag_toggle_exec(snode, NODE_OPTIONS);
1454
1455         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1456
1457         return OPERATOR_FINISHED;
1458 }
1459
1460 void NODE_OT_options_toggle(wmOperatorType *ot)
1461 {
1462         /* identifiers */
1463         ot->name = "Toggle Node Options";
1464         ot->description = "Toggle option buttons display for selected nodes";
1465         ot->idname = "NODE_OT_options_toggle";
1466
1467         /* callbacks */
1468         ot->exec = node_options_toggle_exec;
1469         ot->poll = ED_operator_node_active;
1470
1471         /* flags */
1472         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1473 }
1474
1475 static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1476 {
1477         SpaceNode *snode = CTX_wm_space_node(C);
1478         bNode *node;
1479         int hidden;
1480
1481         /* sanity checking (poll callback checks this already) */
1482         if ((snode == NULL) || (snode->edittree == NULL))
1483                 return OPERATOR_CANCELLED;
1484
1485         ED_preview_kill_jobs(C);
1486
1487         /* Toggle for all selected nodes */
1488         hidden = 0;
1489         for (node = snode->edittree->nodes.first; node; node = node->next) {
1490                 if (node->flag & SELECT) {
1491                         if (node_has_hidden_sockets(node)) {
1492                                 hidden = 1;
1493                                 break;
1494                         }
1495                 }
1496         }
1497         
1498         for (node = snode->edittree->nodes.first; node; node = node->next) {
1499                 if (node->flag & SELECT) {
1500                         node_set_hidden_sockets(snode, node, !hidden);
1501                 }
1502         }
1503
1504         ntreeUpdateTree(snode->edittree);
1505
1506         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1507
1508         return OPERATOR_FINISHED;
1509 }
1510
1511 void NODE_OT_hide_socket_toggle(wmOperatorType *ot)
1512 {
1513         /* identifiers */
1514         ot->name = "Toggle Hidden Node Sockets";
1515         ot->description = "Toggle unused node socket display";
1516         ot->idname = "NODE_OT_hide_socket_toggle";
1517
1518         /* callbacks */
1519         ot->exec = node_socket_toggle_exec;
1520         ot->poll = ED_operator_node_active;
1521
1522         /* flags */
1523         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1524 }
1525
1526 /* ****************** Mute operator *********************** */
1527
1528 static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
1529 {
1530         SpaceNode *snode = CTX_wm_space_node(C);
1531         bNode *node;
1532
1533         ED_preview_kill_jobs(C);
1534
1535         for (node = snode->edittree->nodes.first; node; node = node->next) {
1536                 /* Only allow muting of nodes having a mute func! */
1537                 if ((node->flag & SELECT) && node->typeinfo->update_internal_links) {
1538                         node->flag ^= NODE_MUTED;
1539                         snode_update(snode, node);
1540                 }
1541         }
1542         
1543         snode_notify(C, snode);
1544         snode_dag_update(C, snode);
1545         
1546         return OPERATOR_FINISHED;
1547 }
1548
1549 void NODE_OT_mute_toggle(wmOperatorType *ot)
1550 {
1551         /* identifiers */
1552         ot->name = "Toggle Node Mute";
1553         ot->description = "Toggle muting of the nodes";
1554         ot->idname = "NODE_OT_mute_toggle";
1555         
1556         /* callbacks */
1557         ot->exec = node_mute_exec;
1558         ot->poll = ED_operator_node_active;
1559         
1560         /* flags */
1561         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1562 }
1563
1564 /* ****************** Delete operator ******************* */
1565
1566 static int node_delete_exec(bContext *C, wmOperator *UNUSED(op))
1567 {
1568         SpaceNode *snode = CTX_wm_space_node(C);
1569         bNode *node, *next;
1570         
1571         ED_preview_kill_jobs(C);
1572
1573         for (node = snode->edittree->nodes.first; node; node = next) {
1574                 next = node->next;
1575                 if (node->flag & SELECT) {
1576                         /* check id user here, nodeFreeNode is called for free dbase too */
1577                         if (node->id)
1578                                 node->id->us--;
1579                         nodeFreeNode(snode->edittree, node);
1580                 }
1581         }
1582         
1583         ntreeUpdateTree(snode->edittree);
1584
1585         snode_notify(C, snode);
1586         snode_dag_update(C, snode);
1587         
1588         return OPERATOR_FINISHED;
1589 }
1590
1591 void NODE_OT_delete(wmOperatorType *ot)
1592 {
1593         /* identifiers */
1594         ot->name = "Delete";
1595         ot->description = "Delete selected nodes";
1596         ot->idname = "NODE_OT_delete";
1597         
1598         /* api callbacks */
1599         ot->exec = node_delete_exec;
1600         ot->poll = ED_operator_node_active;
1601         
1602         /* flags */
1603         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1604 }
1605
1606 /* ****************** Delete with reconnect ******************* */
1607 static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
1608 {
1609         SpaceNode *snode = CTX_wm_space_node(C);
1610         bNode *node, *next;
1611
1612         ED_preview_kill_jobs(C);
1613
1614         for (node = snode->edittree->nodes.first; node; node = next) {
1615                 next = node->next;
1616                 if (node->flag & SELECT) {
1617                         nodeInternalRelink(snode->edittree, node);
1618                         
1619                         /* check id user here, nodeFreeNode is called for free dbase too */
1620                         if (node->id)
1621                                 node->id->us--;
1622                         nodeFreeNode(snode->edittree, node);
1623                 }
1624         }
1625
1626         ntreeUpdateTree(snode->edittree);
1627
1628         snode_notify(C, snode);
1629         snode_dag_update(C, snode);
1630
1631         return OPERATOR_FINISHED;
1632 }
1633
1634 void NODE_OT_delete_reconnect(wmOperatorType *ot)
1635 {
1636         /* identifiers */
1637         ot->name = "Delete with Reconnect";
1638         ot->description = "Delete nodes; will reconnect nodes as if deletion was muted";
1639         ot->idname = "NODE_OT_delete_reconnect";
1640
1641         /* api callbacks */
1642         ot->exec = node_delete_reconnect_exec;
1643         ot->poll = ED_operator_node_active;
1644
1645         /* flags */
1646         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1647 }
1648
1649
1650 /* ****************** File Output Add Socket  ******************* */
1651
1652 static int node_output_file_add_socket_exec(bContext *C, wmOperator *op)
1653 {
1654         Scene *scene = CTX_data_scene(C);
1655         SpaceNode *snode = CTX_wm_space_node(C);
1656         PointerRNA ptr;
1657         bNodeTree *ntree;
1658         bNode *node;
1659         char file_path[MAX_NAME];
1660
1661         ptr = CTX_data_pointer_get(C, "node");
1662         if (!ptr.data)
1663                 return OPERATOR_CANCELLED;
1664         node = ptr.data;
1665         ntree = ptr.id.data;
1666
1667         RNA_string_get(op->ptr, "file_path", file_path);
1668         ntreeCompositOutputFileAddSocket(ntree, node, file_path, &scene->r.im_format);
1669
1670         snode_notify(C, snode);
1671
1672         return OPERATOR_FINISHED;
1673 }
1674
1675 void NODE_OT_output_file_add_socket(wmOperatorType *ot)
1676 {
1677         /* identifiers */
1678         ot->name = "Add File Node Socket";
1679         ot->description = "Add a new input to a file output node";
1680         ot->idname = "NODE_OT_output_file_add_socket";
1681
1682         /* callbacks */
1683         ot->exec = node_output_file_add_socket_exec;
1684         ot->poll = composite_node_active;
1685
1686         /* flags */
1687         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1688
1689         RNA_def_string(ot->srna, "file_path", "Image", MAX_NAME, "File Path", "Sub-path of the output file");
1690 }
1691
1692 /* ****************** Multi File Output Remove Socket  ******************* */
1693
1694 static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *UNUSED(op))
1695 {
1696         SpaceNode *snode = CTX_wm_space_node(C);
1697         PointerRNA ptr = CTX_data_pointer_get(C, "node");
1698         bNodeTree *ntree;
1699         bNode *node;
1700         
1701         if (!ptr.data)
1702                 return OPERATOR_CANCELLED;
1703         node = ptr.data;
1704         ntree = ptr.id.data;
1705         
1706         if (!ntreeCompositOutputFileRemoveActiveSocket(ntree, node))
1707                 return OPERATOR_CANCELLED;
1708         
1709         snode_notify(C, snode);
1710         
1711         return OPERATOR_FINISHED;
1712 }
1713
1714 void NODE_OT_output_file_remove_active_socket(wmOperatorType *ot)
1715 {
1716         /* identifiers */
1717         ot->name = "Remove File Node Socket";
1718         ot->description = "Remove active input from a file output node";
1719         ot->idname = "NODE_OT_output_file_remove_active_socket";
1720         
1721         /* callbacks */
1722         ot->exec = node_output_file_remove_active_socket_exec;
1723         ot->poll = composite_node_active;
1724         
1725         /* flags */
1726         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1727 }
1728
1729 /* ****************** Multi File Output Move Socket  ******************* */
1730
1731 static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
1732 {
1733         SpaceNode *snode = CTX_wm_space_node(C);
1734         PointerRNA ptr = CTX_data_pointer_get(C, "node");
1735         bNode *node;
1736         NodeImageMultiFile *nimf;
1737         bNodeSocket *sock;
1738         int direction;
1739         
1740         if (!ptr.data)
1741                 return OPERATOR_CANCELLED;
1742         node = ptr.data;
1743         nimf = node->storage;
1744         
1745         sock = BLI_findlink(&node->inputs, nimf->active_input);
1746         if (!sock)
1747                 return OPERATOR_CANCELLED;
1748         
1749         direction = RNA_enum_get(op->ptr, "direction");
1750         
1751         if (direction == 1) {
1752                 bNodeSocket *before = sock->prev;
1753                 if (!before)
1754                         return OPERATOR_CANCELLED;
1755                 BLI_remlink(&node->inputs, sock);
1756                 BLI_insertlinkbefore(&node->inputs, before, sock);
1757                 nimf->active_input--;
1758         }
1759         else {
1760                 bNodeSocket *after = sock->next;
1761                 if (!after)
1762                         return OPERATOR_CANCELLED;
1763                 BLI_remlink(&node->inputs, sock);
1764                 BLI_insertlinkafter(&node->inputs, after, sock);
1765                 nimf->active_input++;
1766         }
1767         
1768         snode_notify(C, snode);
1769         
1770         return OPERATOR_FINISHED;
1771 }
1772
1773 void NODE_OT_output_file_move_active_socket(wmOperatorType *ot)
1774 {
1775         static EnumPropertyItem direction_items[] = {
1776                 {1, "UP", 0, "Up", ""},
1777                 {2, "DOWN", 0, "Down", ""},
1778                 { 0, NULL, 0, NULL, NULL }
1779         };
1780         
1781         /* identifiers */
1782         ot->name = "Move File Node Socket";
1783         ot->description = "Move the active input of a file output node up or down the list";
1784         ot->idname = "NODE_OT_output_file_move_active_socket";
1785         
1786         /* callbacks */
1787         ot->exec = node_output_file_move_active_socket_exec;
1788         ot->poll = composite_node_active;
1789         
1790         /* flags */
1791         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1792         
1793         RNA_def_enum(ot->srna, "direction", direction_items, 2, "Direction", "");
1794 }
1795
1796 /* ****************** Copy Node Color ******************* */
1797
1798 static int node_copy_color_exec(bContext *C, wmOperator *UNUSED(op))
1799 {
1800         SpaceNode *snode = CTX_wm_space_node(C);
1801         bNodeTree *ntree = snode->edittree;
1802         bNode *node, *tnode;
1803         
1804         if (!ntree)
1805                 return OPERATOR_CANCELLED;
1806         node = nodeGetActive(ntree);
1807         if (!node)
1808                 return OPERATOR_CANCELLED;
1809         
1810         for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
1811                 if (tnode->flag & NODE_SELECT && tnode != node) {
1812                         if (node->flag & NODE_CUSTOM_COLOR) {
1813                                 tnode->flag |= NODE_CUSTOM_COLOR;
1814                                 copy_v3_v3(tnode->color, node->color);
1815                         }
1816                         else
1817                                 tnode->flag &= ~NODE_CUSTOM_COLOR;
1818                 }
1819         }
1820
1821         ED_node_sort(ntree);
1822         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1823
1824         return OPERATOR_FINISHED;
1825 }
1826
1827 void NODE_OT_node_copy_color(wmOperatorType *ot)
1828 {
1829         /* identifiers */
1830         ot->name = "Copy Color";
1831         ot->description = "Copy color to all selected nodes";
1832         ot->idname = "NODE_OT_node_copy_color";
1833
1834         /* api callbacks */
1835         ot->exec = node_copy_color_exec;
1836         ot->poll = ED_operator_node_active;
1837
1838         /* flags */
1839         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1840 }
1841
1842 /* ****************** Copy to clipboard ******************* */
1843
1844 static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
1845 {
1846         SpaceNode *snode = CTX_wm_space_node(C);
1847         bNodeTree *ntree = snode->edittree;
1848         bNode *node;
1849         bNodeLink *link, *newlink;
1850
1851         ED_preview_kill_jobs(C);
1852
1853         /* clear current clipboard */
1854         BKE_node_clipboard_clear();
1855         BKE_node_clipboard_init(ntree);
1856
1857         for (node = ntree->nodes.first; node; node = node->next) {
1858                 if (node->flag & SELECT) {
1859                         bNode *new_node;
1860                         new_node = nodeCopyNode(NULL, node);
1861                         BKE_node_clipboard_add_node(new_node);
1862                 }
1863         }
1864
1865         for (node = ntree->nodes.first; node; node = node->next) {
1866                 if (node->flag & SELECT) {
1867                         bNode *new_node = node->new_node;
1868                         
1869                         /* ensure valid pointers */
1870                         if (new_node->parent) {
1871                                 /* parent pointer must be redirected to new node or detached if parent is not copied */
1872                                 if (new_node->parent->flag & NODE_SELECT) {
1873                                         new_node->parent = new_node->parent->new_node;
1874                                 }
1875                                 else {
1876                                         nodeDetachNode(new_node);
1877                                 }
1878                         }
1879                 }
1880         }
1881
1882         /* copy links between selected nodes
1883          * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
1884          */
1885         for (link = ntree->links.first; link; link = link->next) {
1886                 /* This creates new links between copied nodes. */
1887                 if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
1888                     link->fromnode && (link->fromnode->flag & NODE_SELECT))
1889                 {
1890                         newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
1891                         newlink->flag = link->flag;
1892                         newlink->tonode = link->tonode->new_node;
1893                         newlink->tosock = link->tosock->new_sock;
1894                         newlink->fromnode = link->fromnode->new_node;
1895                         newlink->fromsock = link->fromsock->new_sock;
1896
1897                         BKE_node_clipboard_add_link(newlink);
1898                 }
1899         }
1900
1901         return OPERATOR_FINISHED;
1902 }
1903
1904 void NODE_OT_clipboard_copy(wmOperatorType *ot)
1905 {
1906         /* identifiers */
1907         ot->name = "Copy to Clipboard";
1908         ot->description = "Copies selected nodes to the clipboard";
1909         ot->idname = "NODE_OT_clipboard_copy";
1910
1911         /* api callbacks */
1912         ot->exec = node_clipboard_copy_exec;
1913         ot->poll = ED_operator_node_active;
1914
1915         /* flags */
1916         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1917 }
1918
1919 /* ****************** Paste from clipboard ******************* */
1920
1921 static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
1922 {
1923         SpaceNode *snode = CTX_wm_space_node(C);
1924         bNodeTree *ntree = snode->edittree;
1925         const ListBase *clipboard_nodes_lb;
1926         const ListBase *clipboard_links_lb;
1927         bNode *node;
1928         bNodeLink *link;
1929         int num_nodes;
1930         float center[2];
1931         int is_clipboard_valid;
1932
1933         /* validate pointers in the clipboard */
1934         is_clipboard_valid = BKE_node_clipboard_validate();
1935         clipboard_nodes_lb = BKE_node_clipboard_get_nodes();
1936         clipboard_links_lb = BKE_node_clipboard_get_links();
1937
1938         if (clipboard_nodes_lb->first == NULL) {
1939                 BKE_report(op->reports, RPT_ERROR, "Clipboard is empty");
1940                 return OPERATOR_CANCELLED;
1941         }
1942
1943         if (BKE_node_clipboard_get_type() != ntree->type) {
1944                 BKE_report(op->reports, RPT_ERROR, "Clipboard nodes are an incompatible type");
1945                 return OPERATOR_CANCELLED;
1946         }
1947
1948         /* only warn */
1949         if (is_clipboard_valid == FALSE) {
1950                 BKE_report(op->reports, RPT_WARNING, "Some nodes references could not be restored, will be left empty");
1951         }
1952
1953         ED_preview_kill_jobs(C);
1954
1955         /* deselect old nodes */
1956         node_deselect_all(snode);
1957
1958         /* calculate "barycenter" for placing on mouse cursor */
1959         zero_v2(center);
1960         for (node = clipboard_nodes_lb->first, num_nodes = 0; node; node = node->next, num_nodes++) {
1961                 center[0] += BLI_rctf_cent_x(&node->totr);
1962                 center[1] += BLI_rctf_cent_y(&node->totr);
1963         }
1964         mul_v2_fl(center, 1.0 / num_nodes);
1965
1966         /* copy nodes from clipboard */
1967         for (node = clipboard_nodes_lb->first; node; node = node->next) {
1968                 bNode *new_node = nodeCopyNode(ntree, node);
1969
1970                 /* needed since nodeCopyNode() doesn't increase ID's */
1971                 id_us_plus(node->id);
1972
1973                 /* pasted nodes are selected */
1974                 nodeSetSelected(new_node, TRUE);
1975         }
1976         
1977         /* reparent copied nodes */
1978         for (node = clipboard_nodes_lb->first; node; node = node->next) {
1979                 bNode *new_node = node->new_node;
1980                 if (new_node->parent)
1981                         new_node->parent = new_node->parent->new_node;
1982         }
1983
1984         for (link = clipboard_links_lb->first; link; link = link->next) {
1985                 nodeAddLink(ntree, link->fromnode->new_node, link->fromsock->new_sock,
1986                             link->tonode->new_node, link->tosock->new_sock);
1987         }
1988
1989         ntreeUpdateTree(snode->edittree);
1990
1991         snode_notify(C, snode);
1992         snode_dag_update(C, snode);
1993
1994         return OPERATOR_FINISHED;
1995 }
1996
1997 static int node_clipboard_paste_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1998 {
1999         ARegion *ar = CTX_wm_region(C);
2000         SpaceNode *snode = CTX_wm_space_node(C);
2001
2002         /* convert mouse coordinates to v2d space */
2003         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]);
2004
2005         return node_clipboard_paste_exec(C, op);
2006 }
2007
2008 void NODE_OT_clipboard_paste(wmOperatorType *ot)
2009 {
2010         /* identifiers */
2011         ot->name = "Paste from Clipboard";
2012         ot->description = "Pastes nodes from the clipboard to the active node tree";
2013         ot->idname = "NODE_OT_clipboard_paste";
2014
2015         /* api callbacks */
2016         ot->exec = node_clipboard_paste_exec;
2017         ot->invoke = node_clipboard_paste_invoke;
2018         ot->poll = ED_operator_node_active;
2019
2020         /* flags */
2021         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2022 }
2023
2024 /********************** Add interface socket operator *********************/
2025
2026 static bNodeSocket *ntree_get_active_interface_socket(ListBase *lb)
2027 {
2028         bNodeSocket *sock;
2029         for (sock = lb->first; sock; sock = sock->next)
2030                 if (sock->flag & SELECT)
2031                         return sock;
2032         return NULL;
2033 }
2034
2035 static int ntree_socket_add_exec(bContext *C, wmOperator *op)
2036 {
2037         SpaceNode *snode = CTX_wm_space_node(C);
2038         bNodeTree *ntree = snode->edittree;
2039         int in_out = RNA_enum_get(op->ptr, "in_out");
2040         PointerRNA ntree_ptr;
2041         bNodeSocket *sock, *tsock, *active_sock;
2042         const char *default_name;
2043         
2044         RNA_id_pointer_create((ID *)ntree, &ntree_ptr);
2045         
2046         if (in_out == SOCK_IN) {
2047                 active_sock = ntree_get_active_interface_socket(&ntree->inputs);
2048                 default_name = "Input";
2049         }
2050         else {
2051                 active_sock = ntree_get_active_interface_socket(&ntree->outputs);
2052                 default_name = "Output";
2053         }
2054         
2055         if (active_sock) {
2056                 /* insert a copy of the active socket right after it */
2057                 sock = ntreeInsertSocketInterface(ntree, in_out, active_sock->idname, active_sock->next, active_sock->name);
2058                 /* XXX this only works for actual sockets, not interface templates! */
2059                 /*nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr);*/
2060         }
2061         else {
2062                 /* XXX TODO define default socket type for a tree! */
2063                 sock = ntreeAddSocketInterface(ntree, in_out, "NodeSocketFloat", default_name);
2064         }
2065         
2066         /* deactivate sockets (has to check both lists) */
2067         for (tsock = ntree->inputs.first; tsock; tsock = tsock->next)
2068                 tsock->flag &= ~SELECT;
2069         for (tsock = ntree->outputs.first; tsock; tsock = tsock->next)
2070                 tsock->flag &= ~SELECT;
2071         /* make the new socket active */
2072         sock->flag |= SELECT;
2073         
2074         ntreeUpdateTree(ntree);
2075         
2076         return OPERATOR_FINISHED;
2077 }
2078
2079 void NODE_OT_tree_socket_add(wmOperatorType *ot)
2080 {
2081         /* identifiers */
2082         ot->name = "Add Node Tree Interface Socket";
2083         ot->idname = "NODE_OT_tree_socket_add";
2084         
2085         /* api callbacks */
2086         ot->exec = ntree_socket_add_exec;
2087         ot->poll = ED_operator_node_active;
2088         
2089         /* flags */
2090         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2091         
2092         RNA_def_enum(ot->srna, "in_out", node_socket_in_out_items, SOCK_IN, "Socket Type", "");
2093 }
2094
2095 /********************** Remove interface socket operator *********************/
2096
2097 static int ntree_socket_remove_exec(bContext *C, wmOperator *UNUSED(op))
2098 {
2099         SpaceNode *snode = CTX_wm_space_node(C);
2100         bNodeTree *ntree = snode->edittree;
2101         bNodeSocket *iosock, *active_sock;
2102         
2103         iosock = ntree_get_active_interface_socket(&ntree->inputs);
2104         if (!iosock)
2105                 iosock = ntree_get_active_interface_socket(&ntree->outputs);
2106         if (!iosock)
2107                 return OPERATOR_CANCELLED;
2108         
2109         /* preferably next socket becomes active, otherwise try previous socket */
2110         active_sock = (iosock->next ? iosock->next : iosock->prev);
2111         ntreeRemoveSocketInterface(ntree, iosock);
2112         
2113         /* set active socket */
2114         if (active_sock)
2115                 active_sock->flag |= SELECT;
2116         
2117         ntreeUpdateTree(ntree);
2118         
2119         return OPERATOR_FINISHED;
2120 }
2121
2122 void NODE_OT_tree_socket_remove(wmOperatorType *ot)
2123 {
2124         /* identifiers */
2125         ot->name = "Remove Node Tree Interface Socket";
2126         ot->idname = "NODE_OT_tree_socket_remove";
2127         
2128         /* api callbacks */
2129         ot->exec = ntree_socket_remove_exec;
2130         ot->poll = ED_operator_node_active;
2131         
2132         /* flags */
2133         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2134 }
2135
2136 /********************** Move interface socket operator *********************/
2137
2138 static EnumPropertyItem move_direction_items[] = {
2139         { 1, "UP", 0, "Up", "" },
2140         { 2, "DOWN", 0, "Down", "" },
2141         { 0, NULL, 0, NULL, NULL },
2142 };
2143
2144 static int ntree_socket_move_exec(bContext *C, wmOperator *op)
2145 {
2146         SpaceNode *snode = CTX_wm_space_node(C);
2147         bNodeTree *ntree = snode->edittree;
2148         int direction = RNA_enum_get(op->ptr, "direction");
2149         bNodeSocket *iosock;
2150         ListBase *lb;
2151         
2152         lb = &ntree->inputs;
2153         iosock = ntree_get_active_interface_socket(lb);
2154         if (!iosock) {
2155                 lb = &ntree->outputs;
2156                 iosock = ntree_get_active_interface_socket(lb);
2157         }
2158         if (!iosock)
2159                 return OPERATOR_CANCELLED;
2160         
2161         switch (direction) {
2162         case 1: {       /* up */
2163                 bNodeSocket *before = iosock->prev;
2164                 BLI_remlink(lb, iosock);
2165                 if (before)
2166                         BLI_insertlinkbefore(lb, before, iosock);
2167                 else
2168                         BLI_addhead(lb, iosock);
2169                 break;
2170         }
2171         case 2: {       /* down */
2172                 bNodeSocket *after = iosock->next;
2173                 BLI_remlink(lb, iosock);
2174                 if (after)
2175                         BLI_insertlinkafter(lb, after, iosock);
2176                 else
2177                         BLI_addtail(lb, iosock);
2178                 break;
2179         }
2180         }
2181         
2182         ntreeUpdateTree(ntree);
2183         
2184         return OPERATOR_FINISHED;
2185 }
2186
2187 void NODE_OT_tree_socket_move(wmOperatorType *ot)
2188 {
2189         /* identifiers */
2190         ot->name = "Move Node Tree Socket";
2191         ot->idname = "NODE_OT_tree_socket_move";
2192         
2193         /* api callbacks */
2194         ot->exec = ntree_socket_move_exec;
2195         ot->poll = ED_operator_node_active;
2196         
2197         /* flags */
2198         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2199         
2200         RNA_def_enum(ot->srna, "direction", move_direction_items, 1, "Direction", "");
2201 }
2202
2203 /* ********************** Shader Script Update ******************/
2204
2205 static int node_shader_script_update_poll(bContext *C)
2206 {
2207         Scene *scene = CTX_data_scene(C);
2208         RenderEngineType *type = RE_engines_find(scene->r.engine);
2209         bNode *node;
2210         Text *text;
2211
2212         /* test if we have a render engine that supports shaders scripts */
2213         if (!(type && type->update_script_node))
2214                 return 0;
2215
2216         /* see if we have a shader script node in context */
2217         node = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data;
2218         if (node && node->type == SH_NODE_SCRIPT) {
2219                 NodeShaderScript *nss = node->storage;
2220
2221                 if (node->id || nss->filepath[0]) {
2222                         return 1;
2223                 }
2224         }
2225
2226         /* see if we have a text datablock in context */
2227         text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
2228         if (text)
2229                 return 1;
2230
2231         /* we don't check if text datablock is actually in use, too slow for poll */
2232
2233         return 0;
2234 }
2235
2236 /* recursively check for script nodes in groups using this text and update */
2237 static int node_shader_script_update_text_recursive(RenderEngine *engine, RenderEngineType *type, bNodeTree *ntree, Text *text)
2238 {
2239         int found = FALSE;
2240         bNode *node;
2241         
2242         ntree->done = TRUE;
2243         
2244         /* update each script that is using this text datablock */
2245         for (node = ntree->nodes.first; node; node = node->next) {
2246                 if (node->type == NODE_GROUP) {
2247                         bNodeTree *ngroup = (bNodeTree *)node->id;
2248                         if (ngroup && !ngroup->done)
2249                                 found |= node_shader_script_update_text_recursive(engine, type, ngroup, text);
2250                 }
2251                 else if (node->type == SH_NODE_SCRIPT && node->id == &text->id) {
2252                         type->update_script_node(engine, ntree, node);
2253                         found = TRUE;
2254                 }
2255         }
2256         
2257         return found;
2258 }
2259
2260 static int node_shader_script_update_exec(bContext *C, wmOperator *op)
2261 {
2262         Main *bmain = CTX_data_main(C);
2263         Scene *scene = CTX_data_scene(C);
2264         PointerRNA nodeptr = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript);
2265         RenderEngine *engine;
2266         RenderEngineType *type;
2267         int found = FALSE;
2268
2269         /* setup render engine */
2270         type = RE_engines_find(scene->r.engine);
2271         engine = RE_engine_create(type);
2272         engine->reports = op->reports;
2273
2274         if (nodeptr.data) {
2275                 /* update single node */
2276                 bNodeTree *ntree = nodeptr.id.data;
2277                 bNode *node = nodeptr.data;
2278
2279                 type->update_script_node(engine, ntree, node);
2280
2281                 found = TRUE;
2282         }
2283         else {
2284                 /* update all nodes using text datablock */
2285                 Text *text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
2286
2287                 if (text) {
2288                         /* clear flags for recursion check */
2289                         FOREACH_NODETREE(bmain, ntree, id) {
2290                                 if (ntree->type == NTREE_SHADER)
2291                                         ntree->done = FALSE;
2292                         } FOREACH_NODETREE_END
2293                         
2294                         FOREACH_NODETREE(bmain, ntree, id) {
2295                                 if (ntree->type == NTREE_SHADER) {
2296                                         if (!ntree->done)
2297                                                 found |= node_shader_script_update_text_recursive(engine, type, ntree, text);
2298                                 }
2299                         } FOREACH_NODETREE_END
2300
2301                         if (!found)
2302                                 BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done");
2303                 }
2304         }
2305
2306         RE_engine_free(engine);
2307
2308         return (found)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
2309 }
2310
2311 void NODE_OT_shader_script_update(wmOperatorType *ot)
2312 {
2313         /* identifiers */
2314         ot->name = "Script Node Update";
2315         ot->description = "Update shader script node with new sockets and options from the script";
2316         ot->idname = "NODE_OT_shader_script_update";
2317
2318         /* api callbacks */
2319         ot->exec = node_shader_script_update_exec;
2320         ot->poll = node_shader_script_update_poll;
2321
2322         /* flags */
2323         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2324 }
2325
2326 /* ********************** Viewer border ******************/
2327
2328 static void viewer_border_corner_to_backdrop(SpaceNode *snode, ARegion *ar, int x, int y,
2329                                              int backdrop_width, int backdrop_height,
2330                                              float *fx, float *fy)
2331 {
2332         float bufx, bufy;
2333
2334         bufx = backdrop_width * snode->zoom;
2335         bufy = backdrop_height * snode->zoom;
2336
2337         *fx = (bufx > 0.0f ? ((float) x - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f);
2338         *fy = (bufy > 0.0f ? ((float) y - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f);
2339 }
2340
2341 static int viewer_border_exec(bContext *C, wmOperator *op)
2342 {
2343         Image *ima;
2344         void *lock;
2345         ImBuf *ibuf;
2346
2347         ED_preview_kill_jobs(C);
2348
2349         ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
2350         ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
2351
2352         if (ibuf) {
2353                 ARegion *ar = CTX_wm_region(C);
2354                 SpaceNode *snode = CTX_wm_space_node(C);
2355                 bNodeTree *btree = snode->edittree;
2356                 rcti rect;
2357                 rctf rectf;
2358
2359                 /* get border from operator */
2360                 WM_operator_properties_border_to_rcti(op, &rect);
2361
2362                 /* convert border to unified space within backdrop image */
2363                 viewer_border_corner_to_backdrop(snode, ar, rect.xmin, rect.ymin, ibuf->x, ibuf->y,
2364                                                  &rectf.xmin, &rectf.ymin);
2365
2366                 viewer_border_corner_to_backdrop(snode, ar, rect.xmax, rect.ymax, ibuf->x, ibuf->y,
2367                                                  &rectf.xmax, &rectf.ymax);
2368
2369                 /* clamp coordinates */
2370                 rectf.xmin = max_ff(rectf.xmin, 0.0f);
2371                 rectf.ymin = max_ff(rectf.ymin, 0.0f);
2372                 rectf.xmax = min_ff(rectf.xmax, 1.0f);
2373                 rectf.ymax = min_ff(rectf.ymax, 1.0f);
2374
2375                 if (rectf.xmin < rectf.xmax && rectf.ymin < rectf.ymax) {
2376                         btree->viewer_border = rectf;
2377
2378                         if (rectf.xmin == 0.0f && rectf.ymin == 0.0f &&
2379                             rectf.xmax == 1.0f && rectf.ymax == 1.0f)
2380                         {
2381                                 btree->flag &= ~NTREE_VIEWER_BORDER;
2382                         }
2383                         else {
2384                                 if (ibuf->rect)
2385                                         memset(ibuf->rect, 0, 4 * ibuf->x * ibuf->y);
2386
2387                                 if (ibuf->rect_float)
2388                                         memset(ibuf->rect_float, 0, 4 * ibuf->x * ibuf->y * sizeof(float));
2389
2390                                 ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
2391
2392                                 btree->flag |= NTREE_VIEWER_BORDER;
2393                         }
2394
2395                         snode_notify(C, snode);
2396                         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
2397                 }
2398                 else {
2399                         btree->flag &= ~NTREE_VIEWER_BORDER;
2400                 }
2401         }
2402
2403         BKE_image_release_ibuf(ima, ibuf, lock);
2404
2405         return OPERATOR_FINISHED;
2406 }
2407
2408 void NODE_OT_viewer_border(wmOperatorType *ot)
2409 {
2410         /* identifiers */
2411         ot->name = "Viewer Border";
2412         ot->description = "Set the boundaries for viewer operations";
2413         ot->idname = "NODE_OT_viewer_border";
2414
2415         /* api callbacks */
2416         ot->invoke = WM_border_select_invoke;
2417         ot->exec = viewer_border_exec;
2418         ot->modal = WM_border_select_modal;
2419         ot->cancel = WM_border_select_cancel;
2420         ot->poll = composite_node_active;
2421
2422         /* flags */
2423         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2424
2425         /* properties */
2426         WM_operator_properties_gesture_border(ot, TRUE);
2427 }