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