Patch #7897 Texture Nodes!
[blender-staging.git] / source / blender / src / header_node.c
1 /**
2  *
3  * $Id:
4  *
5  * ***** BEGIN GPL LICENSE BLOCK *****
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version. 
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
20  *
21  * The Original Code is Copyright (C) 2005 Blender Foundation.
22  * All rights reserved.
23  *
24  * The Original Code is: all of this file.
25  *
26  * Contributor(s): David Millan Escriva, Juho Vepsäläinen
27  *
28  * ***** END GPL LICENSE BLOCK *****
29  */
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdio.h>
34
35 #include "DNA_ID.h"
36 #include "DNA_material_types.h"
37 #include "DNA_node_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_screen_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_space_types.h"
42 #include "DNA_view2d_types.h"
43 #include "DNA_userdef_types.h"
44
45 #include "BIF_gl.h"
46 #include "BIF_interface.h"
47 #include "BIF_previewrender.h"
48 #include "BIF_resources.h"
49 #include "BIF_screen.h"
50 #include "BIF_space.h"
51 #include "BIF_toolbox.h"
52 #include "BIF_butspace.h"
53
54 #include "BKE_global.h"
55 #include "BKE_main.h"
56 #include "BKE_material.h"
57 #include "BKE_node.h"
58
59 #include "BSE_drawipo.h"
60 #include "BSE_headerbuttons.h"
61 #include "BSE_node.h"
62
63 #include "blendef.h"
64 #include "butspace.h"
65 #include "mydevice.h"
66
67 void do_node_buttons(ScrArea *sa, unsigned short event)
68 {
69         SpaceNode *snode= sa->spacedata.first;
70         Material *ma;
71         Tex *tx;
72         
73         switch(event) {
74                 case B_NODE_USEMAT:
75                         ma= (Material *)snode->id;
76                         if(ma) {
77                                 if(ma->use_nodes && ma->nodetree==NULL) {
78                                         node_shader_default(ma);
79                                         snode_set_context(snode);
80                                 }
81                                 BIF_preview_changed(ID_MA);
82                                 allqueue(REDRAWNODE, 0);
83                                 allqueue(REDRAWBUTSSHADING, 0);
84                                 allqueue(REDRAWIPO, 0);
85                         }               
86                         break;
87                         
88                 case B_NODE_USESCENE:
89                         if(G.scene->use_nodes) {
90                                 if(G.scene->nodetree==NULL)
91                                         node_composit_default(G.scene);
92                                 addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
93                         }
94                         snode_set_context(snode);
95                         allqueue(REDRAWNODE, 0);
96                         break;
97                         
98                 case B_NODE_USETEX:
99                         tx = (Tex *)snode->id;
100                         if(tx) {
101                                 tx->type = 0;
102                                 if(tx->use_nodes && tx->nodetree==NULL) {
103                                         node_texture_default(tx);
104                                         snode_set_context(snode);
105                                 }
106                                 BIF_preview_changed(ID_TE);
107                                 allqueue(REDRAWNODE, 0);
108                                 allqueue(REDRAWBUTSSHADING, 0);
109                                 allqueue(REDRAWIPO, 0);
110                         }
111                         break;
112         }
113 }
114
115 static void do_node_viewmenu(void *arg, int event)
116 {
117         SpaceNode *snode= curarea->spacedata.first; 
118         
119         switch(event) {
120                 case 1: /* Zoom in */
121                         snode_zoom_in(curarea);
122                         break;
123                 case 2: /* View all */
124                         snode_zoom_out(curarea);
125                         break;
126                 case 3: /* View all */
127                         snode_home(curarea, snode);
128                         break;
129                 case 4: /* Grease Pencil */
130                         add_blockhandler(curarea, NODES_HANDLER_GREASEPENCIL, UI_PNL_UNSTOW);
131                         break;
132         }
133         allqueue(REDRAWNODE, 0);
134 }
135
136 static uiBlock *node_viewmenu(void *arg_unused)
137 {
138         SpaceNode *snode= curarea->spacedata.first; 
139         uiBlock *block;
140         short yco= 0, menuwidth=120;
141         
142         block= uiNewBlock(&curarea->uiblocks, "node_viewmenu", 
143                                           UI_EMBOSSP, UI_HELV, curarea->headwin);
144         uiBlockSetButmFunc(block, do_node_viewmenu, NULL);
145
146         if (snode->nodetree) {
147                 uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Grease Pencil...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
148                 
149                 uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
150         }
151         
152         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom In|NumPad +", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
153         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom Out|NumPad -", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
154         
155         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
156         
157         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View All|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
158         
159         if (!curarea->full) 
160                 uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
161         else 
162                 uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
163         
164         if(curarea->headertype==HEADERTOP) {
165                 uiBlockSetDirection(block, UI_DOWN);
166         }
167         else {
168                 uiBlockSetDirection(block, UI_TOP);
169                 uiBlockFlipOrder(block);
170         }
171         
172         uiTextBoundsBlock(block, 50);
173         
174         return block;
175 }
176
177 static void do_node_selectmenu(void *arg, int event)
178 {
179         SpaceNode *snode= curarea->spacedata.first; 
180         
181         /* functions in editnode.c assume there's a tree */
182         if(snode->nodetree==NULL)
183                 return;
184         
185         switch(event) {
186                 case 1: /* border select */
187                         node_border_select(snode);
188                         break;
189                 case 2: /* select/deselect all */
190                         node_deselectall(snode, 1);
191                         break;
192                 case 3: /* select linked in */
193                         node_select_linked(snode, 0);
194                         break;
195                 case 4: /* select linked out */
196                         node_select_linked(snode, 1);
197                         break;
198         }
199         allqueue(REDRAWNODE, 0);
200 }
201
202 static uiBlock *node_selectmenu(void *arg_unused)
203 {
204         uiBlock *block;
205         short yco= 0, menuwidth=120;
206         
207         block= uiNewBlock(&curarea->uiblocks, "node_selectmenu", 
208                                           UI_EMBOSSP, UI_HELV, curarea->headwin);
209         uiBlockSetButmFunc(block, do_node_selectmenu, NULL);
210         
211         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
212         
213         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
214         
215         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
216         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Linked From|L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
217         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Linked To|Shift L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
218         
219         if(curarea->headertype==HEADERTOP) {
220                 uiBlockSetDirection(block, UI_DOWN);
221         }
222         else {
223                 uiBlockSetDirection(block, UI_TOP);
224                 uiBlockFlipOrder(block);
225         }
226         
227         uiTextBoundsBlock(block, 50);
228         
229         return block;
230 }
231
232 void do_node_addmenu(void *arg, int event)
233 {
234         SpaceNode *snode= curarea->spacedata.first;
235         bNode *node;
236         float locx, locy;
237         short mval[2];
238         
239         /* store selection in temp test flag */
240         for(node= snode->edittree->nodes.first; node; node= node->next) {
241                 if(node->flag & NODE_SELECT) node->flag |= NODE_TEST;
242                 else node->flag &= ~NODE_TEST;
243         }
244         
245         toolbox_mousepos(mval, 0 ); /* get initial mouse position */
246         areamouseco_to_ipoco(G.v2d, mval, &locx, &locy);
247         node= node_add_node(snode, event, locx, locy);
248         
249         /* uses test flag */
250         snode_autoconnect(snode, node, NODE_TEST);
251                 
252         addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
253         
254         BIF_undo_push("Add Node");
255         
256 }
257
258 static void node_make_addmenu(SpaceNode *snode, int nodeclass, uiBlock *block)
259 {
260         bNodeTree *ntree;
261         int tot= 0, a;
262         short yco= 0, menuwidth=120;
263         
264         ntree = snode->nodetree;
265         if(ntree) {
266                 /* mostly taken from toolbox.c, node_add_sublevel() */
267                 if(ntree) {
268                         if(nodeclass==NODE_CLASS_GROUP) {
269                                 bNodeTree *ngroup= G.main->nodetree.first;
270                                 for(; ngroup; ngroup= ngroup->id.next)
271                                         if(ngroup->type==ntree->type)
272                                                 tot++;
273                         }
274                         else {
275                                 bNodeType *type = ntree->alltypes.first;
276                                 while(type) {
277                                         if(type->nclass == nodeclass)
278                                                 tot++;
279                                         type= type->next;
280                                 }
281                         }
282                 }       
283                 
284                 if(tot==0) {
285                         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
286                         return;
287                 }
288                 
289                 if(nodeclass==NODE_CLASS_GROUP) {
290                         bNodeTree *ngroup= G.main->nodetree.first;
291                         for(tot=0, a=0; ngroup; ngroup= ngroup->id.next, tot++) {
292                                 if(ngroup->type==ntree->type) {
293                                         
294                                         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, (ngroup->id.name+2), 0, 
295                                                 yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, NODE_GROUP_MENU+tot, "");
296                                         a++;
297                                 }
298                         }
299                 }
300                 else {
301                         bNodeType *type;
302                         int script=0;
303                         for(a=0, type= ntree->alltypes.first; type; type=type->next) {
304                                 if( type->nclass == nodeclass ) {
305                                         if(type->type == NODE_DYNAMIC) {
306                                                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, type->name, 0, 
307                                                         yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, NODE_DYNAMIC_MENU+script, "");
308                                                 script++;
309                                         } else {
310                                         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, type->name, 0, 
311                                                 yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, type->type, "");
312                                         }
313                                         a++;
314                                 }
315                         }
316                 }
317         } else {
318                 uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
319                 return;
320         }
321 }
322
323 static uiBlock *node_add_inputmenu(void *arg_unused)
324 {
325         SpaceNode *snode= curarea->spacedata.first;
326         uiBlock *block;
327
328         block= uiNewBlock(&curarea->uiblocks, "node_add_inputmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
329         uiBlockSetButmFunc(block, do_node_addmenu, NULL);
330         
331         node_make_addmenu(snode, NODE_CLASS_INPUT, block);
332         
333         uiBlockSetDirection(block, UI_RIGHT);
334         uiTextBoundsBlock(block, 60);
335         
336         return block;
337 }
338 static uiBlock *node_add_outputmenu(void *arg_unused)
339 {
340         SpaceNode *snode= curarea->spacedata.first;
341         uiBlock *block;
342         
343         block= uiNewBlock(&curarea->uiblocks, "node_add_outputmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
344         uiBlockSetButmFunc(block, do_node_addmenu, NULL);
345         
346         node_make_addmenu(snode, NODE_CLASS_OUTPUT, block);
347         
348         uiBlockSetDirection(block, UI_RIGHT);
349         uiTextBoundsBlock(block, 60);
350         
351         return block;
352 }
353 static uiBlock *node_add_colormenu(void *arg_unused)
354 {
355         SpaceNode *snode= curarea->spacedata.first;
356         uiBlock *block;
357         
358         block= uiNewBlock(&curarea->uiblocks, "node_add_colormenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
359         uiBlockSetButmFunc(block, do_node_addmenu, NULL);
360         
361         node_make_addmenu(snode, NODE_CLASS_OP_COLOR, block);
362         
363         uiBlockSetDirection(block, UI_RIGHT);
364         uiTextBoundsBlock(block, 60);
365         
366         return block;
367 }
368 static uiBlock *node_add_vectormenu(void *arg_unused)
369 {
370         SpaceNode *snode= curarea->spacedata.first;
371         uiBlock *block;
372         
373         block= uiNewBlock(&curarea->uiblocks, "node_add_vectormenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
374         uiBlockSetButmFunc(block, do_node_addmenu, NULL);
375         
376         node_make_addmenu(snode, NODE_CLASS_OP_VECTOR, block);
377         
378         uiBlockSetDirection(block, UI_RIGHT);
379         uiTextBoundsBlock(block, 60);
380         
381         return block;
382 }
383 static uiBlock *node_add_filtermenu(void *arg_unused)
384 {
385         SpaceNode *snode= curarea->spacedata.first;
386         uiBlock *block;
387         
388         block= uiNewBlock(&curarea->uiblocks, "node_add_filtermenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
389         uiBlockSetButmFunc(block, do_node_addmenu, NULL);
390         
391         node_make_addmenu(snode, NODE_CLASS_OP_FILTER, block);
392         
393         uiBlockSetDirection(block, UI_RIGHT);
394         uiTextBoundsBlock(block, 60);
395         
396         return block;
397 }
398 static uiBlock *node_add_convertermenu(void *arg_unused)
399 {
400         SpaceNode *snode= curarea->spacedata.first;
401         uiBlock *block;
402         
403         block= uiNewBlock(&curarea->uiblocks, "node_add_convertermenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
404         uiBlockSetButmFunc(block, do_node_addmenu, NULL);
405         
406         node_make_addmenu(snode, NODE_CLASS_CONVERTOR, block);
407         
408         uiBlockSetDirection(block, UI_RIGHT);
409         uiTextBoundsBlock(block, 60);
410         
411         return block;
412 }
413 static uiBlock *node_add_mattemenu(void *arg_unused)
414 {
415         SpaceNode *snode= curarea->spacedata.first;
416         uiBlock *block;
417         
418         block= uiNewBlock(&curarea->uiblocks, "node_add_mattemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
419         uiBlockSetButmFunc(block, do_node_addmenu, NULL);
420         
421         node_make_addmenu(snode, NODE_CLASS_MATTE, block);
422         
423         uiBlockSetDirection(block, UI_RIGHT);
424         uiTextBoundsBlock(block, 60);
425         
426         return block;
427 }
428 static uiBlock *node_add_distortmenu(void *arg_unused)
429 {
430         SpaceNode *snode= curarea->spacedata.first;
431         uiBlock *block;
432         
433         block= uiNewBlock(&curarea->uiblocks, "node_add_distortmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
434         uiBlockSetButmFunc(block, do_node_addmenu, NULL);
435         
436         node_make_addmenu(snode, NODE_CLASS_DISTORT, block);
437         
438         uiBlockSetDirection(block, UI_RIGHT);
439         uiTextBoundsBlock(block, 60);
440         
441         return block;
442 }
443 static uiBlock *node_add_patternmenu(void *arg_unused)
444 {
445         SpaceNode *snode= curarea->spacedata.first;
446         uiBlock *block;
447         
448         block= uiNewBlock(&curarea->uiblocks, "node_add_patternmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
449         uiBlockSetButmFunc(block, do_node_addmenu, NULL);
450         
451         node_make_addmenu(snode, NODE_CLASS_PATTERN, block);
452         
453         uiBlockSetDirection(block, UI_RIGHT);
454         uiTextBoundsBlock(block, 60);
455         
456         return block;
457 }
458 static uiBlock *node_add_texturemenu(void *arg_unused)
459 {
460         SpaceNode *snode= curarea->spacedata.first;
461         uiBlock *block;
462         
463         block= uiNewBlock(&curarea->uiblocks, "node_add_texturemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
464         uiBlockSetButmFunc(block, do_node_addmenu, NULL);
465         
466         node_make_addmenu(snode, NODE_CLASS_TEXTURE, block);
467         
468         uiBlockSetDirection(block, UI_RIGHT);
469         uiTextBoundsBlock(block, 60);
470         
471         return block;
472 }
473 static uiBlock *node_add_groupmenu(void *arg_unused)
474 {
475         SpaceNode *snode= curarea->spacedata.first;
476         uiBlock *block;
477         
478         block= uiNewBlock(&curarea->uiblocks, "node_add_groupmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
479         uiBlockSetButmFunc(block, do_node_addmenu, NULL);
480         
481         node_make_addmenu(snode, NODE_CLASS_GROUP, block);
482         
483         uiBlockSetDirection(block, UI_RIGHT);
484         uiTextBoundsBlock(block, 60);
485         
486         return block;
487 }
488
489 static uiBlock *node_add_dynamicmenu(void *arg_unused)
490 {
491         SpaceNode *snode= curarea->spacedata.first;
492         uiBlock *block;
493         
494         block= uiNewBlock(&curarea->uiblocks, "node_add_dynamicmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
495         uiBlockSetButmFunc(block, do_node_addmenu, NULL);
496         
497         node_make_addmenu(snode, NODE_CLASS_OP_DYNAMIC, block);
498         
499         uiBlockSetDirection(block, UI_RIGHT);
500         uiTextBoundsBlock(block, 60);
501         
502         return block;
503 }
504
505 static uiBlock *node_addmenu(void *arg_unused)
506 {
507         SpaceNode *snode= curarea->spacedata.first;
508         uiBlock *block;
509         short yco= 0, menuwidth=120;
510         
511         block= uiNewBlock(&curarea->uiblocks, "node_addmenu", 
512                                           UI_EMBOSSP, UI_HELV, curarea->headwin);
513         uiBlockSetButmFunc(block, do_node_addmenu, NULL);
514         
515         if(snode->treetype==NTREE_SHADER) {
516                 uiDefIconTextBlockBut(block, node_add_inputmenu, NULL, ICON_RIGHTARROW_THIN, "Input", 0, yco-=20, 120, 19, "");
517                 uiDefIconTextBlockBut(block, node_add_outputmenu, NULL, ICON_RIGHTARROW_THIN, "Output", 0, yco-=20, 120, 19, "");
518                 uiDefIconTextBlockBut(block, node_add_colormenu, NULL, ICON_RIGHTARROW_THIN, "Color", 0, yco-=20, 120, 19, "");
519                 uiDefIconTextBlockBut(block, node_add_vectormenu, NULL, ICON_RIGHTARROW_THIN, "Vector", 0, yco-=20, 120, 19, "");
520                 uiDefIconTextBlockBut(block, node_add_convertermenu, NULL, ICON_RIGHTARROW_THIN, "Convertor", 0, yco-=20, 120, 19, "");
521                 uiDefIconTextBlockBut(block, node_add_groupmenu, NULL, ICON_RIGHTARROW_THIN, "Group", 0, yco-=20, 120, 19, "");
522                 uiDefIconTextBlockBut(block, node_add_dynamicmenu, NULL, ICON_RIGHTARROW_THIN, "Dynamic", 0, yco-=20, 120, 19, "");
523         }
524         else if(snode->treetype==NTREE_COMPOSIT) {
525                 uiDefIconTextBlockBut(block, node_add_inputmenu, NULL, ICON_RIGHTARROW_THIN, "Input", 0, yco-=20, 120, 19, "");
526                 uiDefIconTextBlockBut(block, node_add_outputmenu, NULL, ICON_RIGHTARROW_THIN, "Output", 0, yco-=20, 120, 19, "");
527                 uiDefIconTextBlockBut(block, node_add_colormenu, NULL, ICON_RIGHTARROW_THIN, "Color", 0, yco-=20, 120, 19, "");
528                 uiDefIconTextBlockBut(block, node_add_vectormenu, NULL, ICON_RIGHTARROW_THIN, "Vector", 0, yco-=20, 120, 19, "");
529                 uiDefIconTextBlockBut(block, node_add_filtermenu, NULL, ICON_RIGHTARROW_THIN, "Filter", 0, yco-=20, 120, 19, "");
530                 uiDefIconTextBlockBut(block, node_add_convertermenu, NULL, ICON_RIGHTARROW_THIN, "Convertor", 0, yco-=20, 120, 19, "");
531                 uiDefIconTextBlockBut(block, node_add_mattemenu, NULL, ICON_RIGHTARROW_THIN, "Matte", 0, yco-=20, 120, 19, "");
532                 uiDefIconTextBlockBut(block, node_add_distortmenu, NULL, ICON_RIGHTARROW_THIN, "Distort", 0, yco-=20, 120, 19, "");
533                 uiDefIconTextBlockBut(block, node_add_groupmenu, NULL, ICON_RIGHTARROW_THIN, "Group", 0, yco-=20, 120, 19, "");
534
535         } else if(snode->treetype==NTREE_TEXTURE) {
536                 uiDefIconTextBlockBut(block, node_add_inputmenu, NULL, ICON_RIGHTARROW_THIN, "Input", 0, yco-=20, 120, 19, "");
537                 uiDefIconTextBlockBut(block, node_add_outputmenu, NULL, ICON_RIGHTARROW_THIN, "Output", 0, yco-=20, 120, 19, "");
538                 uiDefIconTextBlockBut(block, node_add_colormenu, NULL, ICON_RIGHTARROW_THIN, "Color", 0, yco-=20, 120, 19, "");
539                 uiDefIconTextBlockBut(block, node_add_patternmenu, NULL, ICON_RIGHTARROW_THIN, "Patterns", 0, yco-=20, 120, 19, "");
540                 uiDefIconTextBlockBut(block, node_add_texturemenu, NULL, ICON_RIGHTARROW_THIN, "Textures", 0, yco-=20, 120, 19, "");
541                 uiDefIconTextBlockBut(block, node_add_convertermenu, NULL, ICON_RIGHTARROW_THIN, "Convertor", 0, yco-=20, 120, 19, "");
542                 uiDefIconTextBlockBut(block, node_add_distortmenu, NULL, ICON_RIGHTARROW_THIN, "Distort", 0, yco-=20, 120, 19, "");
543                 uiDefIconTextBlockBut(block, node_add_groupmenu, NULL, ICON_RIGHTARROW_THIN, "Group", 0, yco-=20, 120, 19, "");
544         }
545         else
546                 uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); 
547         
548         if(curarea->headertype==HEADERTOP) {
549                 uiBlockSetDirection(block, UI_DOWN);
550         }
551         else {
552                 uiBlockSetDirection(block, UI_TOP);
553                 uiBlockFlipOrder(block);
554         }
555         
556         uiTextBoundsBlock(block, 50);
557         
558         return block;
559 }
560
561 static void do_node_nodemenu(void *arg, int event)
562 {
563         SpaceNode *snode= curarea->spacedata.first; 
564         int fromlib=0;
565         
566         /* functions in editnode.c assume there's a tree */
567         if(snode->nodetree==NULL)
568                 return;
569         fromlib= (snode->id && snode->id->lib);
570         
571         switch(event) {
572                 case 1: /* grab/move */
573                         node_transform_ext(0,0);
574                         break;
575                 case 2: /* duplicate */
576                         if(fromlib) fromlib= -1;
577                         else node_adduplicate(snode);
578                         break;
579                 case 3: /* delete */
580                         if(fromlib) fromlib= -1;
581                         else node_delete(snode);
582                         break;
583                 case 4: /* make group */
584                         node_make_group(snode);
585                         break;
586                 case 5: /* ungroup */
587                         node_ungroup(snode);
588                         break;
589                 case 6: /* edit group */
590                         if(fromlib) fromlib= -1;
591                         else snode_make_group_editable(snode, NULL);
592                         break;
593                 case 7: /* hide/unhide */
594                         node_hide(snode);
595                         break;
596                 case 8: /* read saved render layers */
597                         node_read_renderlayers(snode);
598                         break;
599                 case 9: /* show cyclic */
600                         ntreeSolveOrder(snode->edittree);
601                         break;
602                 case 10: /* execute */
603                         addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
604                         break;
605                 case 11: /* make link */
606                         node_make_link(snode);
607                         break;
608                 case 12: /* rename */
609                         node_rename(snode);
610                         break;
611                 case 13: /* read saved full sample layers */
612                         node_read_fullsamplelayers(snode);
613                         break;
614                 case 14: /* connect viewer */
615                         node_active_link_viewer(snode);
616                         break;
617                         
618         }
619         
620         if(fromlib==-1) error_libdata();
621         allqueue(REDRAWNODE, 0);
622 }
623
624 static uiBlock *node_nodemenu(void *arg_unused)
625 {
626         SpaceNode *snode= curarea->spacedata.first; 
627         uiBlock *block;
628         short yco= 0, menuwidth=120;
629         
630         block= uiNewBlock(&curarea->uiblocks, "node_nodemenu", 
631                                           UI_EMBOSSP, UI_HELV, curarea->headwin);
632         uiBlockSetButmFunc(block, do_node_nodemenu, NULL);
633         
634         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move|G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
635         
636         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
637         
638         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate|Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
639         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
640         
641         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
642
643         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Link|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
644
645         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
646         
647         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Group|Ctrl G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
648         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Ungroup|Alt G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
649         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Edit Group|Tab", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
650         
651         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
652         
653         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide/Unhide|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
654         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rename|Ctrl R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
655         
656         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
657         
658         if(snode->treetype==NTREE_COMPOSIT) {
659                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Execute Composite|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
660                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Render Results|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
661                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Full Sample Results|Shift R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
662                 
663                 uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
664                 
665                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Connect Node to Viewer|Ctrl RMB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
666                 
667                 uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
668         }
669         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Cyclic Dependencies|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
670         
671         if(curarea->headertype==HEADERTOP) {
672                 uiBlockSetDirection(block, UI_DOWN);
673         }
674         else {
675                 uiBlockSetDirection(block, UI_TOP);
676                 uiBlockFlipOrder(block);
677         }
678         
679         uiTextBoundsBlock(block, 50);
680         
681         return block;
682 }
683
684 void node_buttons(ScrArea *sa)
685 {
686         SpaceNode *snode= sa->spacedata.first;
687         uiBlock *block;
688         short xco, xmax;
689         char name[256];
690         
691         sprintf(name, "header %d", sa->headwin);
692         block= uiNewBlock(&sa->uiblocks, name, UI_EMBOSS, UI_HELV, sa->headwin);
693
694         if(area_is_active_area(sa)) uiBlockSetCol(block, TH_HEADER);
695         else uiBlockSetCol(block, TH_HEADERDESEL);
696         
697         sa->butspacetype= SPACE_NODE;
698
699         xco = 8;
700         
701         uiDefIconTextButC(block, ICONTEXTROW,B_NEWSPACE, ICON_VIEW3D, 
702                                           windowtype_pup(), xco, 0, XIC+10, YIC, 
703                                           &(sa->butspacetype), 1.0, SPACEICONMAX, 0, 0, 
704                                           "Displays Current Window Type");
705
706         xco += XIC + 14;
707
708         uiBlockSetEmboss(block, UI_EMBOSSN);
709         if (sa->flag & HEADER_NO_PULLDOWN) {
710                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, 
711                                           ICON_DISCLOSURE_TRI_RIGHT, xco,2,XIC,YIC-2,
712                                           &(sa->flag), 0, 0, 0, 0,  "Show pulldown menus");
713         }
714         else {
715                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, 
716                                           ICON_DISCLOSURE_TRI_DOWN,  xco,2,XIC,YIC-2,
717                                           &(sa->flag), 0, 0, 0, 0,  "Hide pulldown menus");
718         }
719         xco+=XIC;
720
721         if((sa->flag & HEADER_NO_PULLDOWN)==0) {
722                 /* pull down menus */
723                 uiBlockSetEmboss(block, UI_EMBOSSP);
724         
725                 xmax= GetButStringLength("View");
726                 uiDefPulldownBut(block, node_viewmenu, NULL, 
727                                           "View", xco, -2, xmax-3, 24, "");
728                 xco+= xmax;
729                 
730                 xmax= GetButStringLength("Select");
731                 uiDefPulldownBut(block, node_selectmenu, NULL, 
732                                                  "Select", xco, -2, xmax-3, 24, "");
733                 xco+= xmax;
734                 
735                 xmax= GetButStringLength("Add");
736                 uiDefPulldownBut(block, node_addmenu, NULL, 
737                                                  "Add", xco, -2, xmax-3, 24, "");
738                 xco+= xmax;
739                 
740                 xmax= GetButStringLength("Node");
741                 uiDefPulldownBut(block, node_nodemenu, NULL, 
742                                                  "Node", xco, -2, xmax-3, 24, "");
743                 xco+= xmax;
744         }
745         
746         uiBlockSetEmboss(block, UI_EMBOSS);
747         
748         /* main type choosing */
749         uiBlockBeginAlign(block);
750         uiDefIconButI(block, ROW, B_REDR, ICON_MATERIAL_DEHLT, xco,2,XIC,YIC-2,
751                                   &(snode->treetype), 2, 0, 0, 0, "Material Nodes");
752         xco+= XIC;
753         uiDefIconButI(block, ROW, B_REDR, ICON_IMAGE_DEHLT, xco,2,XIC,YIC-2,
754                                   &(snode->treetype), 2, 1, 0, 0, "Composite Nodes");
755         xco+= XIC;
756         uiDefIconButI(block, ROW, B_REDR, ICON_TEXTURE_DEHLT, xco,2,XIC,YIC-2,
757                                   &(snode->treetype), 2, 2, 0, 0, "Texture Nodes");
758         xco+= 2*XIC;
759         uiBlockEndAlign(block);
760         
761         /* find and set the context */
762         snode_set_context(snode);
763         
764         if(snode->treetype==NTREE_SHADER) {
765                 if(snode->from) {
766                                                                                 /* 0, NULL -> pin */
767                         xco= std_libbuttons(block, xco, 0, 0, NULL, B_MATBROWSE, ID_MA, 1, snode->id, snode->from, &(snode->menunr), 
768                                            B_MATALONE, B_MATLOCAL, B_MATDELETE, B_AUTOMATNAME, B_KEEPDATA);
769                         
770                         if(snode->id) {
771                                 Material *ma= (Material *)snode->id;
772                                 uiDefButC(block, TOG, B_NODE_USEMAT, "Use Nodes", xco+5,0,70,19, &ma->use_nodes, 0.0f, 0.0f, 0, 0, "");
773                                 xco+=80;
774                         }
775                 }
776         }
777         else if(snode->treetype==NTREE_COMPOSIT) {
778                 uiDefButS(block, TOG, B_NODE_USESCENE, "Use Nodes", xco+5,0,70,19, &G.scene->use_nodes, 0.0f, 0.0f, 0, 0, "Indicate this Scene will use Nodes and execute them while editing");
779                 xco+= 80;
780                 uiDefButBitI(block, TOG, R_COMP_FREE, B_NOP, "Free Unused", xco+5,0,80,19, &G.scene->r.scemode, 0.0f, 0.0f, 0, 0, "Free Nodes that are not used while composite");
781                 xco+= 80;
782                 uiDefButBitS(block, TOG, SNODE_BACKDRAW, REDRAWNODE, "Backdrop", xco+5,0,80,19, &snode->flag, 0.0f, 0.0f, 0, 0, "Use active Viewer Node output as backdrop");
783                 xco+= 80;
784         }
785         else if(snode->treetype==NTREE_TEXTURE) {
786                 if(snode->from) {
787                         
788                         xco= std_libbuttons(block, xco, 0, 0, NULL, B_TEXBROWSE, ID_TE, 1, snode->id, snode->from, &(snode->menunr), 
789                                            B_TEXALONE, B_TEXLOCAL, B_TEXDELETE, B_AUTOTEXNAME, B_KEEPDATA);
790                         
791                         if(snode->id) {
792                                 Tex *tx= (Tex *)snode->id;
793                                 uiDefButC(block, TOG, B_NODE_USETEX, "Use Nodes", xco+5,0,70,19, &tx->use_nodes, 0.0f, 0.0f, 0, 0, "");
794                                 xco+=80;
795                         }
796                 }
797         }
798         
799         /* always as last  */
800         sa->headbutlen= xco+2*XIC;
801
802         uiDrawBlock(block);
803 }