fix usercount error with dropping images in the node view.
[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
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <math.h>
36 #include <string.h>
37 #include <errno.h>
38
39 #include "MEM_guardedalloc.h"
40
41 #include "DNA_ID.h"
42 #include "DNA_lamp_types.h"
43 #include "DNA_material_types.h"
44 #include "DNA_node_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_particle_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_world_types.h"
49 #include "DNA_action_types.h"
50 #include "DNA_anim_types.h"
51
52 #include "BLI_math.h"
53 #include "BLI_blenlib.h"
54 #include "BLI_utildefines.h"
55
56 #include "BKE_action.h"
57 #include "BKE_animsys.h"
58 #include "BKE_context.h"
59 #include "BKE_depsgraph.h"
60 #include "BKE_global.h"
61 #include "BKE_image.h"
62 #include "BKE_library.h"
63 #include "BKE_main.h"
64 #include "BKE_node.h"
65 #include "BKE_material.h"
66 #include "BKE_modifier.h"
67 #include "BKE_paint.h"
68 #include "BKE_scene.h"
69 #include "BKE_screen.h"
70 #include "BKE_texture.h"
71 #include "BKE_report.h"
72
73 #include "RE_pipeline.h"
74
75 #include "IMB_imbuf_types.h"
76
77 #include "ED_node.h"
78 #include "ED_image.h"
79 #include "ED_screen.h"
80 #include "ED_space_api.h"
81 #include "ED_render.h"
82
83 #include "RNA_access.h"
84 #include "RNA_define.h"
85 #include "RNA_enum_types.h"
86
87 #include "WM_api.h"
88 #include "WM_types.h"
89
90 #include "UI_interface.h"
91 #include "UI_resources.h"
92 #include "UI_view2d.h"
93
94 #include "IMB_imbuf.h"
95
96 #include "RNA_enum_types.h"
97
98 #include "GPU_material.h"
99
100 #include "node_intern.h"
101 #include "NOD_socket.h"
102
103 static EnumPropertyItem socket_in_out_items[] = {
104         { SOCK_IN, "SOCK_IN", 0, "Input", "" },
105         { SOCK_OUT, "SOCK_OUT", 0, "Output", "" },
106         { 0, NULL, 0, NULL, NULL },
107 };
108
109 /* ***************** composite job manager ********************** */
110
111 typedef struct CompoJob {
112         Scene *scene;
113         bNodeTree *ntree;
114         bNodeTree *localtree;
115         short *stop;
116         short *do_update;
117         float *progress;
118 } CompoJob;
119
120 /* called by compo, only to check job 'stop' value */
121 static int compo_breakjob(void *cjv)
122 {
123         CompoJob *cj = cjv;
124         
125         return *(cj->stop);
126 }
127
128 /* called by compo, wmJob sends notifier */
129 static void compo_redrawjob(void *cjv, char *UNUSED(str))
130 {
131         CompoJob *cj = cjv;
132         
133         *(cj->do_update) = TRUE;
134 }
135
136 static void compo_freejob(void *cjv)
137 {
138         CompoJob *cj = cjv;
139
140         if (cj->localtree) {
141                 ntreeLocalMerge(cj->localtree, cj->ntree);
142         }
143         MEM_freeN(cj);
144 }
145
146 /* only now we copy the nodetree, so adding many jobs while
147  * sliding buttons doesn't frustrate */
148 static void compo_initjob(void *cjv)
149 {
150         CompoJob *cj = cjv;
151
152         cj->localtree = ntreeLocalize(cj->ntree);
153 }
154
155 /* called before redraw notifiers, it moves finished previews over */
156 static void compo_updatejob(void *cjv)
157 {
158         CompoJob *cj = cjv;
159         
160         ntreeLocalSync(cj->localtree, cj->ntree);
161 }
162
163 static void compo_progressjob(void *cjv, float progress)
164 {
165         CompoJob *cj = cjv;
166         
167         *(cj->progress) = progress;
168 }
169
170
171 /* only this runs inside thread */
172 static void compo_startjob(void *cjv, short *stop, short *do_update, float *progress)
173 {
174         CompoJob *cj = cjv;
175         bNodeTree *ntree = cj->localtree;
176
177         if (cj->scene->use_nodes == FALSE)
178                 return;
179         
180         cj->stop = stop;
181         cj->do_update = do_update;
182         cj->progress = progress;
183
184         ntree->test_break = compo_breakjob;
185         ntree->tbh = cj;
186         ntree->stats_draw = compo_redrawjob;
187         ntree->sdh = cj;
188         ntree->progress = compo_progressjob;
189         ntree->prh = cj;
190         
191         // XXX BIF_store_spare();
192         
193         ntreeCompositExecTree(ntree, &cj->scene->r, 0, 1);  /* 1 is do_previews */
194
195         ntree->test_break = NULL;
196         ntree->stats_draw = NULL;
197         ntree->progress = NULL;
198
199 }
200
201 void snode_composite_job(const bContext *C, ScrArea *sa)
202 {
203         SpaceNode *snode = sa->spacedata.first;
204         wmJob *steve;
205         CompoJob *cj;
206
207         steve = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Compositing", WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS);
208         cj = MEM_callocN(sizeof(CompoJob), "compo job");
209         
210         /* customdata for preview thread */
211         cj->scene = CTX_data_scene(C);
212         cj->ntree = snode->nodetree;
213         
214         /* setup job */
215         WM_jobs_customdata(steve, cj, compo_freejob);
216         WM_jobs_timer(steve, 0.1, NC_SCENE, NC_SCENE | ND_COMPO_RESULT);
217         WM_jobs_callbacks(steve, compo_startjob, compo_initjob, compo_updatejob, NULL);
218         
219         WM_jobs_start(CTX_wm_manager(C), steve);
220         
221 }
222
223 /* ***************************************** */
224
225 /* operator poll callback */
226 static int composite_node_active(bContext *C)
227 {
228         if (ED_operator_node_active(C)) {
229                 SpaceNode *snode = CTX_wm_space_node(C);
230                 if (snode->treetype == NTREE_COMPOSIT)
231                         return 1;
232         }
233         return 0;
234 }
235
236 /* also checks for edited groups */
237 static bNode *editnode_get_active(bNodeTree *ntree)
238 {
239         bNode *node;
240         
241         /* check for edited group */
242         for (node = ntree->nodes.first; node; node = node->next)
243                 if (nodeGroupEditGet(node))
244                         break;
245         if (node)
246                 return nodeGetActive((bNodeTree *)node->id);
247         else
248                 return nodeGetActive(ntree);
249 }
250
251 static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
252 {
253         bNode *node;
254         
255         if (ntree == lookup)
256                 return 1;
257         
258         for (node = ntree->nodes.first; node; node = node->next)
259                 if (node->type == NODE_GROUP && node->id)
260                         if (has_nodetree((bNodeTree *)node->id, lookup))
261                                 return 1;
262         
263         return 0;
264 }
265
266 static void snode_dag_update_group(void *calldata, ID *owner_id, bNodeTree *ntree)
267 {
268         if (has_nodetree(ntree, calldata))
269                 DAG_id_tag_update(owner_id, 0);
270 }
271
272 void snode_dag_update(bContext *C, SpaceNode *snode)
273 {
274         Main *bmain = CTX_data_main(C);
275
276         /* for groups, update all ID's using this */
277         if (snode->edittree != snode->nodetree) {
278                 bNodeTreeType *tti = ntreeGetType(snode->edittree->type);
279                 tti->foreach_nodetree(bmain, snode->edittree, snode_dag_update_group);
280         }
281
282         DAG_id_tag_update(snode->id, 0);
283 }
284
285 void snode_notify(bContext *C, SpaceNode *snode)
286 {
287         WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL);
288
289         if (snode->treetype == NTREE_SHADER)
290                 WM_event_add_notifier(C, NC_MATERIAL | ND_NODES, snode->id);
291         else if (snode->treetype == NTREE_COMPOSIT)
292                 WM_event_add_notifier(C, NC_SCENE | ND_NODES, snode->id);
293         else if (snode->treetype == NTREE_TEXTURE)
294                 WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, snode->id);
295 }
296
297 bNode *node_tree_get_editgroup(bNodeTree *nodetree)
298 {
299         bNode *gnode;
300         
301         /* get the groupnode */
302         for (gnode = nodetree->nodes.first; gnode; gnode = gnode->next)
303                 if (nodeGroupEditGet(gnode))
304                         break;
305         return gnode;
306 }
307
308 /* assumes nothing being done in ntree yet, sets the default in/out node */
309 /* called from shading buttons or header */
310 void ED_node_shader_default(Scene *scene, ID *id)
311 {
312         bNode *in, *out;
313         bNodeSocket *fromsock, *tosock, *sock;
314         bNodeTree *ntree;
315         bNodeTemplate ntemp;
316         int output_type, shader_type;
317         float color[3], strength = 1.0f;
318         
319         ntree = ntreeAddTree("Shader Nodetree", NTREE_SHADER, 0);
320
321         switch (GS(id->name)) {
322                 case ID_MA: {
323                         Material *ma = (Material *)id;
324                         ma->nodetree = ntree;
325
326                         if (BKE_scene_use_new_shading_nodes(scene)) {
327                                 output_type = SH_NODE_OUTPUT_MATERIAL;
328                                 shader_type = SH_NODE_BSDF_DIFFUSE;
329                         }
330                         else {
331                                 output_type = SH_NODE_OUTPUT;
332                                 shader_type = SH_NODE_MATERIAL;
333                         }
334
335                         copy_v3_v3(color, &ma->r);
336                         strength = 0.0f;
337                         break;
338                 }
339                 case ID_WO: {
340                         World *wo = (World *)id;
341                         wo->nodetree = ntree;
342
343                         output_type = SH_NODE_OUTPUT_WORLD;
344                         shader_type = SH_NODE_BACKGROUND;
345
346                         copy_v3_v3(color, &wo->horr);
347                         strength = 1.0f;
348                         break;
349                 }
350                 case ID_LA: {
351                         Lamp *la = (Lamp *)id;
352                         la->nodetree = ntree;
353
354                         output_type = SH_NODE_OUTPUT_LAMP;
355                         shader_type = SH_NODE_EMISSION;
356
357                         copy_v3_v3(color, &la->r);
358                         if (la->type == LA_LOCAL || la->type == LA_SPOT || la->type == LA_AREA)
359                                 strength = 100.0f;
360                         else
361                                 strength = 1.0f;
362                         break;
363                 }
364                 default:
365                         printf("ED_node_shader_default called on wrong ID type.\n");
366                         return;
367         }
368         
369         ntemp.type = output_type;
370         out = nodeAddNode(ntree, &ntemp);
371         out->locx = 300.0f; out->locy = 300.0f;
372         
373         ntemp.type = shader_type;
374         in = nodeAddNode(ntree, &ntemp);
375         in->locx = 10.0f; in->locy = 300.0f;
376         nodeSetActive(ntree, in);
377         
378         /* only a link from color to color */
379         fromsock = in->outputs.first;
380         tosock = out->inputs.first;
381         nodeAddLink(ntree, in, fromsock, out, tosock);
382
383         /* default values */
384         if (BKE_scene_use_new_shading_nodes(scene)) {
385                 sock = in->inputs.first;
386                 copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, color);
387
388                 if (strength != 0.0f) {
389                         sock = in->inputs.last;
390                         ((bNodeSocketValueFloat *)sock->default_value)->value = strength;
391                 }
392         }
393         
394         ntreeUpdateTree(ntree);
395 }
396
397 /* assumes nothing being done in ntree yet, sets the default in/out node */
398 /* called from shading buttons or header */
399 void ED_node_composit_default(Scene *sce)
400 {
401         bNode *in, *out;
402         bNodeSocket *fromsock, *tosock;
403         bNodeTemplate ntemp;
404         
405         /* but lets check it anyway */
406         if (sce->nodetree) {
407                 if (G.debug & G_DEBUG)
408                         printf("error in composite initialize\n");
409                 return;
410         }
411         
412         sce->nodetree = ntreeAddTree("Compositing Nodetree", NTREE_COMPOSIT, 0);
413
414         sce->nodetree->chunksize = 256;
415         sce->nodetree->edit_quality = NTREE_QUALITY_HIGH;
416         sce->nodetree->render_quality = NTREE_QUALITY_HIGH;
417         
418         ntemp.type = CMP_NODE_COMPOSITE;
419         out = nodeAddNode(sce->nodetree, &ntemp);
420         out->locx = 300.0f; out->locy = 400.0f;
421         out->id = &sce->id;
422         id_us_plus(out->id);
423         
424         ntemp.type = CMP_NODE_R_LAYERS;
425         in = nodeAddNode(sce->nodetree, &ntemp);
426         in->locx = 10.0f; in->locy = 400.0f;
427         in->id = &sce->id;
428         id_us_plus(in->id);
429         nodeSetActive(sce->nodetree, in);
430         
431         /* links from color to color */
432         fromsock = in->outputs.first;
433         tosock = out->inputs.first;
434         nodeAddLink(sce->nodetree, in, fromsock, out, tosock);
435         
436         ntreeUpdateTree(sce->nodetree);
437         
438         // XXX ntreeCompositForceHidden(sce->nodetree);
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_texture_default(Tex *tx)
444 {
445         bNode *in, *out;
446         bNodeSocket *fromsock, *tosock;
447         bNodeTemplate ntemp;
448         
449         /* but lets check it anyway */
450         if (tx->nodetree) {
451                 if (G.debug & G_DEBUG)
452                         printf("error in texture initialize\n");
453                 return;
454         }
455         
456         tx->nodetree = ntreeAddTree("Texture Nodetree", NTREE_TEXTURE, 0);
457         
458         ntemp.type = TEX_NODE_OUTPUT;
459         out = nodeAddNode(tx->nodetree, &ntemp);
460         out->locx = 300.0f; out->locy = 300.0f;
461         
462         ntemp.type = TEX_NODE_CHECKER;
463         in = nodeAddNode(tx->nodetree, &ntemp);
464         in->locx = 10.0f; in->locy = 300.0f;
465         nodeSetActive(tx->nodetree, in);
466         
467         fromsock = in->outputs.first;
468         tosock = out->inputs.first;
469         nodeAddLink(tx->nodetree, in, fromsock, out, tosock);
470         
471         ntreeUpdateTree(tx->nodetree);
472 }
473
474 /* id is supposed to contain a node tree */
475 void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *treetype)
476 {
477         if (id) {
478                 bNode *node = NULL;
479                 short idtype = GS(id->name);
480         
481                 if (idtype == ID_NT) {
482                         *ntree = (bNodeTree *)id;
483                         if (treetype) *treetype = (*ntree)->type;
484                 }
485                 else if (idtype == ID_MA) {
486                         *ntree = ((Material *)id)->nodetree;
487                         if (treetype) *treetype = NTREE_SHADER;
488                 }
489                 else if (idtype == ID_LA) {
490                         *ntree = ((Lamp *)id)->nodetree;
491                         if (treetype) *treetype = NTREE_SHADER;
492                 }
493                 else if (idtype == ID_WO) {
494                         *ntree = ((World *)id)->nodetree;
495                         if (treetype) *treetype = NTREE_SHADER;
496                 }
497                 else if (idtype == ID_SCE) {
498                         *ntree = ((Scene *)id)->nodetree;
499                         if (treetype) *treetype = NTREE_COMPOSIT;
500                 }
501                 else if (idtype == ID_TE) {
502                         *ntree = ((Tex *)id)->nodetree;
503                         if (treetype) *treetype = NTREE_TEXTURE;
504                 }
505                 else {
506                         if (treetype) *treetype = 0;
507                         return;
508                 }
509         
510                 /* find editable group */
511                 if (edittree) {
512                         if (*ntree)
513                                 for (node = (*ntree)->nodes.first; node; node = node->next)
514                                         if (nodeGroupEditGet(node))
515                                                 break;
516                         
517                         if (node && node->id)
518                                 *edittree = (bNodeTree *)node->id;
519                         else
520                                 *edittree = *ntree;
521                 }
522         }
523         else {
524                 *ntree = NULL;
525                 *edittree = NULL;
526                 if (treetype) *treetype = 0;
527         }
528 }
529
530 /* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
531 void snode_set_context(SpaceNode *snode, Scene *scene)
532 {
533         Object *ob = OBACT;
534         
535         snode->id = snode->from = NULL;
536         
537         if (snode->treetype == NTREE_SHADER) {
538                 /* need active object, or we allow pinning... */
539                 if (snode->shaderfrom == SNODE_SHADER_OBJECT) {
540                         if (ob) {
541                                 if (ob->type == OB_LAMP) {
542                                         snode->from = &ob->id;
543                                         snode->id = ob->data;
544                                 }
545                                 else {
546                                         Material *ma = give_current_material(ob, ob->actcol);
547                                         if (ma) {
548                                                 snode->from = &ob->id;
549                                                 snode->id = &ma->id;
550                                         }
551                                 }
552                         }
553                 }
554                 else { /* SNODE_SHADER_WORLD */
555                         if (scene->world) {
556                                 snode->from = NULL;
557                                 snode->id = &scene->world->id;
558                         }
559                 }
560         }
561         else if (snode->treetype == NTREE_COMPOSIT) {
562                 snode->id = &scene->id;
563                 
564                 /* update output sockets based on available layers */
565                 ntreeCompositForceHidden(scene->nodetree, scene);
566         }
567         else if (snode->treetype == NTREE_TEXTURE) {
568                 Tex *tx = NULL;
569
570                 if (snode->texfrom == SNODE_TEX_OBJECT) {
571                         if (ob) {
572                                 tx = give_current_object_texture(ob);
573
574                                 if (ob->type == OB_LAMP)
575                                         snode->from = (ID *)ob->data;
576                                 else
577                                         snode->from = (ID *)give_current_material(ob, ob->actcol);
578
579                                 /* from is not set fully for material nodes, should be ID + Node then */
580                                 snode->id = &tx->id;
581                         }
582                 }
583                 else if (snode->texfrom == SNODE_TEX_WORLD) {
584                         tx = give_current_world_texture(scene->world);
585                         snode->from = (ID *)scene->world;
586                         snode->id = &tx->id;
587                 }
588                 else {
589                         struct Brush *brush = NULL;
590                         
591                         if (ob && (ob->mode & OB_MODE_SCULPT))
592                                 brush = paint_brush(&scene->toolsettings->sculpt->paint);
593                         else
594                                 brush = paint_brush(&scene->toolsettings->imapaint.paint);
595
596                         if (brush) {
597                                 snode->from = (ID *)brush;
598                                 tx = give_current_brush_texture(brush);
599                                 snode->id = &tx->id;
600                         }
601                 }
602         }
603         else {
604                 if (snode->nodetree && snode->nodetree->type == snode->treetype)
605                         snode->id = &snode->nodetree->id;
606                 else
607                         snode->id = NULL;
608         }
609
610         node_tree_from_ID(snode->id, &snode->nodetree, &snode->edittree, NULL);
611 }
612
613 static void snode_update(SpaceNode *snode, bNode *node)
614 {
615         bNode *gnode;
616         
617         if (node)
618                 nodeUpdate(snode->edittree, node);
619         
620         /* if inside group, tag entire group */
621         gnode = node_tree_get_editgroup(snode->nodetree);
622         if (gnode)
623                 nodeUpdateID(snode->nodetree, gnode->id);
624 }
625
626 void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
627 {
628         int was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE);
629
630         nodeSetActive(ntree, node);
631         
632         if (node->type != NODE_GROUP) {
633                 int was_output = (node->flag & NODE_DO_OUTPUT);
634                 
635                 /* tree specific activate calls */
636                 if (ntree->type == NTREE_SHADER) {
637                         /* when we select a material, active texture is cleared, for buttons */
638                         if (node->id && ELEM3(GS(node->id->name), ID_MA, ID_LA, ID_WO))
639                                 nodeClearActiveID(ntree, ID_TE);
640                         
641                         if (node->type == SH_NODE_OUTPUT) {
642                                 bNode *tnode;
643                                 
644                                 for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
645                                         if (tnode->type == SH_NODE_OUTPUT)
646                                                 tnode->flag &= ~NODE_DO_OUTPUT;
647                                 
648                                 node->flag |= NODE_DO_OUTPUT;
649                                 if (was_output == 0)
650                                         ED_node_generic_update(bmain, ntree, node);
651                         }
652
653                         /* if active texture changed, free glsl materials */
654                         if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
655                                 Material *ma;
656
657                                 for (ma = bmain->mat.first; ma; ma = ma->id.next)
658                                         if (ma->nodetree && ma->use_nodes && has_nodetree(ma->nodetree, ntree))
659                                                 GPU_material_free(ma);
660
661                                 WM_main_add_notifier(NC_IMAGE, NULL);
662                         }
663
664                         WM_main_add_notifier(NC_MATERIAL | ND_NODES, node->id);
665                 }
666                 else if (ntree->type == NTREE_COMPOSIT) {
667                         /* make active viewer, currently only 1 supported... */
668                         if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
669                                 bNode *tnode;
670                                 
671
672                                 for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
673                                         if (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
674                                                 tnode->flag &= ~NODE_DO_OUTPUT;
675                                 
676                                 node->flag |= NODE_DO_OUTPUT;
677                                 if (was_output == 0)
678                                         ED_node_generic_update(bmain, ntree, node);
679                                 
680                                 /* addnode() doesnt link this yet... */
681                                 node->id = (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
682                         }
683                         else if (node->type == CMP_NODE_R_LAYERS) {
684                                 Scene *scene;
685
686                                 for (scene = bmain->scene.first; scene; scene = scene->id.next) {
687                                         if (scene->nodetree && scene->use_nodes && has_nodetree(scene->nodetree, ntree)) {
688                                                 if (node->id == NULL || node->id == (ID *)scene) {
689                                                         scene->r.actlay = node->custom1;
690                                                 }
691                                         }
692                                 }
693                         }
694                         else if (node->type == CMP_NODE_COMPOSITE) {
695                                 if (was_output == 0) {
696                                         bNode *tnode;
697                                         
698                                         for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
699                                                 if (tnode->type == CMP_NODE_COMPOSITE)
700                                                         tnode->flag &= ~NODE_DO_OUTPUT;
701                                         
702                                         node->flag |= NODE_DO_OUTPUT;
703                                         ED_node_generic_update(bmain, ntree, node);
704                                 }
705                         }
706                 }
707                 else if (ntree->type == NTREE_TEXTURE) {
708                         // XXX
709 #if 0
710                         if (node->id)
711                                 ;  // XXX BIF_preview_changed(-1);
712                         // allqueue(REDRAWBUTSSHADING, 1);
713                         // allqueue(REDRAWIPO, 0);
714 #endif
715                 }
716         }
717 }
718
719 void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree))
720 {
721         /* XXX This does not work due to layout functions relying on node->block,
722          * which only exists during actual drawing. Can we rely on valid totr rects?
723          */
724         /* make sure nodes have correct bounding boxes after transform */
725         /* node_update_nodetree(C, ntree, 0.0f, 0.0f); */
726 }
727
728 /* ***************** generic operator functions for nodes ***************** */
729
730 #if 0 /* UNUSED */
731
732 static int edit_node_poll(bContext *C)
733 {
734         return ED_operator_node_active(C);
735 }
736
737 static void edit_node_properties(wmOperatorType *ot)
738 {
739         /* XXX could node be a context pointer? */
740         RNA_def_string(ot->srna, "node", "", MAX_NAME, "Node", "");
741         RNA_def_int(ot->srna, "socket", 0, 0, MAX_SOCKET, "Socket", "", 0, MAX_SOCKET);
742         RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Side", "");
743 }
744
745 static int edit_node_invoke_properties(bContext *C, wmOperator *op)
746 {
747         if (!RNA_struct_property_is_set(op->ptr, "node")) {
748                 bNode *node = CTX_data_pointer_get_type(C, "node", &RNA_Node).data;
749                 if (!node)
750                         return 0;
751                 else
752                         RNA_string_set(op->ptr, "node", node->name);
753         }
754         
755         if (!RNA_struct_property_is_set(op->ptr, "in_out"))
756                 RNA_enum_set(op->ptr, "in_out", SOCK_IN);
757         
758         if (!RNA_struct_property_is_set(op->ptr, "socket"))
759                 RNA_int_set(op->ptr, "socket", 0);
760         
761         return 1;
762 }
763
764 static void edit_node_properties_get(wmOperator *op, bNodeTree *ntree, bNode **rnode, bNodeSocket **rsock, int *rin_out)
765 {
766         bNode *node;
767         bNodeSocket *sock = NULL;
768         char nodename[MAX_NAME];
769         int sockindex;
770         int in_out;
771         
772         RNA_string_get(op->ptr, "node", nodename);
773         node = nodeFindNodebyName(ntree, nodename);
774         
775         in_out = RNA_enum_get(op->ptr, "in_out");
776         
777         sockindex = RNA_int_get(op->ptr, "socket");
778         switch (in_out) {
779                 case SOCK_IN:   sock = BLI_findlink(&node->inputs, sockindex);  break;
780                 case SOCK_OUT:  sock = BLI_findlink(&node->outputs, sockindex); break;
781         }
782         
783         if (rnode)
784                 *rnode = node;
785         if (rsock)
786                 *rsock = sock;
787         if (rin_out)
788                 *rin_out = in_out;
789 }
790 #endif
791
792 /* ***************** Edit Group operator ************* */
793
794 void snode_make_group_editable(SpaceNode *snode, bNode *gnode)
795 {
796         bNode *node;
797         
798         /* make sure nothing has group editing on */
799         for (node = snode->nodetree->nodes.first; node; node = node->next) {
800                 nodeGroupEditClear(node);
801
802                 /* while we're here, clear texture active */
803                 if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
804                         /* this is not 100% sure to be reliable, see comment on the flag */
805                         node->flag &= ~NODE_ACTIVE_TEXTURE;
806                 }
807         }
808         
809         if (gnode == NULL) {
810                 /* with NULL argument we do a toggle */
811                 if (snode->edittree == snode->nodetree)
812                         gnode = nodeGetActive(snode->nodetree);
813         }
814         
815         if (gnode) {
816                 snode->edittree = nodeGroupEditSet(gnode, 1);
817                 
818                 /* deselect all other nodes, so we can also do grabbing of entire subtree */
819                 for (node = snode->nodetree->nodes.first; node; node = node->next) {
820                         node_deselect(node);
821
822                         if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
823                                 /* this is not 100% sure to be reliable, see comment on the flag */
824                                 node->flag &= ~NODE_ACTIVE_TEXTURE;
825                         }
826                 }
827                 node_select(gnode);
828         }
829         else 
830                 snode->edittree = snode->nodetree;
831 }
832
833 static int node_group_edit_exec(bContext *C, wmOperator *UNUSED(op))
834 {
835         SpaceNode *snode = CTX_wm_space_node(C);
836
837         ED_preview_kill_jobs(C);
838
839         if (snode->nodetree == snode->edittree) {
840                 bNode *gnode = nodeGetActive(snode->edittree);
841                 snode_make_group_editable(snode, gnode);
842         }
843         else
844                 snode_make_group_editable(snode, NULL);
845
846         WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
847
848         return OPERATOR_FINISHED;
849 }
850
851 static int node_group_edit_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
852 {
853         SpaceNode *snode = CTX_wm_space_node(C);
854         bNode *gnode;
855         
856         /* XXX callback? */
857         if (snode->nodetree == snode->edittree) {
858                 gnode = nodeGetActive(snode->edittree);
859                 if (gnode && gnode->id && GS(gnode->id->name) == ID_NT && gnode->id->lib) {
860                         uiPupMenuOkee(C, op->type->idname, "Make group local?");
861                         return OPERATOR_CANCELLED;
862                 }
863         }
864
865         return node_group_edit_exec(C, op);
866 }
867
868 void NODE_OT_group_edit(wmOperatorType *ot)
869 {
870         /* identifiers */
871         ot->name = "Edit Group";
872         ot->description = "Edit node group";
873         ot->idname = "NODE_OT_group_edit";
874         
875         /* api callbacks */
876         ot->invoke = node_group_edit_invoke;
877         ot->exec = node_group_edit_exec;
878         ot->poll = ED_operator_node_active;
879         
880         /* flags */
881         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
882 }
883
884 /* ***************** Add Group Socket operator ************* */
885
886 static int node_group_socket_add_exec(bContext *C, wmOperator *op)
887 {
888         SpaceNode *snode = CTX_wm_space_node(C);
889         int in_out = -1;
890         char name[MAX_NAME] = "";
891         int type = SOCK_FLOAT;
892         bNodeTree *ngroup = snode->edittree;
893         /* bNodeSocket *sock; */ /* UNUSED */
894         
895         ED_preview_kill_jobs(C);
896         
897         if (RNA_struct_property_is_set(op->ptr, "name"))
898                 RNA_string_get(op->ptr, "name", name);
899         
900         if (RNA_struct_property_is_set(op->ptr, "type"))
901                 type = RNA_enum_get(op->ptr, "type");
902         
903         if (RNA_struct_property_is_set(op->ptr, "in_out"))
904                 in_out = RNA_enum_get(op->ptr, "in_out");
905         else
906                 return OPERATOR_CANCELLED;
907         
908         /* using placeholder subtype first */
909         /* sock = */ /* UNUSED */ node_group_add_socket(ngroup, name, type, in_out);
910         
911         ntreeUpdateTree(ngroup);
912         
913         snode_notify(C, snode);
914         
915         return OPERATOR_FINISHED;
916 }
917
918 void NODE_OT_group_socket_add(wmOperatorType *ot)
919 {
920         /* identifiers */
921         ot->name = "Add Group Socket";
922         ot->description = "Add node group socket";
923         ot->idname = "NODE_OT_group_socket_add";
924         
925         /* api callbacks */
926         ot->exec = node_group_socket_add_exec;
927         ot->poll = ED_operator_node_active;
928         
929         /* flags */
930         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
931         
932         RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
933         RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Group socket name");
934         RNA_def_enum(ot->srna, "type", node_socket_type_items, SOCK_FLOAT, "Type", "Type of the group socket");
935 }
936
937 /* ***************** Remove Group Socket operator ************* */
938
939 static int node_group_socket_remove_exec(bContext *C, wmOperator *op)
940 {
941         SpaceNode *snode = CTX_wm_space_node(C);
942         int index = -1;
943         int in_out = -1;
944         bNodeTree *ngroup = snode->edittree;
945         bNodeSocket *sock;
946         
947         ED_preview_kill_jobs(C);
948         
949         if (RNA_struct_property_is_set(op->ptr, "index"))
950                 index = RNA_int_get(op->ptr, "index");
951         else
952                 return OPERATOR_CANCELLED;
953         
954         if (RNA_struct_property_is_set(op->ptr, "in_out"))
955                 in_out = RNA_enum_get(op->ptr, "in_out");
956         else
957                 return OPERATOR_CANCELLED;
958         
959         sock = (bNodeSocket *)BLI_findlink(in_out == SOCK_IN ? &ngroup->inputs : &ngroup->outputs, index);
960         if (sock) {
961                 node_group_remove_socket(ngroup, sock, in_out);
962                 ntreeUpdateTree(ngroup);
963                 
964                 snode_notify(C, snode);
965         }
966         
967         return OPERATOR_FINISHED;
968 }
969
970 void NODE_OT_group_socket_remove(wmOperatorType *ot)
971 {
972         /* identifiers */
973         ot->name = "Remove Group Socket";
974         ot->description = "Remove a node group socket";
975         ot->idname = "NODE_OT_group_socket_remove";
976         
977         /* api callbacks */
978         ot->exec = node_group_socket_remove_exec;
979         ot->poll = ED_operator_node_active;
980         
981         /* flags */
982         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
983         
984         RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
985         RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
986 }
987
988 /* ***************** Move Group Socket Up operator ************* */
989
990 static int node_group_socket_move_up_exec(bContext *C, wmOperator *op)
991 {
992         SpaceNode *snode = CTX_wm_space_node(C);
993         int index = -1;
994         int in_out = -1;
995         bNodeTree *ngroup = snode->edittree;
996         bNodeSocket *sock, *prev;
997         
998         ED_preview_kill_jobs(C);
999         
1000         if (RNA_struct_property_is_set(op->ptr, "index"))
1001                 index = RNA_int_get(op->ptr, "index");
1002         else
1003                 return OPERATOR_CANCELLED;
1004         
1005         if (RNA_struct_property_is_set(op->ptr, "in_out"))
1006                 in_out = RNA_enum_get(op->ptr, "in_out");
1007         else
1008                 return OPERATOR_CANCELLED;
1009         
1010         /* swap */
1011         if (in_out == SOCK_IN) {
1012                 sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index);
1013                 prev = sock->prev;
1014                 /* can't move up the first socket */
1015                 if (!prev)
1016                         return OPERATOR_CANCELLED;
1017                 BLI_remlink(&ngroup->inputs, sock);
1018                 BLI_insertlinkbefore(&ngroup->inputs, prev, sock);
1019                 
1020                 ngroup->update |= NTREE_UPDATE_GROUP_IN;
1021         }
1022         else if (in_out == SOCK_OUT) {
1023                 sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index);
1024                 prev = sock->prev;
1025                 /* can't move up the first socket */
1026                 if (!prev)
1027                         return OPERATOR_CANCELLED;
1028                 BLI_remlink(&ngroup->outputs, sock);
1029                 BLI_insertlinkbefore(&ngroup->outputs, prev, sock);
1030                 
1031                 ngroup->update |= NTREE_UPDATE_GROUP_OUT;
1032         }
1033         ntreeUpdateTree(ngroup);
1034         
1035         snode_notify(C, snode);
1036         
1037         return OPERATOR_FINISHED;
1038 }
1039
1040 void NODE_OT_group_socket_move_up(wmOperatorType *ot)
1041 {
1042         /* identifiers */
1043         ot->name = "Move Group Socket Up";
1044         ot->description = "Move up node group socket";
1045         ot->idname = "NODE_OT_group_socket_move_up";
1046         
1047         /* api callbacks */
1048         ot->exec = node_group_socket_move_up_exec;
1049         ot->poll = ED_operator_node_active;
1050         
1051         /* flags */
1052         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1053         
1054         RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
1055         RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
1056 }
1057
1058 /* ***************** Move Group Socket Up operator ************* */
1059
1060 static int node_group_socket_move_down_exec(bContext *C, wmOperator *op)
1061 {
1062         SpaceNode *snode = CTX_wm_space_node(C);
1063         int index = -1;
1064         int in_out = -1;
1065         bNodeTree *ngroup = snode->edittree;
1066         bNodeSocket *sock, *next;
1067         
1068         ED_preview_kill_jobs(C);
1069         
1070         if (RNA_struct_property_is_set(op->ptr, "index"))
1071                 index = RNA_int_get(op->ptr, "index");
1072         else
1073                 return OPERATOR_CANCELLED;
1074         
1075         if (RNA_struct_property_is_set(op->ptr, "in_out"))
1076                 in_out = RNA_enum_get(op->ptr, "in_out");
1077         else
1078                 return OPERATOR_CANCELLED;
1079         
1080         /* swap */
1081         if (in_out == SOCK_IN) {
1082                 sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index);
1083                 next = sock->next;
1084                 /* can't move down the last socket */
1085                 if (!next)
1086                         return OPERATOR_CANCELLED;
1087                 BLI_remlink(&ngroup->inputs, sock);
1088                 BLI_insertlinkafter(&ngroup->inputs, next, sock);
1089                 
1090                 ngroup->update |= NTREE_UPDATE_GROUP_IN;
1091         }
1092         else if (in_out == SOCK_OUT) {
1093                 sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index);
1094                 next = sock->next;
1095                 /* can't move down the last socket */
1096                 if (!next)
1097                         return OPERATOR_CANCELLED;
1098                 BLI_remlink(&ngroup->outputs, sock);
1099                 BLI_insertlinkafter(&ngroup->outputs, next, sock);
1100                 
1101                 ngroup->update |= NTREE_UPDATE_GROUP_OUT;
1102         }
1103         ntreeUpdateTree(ngroup);
1104         
1105         snode_notify(C, snode);
1106         
1107         return OPERATOR_FINISHED;
1108 }
1109
1110 void NODE_OT_group_socket_move_down(wmOperatorType *ot)
1111 {
1112         /* identifiers */
1113         ot->name = "Move Group Socket Down";
1114         ot->description = "Move down node group socket";
1115         ot->idname = "NODE_OT_group_socket_move_down";
1116         
1117         /* api callbacks */
1118         ot->exec = node_group_socket_move_down_exec;
1119         ot->poll = ED_operator_node_active;
1120         
1121         /* flags */
1122         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1123         
1124         RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
1125         RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
1126 }
1127
1128 /* ******************** Ungroup operator ********************** */
1129
1130 /* returns 1 if its OK */
1131 static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
1132 {
1133         bNodeLink *link, *linkn;
1134         bNode *node, *nextn;
1135         bNodeTree *ngroup, *wgroup;
1136         ListBase anim_basepaths = {NULL, NULL};
1137         
1138         ngroup = (bNodeTree *)gnode->id;
1139         if (ngroup == NULL) return 0;
1140         
1141         /* clear new pointers, set in copytree */
1142         for (node = ntree->nodes.first; node; node = node->next)
1143                 node->new_node = NULL;
1144         
1145         /* wgroup is a temporary copy of the NodeTree we're merging in
1146          *      - all of wgroup's nodes are transferred across to their new home
1147          *      - ngroup (i.e. the source NodeTree) is left unscathed
1148          */
1149         wgroup = ntreeCopyTree(ngroup);
1150         
1151         /* add the nodes into the ntree */
1152         for (node = wgroup->nodes.first; node; node = nextn) {
1153                 nextn = node->next;
1154                 
1155                 /* keep track of this node's RNA "base" path (the part of the path identifying the node) 
1156                  * if the old nodetree has animation data which potentially covers this node
1157                  */
1158                 if (wgroup->adt) {
1159                         PointerRNA ptr;
1160                         char *path;
1161                         
1162                         RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr);
1163                         path = RNA_path_from_ID_to_struct(&ptr);
1164                         
1165                         if (path)
1166                                 BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
1167                 }
1168                 
1169                 /* migrate node */
1170                 BLI_remlink(&wgroup->nodes, node);
1171                 BLI_addtail(&ntree->nodes, node);
1172                 
1173                 /* ensure unique node name in the nodee tree */
1174                 nodeUniqueName(ntree, node);
1175                 
1176                 node->locx += gnode->locx;
1177                 node->locy += gnode->locy;
1178                 
1179                 node->flag |= NODE_SELECT;
1180         }
1181         
1182         /* restore external links to and from the gnode */
1183         for (link = ntree->links.first; link; link = link->next) {
1184                 if (link->fromnode == gnode) {
1185                         if (link->fromsock->groupsock) {
1186                                 bNodeSocket *gsock = link->fromsock->groupsock;
1187                                 if (gsock->link) {
1188                                         if (gsock->link->fromnode) {
1189                                                 /* NB: using the new internal copies here! the groupsock pointer still maps to the old tree */
1190                                                 link->fromnode = (gsock->link->fromnode ? gsock->link->fromnode->new_node : NULL);
1191                                                 link->fromsock = gsock->link->fromsock->new_sock;
1192                                         }
1193                                         else {
1194                                                 /* group output directly maps to group input */
1195                                                 bNodeSocket *insock = node_group_find_input(gnode, gsock->link->fromsock);
1196                                                 if (insock->link) {
1197                                                         link->fromnode = insock->link->fromnode;
1198                                                         link->fromsock = insock->link->fromsock;
1199                                                 }
1200                                         }
1201                                 }
1202                                 else {
1203                                         /* copy the default input value from the group socket default to the external socket */
1204                                         node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, gsock->type, gsock->default_value);
1205                                 }
1206                         }
1207                 }
1208         }
1209         /* remove internal output links, these are not used anymore */
1210         for (link = wgroup->links.first; link; link = linkn) {
1211                 linkn = link->next;
1212                 if (!link->tonode)
1213                         nodeRemLink(wgroup, link);
1214         }
1215         /* restore links from internal nodes */
1216         for (link = wgroup->links.first; link; link = linkn) {
1217                 linkn = link->next;
1218                 /* indicates link to group input */
1219                 if (!link->fromnode) {
1220                         /* NB: can't use find_group_node_input here,
1221                          * because gnode sockets still point to the old tree!
1222                          */
1223                         bNodeSocket *insock;
1224                         for (insock = gnode->inputs.first; insock; insock = insock->next)
1225                                 if (insock->groupsock->new_sock == link->fromsock)
1226                                         break;
1227                         if (insock->link) {
1228                                 link->fromnode = insock->link->fromnode;
1229                                 link->fromsock = insock->link->fromsock;
1230                         }
1231                         else {
1232                                 /* copy the default input value from the group node socket default to the internal socket */
1233                                 node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, insock->type, insock->default_value);
1234                                 nodeRemLink(wgroup, link);
1235                         }
1236                 }
1237         }
1238         
1239         /* add internal links to the ntree */
1240         for (link = wgroup->links.first; link; link = linkn) {
1241                 linkn = link->next;
1242                 BLI_remlink(&wgroup->links, link);
1243                 BLI_addtail(&ntree->links, link);
1244         }
1245         
1246         /* and copy across the animation,
1247          * note that the animation data's action can be NULL here */
1248         if (wgroup->adt) {
1249                 LinkData *ld, *ldn = NULL;
1250                 bAction *waction;
1251                 
1252                 /* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */
1253                 waction = wgroup->adt->action = BKE_action_copy(wgroup->adt->action);
1254                 
1255                 /* now perform the moving */
1256                 BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths);
1257                 
1258                 /* paths + their wrappers need to be freed */
1259                 for (ld = anim_basepaths.first; ld; ld = ldn) {
1260                         ldn = ld->next;
1261                         
1262                         MEM_freeN(ld->data);
1263                         BLI_freelinkN(&anim_basepaths, ld);
1264                 }
1265                 
1266                 /* free temp action too */
1267                 if (waction) {
1268                         BKE_libblock_free(&G.main->action, waction);
1269                 }
1270         }
1271         
1272         /* delete the group instance. this also removes old input links! */
1273         nodeFreeNode(ntree, gnode);
1274
1275         /* free the group tree (takes care of user count) */
1276         BKE_libblock_free(&G.main->nodetree, wgroup);
1277         
1278         ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
1279         
1280         return 1;
1281 }
1282
1283 static int node_group_ungroup_exec(bContext *C, wmOperator *op)
1284 {
1285         SpaceNode *snode = CTX_wm_space_node(C);
1286         bNode *gnode;
1287
1288         ED_preview_kill_jobs(C);
1289
1290         /* are we inside of a group? */
1291         gnode = node_tree_get_editgroup(snode->nodetree);
1292         if (gnode)
1293                 snode_make_group_editable(snode, NULL);
1294         
1295         gnode = nodeGetActive(snode->edittree);
1296         if (gnode == NULL)
1297                 return OPERATOR_CANCELLED;
1298         
1299         if (gnode->type != NODE_GROUP) {
1300                 BKE_report(op->reports, RPT_WARNING, "Not a group");
1301                 return OPERATOR_CANCELLED;
1302         }
1303         else if (node_group_ungroup(snode->nodetree, gnode)) {
1304                 ntreeUpdateTree(snode->nodetree);
1305         }
1306         else {
1307                 BKE_report(op->reports, RPT_WARNING, "Can't ungroup");
1308                 return OPERATOR_CANCELLED;
1309         }
1310
1311         snode_notify(C, snode);
1312         snode_dag_update(C, snode);
1313
1314         return OPERATOR_FINISHED;
1315 }
1316
1317 void NODE_OT_group_ungroup(wmOperatorType *ot)
1318 {
1319         /* identifiers */
1320         ot->name = "Ungroup";
1321         ot->description = "Ungroup selected nodes";
1322         ot->idname = "NODE_OT_group_ungroup";
1323         
1324         /* api callbacks */
1325         ot->exec = node_group_ungroup_exec;
1326         ot->poll = ED_operator_node_active;
1327         
1328         /* flags */
1329         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1330 }
1331
1332 /* ******************** Separate operator ********************** */
1333
1334 /* returns 1 if its OK */
1335 static int node_group_separate_selected(bNodeTree *ntree, bNode *gnode, int make_copy)
1336 {
1337         bNodeLink *link, *link_next;
1338         bNode *node, *node_next, *newnode;
1339         bNodeTree *ngroup;
1340         ListBase anim_basepaths = {NULL, NULL};
1341         
1342         ngroup = (bNodeTree *)gnode->id;
1343         if (ngroup == NULL) return 0;
1344         
1345         /* deselect all nodes in the target tree */
1346         for (node = ntree->nodes.first; node; node = node->next)
1347                 node_deselect(node);
1348         
1349         /* clear new pointers, set in nodeCopyNode */
1350         for (node = ngroup->nodes.first; node; node = node->next)
1351                 node->new_node = NULL;
1352         
1353         /* add selected nodes into the ntree */
1354         for (node = ngroup->nodes.first; node; node = node_next) {
1355                 node_next = node->next;
1356                 if (!(node->flag & NODE_SELECT))
1357                         continue;
1358                 
1359                 if (make_copy) {
1360                         /* make a copy */
1361                         newnode = nodeCopyNode(ngroup, node);
1362                 }
1363                 else {
1364                         /* use the existing node */
1365                         newnode = node;
1366                 }
1367                 
1368                 /* keep track of this node's RNA "base" path (the part of the path identifying the node) 
1369                  * if the old nodetree has animation data which potentially covers this node
1370                  */
1371                 if (ngroup->adt) {
1372                         PointerRNA ptr;
1373                         char *path;
1374                         
1375                         RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr);
1376                         path = RNA_path_from_ID_to_struct(&ptr);
1377                         
1378                         if (path)
1379                                 BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
1380                 }
1381                 
1382                 /* ensure valid parent pointers, detach if parent stays inside the group */
1383                 if (newnode->parent && !(newnode->parent->flag & NODE_SELECT))
1384                         nodeDetachNode(newnode);
1385                 
1386                 /* migrate node */
1387                 BLI_remlink(&ngroup->nodes, newnode);
1388                 BLI_addtail(&ntree->nodes, newnode);
1389                 
1390                 /* ensure unique node name in the node tree */
1391                 nodeUniqueName(ntree, newnode);
1392                 
1393                 newnode->locx += gnode->locx;
1394                 newnode->locy += gnode->locy;
1395         }
1396         
1397         /* add internal links to the ntree */
1398         for (link = ngroup->links.first; link; link = link_next) {
1399                 int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT));
1400                 int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT));
1401                 link_next = link->next;
1402                 
1403                 if (make_copy) {
1404                         /* make a copy of internal links */
1405                         if (fromselect && toselect)
1406                                 nodeAddLink(ntree, link->fromnode->new_node, link->fromsock->new_sock, link->tonode->new_node, link->tosock->new_sock);
1407                 }
1408                 else {
1409                         /* move valid links over, delete broken links */
1410                         if (fromselect && toselect) {
1411                                 BLI_remlink(&ngroup->links, link);
1412                                 BLI_addtail(&ntree->links, link);
1413                         }
1414                         else if (fromselect || toselect) {
1415                                 nodeRemLink(ngroup, link);
1416                         }
1417                 }
1418         }
1419         
1420         /* and copy across the animation,
1421          * note that the animation data's action can be NULL here */
1422         if (ngroup->adt) {
1423                 LinkData *ld, *ldn = NULL;
1424                 
1425                 /* now perform the moving */
1426                 BKE_animdata_separate_by_basepath(&ngroup->id, &ntree->id, &anim_basepaths);
1427                 
1428                 /* paths + their wrappers need to be freed */
1429                 for (ld = anim_basepaths.first; ld; ld = ldn) {
1430                         ldn = ld->next;
1431                         
1432                         MEM_freeN(ld->data);
1433                         BLI_freelinkN(&anim_basepaths, ld);
1434                 }
1435         }
1436         
1437         ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
1438         if (!make_copy)
1439                 ngroup->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
1440         
1441         return 1;
1442 }
1443
1444 typedef enum eNodeGroupSeparateType {
1445         NODE_GS_COPY,
1446         NODE_GS_MOVE
1447 } eNodeGroupSeparateType;
1448
1449 /* Operator Property */
1450 EnumPropertyItem node_group_separate_types[] = {
1451         {NODE_GS_COPY, "COPY", 0, "Copy", "Copy to parent node tree, keep group intact"},
1452         {NODE_GS_MOVE, "MOVE", 0, "Move", "Move to parent node tree, remove from group"},
1453         {0, NULL, 0, NULL, NULL}
1454 };
1455
1456 static int node_group_separate_exec(bContext *C, wmOperator *op)
1457 {
1458         SpaceNode *snode = CTX_wm_space_node(C);
1459         bNode *gnode;
1460         int type = RNA_enum_get(op->ptr, "type");
1461
1462         ED_preview_kill_jobs(C);
1463
1464         /* are we inside of a group? */
1465         gnode = node_tree_get_editgroup(snode->nodetree);
1466         if (!gnode) {
1467                 BKE_report(op->reports, RPT_WARNING, "Not inside node group");
1468                 return OPERATOR_CANCELLED;
1469         }
1470         
1471         switch (type) {
1472                 case NODE_GS_COPY:
1473                         if (!node_group_separate_selected(snode->nodetree, gnode, 1)) {
1474                                 BKE_report(op->reports, RPT_WARNING, "Can't separate nodes");
1475                                 return OPERATOR_CANCELLED;
1476                         }
1477                         break;
1478                 case NODE_GS_MOVE:
1479                         if (!node_group_separate_selected(snode->nodetree, gnode, 0)) {
1480                                 BKE_report(op->reports, RPT_WARNING, "Can't separate nodes");
1481                                 return OPERATOR_CANCELLED;
1482                         }
1483                         break;
1484         }
1485         
1486         /* switch to parent tree */
1487         snode_make_group_editable(snode, NULL);
1488         
1489         ntreeUpdateTree(snode->nodetree);
1490         
1491         snode_notify(C, snode);
1492         snode_dag_update(C, snode);
1493
1494         return OPERATOR_FINISHED;
1495 }
1496
1497 static int node_group_separate_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
1498 {
1499         uiPopupMenu *pup = uiPupMenuBegin(C, "Separate", ICON_NONE);
1500         uiLayout *layout = uiPupMenuLayout(pup);
1501         
1502         uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
1503         uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY);
1504         uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE);
1505         
1506         uiPupMenuEnd(C, pup);
1507         
1508         return OPERATOR_CANCELLED;
1509 }
1510
1511 void NODE_OT_group_separate(wmOperatorType *ot)
1512 {
1513         /* identifiers */
1514         ot->name = "Separate";
1515         ot->description = "Separate selected nodes from the node group";
1516         ot->idname = "NODE_OT_group_separate";
1517         
1518         /* api callbacks */
1519         ot->invoke = node_group_separate_invoke;
1520         ot->exec = node_group_separate_exec;
1521         ot->poll = ED_operator_node_active;
1522         
1523         /* flags */
1524         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1525         
1526         RNA_def_enum(ot->srna, "type", node_group_separate_types, NODE_GS_COPY, "Type", "");
1527 }
1528
1529 /* ************************** Node generic ************** */
1530
1531 /* is rct in visible part of node? */
1532 static bNode *visible_node(SpaceNode *snode, rctf *rct)
1533 {
1534         bNode *node;
1535         
1536         for (node = snode->edittree->nodes.last; node; node = node->prev) {
1537                 if (BLI_rctf_isect(&node->totr, rct, NULL))
1538                         break;
1539         }
1540         return node;
1541 }
1542
1543 /* **************************** */
1544
1545 typedef struct NodeViewMove {
1546         int mvalo[2];
1547         int xmin, ymin, xmax, ymax;
1548 } NodeViewMove;
1549
1550 static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
1551 {
1552         SpaceNode *snode = CTX_wm_space_node(C);
1553         ARegion *ar = CTX_wm_region(C);
1554         NodeViewMove *nvm = op->customdata;
1555
1556         switch (event->type) {
1557                 case MOUSEMOVE:
1558                         
1559                         snode->xof -= (nvm->mvalo[0] - event->mval[0]);
1560                         snode->yof -= (nvm->mvalo[1] - event->mval[1]);
1561                         nvm->mvalo[0] = event->mval[0];
1562                         nvm->mvalo[1] = event->mval[1];
1563                         
1564                         /* prevent dragging image outside of the window and losing it! */
1565                         CLAMP(snode->xof, nvm->xmin, nvm->xmax);
1566                         CLAMP(snode->yof, nvm->ymin, nvm->ymax);
1567                         
1568                         ED_region_tag_redraw(ar);
1569                         
1570                         break;
1571                         
1572                 case LEFTMOUSE:
1573                 case MIDDLEMOUSE:
1574                 case RIGHTMOUSE:
1575                         
1576                         MEM_freeN(nvm);
1577                         op->customdata = NULL;
1578                         
1579                         return OPERATOR_FINISHED;
1580         }
1581         
1582         return OPERATOR_RUNNING_MODAL;
1583 }
1584
1585 static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event)
1586 {
1587         SpaceNode *snode = CTX_wm_space_node(C);
1588         ARegion *ar = CTX_wm_region(C);
1589         NodeViewMove *nvm;
1590         Image *ima;
1591         ImBuf *ibuf;
1592         const float pad = 32.0f; /* better be bigger then scrollbars */
1593
1594         void *lock;
1595         
1596         ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
1597         ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
1598         
1599         if (ibuf == NULL) {
1600                 BKE_image_release_ibuf(ima, lock);
1601                 return OPERATOR_CANCELLED;
1602         }
1603
1604         nvm = MEM_callocN(sizeof(NodeViewMove), "NodeViewMove struct");
1605         op->customdata = nvm;
1606         nvm->mvalo[0] = event->mval[0];
1607         nvm->mvalo[1] = event->mval[1];
1608
1609         nvm->xmin = -(ar->winx / 2) - (ibuf->x * (0.5f * snode->zoom)) + pad;
1610         nvm->xmax =  (ar->winx / 2) + (ibuf->x * (0.5f * snode->zoom)) - pad;
1611         nvm->ymin = -(ar->winy / 2) - (ibuf->y * (0.5f * snode->zoom)) + pad;
1612         nvm->ymax =  (ar->winy / 2) + (ibuf->y * (0.5f * snode->zoom)) - pad;
1613
1614         BKE_image_release_ibuf(ima, lock);
1615         
1616         /* add modal handler */
1617         WM_event_add_modal_handler(C, op);
1618         
1619         return OPERATOR_RUNNING_MODAL;
1620 }
1621
1622 static int snode_bg_viewmove_cancel(bContext *UNUSED(C), wmOperator *op)
1623 {
1624         MEM_freeN(op->customdata);
1625         op->customdata = NULL;
1626
1627         return OPERATOR_CANCELLED;
1628 }
1629
1630 void NODE_OT_backimage_move(wmOperatorType *ot)
1631 {
1632         /* identifiers */
1633         ot->name = "Background Image Move";
1634         ot->description = "Move Node backdrop";
1635         ot->idname = "NODE_OT_backimage_move";
1636         
1637         /* api callbacks */
1638         ot->invoke = snode_bg_viewmove_invoke;
1639         ot->modal = snode_bg_viewmove_modal;
1640         ot->poll = composite_node_active;
1641         ot->cancel = snode_bg_viewmove_cancel;
1642         
1643         /* flags */
1644         ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
1645 }
1646
1647 static int backimage_zoom(bContext *C, wmOperator *op)
1648 {
1649         SpaceNode *snode = CTX_wm_space_node(C);
1650         ARegion *ar = CTX_wm_region(C);
1651         float fac = RNA_float_get(op->ptr, "factor");
1652
1653         snode->zoom *= fac;
1654         ED_region_tag_redraw(ar);
1655
1656         return OPERATOR_FINISHED;
1657 }
1658
1659
1660 void NODE_OT_backimage_zoom(wmOperatorType *ot)
1661 {
1662         
1663         /* identifiers */
1664         ot->name = "Background Image Zoom";
1665         ot->idname = "NODE_OT_backimage_zoom";
1666         ot->description = "Zoom in/out the background image";
1667         
1668         /* api callbacks */
1669         ot->exec = backimage_zoom;
1670         ot->poll = composite_node_active;
1671         
1672         /* flags */
1673         ot->flag = OPTYPE_BLOCKING;
1674
1675         /* internal */
1676         RNA_def_float(ot->srna, "factor", 1.2f, 0.0f, 10.0f, "Factor", "", 0.0f, 10.0f);
1677 }
1678
1679 /******************** sample backdrop operator ********************/
1680
1681 typedef struct ImageSampleInfo {
1682         ARegionType *art;
1683         void *draw_handle;
1684         int x, y;
1685         int channels;
1686         int color_manage;
1687
1688         unsigned char col[4];
1689         float colf[4];
1690
1691         int draw;
1692 } ImageSampleInfo;
1693
1694 static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
1695 {
1696         Scene *scene = CTX_data_scene(C);
1697         ImageSampleInfo *info = arg_info;
1698
1699         if (info->draw) {
1700                 ED_image_draw_info(ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels,
1701                                    info->x, info->y, info->col, info->colf,
1702                                    NULL, NULL /* zbuf - unused for nodes */
1703                                    );
1704         }
1705 }
1706
1707 static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
1708 {
1709         SpaceNode *snode = CTX_wm_space_node(C);
1710         ARegion *ar = CTX_wm_region(C);
1711         ImageSampleInfo *info = op->customdata;
1712         void *lock;
1713         Image *ima;
1714         ImBuf *ibuf;
1715         float fx, fy, bufx, bufy;
1716         
1717         ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
1718         ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
1719         if (!ibuf) {
1720                 info->draw = 0;
1721                 return;
1722         }
1723         
1724         if (!ibuf->rect) {
1725                 if (info->color_manage)
1726                         ibuf->profile = IB_PROFILE_LINEAR_RGB;
1727                 else
1728                         ibuf->profile = IB_PROFILE_NONE;
1729                 IMB_rect_from_float(ibuf);
1730         }
1731
1732         /* map the mouse coords to the backdrop image space */
1733         bufx = ibuf->x * snode->zoom;
1734         bufy = ibuf->y * snode->zoom;
1735         fx = (bufx > 0.0f ? ((float)event->mval[0] - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f);
1736         fy = (bufy > 0.0f ? ((float)event->mval[1] - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f);
1737
1738         if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
1739                 float *fp;
1740                 char *cp;
1741                 int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
1742
1743                 CLAMP(x, 0, ibuf->x - 1);
1744                 CLAMP(y, 0, ibuf->y - 1);
1745
1746                 info->x = x;
1747                 info->y = y;
1748                 info->draw = 1;
1749                 info->channels = ibuf->channels;
1750
1751                 if (ibuf->rect) {
1752                         cp = (char *)(ibuf->rect + y * ibuf->x + x);
1753
1754                         info->col[0] = cp[0];
1755                         info->col[1] = cp[1];
1756                         info->col[2] = cp[2];
1757                         info->col[3] = cp[3];
1758
1759                         info->colf[0] = (float)cp[0] / 255.0f;
1760                         info->colf[1] = (float)cp[1] / 255.0f;
1761                         info->colf[2] = (float)cp[2] / 255.0f;
1762                         info->colf[3] = (float)cp[3] / 255.0f;
1763                 }
1764                 if (ibuf->rect_float) {
1765                         fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
1766
1767                         info->colf[0] = fp[0];
1768                         info->colf[1] = fp[1];
1769                         info->colf[2] = fp[2];
1770                         info->colf[3] = fp[3];
1771                 }
1772
1773                 ED_node_sample_set(info->colf);
1774         }
1775         else {
1776                 info->draw = 0;
1777                 ED_node_sample_set(NULL);
1778         }
1779
1780         BKE_image_release_ibuf(ima, lock);
1781         
1782         ED_area_tag_redraw(CTX_wm_area(C));
1783 }
1784
1785 static void sample_exit(bContext *C, wmOperator *op)
1786 {
1787         ImageSampleInfo *info = op->customdata;
1788
1789         ED_node_sample_set(NULL);
1790         ED_region_draw_cb_exit(info->art, info->draw_handle);
1791         ED_area_tag_redraw(CTX_wm_area(C));
1792         MEM_freeN(info);
1793 }
1794
1795 static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
1796 {
1797         SpaceNode *snode = CTX_wm_space_node(C);
1798         ARegion *ar = CTX_wm_region(C);
1799         ImageSampleInfo *info;
1800
1801         if (snode->treetype != NTREE_COMPOSIT || !(snode->flag & SNODE_BACKDRAW))
1802                 return OPERATOR_CANCELLED;
1803         
1804         info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
1805         info->art = ar->type;
1806         info->draw_handle = ED_region_draw_cb_activate(ar->type, sample_draw, info, REGION_DRAW_POST_PIXEL);
1807         op->customdata = info;
1808
1809         sample_apply(C, op, event);
1810
1811         WM_event_add_modal_handler(C, op);
1812
1813         return OPERATOR_RUNNING_MODAL;
1814 }
1815
1816 static int sample_modal(bContext *C, wmOperator *op, wmEvent *event)
1817 {
1818         switch (event->type) {
1819                 case LEFTMOUSE:
1820                 case RIGHTMOUSE: // XXX hardcoded
1821                         sample_exit(C, op);
1822                         return OPERATOR_CANCELLED;
1823                 case MOUSEMOVE:
1824                         sample_apply(C, op, event);
1825                         break;
1826         }
1827
1828         return OPERATOR_RUNNING_MODAL;
1829 }
1830
1831 static int sample_cancel(bContext *C, wmOperator *op)
1832 {
1833         sample_exit(C, op);
1834         return OPERATOR_CANCELLED;
1835 }
1836
1837 void NODE_OT_backimage_sample(wmOperatorType *ot)
1838 {
1839         /* identifiers */
1840         ot->name = "Backimage Sample";
1841         ot->idname = "NODE_OT_backimage_sample";
1842         ot->description = "Use mouse to sample background image";
1843         
1844         /* api callbacks */
1845         ot->invoke = sample_invoke;
1846         ot->modal = sample_modal;
1847         ot->cancel = sample_cancel;
1848         ot->poll = ED_operator_node_active;
1849
1850         /* flags */
1851         ot->flag = OPTYPE_BLOCKING;
1852 }
1853
1854 /* ********************** size widget operator ******************** */
1855
1856 typedef struct NodeSizeWidget {
1857         float mxstart, mystart;
1858         float oldlocx, oldlocy;
1859         float oldoffsetx, oldoffsety;
1860         float oldwidth, oldheight;
1861         float oldminiwidth;
1862         int directions;
1863 } NodeSizeWidget;
1864
1865 static void node_resize_init(bContext *C, wmOperator *op, wmEvent *UNUSED(event), bNode *node, int dir)
1866 {
1867         SpaceNode *snode = CTX_wm_space_node(C);
1868         
1869         NodeSizeWidget *nsw = MEM_callocN(sizeof(NodeSizeWidget), "size widget op data");
1870         
1871         op->customdata = nsw;
1872         nsw->mxstart = snode->mx;
1873         nsw->mystart = snode->my;
1874         
1875         /* store old */
1876         nsw->oldlocx = node->locx;
1877         nsw->oldlocy = node->locy;
1878         nsw->oldoffsetx = node->offsetx;
1879         nsw->oldoffsety = node->offsety;
1880         nsw->oldwidth = node->width;
1881         nsw->oldheight = node->height;
1882         nsw->oldminiwidth = node->miniwidth;
1883         nsw->directions = dir;
1884         
1885         WM_cursor_modal(CTX_wm_window(C), node_get_resize_cursor(dir));
1886         /* add modal handler */
1887         WM_event_add_modal_handler(C, op);
1888 }
1889
1890 static void node_resize_exit(bContext *C, wmOperator *op, int UNUSED(cancel))
1891 {
1892         WM_cursor_restore(CTX_wm_window(C));
1893         
1894         MEM_freeN(op->customdata);
1895         op->customdata = NULL;
1896 }
1897
1898 static int node_resize_modal(bContext *C, wmOperator *op, wmEvent *event)
1899 {
1900         SpaceNode *snode = CTX_wm_space_node(C);
1901         ARegion *ar = CTX_wm_region(C);
1902         bNode *node = editnode_get_active(snode->edittree);
1903         NodeSizeWidget *nsw = op->customdata;
1904         float mx, my, dx, dy;
1905         
1906         switch (event->type) {
1907                 case MOUSEMOVE:
1908                         
1909                         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mx, &my);
1910                         dx = mx - nsw->mxstart;
1911                         dy = my - nsw->mystart;
1912                         
1913                         if (node) {
1914                                 if (node->flag & NODE_HIDDEN) {
1915                                         float widthmin = 0.0f;
1916                                         float widthmax = 100.0f;
1917                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
1918                                                 node->miniwidth = nsw->oldminiwidth + dx;
1919                                                 CLAMP(node->miniwidth, widthmin, widthmax);
1920                                         }
1921                                         if (nsw->directions & NODE_RESIZE_LEFT) {
1922                                                 float locmax = nsw->oldlocx + nsw->oldminiwidth;
1923                                                 
1924                                                 node->locx = nsw->oldlocx + dx;
1925                                                 CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
1926                                                 node->miniwidth = locmax - node->locx;
1927                                         }
1928                                 }
1929                                 else {
1930                                         float widthmin = UI_DPI_FAC * node->typeinfo->minwidth;
1931                                         float widthmax = UI_DPI_FAC * node->typeinfo->maxwidth;
1932                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
1933                                                 node->width = nsw->oldwidth + dx;
1934                                                 CLAMP(node->width, widthmin, widthmax);
1935                                         }
1936                                         if (nsw->directions & NODE_RESIZE_LEFT) {
1937                                                 float locmax = nsw->oldlocx + nsw->oldwidth;
1938                                                 
1939                                                 node->locx = nsw->oldlocx + dx;
1940                                                 CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
1941                                                 node->width = locmax - node->locx;
1942                                         }
1943                                 }
1944                         
1945                                 /* height works the other way round ... */
1946                                 {
1947                                         float heightmin = UI_DPI_FAC * node->typeinfo->minheight;
1948                                         float heightmax = UI_DPI_FAC * node->typeinfo->maxheight;
1949                                         if (nsw->directions & NODE_RESIZE_TOP) {
1950                                                 float locmin = nsw->oldlocy - nsw->oldheight;
1951                                                 
1952                                                 node->locy = nsw->oldlocy + dy;
1953                                                 CLAMP(node->locy, locmin + heightmin, locmin + heightmax);
1954                                                 node->height = node->locy - locmin;
1955                                         }
1956                                         if (nsw->directions & NODE_RESIZE_BOTTOM) {
1957                                                 node->height = nsw->oldheight - dy;
1958                                                 CLAMP(node->height, heightmin, heightmax);
1959                                         }
1960                                 }
1961                                 
1962                                 /* XXX make callback? */
1963                                 if (node->type == NODE_FRAME) {
1964                                         /* keep the offset symmetric around center point */
1965                                         if (nsw->directions & NODE_RESIZE_LEFT) {
1966                                                 node->locx = nsw->oldlocx + 0.5f * dx;
1967                                                 node->offsetx = nsw->oldoffsetx + 0.5f * dx;
1968                                         }
1969                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
1970                                                 node->locx = nsw->oldlocx + 0.5f * dx;
1971                                                 node->offsetx = nsw->oldoffsetx - 0.5f * dx;
1972                                         }
1973                                         if (nsw->directions & NODE_RESIZE_TOP) {
1974                                                 node->locy = nsw->oldlocy + 0.5f * dy;
1975                                                 node->offsety = nsw->oldoffsety + 0.5f * dy;
1976                                         }
1977                                         if (nsw->directions & NODE_RESIZE_BOTTOM) {
1978                                                 node->locy = nsw->oldlocy + 0.5f * dy;
1979                                                 node->offsety = nsw->oldoffsety - 0.5f * dy;
1980                                         }
1981                                 }
1982                         }
1983                                 
1984                         ED_region_tag_redraw(ar);
1985
1986                         break;
1987                         
1988                 case LEFTMOUSE:
1989                 case MIDDLEMOUSE:
1990                 case RIGHTMOUSE:
1991                         
1992                         node_resize_exit(C, op, 0);
1993                         ED_node_post_apply_transform(C, snode->edittree);
1994                         
1995                         return OPERATOR_FINISHED;
1996         }
1997         
1998         return OPERATOR_RUNNING_MODAL;
1999 }
2000
2001 static int node_resize_invoke(bContext *C, wmOperator *op, wmEvent *event)
2002 {
2003         SpaceNode *snode = CTX_wm_space_node(C);
2004         ARegion *ar = CTX_wm_region(C);
2005         bNode *node = editnode_get_active(snode->edittree);
2006         int dir;
2007         
2008         if (node) {
2009                 /* convert mouse coordinates to v2d space */
2010                 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
2011                                          &snode->mx, &snode->my);
2012                 dir = node->typeinfo->resize_area_func(node, snode->mx, snode->my);
2013                 if (dir != 0) {
2014                         node_resize_init(C, op, event, node, dir);
2015                         return OPERATOR_RUNNING_MODAL;
2016                 }
2017         }
2018         return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
2019 }
2020
2021 static int node_resize_cancel(bContext *C, wmOperator *op)
2022 {
2023         node_resize_exit(C, op, 1);
2024
2025         return OPERATOR_CANCELLED;
2026 }
2027
2028 void NODE_OT_resize(wmOperatorType *ot)
2029 {
2030         /* identifiers */
2031         ot->name = "Resize Node";
2032         ot->idname = "NODE_OT_resize";
2033         ot->description = "Resize a node";
2034         
2035         /* api callbacks */
2036         ot->invoke = node_resize_invoke;
2037         ot->modal = node_resize_modal;
2038         ot->poll = ED_operator_node_active;
2039         ot->cancel = node_resize_cancel;
2040         
2041         /* flags */
2042         ot->flag = OPTYPE_BLOCKING;
2043 }
2044
2045
2046 /* ********************** hidden sockets ******************** */
2047
2048 int node_has_hidden_sockets(bNode *node)
2049 {
2050         bNodeSocket *sock;
2051         
2052         for (sock = node->inputs.first; sock; sock = sock->next)
2053                 if (sock->flag & SOCK_HIDDEN)
2054                         return 1;
2055         for (sock = node->outputs.first; sock; sock = sock->next)
2056                 if (sock->flag & SOCK_HIDDEN)
2057                         return 1;
2058         return 0;
2059 }
2060
2061 void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
2062 {
2063         bNodeSocket *sock;
2064
2065         if (set == 0) {
2066                 for (sock = node->inputs.first; sock; sock = sock->next)
2067                         sock->flag &= ~SOCK_HIDDEN;
2068                 for (sock = node->outputs.first; sock; sock = sock->next)
2069                         sock->flag &= ~SOCK_HIDDEN;
2070         }
2071         else {
2072                 /* hide unused sockets */
2073                 for (sock = node->inputs.first; sock; sock = sock->next) {
2074                         if (sock->link == NULL)
2075                                 sock->flag |= SOCK_HIDDEN;
2076                 }
2077                 for (sock = node->outputs.first; sock; sock = sock->next) {
2078                         if (nodeCountSocketLinks(snode->edittree, sock) == 0)
2079                                 sock->flag |= SOCK_HIDDEN;
2080                 }
2081         }
2082 }
2083
2084 static int node_link_viewer(const bContext *C, bNode *tonode)
2085 {
2086         SpaceNode *snode = CTX_wm_space_node(C);
2087         bNode *node;
2088         bNodeLink *link;
2089         bNodeSocket *sock;
2090
2091         /* context check */
2092         if (tonode == NULL || tonode->outputs.first == NULL)
2093                 return OPERATOR_CANCELLED;
2094         if (ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
2095                 return OPERATOR_CANCELLED;
2096         
2097         /* get viewer */
2098         for (node = snode->edittree->nodes.first; node; node = node->next)
2099                 if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
2100                         if (node->flag & NODE_DO_OUTPUT)
2101                                 break;
2102         /* no viewer, we make one active */
2103         if (node == NULL) {
2104                 for (node = snode->edittree->nodes.first; node; node = node->next) {
2105                         if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
2106                                 node->flag |= NODE_DO_OUTPUT;
2107                                 break;
2108                         }
2109                 }
2110         }
2111         
2112         sock = NULL;
2113         
2114         /* try to find an already connected socket to cycle to the next */
2115         if (node) {
2116                 link = NULL;
2117                 for (link = snode->edittree->links.first; link; link = link->next)
2118                         if (link->tonode == node && link->fromnode == tonode)
2119                                 if (link->tosock == node->inputs.first)
2120                                         break;
2121                 if (link) {
2122                         /* unlink existing connection */
2123                         sock = link->fromsock;
2124                         nodeRemLink(snode->edittree, link);
2125                         
2126                         /* find a socket after the previously connected socket */
2127                         for (sock = sock->next; sock; sock = sock->next)
2128                                 if (!nodeSocketIsHidden(sock))
2129                                         break;
2130                 }
2131         }
2132         
2133         /* find a socket starting from the first socket */
2134         if (!sock) {
2135                 for (sock = tonode->outputs.first; sock; sock = sock->next)
2136                         if (!nodeSocketIsHidden(sock))
2137                                 break;
2138         }
2139         
2140         if (sock) {
2141                 /* add a new viewer if none exists yet */
2142                 if (!node) {
2143                         Main *bmain = CTX_data_main(C);
2144                         Scene *scene = CTX_data_scene(C);
2145                         bNodeTemplate ntemp;
2146                         
2147                         ntemp.type = CMP_NODE_VIEWER;
2148                         /* XXX location is a quick hack, just place it next to the linked socket */
2149                         node = node_add_node(snode, bmain, scene, &ntemp, sock->locx + 100, sock->locy);
2150                         if (!node)
2151                                 return OPERATOR_CANCELLED;
2152                         
2153                         link = NULL;
2154                 }
2155                 else {
2156                         /* get link to viewer */
2157                         for (link = snode->edittree->links.first; link; link = link->next)
2158                                 if (link->tonode == node && link->tosock == node->inputs.first)
2159                                         break;
2160                 }
2161                 
2162                 if (link == NULL) {
2163                         nodeAddLink(snode->edittree, tonode, sock, node, node->inputs.first);
2164                 }
2165                 else {
2166                         link->fromnode = tonode;
2167                         link->fromsock = sock;
2168                         /* make sure the dependency sorting is updated */
2169                         snode->edittree->update |= NTREE_UPDATE_LINKS;
2170                 }
2171                 ntreeUpdateTree(snode->edittree);
2172                 snode_update(snode, node);
2173         }
2174         
2175         return OPERATOR_FINISHED;
2176 }
2177
2178
2179 static int node_active_link_viewer(bContext *C, wmOperator *UNUSED(op))
2180 {
2181         SpaceNode *snode = CTX_wm_space_node(C);
2182         bNode *node;
2183         
2184         node = editnode_get_active(snode->edittree);
2185         
2186         if (!node)
2187                 return OPERATOR_CANCELLED;
2188
2189         ED_preview_kill_jobs(C);
2190
2191         if (node_link_viewer(C, node) == OPERATOR_CANCELLED)
2192                 return OPERATOR_CANCELLED;
2193
2194         snode_notify(C, snode);
2195
2196         return OPERATOR_FINISHED;
2197 }
2198
2199
2200
2201 void NODE_OT_link_viewer(wmOperatorType *ot)
2202 {
2203         /* identifiers */
2204         ot->name = "Link to Viewer Node";
2205         ot->description = "Link to viewer node";
2206         ot->idname = "NODE_OT_link_viewer";
2207         
2208         /* api callbacks */
2209         ot->exec = node_active_link_viewer;
2210         ot->poll = composite_node_active;
2211         
2212         /* flags */
2213         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2214 }
2215
2216
2217
2218 /* return 0, nothing done */
2219 static int UNUSED_FUNCTION(node_mouse_groupheader) (SpaceNode * snode)
2220 {
2221         bNode *gnode;
2222         float mx = 0, my = 0;
2223 // XXX  int mval[2];
2224         
2225         gnode = node_tree_get_editgroup(snode->nodetree);
2226         if (gnode == NULL) return 0;
2227         
2228 // XXX  getmouseco_areawin(mval);
2229 // XXX  areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
2230         
2231         /* click in header or outside? */
2232         if (BLI_in_rctf(&gnode->totr, mx, my) == 0) {
2233                 rctf rect = gnode->totr;
2234                 
2235                 rect.ymax += NODE_DY;
2236                 if (BLI_in_rctf(&rect, mx, my) == 0)
2237                         snode_make_group_editable(snode, NULL);  /* toggles, so exits editmode */
2238 //              else
2239 // XXX                  transform_nodes(snode->nodetree, 'g', "Move group");
2240                 
2241                 return 1;
2242         }
2243         return 0;
2244 }
2245
2246 /* checks snode->mouse position, and returns found node/socket */
2247 /* type is SOCK_IN and/or SOCK_OUT */
2248 int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, int in_out)
2249 {
2250         bNode *node;
2251         bNodeSocket *sock;
2252         rctf rect;
2253         
2254         *nodep = NULL;
2255         *sockp = NULL;
2256         
2257         /* check if we click in a socket */
2258         for (node = snode->edittree->nodes.first; node; node = node->next) {
2259                 
2260                 rect.xmin = snode->mx - (NODE_SOCKSIZE + 4);
2261                 rect.ymin = snode->my - (NODE_SOCKSIZE + 4);
2262                 rect.xmax = snode->mx + (NODE_SOCKSIZE + 4);
2263                 rect.ymax = snode->my + (NODE_SOCKSIZE + 4);
2264                 
2265                 if (!(node->flag & NODE_HIDDEN)) {
2266                         /* extra padding inside and out - allow dragging on the text areas too */
2267                         if (in_out == SOCK_IN) {
2268                                 rect.xmax += NODE_SOCKSIZE;
2269                                 rect.xmin -= NODE_SOCKSIZE * 4;
2270                         }
2271                         else if (in_out == SOCK_OUT) {
2272                                 rect.xmax += NODE_SOCKSIZE * 4;
2273                                 rect.xmin -= NODE_SOCKSIZE;
2274                         }
2275                 }
2276                 
2277                 if (in_out & SOCK_IN) {
2278                         for (sock = node->inputs.first; sock; sock = sock->next) {
2279                                 if (!nodeSocketIsHidden(sock)) {
2280                                         if (BLI_in_rctf(&rect, sock->locx, sock->locy)) {
2281                                                 if (node == visible_node(snode, &rect)) {
2282                                                         *nodep = node;
2283                                                         *sockp = sock;
2284                                                         return 1;
2285                                                 }
2286                                         }
2287                                 }
2288                         }
2289                 }
2290                 if (in_out & SOCK_OUT) {
2291                         for (sock = node->outputs.first; sock; sock = sock->next) {
2292                                 if (!nodeSocketIsHidden(sock)) {
2293                                         if (BLI_in_rctf(&rect, sock->locx, sock->locy)) {
2294                                                 if (node == visible_node(snode, &rect)) {
2295                                                         *nodep = node;
2296                                                         *sockp = sock;
2297                                                         return 1;
2298                                                 }
2299                                         }
2300                                 }
2301                         }
2302                 }
2303         }
2304         
2305         /* check group sockets
2306          * NB: using ngroup->outputs as input sockets and vice versa here!
2307          */
2308         if (in_out & SOCK_IN) {
2309                 for (sock = snode->edittree->outputs.first; sock; sock = sock->next) {
2310                         if (!nodeSocketIsHidden(sock)) {
2311                                 if (BLI_in_rctf(&rect, sock->locx, sock->locy)) {
2312                                         *nodep = NULL;   /* NULL node pointer indicates group socket */
2313                                         *sockp = sock;
2314                                         return 1;
2315                                 }
2316                         }
2317                 }
2318         }
2319         if (in_out & SOCK_OUT) {
2320                 for (sock = snode->edittree->inputs.first; sock; sock = sock->next) {
2321                         if (!nodeSocketIsHidden(sock)) {
2322                                 if (BLI_in_rctf(&rect, sock->locx, sock->locy)) {
2323                                         *nodep = NULL;   /* NULL node pointer indicates group socket */
2324                                         *sockp = sock;
2325                                         return 1;
2326                                 }
2327                         }
2328                 }
2329         }
2330         
2331         return 0;
2332 }
2333
2334 static int outside_group_rect(SpaceNode *snode)
2335 {
2336         bNode *gnode = node_tree_get_editgroup(snode->nodetree);
2337         if (gnode) {
2338                 return (snode->mx <  gnode->totr.xmin ||
2339                         snode->mx >= gnode->totr.xmax ||
2340                         snode->my <  gnode->totr.ymin ||
2341                         snode->my >= gnode->totr.ymax);
2342         }
2343         return 0;
2344 }
2345
2346 /* ****************** Add *********************** */
2347
2348
2349 typedef struct bNodeListItem {
2350         struct bNodeListItem *next, *prev;
2351         struct bNode *node;     
2352 } bNodeListItem;
2353
2354 static int sort_nodes_locx(void *a, void *b)
2355 {
2356         bNodeListItem *nli1 = (bNodeListItem *)a;
2357         bNodeListItem *nli2 = (bNodeListItem *)b;
2358         bNode *node1 = nli1->node;
2359         bNode *node2 = nli2->node;
2360         
2361         if (node1->locx > node2->locx)
2362                 return 1;
2363         else 
2364                 return 0;
2365 }
2366
2367 static int socket_is_available(bNodeTree *UNUSED(ntree), bNodeSocket *sock, int allow_used)
2368 {
2369         if (nodeSocketIsHidden(sock))
2370                 return 0;
2371         
2372         if (!allow_used && (sock->flag & SOCK_IN_USE))
2373                 return 0;
2374         
2375         return 1;
2376 }
2377
2378 static bNodeSocket *best_socket_output(bNodeTree *ntree, bNode *node, bNodeSocket *sock_target, int allow_multiple)
2379 {
2380         bNodeSocket *sock;
2381         
2382         /* first look for selected output */
2383         for (sock = node->outputs.first; sock; sock = sock->next) {
2384                 if (!socket_is_available(ntree, sock, allow_multiple))
2385                         continue;
2386                 
2387                 if (sock->flag & SELECT)
2388                         return sock;
2389         }
2390         
2391         /* try to find a socket with a matching name */
2392         for (sock = node->outputs.first; sock; sock = sock->next) {
2393                 if (!socket_is_available(ntree, sock, allow_multiple))
2394                         continue;
2395
2396                 /* check for same types */
2397                 if (sock->type == sock_target->type) {
2398                         if (strcmp(sock->name, sock_target->name) == 0)
2399                                 return sock;
2400                 }
2401         }
2402         
2403         /* otherwise settle for the first available socket of the right type */
2404         for (sock = node->outputs.first; sock; sock = sock->next) {
2405
2406                 if (!socket_is_available(ntree, sock, allow_multiple))
2407                         continue;
2408                 
2409                 /* check for same types */
2410                 if (sock->type == sock_target->type) {
2411                         return sock;
2412                 }
2413         }
2414         
2415         return NULL;
2416 }
2417
2418 /* this is a bit complicated, but designed to prioritize finding
2419  * sockets of higher types, such as image, first */
2420 static bNodeSocket *best_socket_input(bNodeTree *ntree, bNode *node, int num, int replace)
2421 {
2422         bNodeSocket *sock;
2423         int socktype, maxtype = 0;
2424         int a = 0;
2425         
2426         for (sock = node->inputs.first; sock; sock = sock->next) {
2427                 maxtype = MAX2(sock->type, maxtype);
2428         }
2429         
2430         /* find sockets of higher 'types' first (i.e. image) */
2431         for (socktype = maxtype; socktype >= 0; socktype--) {
2432                 for (sock = node->inputs.first; sock; sock = sock->next) {
2433                         
2434                         if (!socket_is_available(ntree, sock, replace)) {
2435                                 a++;
2436                                 continue;
2437                         }
2438                                 
2439                         if (sock->type == socktype) {
2440                                 /* increment to make sure we don't keep finding 
2441                                  * the same socket on every attempt running this function */
2442                                 a++;
2443                                 if (a > num)
2444                                         return sock;
2445                         }
2446                 }
2447         }
2448         
2449         return NULL;
2450 }
2451
2452 static int snode_autoconnect_input(SpaceNode *snode, bNode *node_fr, bNodeSocket *sock_fr, bNode *node_to, bNodeSocket *sock_to, int replace)
2453 {
2454         bNodeTree *ntree = snode->edittree;
2455         bNodeLink *link;
2456         
2457         /* then we can connect */
2458         if (replace)
2459                 nodeRemSocketLinks(ntree, sock_to);
2460         
2461         link = nodeAddLink(ntree, node_fr, sock_fr, node_to, sock_to);
2462         /* validate the new link */
2463         ntreeUpdateTree(ntree);
2464         if (!(link->flag & NODE_LINK_VALID)) {
2465                 nodeRemLink(ntree, link);
2466                 return 0;
2467         }
2468         
2469         snode_update(snode, node_to);
2470         return 1;
2471 }
2472
2473 void snode_autoconnect(SpaceNode *snode, int allow_multiple, int replace)
2474 {
2475         bNodeTree *ntree = snode->edittree;
2476         ListBase *nodelist = MEM_callocN(sizeof(ListBase), "items_list");
2477         bNodeListItem *nli;
2478         bNode *node;
2479         int i, numlinks = 0;
2480         
2481         for (node = ntree->nodes.first; node; node = node->next) {
2482                 if (node->flag & NODE_SELECT) {
2483                         nli = MEM_mallocN(sizeof(bNodeListItem), "temporary node list item");
2484                         nli->node = node;
2485                         BLI_addtail(nodelist, nli);
2486                 }
2487         }
2488         
2489         /* sort nodes left to right */
2490         BLI_sortlist(nodelist, sort_nodes_locx);
2491         
2492         for (nli = nodelist->first; nli; nli = nli->next) {
2493                 bNode *node_fr, *node_to;
2494                 bNodeSocket *sock_fr, *sock_to;
2495                 int has_selected_inputs = 0;
2496                 
2497                 if (nli->next == NULL) break;
2498                 
2499                 node_fr = nli->node;
2500                 node_to = nli->next->node;
2501                 
2502                 /* if there are selected sockets, connect those */
2503                 for (sock_to = node_to->inputs.first; sock_to; sock_to = sock_to->next) {
2504                         if (sock_to->flag & SELECT) {
2505                                 has_selected_inputs = 1;
2506                                 
2507                                 if (!socket_is_available(ntree, sock_to, replace))
2508                                         continue;
2509                                 
2510                                 /* check for an appropriate output socket to connect from */
2511                                 sock_fr = best_socket_output(ntree, node_fr, sock_to, allow_multiple);
2512                                 if (!sock_fr)
2513                                         continue;
2514         
2515                                 if (snode_autoconnect_input(snode, node_fr, sock_fr, node_to, sock_to, replace))
2516                                         ++numlinks;
2517                         }
2518                 }
2519                 
2520                 if (!has_selected_inputs) {
2521                         /* no selected inputs, connect by finding suitable match */
2522                         int num_inputs = BLI_countlist(&node_to->inputs);
2523                         
2524                         for (i = 0; i < num_inputs; i++) {
2525                                 
2526                                 /* find the best guess input socket */
2527                                 sock_to = best_socket_input(ntree, node_to, i, replace);
2528                                 if (!sock_to)
2529                                         continue;
2530                                 
2531                                 /* check for an appropriate output socket to connect from */
2532                                 sock_fr = best_socket_output(ntree, node_fr, sock_to, allow_multiple);
2533                                 if (!sock_fr)
2534                                         continue;
2535         
2536                                 if (snode_autoconnect_input(snode, node_fr, sock_fr, node_to, sock_to, replace)) {
2537                                         ++numlinks;
2538                                         break;
2539                                 }
2540                         }
2541                 }
2542         }
2543         
2544         if (numlinks > 0) {
2545                 ntreeUpdateTree(ntree);
2546         }
2547         
2548         BLI_freelistN(nodelist);
2549         MEM_freeN(nodelist);
2550 }
2551
2552 /* can be called from menus too, but they should do own undopush and redraws */
2553 bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene, bNodeTemplate *ntemp, float locx, float locy)
2554 {
2555         bNode *node = NULL, *gnode;
2556         
2557         node_deselect_all(snode);
2558         
2559         node = nodeAddNode(snode->edittree, ntemp);
2560         
2561         /* generics */
2562         if (node) {
2563                 node_select(node);
2564                 
2565                 gnode = node_tree_get_editgroup(snode->nodetree);
2566                 // arbitrary y offset of 60 so its visible
2567                 if (gnode) {
2568                         nodeFromView(gnode, locx, locy + 60.0f, &node->locx, &node->locy);
2569                 }
2570                 else {
2571                         node->locx = locx;
2572                         node->locy = locy + 60.0f;
2573                 }
2574
2575                 ntreeUpdateTree(snode->edittree);
2576                 ED_node_set_active(bmain, snode->edittree, node);
2577                 
2578                 if (snode->nodetree->type == NTREE_COMPOSIT) {
2579                         if (ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) {
2580                                 node->id = &scene->id;
2581                         }
2582                         else if (ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) {
2583                                 node->id = (ID *)scene->clip;
2584                         }
2585                         
2586                         ntreeCompositForceHidden(snode->edittree, scene);
2587                 }
2588                         
2589                 if (node->id)
2590                         id_us_plus(node->id);
2591                         
2592                 snode_update(snode, node);
2593         }
2594         
2595         if (snode->nodetree->type == NTREE_TEXTURE) {
2596                 ntreeTexCheckCyclics(snode->edittree);
2597         }
2598         
2599         return node;
2600 }
2601
2602 /* ****************** Duplicate *********************** */
2603
2604 static void node_duplicate_reparent_recursive(bNode *node)
2605 {
2606         bNode *parent;
2607         
2608         node->flag |= NODE_TEST;
2609         
2610         /* find first selected parent */
2611         for (parent = node->parent; parent; parent = parent->parent) {
2612                 if (parent->flag & SELECT) {
2613                         if (!(parent->flag & NODE_TEST))
2614                                 node_duplicate_reparent_recursive(parent);
2615                         break;
2616                 }
2617         }
2618         /* reparent node copy to parent copy */
2619         if (parent) {
2620                 nodeDetachNode(node->new_node);
2621                 nodeAttachNode(node->new_node, parent->new_node);
2622         }
2623 }
2624
2625 static int node_duplicate_exec(bContext *C, wmOperator *op)
2626 {
2627         SpaceNode *snode = CTX_wm_space_node(C);
2628         bNodeTree *ntree = snode->edittree;
2629         bNode *node, *newnode, *lastnode;
2630         bNodeLink *link, *newlink, *lastlink;
2631         int keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
2632         
2633         ED_preview_kill_jobs(C);
2634         
2635         lastnode = ntree->nodes.last;
2636         for (node = ntree->nodes.first; node; node = node->next) {
2637                 if (node->flag & SELECT) {
2638                         newnode = nodeCopyNode(ntree, node);
2639                         
2640                         if (newnode->id) {
2641                                 /* simple id user adjustment, node internal functions don't touch this
2642                                  * but operators and readfile.c do. */
2643                                 id_us_plus(newnode->id);
2644                                 /* to ensure redraws or rerenders happen */
2645                                 ED_node_changed_update(snode->id, newnode);
2646                         }
2647                 }
2648                 
2649                 /* make sure we don't copy new nodes again! */
2650                 if (node == lastnode)
2651                         break;
2652         }
2653         
2654         /* copy links between selected nodes
2655          * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
2656          */
2657         lastlink = ntree->links.last;
2658         for (link = ntree->links.first; link; link = link->next) {
2659                 /* This creates new links between copied nodes.
2660                  * If keep_inputs is set, also copies input links from unselected (when fromnode==NULL)!
2661                  */
2662                 if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
2663                     (keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT))))
2664                 {
2665                         newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
2666                         newlink->flag = link->flag;
2667                         newlink->tonode = link->tonode->new_node;
2668                         newlink->tosock = link->tosock->new_sock;
2669                         if (link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
2670                                 newlink->fromnode = link->fromnode->new_node;
2671                                 newlink->fromsock = link->fromsock->new_sock;
2672                         }
2673                         else {
2674                                 /* input node not copied, this keeps the original input linked */
2675                                 newlink->fromnode = link->fromnode;
2676                                 newlink->fromsock = link->fromsock;
2677                         }
2678                         
2679                         BLI_addtail(&ntree->links, newlink);
2680                 }
2681                 
2682                 /* make sure we don't copy new links again! */
2683                 if (link == lastlink)
2684                         break;
2685         }
2686         
2687         /* clear flags for recursive depth-first iteration */
2688         for (node = ntree->nodes.first; node; node = node->next)
2689                 node->flag &= ~NODE_TEST;
2690         /* reparent copied nodes */
2691         for (node = ntree->nodes.first; node; node = node->next) {
2692                 if ((node->flag & SELECT) && !(node->flag & NODE_TEST))
2693                         node_duplicate_reparent_recursive(node);
2694                 
2695                 /* only has to check old nodes */
2696                 if (node == lastnode)
2697                         break;
2698         }
2699         
2700         /* deselect old nodes, select the copies instead */
2701         for (node = ntree->nodes.first; node; node = node->next) {
2702                 if (node->flag & SELECT) {
2703                         /* has been set during copy above */
2704                         newnode = node->new_node;
2705                         
2706                         node_deselect(node);
2707                         node->flag &= ~NODE_ACTIVE;
2708                         node_select(newnode);
2709                 }
2710                 
2711                 /* make sure we don't copy new nodes again! */
2712                 if (node == lastnode)
2713                         break;
2714         }
2715         
2716         ntreeUpdateTree(snode->edittree);
2717         
2718         snode_notify(C, snode);
2719         snode_dag_update(C, snode);
2720
2721         return OPERATOR_FINISHED;
2722 }
2723
2724 void NODE_OT_duplicate(wmOperatorType *ot)
2725 {
2726         /* identifiers */
2727         ot->name = "Duplicate Nodes";
2728         ot->description = "Duplicate selected nodes";
2729         ot->idname = "NODE_OT_duplicate";
2730         
2731         /* api callbacks */
2732         ot->exec = node_duplicate_exec;
2733         ot->poll = ED_operator_node_active;
2734         
2735         /* flags */
2736         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2737         
2738         RNA_def_boolean(ot->srna, "keep_inputs", 0, "Keep Inputs", "Keep the input links to duplicated nodes");
2739 }
2740
2741 /* *************************** add link op ******************** */
2742
2743 static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeLink *link)
2744 {
2745         bNodeLink *tlink;
2746         bNodeSocket *sock;
2747         
2748         if (tsock && nodeCountSocketLinks(snode->edittree, link->tosock) > tsock->limit) {
2749                 
2750                 for (tlink = snode->edittree->links.first; tlink; tlink = tlink->next) {
2751                         if (link != tlink && tlink->tosock == link->tosock)
2752                                 break;
2753                 }
2754                 if (tlink) {
2755                         /* try to move the existing link to the next available socket */
2756                         if (tlink->tonode) {
2757                                 /* is there a free input socket with the target type? */
2758                                 for (sock = tlink->tonode->inputs.first; sock; sock = sock->next) {
2759                                         if (sock->type == tlink->tosock->type)
2760                                                 if (nodeCountSocketLinks(snode->edittree, sock) < sock->limit)
2761                                                         break;
2762                                 }
2763                                 if (sock) {
2764                                         tlink->tosock = sock;
2765                                         sock->flag &= ~SOCK_HIDDEN;
2766                                 }
2767                                 else {
2768                                         nodeRemLink(snode->edittree, tlink);
2769                                 }
2770                         }
2771                         else
2772                                 nodeRemLink(snode->edittree, tlink);
2773                         
2774                         snode->edittree->update |= NTREE_UPDATE_LINKS;
2775                 }
2776         }
2777 }
2778
2779 /* loop that adds a nodelink, called by function below  */
2780 /* in_out = starting socket */
2781 static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
2782 {
2783         SpaceNode *snode = CTX_wm_space_node(C);
2784         ARegion *ar = CTX_wm_region(C);
2785         bNodeLinkDrag *nldrag = op->customdata;
2786         bNodeTree *ntree = snode->edittree;
2787         bNode *tnode;
2788         bNodeSocket *tsock = NULL;
2789         bNodeLink *link;
2790         LinkData *linkdata;
2791         int in_out;
2792
2793         in_out = nldrag->in_out;
2794         
2795         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
2796                                  &snode->mx, &snode->my);
2797
2798         switch (event->type) {
2799                 case MOUSEMOVE:
2800                         
2801                         if (in_out == SOCK_OUT) {
2802                                 if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
2803                                         for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
2804                                                 link = linkdata->data;
2805                                                 
2806                                                 /* skip if this is already the target socket */
2807                                                 if (link->tosock == tsock)
2808                                                         continue;
2809                                                 /* skip if socket is on the same node as the fromsock */
2810                                                 if (tnode && link->fromnode == tnode)
2811                                                         continue;
2812                                                 
2813                                                 /* attach links to the socket */
2814                                                 link->tonode = tnode;
2815                                                 link->tosock = tsock;
2816                                                 /* add it to the node tree temporarily */
2817                                                 if (BLI_findindex(&ntree->links, link) < 0)
2818                                                         BLI_addtail(&ntree->links, link);
2819                                                 
2820                                                 ntree->update |= NTREE_UPDATE_LINKS;
2821                                         }
2822                                         ntreeUpdateTree(ntree);
2823                                 }
2824                                 else {
2825                                         int do_update = FALSE;
2826                                         for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
2827                                                 link = linkdata->data;
2828                                                 
2829                                                 if (link->tonode || link->tosock) {
2830                                                         BLI_remlink(&ntree->links, link);
2831                                                         link->prev = link->next = NULL;
2832                                                         link->tonode = NULL;
2833                                                         link->tosock = NULL;
2834                                                         
2835                                                         ntree->update |= NTREE_UPDATE_LINKS;
2836                                                         do_update = TRUE;
2837                                                 }
2838                                         }
2839                                         if (do_update) {
2840                                                 ntreeUpdateTree(ntree);
2841                                         }
2842                                 }
2843                         }
2844                         else {
2845                                 if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
2846                                         for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
2847                                                 link = linkdata->data;
2848                                                 
2849                                                 /* skip if this is already the target socket */
2850                                                 if (link->fromsock == tsock)
2851                                                         continue;
2852                                                 /* skip if socket is on the same node as the fromsock */
2853                                                 if (tnode && link->tonode == tnode)
2854                                                         continue;
2855                                                 
2856                                                 /* attach links to the socket */
2857                                                 link->fromnode = tnode;
2858                                                 link->fromsock = tsock;
2859                                                 /* add it to the node tree temporarily */
2860                                                 if (BLI_findindex(&ntree->links, link) < 0)
2861                                                         BLI_addtail(&ntree->links, link);
2862                                                 
2863                                                 ntree->update |= NTREE_UPDATE_LINKS;
2864                                         }
2865                                         ntreeUpdateTree(ntree);
2866                                 }
2867                                 else {
2868                                         int do_update = FALSE;
2869                                         for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
2870                                                 link = linkdata->data;
2871                                                 
2872                                                 if (link->fromnode || link->fromsock) {
2873                                                         BLI_remlink(&ntree->links, link);
2874                                                         link->prev = link->next = NULL;
2875                                                         link->fromnode = NULL;
2876                                                         link->fromsock = NULL;
2877                                                         
2878                                                         ntree->update |= NTREE_UPDATE_LINKS;
2879                                                         do_update = TRUE;
2880                                                 }
2881                                         }
2882                                         if (do_update) {
2883                                                 ntreeUpdateTree(ntree);
2884                                         }
2885                                 }
2886                         }
2887                         
2888                         ED_region_tag_redraw(ar);
2889                         break;
2890                         
2891                 case LEFTMOUSE:
2892                 case RIGHTMOUSE:
2893                 case MIDDLEMOUSE: {
2894                         for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
2895                                 link = linkdata->data;
2896                                 
2897                                 if (link->tosock && link->fromsock) {
2898                                         /* send changed events for original tonode and new */
2899                                         if (link->tonode)
2900                                                 snode_update(snode, link->tonode);
2901                                         
2902                                         /* we might need to remove a link */
2903                                         if (in_out == SOCK_OUT)
2904                                                 node_remove_extra_links(snode, link->tosock, link);
2905                                         
2906                                         /* when linking to group outputs, update the socket type */
2907                                         /* XXX this should all be part of a generic update system */
2908                                         if (!link->tonode) {
2909                                                 if (link->tosock->type != link->fromsock->type)
2910                                                         nodeSocketSetType(link->tosock, link->fromsock->type);
2911                                         }
2912                                 }
2913                                 else if (outside_group_rect(snode) && (link->tonode || link->fromnode)) {
2914                                         /* automatically add new group socket */
2915                                         if (link->tonode && link->tosock) {
2916                                                 link->fromsock = node_group_expose_socket(ntree, link->tosock, SOCK_IN);
2917                                                 link->fromnode = NULL;
2918                                                 if (BLI_findindex(&ntree->links, link) < 0)
2919                                                         BLI_addtail(&ntree->links, link);
2920                                                 
2921                                                 ntree->update |= NTREE_UPDATE_GROUP_IN | NTREE_UPDATE_LINKS;
2922                                         }
2923                                         else if (link->fromnode && link->fromsock) {
2924                                                 link->tosock = node_group_expose_socket(ntree, link->fromsock, SOCK_OUT);
2925                                                 link->tonode = NULL;
2926                                                 if (BLI_findindex(&ntree->links, link) < 0)
2927                                                         BLI_addtail(&ntree->links, link);
2928                                                 
2929                                                 ntree->update |= NTREE_UPDATE_GROUP_OUT | NTREE_UPDATE_LINKS;
2930                                         }
2931                                 }
2932                                 else
2933                                         nodeRemLink(ntree, link);
2934                         }
2935                         
2936                         ntreeUpdateTree(ntree);
2937                         snode_notify(C, snode);
2938                         snode_dag_update(C, snode);
2939                         
2940                         BLI_remlink(&snode->linkdrag, nldrag);
2941                         /* links->data pointers are either held by the tree or freed already */
2942                         BLI_freelistN(&nldrag->links);
2943                         MEM_freeN(nldrag);
2944                         
2945                         return OPERATOR_FINISHED;
2946                 }
2947         }
2948         
2949         return OPERATOR_RUNNING_MODAL;
2950 }
2951
2952 /* return 1 when socket clicked */
2953 static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
2954 {
2955         bNode *node;
2956         bNodeSocket *sock;
2957         bNodeLink *link, *link_next, *oplink;
2958         bNodeLinkDrag *nldrag = NULL;
2959         LinkData *linkdata;
2960         int num_links;
2961         
2962         /* output indicated? */
2963         if (node_find_indicated_socket(snode, &node, &sock, SOCK_OUT)) {
2964                 nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
2965                 
2966                 num_links = nodeCountSocketLinks(snode->edittree, sock);
2967                 if (num_links > 0 && (num_links >= sock->limit || detach)) {
2968                         /* dragged links are fixed on input side */
2969                         nldrag->in_out = SOCK_IN;
2970                         /* detach current links and store them in the operator data */
2971                         for (link = snode->edittree->links.first; link; link = link_next) {
2972                                 link_next = link->next;
2973                                 if (link->fromsock == sock) {
2974                                         linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
2975                                         linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
2976                                         *oplink = *link;
2977                                         oplink->next = oplink->prev = NULL;
2978                                         BLI_addtail(&nldrag->links, linkdata);
2979                                         nodeRemLink(snode->edittree, link);
2980                                 }
2981                         }
2982                 }
2983                 else {
2984                         /* dragged links are fixed on output side */
2985                         nldrag->in_out = SOCK_OUT;
2986                         /* create a new link */
2987                         linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
2988                         linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
2989                         oplink->fromnode = node;
2990                         oplink->fromsock = sock;
2991                         BLI_addtail(&nldrag->links, linkdata);
2992                 }
2993         }
2994         /* or an input? */
2995         else if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN)) {
2996                 nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
2997                 
2998                 num_links = nodeCountSocketLinks(snode->edittree, sock);
2999                 if (num_links > 0 && (num_links >= sock->limit || detach)) {
3000                         /* dragged links are fixed on output side */
3001                         nldrag->in_out = SOCK_OUT;
3002                         /* detach current links and store them in the operator data */
3003                         for (link = snode->edittree->links.first; link; link = link_next) {
3004                                 link_next = link->next;
3005                                 if (link->tosock == sock) {
3006                                         linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
3007                                         linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
3008                                         *oplink = *link;
3009                                         oplink->next = oplink->prev = NULL;
3010                                         BLI_addtail(&nldrag->links, linkdata);
3011                                         nodeRemLink(snode->edittree, link);
3012                                         
3013                                         /* send changed event to original link->tonode */
3014                                         if (node)
3015                                                 snode_update(snode, node);
3016                                 }
3017                         }
3018                 }
3019                 else {
3020                         /* dragged links are fixed on input side */
3021                         nldrag->in_out = SOCK_IN;
3022                         /* create a new link */
3023                         linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
3024                         linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
3025                         oplink->tonode = node;
3026                         oplink->tosock = sock;
3027                         BLI_addtail(&nldrag->links, linkdata);
3028                 }
3029         }
3030         
3031         return nldrag;
3032 }
3033