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