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