Fix for node placement when copying to/pasting from clipboard. Child node location...
[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_object_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_depsgraph.h"
45 #include "BKE_global.h"
46 #include "BKE_image.h"
47 #include "BKE_library.h"
48 #include "BKE_main.h"
49 #include "BKE_node.h"
50 #include "BKE_material.h"
51 #include "BKE_paint.h"
52 #include "BKE_scene.h"
53 #include "BKE_texture.h"
54
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
65 #include "WM_api.h"
66 #include "WM_types.h"
67
68 #include "UI_view2d.h"
69
70 #include "GPU_material.h"
71
72 #include "node_intern.h"  /* own include */
73
74 /* ***************** composite job manager ********************** */
75
76 typedef struct CompoJob {
77         Scene *scene;
78         bNodeTree *ntree;
79         bNodeTree *localtree;
80         short *stop;
81         short *do_update;
82         float *progress;
83 } CompoJob;
84
85 /* called by compo, only to check job 'stop' value */
86 static int compo_breakjob(void *cjv)
87 {
88         CompoJob *cj = cjv;
89         
90         return *(cj->stop);
91 }
92
93 /* called by compo, wmJob sends notifier */
94 static void compo_redrawjob(void *cjv, char *UNUSED(str))
95 {
96         CompoJob *cj = cjv;
97         
98         *(cj->do_update) = TRUE;
99 }
100
101 static void compo_freejob(void *cjv)
102 {
103         CompoJob *cj = cjv;
104
105         if (cj->localtree) {
106                 ntreeLocalMerge(cj->localtree, cj->ntree);
107         }
108         MEM_freeN(cj);
109 }
110
111 /* only now we copy the nodetree, so adding many jobs while
112  * sliding buttons doesn't frustrate */
113 static void compo_initjob(void *cjv)
114 {
115         CompoJob *cj = cjv;
116
117         cj->localtree = ntreeLocalize(cj->ntree);
118 }
119
120 /* called before redraw notifiers, it moves finished previews over */
121 static void compo_updatejob(void *cjv)
122 {
123         CompoJob *cj = cjv;
124         
125         ntreeLocalSync(cj->localtree, cj->ntree);
126 }
127
128 static void compo_progressjob(void *cjv, float progress)
129 {
130         CompoJob *cj = cjv;
131         
132         *(cj->progress) = progress;
133 }
134
135
136 /* only this runs inside thread */
137 static void compo_startjob(void *cjv, short *stop, short *do_update, float *progress)
138 {
139         CompoJob *cj = cjv;
140         bNodeTree *ntree = cj->localtree;
141
142         if (cj->scene->use_nodes == FALSE)
143                 return;
144         
145         cj->stop = stop;
146         cj->do_update = do_update;
147         cj->progress = progress;
148
149         ntree->test_break = compo_breakjob;
150         ntree->tbh = cj;
151         ntree->stats_draw = compo_redrawjob;
152         ntree->sdh = cj;
153         ntree->progress = compo_progressjob;
154         ntree->prh = cj;
155         
156         // XXX BIF_store_spare();
157         
158         ntreeCompositExecTree(ntree, &cj->scene->r, 0, 1);  /* 1 is do_previews */
159
160         ntree->test_break = NULL;
161         ntree->stats_draw = NULL;
162         ntree->progress = NULL;
163
164 }
165
166 void snode_composite_job(const bContext *C, ScrArea *sa)
167 {
168         SpaceNode *snode = sa->spacedata.first;
169         wmJob *steve;
170         CompoJob *cj;
171
172         steve = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Compositing", WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS);
173         cj = MEM_callocN(sizeof(CompoJob), "compo job");
174         
175         /* customdata for preview thread */
176         cj->scene = CTX_data_scene(C);
177         cj->ntree = snode->nodetree;
178         
179         /* setup job */
180         WM_jobs_customdata(steve, cj, compo_freejob);
181         WM_jobs_timer(steve, 0.1, NC_SCENE, NC_SCENE | ND_COMPO_RESULT);
182         WM_jobs_callbacks(steve, compo_startjob, compo_initjob, compo_updatejob, NULL);
183         
184         WM_jobs_start(CTX_wm_manager(C), steve);
185         
186 }
187
188 /* ***************************************** */
189
190 /* operator poll callback */
191 int composite_node_active(bContext *C)
192 {
193         if (ED_operator_node_active(C)) {
194                 SpaceNode *snode = CTX_wm_space_node(C);
195                 if (snode->treetype == NTREE_COMPOSIT)
196                         return 1;
197         }
198         return 0;
199 }
200
201 /* also checks for edited groups */
202 bNode *editnode_get_active(bNodeTree *ntree)
203 {
204         bNode *node;
205         
206         /* check for edited group */
207         for (node = ntree->nodes.first; node; node = node->next)
208                 if (nodeGroupEditGet(node))
209                         break;
210         if (node)
211                 return nodeGetActive((bNodeTree *)node->id);
212         else
213                 return nodeGetActive(ntree);
214 }
215
216 static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
217 {
218         bNode *node;
219         
220         if (ntree == lookup)
221                 return 1;
222         
223         for (node = ntree->nodes.first; node; node = node->next)
224                 if (node->type == NODE_GROUP && node->id)
225                         if (has_nodetree((bNodeTree *)node->id, lookup))
226                                 return 1;
227         
228         return 0;
229 }
230
231 static void snode_dag_update_group(void *calldata, ID *owner_id, bNodeTree *ntree)
232 {
233         if (has_nodetree(ntree, calldata))
234                 DAG_id_tag_update(owner_id, 0);
235 }
236
237 void snode_dag_update(bContext *C, SpaceNode *snode)
238 {
239         Main *bmain = CTX_data_main(C);
240
241         /* for groups, update all ID's using this */
242         if (snode->edittree != snode->nodetree) {
243                 bNodeTreeType *tti = ntreeGetType(snode->edittree->type);
244                 tti->foreach_nodetree(bmain, snode->edittree, snode_dag_update_group);
245         }
246
247         DAG_id_tag_update(snode->id, 0);
248 }
249
250 void snode_notify(bContext *C, SpaceNode *snode)
251 {
252         WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL);
253
254         if (snode->treetype == NTREE_SHADER)
255                 WM_event_add_notifier(C, NC_MATERIAL | ND_NODES, snode->id);
256         else if (snode->treetype == NTREE_COMPOSIT)
257                 WM_event_add_notifier(C, NC_SCENE | ND_NODES, snode->id);
258         else if (snode->treetype == NTREE_TEXTURE)
259                 WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, snode->id);
260 }
261
262 bNode *node_tree_get_editgroup(bNodeTree *nodetree)
263 {
264         bNode *gnode;
265         
266         /* get the groupnode */
267         for (gnode = nodetree->nodes.first; gnode; gnode = gnode->next)
268                 if (nodeGroupEditGet(gnode))
269                         break;
270         return gnode;
271 }
272
273 /* assumes nothing being done in ntree yet, sets the default in/out node */
274 /* called from shading buttons or header */
275 void ED_node_shader_default(Scene *scene, ID *id)
276 {
277         bNode *in, *out;
278         bNodeSocket *fromsock, *tosock, *sock;
279         bNodeTree *ntree;
280         bNodeTemplate ntemp;
281         int output_type, shader_type;
282         float color[3], strength = 1.0f;
283         
284         ntree = ntreeAddTree("Shader Nodetree", NTREE_SHADER, 0);
285
286         switch (GS(id->name)) {
287                 case ID_MA: {
288                         Material *ma = (Material *)id;
289                         ma->nodetree = ntree;
290
291                         if (BKE_scene_use_new_shading_nodes(scene)) {
292                                 output_type = SH_NODE_OUTPUT_MATERIAL;
293                                 shader_type = SH_NODE_BSDF_DIFFUSE;
294                         }
295                         else {
296                                 output_type = SH_NODE_OUTPUT;
297                                 shader_type = SH_NODE_MATERIAL;
298                         }
299
300                         copy_v3_v3(color, &ma->r);
301                         strength = 0.0f;
302                         break;
303                 }
304                 case ID_WO: {
305                         World *wo = (World *)id;
306                         wo->nodetree = ntree;
307
308                         output_type = SH_NODE_OUTPUT_WORLD;
309                         shader_type = SH_NODE_BACKGROUND;
310
311                         copy_v3_v3(color, &wo->horr);
312                         strength = 1.0f;
313                         break;
314                 }
315                 case ID_LA: {
316                         Lamp *la = (Lamp *)id;
317                         la->nodetree = ntree;
318
319                         output_type = SH_NODE_OUTPUT_LAMP;
320                         shader_type = SH_NODE_EMISSION;
321
322                         copy_v3_v3(color, &la->r);
323                         if (la->type == LA_LOCAL || la->type == LA_SPOT || la->type == LA_AREA)
324                                 strength = 100.0f;
325                         else
326                                 strength = 1.0f;
327                         break;
328                 }
329                 default:
330                         printf("ED_node_shader_default called on wrong ID type.\n");
331                         return;
332         }
333         
334         ntemp.type = output_type;
335         out = nodeAddNode(ntree, &ntemp);
336         out->locx = 300.0f; out->locy = 300.0f;
337         
338         ntemp.type = shader_type;
339         in = nodeAddNode(ntree, &ntemp);
340         in->locx = 10.0f; in->locy = 300.0f;
341         nodeSetActive(ntree, in);
342         
343         /* only a link from color to color */
344         fromsock = in->outputs.first;
345         tosock = out->inputs.first;
346         nodeAddLink(ntree, in, fromsock, out, tosock);
347
348         /* default values */
349         if (BKE_scene_use_new_shading_nodes(scene)) {
350                 sock = in->inputs.first;
351                 copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, color);
352
353                 if (strength != 0.0f) {
354                         sock = in->inputs.last;
355                         ((bNodeSocketValueFloat *)sock->default_value)->value = strength;
356                 }
357         }
358         
359         ntreeUpdateTree(ntree);
360 }
361
362 /* assumes nothing being done in ntree yet, sets the default in/out node */
363 /* called from shading buttons or header */
364 void ED_node_composit_default(Scene *sce)
365 {
366         bNode *in, *out;
367         bNodeSocket *fromsock, *tosock;
368         bNodeTemplate ntemp;
369         
370         /* but lets check it anyway */
371         if (sce->nodetree) {
372                 if (G.debug & G_DEBUG)
373                         printf("error in composite initialize\n");
374                 return;
375         }
376         
377         sce->nodetree = ntreeAddTree("Compositing Nodetree", NTREE_COMPOSIT, 0);
378
379         sce->nodetree->chunksize = 256;
380         sce->nodetree->edit_quality = NTREE_QUALITY_HIGH;
381         sce->nodetree->render_quality = NTREE_QUALITY_HIGH;
382         
383         ntemp.type = CMP_NODE_COMPOSITE;
384         out = nodeAddNode(sce->nodetree, &ntemp);
385         out->locx = 300.0f; out->locy = 400.0f;
386         out->id = &sce->id;
387         id_us_plus(out->id);
388         
389         ntemp.type = CMP_NODE_R_LAYERS;
390         in = nodeAddNode(sce->nodetree, &ntemp);
391         in->locx = 10.0f; in->locy = 400.0f;
392         in->id = &sce->id;
393         id_us_plus(in->id);
394         nodeSetActive(sce->nodetree, in);
395         
396         /* links from color to color */
397         fromsock = in->outputs.first;
398         tosock = out->inputs.first;
399         nodeAddLink(sce->nodetree, in, fromsock, out, tosock);
400         
401         ntreeUpdateTree(sce->nodetree);
402         
403         // XXX ntreeCompositForceHidden(sce->nodetree);
404 }
405
406 /* assumes nothing being done in ntree yet, sets the default in/out node */
407 /* called from shading buttons or header */
408 void ED_node_texture_default(Tex *tx)
409 {
410         bNode *in, *out;
411         bNodeSocket *fromsock, *tosock;
412         bNodeTemplate ntemp;
413         
414         /* but lets check it anyway */
415         if (tx->nodetree) {
416                 if (G.debug & G_DEBUG)
417                         printf("error in texture initialize\n");
418                 return;
419         }
420         
421         tx->nodetree = ntreeAddTree("Texture Nodetree", NTREE_TEXTURE, 0);
422         
423         ntemp.type = TEX_NODE_OUTPUT;
424         out = nodeAddNode(tx->nodetree, &ntemp);
425         out->locx = 300.0f; out->locy = 300.0f;
426         
427         ntemp.type = TEX_NODE_CHECKER;
428         in = nodeAddNode(tx->nodetree, &ntemp);
429         in->locx = 10.0f; in->locy = 300.0f;
430         nodeSetActive(tx->nodetree, in);
431         
432         fromsock = in->outputs.first;
433         tosock = out->inputs.first;
434         nodeAddLink(tx->nodetree, in, fromsock, out, tosock);
435         
436         ntreeUpdateTree(tx->nodetree);
437 }
438
439 /* id is supposed to contain a node tree */
440 void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *treetype)
441 {
442         if (id) {
443                 bNode *node = NULL;
444                 short idtype = GS(id->name);
445         
446                 if (idtype == ID_NT) {
447                         *ntree = (bNodeTree *)id;
448                         if (treetype) *treetype = (*ntree)->type;
449                 }
450                 else if (idtype == ID_MA) {
451                         *ntree = ((Material *)id)->nodetree;
452                         if (treetype) *treetype = NTREE_SHADER;
453                 }
454                 else if (idtype == ID_LA) {
455                         *ntree = ((Lamp *)id)->nodetree;
456                         if (treetype) *treetype = NTREE_SHADER;
457                 }
458                 else if (idtype == ID_WO) {
459                         *ntree = ((World *)id)->nodetree;
460                         if (treetype) *treetype = NTREE_SHADER;
461                 }
462                 else if (idtype == ID_SCE) {
463                         *ntree = ((Scene *)id)->nodetree;
464                         if (treetype) *treetype = NTREE_COMPOSIT;
465                 }
466                 else if (idtype == ID_TE) {
467                         *ntree = ((Tex *)id)->nodetree;
468                         if (treetype) *treetype = NTREE_TEXTURE;
469                 }
470                 else {
471                         if (treetype) *treetype = 0;
472                         return;
473                 }
474         
475                 /* find editable group */
476                 if (edittree) {
477                         if (*ntree)
478                                 for (node = (*ntree)->nodes.first; node; node = node->next)
479                                         if (nodeGroupEditGet(node))
480                                                 break;
481                         
482                         if (node && node->id)
483                                 *edittree = (bNodeTree *)node->id;
484                         else
485                                 *edittree = *ntree;
486                 }
487         }
488         else {
489                 *ntree = NULL;
490                 *edittree = NULL;
491                 if (treetype) *treetype = 0;
492         }
493 }
494
495 /* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
496 void snode_set_context(SpaceNode *snode, Scene *scene)
497 {
498         Object *ob = OBACT;
499         
500         snode->id = snode->from = NULL;
501         
502         if (snode->treetype == NTREE_SHADER) {
503                 /* need active object, or we allow pinning... */
504                 if (snode->shaderfrom == SNODE_SHADER_OBJECT) {
505                         if (ob) {
506                                 if (ob->type == OB_LAMP) {
507                                         snode->from = &ob->id;
508                                         snode->id = ob->data;
509                                 }
510                                 else {
511                                         Material *ma = give_current_material(ob, ob->actcol);
512                                         if (ma) {
513                                                 snode->from = &ob->id;
514                                                 snode->id = &ma->id;
515                                         }
516                                 }
517                         }
518                 }
519                 else { /* SNODE_SHADER_WORLD */
520                         if (scene->world) {
521                                 snode->from = NULL;
522                                 snode->id = &scene->world->id;
523                         }
524                 }
525         }
526         else if (snode->treetype == NTREE_COMPOSIT) {
527                 snode->id = &scene->id;
528                 
529                 /* update output sockets based on available layers */
530                 ntreeCompositForceHidden(scene->nodetree, scene);
531         }
532         else if (snode->treetype == NTREE_TEXTURE) {
533                 Tex *tx = NULL;
534
535                 if (snode->texfrom == SNODE_TEX_OBJECT) {
536                         if (ob) {
537                                 tx = give_current_object_texture(ob);
538
539                                 if (ob->type == OB_LAMP)
540                                         snode->from = (ID *)ob->data;
541                                 else
542                                         snode->from = (ID *)give_current_material(ob, ob->actcol);
543
544                                 /* from is not set fully for material nodes, should be ID + Node then */
545                                 snode->id = &tx->id;
546                         }
547                 }
548                 else if (snode->texfrom == SNODE_TEX_WORLD) {
549                         tx = give_current_world_texture(scene->world);
550                         snode->from = (ID *)scene->world;
551                         snode->id = &tx->id;
552                 }
553                 else {
554                         struct Brush *brush = NULL;
555                         
556                         if (ob && (ob->mode & OB_MODE_SCULPT))
557                                 brush = paint_brush(&scene->toolsettings->sculpt->paint);
558                         else
559                                 brush = paint_brush(&scene->toolsettings->imapaint.paint);
560
561                         if (brush) {
562                                 snode->from = (ID *)brush;
563                                 tx = give_current_brush_texture(brush);
564                                 snode->id = &tx->id;
565                         }
566                 }
567         }
568         else {
569                 if (snode->nodetree && snode->nodetree->type == snode->treetype)
570                         snode->id = &snode->nodetree->id;
571                 else
572                         snode->id = NULL;
573         }
574
575         node_tree_from_ID(snode->id, &snode->nodetree, &snode->edittree, NULL);
576 }
577
578 void snode_update(SpaceNode *snode, bNode *node)
579 {
580         bNode *gnode;
581         
582         if (node)
583                 nodeUpdate(snode->edittree, node);
584         
585         /* if inside group, tag entire group */
586         gnode = node_tree_get_editgroup(snode->nodetree);
587         if (gnode)
588                 nodeUpdateID(snode->nodetree, gnode->id);
589 }
590
591 void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
592 {
593         int was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE);
594
595         nodeSetActive(ntree, node);
596         
597         if (node->type != NODE_GROUP) {
598                 int was_output = (node->flag & NODE_DO_OUTPUT);
599                 
600                 /* tree specific activate calls */
601                 if (ntree->type == NTREE_SHADER) {
602                         /* when we select a material, active texture is cleared, for buttons */
603                         if (node->id && ELEM3(GS(node->id->name), ID_MA, ID_LA, ID_WO))
604                                 nodeClearActiveID(ntree, ID_TE);
605                         
606                         if (node->type == SH_NODE_OUTPUT) {
607                                 bNode *tnode;
608                                 
609                                 for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
610                                         if (tnode->type == SH_NODE_OUTPUT)
611                                                 tnode->flag &= ~NODE_DO_OUTPUT;
612                                 
613                                 node->flag |= NODE_DO_OUTPUT;
614                                 if (was_output == 0)
615                                         ED_node_generic_update(bmain, ntree, node);
616                         }
617
618                         /* if active texture changed, free glsl materials */
619                         if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
620                                 Material *ma;
621
622                                 for (ma = bmain->mat.first; ma; ma = ma->id.next)
623                                         if (ma->nodetree && ma->use_nodes && has_nodetree(ma->nodetree, ntree))
624                                                 GPU_material_free(ma);
625
626                                 WM_main_add_notifier(NC_IMAGE, NULL);
627                         }
628
629                         WM_main_add_notifier(NC_MATERIAL | ND_NODES, node->id);
630                 }
631                 else if (ntree->type == NTREE_COMPOSIT) {
632                         /* make active viewer, currently only 1 supported... */
633                         if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
634                                 bNode *tnode;
635                                 
636
637                                 for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
638                                         if (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
639                                                 tnode->flag &= ~NODE_DO_OUTPUT;
640                                 
641                                 node->flag |= NODE_DO_OUTPUT;
642                                 if (was_output == 0)
643                                         ED_node_generic_update(bmain, ntree, node);
644                                 
645                                 /* addnode() doesnt link this yet... */
646                                 node->id = (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
647                         }
648                         else if (node->type == CMP_NODE_R_LAYERS) {
649                                 Scene *scene;
650
651                                 for (scene = bmain->scene.first; scene; scene = scene->id.next) {
652                                         if (scene->nodetree && scene->use_nodes && has_nodetree(scene->nodetree, ntree)) {
653                                                 if (node->id == NULL || node->id == (ID *)scene) {
654                                                         scene->r.actlay = node->custom1;
655                                                 }
656                                         }
657                                 }
658                         }
659                         else if (node->type == CMP_NODE_COMPOSITE) {
660                                 if (was_output == 0) {
661                                         bNode *tnode;
662                                         
663                                         for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
664                                                 if (tnode->type == CMP_NODE_COMPOSITE)
665                                                         tnode->flag &= ~NODE_DO_OUTPUT;
666                                         
667                                         node->flag |= NODE_DO_OUTPUT;
668                                         ED_node_generic_update(bmain, ntree, node);
669                                 }
670                         }
671                 }
672                 else if (ntree->type == NTREE_TEXTURE) {
673                         // XXX
674 #if 0
675                         if (node->id)
676                                 ;  // XXX BIF_preview_changed(-1);
677                         // allqueue(REDRAWBUTSSHADING, 1);
678                         // allqueue(REDRAWIPO, 0);
679 #endif
680                 }
681         }
682 }
683
684 void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree))
685 {
686         /* XXX This does not work due to layout functions relying on node->block,
687          * which only exists during actual drawing. Can we rely on valid totr rects?
688          */
689         /* make sure nodes have correct bounding boxes after transform */
690         /* node_update_nodetree(C, ntree, 0.0f, 0.0f); */
691 }
692
693 /* ***************** generic operator functions for nodes ***************** */
694
695 #if 0 /* UNUSED */
696
697 static int edit_node_poll(bContext *C)
698 {
699         return ED_operator_node_active(C);
700 }
701
702 static void edit_node_properties(wmOperatorType *ot)
703 {
704         /* XXX could node be a context pointer? */
705         RNA_def_string(ot->srna, "node", "", MAX_NAME, "Node", "");
706         RNA_def_int(ot->srna, "socket", 0, 0, MAX_SOCKET, "Socket", "", 0, MAX_SOCKET);
707         RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Side", "");
708 }
709
710 static int edit_node_invoke_properties(bContext *C, wmOperator *op)
711 {
712         if (!RNA_struct_property_is_set(op->ptr, "node")) {
713                 bNode *node = CTX_data_pointer_get_type(C, "node", &RNA_Node).data;
714                 if (!node)
715                         return 0;
716                 else
717                         RNA_string_set(op->ptr, "node", node->name);
718         }
719         
720         if (!RNA_struct_property_is_set(op->ptr, "in_out"))
721                 RNA_enum_set(op->ptr, "in_out", SOCK_IN);
722         
723         if (!RNA_struct_property_is_set(op->ptr, "socket"))
724                 RNA_int_set(op->ptr, "socket", 0);
725         
726         return 1;
727 }
728
729 static void edit_node_properties_get(wmOperator *op, bNodeTree *ntree, bNode **rnode, bNodeSocket **rsock, int *rin_out)
730 {
731         bNode *node;
732         bNodeSocket *sock = NULL;
733         char nodename[MAX_NAME];
734         int sockindex;
735         int in_out;
736         
737         RNA_string_get(op->ptr, "node", nodename);
738         node = nodeFindNodebyName(ntree, nodename);
739         
740         in_out = RNA_enum_get(op->ptr, "in_out");
741         
742         sockindex = RNA_int_get(op->ptr, "socket");
743         switch (in_out) {
744                 case SOCK_IN:   sock = BLI_findlink(&node->inputs, sockindex);  break;
745                 case SOCK_OUT:  sock = BLI_findlink(&node->outputs, sockindex); break;
746         }
747         
748         if (rnode)
749                 *rnode = node;
750         if (rsock)
751                 *rsock = sock;
752         if (rin_out)
753                 *rin_out = in_out;
754 }
755 #endif
756
757 /* ************************** Node generic ************** */
758
759 /* is rct in visible part of node? */
760 static bNode *visible_node(SpaceNode *snode, rctf *rct)
761 {
762         bNode *node;
763         
764         for (node = snode->edittree->nodes.last; node; node = node->prev) {
765                 if (BLI_rctf_isect(&node->totr, rct, NULL))
766                         break;
767         }
768         return node;
769 }
770
771 /* ********************** size widget operator ******************** */
772
773 typedef struct NodeSizeWidget {
774         float mxstart, mystart;
775         float oldlocx, oldlocy;
776         float oldoffsetx, oldoffsety;
777         float oldwidth, oldheight;
778         float oldminiwidth;
779         int directions;
780 } NodeSizeWidget;
781
782 static void node_resize_init(bContext *C, wmOperator *op, wmEvent *UNUSED(event), bNode *node, int dir)
783 {
784         SpaceNode *snode = CTX_wm_space_node(C);
785         
786         NodeSizeWidget *nsw = MEM_callocN(sizeof(NodeSizeWidget), "size widget op data");
787         
788         op->customdata = nsw;
789         nsw->mxstart = snode->mx;
790         nsw->mystart = snode->my;
791         
792         /* store old */
793         nsw->oldlocx = node->locx;
794         nsw->oldlocy = node->locy;
795         nsw->oldoffsetx = node->offsetx;
796         nsw->oldoffsety = node->offsety;
797         nsw->oldwidth = node->width;
798         nsw->oldheight = node->height;
799         nsw->oldminiwidth = node->miniwidth;
800         nsw->directions = dir;
801         
802         WM_cursor_modal(CTX_wm_window(C), node_get_resize_cursor(dir));
803         /* add modal handler */
804         WM_event_add_modal_handler(C, op);
805 }
806
807 static void node_resize_exit(bContext *C, wmOperator *op, int UNUSED(cancel))
808 {
809         WM_cursor_restore(CTX_wm_window(C));
810         
811         MEM_freeN(op->customdata);
812         op->customdata = NULL;
813 }
814
815 static int node_resize_modal(bContext *C, wmOperator *op, wmEvent *event)
816 {
817         SpaceNode *snode = CTX_wm_space_node(C);
818         ARegion *ar = CTX_wm_region(C);
819         bNode *node = editnode_get_active(snode->edittree);
820         NodeSizeWidget *nsw = op->customdata;
821         float mx, my, dx, dy;
822         
823         switch (event->type) {
824                 case MOUSEMOVE:
825                         
826                         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mx, &my);
827                         dx = mx - nsw->mxstart;
828                         dy = my - nsw->mystart;
829                         
830                         if (node) {
831                                 if (node->flag & NODE_HIDDEN) {
832                                         float widthmin = 0.0f;
833                                         float widthmax = 100.0f;
834                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
835                                                 node->miniwidth = nsw->oldminiwidth + dx;
836                                                 CLAMP(node->miniwidth, widthmin, widthmax);
837                                         }
838                                         if (nsw->directions & NODE_RESIZE_LEFT) {
839                                                 float locmax = nsw->oldlocx + nsw->oldminiwidth;
840                                                 
841                                                 node->locx = nsw->oldlocx + dx;
842                                                 CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
843                                                 node->miniwidth = locmax - node->locx;
844                                         }
845                                 }
846                                 else {
847                                         float widthmin = UI_DPI_FAC * node->typeinfo->minwidth;
848                                         float widthmax = UI_DPI_FAC * node->typeinfo->maxwidth;
849                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
850                                                 node->width = nsw->oldwidth + dx;
851                                                 CLAMP(node->width, widthmin, widthmax);
852                                         }
853                                         if (nsw->directions & NODE_RESIZE_LEFT) {
854                                                 float locmax = nsw->oldlocx + nsw->oldwidth;
855                                                 
856                                                 node->locx = nsw->oldlocx + dx;
857                                                 CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
858                                                 node->width = locmax - node->locx;
859                                         }
860                                 }
861                         
862                                 /* height works the other way round ... */
863                                 {
864                                         float heightmin = UI_DPI_FAC * node->typeinfo->minheight;
865                                         float heightmax = UI_DPI_FAC * node->typeinfo->maxheight;
866                                         if (nsw->directions & NODE_RESIZE_TOP) {
867                                                 float locmin = nsw->oldlocy - nsw->oldheight;
868                                                 
869                                                 node->locy = nsw->oldlocy + dy;
870                                                 CLAMP(node->locy, locmin + heightmin, locmin + heightmax);
871                                                 node->height = node->locy - locmin;
872                                         }
873                                         if (nsw->directions & NODE_RESIZE_BOTTOM) {
874                                                 node->height = nsw->oldheight - dy;
875                                                 CLAMP(node->height, heightmin, heightmax);
876                                         }
877                                 }
878                                 
879                                 /* XXX make callback? */
880                                 if (node->type == NODE_FRAME) {
881                                         /* keep the offset symmetric around center point */
882                                         if (nsw->directions & NODE_RESIZE_LEFT) {
883                                                 node->locx = nsw->oldlocx + 0.5f * dx;
884                                                 node->offsetx = nsw->oldoffsetx + 0.5f * dx;
885                                         }
886                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
887                                                 node->locx = nsw->oldlocx + 0.5f * dx;
888                                                 node->offsetx = nsw->oldoffsetx - 0.5f * dx;
889                                         }
890                                         if (nsw->directions & NODE_RESIZE_TOP) {
891                                                 node->locy = nsw->oldlocy + 0.5f * dy;
892                                                 node->offsety = nsw->oldoffsety + 0.5f * dy;
893                                         }
894                                         if (nsw->directions & NODE_RESIZE_BOTTOM) {
895                                                 node->locy = nsw->oldlocy + 0.5f * dy;
896                                                 node->offsety = nsw->oldoffsety - 0.5f * dy;
897                                         }
898                                 }
899                         }
900                                 
901                         ED_region_tag_redraw(ar);
902
903                         break;
904                         
905                 case LEFTMOUSE:
906                 case MIDDLEMOUSE:
907                 case RIGHTMOUSE:
908                         
909                         node_resize_exit(C, op, 0);
910                         ED_node_post_apply_transform(C, snode->edittree);
911                         
912                         return OPERATOR_FINISHED;
913         }
914         
915         return OPERATOR_RUNNING_MODAL;
916 }
917
918 static int node_resize_invoke(bContext *C, wmOperator *op, wmEvent *event)
919 {
920         SpaceNode *snode = CTX_wm_space_node(C);
921         ARegion *ar = CTX_wm_region(C);
922         bNode *node = editnode_get_active(snode->edittree);
923         int dir;
924         
925         if (node) {
926                 /* convert mouse coordinates to v2d space */
927                 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
928                                          &snode->mx, &snode->my);
929                 dir = node->typeinfo->resize_area_func(node, snode->mx, snode->my);
930                 if (dir != 0) {
931                         node_resize_init(C, op, event, node, dir);
932                         return OPERATOR_RUNNING_MODAL;
933                 }
934         }
935         return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
936 }
937
938 static int node_resize_cancel(bContext *C, wmOperator *op)
939 {
940         node_resize_exit(C, op, 1);
941
942         return OPERATOR_CANCELLED;
943 }
944
945 void NODE_OT_resize(wmOperatorType *ot)
946 {
947         /* identifiers */
948         ot->name = "Resize Node";
949         ot->idname = "NODE_OT_resize";
950         ot->description = "Resize a node";
951         
952         /* api callbacks */
953         ot->invoke = node_resize_invoke;
954         ot->modal = node_resize_modal;
955         ot->poll = ED_operator_node_active;
956         ot->cancel = node_resize_cancel;
957         
958         /* flags */
959         ot->flag = OPTYPE_BLOCKING;
960 }
961
962
963 /* ********************** hidden sockets ******************** */
964
965 int node_has_hidden_sockets(bNode *node)
966 {
967         bNodeSocket *sock;
968         
969         for (sock = node->inputs.first; sock; sock = sock->next)
970                 if (sock->flag & SOCK_HIDDEN)
971                         return 1;
972         for (sock = node->outputs.first; sock; sock = sock->next)
973                 if (sock->flag & SOCK_HIDDEN)
974                         return 1;
975         return 0;
976 }
977
978 void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
979 {
980         bNodeSocket *sock;
981
982         if (set == 0) {
983                 for (sock = node->inputs.first; sock; sock = sock->next)
984                         sock->flag &= ~SOCK_HIDDEN;
985                 for (sock = node->outputs.first; sock; sock = sock->next)
986                         sock->flag &= ~SOCK_HIDDEN;
987         }
988         else {
989                 /* hide unused sockets */
990                 for (sock = node->inputs.first; sock; sock = sock->next) {
991                         if (sock->link == NULL)
992                                 sock->flag |= SOCK_HIDDEN;
993                 }
994                 for (sock = node->outputs.first; sock; sock = sock->next) {
995                         if (nodeCountSocketLinks(snode->edittree, sock) == 0)
996                                 sock->flag |= SOCK_HIDDEN;
997                 }
998         }
999 }
1000
1001 /* return 0, nothing done */
1002 static int UNUSED_FUNCTION(node_mouse_groupheader) (SpaceNode * snode)
1003 {
1004         bNode *gnode;
1005         float mx = 0, my = 0;
1006 // XXX  int mval[2];
1007         
1008         gnode = node_tree_get_editgroup(snode->nodetree);
1009         if (gnode == NULL) return 0;
1010         
1011 // XXX  getmouseco_areawin(mval);
1012 // XXX  areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
1013         
1014         /* click in header or outside? */
1015         if (BLI_in_rctf(&gnode->totr, mx, my) == 0) {
1016                 rctf rect = gnode->totr;
1017                 
1018                 rect.ymax += NODE_DY;
1019                 if (BLI_in_rctf(&rect, mx, my) == 0)
1020                         snode_make_group_editable(snode, NULL);  /* toggles, so exits editmode */
1021 //              else
1022 // XXX                  transform_nodes(snode->nodetree, 'g', "Move group");
1023                 
1024                 return 1;
1025         }
1026         return 0;
1027 }
1028
1029 /* checks snode->mouse position, and returns found node/socket */
1030 /* type is SOCK_IN and/or SOCK_OUT */
1031 int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, int in_out)
1032 {
1033         bNode *node;
1034         bNodeSocket *sock;
1035         rctf rect;
1036         
1037         *nodep = NULL;
1038         *sockp = NULL;
1039         
1040         /* check if we click in a socket */
1041         for (node = snode->edittree->nodes.first; node; node = node->next) {
1042                 
1043                 rect.xmin = snode->mx - (NODE_SOCKSIZE + 4);
1044                 rect.ymin = snode->my - (NODE_SOCKSIZE + 4);
1045                 rect.xmax = snode->mx + (NODE_SOCKSIZE + 4);
1046                 rect.ymax = snode->my + (NODE_SOCKSIZE + 4);
1047                 
1048                 if (!(node->flag & NODE_HIDDEN)) {
1049                         /* extra padding inside and out - allow dragging on the text areas too */
1050                         if (in_out == SOCK_IN) {
1051                                 rect.xmax += NODE_SOCKSIZE;
1052                                 rect.xmin -= NODE_SOCKSIZE * 4;
1053                         }
1054                         else if (in_out == SOCK_OUT) {
1055                                 rect.xmax += NODE_SOCKSIZE * 4;
1056                                 rect.xmin -= NODE_SOCKSIZE;
1057                         }
1058                 }
1059                 
1060                 if (in_out & SOCK_IN) {
1061                         for (sock = node->inputs.first; sock; sock = sock->next) {
1062                                 if (!nodeSocketIsHidden(sock)) {
1063                                         if (BLI_in_rctf(&rect, sock->locx, sock->locy)) {
1064                                                 if (node == visible_node(snode, &rect)) {
1065                                                         *nodep = node;
1066                                                         *sockp = sock;
1067                                                         return 1;
1068                                                 }
1069                                         }
1070                                 }
1071                         }
1072                 }
1073                 if (in_out & SOCK_OUT) {
1074                         for (sock = node->outputs.first; sock; sock = sock->next) {
1075                                 if (!nodeSocketIsHidden(sock)) {
1076                                         if (BLI_in_rctf(&rect, sock->locx, sock->locy)) {
1077                                                 if (node == visible_node(snode, &rect)) {
1078                                                         *nodep = node;
1079                                                         *sockp = sock;
1080                                                         return 1;
1081                                                 }
1082                                         }
1083                                 }
1084                         }
1085                 }
1086         }
1087         
1088         /* check group sockets
1089          * NB: using ngroup->outputs as input sockets and vice versa here!
1090          */
1091         if (in_out & SOCK_IN) {
1092                 for (sock = snode->edittree->outputs.first; sock; sock = sock->next) {
1093                         if (!nodeSocketIsHidden(sock)) {
1094                                 if (BLI_in_rctf(&rect, sock->locx, sock->locy)) {
1095                                         *nodep = NULL;   /* NULL node pointer indicates group socket */
1096                                         *sockp = sock;
1097                                         return 1;
1098                                 }
1099                         }
1100                 }
1101         }
1102         if (in_out & SOCK_OUT) {
1103                 for (sock = snode->edittree->inputs.first; sock; sock = sock->next) {
1104                         if (!nodeSocketIsHidden(sock)) {
1105                                 if (BLI_in_rctf(&rect, sock->locx, sock->locy)) {
1106                                         *nodep = NULL;   /* NULL node pointer indicates group socket */
1107                                         *sockp = sock;
1108                                         return 1;
1109                                 }
1110                         }
1111                 }
1112         }
1113         
1114         return 0;
1115 }
1116
1117 /* ****************** Duplicate *********************** */
1118
1119 static void node_duplicate_reparent_recursive(bNode *node)
1120 {
1121         bNode *parent;
1122         
1123         node->flag |= NODE_TEST;
1124         
1125         /* find first selected parent */
1126         for (parent = node->parent; parent; parent = parent->parent) {
1127                 if (parent->flag & SELECT) {
1128                         if (!(parent->flag & NODE_TEST))
1129                                 node_duplicate_reparent_recursive(parent);
1130                         break;
1131                 }
1132         }
1133         /* reparent node copy to parent copy */
1134         if (parent) {
1135                 nodeDetachNode(node->new_node);
1136                 nodeAttachNode(node->new_node, parent->new_node);
1137         }
1138 }
1139
1140 static int node_duplicate_exec(bContext *C, wmOperator *op)
1141 {
1142         SpaceNode *snode = CTX_wm_space_node(C);
1143         bNodeTree *ntree = snode->edittree;
1144         bNode *node, *newnode, *lastnode;
1145         bNodeLink *link, *newlink, *lastlink;
1146         int keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
1147         
1148         ED_preview_kill_jobs(C);
1149         
1150         lastnode = ntree->nodes.last;
1151         for (node = ntree->nodes.first; node; node = node->next) {
1152                 if (node->flag & SELECT) {
1153                         newnode = nodeCopyNode(ntree, node);
1154                         
1155                         if (newnode->id) {
1156                                 /* simple id user adjustment, node internal functions don't touch this
1157                                  * but operators and readfile.c do. */
1158                                 id_us_plus(newnode->id);
1159                                 /* to ensure redraws or rerenders happen */
1160                                 ED_node_changed_update(snode->id, newnode);
1161                         }
1162                 }
1163                 
1164                 /* make sure we don't copy new nodes again! */
1165                 if (node == lastnode)
1166                         break;
1167         }
1168         
1169         /* copy links between selected nodes
1170          * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
1171          */
1172         lastlink = ntree->links.last;
1173         for (link = ntree->links.first; link; link = link->next) {
1174                 /* This creates new links between copied nodes.
1175                  * If keep_inputs is set, also copies input links from unselected (when fromnode==NULL)!
1176                  */
1177                 if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
1178                     (keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT))))
1179                 {
1180                         newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
1181                         newlink->flag = link->flag;
1182                         newlink->tonode = link->tonode->new_node;
1183                         newlink->tosock = link->tosock->new_sock;
1184                         if (link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
1185                                 newlink->fromnode = link->fromnode->new_node;
1186                                 newlink->fromsock = link->fromsock->new_sock;
1187                         }
1188                         else {
1189                                 /* input node not copied, this keeps the original input linked */
1190                                 newlink->fromnode = link->fromnode;
1191                                 newlink->fromsock = link->fromsock;
1192                         }
1193                         
1194                         BLI_addtail(&ntree->links, newlink);
1195                 }
1196                 
1197                 /* make sure we don't copy new links again! */
1198                 if (link == lastlink)
1199                         break;
1200         }
1201         
1202         /* clear flags for recursive depth-first iteration */
1203         for (node = ntree->nodes.first; node; node = node->next)
1204                 node->flag &= ~NODE_TEST;
1205         /* reparent copied nodes */
1206         for (node = ntree->nodes.first; node; node = node->next) {
1207                 if ((node->flag & SELECT) && !(node->flag & NODE_TEST))
1208                         node_duplicate_reparent_recursive(node);
1209                 
1210                 /* only has to check old nodes */
1211                 if (node == lastnode)
1212                         break;
1213         }
1214         
1215         /* deselect old nodes, select the copies instead */
1216         for (node = ntree->nodes.first; node; node = node->next) {
1217                 if (node->flag & SELECT) {
1218                         /* has been set during copy above */
1219                         newnode = node->new_node;
1220                         
1221                         node_deselect(node);
1222                         node->flag &= ~NODE_ACTIVE;
1223                         node_select(newnode);
1224                 }
1225                 
1226                 /* make sure we don't copy new nodes again! */
1227                 if (node == lastnode)
1228                         break;
1229         }
1230         
1231         ntreeUpdateTree(snode->edittree);
1232         
1233         snode_notify(C, snode);
1234         snode_dag_update(C, snode);
1235
1236         return OPERATOR_FINISHED;
1237 }
1238
1239 void NODE_OT_duplicate(wmOperatorType *ot)
1240 {
1241         /* identifiers */
1242         ot->name = "Duplicate Nodes";
1243         ot->description = "Duplicate selected nodes";
1244         ot->idname = "NODE_OT_duplicate";
1245         
1246         /* api callbacks */
1247         ot->exec = node_duplicate_exec;
1248         ot->poll = ED_operator_node_active;
1249         
1250         /* flags */
1251         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1252         
1253         RNA_def_boolean(ot->srna, "keep_inputs", 0, "Keep Inputs", "Keep the input links to duplicated nodes");
1254 }
1255
1256 int ED_node_select_check(ListBase *lb)
1257 {
1258         bNode *node;
1259
1260         for (node = lb->first; node; node = node->next) {
1261                 if (node->flag & NODE_SELECT) {
1262                         return TRUE;
1263                 }
1264         }
1265
1266         return FALSE;
1267 }
1268
1269 /* ******************************** */
1270 // XXX some code needing updating to operators...
1271
1272
1273 /* goes over all scenes, reads render layers */
1274 static int node_read_renderlayers_exec(bContext *C, wmOperator *UNUSED(op))
1275 {
1276         Main *bmain = CTX_data_main(C);
1277         SpaceNode *snode = CTX_wm_space_node(C);
1278         Scene *curscene = CTX_data_scene(C), *scene;
1279         bNode *node;
1280
1281         ED_preview_kill_jobs(C);
1282
1283         /* first tag scenes unread */
1284         for (scene = bmain->scene.first; scene; scene = scene->id.next)
1285                 scene->id.flag |= LIB_DOIT;
1286
1287         for (node = snode->edittree->nodes.first; node; node = node->next) {
1288                 if (node->type == CMP_NODE_R_LAYERS) {
1289                         ID *id = node->id;
1290                         if (id->flag & LIB_DOIT) {
1291                                 RE_ReadRenderResult(curscene, (Scene *)id);
1292                                 ntreeCompositTagRender((Scene *)id);
1293                                 id->flag &= ~LIB_DOIT;
1294                         }
1295                 }
1296         }
1297         
1298         snode_notify(C, snode);
1299         snode_dag_update(C, snode);
1300
1301         return OPERATOR_FINISHED;
1302 }
1303
1304 void NODE_OT_read_renderlayers(wmOperatorType *ot)
1305 {
1306         
1307         ot->name = "Read Render Layers";
1308         ot->idname = "NODE_OT_read_renderlayers";
1309         ot->description = "Read all render layers of all used scenes";
1310         
1311         ot->exec = node_read_renderlayers_exec;
1312         
1313         ot->poll = composite_node_active;
1314         
1315         /* flags */
1316         ot->flag = 0;
1317 }
1318
1319 static int node_read_fullsamplelayers_exec(bContext *C, wmOperator *UNUSED(op))
1320 {
1321         Main *bmain = CTX_data_main(C);
1322         SpaceNode *snode = CTX_wm_space_node(C);
1323         Scene *curscene = CTX_data_scene(C);
1324         Render *re = RE_NewRender(curscene->id.name);
1325
1326         WM_cursor_wait(1);
1327         RE_MergeFullSample(re, bmain, curscene, snode->nodetree);
1328         WM_cursor_wait(0);
1329
1330         /* note we are careful to send the right notifier, as otherwise the
1331          * compositor would reexecute and overwrite the full sample result */
1332         WM_event_add_notifier(C, NC_SCENE | ND_COMPO_RESULT, NULL);
1333
1334         return OPERATOR_FINISHED;
1335 }
1336
1337
1338 void NODE_OT_read_fullsamplelayers(wmOperatorType *ot)
1339 {
1340         
1341         ot->name = "Read Full Sample Layers";
1342         ot->idname = "NODE_OT_read_fullsamplelayers";
1343         ot->description = "Read all render layers of current scene, in full sample";
1344         
1345         ot->exec = node_read_fullsamplelayers_exec;
1346         
1347         ot->poll = composite_node_active;
1348         
1349         /* flags */
1350         ot->flag = 0;
1351 }
1352
1353 int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op))
1354 {
1355         Scene *sce = CTX_data_scene(C);
1356         bNode *node;
1357         
1358         for (node = sce->nodetree->nodes.first; node; node = node->next) {
1359                 if (node->id == (ID *)sce && node->need_exec) {
1360                         break;
1361                 }
1362         }
1363         if (node) {
1364                 SceneRenderLayer *srl = BLI_findlink(&sce->r.layers, node->custom1);
1365                 
1366                 if (srl) {
1367                         PointerRNA op_ptr;
1368                         
1369                         WM_operator_properties_create(&op_ptr, "RENDER_OT_render");
1370                         RNA_string_set(&op_ptr, "layer", srl->name);
1371                         RNA_string_set(&op_ptr, "scene", sce->id.name + 2);
1372                         
1373                         /* to keep keypositions */
1374                         sce->r.scemode |= R_NO_FRAME_UPDATE;
1375                         
1376                         WM_operator_name_call(C, "RENDER_OT_render", WM_OP_INVOKE_DEFAULT, &op_ptr);
1377
1378                         WM_operator_properties_free(&op_ptr);
1379                         
1380                         return OPERATOR_FINISHED;
1381                 }
1382                    
1383         }
1384         return OPERATOR_CANCELLED;
1385 }
1386
1387 void NODE_OT_render_changed(wmOperatorType *ot)
1388 {
1389         ot->name = "Render Changed Layer";
1390         ot->idname = "NODE_OT_render_changed";
1391         ot->description = "Render current scene, when input node's layer has been changed";
1392         
1393         ot->exec = node_render_changed_exec;
1394         
1395         ot->poll = composite_node_active;
1396         
1397         /* flags */
1398         ot->flag = 0;
1399 }
1400
1401 /* ****************** Hide operator *********************** */
1402
1403 static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
1404 {
1405         bNode *node;
1406         int tot_eq = 0, tot_neq = 0;
1407
1408         /* Toggles the flag on all selected nodes.
1409          * If the flag is set on all nodes it is unset.
1410          * If the flag is not set on all nodes, it is set.
1411          */
1412         for (node = snode->edittree->nodes.first; node; node = node->next) {
1413                 if (node->flag & SELECT) {
1414                         
1415                         if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0)
1416                                 continue;
1417                         if (toggle_flag == NODE_OPTIONS && (node->typeinfo->flag & NODE_OPTIONS) == 0)
1418                                 continue;
1419                         
1420                         if (node->flag & toggle_flag)
1421                                 tot_eq++;
1422                         else
1423                                 tot_neq++;
1424                 }
1425         }
1426         for (node = snode->edittree->nodes.first; node; node = node->next) {
1427                 if (node->flag & SELECT) {
1428                         
1429                         if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0)
1430                                 continue;
1431                         if (toggle_flag == NODE_OPTIONS && (node->typeinfo->flag & NODE_OPTIONS) == 0)
1432                                 continue;
1433                         
1434                         if ( (tot_eq && tot_neq) || tot_eq == 0)
1435                                 node->flag |= toggle_flag;
1436                         else
1437                                 node->flag &= ~toggle_flag;
1438                 }
1439         }
1440 }
1441
1442 static int node_hide_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1443 {
1444         SpaceNode *snode = CTX_wm_space_node(C);
1445         
1446         /* sanity checking (poll callback checks this already) */
1447         if ((snode == NULL) || (snode->edittree == NULL))
1448                 return OPERATOR_CANCELLED;
1449         
1450         node_flag_toggle_exec(snode, NODE_HIDDEN);
1451
1452         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1453
1454         return OPERATOR_FINISHED;
1455 }
1456
1457 void NODE_OT_hide_toggle(wmOperatorType *ot)
1458 {
1459         /* identifiers */
1460         ot->name = "Hide";
1461         ot->description = "Toggle hiding of selected nodes";
1462         ot->idname = "NODE_OT_hide_toggle";
1463         
1464         /* callbacks */
1465         ot->exec = node_hide_toggle_exec;
1466         ot->poll = ED_operator_node_active;
1467
1468         /* flags */
1469         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1470 }
1471
1472 static int node_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1473 {
1474         SpaceNode *snode = CTX_wm_space_node(C);
1475
1476         /* sanity checking (poll callback checks this already) */
1477         if ((snode == NULL) || (snode->edittree == NULL))
1478                 return OPERATOR_CANCELLED;
1479
1480         ED_preview_kill_jobs(C);
1481
1482         node_flag_toggle_exec(snode, NODE_PREVIEW);
1483
1484         snode_notify(C, snode);
1485
1486         return OPERATOR_FINISHED;
1487 }
1488
1489 void NODE_OT_preview_toggle(wmOperatorType *ot)
1490 {
1491         /* identifiers */
1492         ot->name = "Toggle Node Preview";
1493         ot->description = "Toggle preview display for selected nodes";
1494         ot->idname = "NODE_OT_preview_toggle";
1495
1496         /* callbacks */
1497         ot->exec = node_preview_toggle_exec;
1498         ot->poll = ED_operator_node_active;
1499
1500         /* flags */
1501         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1502 }
1503
1504 static int node_options_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1505 {
1506         SpaceNode *snode = CTX_wm_space_node(C);
1507
1508         /* sanity checking (poll callback checks this already) */
1509         if ((snode == NULL) || (snode->edittree == NULL))
1510                 return OPERATOR_CANCELLED;
1511
1512         node_flag_toggle_exec(snode, NODE_OPTIONS);
1513
1514         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1515
1516         return OPERATOR_FINISHED;
1517 }
1518
1519 void NODE_OT_options_toggle(wmOperatorType *ot)
1520 {
1521         /* identifiers */
1522         ot->name = "Toggle Node Options";
1523         ot->description = "Toggle option buttons display for selected nodes";
1524         ot->idname = "NODE_OT_options_toggle";
1525
1526         /* callbacks */
1527         ot->exec = node_options_toggle_exec;
1528         ot->poll = ED_operator_node_active;
1529
1530         /* flags */
1531         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1532 }
1533
1534 static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1535 {
1536         SpaceNode *snode = CTX_wm_space_node(C);
1537         bNode *node;
1538         int hidden;
1539
1540         /* sanity checking (poll callback checks this already) */
1541         if ((snode == NULL) || (snode->edittree == NULL))
1542                 return OPERATOR_CANCELLED;
1543
1544         ED_preview_kill_jobs(C);
1545
1546         /* Toggle for all selected nodes */
1547         hidden = 0;
1548         for (node = snode->edittree->nodes.first; node; node = node->next) {
1549                 if (node->flag & SELECT) {
1550                         if (node_has_hidden_sockets(node)) {
1551                                 hidden = 1;
1552                                 break;
1553                         }
1554                 }
1555         }
1556         
1557         for (node = snode->edittree->nodes.first; node; node = node->next) {
1558                 if (node->flag & SELECT) {
1559                         node_set_hidden_sockets(snode, node, !hidden);
1560                 }
1561         }
1562
1563         ntreeUpdateTree(snode->edittree);
1564
1565         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1566
1567         return OPERATOR_FINISHED;
1568 }
1569
1570 void NODE_OT_hide_socket_toggle(wmOperatorType *ot)
1571 {
1572         /* identifiers */
1573         ot->name = "Toggle Hidden Node Sockets";
1574         ot->description = "Toggle unused node socket display";
1575         ot->idname = "NODE_OT_hide_socket_toggle";
1576
1577         /* callbacks */
1578         ot->exec = node_socket_toggle_exec;
1579         ot->poll = ED_operator_node_active;
1580
1581         /* flags */
1582         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1583 }
1584
1585 /* ****************** Mute operator *********************** */
1586
1587 static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
1588 {
1589         SpaceNode *snode = CTX_wm_space_node(C);
1590         bNode *node;
1591
1592         ED_preview_kill_jobs(C);
1593
1594         for (node = snode->edittree->nodes.first; node; node = node->next) {
1595                 /* Only allow muting of nodes having a mute func! */
1596                 if ((node->flag & SELECT) && node->typeinfo->internal_connect) {
1597                         node->flag ^= NODE_MUTED;
1598                         snode_update(snode, node);
1599                 }
1600         }
1601         
1602         snode_notify(C, snode);
1603         snode_dag_update(C, snode);
1604         
1605         return OPERATOR_FINISHED;
1606 }
1607
1608 void NODE_OT_mute_toggle(wmOperatorType *ot)
1609 {
1610         /* identifiers */
1611         ot->name = "Toggle Node Mute";
1612         ot->description = "Toggle muting of the nodes";
1613         ot->idname = "NODE_OT_mute_toggle";
1614         
1615         /* callbacks */
1616         ot->exec = node_mute_exec;
1617         ot->poll = ED_operator_node_active;
1618         
1619         /* flags */
1620         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1621 }
1622
1623 /* ****************** Delete operator ******************* */
1624
1625 static int node_delete_exec(bContext *C, wmOperator *UNUSED(op))
1626 {
1627         SpaceNode *snode = CTX_wm_space_node(C);
1628         bNode *node, *next;
1629         
1630         ED_preview_kill_jobs(C);
1631
1632         for (node = snode->edittree->nodes.first; node; node = next) {
1633                 next = node->next;
1634                 if (node->flag & SELECT) {
1635                         /* check id user here, nodeFreeNode is called for free dbase too */
1636                         if (node->id)
1637                                 node->id->us--;
1638                         nodeFreeNode(snode->edittree, node);
1639                 }
1640         }
1641         
1642         ntreeUpdateTree(snode->edittree);
1643
1644         snode_notify(C, snode);
1645         snode_dag_update(C, snode);
1646         
1647         return OPERATOR_FINISHED;
1648 }
1649
1650 void NODE_OT_delete(wmOperatorType *ot)
1651 {
1652         /* identifiers */
1653         ot->name = "Delete";
1654         ot->description = "Delete selected nodes";
1655         ot->idname = "NODE_OT_delete";
1656         
1657         /* api callbacks */
1658         ot->exec = node_delete_exec;
1659         ot->poll = ED_operator_node_active;
1660         
1661         /* flags */
1662         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1663 }
1664
1665 /* ****************** Delete with reconnect ******************* */
1666 static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
1667 {
1668         SpaceNode *snode = CTX_wm_space_node(C);
1669         bNode *node, *next;
1670
1671         ED_preview_kill_jobs(C);
1672
1673         for (node = snode->edittree->nodes.first; node; node = next) {
1674                 next = node->next;
1675                 if (node->flag & SELECT) {
1676                         nodeInternalRelink(snode->edittree, node);
1677                         
1678                         /* check id user here, nodeFreeNode is called for free dbase too */
1679                         if (node->id)
1680                                 node->id->us--;
1681                         nodeFreeNode(snode->edittree, node);
1682                 }
1683         }
1684
1685         ntreeUpdateTree(snode->edittree);
1686
1687         snode_notify(C, snode);
1688         snode_dag_update(C, snode);
1689
1690         return OPERATOR_FINISHED;
1691 }
1692
1693 void NODE_OT_delete_reconnect(wmOperatorType *ot)
1694 {
1695         /* identifiers */
1696         ot->name = "Delete with reconnect";
1697         ot->description = "Delete nodes; will reconnect nodes as if deletion was muted";
1698         ot->idname = "NODE_OT_delete_reconnect";
1699
1700         /* api callbacks */
1701         ot->exec = node_delete_reconnect_exec;
1702         ot->poll = ED_operator_node_active;
1703
1704         /* flags */
1705         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1706 }
1707
1708
1709 /* ****************** File Output Add Socket  ******************* */
1710
1711 static int node_output_file_add_socket_exec(bContext *C, wmOperator *op)
1712 {
1713         Scene *scene = CTX_data_scene(C);
1714         SpaceNode *snode = CTX_wm_space_node(C);
1715         PointerRNA ptr;
1716         bNodeTree *ntree;
1717         bNode *node;
1718         char file_path[MAX_NAME];
1719
1720         ptr = CTX_data_pointer_get(C, "node");
1721         if (!ptr.data)
1722                 return OPERATOR_CANCELLED;
1723         node = ptr.data;
1724         ntree = ptr.id.data;
1725
1726         RNA_string_get(op->ptr, "file_path", file_path);
1727         ntreeCompositOutputFileAddSocket(ntree, node, file_path, &scene->r.im_format);
1728
1729         snode_notify(C, snode);
1730
1731         return OPERATOR_FINISHED;
1732 }
1733
1734 void NODE_OT_output_file_add_socket(wmOperatorType *ot)
1735 {
1736         /* identifiers */
1737         ot->name = "Add File Node Socket";
1738         ot->description = "Add a new input to a file output node";
1739         ot->idname = "NODE_OT_output_file_add_socket";
1740
1741         /* callbacks */
1742         ot->exec = node_output_file_add_socket_exec;
1743         ot->poll = composite_node_active;
1744
1745         /* flags */
1746         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1747
1748         RNA_def_string(ot->srna, "file_path", "Image", MAX_NAME, "File Path", "Sub-path of the output file");
1749 }
1750
1751 /* ****************** Multi File Output Remove Socket  ******************* */
1752
1753 static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *UNUSED(op))
1754 {
1755         SpaceNode *snode = CTX_wm_space_node(C);
1756         PointerRNA ptr = CTX_data_pointer_get(C, "node");
1757         bNodeTree *ntree;
1758         bNode *node;
1759         
1760         if (!ptr.data)
1761                 return OPERATOR_CANCELLED;
1762         node = ptr.data;
1763         ntree = ptr.id.data;
1764         
1765         if (!ntreeCompositOutputFileRemoveActiveSocket(ntree, node))
1766                 return OPERATOR_CANCELLED;
1767         
1768         snode_notify(C, snode);
1769         
1770         return OPERATOR_FINISHED;
1771 }
1772
1773 void NODE_OT_output_file_remove_active_socket(wmOperatorType *ot)
1774 {
1775         /* identifiers */
1776         ot->name = "Remove File Node Socket";
1777         ot->description = "Remove active input from a file output node";
1778         ot->idname = "NODE_OT_output_file_remove_active_socket";
1779         
1780         /* callbacks */
1781         ot->exec = node_output_file_remove_active_socket_exec;
1782         ot->poll = composite_node_active;
1783         
1784         /* flags */
1785         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1786 }
1787
1788 /* ****************** Multi File Output Move Socket  ******************* */
1789
1790 static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
1791 {
1792         SpaceNode *snode = CTX_wm_space_node(C);
1793         PointerRNA ptr = CTX_data_pointer_get(C, "node");
1794         bNode *node;
1795         NodeImageMultiFile *nimf;
1796         bNodeSocket *sock;
1797         int direction;
1798         
1799         if (!ptr.data)
1800                 return OPERATOR_CANCELLED;
1801         node = ptr.data;
1802         nimf = node->storage;
1803         
1804         sock = BLI_findlink(&node->inputs, nimf->active_input);
1805         if (!sock)
1806                 return OPERATOR_CANCELLED;
1807         
1808         direction = RNA_enum_get(op->ptr, "direction");
1809         
1810         if (direction == 1) {
1811                 bNodeSocket *before = sock->prev;
1812                 if (!before)
1813                         return OPERATOR_CANCELLED;
1814                 BLI_remlink(&node->inputs, sock);
1815                 BLI_insertlinkbefore(&node->inputs, before, sock);
1816                 --nimf->active_input;
1817         }
1818         else {
1819                 bNodeSocket *after = sock->next;
1820                 if (!after)
1821                         return OPERATOR_CANCELLED;
1822                 BLI_remlink(&node->inputs, sock);
1823                 BLI_insertlinkafter(&node->inputs, after, sock);
1824                 ++nimf->active_input;
1825         }
1826         
1827         snode_notify(C, snode);
1828         
1829         return OPERATOR_FINISHED;
1830 }
1831
1832 void NODE_OT_output_file_move_active_socket(wmOperatorType *ot)
1833 {
1834         static EnumPropertyItem direction_items[] = {
1835                 {1, "UP", 0, "Up", ""},
1836                 {2, "DOWN", 0, "Down", ""},
1837                 { 0, NULL, 0, NULL, NULL }
1838         };
1839         
1840         /* identifiers */
1841         ot->name = "Move File Node Socket";
1842         ot->description = "Move the active input of a file output node up or down the list";
1843         ot->idname = "NODE_OT_output_file_move_active_socket";
1844         
1845         /* callbacks */
1846         ot->exec = node_output_file_move_active_socket_exec;
1847         ot->poll = composite_node_active;
1848         
1849         /* flags */
1850         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1851         
1852         RNA_def_enum(ot->srna, "direction", direction_items, 2, "Direction", "");
1853 }
1854
1855 /* ****************** Copy Node Color ******************* */
1856
1857 static int node_copy_color_exec(bContext *C, wmOperator *UNUSED(op))
1858 {
1859         SpaceNode *snode = CTX_wm_space_node(C);
1860         bNodeTree *ntree = snode->edittree;
1861         bNode *node, *tnode;
1862         
1863         if (!ntree)
1864                 return OPERATOR_CANCELLED;
1865         node = nodeGetActive(ntree);
1866         if (!node)
1867                 return OPERATOR_CANCELLED;
1868         
1869         for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
1870                 if (tnode->flag & NODE_SELECT && tnode != node) {
1871                         if (node->flag & NODE_CUSTOM_COLOR) {
1872                                 tnode->flag |= NODE_CUSTOM_COLOR;
1873                                 copy_v3_v3(tnode->color, node->color);
1874                         }
1875                         else
1876                                 tnode->flag &= ~NODE_CUSTOM_COLOR;
1877                 }
1878         }
1879
1880         ED_node_sort(ntree);
1881         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1882
1883         return OPERATOR_FINISHED;
1884 }
1885
1886 void NODE_OT_node_copy_color(wmOperatorType *ot)
1887 {
1888         /* identifiers */
1889         ot->name = "Copy Color";
1890         ot->description = "Copy color to all selected nodes";
1891         ot->idname = "NODE_OT_node_copy_color";
1892
1893         /* api callbacks */
1894         ot->exec = node_copy_color_exec;
1895         ot->poll = ED_operator_node_active;
1896
1897         /* flags */
1898         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1899 }
1900
1901 /* ****************** Copy to clipboard ******************* */
1902
1903 static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
1904 {
1905         SpaceNode *snode = CTX_wm_space_node(C);
1906         bNodeTree *ntree = snode->edittree;
1907         bNode *gnode = node_tree_get_editgroup(snode->nodetree);
1908         float gnode_x = 0.0f, gnode_y = 0.0f;
1909         bNode *node, *new_node;
1910         bNodeLink *link, *newlink;
1911
1912         ED_preview_kill_jobs(C);
1913
1914         /* clear current clipboard */
1915         nodeClipboardClear();
1916
1917         /* get group node offset */
1918         if (gnode)
1919                 nodeToView(gnode, 0.0f, 0.0f, &gnode_x, &gnode_y);
1920         
1921         for (node = ntree->nodes.first; node; node = node->next) {
1922                 if (node->flag & SELECT) {
1923                         new_node = nodeCopyNode(NULL, node);
1924                         nodeClipboardAddNode(new_node);
1925                 }
1926         }
1927
1928         for (node = ntree->nodes.first; node; node = node->next) {
1929                 if (node->flag & SELECT) {
1930                         bNode *new_node = node->new_node;
1931                         
1932                         /* ensure valid pointers */
1933                         if (new_node->parent) {
1934                                 /* parent pointer must be redirected to new node or detached if parent is not copied */
1935                                 if (new_node->parent->flag & NODE_SELECT) {
1936                                         new_node->parent = new_node->parent->new_node;
1937                                 }
1938                                 else {
1939                                         nodeDetachNode(new_node);
1940                                 }
1941                         }
1942
1943                         /* transform to basic view space. child node location is relative to parent */
1944                         if (!new_node->parent) {        
1945                                 new_node->locx += gnode_x;
1946                                 new_node->locy += gnode_y;
1947                         }
1948                 }
1949         }
1950
1951         /* copy links between selected nodes
1952          * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
1953          */
1954         for (link = ntree->links.first; link; link = link->next) {
1955                 /* This creates new links between copied nodes. */
1956                 if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
1957                     link->fromnode && (link->fromnode->flag & NODE_SELECT))
1958                 {
1959                         newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
1960                         newlink->flag = link->flag;
1961                         newlink->tonode = link->tonode->new_node;
1962                         newlink->tosock = link->tosock->new_sock;
1963                         newlink->fromnode = link->fromnode->new_node;
1964                         newlink->fromsock = link->fromsock->new_sock;
1965
1966                         nodeClipboardAddLink(newlink);
1967                 }
1968         }
1969
1970         return OPERATOR_FINISHED;
1971 }
1972
1973 void NODE_OT_clipboard_copy(wmOperatorType *ot)
1974 {
1975         /* identifiers */
1976         ot->name = "Copy to clipboard";
1977         ot->description = "Copies selected nodes to the clipboard";
1978         ot->idname = "NODE_OT_clipboard_copy";
1979
1980         /* api callbacks */
1981         ot->exec = node_clipboard_copy_exec;
1982         ot->poll = ED_operator_node_active;
1983
1984         /* flags */
1985         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1986 }
1987
1988 /* ****************** Paste from clipboard ******************* */
1989
1990 static int node_clipboard_paste_exec(bContext *C, wmOperator *UNUSED(op))
1991 {
1992         SpaceNode *snode = CTX_wm_space_node(C);
1993         bNodeTree *ntree = snode->edittree;
1994         bNode *gnode = node_tree_get_editgroup(snode->nodetree);
1995         float gnode_x = 0.0f, gnode_y = 0.0f;
1996         bNode *node;
1997         bNodeLink *link;
1998         int num_nodes;
1999         float centerx, centery;
2000
2001         ED_preview_kill_jobs(C);
2002
2003         /* deselect old nodes */
2004         node_deselect_all(snode);
2005
2006         /* get group node offset */
2007         if (gnode)
2008                 nodeToView(gnode, 0.0f, 0.0f, &gnode_x, &gnode_y);
2009
2010         /* calculate "barycenter" for placing on mouse cursor */
2011         num_nodes = 0;
2012         centerx = centery = 0.0f;
2013         for (node = nodeClipboardGetNodes()->first; node; node = node->next) {
2014                 ++num_nodes;
2015                 centerx += 0.5f * (node->totr.xmin + node->totr.xmax);
2016                 centery += 0.5f * (node->totr.ymin + node->totr.ymax);
2017         }
2018         centerx /= num_nodes;
2019         centery /= num_nodes;
2020
2021         /* copy nodes from clipboard */
2022         for (node = nodeClipboardGetNodes()->first; node; node = node->next) {
2023                 bNode *new_node = nodeCopyNode(ntree, node);
2024
2025                 /* pasted nodes are selected */
2026                 node_select(new_node);
2027         }
2028         
2029         /* reparent copied nodes */
2030         for (node = nodeClipboardGetNodes()->first; node; node = node->next) {
2031                 bNode *new_node = node->new_node;
2032                 if (new_node->parent)
2033                         new_node->parent = new_node->parent->new_node;
2034                 
2035                 
2036                 /* place nodes around the mouse cursor. child nodes locations are relative to parent */
2037                 if (!new_node->parent) {
2038                         new_node->locx += snode->mx - centerx - gnode_x;
2039                         new_node->locy += snode->my - centery - gnode_y;
2040                 }
2041         }
2042
2043         for (link = nodeClipboardGetLinks()->first; link; link = link->next) {
2044                 nodeAddLink(ntree, link->fromnode->new_node, link->fromsock->new_sock,
2045                             link->tonode->new_node, link->tosock->new_sock);
2046         }
2047
2048         ntreeUpdateTree(snode->edittree);
2049
2050         snode_notify(C, snode);
2051         snode_dag_update(C, snode);
2052
2053         return OPERATOR_FINISHED;
2054 }
2055
2056 static int node_clipboard_paste_invoke(bContext *C, wmOperator *op, wmEvent *event)
2057 {
2058         ARegion *ar = CTX_wm_region(C);
2059         SpaceNode *snode = CTX_wm_space_node(C);
2060
2061         /* convert mouse coordinates to v2d space */
2062         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->mx, &snode->my);
2063
2064         return node_clipboard_paste_exec(C, op);
2065 }
2066
2067 void NODE_OT_clipboard_paste(wmOperatorType *ot)
2068 {
2069         /* identifiers */
2070         ot->name = "Paste from clipboard";
2071         ot->description = "Pastes nodes from the clipboard to the active node tree";
2072         ot->idname = "NODE_OT_clipboard_paste";
2073
2074         /* api callbacks */
2075         ot->exec = node_clipboard_paste_exec;
2076         ot->invoke = node_clipboard_paste_invoke;
2077         ot->poll = ED_operator_node_active;
2078
2079         /* flags */
2080         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2081 }