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