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