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