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