Fix for bug #8555: geometry node front/bake was broken.
[blender.git] / source / blender / src / editnode.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2005 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): David Millan Escriva, Juho Vepsäläinen
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <math.h>
33 #include <string.h>
34
35 #include "MEM_guardedalloc.h"
36
37 #include "DNA_action_types.h"
38 #include "DNA_color_types.h"
39 #include "DNA_image_types.h"
40 #include "DNA_ipo_types.h"
41 #include "DNA_object_types.h"
42 #include "DNA_material_types.h"
43 #include "DNA_node_types.h"
44 #include "DNA_space_types.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_userdef_types.h"
48
49 #include "BKE_colortools.h"
50 #include "BKE_global.h"
51 #include "BKE_image.h"
52 #include "BKE_library.h"
53 #include "BKE_main.h"
54 #include "BKE_node.h"
55 #include "BKE_material.h"
56 #include "BKE_scene.h"
57 #include "BKE_utildefines.h"
58
59 #include "BIF_cursors.h"
60 #include "BIF_editview.h"
61 #include "BIF_gl.h"
62 #include "BIF_graphics.h"
63 #include "BIF_imasel.h"
64 #include "BIF_interface.h"
65 #include "BIF_mywindow.h"
66 #include "BIF_previewrender.h"
67 #include "BIF_resources.h"
68 #include "BIF_renderwin.h"
69 #include "BIF_space.h"
70 #include "BIF_screen.h"
71 #include "BIF_toolbox.h"
72
73 #include "BSE_drawipo.h"
74 #include "BSE_edit.h"
75 #include "BSE_filesel.h"
76 #include "BSE_headerbuttons.h"
77 #include "BSE_node.h"
78
79 #include "BLI_blenlib.h"
80 #include "BLI_arithb.h"
81
82 #include "BDR_editobject.h"
83
84 #include "RE_pipeline.h"
85 #include "IMB_imbuf_types.h"
86
87 #include "blendef.h"
88 #include "butspace.h"
89 #include "PIL_time.h"
90 #include "mydevice.h"
91 #include "winlay.h"
92
93
94 /* currently called from BIF_preview_changed */
95 void snode_tag_dirty(SpaceNode *snode)
96 {
97         bNode *node;
98         
99         if(snode->treetype==NTREE_SHADER) {
100                 if(snode->nodetree) {
101                         for(node= snode->nodetree->nodes.first; node; node= node->next) {
102                                 if(node->type==SH_NODE_OUTPUT)
103                                         node->lasty= 0;
104                         }
105                         snode->flag |= SNODE_DO_PREVIEW;        /* this adds an afterqueue on a redraw, to allow button previews to work first */
106                 }
107         }
108         allqueue(REDRAWNODE, 1);
109 }
110
111 static void shader_node_previewrender(ScrArea *sa, SpaceNode *snode)
112 {
113         bNode *node;
114         
115         if(snode->id==NULL) return;
116         if( ((Material *)snode->id )->use_nodes==0 ) return;
117
118         for(node= snode->nodetree->nodes.first; node; node= node->next) {
119                 if(node->type==SH_NODE_OUTPUT) {
120                         if(node->flag & NODE_DO_OUTPUT) {
121                                 if(node->lasty<PREVIEW_RENDERSIZE-2) {
122                                         RenderInfo ri;  
123 //                                      int test= node->lasty;
124                                         
125                                         ri.curtile = 0;
126                                         ri.tottile = 0;
127                                         ri.rect = NULL;
128                                         ri.pr_rectx = PREVIEW_RENDERSIZE;
129                                         ri.pr_recty = PREVIEW_RENDERSIZE;
130                                         
131                                         BIF_previewrender(snode->id, &ri, NULL, PR_DO_RENDER);  /* sends redraw event */
132                                         if(ri.rect) MEM_freeN(ri.rect);
133                                         
134                                         /* when not finished... */
135                                         if(ri.curtile<ri.tottile)
136                                                 addafterqueue(sa->win, RENDERPREVIEW, 1);
137 //                                      if(test!=node->lasty)
138 //                                              printf("node rendered to %d\n", node->lasty);
139
140                                         break;
141                                 }
142                         }
143                 }
144         }
145 }
146
147
148 static void snode_handle_recalc(SpaceNode *snode)
149 {
150         if(snode->treetype==NTREE_SHADER) {
151                 BIF_preview_changed(ID_MA);      /* signals buttons windows and node editors */
152         }
153         else if(snode->treetype==NTREE_COMPOSIT) {
154                 if(G.scene->use_nodes) {
155                         snode->nodetree->timecursor= set_timecursor;
156                         G.afbreek= 0;
157                         snode->nodetree->test_break= blender_test_break;
158                         
159                         BIF_store_spare();
160                         
161                         ntreeCompositExecTree(snode->nodetree, &G.scene->r, 1); /* 1 is do_previews */
162                         
163                         snode->nodetree->timecursor= NULL;
164                         snode->nodetree->test_break= NULL;
165                         waitcursor(0);
166                         
167                         allqueue(REDRAWNODE, 1);
168                         allqueue(REDRAWIMAGE, 1);
169                         if(G.scene->r.scemode & R_DOCOMP) {
170                                 BIF_redraw_render_rect();       /* seems to screwup display? */
171                                 mywinset(curarea->win);
172                         }
173                 }
174         }
175 }
176
177 static void shader_node_event(SpaceNode *snode, short event)
178 {
179         switch(event) {
180                 case B_REDR:
181                         allqueue(REDRAWNODE, 1);
182                         break;
183                 default:
184                         /* B_NODE_EXEC */
185                         snode_handle_recalc(snode);
186                         break;
187                         
188         }
189 }
190
191 static void load_node_image(char *str)  /* called from fileselect */
192 {
193         SpaceNode *snode= curarea->spacedata.first;
194         bNode *node= nodeGetActive(snode->edittree);
195         Image *ima= NULL;
196         
197         ima= BKE_add_image_file(str);
198         if(ima) {
199                 if(node->id)
200                         node->id->us--;
201                 
202                 node->id= &ima->id;
203                 id_us_plus(node->id);
204
205                 BLI_strncpy(node->name, node->id->name+2, 21);
206                                    
207                 BKE_image_signal(ima, node->storage, IMA_SIGNAL_RELOAD);
208                 
209                 NodeTagChanged(snode->edittree, node);
210                 snode_handle_recalc(snode);
211                 allqueue(REDRAWNODE, 0); 
212         }
213 }
214
215 static void set_node_imagepath(char *str)       /* called from fileselect */
216 {
217         SpaceNode *snode= curarea->spacedata.first;
218         bNode *node= nodeGetActive(snode->edittree);
219         BLI_strncpy(((NodeImageFile *)node->storage)->name, str, sizeof( ((NodeImageFile *)node->storage)->name ));
220 }
221
222 static bNode *snode_get_editgroup(SpaceNode *snode)
223 {
224         bNode *gnode;
225         
226         /* get the groupnode */
227         for(gnode= snode->nodetree->nodes.first; gnode; gnode= gnode->next)
228                 if(gnode->flag & NODE_GROUP_EDIT)
229                         break;
230         return gnode;
231 }
232
233 /* node has to be of type 'render layers' */
234 /* is a bit clumsy copying renderdata here... scene nodes use render size of current render */
235 static void composite_node_render(SpaceNode *snode, bNode *node)
236 {
237         RenderData rd;
238         Scene *scene= NULL;
239         int scemode, actlay;
240         
241         /* the button press won't show up otherwise, button hilites disabled */
242         force_draw(0);
243         
244         if(node->id && node->id!=(ID *)G.scene) {
245                 scene= G.scene;
246                 set_scene_bg((Scene *)node->id);
247                 rd= G.scene->r;
248                 G.scene->r.xsch= scene->r.xsch;
249                 G.scene->r.ysch= scene->r.ysch;
250                 G.scene->r.size= scene->r.size;
251                 G.scene->r.mode &= ~(R_BORDER|R_DOCOMP);
252                 G.scene->r.mode |= scene->r.mode & R_BORDER;
253                 G.scene->r.border= scene->r.border;
254                 G.scene->r.cfra= scene->r.cfra;
255         }
256         
257         scemode= G.scene->r.scemode;
258         actlay= G.scene->r.actlay;
259         
260         G.scene->r.scemode |= R_SINGLE_LAYER;
261         G.scene->r.actlay= node->custom1;
262         
263         BIF_do_render(0);
264         
265         G.scene->r.scemode= scemode;
266         G.scene->r.actlay= actlay;
267
268         node->custom2= 0;
269         
270         if(scene) {
271                 G.scene->r= rd;
272                 set_scene_bg(scene);
273         }
274 }
275
276 static void composit_node_event(SpaceNode *snode, short event)
277 {
278         
279         switch(event) {
280                 case B_REDR:
281                         allqueue(REDRAWNODE, 1);
282                         break;
283                 case B_NODE_LOADIMAGE:
284                 {
285                         bNode *node= nodeGetActive(snode->edittree);
286                         char name[FILE_MAXDIR+FILE_MAXFILE];
287                         
288                         if(node->id)
289                                 strcpy(name, ((Image *)node->id)->name);
290                         else strcpy(name, U.textudir);
291                         if (G.qual & LR_CTRLKEY) {
292                                 activate_imageselect(FILE_SPECIAL, "SELECT IMAGE", name, load_node_image);
293                         } else {
294                                 activate_fileselect(FILE_SPECIAL, "SELECT IMAGE", name, load_node_image);
295                         }
296                         break;
297                 }
298                 case B_NODE_SETIMAGE:
299                 {
300                         bNode *node= nodeGetActive(snode->edittree);
301                         char name[FILE_MAXDIR+FILE_MAXFILE];
302                         
303                         strcpy(name, ((NodeImageFile *)node->storage)->name);
304                         if (G.qual & LR_CTRLKEY) {
305                                 activate_imageselect(FILE_SPECIAL, "SELECT OUTPUT DIR", name, set_node_imagepath);
306                         } else {
307                                 activate_fileselect(FILE_SPECIAL, "SELECT OUTPUT DIR", name, set_node_imagepath);
308                         }
309                         break;
310                 }
311                 case B_NODE_TREE_EXEC:
312                         snode_handle_recalc(snode);
313                         break;          
314                 default:
315                         /* B_NODE_EXEC */
316                 {
317                         bNode *node= BLI_findlink(&snode->edittree->nodes, event-B_NODE_EXEC);
318                         if(node) {
319                                 NodeTagChanged(snode->edittree, node);
320                                 /* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */
321                                 
322                                 /* not the best implementation of the world... but we need it to work now :) */
323                                 if(node->type==CMP_NODE_R_LAYERS && node->custom2) {
324                                         /* add event for this window (after render curarea can be changed) */
325                                         addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
326                                         
327                                         composite_node_render(snode, node);
328                                         snode_handle_recalc(snode);
329                                         
330                                         /* add another event, a render can go fullscreen and open new window */
331                                         addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
332                                 }
333                                 else {
334                                         node= snode_get_editgroup(snode);
335                                         if(node)
336                                                 NodeTagIDChanged(snode->nodetree, node->id);
337                                         
338                                         snode_handle_recalc(snode);
339                                 }
340                         }
341                 }                       
342         }
343 }
344
345
346 /* assumes nothing being done in ntree yet, sets the default in/out node */
347 /* called from shading buttons or header */
348 void node_shader_default(Material *ma)
349 {
350         bNode *in, *out;
351         bNodeSocket *fromsock, *tosock;
352         
353         /* but lets check it anyway */
354         if(ma->nodetree) {
355                 printf("error in shader initialize\n");
356                 return;
357         }
358         
359         ma->nodetree= ntreeAddTree(NTREE_SHADER);
360         
361         out= nodeAddNodeType(ma->nodetree, SH_NODE_OUTPUT, NULL, NULL);
362         out->locx= 300.0f; out->locy= 300.0f;
363         
364         in= nodeAddNodeType(ma->nodetree, SH_NODE_MATERIAL, NULL, NULL);
365         in->locx= 10.0f; in->locy= 300.0f;
366         nodeSetActive(ma->nodetree, in);
367         
368         /* only a link from color to color */
369         fromsock= in->outputs.first;
370         tosock= out->inputs.first;
371         nodeAddLink(ma->nodetree, in, fromsock, out, tosock);
372         
373         ntreeSolveOrder(ma->nodetree);  /* needed for pointers */
374 }
375
376 /* assumes nothing being done in ntree yet, sets the default in/out node */
377 /* called from shading buttons or header */
378 void node_composit_default(Scene *sce)
379 {
380         bNode *in, *out;
381         bNodeSocket *fromsock, *tosock;
382         
383         /* but lets check it anyway */
384         if(sce->nodetree) {
385                 printf("error in composit initialize\n");
386                 return;
387         }
388         
389         sce->nodetree= ntreeAddTree(NTREE_COMPOSIT);
390         
391         out= nodeAddNodeType(sce->nodetree, CMP_NODE_COMPOSITE, NULL, NULL);
392         out->locx= 300.0f; out->locy= 400.0f;
393         
394         in= nodeAddNodeType(sce->nodetree, CMP_NODE_R_LAYERS, NULL, NULL);
395         in->locx= 10.0f; in->locy= 400.0f;
396         nodeSetActive(sce->nodetree, in);
397         
398         /* links from color to color */
399         fromsock= in->outputs.first;
400         tosock= out->inputs.first;
401         nodeAddLink(sce->nodetree, in, fromsock, out, tosock);
402         
403         ntreeSolveOrder(sce->nodetree); /* needed for pointers */
404         
405         ntreeCompositForceHidden(sce->nodetree);
406 }
407
408 /* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
409 void snode_set_context(SpaceNode *snode)
410 {
411         Object *ob= OBACT;
412         bNode *node= NULL;
413         
414         snode->nodetree= NULL;
415         snode->id= snode->from= NULL;
416         
417         if(snode->treetype==NTREE_SHADER) {
418                 /* need active object, or we allow pinning... */
419                 if(ob) {
420                         Material *ma= give_current_material(ob, ob->actcol);
421                         if(ma) {
422                                 snode->from= material_from(ob, ob->actcol);
423                                 snode->id= &ma->id;
424                                 snode->nodetree= ma->nodetree;
425                         }
426                 }
427         }
428         else if(snode->treetype==NTREE_COMPOSIT) {
429                 snode->from= NULL;
430                 snode->id= &G.scene->id;
431                 
432                 /* bit clumsy but reliable way to see if we draw first time */
433                 if(snode->nodetree==NULL)
434                         ntreeCompositForceHidden(G.scene->nodetree);
435                 
436                 snode->nodetree= G.scene->nodetree;
437         }
438         
439         /* find editable group */
440         if(snode->nodetree)
441                 for(node= snode->nodetree->nodes.first; node; node= node->next)
442                         if(node->flag & NODE_GROUP_EDIT)
443                                 break;
444         
445         if(node && node->id)
446                 snode->edittree= (bNodeTree *)node->id;
447         else
448                 snode->edittree= snode->nodetree;
449 }
450
451 /* on activate image viewer, check if we show it */
452 static void node_active_image(Image *ima)
453 {
454         ScrArea *sa;
455         SpaceImage *sima= NULL;
456         
457         /* find an imagewindow showing render result */
458         for(sa=G.curscreen->areabase.first; sa; sa= sa->next) {
459                 if(sa->spacetype==SPACE_IMAGE) {
460                         sima= sa->spacedata.first;
461                         if(sima->image && sima->image->source!=IMA_SRC_VIEWER)
462                                 break;
463                 }
464         }
465         if(sa && sima) {
466                 sima->image= ima;
467                 scrarea_queue_winredraw(sa);
468                 scrarea_queue_headredraw(sa);
469         }
470 }
471
472
473 static void node_set_active(SpaceNode *snode, bNode *node)
474 {
475         
476         nodeSetActive(snode->edittree, node);
477         
478         if(node->type!=NODE_GROUP) {
479                 
480                 /* tree specific activate calls */
481                 if(snode->treetype==NTREE_SHADER) {
482                         
483                         /* when we select a material, active texture is cleared, for buttons */
484                         if(node->id && GS(node->id->name)==ID_MA)
485                                 nodeClearActiveID(snode->edittree, ID_TE);
486                         if(node->id)
487                                 BIF_preview_changed(-1);        /* temp hack to force texture preview to update */
488                         
489                         allqueue(REDRAWBUTSSHADING, 1);
490                         allqueue(REDRAWIPO, 0);
491                 }
492                 else if(snode->treetype==NTREE_COMPOSIT) {
493                         /* make active viewer, currently only 1 supported... */
494                         if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
495                                 bNode *tnode;
496                                 int was_output= node->flag & NODE_DO_OUTPUT;
497
498                                 for(tnode= snode->edittree->nodes.first; tnode; tnode= tnode->next)
499                                         if( ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
500                                                 tnode->flag &= ~NODE_DO_OUTPUT;
501                                 
502                                 node->flag |= NODE_DO_OUTPUT;
503                                 if(was_output==0) {
504                                         bNode *gnode;
505                                         
506                                         NodeTagChanged(snode->edittree, node);
507                                         
508                                         /* if inside group, tag entire group */
509                                         gnode= snode_get_editgroup(snode);
510                                         if(gnode)
511                                                 NodeTagIDChanged(snode->nodetree, gnode->id);
512                                         
513                                         snode_handle_recalc(snode);
514                                 }
515                                 
516                                 /* addnode() doesnt link this yet... */
517                                 node->id= (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
518                         }
519                         else if(node->type==CMP_NODE_IMAGE) {
520                                 if(node->id)
521                                         node_active_image((Image *)node->id);
522                         }
523                         else if(node->type==CMP_NODE_R_LAYERS) {
524                                 if(node->id==NULL || node->id==(ID *)G.scene) {
525                                         G.scene->r.actlay= node->custom1;
526                                         allqueue(REDRAWBUTSSCENE, 0);
527                                 }
528                         }
529                 }
530         }
531 }
532
533 void snode_make_group_editable(SpaceNode *snode, bNode *gnode)
534 {
535         bNode *node;
536         
537         /* make sure nothing has group editing on */
538         for(node= snode->nodetree->nodes.first; node; node= node->next)
539                 node->flag &= ~NODE_GROUP_EDIT;
540         
541         if(gnode==NULL) {
542                 /* with NULL argument we do a toggle */
543                 if(snode->edittree==snode->nodetree)
544                         gnode= nodeGetActive(snode->nodetree);
545         }
546         
547         if(gnode && gnode->type==NODE_GROUP && gnode->id) {
548                 if(gnode->id->lib) {
549                         if(okee("Make Group Local"))
550                                 ntreeMakeLocal((bNodeTree *)gnode->id);
551                         else
552                                 return;
553                 }
554                 gnode->flag |= NODE_GROUP_EDIT;
555                 snode->edittree= (bNodeTree *)gnode->id;
556                 
557                 /* deselect all other nodes, so we can also do grabbing of entire subtree */
558                 for(node= snode->nodetree->nodes.first; node; node= node->next)
559                         node->flag &= ~SELECT;
560                 gnode->flag |= SELECT;
561                 
562         }
563         else 
564                 snode->edittree= snode->nodetree;
565         
566         ntreeSolveOrder(snode->nodetree);
567         
568         /* finally send out events for new active node */
569         if(snode->treetype==NTREE_SHADER) {
570                 allqueue(REDRAWBUTSSHADING, 0);
571                 
572                 BIF_preview_changed(-1);        /* temp hack to force texture preview to update */
573         }
574         
575         allqueue(REDRAWNODE, 0);
576 }
577
578 void node_ungroup(SpaceNode *snode)
579 {
580         bNode *gnode;
581
582         /* are we inside of a group? */
583         gnode= snode_get_editgroup(snode);
584         if(gnode)
585                 snode_make_group_editable(snode, NULL);
586         
587         gnode= nodeGetActive(snode->edittree);
588         if(gnode==NULL) return;
589         
590         if(gnode->type!=NODE_GROUP)
591                 error("Not a group");
592         else {
593                 if(nodeGroupUnGroup(snode->edittree, gnode)) {
594                         
595                         BIF_undo_push("Deselect all nodes");
596                         allqueue(REDRAWNODE, 0);
597                 }
598                 else
599                         error("Can't ungroup");
600         }
601 }
602
603 /* when links in groups change, inputs/outputs change, nodes added/deleted... */
604 static void snode_verify_groups(SpaceNode *snode)
605 {
606         bNode *gnode;
607         
608         gnode= snode_get_editgroup(snode);
609         
610         /* does all materials */
611         if(gnode)
612                 nodeVerifyGroup((bNodeTree *)gnode->id);
613         
614 }
615
616 static void node_addgroup(SpaceNode *snode)
617 {
618         bNodeTree *ngroup;
619         int tot= 0, offs, val;
620         char *strp;
621         
622         if(snode->edittree!=snode->nodetree) {
623                 error("Can not add a Group in a Group");
624                 return;
625         }
626         
627         /* construct menu with choices */
628         for(ngroup= G.main->nodetree.first; ngroup; ngroup= ngroup->id.next) {
629                 if(ngroup->type==snode->treetype)
630                         tot++;
631         }
632         if(tot==0) {
633                 error("No groups available in database");
634                 return;
635         }
636         strp= MEM_mallocN(32*tot+32, "menu");
637         strcpy(strp, "Add Group %t");
638         offs= strlen(strp);
639         
640         for(tot=0, ngroup= G.main->nodetree.first; ngroup; ngroup= ngroup->id.next, tot++) {
641                 if(ngroup->type==snode->treetype)
642                         offs+= sprintf(strp+offs, "|%s %%x%d", ngroup->id.name+2, tot);
643         }       
644         
645         val= pupmenu(strp);
646         if(val>=0) {
647                 ngroup= BLI_findlink(&G.main->nodetree, val);
648                 if(ngroup) {
649                         bNode *node= nodeAddNodeType(snode->edittree, NODE_GROUP, ngroup, NULL);
650                         
651                         /* generics */
652                         if(node) {
653                                 float locx, locy;
654                                 short mval[2];
655
656                                 node_deselectall(snode, 0);
657                                 
658                                 getmouseco_areawin(mval);
659                                 areamouseco_to_ipoco(G.v2d, mval, &locx, &locy);
660                                 
661                                 node->locx= locx;
662                                 node->locy= locy + 60.0f;               // arbitrary.. so its visible
663                                 node->flag |= SELECT;
664                                 
665                                 id_us_plus(node->id);
666                                 
667                                 node_set_active(snode, node);
668                                 BIF_undo_push("Add Node");
669                         }
670                 }                       
671         }
672         MEM_freeN(strp);
673 }
674
675
676 /* ************************** Node generic ************** */
677
678 /* allows to walk the list in order of visibility */
679 static bNode *next_node(bNodeTree *ntree)
680 {
681         static bNode *current=NULL, *last= NULL;
682         
683         if(ntree) {
684                 /* set current to the first selected node */
685                 for(current= ntree->nodes.last; current; current= current->prev)
686                         if(current->flag & NODE_SELECT)
687                                 break;
688                 
689                 /* set last to the first unselected node */
690                 for(last= ntree->nodes.last; last; last= last->prev)
691                         if((last->flag & NODE_SELECT)==0)
692                                 break;
693                 
694                 if(current==NULL)
695                         current= last;
696                 
697                 return NULL;
698         }
699         /* no nodes, or we are ready */
700         if(current==NULL)
701                 return NULL;
702         
703         /* now we walk the list backwards, but we always return current */
704         if(current->flag & NODE_SELECT) {
705                 bNode *node= current;
706                 
707                 /* find previous selected */
708                 current= current->prev;
709                 while(current && (current->flag & NODE_SELECT)==0)
710                         current= current->prev;
711                 
712                 /* find first unselected */
713                 if(current==NULL)
714                         current= last;
715                 
716                 return node;
717         }
718         else {
719                 bNode *node= current;
720                 
721                 /* find previous unselected */
722                 current= current->prev;
723                 while(current && (current->flag & NODE_SELECT))
724                         current= current->prev;
725                 
726                 return node;
727         }
728         
729         return NULL;
730 }
731
732 /* is rct in visible part of node? */
733 static bNode *visible_node(SpaceNode *snode, rctf *rct)
734 {
735         bNode *tnode;
736         
737         for(next_node(snode->edittree); (tnode=next_node(NULL));) {
738                 if(BLI_isect_rctf(&tnode->totr, rct, NULL))
739                         break;
740         }
741         return tnode;
742 }
743
744 void snode_home(ScrArea *sa, SpaceNode *snode)
745 {
746         bNode *node;
747         int first= 1;
748         
749         snode->v2d.cur.xmin= snode->v2d.cur.ymin= 0.0f;
750         snode->v2d.cur.xmax= sa->winx;
751         snode->v2d.cur.xmax= sa->winy;
752         
753         if(snode->edittree) {
754                 for(node= snode->edittree->nodes.first; node; node= node->next) {
755                         if(first) {
756                                 first= 0;
757                                 snode->v2d.cur= node->totr;
758                         }
759                         else {
760                                 BLI_union_rctf(&snode->v2d.cur, &node->totr);
761                         }
762                 }
763         }
764         snode->v2d.tot= snode->v2d.cur;
765         
766         snode->xof = snode->yof = 0.0;
767         
768         test_view2d(G.v2d, sa->winx, sa->winy);
769         
770 }
771
772 void snode_zoom_out(ScrArea *sa)
773 {
774         float dx;
775         
776         dx= (float)(0.15*(G.v2d->cur.xmax-G.v2d->cur.xmin));
777         G.v2d->cur.xmin-= dx;
778         G.v2d->cur.xmax+= dx;
779         dx= (float)(0.15*(G.v2d->cur.ymax-G.v2d->cur.ymin));
780         G.v2d->cur.ymin-= dx;
781         G.v2d->cur.ymax+= dx;
782         test_view2d(G.v2d, sa->winx, sa->winy);
783 }
784
785 void snode_zoom_in(ScrArea *sa)
786 {
787         float dx;
788         
789         dx= (float)(0.1154*(G.v2d->cur.xmax-G.v2d->cur.xmin));
790         G.v2d->cur.xmin+= dx;
791         G.v2d->cur.xmax-= dx;
792         dx= (float)(0.1154*(G.v2d->cur.ymax-G.v2d->cur.ymin));
793         G.v2d->cur.ymin+= dx;
794         G.v2d->cur.ymax-= dx;
795         test_view2d(G.v2d, sa->winx, sa->winy);
796 }
797
798 static void snode_bg_viewmove(SpaceNode *snode)
799 {
800         ScrArea *sa;
801         Image *ima;
802         ImBuf *ibuf;
803         Window *win;
804         short mval[2], mvalo[2];
805         short rectx, recty, xmin, xmax, ymin, ymax, pad;
806         int oldcursor;
807         
808         ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
809         ibuf= BKE_image_get_ibuf(ima, NULL);
810         
811         sa = snode->area;
812         
813         if(ibuf) {
814                 rectx = ibuf->x;
815                 recty = ibuf->y;
816         } else {
817                 rectx = recty = 1;
818         }
819         
820         pad = 10;
821         xmin = -(sa->winx/2) - rectx/2 + pad;
822         xmax = sa->winx/2 + rectx/2 - pad;
823         ymin = -(sa->winy/2) - recty/2 + pad;
824         ymax = sa->winy/2 + recty/2 - pad;
825         
826         getmouseco_sc(mvalo);
827         
828         /* store the old cursor to temporarily change it */
829         oldcursor=get_cursor();
830         win=winlay_get_active_window();
831         
832         SetBlenderCursor(BC_NSEW_SCROLLCURSOR);
833         
834         while(get_mbut()&(L_MOUSE|M_MOUSE)) {
835                 
836                 getmouseco_sc(mval);
837                 
838                 if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
839                         
840                         snode->xof -= (mvalo[0]-mval[0]);
841                         snode->yof -= (mvalo[1]-mval[1]);
842                         
843                         /* prevent dragging image outside of the window and losing it! */
844                         CLAMP(snode->xof, xmin, xmax);
845                         CLAMP(snode->yof, ymin, ymax);
846                         
847                         mvalo[0]= mval[0];
848                         mvalo[1]= mval[1];
849                         
850                         scrarea_do_windraw(curarea);
851                         screen_swapbuffers();
852                 }
853                 else BIF_wait_for_statechange();
854         }
855         
856         window_set_cursor(win, oldcursor);
857 }
858
859 static void reset_sel_socket(SpaceNode *snode, int in_out)
860 {
861         bNode *node;
862         bNodeSocket *sock;
863         
864         for(node= snode->edittree->nodes.first; node; node= node->next) {
865                 if(in_out & SOCK_IN) {
866                         for(sock= node->inputs.first; sock; sock= sock->next)
867                                 if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL;
868                 }
869                 if(in_out & SOCK_OUT) {
870                         for(sock= node->outputs.first; sock; sock= sock->next)
871                                 if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL;
872                 }
873         }
874 }
875
876 /* checks mouse position, and returns found node/socket */
877 /* type is SOCK_IN and/or SOCK_OUT */
878 static int find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, int in_out)
879 {
880         bNode *node;
881         bNodeSocket *sock;
882         rctf rect;
883         short mval[2];
884         
885         getmouseco_areawin(mval);
886         
887         /* check if we click in a socket */
888         for(node= snode->edittree->nodes.first; node; node= node->next) {
889         
890                 areamouseco_to_ipoco(G.v2d, mval, &rect.xmin, &rect.ymin);
891                 
892                 rect.xmin -= NODE_SOCKSIZE+3;
893                 rect.ymin -= NODE_SOCKSIZE+3;
894                 rect.xmax = rect.xmin + 2*NODE_SOCKSIZE+6;
895                 rect.ymax = rect.ymin + 2*NODE_SOCKSIZE+6;
896                 
897                 if (!(node->flag & NODE_HIDDEN)) {
898                         /* extra padding inside and out - allow dragging on the text areas too */
899                         if (in_out == SOCK_IN) {
900                                 rect.xmax += NODE_SOCKSIZE;
901                                 rect.xmin -= NODE_SOCKSIZE*4;
902                         } else if (in_out == SOCK_OUT) {
903                                 rect.xmax += NODE_SOCKSIZE*4;
904                                 rect.xmin -= NODE_SOCKSIZE;
905                         }
906                 }
907                         
908                 if(in_out & SOCK_IN) {
909                         for(sock= node->inputs.first; sock; sock= sock->next) {
910                                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
911                                         if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
912                                                 if(node == visible_node(snode, &rect)) {
913                                                         *nodep= node;
914                                                         *sockp= sock;
915                                                         return 1;
916                                                 }
917                                         }
918                                 }
919                         }
920                 }
921                 if(in_out & SOCK_OUT) {
922                         for(sock= node->outputs.first; sock; sock= sock->next) {
923                                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
924                                         if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
925                                                 if(node == visible_node(snode, &rect)) {
926                                                         *nodep= node;
927                                                         *sockp= sock;
928                                                         return 1;
929                                                 }
930                                         }
931                                 }
932                         }
933                 }
934         }
935         return 0;
936 }
937
938 /* ********************* transform ****************** */
939
940 /* releases on event, only intern (for extern see below) */
941 /* we need argument ntree to allow operations on edittree or nodetree */
942 static void transform_nodes(bNodeTree *ntree, char mode, char *undostr)
943 {
944         bNode *node;
945         float mxstart, mystart, mx, my, *oldlocs, *ol;
946         int cont=1, tot=0, cancel=0, firsttime=1;
947         short mval[2], mvalo[2];
948         
949         /* count total */
950         for(node= ntree->nodes.first; node; node= node->next)
951                 if(node->flag & SELECT) tot++;
952         
953         if(tot==0) return;
954         
955         /* store oldlocs */
956         ol= oldlocs= MEM_mallocN(sizeof(float)*2*tot, "oldlocs transform");
957         for(node= ntree->nodes.first; node; node= node->next) {
958                 if(node->flag & SELECT) {
959                         ol[0]= node->locx; ol[1]= node->locy;
960                         ol+= 2;
961                 }
962         }
963         
964         getmouseco_areawin(mvalo);
965         areamouseco_to_ipoco(G.v2d, mvalo, &mxstart, &mystart);
966         
967         while(cont) {
968                 
969                 getmouseco_areawin(mval);
970                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || firsttime) {
971
972                         firsttime= 0;
973                         
974                         areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
975                         mvalo[0]= mval[0];
976                         mvalo[1]= mval[1];
977                         
978                         for(ol= oldlocs, node= ntree->nodes.first; node; node= node->next) {
979                                 if(node->flag & SELECT) {
980                                         node->locx= ol[0] + mx-mxstart;
981                                         node->locy= ol[1] + my-mystart;
982                                         ol+= 2;
983                                 }
984                         }
985                         
986                         force_draw(0);
987                 }
988                 else
989                         PIL_sleep_ms(10);
990                 
991                 while (qtest()) {
992                         short val;
993                         unsigned short event= extern_qread(&val);
994                         
995                         switch (event) {
996                                 case LEFTMOUSE:
997                                 case SPACEKEY:
998                                 case RETKEY:
999                                         cont=0;
1000                                         break;
1001                                 case ESCKEY:
1002                                 case RIGHTMOUSE:
1003                                         if(val) {
1004                                                 cancel=1;
1005                                                 cont=0;
1006                                         }
1007                                         break;
1008                                 default:
1009                                         if(val) arrows_move_cursor(event);
1010                                         break;
1011                         }
1012                 }
1013                 
1014         }
1015         
1016         if(cancel) {
1017                 for(ol= oldlocs, node= ntree->nodes.first; node; node= node->next) {
1018                         if(node->flag & SELECT) {
1019                                 node->locx= ol[0];
1020                                 node->locy= ol[1];
1021                                 ol+= 2;
1022                         }
1023                 }
1024                 
1025         }
1026         else
1027                 BIF_undo_push(undostr);
1028         
1029         allqueue(REDRAWNODE, 1);
1030         MEM_freeN(oldlocs);
1031 }
1032
1033 /* external call, also for callback */
1034 void node_transform_ext(int mode, int unused)
1035 {
1036         SpaceNode *snode= curarea->spacedata.first;
1037         
1038         transform_nodes(snode->edittree, 'g', "Move Node");
1039 }
1040
1041
1042 /* releases on event, only 1 node */
1043 static void scale_node(SpaceNode *snode, bNode *node)
1044 {
1045         float mxstart, mystart, mx, my, oldwidth;
1046         int cont=1, cancel=0;
1047         short mval[2], mvalo[2];
1048         
1049         /* store old */
1050         if(node->flag & NODE_HIDDEN)
1051                 oldwidth= node->miniwidth;
1052         else
1053                 oldwidth= node->width;
1054                 
1055         getmouseco_areawin(mvalo);
1056         areamouseco_to_ipoco(G.v2d, mvalo, &mxstart, &mystart);
1057         
1058         while(cont) {
1059                 
1060                 getmouseco_areawin(mval);
1061                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
1062                         
1063                         areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
1064                         mvalo[0]= mval[0];
1065                         mvalo[1]= mval[1];
1066                         
1067                         if(node->flag & NODE_HIDDEN) {
1068                                 node->miniwidth= oldwidth + mx-mxstart;
1069                                 CLAMP(node->miniwidth, 0.0f, 100.0f);
1070                         }
1071                         else {
1072                                 node->width= oldwidth + mx-mxstart;
1073                                 CLAMP(node->width, node->typeinfo->minwidth, node->typeinfo->maxwidth);
1074                         }
1075                         
1076                         force_draw(0);
1077                 }
1078                 else
1079                         PIL_sleep_ms(10);
1080                 
1081                 while (qtest()) {
1082                         short val;
1083                         unsigned short event= extern_qread(&val);
1084                         
1085                         switch (event) {
1086                                 case LEFTMOUSE:
1087                                 case SPACEKEY:
1088                                 case RETKEY:
1089                                         cont=0;
1090                                         break;
1091                                 case ESCKEY:
1092                                 case RIGHTMOUSE:
1093                                         if(val) {
1094                                                 cancel=1;
1095                                                 cont=0;
1096                                         }
1097                                         break;
1098                         }
1099                 }
1100                 
1101         }
1102         
1103         if(cancel) {
1104                 node->width= oldwidth;
1105         }
1106         else
1107                 BIF_undo_push("Scale Node");
1108         
1109         allqueue(REDRAWNODE, 1);
1110 }
1111
1112 /* ******************** rename ******************* */
1113
1114 void node_rename(SpaceNode *snode)
1115 {
1116         bNode *node, *rename_node;
1117         short found_node= 0;
1118
1119         /* check if a node is selected */
1120         for(node= snode->edittree->nodes.first; node; node= node->next) {
1121                 if(node->flag & SELECT) {
1122                         found_node= 1;
1123                         break;
1124                 }
1125         }
1126
1127         if(found_node) {
1128                 rename_node= nodeGetActive(snode->edittree);
1129                 node_rename_but((char *)rename_node->username);
1130                 BIF_undo_push("Rename Node");
1131         
1132                 allqueue(REDRAWNODE, 1);
1133         }
1134 }
1135
1136 /* ********************** select ******************** */
1137
1138 /* used in buttons to check context, also checks for edited groups */
1139 bNode *editnode_get_active_idnode(bNodeTree *ntree, short id_code)
1140 {
1141         return nodeGetActiveID(ntree, id_code);
1142 }
1143
1144 /* used in buttons to check context, also checks for edited groups */
1145 Material *editnode_get_active_material(Material *ma)
1146 {
1147         if(ma && ma->use_nodes && ma->nodetree) {
1148                 bNode *node= editnode_get_active_idnode(ma->nodetree, ID_MA);
1149                 if(node)
1150                         return (Material *)node->id;
1151                 else
1152                         return NULL;
1153         }
1154         return ma;
1155 }
1156
1157 /* used in buttons to check context, also checks for edited groups */
1158 bNode *editnode_get_active(bNodeTree *ntree)
1159 {
1160         bNode *node;
1161         
1162         /* check for edited group */
1163         for(node= ntree->nodes.first; node; node= node->next)
1164                 if(node->flag & NODE_GROUP_EDIT)
1165                         break;
1166         if(node)
1167                 return nodeGetActive((bNodeTree *)node->id);
1168         else
1169                 return nodeGetActive(ntree);
1170 }
1171
1172
1173 /* no undo here! */
1174 void node_deselectall(SpaceNode *snode, int swap)
1175 {
1176         bNode *node;
1177         
1178         if(swap) {
1179                 for(node= snode->edittree->nodes.first; node; node= node->next)
1180                         if(node->flag & SELECT)
1181                                 break;
1182                 if(node==NULL) {
1183                         for(node= snode->edittree->nodes.first; node; node= node->next)
1184                                 node->flag |= SELECT;
1185                         allqueue(REDRAWNODE, 0);
1186                         return;
1187                 }
1188                 /* else pass on to deselect */
1189         }
1190         
1191         for(node= snode->edittree->nodes.first; node; node= node->next)
1192                 node->flag &= ~SELECT;
1193         
1194         allqueue(REDRAWNODE, 0);
1195 }
1196
1197 int node_has_hidden_sockets(bNode *node)
1198 {
1199         bNodeSocket *sock;
1200         
1201         for(sock= node->inputs.first; sock; sock= sock->next)
1202                 if(sock->flag & SOCK_HIDDEN)
1203                         return 1;
1204         for(sock= node->outputs.first; sock; sock= sock->next)
1205                 if(sock->flag & SOCK_HIDDEN)
1206                         return 1;
1207         return 0;
1208 }
1209
1210
1211 static void node_hide_unhide_sockets(SpaceNode *snode, bNode *node)
1212 {
1213         bNodeSocket *sock;
1214         
1215         /* unhide all */
1216         if( node_has_hidden_sockets(node) ) {
1217                 for(sock= node->inputs.first; sock; sock= sock->next)
1218                         sock->flag &= ~SOCK_HIDDEN;
1219                 for(sock= node->outputs.first; sock; sock= sock->next)
1220                         sock->flag &= ~SOCK_HIDDEN;
1221         }
1222         else {
1223                 bNode *gnode= snode_get_editgroup(snode);
1224                 
1225                 /* hiding inside group should not break links in other group users */
1226                 if(gnode) {
1227                         nodeGroupSocketUseFlags((bNodeTree *)gnode->id);
1228                         for(sock= node->inputs.first; sock; sock= sock->next)
1229                                 if(!(sock->flag & SOCK_IN_USE))
1230                                         if(sock->link==NULL)
1231                                                 sock->flag |= SOCK_HIDDEN;
1232                         for(sock= node->outputs.first; sock; sock= sock->next)
1233                                 if(!(sock->flag & SOCK_IN_USE))
1234                                         if(nodeCountSocketLinks(snode->edittree, sock)==0)
1235                                                 sock->flag |= SOCK_HIDDEN;
1236                 }
1237                 else {
1238                         /* hide unused sockets */
1239                         for(sock= node->inputs.first; sock; sock= sock->next) {
1240                                 if(sock->link==NULL)
1241                                         sock->flag |= SOCK_HIDDEN;
1242                         }
1243                         for(sock= node->outputs.first; sock; sock= sock->next) {
1244                                 if(nodeCountSocketLinks(snode->edittree, sock)==0)
1245                                         sock->flag |= SOCK_HIDDEN;
1246                         }
1247                 }
1248         }
1249
1250         allqueue(REDRAWNODE, 1);
1251         snode_verify_groups(snode);
1252         BIF_undo_push("Hide/Unhide sockets");
1253
1254 }
1255
1256 static int do_header_node(SpaceNode *snode, bNode *node, float mx, float my)
1257 {
1258         rctf totr= node->totr;
1259         
1260         totr.ymin= totr.ymax-20.0f;
1261         
1262         totr.xmax= totr.xmin+15.0f;
1263         if(BLI_in_rctf(&totr, mx, my)) {
1264                 node->flag |= NODE_HIDDEN;
1265                 allqueue(REDRAWNODE, 0);
1266                 return 1;
1267         }       
1268         
1269         totr.xmax= node->totr.xmax;
1270         totr.xmin= totr.xmax-18.0f;
1271         if(node->typeinfo->flag & NODE_PREVIEW) {
1272                 if(BLI_in_rctf(&totr, mx, my)) {
1273                         node->flag ^= NODE_PREVIEW;
1274                         allqueue(REDRAWNODE, 0);
1275                         return 1;
1276                 }
1277                 totr.xmin-=18.0f;
1278         }
1279         if(node->type == NODE_GROUP) {
1280                 if(BLI_in_rctf(&totr, mx, my)) {
1281                         snode_make_group_editable(snode, node);
1282                         return 1;
1283                 }
1284                 totr.xmin-=18.0f;
1285         }
1286         if(node->typeinfo->flag & NODE_OPTIONS) {
1287                 if(BLI_in_rctf(&totr, mx, my)) {
1288                         node->flag ^= NODE_OPTIONS;
1289                         allqueue(REDRAWNODE, 0);
1290                         return 1;
1291                 }
1292                 totr.xmin-=18.0f;
1293         }
1294         /* hide unused sockets */
1295         if(BLI_in_rctf(&totr, mx, my)) {
1296                 node_hide_unhide_sockets(snode, node);
1297         }
1298         
1299         
1300         totr= node->totr;
1301         totr.xmin= totr.xmax-10.0f;
1302         totr.ymax= totr.ymin+10.0f;
1303         if(BLI_in_rctf(&totr, mx, my)) {
1304                 scale_node(snode, node);
1305                 return 1;
1306         }
1307         return 0;
1308 }
1309
1310 static int do_header_hidden_node(SpaceNode *snode, bNode *node, float mx, float my)
1311 {
1312         rctf totr= node->totr;
1313         
1314         totr.xmax= totr.xmin+15.0f;
1315         if(BLI_in_rctf(&totr, mx, my)) {
1316                 node->flag &= ~NODE_HIDDEN;
1317                 allqueue(REDRAWNODE, 0);
1318                 return 1;
1319         }       
1320         
1321         totr.xmax= node->totr.xmax;
1322         totr.xmin= node->totr.xmax-15.0f;
1323         if(BLI_in_rctf(&totr, mx, my)) {
1324                 scale_node(snode, node);
1325                 return 1;
1326         }
1327         return 0;
1328 }
1329
1330 static void node_link_viewer(SpaceNode *snode, bNode *tonode)
1331 {
1332         bNode *node;
1333
1334         /* context check */
1335         if(tonode==NULL || tonode->outputs.first==NULL)
1336                 return;
1337         if( ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) 
1338                 return;
1339         
1340         /* get viewer */
1341         for(node= snode->edittree->nodes.first; node; node= node->next)
1342                 if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) 
1343                         if(node->flag & NODE_DO_OUTPUT)
1344                                 break;
1345                 
1346         if(node) {
1347                 bNodeLink *link;
1348                 
1349                 /* get link to viewer */
1350                 for(link= snode->edittree->links.first; link; link= link->next)
1351                         if(link->tonode==node)
1352                                 break;
1353
1354                 if(link) {
1355                         link->fromnode= tonode;
1356                         link->fromsock= tonode->outputs.first;
1357                         NodeTagChanged(snode->edittree, node);
1358                         
1359                         snode_handle_recalc(snode);
1360                 }
1361         }
1362 }
1363
1364
1365 void node_active_link_viewer(SpaceNode *snode)
1366 {
1367         bNode *node= editnode_get_active(snode->edittree);
1368         if(node)
1369                 node_link_viewer(snode, node);
1370 }
1371
1372 /* return 0: nothing done */
1373 static int node_mouse_select(SpaceNode *snode, unsigned short event)
1374 {
1375         bNode *node;
1376         float mx, my;
1377         short mval[2];
1378         
1379         getmouseco_areawin(mval);
1380         areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
1381         
1382         for(next_node(snode->edittree); (node=next_node(NULL));) {
1383                 
1384                 /* first check for the headers or scaling widget */
1385                 if(node->flag & NODE_HIDDEN) {
1386                         if(do_header_hidden_node(snode, node, mx, my))
1387                                 return 1;
1388                 }
1389                 else {
1390                         if(do_header_node(snode, node, mx, my))
1391                                 return 1;
1392                 }
1393                 
1394                 /* node body */
1395                 if(BLI_in_rctf(&node->totr, mx, my))
1396                         break;
1397         }
1398         if(node) {
1399                 if((G.qual & LR_SHIFTKEY)==0)
1400                         node_deselectall(snode, 0);
1401                 
1402                 if(G.qual & LR_SHIFTKEY) {
1403                         if(node->flag & SELECT)
1404                                 node->flag &= ~SELECT;
1405                         else
1406                                 node->flag |= SELECT;
1407                 }
1408                 else 
1409                         node->flag |= SELECT;
1410                 
1411                 node_set_active(snode, node);
1412                 
1413                 /* viewer linking */
1414                 if(G.qual & LR_CTRLKEY)
1415                         node_link_viewer(snode, node);
1416                 
1417                 /* not so nice (no event), but function below delays redraw otherwise */
1418                 force_draw(0);
1419                 
1420                 std_rmouse_transform(node_transform_ext);       /* does undo push for select */
1421                 
1422                 return 1;
1423         }
1424         return 0;
1425 }
1426
1427 /* return 0, nothing done */
1428 static int node_mouse_groupheader(SpaceNode *snode)
1429 {
1430         bNode *gnode;
1431         float mx, my;
1432         short mval[2];
1433         
1434         gnode= snode_get_editgroup(snode);
1435         if(gnode==NULL) return 0;
1436         
1437         getmouseco_areawin(mval);
1438         areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
1439         
1440         /* click in header or outside? */
1441         if(BLI_in_rctf(&gnode->totr, mx, my)==0) {
1442                 rctf rect= gnode->totr;
1443                 
1444                 rect.ymax += NODE_DY;
1445                 if(BLI_in_rctf(&rect, mx, my)==0)
1446                         snode_make_group_editable(snode, NULL); /* toggles, so exits editmode */
1447                 else
1448                         transform_nodes(snode->nodetree, 'g', "Move group");
1449                 
1450                 return 1;
1451         }
1452         return 0;
1453 }
1454
1455 static int node_socket_hilights(SpaceNode *snode, int in_out)
1456 {
1457         bNode *node;
1458         bNodeSocket *sock, *tsock, *socksel= NULL;
1459         float mx, my;
1460         short mval[2], redraw= 0;
1461         
1462         if(snode->edittree==NULL) return 0;
1463         
1464         getmouseco_areawin(mval);
1465         areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
1466         
1467         /* deselect socks */
1468         for(node= snode->edittree->nodes.first; node; node= node->next) {
1469                 for(sock= node->inputs.first; sock; sock= sock->next) {
1470                         if(sock->flag & SELECT) {
1471                                 sock->flag &= ~SELECT;
1472                                 redraw++;
1473                                 socksel= sock;
1474                         }
1475                 }
1476                 for(sock= node->outputs.first; sock; sock= sock->next) {
1477                         if(sock->flag & SELECT) {
1478                                 sock->flag &= ~SELECT;
1479                                 redraw++;
1480                                 socksel= sock;
1481                         }
1482                 }
1483         }
1484         
1485         if(find_indicated_socket(snode, &node, &tsock, in_out)) {
1486                 tsock->flag |= SELECT;
1487                 if(redraw==1 && tsock==socksel) redraw= 0;
1488                 else redraw= 1;
1489         }
1490         
1491         return redraw;
1492 }
1493
1494 void node_border_select(SpaceNode *snode)
1495 {
1496         bNode *node;
1497         rcti rect;
1498         rctf rectf;
1499         short val, mval[2];
1500         
1501         if ( (val = get_border(&rect, 3)) ) {
1502                 
1503                 mval[0]= rect.xmin;
1504                 mval[1]= rect.ymin;
1505                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
1506                 mval[0]= rect.xmax;
1507                 mval[1]= rect.ymax;
1508                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
1509                 
1510                 for(node= snode->edittree->nodes.first; node; node= node->next) {
1511                         if(BLI_isect_rctf(&rectf, &node->totr, NULL)) {
1512                                 if(val==LEFTMOUSE)
1513                                         node->flag |= SELECT;
1514                                 else
1515                                         node->flag &= ~SELECT;
1516                         }
1517                 }
1518                 allqueue(REDRAWNODE, 1);
1519                 BIF_undo_push("Border select nodes");
1520         }               
1521 }
1522
1523 /* ****************** Add *********************** */
1524
1525 void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag)
1526 {
1527         bNodeSocket *sock, *sockfrom[8];
1528         bNode *node, *nodefrom[8];
1529         int totsock= 0, socktype=0;
1530
1531         if(node_to==NULL || node_to->inputs.first==NULL)
1532                 return;
1533         
1534         /* no inputs for node allowed (code it) */
1535
1536         /* connect first 1 socket type now */
1537         for(sock= node_to->inputs.first; sock; sock= sock->next)
1538                 if(socktype<sock->type)
1539                         socktype= sock->type;
1540
1541         
1542         /* find potential sockets, max 8 should work */
1543         for(node= snode->edittree->nodes.first; node; node= node->next) {
1544                 if((node->flag & flag) && node!=node_to) {
1545                         for(sock= node->outputs.first; sock; sock= sock->next) {
1546                                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
1547                                         sockfrom[totsock]= sock;
1548                                         nodefrom[totsock]= node;
1549                                         totsock++;
1550                                         if(totsock>7)
1551                                                 break;
1552                                 }
1553                         }
1554                 }
1555                 if(totsock>7)
1556                         break;
1557         }
1558
1559         /* now just get matching socket types and create links */
1560         for(sock= node_to->inputs.first; sock; sock= sock->next) {
1561                 int a;
1562                 
1563                 for(a=0; a<totsock; a++) {
1564                         if(sockfrom[a]) {
1565                                 if(sock->type==sockfrom[a]->type && sock->type==socktype) {
1566                                         nodeAddLink(snode->edittree, nodefrom[a], sockfrom[a], node_to, sock);
1567                                         sockfrom[a]= NULL;
1568                                         break;
1569                                 }
1570                         }
1571                 }
1572         }
1573         
1574         ntreeSolveOrder(snode->edittree);
1575 }
1576
1577 /* can be called from menus too, but they should do own undopush and redraws */
1578 bNode *node_add_node(SpaceNode *snode, int type, float locx, float locy)
1579 {
1580         bNode *node= NULL, *gnode;
1581         
1582         node_deselectall(snode, 0);
1583         
1584         if(type>=NODE_DYNAMIC_MENU) {
1585                 node= nodeAddNodeType(snode->edittree, type, NULL, NULL);
1586         }
1587         else if(type>=NODE_GROUP_MENU) {
1588                 if(snode->edittree!=snode->nodetree) {
1589                         error("Can not add a Group in a Group");
1590                         return NULL;
1591                 }
1592                 else {
1593                         bNodeTree *ngroup= BLI_findlink(&G.main->nodetree, type-NODE_GROUP_MENU);
1594                         if(ngroup)
1595                                 node= nodeAddNodeType(snode->edittree, NODE_GROUP, ngroup, NULL);
1596                 }
1597         }
1598         else
1599                 node= nodeAddNodeType(snode->edittree, type, NULL, NULL);
1600         
1601         /* generics */
1602         if(node) {
1603                 node->locx= locx;
1604                 node->locy= locy + 60.0f;               // arbitrary.. so its visible
1605                 node->flag |= SELECT;
1606                 
1607                 gnode= snode_get_editgroup(snode);
1608                 if(gnode) {
1609                         node->locx -= gnode->locx;
1610                         node->locy -= gnode->locy;
1611                 }
1612
1613                 snode_verify_groups(snode);
1614                 node_set_active(snode, node);
1615                 
1616                 if(node->id)
1617                         id_us_plus(node->id);
1618                 
1619                 if(snode->nodetree->type==NTREE_COMPOSIT)
1620                         ntreeCompositForceHidden(snode->edittree);
1621                 
1622                 NodeTagChanged(snode->edittree, node);
1623         }
1624         return node;
1625 }
1626
1627 void node_mute(SpaceNode *snode)
1628 {
1629         bNode *node;
1630
1631         /* no disabling inside of groups */
1632         if(snode_get_editgroup(snode))
1633                 return;
1634         
1635         for(node= snode->edittree->nodes.first; node; node= node->next) {
1636                 if(node->flag & SELECT) {
1637                         if(node->inputs.first && node->outputs.first) {
1638                                 if(node->flag & NODE_MUTED)
1639                                         node->flag &= ~NODE_MUTED;
1640                                 else
1641                                         node->flag |= NODE_MUTED;
1642                         }
1643                 }
1644         }
1645         
1646         allqueue(REDRAWNODE, 0);
1647         BIF_undo_push("Enable/Disable nodes");
1648
1649 }
1650
1651 void node_adduplicate(SpaceNode *snode)
1652 {
1653         
1654         ntreeCopyTree(snode->edittree, 1);      /* 1 == internally selected nodes */
1655         
1656         ntreeSolveOrder(snode->edittree);
1657         snode_verify_groups(snode);
1658         snode_handle_recalc(snode);
1659
1660         transform_nodes(snode->edittree, 'g', "Duplicate");
1661 }
1662
1663 #if 0
1664 static void node_insert_convertor(SpaceNode *snode, bNodeLink *link)
1665 {
1666         bNode *newnode= NULL;
1667         
1668         if(link->fromsock->type==SOCK_RGBA && link->tosock->type==SOCK_VALUE) {
1669                 if(snode->edittree->type==NTREE_SHADER)
1670                         newnode= node_add_node(snode, SH_NODE_RGBTOBW, 0.0f, 0.0f);
1671                 else if(snode->edittree->type==NTREE_COMPOSIT)
1672                         newnode= node_add_node(snode, CMP_NODE_RGBTOBW, 0.0f, 0.0f);
1673                 else
1674                         newnode= NULL;
1675         }
1676         else if(link->fromsock->type==SOCK_VALUE && link->tosock->type==SOCK_RGBA) {
1677                 if(snode->edittree->type==NTREE_SHADER)
1678                         newnode= node_add_node(snode, SH_NODE_VALTORGB, 0.0f, 0.0f);
1679                 else if(snode->edittree->type==NTREE_COMPOSIT)
1680                         newnode= node_add_node(snode, CMP_NODE_VALTORGB, 0.0f, 0.0f);
1681                 else
1682                         newnode= NULL;
1683         }
1684         
1685         if(newnode) {
1686                 /* dangerous assumption to use first in/out socks, but thats fine for now */
1687                 newnode->flag |= NODE_HIDDEN;
1688                 newnode->locx= 0.5f*(link->fromsock->locx + link->tosock->locx);
1689                 newnode->locy= 0.5f*(link->fromsock->locy + link->tosock->locy) + HIDDEN_RAD;
1690                 
1691                 nodeAddLink(snode->edittree, newnode, newnode->outputs.first, link->tonode, link->tosock);
1692                 link->tonode= newnode;
1693                 link->tosock= newnode->inputs.first;
1694         }
1695 }
1696
1697 #endif
1698
1699 static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeLink *link)
1700 {
1701         bNodeLink *tlink;
1702         bNodeSocket *sock;
1703         
1704         if(tsock && nodeCountSocketLinks(snode->edittree, link->tosock) > tsock->limit) {
1705                 
1706                 for(tlink= snode->edittree->links.first; tlink; tlink= tlink->next) {
1707                         if(link!=tlink && tlink->tosock==link->tosock)
1708                                 break;
1709                 }
1710                 if(tlink) {
1711                         /* is there a free input socket with same type? */
1712                         for(sock= tlink->tonode->inputs.first; sock; sock= sock->next) {
1713                                 if(sock->type==tlink->fromsock->type)
1714                                         if(nodeCountSocketLinks(snode->edittree, sock) < sock->limit)
1715                                                 break;
1716                         }
1717                         if(sock)
1718                                 tlink->tosock= sock;
1719                         else {
1720                                 nodeRemLink(snode->edittree, tlink);
1721                         }
1722                 }
1723         }
1724 }
1725
1726 /* loop that adds a nodelink, called by function below  */
1727 /* in_out = starting socket */
1728 static int node_add_link_drag(SpaceNode *snode, bNode *node, bNodeSocket *sock, int in_out)
1729 {
1730         bNode *tnode;
1731         bNodeSocket *tsock= NULL;
1732         bNodeLink *link= NULL;
1733         short mval[2], mvalo[2], firsttime=1;   /* firsttime reconnects a link broken by caller */
1734         
1735         /* we make a temporal link */
1736         if(in_out==SOCK_OUT)
1737                 link= nodeAddLink(snode->edittree, node, sock, NULL, NULL);
1738         else
1739                 link= nodeAddLink(snode->edittree, NULL, NULL, node, sock);
1740         
1741         getmouseco_areawin(mvalo);
1742         while (get_mbut() & L_MOUSE) {
1743                 
1744                 getmouseco_areawin(mval);
1745                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || firsttime) {
1746                         firsttime= 0;
1747                         
1748                         mvalo[0]= mval[0];
1749                         mvalo[1]= mval[1];
1750                         
1751                         if(in_out==SOCK_OUT) {
1752                                 if(find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
1753                                         if(nodeFindLink(snode->edittree, sock, tsock)==NULL) {
1754                                                 if(tnode!=node  && link->tonode!=tnode && link->tosock!= tsock) {
1755                                                         link->tonode= tnode;
1756                                                         link->tosock= tsock;
1757                                                         ntreeSolveOrder(snode->edittree);       /* for interactive red line warning */
1758                                                 }
1759                                         }
1760                                 }
1761                                 else {
1762                                         link->tonode= NULL;
1763                                         link->tosock= NULL;
1764                                 }
1765                         }
1766                         else {
1767                                 if(find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
1768                                         if(nodeFindLink(snode->edittree, sock, tsock)==NULL) {
1769                                                 if(nodeCountSocketLinks(snode->edittree, tsock) < tsock->limit) {
1770                                                         if(tnode!=node && link->fromnode!=tnode && link->fromsock!= tsock) {
1771                                                                 link->fromnode= tnode;
1772                                                                 link->fromsock= tsock;
1773                                                                 ntreeSolveOrder(snode->edittree);       /* for interactive red line warning */
1774                                                         }
1775                                                 }
1776                                         }
1777                                 }
1778                                 else {
1779                                         link->fromnode= NULL;
1780                                         link->fromsock= NULL;
1781                                 }
1782                         }
1783                         /* hilight target sockets only */
1784                         node_socket_hilights(snode, in_out==SOCK_OUT?SOCK_IN:SOCK_OUT);
1785                         
1786                         force_draw(0);
1787                 }
1788                 else BIF_wait_for_statechange();                
1789         }
1790         
1791         /* remove link? */
1792         if(link->tonode==NULL || link->fromnode==NULL) {
1793                 nodeRemLink(snode->edittree, link);
1794         }
1795         else {
1796                 /* send changed events for original tonode and new */
1797                 if(link->tonode) 
1798                         NodeTagChanged(snode->edittree, link->tonode);
1799                 
1800                 /* we might need to remove a link */
1801                 if(in_out==SOCK_OUT) node_remove_extra_links(snode, tsock, link);
1802         }
1803         
1804         ntreeSolveOrder(snode->edittree);
1805         snode_verify_groups(snode);
1806         snode_handle_recalc(snode);
1807         
1808         allqueue(REDRAWNODE, 0);
1809         BIF_undo_push("Add link");
1810
1811         return 1;
1812 }
1813
1814 /* return 1 when socket clicked */
1815 static int node_add_link(SpaceNode *snode)
1816 {
1817         bNode *node;
1818         bNodeLink *link;
1819         bNodeSocket *sock;
1820         
1821         /* output indicated? */
1822         if(find_indicated_socket(snode, &node, &sock, SOCK_OUT)) {
1823                 if(nodeCountSocketLinks(snode->edittree, sock)<sock->limit)
1824                         return node_add_link_drag(snode, node, sock, SOCK_OUT);
1825                 else {
1826                         /* find if we break a link */
1827                         for(link= snode->edittree->links.first; link; link= link->next) {
1828                                 if(link->fromsock==sock)
1829                                         break;
1830                         }
1831                         if(link) {
1832                                 node= link->tonode;
1833                                 sock= link->tosock;
1834                                 nodeRemLink(snode->edittree, link);
1835                                 return node_add_link_drag(snode, node, sock, SOCK_IN);
1836                         }
1837                 }
1838         }
1839         /* or an input? */
1840         else if(find_indicated_socket(snode, &node, &sock, SOCK_IN)) {
1841                 if(nodeCountSocketLinks(snode->edittree, sock)<sock->limit)
1842                         return node_add_link_drag(snode, node, sock, SOCK_IN);
1843                 else {
1844                         /* find if we break a link */
1845                         for(link= snode->edittree->links.first; link; link= link->next) {
1846                                 if(link->tosock==sock)
1847                                         break;
1848                         }
1849                         if(link) {
1850                                 /* send changed event to original tonode */
1851                                 if(link->tonode) 
1852                                         NodeTagChanged(snode->edittree, link->tonode);
1853                                 
1854                                 node= link->fromnode;
1855                                 sock= link->fromsock;
1856                                 nodeRemLink(snode->edittree, link);
1857                                 return node_add_link_drag(snode, node, sock, SOCK_OUT);
1858                         }
1859                 }
1860         }
1861         
1862         return 0;
1863 }
1864
1865 void node_delete(SpaceNode *snode)
1866 {
1867         bNode *node, *next;
1868         bNodeSocket *sock;
1869         
1870         for(node= snode->edittree->nodes.first; node; node= next) {
1871                 next= node->next;
1872                 if(node->flag & SELECT) {
1873                         /* set selin and selout NULL if the sockets belong to a node to be deleted */
1874                         for(sock= node->inputs.first; sock; sock= sock->next)
1875                                 if(snode->edittree->selin == sock) snode->edittree->selin= NULL;
1876
1877                         for(sock= node->outputs.first; sock; sock= sock->next)
1878                                 if(snode->edittree->selout == sock) snode->edittree->selout= NULL;
1879
1880                         /* check id user here, nodeFreeNode is called for free dbase too */
1881                         if(node->id)
1882                                 node->id->us--;
1883                         nodeFreeNode(snode->edittree, node);
1884                 }
1885         }
1886         
1887         snode_verify_groups(snode);
1888         snode_handle_recalc(snode);
1889         BIF_undo_push("Delete nodes");
1890         allqueue(REDRAWNODE, 1);
1891 }
1892
1893 void node_hide(SpaceNode *snode)
1894 {
1895         bNode *node;
1896         int nothidden=0, ishidden=0;
1897         
1898         for(node= snode->edittree->nodes.first; node; node= node->next) {
1899                 if(node->flag & SELECT) {
1900                         if(node->flag & NODE_HIDDEN)
1901                                 ishidden++;
1902                         else
1903                                 nothidden++;
1904                 }
1905         }
1906         for(node= snode->edittree->nodes.first; node; node= node->next) {
1907                 if(node->flag & SELECT) {
1908                         if( (ishidden && nothidden) || ishidden==0)
1909                                 node->flag |= NODE_HIDDEN;
1910                         else 
1911                                 node->flag &= ~NODE_HIDDEN;
1912                 }
1913         }
1914         BIF_undo_push("Hide nodes");
1915         allqueue(REDRAWNODE, 1);
1916 }
1917
1918 void node_insert_key(SpaceNode *snode)
1919 {
1920         bNode *node= editnode_get_active(snode->edittree);
1921
1922         if(node->type==CMP_NODE_TIME) {
1923                 if(node->custom1<node->custom2) {
1924
1925                         CurveMapping *cumap= node->storage;
1926                         float fval, curval;
1927                 
1928                         curval= (float)(CFRA - node->custom1)/(float)(node->custom2-node->custom1);
1929                         fval= curvemapping_evaluateF(cumap, 0, curval);
1930                         
1931                         if(fbutton(&fval, 0.0f, 1.0f, 10, 10, "Insert Value")) {
1932                                 curvemap_insert(cumap->cm, curval, fval);
1933
1934                                 BIF_undo_push("Insert key in Time node");
1935                                 allqueue(REDRAWNODE, 1);
1936                         }
1937                 }
1938         }
1939 }
1940
1941 void node_select_linked(SpaceNode *snode, int out)
1942 {
1943         bNodeLink *link;
1944         bNode *node;
1945         
1946         /* NODE_TEST is the free flag */
1947         for(node= snode->edittree->nodes.first; node; node= node->next)
1948                 node->flag &= ~NODE_TEST;
1949
1950         for(link= snode->edittree->links.first; link; link= link->next) {
1951                 if(out) {
1952                         if(link->fromnode->flag & NODE_SELECT)
1953                                 link->tonode->flag |= NODE_TEST;
1954                 }
1955                 else {
1956                         if(link->tonode->flag & NODE_SELECT)
1957                                 link->fromnode->flag |= NODE_TEST;
1958                 }
1959         }
1960         
1961         for(node= snode->edittree->nodes.first; node; node= node->next)
1962                 if(node->flag & NODE_TEST)
1963                         node->flag |= NODE_SELECT;
1964         
1965         BIF_undo_push("Select Linked nodes");
1966         allqueue(REDRAWNODE, 1);
1967 }
1968
1969 /* makes a link between selected output and input sockets */
1970 void node_make_link(SpaceNode *snode)
1971 {
1972         bNode *fromnode, *tonode;
1973         bNodeLink *link;
1974         bNodeSocket *outsock= snode->edittree->selout;
1975         bNodeSocket *insock= snode->edittree->selin;
1976
1977         if(!insock || !outsock) return;
1978         if(nodeFindLink(snode->edittree, outsock, insock)) return;
1979
1980         if(nodeFindNode(snode->edittree, outsock, &fromnode, NULL) &&
1981                 nodeFindNode(snode->edittree, insock, &tonode, NULL)) {
1982                 link= nodeAddLink(snode->edittree, fromnode, outsock, tonode, insock);
1983                 NodeTagChanged(snode->edittree, tonode);
1984                 node_remove_extra_links(snode, insock, link);
1985         }
1986         else return;
1987
1988         ntreeSolveOrder(snode->edittree);
1989         snode_verify_groups(snode);
1990         snode_handle_recalc(snode);
1991
1992         allqueue(REDRAWNODE, 0);
1993         BIF_undo_push("Make Link Between Sockets");
1994 }
1995
1996 static void node_border_link_delete(SpaceNode *snode)
1997 {
1998         rcti rect;
1999         short val, mval[2], mvalo[2];
2000
2001         /* to make this work more friendly, we first wait for a mouse move */
2002         getmouseco_areawin(mvalo);
2003         while (get_mbut() & L_MOUSE) {
2004                 getmouseco_areawin(mval);
2005                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1])
2006                         break;
2007                 else BIF_wait_for_statechange();
2008         }
2009         if((get_mbut() & L_MOUSE)==0)
2010                 return;
2011         
2012         /* now change cursor and draw border */
2013         setcursor_space(SPACE_NODE, CURSOR_VPAINT);
2014         
2015         if ( (val = get_border(&rect, 2)) ) {
2016                 if(rect.xmin<rect.xmax && rect.ymin<rect.ymax) {
2017                         //#define NODE_MAXPICKBUF       256
2018                         bNodeLink *link, *next;
2019                         GLuint buffer[256];
2020                         rctf rectf;
2021                         int code=0, hits;
2022                         
2023                         mval[0]= rect.xmin;
2024                         mval[1]= rect.ymin;
2025                         areamouseco_to_ipoco(&snode->v2d, mval, &rectf.xmin, &rectf.ymin);
2026                         mval[0]= rect.xmax;
2027                         mval[1]= rect.ymax;
2028                         areamouseco_to_ipoco(&snode->v2d, mval, &rectf.xmax, &rectf.ymax);
2029                         
2030                         myortho2(rectf.xmin, rectf.xmax, rectf.ymin, rectf.ymax);
2031                         
2032                         glSelectBuffer(256, buffer); 
2033                         glRenderMode(GL_SELECT);
2034                         glInitNames();
2035                         glPushName(-1);
2036                         
2037                         /* draw links */
2038                         for(link= snode->edittree->links.first; link; link= link->next) {
2039                                 glLoadName(code++);
2040                                 node_draw_link(snode, link);
2041                         }
2042                         
2043                         hits= glRenderMode(GL_RENDER);
2044                         glPopName();
2045                         if(hits>0) {
2046                                 int a;
2047                                 for(a=0; a<hits; a++) {
2048                                         bNodeLink *link= BLI_findlink(&snode->edittree->links, buffer[ (4 * a) + 3]);
2049                                         if(link)
2050                                                 link->fromnode= NULL;   /* first tag for delete, otherwise indices are wrong */
2051                                 }
2052                                 for(link= snode->edittree->links.first; link; link= next) {
2053                                         next= link->next;
2054                                         if(link->fromnode==NULL) {
2055                                                 NodeTagChanged(snode->edittree, link->tonode);
2056                                                 nodeRemLink(snode->edittree, link);
2057                                         }
2058                                 }
2059                                 ntreeSolveOrder(snode->edittree);
2060                                 snode_verify_groups(snode);
2061                                 snode_handle_recalc(snode);
2062                         }
2063                         allqueue(REDRAWNODE, 0);
2064                         BIF_undo_push("Erase links");
2065                 }
2066         }
2067         
2068         setcursor_space(SPACE_NODE, CURSOR_STD);
2069 }
2070
2071 /* goes over all scenes, reads render layerss */
2072 void node_read_renderlayers(SpaceNode *snode)
2073 {
2074         Scene *scene;
2075         bNode *node;
2076
2077         /* first tag scenes unread */
2078         for(scene= G.main->scene.first; scene; scene= scene->id.next) 
2079                 scene->id.flag |= LIB_DOIT;
2080
2081         for(node= snode->edittree->nodes.first; node; node= node->next) {
2082                 if(node->type==CMP_NODE_R_LAYERS) {
2083                         ID *id= node->id;
2084                         if(id==NULL) id= (ID *)G.scene;
2085                         if(id->flag & LIB_DOIT) {
2086                                 RE_ReadRenderResult(G.scene, (Scene *)id);
2087                                 ntreeCompositTagRender((Scene *)id);
2088                                 id->flag &= ~LIB_DOIT;
2089                         }
2090                 }
2091         }
2092         
2093         /* own render result should be read/allocated */
2094         if(G.scene->id.flag & LIB_DOIT)
2095                 RE_ReadRenderResult(G.scene, G.scene);
2096         
2097         snode_handle_recalc(snode);
2098 }
2099
2100 void node_read_fullsamplelayers(SpaceNode *snode)
2101 {
2102         Render *re= RE_NewRender(G.scene->id.name);
2103
2104         waitcursor(1);
2105
2106         BIF_init_render_callbacks(re, 1);
2107         RE_MergeFullSample(re, G.scene, snode->nodetree);
2108         BIF_end_render_callbacks();
2109         
2110         allqueue(REDRAWNODE, 1);
2111         allqueue(REDRAWIMAGE, 1);
2112         
2113         waitcursor(0);
2114 }
2115
2116 /* called from header_info, when deleting a scene
2117  * goes over all scenes other than the input, checks if they have
2118  * render layer nodes referencing the to-be-deleted scene, and
2119  * resets them to NULL. */
2120 void clear_scene_in_nodes(Scene *sce)
2121 {
2122         Scene *sce1;
2123         bNode *node;
2124
2125         sce1= G.main->scene.first;
2126         while(sce1) {
2127                 if(sce1!=sce) {
2128                         if (sce1->nodetree) {
2129                                 for(node= sce1->nodetree->nodes.first; node; node= node->next) {
2130                                         if(node->type==CMP_NODE_R_LAYERS) {
2131                                                 Scene *nodesce= (Scene *)node->id;
2132                                                 
2133                                                 if (nodesce==sce) node->id = NULL;
2134                                         }
2135                                 }
2136                         }
2137                 }
2138                 sce1= sce1->id.next;
2139         }
2140 }
2141
2142
2143 /* gets active viewer user */
2144 struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
2145 {
2146         bNode *node;
2147         
2148         if(ntree)
2149                 for(node= ntree->nodes.first; node; node= node->next)
2150                         if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) 
2151                                 if(node->flag & NODE_DO_OUTPUT)
2152                                         return node->storage;
2153         return NULL;
2154 }
2155
2156 void imagepaint_composite_tags(bNodeTree *ntree, Image *image, ImageUser *iuser)
2157 {
2158         bNode *node;
2159         
2160         if(ntree==NULL)
2161                 return;
2162         
2163         /* search for renderresults */
2164         if(image->type==IMA_TYPE_R_RESULT) {
2165                 for(node= ntree->nodes.first; node; node= node->next) {
2166                         if(node->type==CMP_NODE_R_LAYERS && node->id==NULL) {
2167                                 /* imageuser comes from ImageWin, so indexes are offset 1 */
2168                                 if(node->custom1==iuser->layer-1)
2169                                         NodeTagChanged(ntree, node);
2170                         }
2171                 }
2172         }
2173         else {
2174                 for(node= ntree->nodes.first; node; node= node->next) {
2175                         if(node->id== &image->id)
2176                                 NodeTagChanged(ntree, node);
2177                 }
2178         }
2179 }
2180
2181 /* ********************** */
2182
2183 void node_make_group(SpaceNode *snode)
2184 {
2185         bNode *gnode;
2186         
2187         if(snode->edittree!=snode->nodetree) {
2188                 error("Can not add a new Group in a Group");
2189                 return;
2190         }
2191         
2192         /* for time being... is too complex to handle */
2193         if(snode->treetype==NTREE_COMPOSIT) {
2194                 for(gnode=snode->nodetree->nodes.first; gnode; gnode= gnode->next) {
2195                         if(gnode->flag & SELECT)
2196                                 if(gnode->type==CMP_NODE_R_LAYERS)
2197                                         break;
2198                 }
2199                 if(gnode) {
2200                         error("Can not add RenderLayer in a Group");
2201                         return;
2202                 }
2203         }
2204         
2205         gnode= nodeMakeGroupFromSelected(snode->nodetree);
2206         if(gnode==NULL) {
2207                 error("Can not make Group");
2208         }
2209         else {
2210                 nodeSetActive(snode->nodetree, gnode);
2211                 ntreeSolveOrder(snode->nodetree);
2212                 allqueue(REDRAWNODE, 0);
2213                 BIF_undo_push("Make Node Group");
2214         }
2215 }
2216
2217 /* ******************** main event loop ****************** */
2218
2219 /* special version to prevent overlapping buttons, has a bit of hack... */
2220 /* yes, check for example composit_node_event(), file window use... */
2221 static int node_uiDoBlocks(ScrArea *sa, short event)
2222 {
2223         SpaceNode *snode= sa->spacedata.first;
2224         ListBase *lb= &sa->uiblocks;
2225         ListBase listb= *lb;
2226         bNode *node;
2227         rctf rect;
2228         void *prev, *next;
2229         int retval= UI_NOTHING;
2230         short mval[2];
2231         
2232         getmouseco_areawin(mval);
2233         areamouseco_to_ipoco(G.v2d, mval, &rect.xmin, &rect.ymin);
2234
2235         /* this happens after filesel usage... */
2236         if(lb->first==NULL) {
2237                 return UI_NOTHING;
2238         }
2239         
2240         rect.xmin -= 2.0f;
2241         rect.ymin -= 2.0f;
2242         rect.xmax = rect.xmin + 4.0f;
2243         rect.ymax = rect.ymin + 4.0f;
2244         
2245         for(node= snode->edittree->nodes.first; node; node= node->next) {
2246                 uiBlock *block;
2247                 char str[32];
2248                 
2249                 /* retreive unique block name, see also drawnode.c */
2250                 sprintf(str, "node buttons %p", node);
2251                 block= uiGetBlock(str, sa);
2252                 
2253                 if(block) {
2254                         if(node == visible_node(snode, &rect)) {
2255
2256                                 /* when there's menus, the prev pointer becomes zero! */
2257                                 prev= ((struct Link *)block)->prev;
2258                                 next= ((struct Link *)block)->next;
2259                                 ((struct Link *)block)->prev= NULL;
2260                                 ((struct Link *)block)->next= NULL;
2261                                 
2262                                 lb->first= lb->last= block;
2263                                 retval= uiDoBlocks(lb, event, 1);
2264                                 
2265                                 ((struct Link *)block)->prev= prev;
2266                                 ((struct Link *)block)->next= next;
2267
2268                                 break;
2269                         }
2270                 }
2271         }
2272         
2273         *lb= listb;
2274         
2275         return retval;
2276 }
2277
2278 void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
2279 {
2280         SpaceNode *snode= spacedata;
2281         bNode *actnode;
2282         bNodeSocket *actsock;
2283         unsigned short event= evt->event;
2284         short val= evt->val, doredraw=0, fromlib= 0;
2285         
2286         if(sa->win==0) return;
2287         if(snode->nodetree==NULL) return;
2288         
2289         if(val) {
2290
2291                 if( node_uiDoBlocks(sa, event)!=UI_NOTHING ) event= 0;  
2292
2293                 fromlib= (snode->id && snode->id->lib);
2294                 
2295                 switch(event) {
2296                 case LEFTMOUSE:
2297                         if(fromlib) {
2298                                 if(node_mouse_groupheader(snode)==0)
2299                                         node_mouse_select(snode, event);
2300                         }
2301                         else {
2302                                 if(node_add_link(snode)==0)
2303                                         if(node_mouse_groupheader(snode)==0)
2304                                                 if(node_mouse_select(snode, event)==0)
2305                                                         node_border_link_delete(snode);
2306                         }
2307                         break;
2308                         
2309                 case RIGHTMOUSE: 
2310                         if(find_indicated_socket(snode, &actnode, &actsock, SOCK_IN)) {
2311                                 if(actsock->flag & SOCK_SEL) {
2312                                         snode->edittree->selin= NULL;
2313                                         actsock->flag&= ~SOCK_SEL;
2314                                 }
2315                                 else {
2316                                         snode->edittree->selin= actsock;
2317                                         reset_sel_socket(snode, SOCK_IN);
2318                                         actsock->flag|= SOCK_SEL;
2319                                 }
2320                         }
2321                         else if(find_indicated_socket(snode, &actnode, &actsock, SOCK_OUT)) {
2322                                 if(actsock->flag & SOCK_SEL) {
2323                                         snode->edittree->selout= NULL;
2324                                         actsock->flag&= ~SOCK_SEL;
2325                                 }
2326                                 else {
2327                                         snode->edittree->selout= actsock;
2328                                         reset_sel_socket(snode, SOCK_OUT);
2329                                         actsock->flag|= SOCK_SEL;
2330                                 }
2331                         }
2332                         else if(!node_mouse_select(snode, event)) 
2333                                 toolbox_n();
2334
2335                         break;
2336                 case MIDDLEMOUSE:
2337                         if((snode->flag & SNODE_BACKDRAW) && (snode->treetype==NTREE_COMPOSIT)
2338                            && (G.qual==LR_SHIFTKEY)) {
2339                                 snode_bg_viewmove(snode);
2340                         } else {
2341                                 view2dmove(event);
2342                         }
2343                 case WHEELUPMOUSE:
2344                 case WHEELDOWNMOUSE:
2345                         view2dmove(event);      /* in drawipo.c */
2346                         break;
2347                         
2348                 case MOUSEY:
2349                         doredraw= node_socket_hilights(snode, SOCK_IN|SOCK_OUT);
2350                         break;
2351                 
2352                 case UI_BUT_EVENT:
2353                         /* future: handlerize this! */
2354                         if(snode->treetype==NTREE_SHADER)
2355                                 shader_node_event(snode, val);
2356                         else if(snode->treetype==NTREE_COMPOSIT)
2357                                 composit_node_event(snode, val);
2358                         break;
2359                         
2360                 case RENDERPREVIEW:
2361                         if(snode->treetype==NTREE_SHADER)
2362                                 shader_node_previewrender(sa, snode);
2363                         break;
2364                         
2365                 case PADPLUSKEY:
2366                         snode_zoom_in(sa);
2367                         doredraw= 1;
2368                         break;
2369                 case PADMINUS:
2370                         snode_zoom_out(sa);
2371                         doredraw= 1;
2372                         break;
2373                 case HOMEKEY:
2374                         snode_home(sa, snode);
2375                         doredraw= 1;
2376                         break;
2377                 case TABKEY:
2378                         if(fromlib) fromlib= -1;
2379                         else snode_make_group_editable(snode, NULL);
2380                         break;
2381                         
2382                 case AKEY:
2383                         if(G.qual==LR_SHIFTKEY) {
2384                                 if(fromlib) fromlib= -1;
2385                                 else toolbox_n_add();
2386                         }
2387                         else if(G.qual==0) {
2388                                 node_deselectall(snode, 1);
2389                                 BIF_undo_push("Deselect all nodes");
2390                         }
2391                         break;
2392                 case BKEY:
2393                         if(G.qual==0)
2394                                 node_border_select(snode);
2395                         break;
2396                 case CKEY:      /* sort again, showing cyclics */
2397                         ntreeSolveOrder(snode->edittree);
2398                         doredraw= 1;
2399                         break;
2400                 case DKEY:
2401                         if(G.qual==LR_SHIFTKEY) {
2402                                 if(fromlib) fromlib= -1;
2403                                 else node_adduplicate(snode);
2404                         }
2405                         break;
2406                 case EKEY:
2407                         snode_handle_recalc(snode);
2408                         break;
2409                 case FKEY:
2410                         node_make_link(snode);
2411                         break;
2412                 case GKEY:
2413                         if(fromlib) fromlib= -1;
2414                         else {
2415                                 if(G.qual==LR_CTRLKEY) {
2416                                         if(okee("Make Group"))
2417                                                 node_make_group(snode);
2418                                 }
2419                                 else if(G.qual==LR_ALTKEY) {
2420                                         if(okee("Ungroup"))
2421                                                 node_ungroup(snode);
2422                                 }
2423                                 else if(G.qual==LR_SHIFTKEY) {
2424                                         node_addgroup(snode);
2425                                 }
2426                                 else
2427                                         transform_nodes(snode->edittree, 'g', "Move Node");
2428                         }
2429                         break;
2430                 case HKEY:
2431                         node_hide(snode);
2432                         break;
2433                 case IKEY:
2434                         node_insert_key(snode);
2435                         break;
2436                 case LKEY:
2437                         node_select_linked(snode, G.qual==LR_SHIFTKEY);
2438                         break;
2439                 case MKEY:
2440                         node_mute(snode);
2441                         break;
2442                 case RKEY:
2443                         if(G.qual==LR_CTRLKEY) {
2444                                 node_rename(snode);
2445                         } 
2446                         else if(G.qual==LR_SHIFTKEY) {
2447                                 if(okee("Read saved Full Sample Layers"))
2448                                         node_read_fullsamplelayers(snode);
2449                         }
2450                         else {
2451                                 if(okee("Read saved Render Layers"))
2452                                         node_read_renderlayers(snode);
2453                         }
2454                         break;
2455                 case DELKEY:
2456                 case XKEY:
2457                         if(fromlib) fromlib= -1;
2458                         else node_delete(snode);
2459                         break;
2460                 }
2461         }
2462
2463         if(fromlib==-1)
2464                 error_libdata();
2465         if(doredraw)
2466                 scrarea_queue_winredraw(sa);
2467         if(doredraw==2)
2468                 scrarea_queue_headredraw(sa);
2469 }
2470
2471