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