Merging r47740 through r47782 from trunk into soc-2011-tomato
[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         if (gnode==NULL) {
803                 /* with NULL argument we do a toggle */
804                 if (snode->edittree==snode->nodetree)
805                         gnode= nodeGetActive(snode->nodetree);
806         }
807         
808         if (gnode) {
809                 snode->edittree = nodeGroupEditSet(gnode, 1);
810                 
811                 /* deselect all other nodes, so we can also do grabbing of entire subtree */
812                 for (node= snode->nodetree->nodes.first; node; node= node->next)
813                         node_deselect(node);
814                 node_select(gnode);
815         }
816         else 
817                 snode->edittree= snode->nodetree;
818 }
819
820 static int node_group_edit_exec(bContext *C, wmOperator *UNUSED(op))
821 {
822         SpaceNode *snode = CTX_wm_space_node(C);
823
824         ED_preview_kill_jobs(C);
825
826         if (snode->nodetree==snode->edittree) {
827                 bNode *gnode = nodeGetActive(snode->edittree);
828                 snode_make_group_editable(snode, gnode);
829         }
830         else
831                 snode_make_group_editable(snode, NULL);
832
833         WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL);
834
835         return OPERATOR_FINISHED;
836 }
837
838 static int node_group_edit_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
839 {
840         SpaceNode *snode = CTX_wm_space_node(C);
841         bNode *gnode;
842         
843         /* XXX callback? */
844         if (snode->nodetree==snode->edittree) {
845                 gnode = nodeGetActive(snode->edittree);
846                 if (gnode && gnode->id && GS(gnode->id->name)==ID_NT && gnode->id->lib) {
847                         uiPupMenuOkee(C, op->type->idname, "Make group local?");
848                         return OPERATOR_CANCELLED;
849                 }
850         }
851
852         return node_group_edit_exec(C, op);
853 }
854
855 void NODE_OT_group_edit(wmOperatorType *ot)
856 {
857         /* identifiers */
858         ot->name = "Edit Group";
859         ot->description = "Edit node group";
860         ot->idname = "NODE_OT_group_edit";
861         
862         /* api callbacks */
863         ot->invoke = node_group_edit_invoke;
864         ot->exec = node_group_edit_exec;
865         ot->poll = ED_operator_node_active;
866         
867         /* flags */
868         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
869 }
870
871 /* ***************** Add Group Socket operator ************* */
872
873 static int node_group_socket_add_exec(bContext *C, wmOperator *op)
874 {
875         SpaceNode *snode = CTX_wm_space_node(C);
876         int in_out= -1;
877         char name[MAX_NAME]= "";
878         int type= SOCK_FLOAT;
879         bNodeTree *ngroup= snode->edittree;
880         /* bNodeSocket *sock; */ /* UNUSED */
881         
882         ED_preview_kill_jobs(C);
883         
884         if (RNA_struct_property_is_set(op->ptr, "name"))
885                 RNA_string_get(op->ptr, "name", name);
886         
887         if (RNA_struct_property_is_set(op->ptr, "type"))
888                 type = RNA_enum_get(op->ptr, "type");
889         
890         if (RNA_struct_property_is_set(op->ptr, "in_out"))
891                 in_out = RNA_enum_get(op->ptr, "in_out");
892         else
893                 return OPERATOR_CANCELLED;
894         
895         /* using placeholder subtype first */
896         /* sock = */ /* UNUSED */ node_group_add_socket(ngroup, name, type, in_out);
897         
898         ntreeUpdateTree(ngroup);
899         
900         snode_notify(C, snode);
901         
902         return OPERATOR_FINISHED;
903 }
904
905 void NODE_OT_group_socket_add(wmOperatorType *ot)
906 {
907         /* identifiers */
908         ot->name = "Add Group Socket";
909         ot->description = "Add node group socket";
910         ot->idname = "NODE_OT_group_socket_add";
911         
912         /* api callbacks */
913         ot->exec = node_group_socket_add_exec;
914         ot->poll = ED_operator_node_active;
915         
916         /* flags */
917         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
918         
919         RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
920         RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Group socket name");
921         RNA_def_enum(ot->srna, "type", node_socket_type_items, SOCK_FLOAT, "Type", "Type of the group socket");
922 }
923
924 /* ***************** Remove Group Socket operator ************* */
925
926 static int node_group_socket_remove_exec(bContext *C, wmOperator *op)
927 {
928         SpaceNode *snode = CTX_wm_space_node(C);
929         int index= -1;
930         int in_out= -1;
931         bNodeTree *ngroup= snode->edittree;
932         bNodeSocket *sock;
933         
934         ED_preview_kill_jobs(C);
935         
936         if (RNA_struct_property_is_set(op->ptr, "index"))
937                 index = RNA_int_get(op->ptr, "index");
938         else
939                 return OPERATOR_CANCELLED;
940         
941         if (RNA_struct_property_is_set(op->ptr, "in_out"))
942                 in_out = RNA_enum_get(op->ptr, "in_out");
943         else
944                 return OPERATOR_CANCELLED;
945         
946         sock = (bNodeSocket*)BLI_findlink(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, index);
947         if (sock) {
948                 node_group_remove_socket(ngroup, sock, in_out);
949                 ntreeUpdateTree(ngroup);
950                 
951                 snode_notify(C, snode);
952         }
953         
954         return OPERATOR_FINISHED;
955 }
956
957 void NODE_OT_group_socket_remove(wmOperatorType *ot)
958 {
959         /* identifiers */
960         ot->name = "Remove Group Socket";
961         ot->description = "Remove a node group socket";
962         ot->idname = "NODE_OT_group_socket_remove";
963         
964         /* api callbacks */
965         ot->exec = node_group_socket_remove_exec;
966         ot->poll = ED_operator_node_active;
967         
968         /* flags */
969         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
970         
971         RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
972         RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
973 }
974
975 /* ***************** Move Group Socket Up operator ************* */
976
977 static int node_group_socket_move_up_exec(bContext *C, wmOperator *op)
978 {
979         SpaceNode *snode = CTX_wm_space_node(C);
980         int index= -1;
981         int in_out= -1;
982         bNodeTree *ngroup= snode->edittree;
983         bNodeSocket *sock, *prev;
984         
985         ED_preview_kill_jobs(C);
986         
987         if (RNA_struct_property_is_set(op->ptr, "index"))
988                 index = RNA_int_get(op->ptr, "index");
989         else
990                 return OPERATOR_CANCELLED;
991         
992         if (RNA_struct_property_is_set(op->ptr, "in_out"))
993                 in_out = RNA_enum_get(op->ptr, "in_out");
994         else
995                 return OPERATOR_CANCELLED;
996         
997         /* swap */
998         if (in_out==SOCK_IN) {
999                 sock = (bNodeSocket*)BLI_findlink(&ngroup->inputs, index);
1000                 prev = sock->prev;
1001                 /* can't move up the first socket */
1002                 if (!prev)
1003                         return OPERATOR_CANCELLED;
1004                 BLI_remlink(&ngroup->inputs, sock);
1005                 BLI_insertlinkbefore(&ngroup->inputs, prev, sock);
1006                 
1007                 ngroup->update |= NTREE_UPDATE_GROUP_IN;
1008         }
1009         else if (in_out==SOCK_OUT) {
1010                 sock = (bNodeSocket*)BLI_findlink(&ngroup->outputs, index);
1011                 prev = sock->prev;
1012                 /* can't move up the first socket */
1013                 if (!prev)
1014                         return OPERATOR_CANCELLED;
1015                 BLI_remlink(&ngroup->outputs, sock);
1016                 BLI_insertlinkbefore(&ngroup->outputs, prev, sock);
1017                 
1018                 ngroup->update |= NTREE_UPDATE_GROUP_OUT;
1019         }
1020         ntreeUpdateTree(ngroup);
1021         
1022         snode_notify(C, snode);
1023         
1024         return OPERATOR_FINISHED;
1025 }
1026
1027 void NODE_OT_group_socket_move_up(wmOperatorType *ot)
1028 {
1029         /* identifiers */
1030         ot->name = "Move Group Socket Up";
1031         ot->description = "Move up node group socket";
1032         ot->idname = "NODE_OT_group_socket_move_up";
1033         
1034         /* api callbacks */
1035         ot->exec = node_group_socket_move_up_exec;
1036         ot->poll = ED_operator_node_active;
1037         
1038         /* flags */
1039         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
1040         
1041         RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
1042         RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
1043 }
1044
1045 /* ***************** Move Group Socket Up operator ************* */
1046
1047 static int node_group_socket_move_down_exec(bContext *C, wmOperator *op)
1048 {
1049         SpaceNode *snode = CTX_wm_space_node(C);
1050         int index= -1;
1051         int in_out= -1;
1052         bNodeTree *ngroup= snode->edittree;
1053         bNodeSocket *sock, *next;
1054         
1055         ED_preview_kill_jobs(C);
1056         
1057         if (RNA_struct_property_is_set(op->ptr, "index"))
1058                 index = RNA_int_get(op->ptr, "index");
1059         else
1060                 return OPERATOR_CANCELLED;
1061         
1062         if (RNA_struct_property_is_set(op->ptr, "in_out"))
1063                 in_out = RNA_enum_get(op->ptr, "in_out");
1064         else
1065                 return OPERATOR_CANCELLED;
1066         
1067         /* swap */
1068         if (in_out==SOCK_IN) {
1069                 sock = (bNodeSocket*)BLI_findlink(&ngroup->inputs, index);
1070                 next = sock->next;
1071                 /* can't move down the last socket */
1072                 if (!next)
1073                         return OPERATOR_CANCELLED;
1074                 BLI_remlink(&ngroup->inputs, sock);
1075                 BLI_insertlinkafter(&ngroup->inputs, next, sock);
1076                 
1077                 ngroup->update |= NTREE_UPDATE_GROUP_IN;
1078         }
1079         else if (in_out==SOCK_OUT) {
1080                 sock = (bNodeSocket*)BLI_findlink(&ngroup->outputs, index);
1081                 next = sock->next;
1082                 /* can't move down the last socket */
1083                 if (!next)
1084                         return OPERATOR_CANCELLED;
1085                 BLI_remlink(&ngroup->outputs, sock);
1086                 BLI_insertlinkafter(&ngroup->outputs, next, sock);
1087                 
1088                 ngroup->update |= NTREE_UPDATE_GROUP_OUT;
1089         }
1090         ntreeUpdateTree(ngroup);
1091         
1092         snode_notify(C, snode);
1093         
1094         return OPERATOR_FINISHED;
1095 }
1096
1097 void NODE_OT_group_socket_move_down(wmOperatorType *ot)
1098 {
1099         /* identifiers */
1100         ot->name = "Move Group Socket Down";
1101         ot->description = "Move down node group socket";
1102         ot->idname = "NODE_OT_group_socket_move_down";
1103         
1104         /* api callbacks */
1105         ot->exec = node_group_socket_move_down_exec;
1106         ot->poll = ED_operator_node_active;
1107         
1108         /* flags */
1109         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
1110         
1111         RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
1112         RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
1113 }
1114
1115 /* ******************** Ungroup operator ********************** */
1116
1117 /* returns 1 if its OK */
1118 static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
1119 {
1120         bNodeLink *link, *linkn;
1121         bNode *node, *nextn;
1122         bNodeTree *ngroup, *wgroup;
1123         ListBase anim_basepaths = {NULL, NULL};
1124         
1125         ngroup= (bNodeTree *)gnode->id;
1126         if (ngroup==NULL) return 0;
1127         
1128         /* clear new pointers, set in copytree */
1129         for (node= ntree->nodes.first; node; node= node->next)
1130                 node->new_node= NULL;
1131         
1132         /* wgroup is a temporary copy of the NodeTree we're merging in
1133          *      - all of wgroup's nodes are transferred across to their new home
1134          *      - ngroup (i.e. the source NodeTree) is left unscathed
1135          */
1136         wgroup= ntreeCopyTree(ngroup);
1137         
1138         /* add the nodes into the ntree */
1139         for (node= wgroup->nodes.first; node; node= nextn) {
1140                 nextn= node->next;
1141                 
1142                 /* keep track of this node's RNA "base" path (the part of the path identifying the node) 
1143                  * if the old nodetree has animation data which potentially covers this node
1144                  */
1145                 if (wgroup->adt) {
1146                         PointerRNA ptr;
1147                         char *path;
1148                         
1149                         RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr);
1150                         path = RNA_path_from_ID_to_struct(&ptr);
1151                         
1152                         if (path)
1153                                 BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
1154                 }
1155                 
1156                 /* migrate node */
1157                 BLI_remlink(&wgroup->nodes, node);
1158                 BLI_addtail(&ntree->nodes, node);
1159                 
1160                 node->locx += gnode->locx;
1161                 node->locy += gnode->locy;
1162                 
1163                 node->flag |= NODE_SELECT;
1164         }
1165         
1166         /* restore external links to and from the gnode */
1167         for (link= ntree->links.first; link; link= link->next) {
1168                 if (link->fromnode==gnode) {
1169                         if (link->fromsock->groupsock) {
1170                                 bNodeSocket *gsock= link->fromsock->groupsock;
1171                                 if (gsock->link) {
1172                                         if (gsock->link->fromnode) {
1173                                                 /* NB: using the new internal copies here! the groupsock pointer still maps to the old tree */
1174                                                 link->fromnode = (gsock->link->fromnode ? gsock->link->fromnode->new_node : NULL);
1175                                                 link->fromsock = gsock->link->fromsock->new_sock;
1176                                         }
1177                                         else {
1178                                                 /* group output directly maps to group input */
1179                                                 bNodeSocket *insock= node_group_find_input(gnode, gsock->link->fromsock);
1180                                                 if (insock->link) {
1181                                                         link->fromnode = insock->link->fromnode;
1182                                                         link->fromsock = insock->link->fromsock;
1183                                                 }
1184                                         }
1185                                 }
1186                                 else {
1187                                         /* copy the default input value from the group socket default to the external socket */
1188                                         node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, gsock->type, gsock->default_value);
1189                                 }
1190                         }
1191                 }
1192         }
1193         /* remove internal output links, these are not used anymore */
1194         for (link=wgroup->links.first; link; link= linkn) {
1195                 linkn = link->next;
1196                 if (!link->tonode)
1197                         nodeRemLink(wgroup, link);
1198         }
1199         /* restore links from internal nodes */
1200         for (link= wgroup->links.first; link; link= link->next) {
1201                 /* indicates link to group input */
1202                 if (!link->fromnode) {
1203                         /* NB: can't use find_group_node_input here,
1204                          * because gnode sockets still point to the old tree!
1205                          */
1206                         bNodeSocket *insock;
1207                         for (insock= gnode->inputs.first; insock; insock= insock->next)
1208                                 if (insock->groupsock->new_sock == link->fromsock)
1209                                         break;
1210                         if (insock->link) {
1211                                 link->fromnode = insock->link->fromnode;
1212                                 link->fromsock = insock->link->fromsock;
1213                         }
1214                         else {
1215                                 /* copy the default input value from the group node socket default to the internal socket */
1216                                 node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, insock->type, insock->default_value);
1217                                 nodeRemLink(wgroup, link);
1218                         }
1219                 }
1220         }
1221         
1222         /* add internal links to the ntree */
1223         for (link= wgroup->links.first; link; link= linkn) {
1224                 linkn= link->next;
1225                 BLI_remlink(&wgroup->links, link);
1226                 BLI_addtail(&ntree->links, link);
1227         }
1228         
1229         /* and copy across the animation,
1230          * note that the animation data's action can be NULL here */
1231         if (wgroup->adt) {
1232                 LinkData *ld, *ldn=NULL;
1233                 bAction *waction;
1234                 
1235                 /* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */
1236                 waction = wgroup->adt->action = BKE_action_copy(wgroup->adt->action);
1237                 
1238                 /* now perform the moving */
1239                 BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths);
1240                 
1241                 /* paths + their wrappers need to be freed */
1242                 for (ld = anim_basepaths.first; ld; ld = ldn) {
1243                         ldn = ld->next;
1244                         
1245                         MEM_freeN(ld->data);
1246                         BLI_freelinkN(&anim_basepaths, ld);
1247                 }
1248                 
1249                 /* free temp action too */
1250                 if (waction) {
1251                         BKE_libblock_free(&G.main->action, waction);
1252                 }
1253         }
1254         
1255         /* delete the group instance. this also removes old input links! */
1256         nodeFreeNode(ntree, gnode);
1257
1258         /* free the group tree (takes care of user count) */
1259         BKE_libblock_free(&G.main->nodetree, wgroup);
1260         
1261         ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
1262         
1263         return 1;
1264 }
1265
1266 static int node_group_ungroup_exec(bContext *C, wmOperator *op)
1267 {
1268         SpaceNode *snode = CTX_wm_space_node(C);
1269         bNode *gnode;
1270
1271         ED_preview_kill_jobs(C);
1272
1273         /* are we inside of a group? */
1274         gnode= node_tree_get_editgroup(snode->nodetree);
1275         if (gnode)
1276                 snode_make_group_editable(snode, NULL);
1277         
1278         gnode= nodeGetActive(snode->edittree);
1279         if (gnode==NULL)
1280                 return OPERATOR_CANCELLED;
1281         
1282         if (gnode->type!=NODE_GROUP) {
1283                 BKE_report(op->reports, RPT_WARNING, "Not a group");
1284                 return OPERATOR_CANCELLED;
1285         }
1286         else if (node_group_ungroup(snode->nodetree, gnode)) {
1287                 ntreeUpdateTree(snode->nodetree);
1288         }
1289         else {
1290                 BKE_report(op->reports, RPT_WARNING, "Can't ungroup");
1291                 return OPERATOR_CANCELLED;
1292         }
1293
1294         snode_notify(C, snode);
1295         snode_dag_update(C, snode);
1296
1297         return OPERATOR_FINISHED;
1298 }
1299
1300 void NODE_OT_group_ungroup(wmOperatorType *ot)
1301 {
1302         /* identifiers */
1303         ot->name = "Ungroup";
1304         ot->description = "Ungroup selected nodes";
1305         ot->idname = "NODE_OT_group_ungroup";
1306         
1307         /* api callbacks */
1308         ot->exec = node_group_ungroup_exec;
1309         ot->poll = ED_operator_node_active;
1310         
1311         /* flags */
1312         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
1313 }
1314
1315 /* ******************** Separate operator ********************** */
1316
1317 /* returns 1 if its OK */
1318 static int node_group_separate_selected(bNodeTree *ntree, bNode *gnode, int make_copy)
1319 {
1320         bNodeLink *link, *link_next;
1321         bNode *node, *node_next, *newnode;
1322         bNodeTree *ngroup;
1323         ListBase anim_basepaths = {NULL, NULL};
1324         
1325         ngroup= (bNodeTree *)gnode->id;
1326         if (ngroup==NULL) return 0;
1327         
1328         /* deselect all nodes in the target tree */
1329         for (node=ntree->nodes.first; node; node=node->next)
1330                 node_deselect(node);
1331         
1332         /* clear new pointers, set in nodeCopyNode */
1333         for (node= ngroup->nodes.first; node; node= node->next)
1334                 node->new_node= NULL;
1335         
1336         /* add selected nodes into the ntree */
1337         for (node= ngroup->nodes.first; node; node= node_next) {
1338                 node_next = node->next;
1339                 if (!(node->flag & NODE_SELECT))
1340                         continue;
1341                 
1342                 if (make_copy) {
1343                         /* make a copy */
1344                         newnode = nodeCopyNode(ngroup, node);
1345                 }
1346                 else {
1347                         /* use the existing node */
1348                         newnode = node;
1349                 }
1350                 
1351                 /* keep track of this node's RNA "base" path (the part of the path identifying the node) 
1352                  * if the old nodetree has animation data which potentially covers this node
1353                  */
1354                 if (ngroup->adt) {
1355                         PointerRNA ptr;
1356                         char *path;
1357                         
1358                         RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr);
1359                         path = RNA_path_from_ID_to_struct(&ptr);
1360                         
1361                         if (path)
1362                                 BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
1363                 }
1364                 
1365                 /* ensure valid parent pointers, detach if parent stays inside the group */
1366                 if (newnode->parent && !(newnode->parent->flag & NODE_SELECT))
1367                         nodeDetachNode(newnode);
1368                 
1369                 /* migrate node */
1370                 BLI_remlink(&ngroup->nodes, newnode);
1371                 BLI_addtail(&ntree->nodes, newnode);
1372                 
1373                 newnode->locx += gnode->locx;
1374                 newnode->locy += gnode->locy;
1375         }
1376         
1377         /* add internal links to the ntree */
1378         for (link= ngroup->links.first; link; link= link_next) {
1379                 int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT));
1380                 int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT));
1381                 link_next = link->next;
1382                 
1383                 if (make_copy) {
1384                         /* make a copy of internal links */
1385                         if (fromselect && toselect)
1386                                 nodeAddLink(ntree, link->fromnode->new_node, link->fromsock->new_sock, link->tonode->new_node, link->tosock->new_sock);
1387                 }
1388                 else {
1389                         /* move valid links over, delete broken links */
1390                         if (fromselect && toselect) {
1391                                 BLI_remlink(&ngroup->links, link);
1392                                 BLI_addtail(&ntree->links, link);
1393                         }
1394                         else if (fromselect || toselect) {
1395                                 nodeRemLink(ngroup, link);
1396                         }
1397                 }
1398         }
1399         
1400         /* and copy across the animation,
1401          * note that the animation data's action can be NULL here */
1402         if (ngroup->adt) {
1403                 LinkData *ld, *ldn=NULL;
1404                 
1405                 /* now perform the moving */
1406                 BKE_animdata_separate_by_basepath(&ngroup->id, &ntree->id, &anim_basepaths);
1407                 
1408                 /* paths + their wrappers need to be freed */
1409                 for (ld = anim_basepaths.first; ld; ld = ldn) {
1410                         ldn = ld->next;
1411                         
1412                         MEM_freeN(ld->data);
1413                         BLI_freelinkN(&anim_basepaths, ld);
1414                 }
1415         }
1416         
1417         ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
1418         if (!make_copy)
1419                 ngroup->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
1420         
1421         return 1;
1422 }
1423
1424 typedef enum eNodeGroupSeparateType {
1425         NODE_GS_COPY,
1426         NODE_GS_MOVE
1427 } eNodeGroupSeparateType;
1428
1429 /* Operator Property */
1430 EnumPropertyItem node_group_separate_types[] = {
1431     {NODE_GS_COPY, "COPY", 0, "Copy", "Copy to parent node tree, keep group intact"},
1432         {NODE_GS_MOVE, "MOVE", 0, "Move", "Move to parent node tree, remove from group"},
1433         {0, NULL, 0, NULL, NULL}
1434 };
1435
1436 static int node_group_separate_exec(bContext *C, wmOperator *op)
1437 {
1438         SpaceNode *snode = CTX_wm_space_node(C);
1439         bNode *gnode;
1440         int type = RNA_enum_get(op->ptr, "type");
1441
1442         ED_preview_kill_jobs(C);
1443
1444         /* are we inside of a group? */
1445         gnode= node_tree_get_editgroup(snode->nodetree);
1446         if (!gnode) {
1447                 BKE_report(op->reports, RPT_WARNING, "Not inside node group");
1448                 return OPERATOR_CANCELLED;
1449         }
1450         
1451         switch (type) {
1452         case NODE_GS_COPY:
1453                 if (!node_group_separate_selected(snode->nodetree, gnode, 1)) {
1454                         BKE_report(op->reports, RPT_WARNING, "Can't separate nodes");
1455                         return OPERATOR_CANCELLED;
1456                 }
1457                 break;
1458         case NODE_GS_MOVE:
1459                 if (!node_group_separate_selected(snode->nodetree, gnode, 0)) {
1460                         BKE_report(op->reports, RPT_WARNING, "Can't separate nodes");
1461                         return OPERATOR_CANCELLED;
1462                 }
1463                 break;
1464         }
1465         
1466         /* switch to parent tree */
1467         snode_make_group_editable(snode, NULL);
1468         
1469         ntreeUpdateTree(snode->nodetree);
1470         
1471         snode_notify(C, snode);
1472         snode_dag_update(C, snode);
1473
1474         return OPERATOR_FINISHED;
1475 }
1476
1477 static int node_group_separate_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
1478 {
1479         uiPopupMenu *pup = uiPupMenuBegin(C, "Separate", ICON_NONE);
1480         uiLayout *layout = uiPupMenuLayout(pup);
1481         
1482         uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
1483         uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY);
1484         uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE);
1485         
1486         uiPupMenuEnd(C, pup);
1487         
1488         return OPERATOR_CANCELLED;
1489 }
1490
1491 void NODE_OT_group_separate(wmOperatorType *ot)
1492 {
1493         /* identifiers */
1494         ot->name = "Separate";
1495         ot->description = "Separate selected nodes from the node group";
1496         ot->idname = "NODE_OT_group_separate";
1497         
1498         /* api callbacks */
1499         ot->invoke = node_group_separate_invoke;
1500         ot->exec = node_group_separate_exec;
1501         ot->poll = ED_operator_node_active;
1502         
1503         /* flags */
1504         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
1505         
1506         RNA_def_enum(ot->srna, "type", node_group_separate_types, NODE_GS_COPY, "Type", "");
1507 }
1508
1509 /* ************************** Node generic ************** */
1510
1511 /* is rct in visible part of node? */
1512 static bNode *visible_node(SpaceNode *snode, rctf *rct)
1513 {
1514         bNode *node;
1515         
1516         for (node=snode->edittree->nodes.last; node; node=node->prev) {
1517                 if (BLI_isect_rctf(&node->totr, rct, NULL))
1518                         break;
1519         }
1520         return node;
1521 }
1522
1523 /* **************************** */
1524
1525 typedef struct NodeViewMove {
1526         int mvalo[2];
1527         int xmin, ymin, xmax, ymax;
1528 } NodeViewMove;
1529
1530 static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
1531 {
1532         SpaceNode *snode= CTX_wm_space_node(C);
1533         ARegion *ar= CTX_wm_region(C);
1534         NodeViewMove *nvm= op->customdata;
1535
1536         switch (event->type) {
1537                 case MOUSEMOVE:
1538                         
1539                         snode->xof -= (nvm->mvalo[0]-event->mval[0]);
1540                         snode->yof -= (nvm->mvalo[1]-event->mval[1]);
1541                         nvm->mvalo[0]= event->mval[0];
1542                         nvm->mvalo[1]= event->mval[1];
1543                         
1544                         /* prevent dragging image outside of the window and losing it! */
1545                         CLAMP(snode->xof, nvm->xmin, nvm->xmax);
1546                         CLAMP(snode->yof, nvm->ymin, nvm->ymax);
1547                         
1548                         ED_region_tag_redraw(ar);
1549                         
1550                         break;
1551                         
1552                 case LEFTMOUSE:
1553                 case MIDDLEMOUSE:
1554                 case RIGHTMOUSE:
1555                         
1556                         MEM_freeN(nvm);
1557                         op->customdata= NULL;
1558
1559                         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_NODE, NULL);
1560                         
1561                         return OPERATOR_FINISHED;
1562         }
1563         
1564         return OPERATOR_RUNNING_MODAL;
1565 }
1566
1567 static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event)
1568 {
1569         ARegion *ar= CTX_wm_region(C);
1570         NodeViewMove *nvm;
1571         Image *ima;
1572         ImBuf *ibuf;
1573         int pad= 10;
1574         void *lock;
1575         
1576         ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
1577         ibuf= BKE_image_acquire_ibuf(ima, NULL, &lock);
1578         
1579         if (ibuf == NULL) {
1580                 BKE_image_release_ibuf(ima, lock);
1581                 return OPERATOR_CANCELLED;
1582         }
1583
1584         nvm= MEM_callocN(sizeof(NodeViewMove), "NodeViewMove struct");
1585         op->customdata= nvm;
1586         nvm->mvalo[0]= event->mval[0];
1587         nvm->mvalo[1]= event->mval[1];
1588
1589         nvm->xmin = -(ar->winx/2) - ibuf->x/2 + pad;
1590         nvm->xmax = ar->winx/2 + ibuf->x/2 - pad;
1591         nvm->ymin = -(ar->winy/2) - ibuf->y/2 + pad;
1592         nvm->ymax = ar->winy/2 + ibuf->y/2 - pad;
1593
1594         BKE_image_release_ibuf(ima, lock);
1595         
1596         /* add modal handler */
1597         WM_event_add_modal_handler(C, op);
1598         
1599         return OPERATOR_RUNNING_MODAL;
1600 }
1601
1602 static int snode_bg_viewmove_cancel(bContext *UNUSED(C), wmOperator *op)
1603 {
1604         MEM_freeN(op->customdata);
1605         op->customdata= NULL;
1606
1607         return OPERATOR_CANCELLED;
1608 }
1609
1610 void NODE_OT_backimage_move(wmOperatorType *ot)
1611 {
1612         /* identifiers */
1613         ot->name = "Background Image Move";
1614         ot->description = "Move Node backdrop";
1615         ot->idname = "NODE_OT_backimage_move";
1616         
1617         /* api callbacks */
1618         ot->invoke = snode_bg_viewmove_invoke;
1619         ot->modal = snode_bg_viewmove_modal;
1620         ot->poll = composite_node_active;
1621         ot->cancel = snode_bg_viewmove_cancel;
1622         
1623         /* flags */
1624         ot->flag = OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER;
1625 }
1626
1627 static int backimage_zoom(bContext *C, wmOperator *op)
1628 {
1629         SpaceNode *snode= CTX_wm_space_node(C);
1630         ARegion *ar= CTX_wm_region(C);
1631         float fac= RNA_float_get(op->ptr, "factor");
1632
1633         snode->zoom *= fac;
1634         ED_region_tag_redraw(ar);
1635
1636         return OPERATOR_FINISHED;
1637 }
1638
1639
1640 void NODE_OT_backimage_zoom(wmOperatorType *ot)
1641 {
1642         
1643         /* identifiers */
1644         ot->name = "Background Image Zoom";
1645         ot->idname = "NODE_OT_backimage_zoom";
1646         ot->description = "Zoom in/out the brackground image";
1647         
1648         /* api callbacks */
1649         ot->exec = backimage_zoom;
1650         ot->poll = composite_node_active;
1651         
1652         /* flags */
1653         ot->flag = OPTYPE_BLOCKING;
1654
1655         /* internal */
1656         RNA_def_float(ot->srna, "factor", 1.2f, 0.0f, 10.0f, "Factor", "", 0.0f, 10.0f);
1657 }
1658
1659 /******************** sample backdrop operator ********************/
1660
1661 typedef struct ImageSampleInfo {
1662         ARegionType *art;
1663         void *draw_handle;
1664         int x, y;
1665         int channels;
1666         int color_manage;
1667
1668         unsigned char col[4];
1669         float colf[4];
1670
1671         int draw;
1672 } ImageSampleInfo;
1673
1674 static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
1675 {
1676         Scene *scene = CTX_data_scene(C);
1677         ImageSampleInfo *info= arg_info;
1678
1679         ED_image_draw_info(ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels,
1680                            info->x, info->y, info->col, info->colf,
1681                            NULL, NULL /* zbuf - unused for nodes */
1682                            );
1683 }
1684
1685 static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
1686 {
1687         SpaceNode *snode= CTX_wm_space_node(C);
1688         ARegion *ar= CTX_wm_region(C);
1689         ImageSampleInfo *info= op->customdata;
1690         void *lock;
1691         Image *ima;
1692         ImBuf *ibuf;
1693         float fx, fy, bufx, bufy;
1694         
1695         ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
1696         ibuf= BKE_image_acquire_ibuf(ima, NULL, &lock);
1697         if (!ibuf)
1698                 return;
1699         
1700         if (!ibuf->rect) {
1701                 if (info->color_manage)
1702                         ibuf->profile = IB_PROFILE_LINEAR_RGB;
1703                 else
1704                         ibuf->profile = IB_PROFILE_NONE;
1705                 IMB_rect_from_float(ibuf);
1706         }
1707
1708         /* map the mouse coords to the backdrop image space */
1709         bufx = ibuf->x * snode->zoom;
1710         bufy = ibuf->y * snode->zoom;
1711         fx = (bufx > 0.0f ? ((float)event->mval[0] - 0.5f*ar->winx - snode->xof) / bufx + 0.5f : 0.0f);
1712         fy = (bufy > 0.0f ? ((float)event->mval[1] - 0.5f*ar->winy - snode->yof) / bufy + 0.5f : 0.0f);
1713
1714         if (fx>=0.0f && fy>=0.0f && fx<1.0f && fy<1.0f) {
1715                 float *fp;
1716                 char *cp;
1717                 int x= (int)(fx*ibuf->x), y= (int)(fy*ibuf->y);
1718
1719                 CLAMP(x, 0, ibuf->x-1);
1720                 CLAMP(y, 0, ibuf->y-1);
1721
1722                 info->x= x;
1723                 info->y= y;
1724                 info->draw= 1;
1725                 info->channels= ibuf->channels;
1726
1727                 if (ibuf->rect) {
1728                         cp= (char *)(ibuf->rect + y*ibuf->x + x);
1729
1730                         info->col[0]= cp[0];
1731                         info->col[1]= cp[1];
1732                         info->col[2]= cp[2];
1733                         info->col[3]= cp[3];
1734
1735                         info->colf[0]= (float)cp[0]/255.0f;
1736                         info->colf[1]= (float)cp[1]/255.0f;
1737                         info->colf[2]= (float)cp[2]/255.0f;
1738                         info->colf[3]= (float)cp[3]/255.0f;
1739                 }
1740                 if (ibuf->rect_float) {
1741                         fp= (ibuf->rect_float + (ibuf->channels)*(y*ibuf->x + x));
1742
1743                         info->colf[0]= fp[0];
1744                         info->colf[1]= fp[1];
1745                         info->colf[2]= fp[2];
1746                         info->colf[3]= fp[3];
1747                 }
1748         }
1749         else
1750                 info->draw= 0;
1751
1752         BKE_image_release_ibuf(ima, lock);
1753         
1754         ED_area_tag_redraw(CTX_wm_area(C));
1755 }
1756
1757 static void sample_exit(bContext *C, wmOperator *op)
1758 {
1759         ImageSampleInfo *info= op->customdata;
1760
1761         ED_region_draw_cb_exit(info->art, info->draw_handle);
1762         ED_area_tag_redraw(CTX_wm_area(C));
1763         MEM_freeN(info);
1764 }
1765
1766 static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
1767 {
1768         SpaceNode *snode= CTX_wm_space_node(C);
1769         ARegion *ar= CTX_wm_region(C);
1770         ImageSampleInfo *info;
1771
1772         if (snode->treetype!=NTREE_COMPOSIT || !(snode->flag & SNODE_BACKDRAW))
1773                 return OPERATOR_CANCELLED;
1774         
1775         info= MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
1776         info->art= ar->type;
1777         info->draw_handle = ED_region_draw_cb_activate(ar->type, sample_draw, info, REGION_DRAW_POST_PIXEL);
1778         op->customdata= info;
1779
1780         sample_apply(C, op, event);
1781
1782         WM_event_add_modal_handler(C, op);
1783
1784         return OPERATOR_RUNNING_MODAL;
1785 }
1786
1787 static int sample_modal(bContext *C, wmOperator *op, wmEvent *event)
1788 {
1789         switch (event->type) {
1790                 case LEFTMOUSE:
1791                 case RIGHTMOUSE: // XXX hardcoded
1792                         sample_exit(C, op);
1793                         return OPERATOR_CANCELLED;
1794                 case MOUSEMOVE:
1795                         sample_apply(C, op, event);
1796                         break;
1797         }
1798
1799         return OPERATOR_RUNNING_MODAL;
1800 }
1801
1802 static int sample_cancel(bContext *C, wmOperator *op)
1803 {
1804         sample_exit(C, op);
1805         return OPERATOR_CANCELLED;
1806 }
1807
1808 void NODE_OT_backimage_sample(wmOperatorType *ot)
1809 {
1810         /* identifiers */
1811         ot->name = "Backimage Sample";
1812         ot->idname = "NODE_OT_backimage_sample";
1813         ot->description = "Use mouse to sample background image";
1814         
1815         /* api callbacks */
1816         ot->invoke = sample_invoke;
1817         ot->modal = sample_modal;
1818         ot->cancel = sample_cancel;
1819         ot->poll = ED_operator_node_active;
1820
1821         /* flags */
1822         ot->flag = OPTYPE_BLOCKING;
1823 }
1824
1825 /* ********************** size widget operator ******************** */
1826
1827 typedef struct NodeSizeWidget {
1828         float mxstart, mystart;
1829         float oldlocx, oldlocy;
1830         float oldoffsetx, oldoffsety;
1831         float oldwidth, oldheight;
1832         float oldminiwidth;
1833         int directions;
1834 } NodeSizeWidget;
1835
1836 static void node_resize_init(bContext *C, wmOperator *op, wmEvent *UNUSED(event), bNode *node, int dir)
1837 {
1838         SpaceNode *snode = CTX_wm_space_node(C);
1839         
1840         NodeSizeWidget *nsw= MEM_callocN(sizeof(NodeSizeWidget), "size widget op data");
1841         
1842         op->customdata= nsw;
1843         nsw->mxstart= snode->mx;
1844         nsw->mystart= snode->my;
1845         
1846         /* store old */
1847         nsw->oldlocx= node->locx;
1848         nsw->oldlocy= node->locy;
1849         nsw->oldoffsetx= node->offsetx;
1850         nsw->oldoffsety= node->offsety;
1851         nsw->oldwidth= node->width;
1852         nsw->oldheight= node->height;
1853         nsw->oldminiwidth= node->miniwidth;
1854         nsw->directions = dir;
1855         
1856         WM_cursor_modal(CTX_wm_window(C), node_get_resize_cursor(dir));
1857         /* add modal handler */
1858         WM_event_add_modal_handler(C, op);
1859 }
1860
1861 static void node_resize_exit(bContext *C, wmOperator *op, int UNUSED(cancel))
1862 {
1863         WM_cursor_restore(CTX_wm_window(C));
1864         
1865         MEM_freeN(op->customdata);
1866         op->customdata= NULL;
1867 }
1868
1869 static int node_resize_modal(bContext *C, wmOperator *op, wmEvent *event)
1870 {
1871         SpaceNode *snode= CTX_wm_space_node(C);
1872         ARegion *ar= CTX_wm_region(C);
1873         bNode *node= editnode_get_active(snode->edittree);
1874         NodeSizeWidget *nsw= op->customdata;
1875         float mx, my, dx, dy;
1876         
1877         switch (event->type) {
1878                 case MOUSEMOVE:
1879                         
1880                         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mx, &my);
1881                         dx = mx - nsw->mxstart;
1882                         dy = my - nsw->mystart;
1883                         
1884                         if (node) {
1885                                 if (node->flag & NODE_HIDDEN) {
1886                                         float widthmin = 0.0f;
1887                                         float widthmax = 100.0f;
1888                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
1889                                                 node->miniwidth= nsw->oldminiwidth + dx;
1890                                                 CLAMP(node->miniwidth, widthmin, widthmax);
1891                                         }
1892                                         if (nsw->directions & NODE_RESIZE_LEFT) {
1893                                                 float locmax = nsw->oldlocx + nsw->oldminiwidth;
1894                                                 
1895                                                 node->locx= nsw->oldlocx + dx;
1896                                                 CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
1897                                                 node->miniwidth= locmax - node->locx;
1898                                         }
1899                                 }
1900                                 else {
1901                                         float widthmin = UI_DPI_FAC*node->typeinfo->minwidth;
1902                                         float widthmax = UI_DPI_FAC*node->typeinfo->maxwidth;
1903                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
1904                                                 node->width= nsw->oldwidth + dx;
1905                                                 CLAMP(node->width, widthmin, widthmax);
1906                                         }
1907                                         if (nsw->directions & NODE_RESIZE_LEFT) {
1908                                                 float locmax = nsw->oldlocx + nsw->oldwidth;
1909                                                 
1910                                                 node->locx= nsw->oldlocx + dx;
1911                                                 CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
1912                                                 node->width= locmax - node->locx;
1913                                         }
1914                                 }
1915                         
1916                                 /* height works the other way round ... */
1917                                 {
1918                                         float heightmin = UI_DPI_FAC*node->typeinfo->minheight;
1919                                         float heightmax = UI_DPI_FAC*node->typeinfo->maxheight;
1920                                         if (nsw->directions & NODE_RESIZE_TOP) {
1921                                                 float locmin = nsw->oldlocy - nsw->oldheight;
1922                                                 
1923                                                 node->locy= nsw->oldlocy + dy;
1924                                                 CLAMP(node->locy, locmin + heightmin, locmin + heightmax);
1925                                                 node->height= node->locy - locmin;
1926                                         }
1927                                         if (nsw->directions & NODE_RESIZE_BOTTOM) {
1928                                                 node->height= nsw->oldheight - dy;
1929                                                 CLAMP(node->height, heightmin, heightmax);
1930                                         }
1931                                 }
1932                                 
1933                                 /* XXX make callback? */
1934                                 if (node->type == NODE_FRAME) {
1935                                         /* keep the offset symmetric around center point */
1936                                         if (nsw->directions & NODE_RESIZE_LEFT) {
1937                                                 node->locx = nsw->oldlocx + 0.5f*dx;
1938                                                 node->offsetx = nsw->oldoffsetx + 0.5f*dx;
1939                                         }
1940                                         if (nsw->directions & NODE_RESIZE_RIGHT) {
1941                                                 node->locx = nsw->oldlocx + 0.5f*dx;
1942                                                 node->offsetx = nsw->oldoffsetx - 0.5f*dx;
1943                                         }
1944                                         if (nsw->directions & NODE_RESIZE_TOP) {
1945                                                 node->locy = nsw->oldlocy + 0.5f*dy;
1946                                                 node->offsety = nsw->oldoffsety + 0.5f*dy;
1947                                         }
1948                                         if (nsw->directions & NODE_RESIZE_BOTTOM) {
1949                                                 node->locy = nsw->oldlocy + 0.5f*dy;
1950                                                 node->offsety = nsw->oldoffsety - 0.5f*dy;
1951                                         }
1952                                 }
1953                         }
1954                                 
1955                         ED_region_tag_redraw(ar);
1956
1957                         break;
1958                         
1959                 case LEFTMOUSE:
1960                 case MIDDLEMOUSE:
1961                 case RIGHTMOUSE:
1962                         
1963                         node_resize_exit(C, op, 0);
1964                         ED_node_post_apply_transform(C, snode->edittree);
1965                         
1966                         return OPERATOR_FINISHED;
1967         }
1968         
1969         return OPERATOR_RUNNING_MODAL;
1970 }
1971
1972 static int node_resize_invoke(bContext *C, wmOperator *op, wmEvent *event)
1973 {
1974         SpaceNode *snode= CTX_wm_space_node(C);
1975         ARegion *ar= CTX_wm_region(C);
1976         bNode *node= editnode_get_active(snode->edittree);
1977         int dir;
1978         
1979         if (node) {
1980                 /* convert mouse coordinates to v2d space */
1981                 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
1982                                          &snode->mx, &snode->my);
1983                 dir = node->typeinfo->resize_area_func(node, snode->mx, snode->my);
1984                 if (dir != 0) {
1985                         node_resize_init(C, op, event, node, dir);
1986                         return OPERATOR_RUNNING_MODAL;
1987                 }
1988         }
1989         return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH;
1990 }
1991
1992 static int node_resize_cancel(bContext *C, wmOperator *op)
1993 {
1994         node_resize_exit(C, op, 1);
1995
1996         return OPERATOR_CANCELLED;
1997 }
1998
1999 void NODE_OT_resize(wmOperatorType *ot)
2000 {
2001         /* identifiers */
2002         ot->name = "Resize Node";
2003         ot->idname = "NODE_OT_resize";
2004         ot->description = "Resize a node";
2005         
2006         /* api callbacks */
2007         ot->invoke = node_resize_invoke;
2008         ot->modal = node_resize_modal;
2009         ot->poll = ED_operator_node_active;
2010         ot->cancel = node_resize_cancel;
2011         
2012         /* flags */
2013         ot->flag = OPTYPE_BLOCKING;
2014 }
2015
2016
2017 /* ********************** hidden sockets ******************** */
2018
2019 int node_has_hidden_sockets(bNode *node)
2020 {
2021         bNodeSocket *sock;
2022         
2023         for (sock= node->inputs.first; sock; sock= sock->next)
2024                 if (sock->flag & SOCK_HIDDEN)
2025                         return 1;
2026         for (sock= node->outputs.first; sock; sock= sock->next)
2027                 if (sock->flag & SOCK_HIDDEN)
2028                         return 1;
2029         return 0;
2030 }
2031
2032 void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
2033 {
2034         bNodeSocket *sock;
2035
2036         if (set==0) {
2037                 for (sock= node->inputs.first; sock; sock= sock->next)
2038                         sock->flag &= ~SOCK_HIDDEN;
2039                 for (sock= node->outputs.first; sock; sock= sock->next)
2040                         sock->flag &= ~SOCK_HIDDEN;
2041         }
2042         else {
2043                 /* hide unused sockets */
2044                 for (sock= node->inputs.first; sock; sock= sock->next) {
2045                         if (sock->link==NULL)
2046                                 sock->flag |= SOCK_HIDDEN;
2047                 }
2048                 for (sock= node->outputs.first; sock; sock= sock->next) {
2049                         if (nodeCountSocketLinks(snode->edittree, sock)==0)
2050                                 sock->flag |= SOCK_HIDDEN;
2051                 }
2052         }
2053 }
2054
2055 static int node_link_viewer(const bContext *C, bNode *tonode)
2056 {
2057         SpaceNode *snode = CTX_wm_space_node(C);
2058         bNode *node;
2059         bNodeLink *link;
2060         bNodeSocket *sock;
2061
2062         /* context check */
2063         if (tonode==NULL || tonode->outputs.first==NULL)
2064                 return OPERATOR_CANCELLED;
2065         if ( ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
2066                 return OPERATOR_CANCELLED;
2067         
2068         /* get viewer */
2069         for (node= snode->edittree->nodes.first; node; node= node->next)
2070                 if ( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
2071                         if (node->flag & NODE_DO_OUTPUT)
2072                                 break;
2073         /* no viewer, we make one active */
2074         if (node==NULL) {
2075                 for (node= snode->edittree->nodes.first; node; node= node->next) {
2076                         if ( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
2077                                 node->flag |= NODE_DO_OUTPUT;
2078                                 break;
2079                         }
2080                 }
2081         }
2082         
2083         sock = NULL;
2084         
2085         /* try to find an already connected socket to cycle to the next */
2086         if (node) {
2087                 link = NULL;
2088                 for (link= snode->edittree->links.first; link; link= link->next)
2089                         if (link->tonode==node && link->fromnode==tonode)
2090                                 if (link->tosock==node->inputs.first)
2091                                         break;
2092                 if (link) {
2093                         /* unlink existing connection */
2094                         sock= link->fromsock;
2095                         nodeRemLink(snode->edittree, link);
2096                         
2097                         /* find a socket after the previously connected socket */
2098                         for (sock=sock->next; sock; sock= sock->next)
2099                                 if (!nodeSocketIsHidden(sock))
2100                                         break;
2101                 }
2102         }
2103         
2104         /* find a socket starting from the first socket */
2105         if (!sock) {
2106                 for (sock= tonode->outputs.first; sock; sock= sock->next)
2107                         if (!nodeSocketIsHidden(sock))
2108                                 break;
2109         }
2110         
2111         if (sock) {
2112                 /* add a new viewer if none exists yet */
2113                 if (!node) {
2114                         Main *bmain = CTX_data_main(C);
2115                         Scene *scene = CTX_data_scene(C);
2116                         bNodeTemplate ntemp;
2117                         
2118                         ntemp.type = CMP_NODE_VIEWER;
2119                         /* XXX location is a quick hack, just place it next to the linked socket */
2120                         node = node_add_node(snode, bmain, scene, &ntemp, sock->locx + 100, sock->locy);
2121                         if (!node)
2122                                 return OPERATOR_CANCELLED;
2123                         
2124                         link = NULL;
2125                 }
2126                 else {
2127                         /* get link to viewer */
2128                         for (link= snode->edittree->links.first; link; link= link->next)
2129                                 if (link->tonode==node && link->tosock==node->inputs.first)
2130                                         break;
2131                 }
2132                 
2133                 if (link==NULL) {
2134                         nodeAddLink(snode->edittree, tonode, sock, node, node->inputs.first);
2135                 }
2136                 else {
2137                         link->fromnode= tonode;
2138                         link->fromsock= sock;
2139                         /* make sure the dependency sorting is updated */
2140                         snode->edittree->update |= NTREE_UPDATE_LINKS;
2141                 }
2142                 ntreeUpdateTree(snode->edittree);
2143                 snode_update(snode, node);
2144         }
2145         
2146         return OPERATOR_FINISHED;
2147 }
2148
2149
2150 static int node_active_link_viewer(bContext *C, wmOperator *UNUSED(op))
2151 {
2152         SpaceNode *snode= CTX_wm_space_node(C);
2153         bNode *node;
2154         
2155         node= editnode_get_active(snode->edittree);
2156         
2157         if (!node)
2158                 return OPERATOR_CANCELLED;
2159
2160         ED_preview_kill_jobs(C);
2161
2162         if (node_link_viewer(C, node) == OPERATOR_CANCELLED)
2163                 return OPERATOR_CANCELLED;
2164
2165         snode_notify(C, snode);
2166
2167         return OPERATOR_FINISHED;
2168 }
2169
2170
2171
2172 void NODE_OT_link_viewer(wmOperatorType *ot)
2173 {
2174         /* identifiers */
2175         ot->name = "Link to Viewer Node";
2176         ot->description = "Link to viewer node";
2177         ot->idname = "NODE_OT_link_viewer";
2178         
2179         /* api callbacks */
2180         ot->exec = node_active_link_viewer;
2181         ot->poll = composite_node_active;
2182         
2183         /* flags */
2184         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2185 }
2186
2187
2188
2189 /* return 0, nothing done */
2190 static int UNUSED_FUNCTION(node_mouse_groupheader)(SpaceNode *snode)
2191 {
2192         bNode *gnode;
2193         float mx=0, my=0;
2194 // XXX  int mval[2];
2195         
2196         gnode= node_tree_get_editgroup(snode->nodetree);
2197         if (gnode==NULL) return 0;
2198         
2199 // XXX  getmouseco_areawin(mval);
2200 // XXX  areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
2201         
2202         /* click in header or outside? */
2203         if (BLI_in_rctf(&gnode->totr, mx, my)==0) {
2204                 rctf rect= gnode->totr;
2205                 
2206                 rect.ymax += NODE_DY;
2207                 if (BLI_in_rctf(&rect, mx, my)==0)
2208                         snode_make_group_editable(snode, NULL); /* toggles, so exits editmode */
2209 //              else
2210 // XXX                  transform_nodes(snode->nodetree, 'g', "Move group");
2211                 
2212                 return 1;
2213         }
2214         return 0;
2215 }
2216
2217 /* checks snode->mouse position, and returns found node/socket */
2218 /* type is SOCK_IN and/or SOCK_OUT */
2219 int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, int in_out)
2220 {
2221         bNode *node;
2222         bNodeSocket *sock;
2223         rctf rect;
2224         
2225         *nodep= NULL;
2226         *sockp= NULL;
2227         
2228         /* check if we click in a socket */
2229         for (node= snode->edittree->nodes.first; node; node= node->next) {
2230                 
2231                 rect.xmin = snode->mx - (NODE_SOCKSIZE+4);
2232                 rect.ymin = snode->my - (NODE_SOCKSIZE+4);
2233                 rect.xmax = snode->mx + (NODE_SOCKSIZE+4);
2234                 rect.ymax = snode->my + (NODE_SOCKSIZE+4);
2235                 
2236                 if (!(node->flag & NODE_HIDDEN)) {
2237                         /* extra padding inside and out - allow dragging on the text areas too */
2238                         if (in_out == SOCK_IN) {
2239                                 rect.xmax += NODE_SOCKSIZE;
2240                                 rect.xmin -= NODE_SOCKSIZE*4;
2241                         }
2242                         else if (in_out == SOCK_OUT) {
2243                                 rect.xmax += NODE_SOCKSIZE*4;
2244                                 rect.xmin -= NODE_SOCKSIZE;
2245                         }
2246                 }
2247                 
2248                 if (in_out & SOCK_IN) {
2249                         for (sock= node->inputs.first; sock; sock= sock->next) {
2250                                 if (!nodeSocketIsHidden(sock)) {
2251                                         if (BLI_in_rctf(&rect, sock->locx, sock->locy)) {
2252                                                 if (node == visible_node(snode, &rect)) {
2253                                                         *nodep= node;
2254                                                         *sockp= sock;
2255                                                         return 1;
2256                                                 }
2257                                         }
2258                                 }
2259                         }
2260                 }
2261                 if (in_out & SOCK_OUT) {
2262                         for (sock= node->outputs.first; sock; sock= sock->next) {
2263                                 if (!nodeSocketIsHidden(sock)) {
2264                                         if (BLI_in_rctf(&rect, sock->locx, sock->locy)) {
2265                                                 if (node == visible_node(snode, &rect)) {
2266                                                         *nodep= node;
2267                                                         *sockp= sock;
2268                                                         return 1;
2269                                                 }
2270                                         }
2271                                 }
2272                         }
2273                 }
2274         }
2275         
2276         /* check group sockets
2277          * NB: using ngroup->outputs as input sockets and vice versa here!
2278          */
2279         if (in_out & SOCK_IN) {
2280                 for (sock= snode->edittree->outputs.first; sock; sock= sock->next) {
2281                         if (!nodeSocketIsHidden(sock)) {
2282                                 if (BLI_in_rctf(&rect, sock->locx, sock->locy)) {
2283                                         *nodep= NULL;   /* NULL node pointer indicates group socket */
2284                                         *sockp= sock;
2285                                         return 1;
2286                                 }
2287                         }
2288                 }
2289         }
2290         if (in_out & SOCK_OUT) {
2291                 for (sock= snode->edittree->inputs.first; sock; sock= sock->next) {
2292                         if (!nodeSocketIsHidden(sock)) {
2293                                 if (BLI_in_rctf(&rect, sock->locx, sock->locy)) {
2294                                         *nodep= NULL;   /* NULL node pointer indicates group socket */
2295                                         *sockp= sock;
2296                                         return 1;
2297                                 }
2298                         }
2299                 }
2300         }
2301         
2302         return 0;
2303 }
2304
2305 static int outside_group_rect(SpaceNode *snode)
2306 {
2307         bNode *gnode= node_tree_get_editgroup(snode->nodetree);
2308         if (gnode) {
2309                 return (snode->mx <  gnode->totr.xmin ||
2310                         snode->mx >= gnode->totr.xmax ||
2311                         snode->my <  gnode->totr.ymin ||
2312                         snode->my >= gnode->totr.ymax);
2313         }
2314         return 0;
2315 }
2316
2317 /* ****************** Add *********************** */
2318
2319
2320 typedef struct bNodeListItem {
2321         struct bNodeListItem *next, *prev;
2322         struct bNode *node;     
2323 } bNodeListItem;
2324
2325 static int sort_nodes_locx(void *a, void *b)
2326 {
2327         bNodeListItem *nli1 = (bNodeListItem *)a;
2328         bNodeListItem *nli2 = (bNodeListItem *)b;
2329         bNode *node1 = nli1->node;
2330         bNode *node2 = nli2->node;
2331         
2332         if (node1->locx > node2->locx)
2333                 return 1;
2334         else 
2335                 return 0;
2336 }
2337
2338 static int socket_is_available(bNodeTree *UNUSED(ntree), bNodeSocket *sock, int allow_used)
2339 {
2340         if (nodeSocketIsHidden(sock))
2341                 return 0;
2342         
2343         if (!allow_used && (sock->flag & SOCK_IN_USE))
2344                 return 0;
2345         
2346         return 1;
2347 }
2348
2349 static bNodeSocket *best_socket_output(bNodeTree *ntree, bNode *node, bNodeSocket *sock_target, int allow_multiple)
2350 {
2351         bNodeSocket *sock;
2352         
2353         /* first look for selected output */
2354         for (sock=node->outputs.first; sock; sock=sock->next) {
2355                 if (!socket_is_available(ntree, sock, allow_multiple))
2356                         continue;
2357                 
2358                 if (sock->flag & SELECT)
2359                         return sock;
2360         }
2361         
2362         /* try to find a socket with a matching name */
2363         for (sock=node->outputs.first; sock; sock=sock->next) {
2364                 if (!socket_is_available(ntree, sock, allow_multiple))
2365                         continue;
2366
2367                 /* check for same types */
2368                 if (sock->type == sock_target->type) {
2369                         if (strcmp(sock->name, sock_target->name)==0)
2370                                 return sock;
2371                 }
2372         }
2373         
2374         /* otherwise settle for the first available socket of the right type */
2375         for (sock=node->outputs.first; sock; sock=sock->next) {
2376
2377                 if (!socket_is_available(ntree, sock, allow_multiple))
2378                         continue;
2379                 
2380                 /* check for same types */
2381                 if (sock->type == sock_target->type) {
2382                         return sock;
2383                 }
2384         }
2385         
2386         return NULL;
2387 }
2388
2389 /* this is a bit complicated, but designed to prioritize finding
2390  * sockets of higher types, such as image, first */
2391 static bNodeSocket *best_socket_input(bNodeTree *ntree, bNode *node, int num, int replace)
2392 {
2393         bNodeSocket *sock;
2394         int socktype, maxtype=0;
2395         int a = 0;
2396         
2397         for (sock=node->inputs.first; sock; sock=sock->next) {
2398                 maxtype = MAX2(sock->type, maxtype);
2399         }
2400         
2401         /* find sockets of higher 'types' first (i.e. image) */
2402         for (socktype=maxtype; socktype >= 0; socktype--) {
2403                 for (sock=node->inputs.first; sock; sock=sock->next) {
2404                         
2405                         if (!socket_is_available(ntree, sock, replace)) {
2406                                 a++;
2407                                 continue;
2408                         }
2409                                 
2410                         if (sock->type == socktype) {
2411                                 /* increment to make sure we don't keep finding 
2412                                  * the same socket on every attempt running this function */
2413                                 a++;
2414                                 if (a > num)
2415                                         return sock;
2416                         }
2417                 }
2418         }
2419         
2420         return NULL;
2421 }
2422
2423 static int snode_autoconnect_input(SpaceNode *snode, bNode *node_fr, bNodeSocket *sock_fr, bNode *node_to, bNodeSocket *sock_to, int replace)
2424 {
2425         bNodeTree *ntree = snode->edittree;
2426         bNodeLink *link;
2427         
2428         /* then we can connect */
2429         if (replace)
2430                 nodeRemSocketLinks(ntree, sock_to);
2431         
2432         link = nodeAddLink(ntree, node_fr, sock_fr, node_to, sock_to);
2433         /* validate the new link */
2434         ntreeUpdateTree(ntree);
2435         if (!(link->flag & NODE_LINK_VALID)) {
2436                 nodeRemLink(ntree, link);
2437                 return 0;
2438         }
2439         
2440         snode_update(snode, node_to);
2441         return 1;
2442 }
2443
2444 void snode_autoconnect(SpaceNode *snode, int allow_multiple, int replace)
2445 {
2446         bNodeTree *ntree = snode->edittree;
2447         ListBase *nodelist = MEM_callocN(sizeof(ListBase), "items_list");
2448         bNodeListItem *nli;
2449         bNode *node;
2450         int i, numlinks=0;
2451         
2452         for (node= ntree->nodes.first; node; node= node->next) {
2453                 if (node->flag & NODE_SELECT) {
2454                         nli = MEM_mallocN(sizeof(bNodeListItem), "temporary node list item");
2455                         nli->node = node;
2456                         BLI_addtail(nodelist, nli);
2457                 }
2458         }
2459         
2460         /* sort nodes left to right */
2461         BLI_sortlist(nodelist, sort_nodes_locx);
2462         
2463         for (nli=nodelist->first; nli; nli=nli->next) {
2464                 bNode *node_fr, *node_to;
2465                 bNodeSocket *sock_fr, *sock_to;
2466                 int has_selected_inputs = 0;
2467                 
2468                 if (nli->next == NULL) break;
2469                 
2470                 node_fr = nli->node;
2471                 node_to = nli->next->node;
2472                 
2473                 /* if there are selected sockets, connect those */
2474                 for (sock_to = node_to->inputs.first; sock_to; sock_to=sock_to->next) {
2475                         if (sock_to->flag & SELECT) {
2476                                 has_selected_inputs = 1;
2477                                 
2478                                 if (!socket_is_available(ntree, sock_to, replace))
2479                                         continue;
2480                                 
2481                                 /* check for an appropriate output socket to connect from */
2482                                 sock_fr = best_socket_output(ntree, node_fr, sock_to, allow_multiple);
2483                                 if (!sock_fr)
2484                                         continue;
2485         
2486                                 if (snode_autoconnect_input(snode, node_fr, sock_fr, node_to, sock_to, replace))
2487                                         ++numlinks;
2488                         }
2489                 }
2490                 
2491                 if (!has_selected_inputs) {
2492                         /* no selected inputs, connect by finding suitable match */
2493                         int num_inputs = BLI_countlist(&node_to->inputs);
2494                         
2495                         for (i=0; i<num_inputs; i++) {
2496                                 
2497                                 /* find the best guess input socket */
2498                                 sock_to = best_socket_input(ntree, node_to, i, replace);
2499                                 if (!sock_to)
2500                                         continue;
2501                                 
2502                                 /* check for an appropriate output socket to connect from */
2503                                 sock_fr = best_socket_output(ntree, node_fr, sock_to, allow_multiple);
2504                                 if (!sock_fr)
2505                                         continue;
2506         
2507                                 if (snode_autoconnect_input(snode, node_fr, sock_fr, node_to, sock_to, replace)) {
2508                                         ++numlinks;
2509                                         break;
2510                                 }
2511                         }
2512                 }
2513         }
2514         
2515         if (numlinks > 0) {
2516                 ntreeUpdateTree(ntree);
2517         }
2518         
2519         BLI_freelistN(nodelist);
2520         MEM_freeN(nodelist);
2521 }
2522
2523 /* can be called from menus too, but they should do own undopush and redraws */
2524 bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene, bNodeTemplate *ntemp, float locx, float locy)
2525 {
2526         bNode *node= NULL, *gnode;
2527         
2528         node_deselect_all(snode);
2529         
2530         node = nodeAddNode(snode->edittree, ntemp);
2531         
2532         /* generics */
2533         if (node) {
2534                 node->locx= locx;
2535                 node->locy= locy + 60.0f;               // arbitrary.. so its visible, (0,0) is top of node
2536                 node_select(node);
2537                 
2538                 gnode= node_tree_get_editgroup(snode->nodetree);
2539                 if (gnode) {
2540                         node->locx -= gnode->locx;
2541                         node->locy -= gnode->locy;
2542                 }
2543
2544                 ntreeUpdateTree(snode->edittree);
2545                 ED_node_set_active(bmain, snode->edittree, node);
2546                 
2547                 if (snode->nodetree->type==NTREE_COMPOSIT) {
2548                         if (ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) {
2549                                 node->id = &scene->id;
2550                         }
2551                         else if (ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) {
2552                                 node->id = (ID *)scene->clip;
2553                         }
2554                         
2555                         ntreeCompositForceHidden(snode->edittree, scene);
2556                 }
2557                         
2558                 if (node->id)
2559                         id_us_plus(node->id);
2560                         
2561                 snode_update(snode, node);
2562         }
2563         
2564         if (snode->nodetree->type==NTREE_TEXTURE) {
2565                 ntreeTexCheckCyclics(snode->edittree);
2566         }
2567         
2568         return node;
2569 }
2570
2571 /* ****************** Duplicate *********************** */
2572
2573 static void node_duplicate_reparent_recursive(bNode *node)
2574 {
2575         bNode *parent;
2576         
2577         node->flag |= NODE_TEST;
2578         
2579         /* find first selected parent */
2580         for (parent=node->parent; parent; parent=parent->parent) {
2581                 if (parent->flag & SELECT) {
2582                         if (!(parent->flag & NODE_TEST))
2583                                 node_duplicate_reparent_recursive(parent);
2584                         break;
2585                 }
2586         }
2587         /* reparent node copy to parent copy */
2588         if (parent) {
2589                 nodeDetachNode(node->new_node);
2590                 nodeAttachNode(node->new_node, parent->new_node);
2591         }
2592 }
2593
2594 static int node_duplicate_exec(bContext *C, wmOperator *op)
2595 {
2596         SpaceNode *snode= CTX_wm_space_node(C);
2597         bNodeTree *ntree= snode->edittree;
2598         bNode *node, *newnode, *lastnode;
2599         bNodeLink *link, *newlink, *lastlink;
2600         int keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
2601         
2602         ED_preview_kill_jobs(C);
2603         
2604         lastnode = ntree->nodes.last;
2605         for (node= ntree->nodes.first; node; node= node->next) {
2606                 if (node->flag & SELECT) {
2607                         newnode = nodeCopyNode(ntree, node);
2608                         
2609                         if (newnode->id) {
2610                                 /* simple id user adjustment, node internal functions don't touch this
2611                                  * but operators and readfile.c do. */
2612                                 id_us_plus(newnode->id);
2613                                 /* to ensure redraws or rerenders happen */
2614                                 ED_node_changed_update(snode->id, newnode);
2615                         }
2616                 }
2617                 
2618                 /* make sure we don't copy new nodes again! */
2619                 if (node==lastnode)
2620                         break;
2621         }
2622         
2623         /* copy links between selected nodes
2624          * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
2625          */
2626         lastlink = ntree->links.last;
2627         for (link=ntree->links.first; link; link=link->next) {
2628                 /* This creates new links between copied nodes.
2629                  * If keep_inputs is set, also copies input links from unselected (when fromnode==NULL)!
2630                  */
2631                 if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
2632                     (keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT))))
2633                 {
2634                         newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
2635                         newlink->flag = link->flag;
2636                         newlink->tonode = link->tonode->new_node;
2637                         newlink->tosock = link->tosock->new_sock;
2638                         if (link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
2639                                 newlink->fromnode = link->fromnode->new_node;
2640                                 newlink->fromsock = link->fromsock->new_sock;
2641                         }
2642                         else {
2643                                 /* input node not copied, this keeps the original input linked */
2644                                 newlink->fromnode = link->fromnode;
2645                                 newlink->fromsock = link->fromsock;
2646                         }
2647                         
2648                         BLI_addtail(&ntree->links, newlink);
2649                 }
2650                 
2651                 /* make sure we don't copy new links again! */
2652                 if (link==lastlink)
2653                         break;
2654         }
2655         
2656         /* clear flags for recursive depth-first iteration */
2657         for (node= ntree->nodes.first; node; node= node->next)
2658                 node->flag &= ~NODE_TEST;
2659         /* reparent copied nodes */
2660         for (node= ntree->nodes.first; node; node= node->next) {
2661                 if ((node->flag & SELECT) && !(node->flag & NODE_TEST))
2662                         node_duplicate_reparent_recursive(node);
2663                 
2664                 /* only has to check old nodes */
2665                 if (node==lastnode)
2666                         break;
2667         }
2668         
2669         /* deselect old nodes, select the copies instead */
2670         for (node= ntree->nodes.first; node; node= node->next) {
2671                 if (node->flag & SELECT) {
2672                         /* has been set during copy above */
2673                         newnode = node->new_node;
2674                         
2675                         node_deselect(node);
2676                         node->flag &= ~NODE_ACTIVE;
2677                         node_select(newnode);
2678                 }
2679                 
2680                 /* make sure we don't copy new nodes again! */
2681                 if (node==lastnode)
2682                         break;
2683         }
2684         
2685         ntreeUpdateTree(snode->edittree);
2686         
2687         snode_notify(C, snode);
2688         snode_dag_update(C, snode);
2689
2690         return OPERATOR_FINISHED;
2691 }
2692
2693 void NODE_OT_duplicate(wmOperatorType *ot)
2694 {
2695         /* identifiers */
2696         ot->name = "Duplicate Nodes";
2697         ot->description = "Duplicate selected nodes";
2698         ot->idname = "NODE_OT_duplicate";
2699         
2700         /* api callbacks */
2701         ot->exec = node_duplicate_exec;
2702         ot->poll = ED_operator_node_active;
2703         
2704         /* flags */
2705         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2706         
2707         RNA_def_boolean(ot->srna, "keep_inputs", 0, "Keep Inputs", "Keep the input links to duplicated nodes");
2708 }
2709
2710 /* *************************** add link op ******************** */
2711
2712 static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeLink *link)
2713 {
2714         bNodeLink *tlink;
2715         bNodeSocket *sock;
2716         
2717         if (tsock && nodeCountSocketLinks(snode->edittree, link->tosock) > tsock->limit) {
2718                 
2719                 for (tlink= snode->edittree->links.first; tlink; tlink= tlink->next) {
2720                         if (link!=tlink && tlink->tosock==link->tosock)
2721                                 break;
2722                 }
2723                 if (tlink) {
2724                         /* try to move the existing link to the next available socket */
2725                         if (tlink->tonode) {
2726                                 /* is there a free input socket with the target type? */
2727                                 for (sock= tlink->tonode->inputs.first; sock; sock= sock->next) {
2728                                         if (sock->type==tlink->tosock->type)
2729                                                 if (nodeCountSocketLinks(snode->edittree, sock) < sock->limit)
2730                                                         break;
2731                                 }
2732                                 if (sock) {
2733                                         tlink->tosock= sock;
2734                                         sock->flag &= ~SOCK_HIDDEN;
2735                                 }
2736                                 else {
2737                                         nodeRemLink(snode->edittree, tlink);
2738                                 }
2739                         }
2740                         else
2741                                 nodeRemLink(snode->edittree, tlink);
2742                         
2743                         snode->edittree->update |= NTREE_UPDATE_LINKS;
2744                 }
2745         }
2746 }
2747
2748 /* loop that adds a nodelink, called by function below  */
2749 /* in_out = starting socket */
2750 static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
2751 {
2752         SpaceNode *snode= CTX_wm_space_node(C);
2753         ARegion *ar= CTX_wm_region(C);
2754         bNodeLinkDrag *nldrag= op->customdata;
2755         bNodeTree *ntree = snode->edittree;
2756         bNode *tnode;
2757         bNodeSocket *tsock= NULL;
2758         bNodeLink *link;
2759         LinkData *linkdata;
2760         int in_out;
2761
2762         in_out = nldrag->in_out;
2763         
2764         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
2765                                                          &snode->mx, &snode->my);
2766
2767         switch (event->type) {
2768                 case MOUSEMOVE:
2769                         
2770                         if (in_out==SOCK_OUT) {
2771                                 if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
2772                                         for (linkdata=nldrag->links.first; linkdata; linkdata=linkdata->next) {
2773                                                 link = linkdata->data;
2774                                                 
2775                                                 /* skip if this is already the target socket */
2776                                                 if (link->tosock == tsock)
2777                                                         continue;
2778                                                 /* skip if socket is on the same node as the fromsock */
2779                                                 if (tnode && link->fromnode == tnode)
2780                                                         continue;
2781                                                 
2782                                                 /* attach links to the socket */
2783                                                 link->tonode = tnode;
2784                                                 link->tosock = tsock;
2785                                                 /* add it to the node tree temporarily */
2786                                                 if (BLI_findindex(&ntree->links, link) < 0)
2787                                                         BLI_addtail(&ntree->links, link);
2788                                                 
2789                                                 ntree->update |= NTREE_UPDATE_LINKS;
2790                                         }
2791                                         ntreeUpdateTree(ntree);
2792                                 }
2793                                 else {
2794                                         int do_update = FALSE;
2795                                         for (linkdata=nldrag->links.first; linkdata; linkdata=linkdata->next) {
2796                                                 link = linkdata->data;
2797                                                 
2798                                                 if (link->tonode || link->tosock) {
2799                                                         BLI_remlink(&ntree->links, link);
2800                                                         link->prev = link->next = NULL;
2801                                                         link->tonode= NULL;
2802                                                         link->tosock= NULL;
2803                                                         
2804                                                         ntree->update |= NTREE_UPDATE_LINKS;
2805                                                         do_update = TRUE;
2806                                                 }
2807                                         }
2808                                         if (do_update) {
2809                                                 ntreeUpdateTree(ntree);
2810                                         }
2811                                 }
2812                         }
2813                         else {
2814                                 if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
2815                                         for (linkdata=nldrag->links.first; linkdata; linkdata=linkdata->next) {
2816                                                 link = linkdata->data;
2817                                                 
2818                                                 /* skip if this is already the target socket */
2819                                                 if (link->fromsock == tsock)
2820                                                         continue;
2821                                                 /* skip if socket is on the same node as the fromsock */
2822                                                 if (tnode && link->tonode == tnode)
2823                                                         continue;
2824                                                 
2825                                                 /* attach links to the socket */
2826                                                 link->fromnode = tnode;
2827                                                 link->fromsock = tsock;
2828                                                 /* add it to the node tree temporarily */
2829                                                 if (BLI_findindex(&ntree->links, link) < 0)
2830                                                         BLI_addtail(&ntree->links, link);
2831                                                 
2832                                                 ntree->update |= NTREE_UPDATE_LINKS;
2833                                         }
2834                                         ntreeUpdateTree(ntree);
2835                                 }
2836                                 else {
2837                                         int do_update = FALSE;
2838                                         for (linkdata=nldrag->links.first; linkdata; linkdata=linkdata->next) {
2839                                                 link = linkdata->data;
2840                                                 
2841                                                 if (link->fromnode || link->fromsock) {
2842                                                         BLI_remlink(&ntree->links, link);
2843                                                         link->prev = link->next = NULL;
2844                                                         link->fromnode= NULL;
2845                                                         link->fromsock= NULL;
2846                                                         
2847                                                         ntree->update |= NTREE_UPDATE_LINKS;
2848                                                         do_update = TRUE;
2849                                                 }
2850                                         }
2851                                         if (do_update) {
2852                                                 ntreeUpdateTree(ntree);
2853                                         }
2854                                 }
2855                         }
2856                         
2857                         ED_region_tag_redraw(ar);
2858                         break;
2859                         
2860                 case LEFTMOUSE:
2861                 case RIGHTMOUSE:
2862                 case MIDDLEMOUSE: {
2863                         for (linkdata=nldrag->links.first; linkdata; linkdata=linkdata->next) {
2864                                 link = linkdata->data;
2865                                 
2866                                 if (link->tosock && link->fromsock) {
2867                                         /* send changed events for original tonode and new */
2868                                         if (link->tonode)
2869                                                 snode_update(snode, link->tonode);
2870                                         
2871                                         /* we might need to remove a link */
2872                                         if (in_out==SOCK_OUT)
2873                                                 node_remove_extra_links(snode, link->tosock, link);
2874                                         
2875                                         /* when linking to group outputs, update the socket type */
2876                                         /* XXX this should all be part of a generic update system */
2877                                         if (!link->tonode) {
2878                                                 if (link->tosock->type != link->fromsock->type)
2879                                                         nodeSocketSetType(link->tosock, link->fromsock->type);
2880                                         }
2881                                 }
2882                                 else if (outside_group_rect(snode) && (link->tonode || link->fromnode)) {
2883                                         /* automatically add new group socket */
2884                                         if (link->tonode && link->tosock) {
2885                                                 link->fromsock = node_group_expose_socket(ntree, link->tosock, SOCK_IN);
2886                                                 link->fromnode = NULL;
2887                                                 if (BLI_findindex(&ntree->links, link) < 0)
2888                                                         BLI_addtail(&ntree->links, link);
2889                                                 
2890                                                 ntree->update |= NTREE_UPDATE_GROUP_IN | NTREE_UPDATE_LINKS;
2891                                         }
2892                                         else if (link->fromnode && link->fromsock) {
2893                                                 link->tosock = node_group_expose_socket(ntree, link->fromsock, SOCK_OUT);
2894                                                 link->tonode = NULL;
2895                                                 if (BLI_findindex(&ntree->links, link) < 0)
2896                                                         BLI_addtail(&ntree->links, link);
2897                                                 
2898                                                 ntree->update |= NTREE_UPDATE_GROUP_OUT | NTREE_UPDATE_LINKS;
2899                                         }
2900                                 }
2901                                 else
2902                                         nodeRemLink(ntree, link);
2903                         }
2904                         
2905                         ntreeUpdateTree(ntree);
2906                         snode_notify(C, snode);
2907                         snode_dag_update(C, snode);
2908                         
2909                         BLI_remlink(&snode->linkdrag, nldrag);
2910                         /* links->data pointers are either held by the tree or freed already */
2911                         BLI_freelistN(&nldrag->links);
2912                         MEM_freeN(nldrag);
2913                         
2914                         return OPERATOR_FINISHED;
2915                 }
2916         }
2917         
2918         return OPERATOR_RUNNING_MODAL;
2919 }
2920
2921 /* return 1 when socket clicked */
2922 static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
2923 {
2924         bNode *node;
2925         bNodeSocket *sock;
2926         bNodeLink *link, *link_next, *oplink;
2927         bNodeLinkDrag *nldrag = NULL;
2928         LinkData *linkdata;
2929         int num_links;
2930         
2931         /* output indicated? */
2932         if (node_find_indicated_socket(snode, &node, &sock, SOCK_OUT)) {
2933                 nldrag= MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
2934                 
2935                 num_links = nodeCountSocketLinks(snode->edittree, sock);
2936                 if (num_links > 0 && (num_links >= sock->limit || detach)) {
2937                         /* dragged links are fixed on input side */
2938                         nldrag->in_out = SOCK_IN;
2939                         /* detach current links and store them in the operator data */
2940                         for (link= snode->edittree->links.first; link; link= link_next) {
2941                                 link_next = link->next;
2942                                 if (link->fromsock==sock) {
2943                                         linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
2944                                         linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
2945                                         *oplink = *link;
2946                                         oplink->next = oplink->prev = NULL;
2947                                         BLI_addtail(&nldrag->links, linkdata);
2948                                         nodeRemLink(snode->edittree, link);
2949                                 }
2950                         }
2951                 }
2952                 else {
2953                         /* dragged links are fixed on output side */
2954                         nldrag->in_out = SOCK_OUT;
2955                         /* create a new link */
2956                         linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
2957                         linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
2958                         oplink->fromnode = node;
2959                         oplink->fromsock = sock;
2960                         BLI_addtail(&nldrag->links, linkdata);
2961                 }
2962         }
2963         /* or an input? */
2964         else if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN)) {
2965                 nldrag= MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
2966                 
2967                 num_links = nodeCountSocketLinks(snode->edittree, sock);
2968                 if (num_links > 0 && (num_links >= sock->limit || detach)) {
2969                         /* dragged links are fixed on output side */
2970                         nldrag->in_out = SOCK_OUT;
2971                         /* detach current links and store them in the operator data */
2972                         for (link= snode->edittree->links.first; link; link= link_next) {
2973                                 link_next = link->next;
2974                                 if (link->tosock==sock) {
2975                                         linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
2976                                         linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
2977                                         *oplink = *link;
2978                                         oplink->next = oplink->prev = NULL;
2979                                         BLI_addtail(&nldrag->links, linkdata);
2980                                         nodeRemLink(snode->edittree, link);
2981                                         
2982                                         /* send changed event to original link->tonode */
2983                                         if (node)
2984                                                 snode_update(snode, node);
2985                                 }
2986                         }
2987                 }
2988                 else {
2989                         /* dragged links are fixed on input side */
2990                         nldrag->in_out = SOCK_IN;
2991                         /* create a new link */
2992                         linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
2993                         linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
2994                         oplink->tonode = node;
2995                         oplink->tosock = sock;
2996                         BLI_addtail(&nldrag->links, linkdata);
2997                 }
2998         }
2999         
3000         return nldrag;
3001 }
3002
3003 static int node_link_invoke(bContext *C, wmOperator *op, wmEvent *event)
3004 {
3005         SpaceNode *snode= CTX_wm_space_node(C);
3006         ARegion *ar= CTX_wm_region(C);
3007         bNodeLinkDrag *nldrag;
3008         int detach = RNA_boolean_get(op->ptr, "detach");
3009         
3010         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
3011                                                          &snode->mx, &snode->my);
3012
3013         ED_preview_kill_jobs(C);
3014
3015         nldrag = node_link_init(snode, detach);
3016         
3017         if (nldrag) {
3018                 op->customdata= nldrag;
3019                 BLI_addtail(&snode->linkdrag, nldrag);
3020                 
3021                 /* add modal handler */
3022                 WM_event_add_modal_handler(C, op);
3023                 
3024                 return OPERATOR_RUNNING_MODAL;
3025         }
3026         else
3027                 return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH;
3028 }
3029
3030 static int node_link_cancel(bContext *C, wmOperator *op)
3031 {
3032         SpaceNode *snode= CTX_wm_space_node(C);
3033         bNodeLinkDrag *nldrag= op->customdata;
3034         
3035         BLI_remlink(&snode->linkdrag, nldrag);
3036         
3037         BLI_freelistN(&nldrag->links);
3038         MEM_freeN(nldrag);
3039         
3040         return OPERATOR_CANCELLED;
3041 }
3042
3043 void NODE_OT_link(wmOperatorType *ot)
3044 {
3045         /* identifiers */
3046         ot->name = "Link Nodes";
3047         ot->idname = "NODE_OT_link";
3048         ot->description = "Use the mouse to create a link between two nodes";
3049         
3050         /* api callbacks */
3051         ot->invoke = node_link_invoke;
3052         ot->modal = node_link_modal;
3053 //      ot->exec = node_link_exec;
3054         ot->poll = ED_operator_node_active;