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