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