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