Two in one:
[blender.git] / source / blender / src / toolbox.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #define PY_TOOLBOX 1
34
35 #include <math.h>
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <stdarg.h>
40
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif
44
45 #ifndef WIN32
46 #include <unistd.h>
47 #else
48 #include <io.h>
49 #endif   
50
51 #include <fcntl.h>
52 #include "MEM_guardedalloc.h"
53
54 #include "BMF_Api.h"
55 #include "BIF_language.h"
56 #include "BIF_resources.h"
57
58 #include "DNA_group_types.h"
59 #include "DNA_image_types.h"
60 #include "DNA_lamp_types.h"
61 #include "DNA_mesh_types.h"
62 #include "DNA_node_types.h"
63 #include "DNA_object_types.h"
64 #include "DNA_screen_types.h"
65 #include "DNA_space_types.h"
66 #include "DNA_scene_types.h"
67 #include "DNA_userdef_types.h"
68 #include "DNA_view3d_types.h"
69 #include "DNA_camera_types.h"
70
71 #include "BLI_blenlib.h"
72 #include "BLI_arithb.h"
73
74 #include "BKE_displist.h"
75 #include "BKE_depsgraph.h"
76 #include "BKE_global.h"
77 #include "BKE_image.h"
78 #include "BKE_library.h"
79 #include "BKE_mesh.h"
80 #include "BKE_node.h"
81 #include "BKE_main.h"
82 #include "BKE_plugin_types.h"
83 #include "BKE_utildefines.h"
84
85 #include "BIF_editnla.h"
86 #include "BIF_editarmature.h"
87 #include "BIF_editdeform.h"
88 #include "BIF_editfont.h"
89 #include "BIF_editmesh.h"
90 #include "BIF_editseq.h"
91 #include "BIF_editlattice.h"
92 #include "BIF_editsima.h"
93 #include "BIF_editoops.h"
94 #include "BIF_editview.h"
95 #include "BIF_gl.h"
96 #include "BIF_graphics.h"
97 #include "BIF_imasel.h"
98 #include "BIF_interface.h"
99 #include "BIF_mainqueue.h"
100 #include "BIF_mywindow.h"
101 #include "BIF_renderwin.h"
102 #include "BIF_screen.h"
103 #include "BIF_space.h"
104 #include "BIF_toolbox.h"
105 #include "BIF_tbcallback.h"
106 #include "BIF_transform.h"
107
108 #include "BDR_editobject.h"
109 #include "BDR_editcurve.h"
110 #include "BDR_editmball.h"
111
112 #include "BSE_drawipo.h"
113 #include "BSE_edit.h"
114 #include "BSE_editipo.h"
115 #include "BSE_filesel.h"
116 #include "BSE_headerbuttons.h"
117 #include "BSE_node.h"
118
119 #include "IMB_imbuf.h"
120
121 #include "blendef.h"
122 #include "butspace.h"
123 #include "mydevice.h"
124
125 void asciitoraw(int ch, unsigned short *event, unsigned short *qual)
126 {
127         if( isalpha(ch)==0 ) return;
128         
129         if( isupper(ch) ) {
130                 *qual= LEFTSHIFTKEY;
131                 ch= tolower(ch);
132         }
133         
134         switch(ch) {
135         case 'a': *event= AKEY; break;
136         case 'b': *event= BKEY; break;
137         case 'c': *event= CKEY; break;
138         case 'd': *event= DKEY; break;
139         case 'e': *event= EKEY; break;
140         case 'f': *event= FKEY; break;
141         case 'g': *event= GKEY; break;
142         case 'h': *event= HKEY; break;
143         case 'i': *event= IKEY; break;
144         case 'j': *event= JKEY; break;
145         case 'k': *event= KKEY; break;
146         case 'l': *event= LKEY; break;
147         case 'm': *event= MKEY; break;
148         case 'n': *event= NKEY; break;
149         case 'o': *event= OKEY; break;
150         case 'p': *event= PKEY; break;
151         case 'q': *event= QKEY; break;
152         case 'r': *event= RKEY; break;
153         case 's': *event= SKEY; break;
154         case 't': *event= TKEY; break;
155         case 'u': *event= UKEY; break;
156         case 'v': *event= VKEY; break;
157         case 'w': *event= WKEY; break;
158         case 'x': *event= XKEY; break;
159         case 'y': *event= YKEY; break;
160         case 'z': *event= ZKEY; break;
161         }
162 }
163
164 /* ************************************  */
165
166 /* this va_ stuff allows printf() style codes in these menus */
167
168 static int vconfirm(char *title, char *itemfmt, va_list ap)
169 {
170         char *s, buf[512];
171
172         s= buf;
173         if (title) s+= sprintf(s, "%s%%t|", title);
174         vsprintf(s, itemfmt, ap);
175         
176         return (pupmenu(buf)>=0);
177 }
178
179 static int confirm(char *title, char *itemfmt, ...)
180 {
181         va_list ap;
182         int ret;
183         
184         va_start(ap, itemfmt);
185         ret= vconfirm(title, itemfmt, ap);
186         va_end(ap);
187         
188         return ret;
189 }
190
191 int okee(char *str, ...)
192 {
193         va_list ap;
194         int ret;
195         char titlestr[256];
196         
197         sprintf(titlestr, "OK? %%i%d", ICON_HELP);
198         
199         va_start(ap, str);
200         ret= vconfirm(titlestr, str, ap);
201         va_end(ap);
202         
203         return ret;
204 }
205
206 void notice(char *str, ...)
207 {
208         va_list ap;
209         
210         va_start(ap, str);
211         vconfirm(NULL, str, ap);
212         va_end(ap);
213 }
214
215 void error(char *fmt, ...)
216 {
217         va_list ap;
218         char nfmt[256];
219         char titlestr[256];
220         
221         sprintf(titlestr, "Error %%i%d", ICON_ERROR);
222         
223         sprintf(nfmt, "%s", fmt);
224         
225         va_start(ap, fmt);
226         if (G.background || !G.curscreen) {
227                 vprintf(nfmt, ap);
228                 printf("\n");
229         } else {
230                 vconfirm(titlestr, nfmt, ap);
231         }
232         va_end(ap);
233 }
234
235 int saveover(char *file)
236 {
237         int len= strlen(file);
238         
239         if(len==0) 
240                 return 0;
241         
242         if(BLI_exists(file)==0)
243                 return 1;
244         
245         if( file[len-1]=='/' || file[len-1]=='\\' ) {
246                 error("Cannot overwrite a directory");
247                 return 0;
248         }
249                 
250         return confirm("Save over", file);
251 }
252
253 /* ****************** EXTRA STUFF **************** */
254
255 short button(short *var, short min, short max, char *str)
256 {
257         uiBlock *block;
258         ListBase listb={0, 0};
259         short x1,y1;
260         short mval[2], ret=0;
261
262         if(min>max) min= max;
263
264         getmouseco_sc(mval);
265         
266         if(mval[0]<150) mval[0]=150;
267         if(mval[1]<30) mval[1]=30;
268         if(mval[0]>G.curscreen->sizex) mval[0]= G.curscreen->sizex-10;
269         if(mval[1]>G.curscreen->sizey) mval[1]= G.curscreen->sizey-10;
270
271         block= uiNewBlock(&listb, "button", UI_EMBOSS, UI_HELV, G.curscreen->mainwin);
272         uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_ENTER_OK);
273
274         x1=mval[0]-150; 
275         y1=mval[1]-20; 
276         
277         uiDefButS(block, NUM, 0, str,   (short)(x1+5),(short)(y1+10),125,20, var,(float)min,(float)max, 0, 0, "");
278         uiDefBut(block, BUT, 32767, "OK",       (short)(x1+136),(short)(y1+10),25,20, NULL, 0, 0, 0, 0, "");
279
280         uiBoundsBlock(block, 5);
281
282         ret= uiDoBlocks(&listb, 0);
283
284         if(ret==UI_RETURN_OK) return 1;
285         return 0;
286 }
287
288 short sbutton(char *var, float min, float max, char *str)
289 {
290         uiBlock *block;
291         ListBase listb={0, 0};
292         short x1,y1;
293         short mval[2], ret=0;
294
295         if(min>max) min= max;
296
297         getmouseco_sc(mval);
298         
299         if(mval[0]<150) mval[0]=150;
300         if(mval[1]<30) mval[1]=30;
301         if(mval[0]>G.curscreen->sizex) mval[0]= G.curscreen->sizex-10;
302         if(mval[1]>G.curscreen->sizey) mval[1]= G.curscreen->sizey-10;
303
304         block= uiNewBlock(&listb, "button", UI_EMBOSS, UI_HELV, G.curscreen->mainwin);
305         uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_ENTER_OK);
306
307         x1=mval[0]-150; 
308         y1=mval[1]-20; 
309         
310         uiDefButC(block, TEX, 32766, str,       x1+5,y1+10,125,20, var,(float)min,(float)max, 0, 0, "");
311         uiDefBut(block, BUT, 32767, "OK",       x1+136,y1+10,25,20, NULL, 0, 0, 0, 0, "");
312
313         uiBoundsBlock(block, 5);
314         
315         mainqenter_ext(BUT_ACTIVATE, 32766, 0); /* note, button id '32766' is asking for errors some day! */
316         ret= uiDoBlocks(&listb, 0);
317
318         if(ret==UI_RETURN_OK) return 1;
319         return 0;
320 }
321
322 short fbutton(float *var, float min, float max, float a1, float a2, char *str)
323 {
324         uiBlock *block;
325         ListBase listb={0, 0};
326         short x1,y1;
327         short mval[2], ret=0;
328
329         if(min>max) min= max;
330
331         getmouseco_sc(mval);
332         
333         if(mval[0]<150) mval[0]=150;
334         if(mval[1]<30) mval[1]=30;
335         if(mval[0]>G.curscreen->sizex) mval[0]= G.curscreen->sizex-10;
336         if(mval[1]>G.curscreen->sizey) mval[1]= G.curscreen->sizey-10;
337
338         block= uiNewBlock(&listb, "button", UI_EMBOSS, UI_HELV, G.curscreen->mainwin);
339         uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
340
341         x1=mval[0]-150; 
342         y1=mval[1]-20; 
343         
344         uiDefButF(block, NUM, 0, str,(short)(x1+5),(short)(y1+10),125,20, var, min, max, a1, a2, "");
345         uiDefBut(block, BUT, 32767, "OK",(short)(x1+136),(short)(y1+10), 35, 20, NULL, 0, 0, 0, 0, "");
346
347         uiBoundsBlock(block, 2);
348
349         ret= uiDoBlocks(&listb, 0);
350
351         if(ret==UI_RETURN_OK) return 1;
352         return 0;
353 }
354
355 int movetolayer_buts(unsigned int *lay, char *title)
356 {
357         uiBlock *block;
358         ListBase listb={0, 0};
359         int dx, dy, a, x1, y1, sizex=160, sizey=30;
360         short pivot[2], mval[2], ret=0;
361         
362         if(G.vd->localview) {
363                 error("Not in localview ");
364                 return ret;
365         }
366
367         getmouseco_sc(mval);
368
369         pivot[0]= CLAMPIS(mval[0], (sizex+10), G.curscreen->sizex-30);
370         pivot[1]= CLAMPIS(mval[1], (sizey/2)+10, G.curscreen->sizey-(sizey/2)-10);
371         
372         if (pivot[0]!=mval[0] || pivot[1]!=mval[1])
373                 warp_pointer(pivot[0], pivot[1]);
374
375         mywinset(G.curscreen->mainwin);
376         
377         x1= pivot[0]-sizex+10; 
378         y1= pivot[1]-sizey/2; 
379
380         block= uiNewBlock(&listb, "button", UI_EMBOSS, UI_HELV, G.curscreen->mainwin);
381         uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT|UI_BLOCK_ENTER_OK);
382         
383         dx= (sizex-5)/12;
384         dy= sizey/2;
385         
386         if(title)
387                 uiDefBut(block, LABEL, 0, title, (short)(x1), (short)y1+30, sizex, 20, NULL, 1, 0, 0, 0, "");
388         
389         /* buttons have 0 as return event, to prevent menu to close on hotkeys */
390         uiBlockBeginAlign(block);
391         for(a=0; a<5; a++) 
392                 uiDefButBitI(block, TOGR, 1<<a, 0, "",(short)(x1+a*dx),(short)(y1+dy),(short)dx,(short)dy, lay, 0, 0, 0, 0, "");
393         for(a=0; a<5; a++) 
394                 uiDefButBitI(block, TOGR, 1<<(a+10), 0, "",(short)(x1+a*dx),(short)y1,(short)dx,(short)dy, lay, 0, 0, 0, 0, "");
395         x1+= 5;
396         
397         uiBlockBeginAlign(block);
398         for(a=5; a<10; a++) 
399                 uiDefButBitI(block, TOGR, 1<<a, 0, "",(short)(x1+a*dx),(short)(y1+dy),(short)dx,(short)dy, lay, 0, 0, 0, 0, "");
400         for(a=5; a<10; a++) 
401                 uiDefButBitI(block, TOGR, 1<<(a+10), 0, "",(short)(x1+a*dx),(short)y1,(short)dx,(short)dy, lay, 0, 0, 0, 0, "");
402         uiBlockEndAlign(block);
403
404         x1-= 5;
405         uiDefBut(block, BUT, 32767, "OK", (short)(x1+10*dx+10), (short)y1, (short)(3*dx), (short)(2*dy), NULL, 0, 0, 0, 0, "");
406
407         uiBoundsBlock(block, 2);
408
409         ret= uiDoBlocks(&listb, 0);
410
411         if(ret==UI_RETURN_OK) return 1;
412         return 0;
413 }
414
415 /* armature or bone */
416 int movetolayer_short_buts(short *lay, char *title)
417 {
418         uiBlock *block;
419         ListBase listb={0, 0};
420         int dx, dy, a, x1, y1, sizex=120, sizey=30;
421         short pivot[2], mval[2], ret=0;
422         
423         getmouseco_sc(mval);
424         
425         pivot[0]= CLAMPIS(mval[0], (sizex+10), G.curscreen->sizex-30);
426         pivot[1]= CLAMPIS(mval[1], (sizey/2)+10, G.curscreen->sizey-(sizey/2)-10);
427         
428         if (pivot[0]!=mval[0] || pivot[1]!=mval[1])
429                 warp_pointer(pivot[0], pivot[1]);
430         
431         mywinset(G.curscreen->mainwin);
432         
433         x1= pivot[0]-sizex+10; 
434         y1= pivot[1]-sizey/2; 
435         
436         block= uiNewBlock(&listb, "button", UI_EMBOSS, UI_HELV, G.curscreen->mainwin);
437         uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT|UI_BLOCK_ENTER_OK);
438         
439         dx= (sizex-5)/10;
440         dy= sizey/2;
441         
442         if(title)
443                 uiDefBut(block, LABEL, 0, title, (short)(x1), (short)y1+30, sizex, 20, NULL, 1, 0, 0, 0, "");
444
445         /* buttons have 0 as return event, to prevent menu to close on hotkeys */
446         uiBlockBeginAlign(block);
447         for(a=0; a<8; a++) 
448                 uiDefButBitS(block, TOGR, 1<<a, 0, "",(short)(x1+a*dx),(short)(y1+dy),(short)dx,(short)dy, lay, 0, 0, 0, 0, "");
449         for(a=0; a<8; a++) 
450                 uiDefButBitS(block, TOGR, 1<<(a+8), 0, "",(short)(x1+a*dx),(short)y1,(short)dx,(short)dy, lay, 0, 0, 0, 0, "");
451         
452         uiBlockEndAlign(block);
453         
454         x1-= 5;
455         uiDefBut(block, BUT, 32767, "OK", (short)(x1+8*dx+10), (short)y1, (short)(3*dx), (short)(2*dy), NULL, 0, 0, 0, 0, "");
456         
457         uiBoundsBlock(block, 2);
458         
459         ret= uiDoBlocks(&listb, 0);
460         
461         if(ret==UI_RETURN_OK) return 1;
462         return 0;
463 }
464
465
466 /* ********************** CLEVER_NUMBUTS ******************** */
467
468 #define MAXNUMBUTS      120
469 #define MAXNUMBUTROWS   8
470
471 VarStruct numbuts[MAXNUMBUTS];
472 void *numbpoin[MAXNUMBUTS];
473 int numbdata[MAXNUMBUTS];
474
475 void draw_numbuts_tip(char *str, int x1, int y1, int x2, int y2)
476 {
477         static char *last=0;    /* avoid ugly updates! */
478         int temp;
479         
480         if(str==last) return;
481         last= str;
482         if(str==0) return;
483
484         glColor3ub(160, 160, 160); /* MGREY */
485         glRecti(x1+4,  y2-36,  x2-4,  y2-16);
486
487         cpack(0x0);
488
489         temp= 0;
490         while( BIF_GetStringWidth(G.fonts, str+temp, (U.transopts & USER_TR_BUTTONS))>(x2 - x1-24)) temp++;
491         glRasterPos2i(x1+16, y2-30);
492         BIF_DrawString(G.fonts, str+temp, (U.transopts & USER_TR_BUTTONS));
493 }
494
495 int do_clever_numbuts(char *name, int tot, int winevent)
496 {
497         ListBase listb= {NULL, NULL};
498         uiBlock *block;
499         VarStruct *varstr;
500         int a, sizex, sizey, x1, y2, width, colunms=1, xi=0, yi=0;
501         short mval[2], event;
502         
503         /* Clear all events so tooltips work, this is not ideal and
504         only needed because calls from the menu still have some events
505         left over when do_clever_numbuts is called.
506         Calls from keyshortcuts do not have this problem.*/
507         ScrArea *sa;
508         BWinEvent temp_bevt;
509         for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
510                 if(sa->win) {
511                         while( bwin_qread( sa->win, &temp_bevt ) ) {}
512                 }
513                 if(sa->headwin) {
514                         while( bwin_qread( sa->headwin, &temp_bevt ) ) {}
515                 }
516         }
517         /* Done clearing events */
518         
519         if(tot<=0 || tot>MAXNUMBUTS) return 0;
520         
521         /* if we have too many buttons then have more then 1 column */
522         colunms= (int)ceil((double)tot / (double)MAXNUMBUTROWS);
523         
524         getmouseco_sc(mval);
525
526         /* size */
527         sizex= 175;
528         sizey= 30+20*(MIN2(MAXNUMBUTROWS, tot)+1);
529         width= (sizex*colunms)+60;
530         
531         /* center */
532         if(mval[0]<width/2) mval[0]=width/2;
533         if(mval[1]<sizey/2) mval[1]=sizey/2;
534         if(mval[0]>G.curscreen->sizex -width/2) mval[0]= G.curscreen->sizex -width/2;
535         if(mval[1]>G.curscreen->sizey -sizey/2) mval[1]= G.curscreen->sizey -sizey/2;
536
537         mywinset(G.curscreen->mainwin);
538         
539         x1= mval[0]-width/2; 
540         y2= mval[1]+sizey/2;
541         
542         block= uiNewBlock(&listb, "numbuts", UI_EMBOSS, UI_HELV, G.curscreen->mainwin);
543         uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_ENTER_OK);
544         
545         /* WATCH IT: TEX BUTTON EXCEPTION */
546         /* WARNING: ONLY A SINGLE BIT-BUTTON POSSIBLE: WE WORK AT COPIED DATA! */
547         
548         BIF_ThemeColor(TH_MENU_TEXT); /* makes text readable on dark theme */
549         
550         uiDefBut(block, LABEL, 0, name, (short)(x1+15), (short)(y2-35), (short)(width-60), 19, 0, 1.0, 0.0, 0, 0, ""); 
551         
552         /*
553         if(name[0]=='A' && name[7]=='O') {
554                 y2 -= 20;
555                 uiDefBut(block, LABEL, 0, "Rotations in degrees!",      (short)(x1+15), (short)(y2-35), (short)(sizex-60), 19, 0, 0.0, 0.0, 0, 0, "");
556         }*/
557         
558         uiBlockBeginAlign(block);
559         varstr= &numbuts[0];
560         for(a=0; a<tot; a++, varstr++) {
561                 
562                 if(varstr->type==TEX) {
563                         uiDefBut(block, TEX, 0, varstr->name,(short)((x1+15) + (sizex*xi)),(short)(y2-55- 20*yi),(short)(sizex), 19, numbpoin[a], varstr->min, varstr->max, 0, 0, varstr->tip);
564                 }
565                 else  {
566                         if(varstr->type==LABEL) {/* dont include the label when rounding the buttons */
567                                 uiBlockEndAlign(block);
568                         
569                                 /* using the tip for the name, this is incorrect lets us get around the 16 char limit of name */
570                                 /* Changed from the line below to use the tip since the tip isnt used for a label */
571                                 uiDefBut(block, varstr->type, 0, varstr->tip,(short)((x1+15) + (sizex*xi)),(short)(y2-55-20*yi), (short)(sizex), 19, &(numbdata[a]), varstr->min, varstr->max, 100, 0, "");
572                         } else {
573                                 uiDefBut(block, varstr->type, 0, varstr->name,(short)((x1+15) + (sizex*xi)),(short)(y2-55-20*yi), (short)(sizex), 19, &(numbdata[a]), varstr->min, varstr->max, 100, 0, varstr->tip);
574                         }
575                         
576                         if(varstr->type==LABEL)
577                                 uiBlockBeginAlign(block);
578                 }
579                 
580                 /* move to the next column */
581                 yi++;
582                 if (yi>=MAXNUMBUTROWS) {
583                         yi=0;
584                         xi++;
585                         uiBlockEndAlign(block);
586                         uiBlockBeginAlign(block);
587                 }
588         }
589         uiBlockEndAlign(block);
590
591         uiDefBut(block, BUT, 4000, "OK", (short)(x1+width-40),(short)(y2-35-20*MIN2(MAXNUMBUTROWS,a)), 25, (short)(sizey-50), 0, 0, 0, 0, 0, "OK: Assign Values");
592         
593         uiBoundsBlock(block, 5);
594
595         event= uiDoBlocks(&listb, 0);
596
597         areawinset(curarea->win);
598         
599         if(event & UI_RETURN_OK) {
600                 
601                 varstr= &numbuts[0];
602                 for(a=0; a<tot; a++, varstr++) {
603                         if(varstr->type==TEX);
604                         else if ELEM( (varstr->type & BUTPOIN), FLO, INT ) memcpy(numbpoin[a], numbdata+a, 4);
605                         else if((varstr->type & BUTPOIN)==SHO ) *((short *)(numbpoin[a]))= *( (short *)(numbdata+a));
606                 }
607                 
608                 if(winevent) {
609                         ScrArea *sa;
610                 
611                         sa= G.curscreen->areabase.first;
612                         while(sa) {
613                                 if(sa->spacetype==curarea->spacetype) addqueue(sa->win, winevent, 1);
614                                 sa= sa->next;
615                         }
616                 }
617                 
618                 return 1;
619         }
620         return 0;
621 }
622
623 void add_numbut(int nr, int type, char *str, float min, float max, void *poin, char *tip)
624 {
625         int tip_max = sizeof(numbuts[nr].tip);
626         int name_max = sizeof(numbuts[nr].name);
627
628         if(nr >= MAXNUMBUTS || (nr < 0)) return;
629
630         numbuts[nr].type= type;
631         
632         numbuts[nr].min= min;
633         numbuts[nr].max= max;
634         
635         if (type==LABEL) {
636                 /* evil use it tooltip for the label string to get around the 16 char limit of "name" */
637                 if (str) {
638                         strncpy(numbuts[nr].tip, str, tip_max);
639                         numbuts[nr].tip[tip_max-1] = 0;
640                 } else {
641                         strcpy(numbuts[nr].tip, "");
642                 }
643         } else {
644                 /* for all other types */
645                 if (str) {
646                         strncpy(numbuts[nr].name, str, name_max);
647                         numbuts[nr].name[name_max-1] = 0;
648                 } else {
649                         strcpy(numbuts[nr].name, "");
650                 }
651                 if (tip) {
652                         strncpy(numbuts[nr].tip, tip, tip_max);
653                         numbuts[nr].tip[tip_max-1] = 0;
654                 } else {
655                         strcpy(numbuts[nr].tip, "");
656                 }
657         }
658         
659         /*WATCH: TEX BUTTON EXCEPTION */
660         
661         numbpoin[nr]= poin;
662         
663         if ELEM( (type & BUTPOIN), FLO, INT ) memcpy(numbdata+nr, poin, 4);
664         if((type & BUTPOIN)==SHO ) *((short *)(numbdata+nr))= *( (short *)poin);
665         
666         /* if( strncmp(numbuts[nr].name, "Rot", 3)==0 ) {
667                 float *fp;
668                 
669                 fp= (float *)(numbdata+nr);
670                 fp[0]= 180.0*fp[0]/M_PI;
671         } */
672
673 }
674
675 void clever_numbuts(void)
676 {
677         
678         if(curarea->spacetype==SPACE_VIEW3D) {
679                 // panel now
680         }
681         else if(curarea->spacetype==SPACE_NLA){
682                 // panel now
683         }
684         else if(curarea->spacetype==SPACE_IPO) {
685                 // panel now
686         }
687         else if(curarea->spacetype==SPACE_SEQ) {
688                 // panel now
689         }
690         else if(curarea->spacetype==SPACE_IMAGE) {
691                 // panel now
692         }
693         else if(curarea->spacetype==SPACE_IMASEL) {
694                 clever_numbuts_imasel();
695         }
696         else if(curarea->spacetype==SPACE_OOPS) {
697                 clever_numbuts_oops();
698         }
699         else if(curarea->spacetype==SPACE_ACTION){
700                 // in its own queue
701         }
702         else if(curarea->spacetype==SPACE_FILE) {
703                 clever_numbuts_filesel();
704         }
705 }
706
707
708 void replace_names_but(void)
709 {
710         Image *ima= G.main->image.first;
711         short len, tot=0;
712         char old[64], new[64], temp[80];
713         
714         strcpy(old, "/");
715         strcpy(new, "/");
716         
717         add_numbut(0, TEX, "Old:", 0, 63, old, 0);
718         add_numbut(1, TEX, "New:", 0, 63, new, 0);
719
720         if (do_clever_numbuts("Replace image name", 2, REDRAW) ) {
721                 
722                 len= strlen(old);
723                 
724                 while(ima) {
725                         
726                         if(strncmp(old, ima->name, len)==0) {
727                                 
728                                 strcpy(temp, new);
729                                 strcat(temp, ima->name+len);
730                                 BLI_strncpy(ima->name, temp, sizeof(ima->name));
731                                 
732                                 BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
733                                 
734                                 tot++;
735                         }
736                         
737                         ima= ima->id.next;
738                 }
739
740                 notice("Replaced %d names", tot);
741         }
742         
743 }
744
745
746 /* ********************** NEW TOOLBOX ********************** */
747
748 ListBase tb_listb= {NULL, NULL};
749
750 #define TB_TAB  256
751 #define TB_ALT  512
752 #define TB_CTRL 1024
753 #define TB_PAD  2048
754 #define TB_SHIFT 4096
755
756 typedef struct TBitem {
757         int icon;
758         char *name;
759         int retval;
760         void *poin;
761 } TBitem;
762
763 static void tb_do_hotkey(void *arg, int event)
764 {
765         unsigned short i, key=0;
766         unsigned short qual[] = { 0,0,0,0 };
767         
768         if(event & TB_CTRL) {
769                 qual[0] = LEFTCTRLKEY;
770                 event &= ~TB_CTRL;
771         }
772         if(event & TB_ALT) {
773                 qual[1] = LEFTALTKEY;
774                 event &= ~TB_ALT;
775         }
776         if(event & TB_SHIFT) {
777                 qual[2] = LEFTSHIFTKEY;
778                 event &= ~TB_SHIFT;
779         }
780         
781         if(event & TB_TAB) key= TABKEY;
782         else if(event & TB_PAD) {
783                 event &= ~TB_PAD;
784                 switch(event) {
785                 case '-': key= PADMINUS; break;
786                 case '+': key= PADPLUSKEY; break;
787                 case '0': key= PAD0; break;
788                 case '5': key= PAD5; break;
789                 case '/': key= PADSLASHKEY; break;
790                 case '.': key= PADPERIOD; break;
791                 case '*': key= PADASTERKEY; break;
792                 case 'h': key= HOMEKEY; break;
793                 case 'u': key= PAGEUPKEY; break;
794                 case 'd': key= PAGEDOWNKEY; break;
795                 }
796         }
797         else asciitoraw(event, &key, &qual[3]);
798
799         for (i=0;i<4;i++)
800         {
801                 if(qual[i]) mainqenter(qual[i], 1);
802         }
803         mainqenter(key, 1);
804         mainqenter(key, 0);
805         mainqenter(EXECUTE, 1);
806
807         for (i=0;i<4;i++)
808         {
809                 if(qual[i]) mainqenter(qual[i], 0);
810         }
811 }
812
813 /* *************Select ********** */
814
815 static TBitem tb_object_select_layer1_5[]= {
816 {       0, "1",         1, NULL},
817 {       0, "2",         2, NULL},
818 {       0, "3",         3, NULL},
819 {       0, "4",         4, NULL},
820 {       0, "5",         5, NULL},
821 {  -1, "",              0, do_view3d_select_object_layermenu}};
822
823 static TBitem tb_object_select_layer6_10[]= {
824 {       0, "6",         6, NULL},
825 {       0, "7",         7, NULL},
826 {       0, "8",         8, NULL},
827 {       0, "9",         9, NULL},
828 {       0, "10",        10, NULL},
829 {  -1, "",              0, do_view3d_select_object_layermenu}};
830
831 static TBitem tb_object_select_layer11_15[]= {
832 {       0, "11",        11, NULL},
833 {       0, "12",        12, NULL},
834 {       0, "13",        13, NULL},
835 {       0, "14",        14, NULL},
836 {       0, "15",        15, NULL},
837 {  -1, "",              0, do_view3d_select_object_layermenu}};
838
839 static TBitem tb_object_select_layer16_20[]= {
840 {       0, "16",        16, NULL},
841 {       0, "17",        17, NULL},
842 {       0, "18",        18, NULL},
843 {       0, "19",        19, NULL},
844 {       0, "20",        20, NULL},
845 {  -1, "",              0, do_view3d_select_object_layermenu}};
846
847 static TBitem tb_object_select_layer[]= {
848 {       0, "Layers 1-5",        0,              tb_object_select_layer1_5},
849 {       0, "Layers 6-10",       0,              tb_object_select_layer6_10},
850 {       0, "Layers 11-15",      0,              tb_object_select_layer11_15},
851 {       0, "Layers 16-20",      0,              tb_object_select_layer16_20},
852 {  -1, "",                      0, tb_do_hotkey}};
853
854 static TBitem tb_object_select_type[]= {
855 {       0, "Mesh",              1, NULL},
856 {       0, "Curve",     2, NULL},
857 {       0, "Surface",   3, NULL},
858 {       0, "Meta",              4, NULL},
859 {       0, "SEPR",              0, NULL},
860 {       0, "Armature",  5, NULL},
861 {       0, "Lattice",   6, NULL},
862 {       0, "Text",              7, NULL},
863 {       0, "Empty",     8, NULL},
864 {       0, "SEPR",              0, NULL},
865 {       0, "Camera",    9, NULL},
866 {       0, "Lamp",              10, NULL},
867 {  -1, "",                      0, do_view3d_select_object_typemenu}};
868
869 static TBitem tb_object_select_linked[]= {
870 {       0, "Object Ipo|Shift L, 1",     1, NULL},
871 {       0, "ObData|Shift L, 2",         2, NULL},
872 {       0, "Material|Shift L, 3",       3, NULL},
873 {       0, "Texture|Shift L, 4",        4, NULL},
874 {  -1, "",                      0, do_view3d_select_object_linkedmenu}};
875
876 static TBitem tb_object_select_grouped[]= {
877 {       0, "Children|Shift G, 1",       1, NULL},
878 {       0, "Immediate Children|Shift G, 2",     2, NULL},
879 {       0, "Parent|Shift G, 3",         3, NULL},
880 {       0, "Siblings (Shared Parent)|Shift G, 4",       4, NULL},
881 {       0, "Objects of Same Type|Shift G, 5",   5, NULL},
882 {       0, "Objects on Shared Layers|Shift G, 6",       6, NULL},
883 {       0, "Objects in Same Group|Shift G, 7",  7, NULL},
884 {       0, "Object Hooks|Shift G, 8",   8, NULL},
885 {  -1, "",                      0, do_view3d_select_object_groupedmenu}};
886
887 static TBitem tb_object_select[]= {
888 {       0, "Border Select|B",   0, NULL},
889 {       0, "SEPR",                              0, NULL},
890 {       0, "Select/Deselect All|A",     1, NULL},
891 {       0, "Inverse",                   2, NULL},
892 {       0, "Select All by Layer",       0,              tb_object_select_layer},
893 {       0, "Select All by Type",        0,              tb_object_select_type},
894 {       0, "SEPR",                              0, NULL},
895 {       0, "Linked",    0,      tb_object_select_linked},
896 {       0, "Grouped",   0,      tb_object_select_grouped},
897 {  -1, "",                      0, do_view3d_select_objectmenu}};
898
899 static TBitem tb_face_select[]= {
900 {       0, "Border Select|B",           0, NULL},
901 {       0, "SEPR",                                      0, NULL},
902 {       0, "Select/Deselect All|A", 2, NULL},
903 {       0, "Inverse",                           3, NULL},
904 {       0, "Same UV",                           4, NULL},
905 {       0, "SEPR",                                      0, NULL},
906 {       0, "Linked Faces|Ctrl L",       5, NULL},
907 {  -1, "",                                              0, do_view3d_select_faceselmenu}};
908
909 static TBitem tb_mesh_select[]= {
910 {       0, "Border Select|B",               0, NULL},
911 {       0, "SEPR",                          0, NULL},
912 {       0, "(De)select All|A",              2, NULL},
913 {       0, "Inverse",                       3, NULL},
914 {       0, "SEPR",                          0, NULL},
915 {       0, "Random...",                             5, NULL},
916 {       0, "Non-Manifold|Shift Ctrl Alt M", 9, NULL},
917 {       0, "Sharp Edges|Shift Ctrl Alt S", 14, NULL},
918 {       0, "Linked Flat Faces|Shift Ctrl Alt F", 15, NULL},
919 {       0, "Triangles|Shift Ctrl Alt 3",    11, NULL},
920 {       0, "Quads|Shift Ctrl Alt 4",        12, NULL},
921 {       0, "Non-Triangles/Quads|Shift Ctrl Alt 5", 13, NULL},
922 {       0, "Group From Selection|Shift G", 21, NULL},
923 {       0, "SEPR",                          0, NULL},
924 {       0, "More|Ctrl NumPad +",            7, NULL},
925 {       0, "Less|Ctrl NumPad -",            8, NULL},
926 {       0, "SEPR",                          0, NULL},
927 {       0, "Linked Vertices|Ctrl L",        4, NULL},
928 {       0, "Vertex Path|W Alt 7",               16, NULL},
929 {       0, "Edge Loop|Ctrl E 6",                17, NULL},
930 {       0, "Edge Ring|Ctrl E 7",                18, NULL},
931 {       0, "SEPR",                          0, NULL},
932 {       0, "Loop to Region|Ctrl E 8",           19, NULL},
933 {       0, "Region to Loop|Ctrl E 9",           20, NULL},
934 {  -1, "",                      0, do_view3d_select_meshmenu}};
935
936
937 static TBitem tb_curve_select[]= {
938 {       0, "Border Select|B",   0, NULL},
939 {       0, "SEPR",                              0, NULL},
940 {       0, "(De)select All|A",  2, NULL},
941 {       0, "Inverse",                   3, NULL},
942 {       0, "Row|Shift R",                       5, NULL},
943 {       0, "SEPR",                              0, NULL},
944 {       0, "(De)select First",  7, NULL},
945 {       0, "(De)select Last",   8, NULL},
946 {       0, "Select Next",               11, NULL},
947 {       0, "Select Previous",   12, NULL},
948 {       0, "SEPR",                              0, NULL},
949 {       0, "More|Ctrl NumPad +",        9, NULL},
950 {       0, "Less|Ctrl NumPad -",        10, NULL},
951 {  -1, "",                              0, do_view3d_select_curvemenu}};
952
953 static TBitem tb__select[]= {
954 {       0, "Border Select|B",   'b', NULL},
955 {       0, "(De)select All|A",  'a', NULL},
956 {  -1, "",                      0, tb_do_hotkey}};
957
958
959 /* *************Edit ********** */
960
961 static TBitem tb_edit[]= {
962 {       0, "Exit Editmode|Tab",         TB_TAB, NULL},
963 {  -1, "",                      0, tb_do_hotkey}};
964
965 static TBitem tb_curve_edit_seg[]= {
966 {       0, "Subdivide|W, 1",            0, NULL},
967 {       0, "Switch Direction|W, 2",     1, NULL},
968 {  -1, "",                      0, do_view3d_edit_curve_segmentsmenu}};
969
970 static TBitem tb_curve_edit_cv[]= {
971 {       0, "Tilt|T",    't', NULL},
972 {       0, "Clear Tilt|Alt T",                  TB_ALT|'t', NULL},
973 {       0, "Separate|P",        'p', NULL},
974 {       0, "SEPR",                                                              0, NULL},
975 {       0, "Automatic|Shift H",                 'H', NULL},
976 {       0, "Toggle Free/Aligned|H",     'h', NULL},
977 {       0, "Vector|V",                                  'v', NULL},
978 {       0, "SEPR",                                                              0, NULL},
979 {       0, "Make Vertex Parent|Ctrl P", TB_CTRL|'p', NULL},
980 {       0, "Add Hook|Ctrl H",                   TB_CTRL|'h', NULL},
981 {  -1, "",                      0, tb_do_hotkey}};
982
983
984 static TBitem tb_curve_edit[]= {
985 {       0, "Exit Editmode|Tab",         TB_TAB, NULL},
986 {       0, "SEPR",                                                              0, NULL},
987 {       0, "Extrude|E",                 'e',            NULL},
988 {       0, "Duplicate|Shift D", 'D',            NULL},
989 {       0, "Make Segment|F",    'f',            NULL},
990 {       0, "Toggle Cyclic|C",   'c',            NULL},
991 {       0, "Delete...|X",               'x',            NULL},
992 {       0, "SEPR",                                                              0, NULL},
993 {       0, "Control Points",    0,              tb_curve_edit_cv},
994 {       0, "Segments",  0,              tb_curve_edit_seg},
995 {  -1, "",                      0, tb_do_hotkey}};
996
997
998 static TBitem tb_mesh_edit_vertex[]= {
999 {       0, "Merge...|Alt M",            5, NULL},
1000 {       0, "Rip|V",                                     7, NULL},
1001 {       0, "Split|Y",                           4,              NULL},
1002 {       0, "Separate|P",                        3,              NULL},
1003 {       0, "SEPR",                                      0, NULL},
1004 {       0, "Smooth|W, Alt 1",                   2, NULL},
1005 {       0, "Remove Doubles|W, 5",                       1, NULL},
1006 {       0, "SEPR",                                      0, NULL},
1007 {       0, "Make Vertex Parent|Ctrl P",         0, NULL},
1008 {       0, "Add Hook|Ctrl H",           6, NULL},
1009 {  -1, "",                      0, do_view3d_edit_mesh_verticesmenu}};
1010
1011 static TBitem tb_mesh_edit_edge[]= {
1012 {       0, "Make Edge/Face|F",                  5,              NULL},
1013 {       0, "Collapse|Alt M", 14,                        NULL},
1014 {       0, "SEPR",                                              0, NULL},
1015 {       0, "Bevel|W, Alt 2",                                    6,              NULL},
1016 {       0, "Loop Subdivide|Ctrl R",             4,              NULL},
1017 {       0, "Knife Subdivide...|Shift K",        3,              NULL},
1018 {       0, "SEPR",                                                              0, NULL},
1019 {       0, "Subdivide|W, 1",                    2,              NULL},
1020 {       0, "Subdivide Fractal|W, 2",    1,              NULL},
1021 {       0, "Subdivide Smooth|W, 3",             0,              NULL},
1022 {       0, "SEPR",                                                              0, NULL},
1023 {       0, "Mark Seam|Ctrl E",                  7,              NULL},
1024 {       0, "Clear Seam|Ctrl E",                 8,              NULL},
1025 {       0, "SEPR",                                                              0, NULL},
1026 {       0, "Crease SubSurf|Shift E",    9,              NULL},
1027 {       0, "SEPR",                                                              0, NULL},
1028 {       0, "Rotate Edge CW|Ctrl E",     10,             NULL},
1029 {       0, "Rotate Edge CCW|Ctrl E",    11,             NULL},
1030 {       0, "SEPR",                                                              0, NULL},
1031 {       0, "Slide Edge|Ctrl E", 12,             NULL},
1032 {       0, "Delete Edge Loop|X",        13,             NULL},
1033 {  -1, "",                      0, do_view3d_edit_mesh_edgesmenu}};
1034
1035 static TBitem tb_mesh_edit_face[]= {
1036 {       0, "Make Edge/Face|F",                  5,              NULL},
1037 {       0, "Fill|Shift F",                              0,              NULL},
1038 {       0, "Beautify Fill|Alt F",                       1,              NULL},
1039 {       0, "SEPR",                                      0, NULL},
1040 {       0, "Convert to Triangles|Ctrl T",       2,              NULL},
1041 {       0, "Convert to Quads|Alt J",            3,              NULL},
1042 {       0, "Flip Triangle Edges|Ctrl F",        4,              NULL},
1043 {       0, "Set Smooth|W, Alt 3",       6,              NULL},
1044 {       0, "Set Solid|W, Alt 4",        7,              NULL},
1045 {  -1, "",                      0, do_view3d_edit_mesh_facesmenu}};
1046
1047
1048 static TBitem tb_mesh_edit_normal[]= {
1049 {       0, "Recalculate Outside|Ctrl N",        2,              NULL},
1050 {       0, "Recalculate Inside|Ctrl Shift N",   1,              NULL},
1051 {       0, "SEPR",                                      0, NULL},
1052 {       0, "Flip|W, 9",                                 0,              NULL},
1053 {  -1, "",                      0, do_view3d_edit_mesh_normalsmenu}};
1054
1055 static TBitem tb_mesh_edit[]= {
1056 {       0, "Exit Editmode|Tab",         TB_TAB, NULL},
1057 {       0, "Undo|U",                    'u',            NULL},
1058 {       0, "Redo|Shift U",              'U',            NULL},
1059 {       0, "SEPR",                              0,                      NULL},
1060 {       0, "Extrude|E",                 'e',            NULL},
1061 {       0, "Duplicate|Shift D", 'D',            NULL},
1062 {       0, "Delete...|X",               'x',            NULL},
1063 {       0, "SEPR",                              0,                      NULL},
1064 {       0, "Vertices",          0,              tb_mesh_edit_vertex},
1065 {       0, "Edges",             0,              tb_mesh_edit_edge},
1066 {       0, "Faces",             0,              tb_mesh_edit_face},
1067 {       0, "Normals",           0,              tb_mesh_edit_normal},
1068 {  -1, "",                      0, tb_do_hotkey}};
1069
1070
1071 static TBitem tb_object_ipo[]= {
1072 {       0, "Show/Hide",         'k', NULL},
1073 {       0, "Select Next",       TB_PAD|'u', NULL},
1074 {       0, "Select Prev",       TB_PAD|'d', NULL},
1075 {  -1, "",                      0, tb_do_hotkey}};
1076
1077
1078 static TBitem tb_object_edit[]= {
1079 {       0, "Enter Editmode|Tab",        TB_TAB, NULL},
1080 {       0, "SEPR",                                                              0, NULL},
1081 {       0, "Duplicate|Shift D",                 'D',            NULL},
1082 {       0, "Duplicate Linked|Alt D",    TB_ALT|'d', NULL},
1083 {       0, "Delete|X",                                  'x',            NULL},
1084 {       0, "SEPR",                                                              0, NULL},
1085 {       0, "Object Keys",       0, tb_object_ipo},
1086 {  -1, "",                      0, tb_do_hotkey}};
1087
1088
1089 /* ************* Type  ********** */
1090
1091 static TBitem tb_obdata_hide[]= {
1092 {       0, "Show Hidden|Alt H",                 TB_ALT|'h',             NULL},
1093 {       0, "Hide Selected|H",                   'h',            NULL},
1094 {       0, "Hide Deselected|Shift H",   'H',            NULL},
1095 {  -1, "",                      0, tb_do_hotkey}};
1096
1097 static void tb_do_mesh(void *arg, int event){
1098         switch(event) {
1099         case 1: common_insertkey(); break;
1100         case 2: G.f ^= G_DRAWEDGES; break;
1101         case 3: G.f ^= G_DRAWFACES; break;
1102         case 4: G.f ^= G_DRAWNORMALS; break;
1103         case 5: flip_subdivison(-1); break;
1104         }
1105         addqueue(curarea->win, REDRAW, 1);
1106 }
1107
1108 static TBitem tb_mesh[]= {
1109 {       0, "Insert Keyframe|I",                 1,              NULL},
1110 {       0, "SEPR",                                              0, NULL},
1111 {       0, "Show/Hide Edges",                   2,              NULL},
1112 {       0, "Show/Hide Faces",                   3,              NULL},
1113 {       0, "Show/Hide Normals",                 4,              NULL},
1114 {       0, "SEPR",                                              0,      NULL},
1115 {       0, "Subdivision Surface",               5,              NULL},
1116 {       0, "SEPR",                                              0, NULL},
1117 {       0, "Show/Hide Vertices",        0,              tb_obdata_hide},
1118 {  -1, "",                      0, tb_do_mesh}};
1119
1120 static TBitem tb_curve_hide[]= {
1121 {       0, "Show Hidden|Alt H",                 10,             NULL},
1122 {       0, "Hide Selected|H",                   11,             NULL},
1123 {  -1, "",                      0, do_view3d_edit_curve_showhidemenu}};
1124
1125
1126 static TBitem tb_curve[]= {
1127 {       0, "Insert Keyframe|I",                 'i',            NULL},
1128 {       0, "SEPR",                                              0, NULL},
1129 {       0, "Show/Hide Points",  0,              tb_curve_hide},
1130 {  -1, "",                      0, tb_do_hotkey}};
1131
1132 static TBitem tb_obdata[]= {
1133 {       0, "Duplicate|Shift D",                 'D',            NULL},
1134 {       0, "Delete|X",                                  'x',            NULL},
1135 {  -1, "",                      0, tb_do_hotkey}};
1136
1137 static TBitem tb_object_parent[]= {
1138 {       0, "Make Parent...|Ctrl P",             TB_CTRL|'p', NULL},
1139 {       0, "Clear Parent...|Alt P",             TB_ALT|'p', NULL},
1140 {  -1, "",                      0, tb_do_hotkey}};
1141
1142 static TBitem tb_object_track[]= {
1143 {       0, "Make Track|Ctrl T",                 TB_CTRL|'t', NULL},
1144 {       0, "Clear Track|Alt T",                 TB_ALT|'t', NULL},
1145 {  -1, "",                      0, tb_do_hotkey}};
1146
1147 static TBitem tb_object[]= {
1148 {       0, "Insert Keyframe|I",                 'i',            NULL},
1149 {       0, "SEPR",                                                              0, NULL},
1150 {       0, "Make Links...|Ctrl L",              TB_CTRL|'l', NULL},
1151 {       0, "Make Single User...|U",     'u',            NULL},
1152 {       0, "Copy Attributes...|Ctrl C", TB_CTRL|'c', NULL},
1153 {       0, "SEPR",                                                              0, NULL},
1154 {       0, "Parent",    0,              tb_object_parent},
1155 {       0, "Track",     0,              tb_object_track},
1156 {       0, "SEPR",                                                              0, NULL},
1157 {       0, "Boolean Operation|W",       'w', NULL},
1158 {       0, "Join Objects...|Ctrl J",    TB_CTRL|'j', NULL},
1159 {       0, "Convert Object Type...|Alt C",      TB_ALT|'c', NULL},
1160 {       0, "SEPR",                                                              0, NULL},
1161 {       0, "Move to Layer...|M",                'm', NULL},
1162 {  -1, "",                      0, tb_do_hotkey}};
1163
1164
1165 /* *************VIEW ********** */
1166
1167 static void tb_do_view_dt(void *arg, int event){
1168         G.vd->drawtype= event;
1169         addqueue(curarea->win, REDRAW, 1);
1170 }
1171
1172 static TBitem tb_view_dt[]= {
1173 {       ICON_BBOX, "Bounding Box",      1, NULL},
1174 {       ICON_WIRE, "Wireframe|Z",       2, NULL},
1175 {       ICON_SOLID, "Solid|Z",          3, NULL},
1176 {       ICON_SMOOTH, "Shaded|Shift Z",          4, NULL},
1177 {       ICON_POTATO, "Textured|Alt Z",  5, NULL},
1178 {  -1, "",                      0, tb_do_view_dt}};
1179
1180 static TBitem tb_view_alignview[]= {
1181 {       0, "Centre View to Cursor|C",           'c', NULL},
1182 {       0, "Align Active Camera to View|Ctrl Alt NumPad 0",
1183 TB_CTRL|TB_ALT|TB_PAD|'0', NULL}, 
1184 {       0, "Align View to Selected|NumPad *",           TB_PAD|'*', NULL},
1185 {  -1, "",                      0, tb_do_hotkey}};
1186
1187 static TBitem tb_view[]= {
1188 {       0, "Viewport Shading",                  0, tb_view_dt},
1189 {       0, "SEPR",                                              0, NULL},
1190 {       0, "Ortho/Perspective|NumPad 5",        TB_PAD|'5', NULL},
1191 {       0, "Local/Global View|NumPad /",        TB_PAD|'/', NULL},
1192 {       0, "SEPR",                                              0, NULL},
1193 {       0, "Align View",                        0, tb_view_alignview},
1194 {       0, "SEPR",              0, NULL},
1195 {       0, "View Selected|NumPad .",    TB_PAD|'.', NULL},
1196 {       0, "View All|Home",             TB_PAD|'h', NULL},
1197 {       0, "SEPR",              0, NULL},
1198 {       0, "Play Back Animation|Alt A", TB_ALT|'a', NULL},
1199 {       0, "Camera Fly Mode|Shift F", TB_SHIFT|'f', NULL},
1200 {  -1, "",                      0, tb_do_hotkey}};
1201
1202
1203 /* *************TRANSFORM ********** */
1204
1205 static TBitem tb_transform_moveaxis[]= {
1206 {       0, "X Global|G, X",     0, NULL},
1207 {       0, "Y Global|G, Y",     1, NULL},
1208 {       0, "Z Global|G, Z",     2, NULL},
1209 {       0, "SEPR",                                      0, NULL},
1210 {       0, "X Local|G, X, X",   3, NULL},
1211 {       0, "Y Local|G, Y, Y",   4, NULL},
1212 {       0, "Z Local|G, Z, Z",   5, NULL},
1213 {  -1, "",                      0, do_view3d_transform_moveaxismenu}};
1214
1215 static TBitem tb_transform_rotateaxis[]= {
1216 {       0, "X Global|R, X",     0, NULL},
1217 {       0, "Y Global|R, Y",     1, NULL},
1218 {       0, "Z Global|R, Z",     2, NULL},
1219 {       0, "SEPR",                                      0, NULL},
1220 {       0, "X Local|R, X, X",   3, NULL},
1221 {       0, "Y Local|R, Y, Y",   4, NULL},
1222 {       0, "Z Local|R, Z, Z",   5, NULL},
1223 {  -1, "",                      0, do_view3d_transform_rotateaxismenu}};
1224
1225 static TBitem tb_transform_scaleaxis[]= {
1226 {       0, "X Global|S, X",     0, NULL},
1227 {       0, "Y Global|S, Y",     1, NULL},
1228 {       0, "Z Global|S, Z",     2, NULL},
1229 {       0, "SEPR",                                      0, NULL},
1230 {       0, "X Local|S, X, X",   3, NULL},
1231 {       0, "Y Local|S, Y, Y",   4, NULL},
1232 {       0, "Z Local|S, Z, Z",   5, NULL},
1233 {  -1, "",                      0, do_view3d_transform_scaleaxismenu}};
1234
1235 static void tb_do_transform_clearapply(void *arg, int event)
1236 {
1237         Object *ob;
1238         ob= OBACT;
1239         
1240         switch(event)
1241         {
1242             case 0: /* clear location */
1243                         clear_object('g');
1244                         break;
1245                 case 1: /* clear rotation */
1246                         clear_object('r');
1247                         break;
1248                 case 2: /* clear scale */
1249                         clear_object('s');
1250                         break;
1251                 case 3: /* apply scale/rotation */
1252                         apply_object();
1253                         break;
1254                 case 4: /* apply deformation */
1255                         object_apply_deform(ob);
1256                         break;
1257                 case 5: /* make duplicates real */
1258                         if (ob->transflag & OB_DUPLI) make_duplilist_real();
1259                         else error("The active object does not have dupliverts");
1260                         break;
1261         }
1262 }
1263
1264 static TBitem tb_transform_clearapply[]= {
1265 {       0, "Clear Location|Alt G",              0, NULL},
1266 {       0, "Clear Rotation|Alt R",              1, NULL},
1267 {       0, "Clear Scale|Alt S",                 2, NULL},
1268 {       0, "SEPR",                                      0, NULL},
1269 {       0, "Apply Scale/Rotation|Ctrl A", 3, NULL},
1270 {       0, "Apply Deformation|Shift Ctrl A", 4, NULL},
1271 {       0, "Make Duplicates Real|Shift Ctrl A", 5, NULL},
1272 {  -1, "",                      0, tb_do_transform_clearapply}};
1273
1274 static TBitem tb_transform_snap[]= {
1275 {       0, "Selection -> Grid|Shift S, 1",              1, NULL},
1276 {       0, "Selection -> Cursor|Shift S, 2",    2, NULL},
1277 {       0, "Cursor -> Grid|Shift S, 3",                 3, NULL},
1278 {       0, "Cursor -> Selection|Shift S, 4", 4, NULL},
1279 {       0, "Selection -> Center|Shift S, 5", 5, NULL},
1280 {  -1, "",                      0, do_view3d_edit_snapmenu}};
1281
1282 static void tb_do_transform(void *arg, int event)
1283 {
1284         switch(event)
1285         {
1286                 case 0: /* Grab/move */
1287                         initTransform(TFM_TRANSLATION, CTX_NONE);
1288                         Transform();
1289                         break;
1290                 case 1: /* Rotate */
1291                         initTransform(TFM_ROTATION, CTX_NONE);
1292                         Transform();
1293                         break;
1294                 case 2: /* Scale */
1295                         initTransform(TFM_RESIZE,CTX_NONE);
1296                         Transform();
1297                         break;
1298                 case 3: /* transform properties */
1299                         add_blockhandler(curarea, VIEW3D_HANDLER_OBJECT, UI_PNL_UNSTOW);
1300                         break;
1301                 case 4: /* snap */
1302                         snapmenu();
1303                         break;
1304                 case 5: /* Shrink/Fatten Along Normals */
1305                         initTransform(TFM_SHRINKFATTEN, CTX_NONE);
1306                         Transform();
1307                         break;
1308                 case 6: /* Shear */
1309                         initTransform(TFM_SHEAR, CTX_NONE);
1310                         Transform();
1311                         break;
1312                 case 7: /* Warp */
1313                         initTransform(TFM_WARP, CTX_NONE);
1314                         Transform();
1315                         break;
1316                 case 8: /* proportional edit (toggle) */
1317                         if(G.scene->proportional) G.scene->proportional= 0;
1318                         else G.scene->proportional= 1;
1319                         break;
1320                 case 10:
1321                         docentre(0);
1322                         break;
1323                 case 11:
1324                         docentre_new();
1325                         break;
1326                 case 12:
1327                         docentre_cursor();
1328                         break;
1329         }
1330         allqueue(REDRAWVIEW3D, 0);
1331 }
1332
1333 static TBitem tb_transform_object_mirror[]= {
1334 {       0, "X Local|Ctrl M, 1",         1, NULL},
1335 {       0, "Y Local|Ctrl M, 2",         2, NULL},
1336 {       0, "Z Local|Ctrl M, 3",         3, NULL},
1337 {  -1, "",                      0, do_view3d_object_mirrormenu}};
1338
1339 static TBitem tb_transform[]= {
1340 {       0, "Grab/Move|G",       0, NULL},
1341 {       0, "Grab/Move on Axis| ",       0, tb_transform_moveaxis},
1342 {       0, "Rotate|R",          1, NULL},
1343 {       0, "Rotate on Axis",    0, tb_transform_rotateaxis},
1344 {       0, "Scale|S",           2, NULL},
1345 {       0, "Scale on Axis",     0, tb_transform_scaleaxis},
1346 {       0, "SEPR",                                      0, NULL},
1347 {       0, "ObData to Center",          10, NULL},
1348 {       0, "Center New",                        11, NULL},
1349 {       0, "Center Cursor",                     12, NULL},
1350 {       0, "SEPR",                                      0, NULL},
1351 {       ICON_MENU_PANEL, "Properties|N", 3, NULL},
1352 {       0, "SEPR",                                      0, NULL},
1353 {       0, "Mirror",    0, tb_transform_object_mirror},
1354 {       0, "SEPR",                                      0, NULL},
1355 {       0, "Snap",              0, tb_transform_snap},
1356 {       0, "SEPR",                                      0, NULL},
1357 {       0, "Clear/Apply",       0, tb_transform_clearapply},
1358 {  -1, "",                      0, tb_do_transform}};
1359
1360 static TBitem tb_transform_edit_mirror[]= {
1361 {       0, "X Global|Ctrl M, 1",        1, NULL},
1362 {       0, "Y Global|Ctrl M, 2",        2, NULL},
1363 {       0, "Z Global|Ctrl M, 3",        3, NULL},
1364 {       0, "SEPR",                                      0, NULL},
1365 {       0, "X Local|Ctrl M, 4",         4, NULL},
1366 {       0, "Y Local|Ctrl M, 5",         5, NULL},
1367 {       0, "Z Local|Ctrl M, 6",         6, NULL},
1368 {       0, "SEPR",                                      0, NULL},
1369 {       0, "X View|Ctrl M, 7",  7, NULL},
1370 {       0, "Y View|Ctrl M, 8",  8, NULL},
1371 {       0, "Z View|Ctrl M, 9",  9, NULL},
1372 {  -1, "",                      0, do_view3d_edit_mirrormenu}};
1373
1374 static TBitem tb_transform_editmode1[]= {
1375 {       0, "Grab/Move|G",       0, NULL},
1376 {       0, "Grab/Move on Axis| ",       0, tb_transform_moveaxis},
1377 {       0, "Rotate|R",          1, NULL},
1378 {       0, "Rotate on Axis",    0, tb_transform_rotateaxis},
1379 {       0, "Scale|S",           2, NULL},
1380 {       0, "Scale on Axis",     0, tb_transform_scaleaxis},
1381 {       0, "SEPR",                                      0, NULL},
1382 {       0, "Shrink/Fatten|Alt S", 5, NULL},
1383 {       0, "Shear|Ctrl S", 6, NULL},
1384 {       0, "Warp|Shift W",      7, NULL},
1385 {       0, "SEPR",                                      0, NULL},
1386 {       0, "ObData to Center",          10, NULL},
1387 {       0, "SEPR",                                      0, NULL},
1388 {       ICON_MENU_PANEL, "Properties|N", 3, NULL},
1389 {       0, "SEPR",                                      0, NULL},
1390 {       0, "Mirror",    0, tb_transform_edit_mirror},
1391 {       0, "SEPR",                                      0, NULL},
1392 {       0, "Snap",              0, tb_transform_snap},
1393 {       0, "SEPR",                                      0, NULL},
1394 {       0, "Proportional Edit|O",       8,              NULL},
1395 {  -1, "",                      0, tb_do_transform}};
1396
1397
1398 static TBitem tb_transform_editmode2[]= {
1399 {       0, "Grab/Move|G",       0, NULL},
1400 {       0, "Grab/Move on Axis| ",       0, tb_transform_moveaxis},
1401 {       0, "Rotate|R",          1, NULL},
1402 {       0, "Rotate on Axis",    0, tb_transform_rotateaxis},
1403 {       0, "Scale|S",           2, NULL},
1404 {       0, "Scale on Axis",     0, tb_transform_scaleaxis},
1405 {       0, "SEPR",                                      0, NULL},
1406 {       ICON_MENU_PANEL, "Properties|N", 3, NULL},
1407 {       0, "Snap",              0, tb_transform_snap},
1408 {  -1, "",                      0, tb_do_transform}};
1409
1410
1411 /* *************ADD ********** */
1412
1413 static TBitem addmenu_mesh[]= {
1414 {       0, "Plane",     0, NULL},
1415 {       0, "Cube",              1, NULL},
1416 {       0, "Circle",    2, NULL},
1417 {       0, "UVsphere",  3, NULL},
1418 {       0, "Icosphere", 4, NULL},
1419 {       0, "Cylinder",  5, NULL},
1420 {       0, "Tube",              6, NULL},
1421 {       0, "Cone",              7, NULL},
1422 {       0, "SEPR",              0, NULL},
1423 {       0, "Grid",              8, NULL},
1424 {       0, "Monkey",    9, NULL},
1425 {  -1, "",                      0, do_info_add_meshmenu}};
1426
1427 static TBitem addmenu_curve[]= {
1428 {       0, "Bezier Curve",      0, NULL},
1429 {       0, "Bezier Circle", 1, NULL},
1430 {       0, "NURBS Curve",       2, NULL},
1431 {       0, "NURBS Circle",      3, NULL},
1432 {       0, "Path",                      4, NULL},
1433 {  -1, "",                      0, do_info_add_curvemenu}};
1434
1435 static TBitem addmenu_surf[]= {
1436 {       0, "NURBS Curve",       0, NULL},
1437 {       0, "NURBS Circle",      1, NULL},
1438 {       0, "NURBS Surface", 2, NULL},
1439 {       0, "NURBS Tube",        3, NULL},
1440 {       0, "NURBS Sphere",      4, NULL},
1441 {       0, "NURBS Donut",       5, NULL},
1442 {  -1, "",                      0, do_info_add_surfacemenu}};
1443
1444 static TBitem addmenu_meta[]= {
1445 {       0, "Meta Ball",         0, NULL},
1446 {       0, "Meta Tube",         1, NULL},
1447 {       0, "Meta Plane",        2, NULL},
1448 {       0, "Meta Ellipsoid", 3, NULL},
1449 {       0, "Meta Cube",         4, NULL},
1450 {  -1, "",                      0, do_info_add_metamenu}};
1451
1452 static TBitem addmenu_lamp[]= {
1453 {       0, "Lamp",      0, NULL},
1454 {       0, "Sun",       1, NULL},
1455 {       0, "Spot",      2, NULL},
1456 {       0, "Hemi", 3, NULL},
1457 {       0, "Area",      4, NULL},
1458 {  -1, "",                      0, do_info_add_lampmenu}};
1459
1460 static TBitem addmenu_YF_lamp[]= {
1461 {       0, "Lamp",      0, NULL},
1462 {       0, "Sun",       1, NULL},
1463 {       0, "Spot",      2, NULL},
1464 {       0, "Hemi", 3, NULL},
1465 {       0, "Area",      4, NULL},
1466 {       0, "Photon",    5, NULL},
1467 {  -1, "",                      0, do_info_add_lampmenu}};
1468
1469
1470 static TBitem addmenu_armature[]= {
1471 {       0, "Bone",      8, NULL},
1472 {  -1, "",                      0, do_info_addmenu}};
1473
1474 /* dynamic items */
1475 #define TB_ADD_GROUP    7
1476 #define TB_ADD_LAMP             10
1477
1478 static TBitem tb_add[]= {
1479 {       0, "Mesh",              0, addmenu_mesh},
1480 {       0, "Curve",     1, addmenu_curve},
1481 {       0, "Surface",   2, addmenu_surf},
1482 {       0, "Meta",      3, addmenu_meta},
1483 {       0, "Text",              4, NULL},
1484 {       0, "Empty",     5, NULL},
1485 {       0, "SEPR",              0, NULL},
1486 {       0, "Group",     10, NULL},
1487 {       0, "SEPR",              0, NULL},
1488 {       0, "Camera",    6, NULL},
1489 {       0, "Lamp",              7, addmenu_lamp},
1490 {       0, "SEPR",              0, NULL},
1491 {       0, "Armature",  8, NULL},
1492 {       0, "Lattice",   9, NULL},
1493 {  -1, "",                      0, do_info_addmenu}};
1494
1495 static TBitem tb_empty[]= {
1496 {       0, "Nothing...",        0, NULL},
1497 {  -1, "",              0, NULL}};
1498
1499
1500 /* *************RENDER ********** */
1501
1502 static void tb_do_render(void *arg, int event){
1503         switch(event)
1504         {
1505                 case 1: /* set render border */
1506                         set_render_border();
1507                         break;
1508                 case 2: /* render */
1509                         BIF_do_render(0);
1510                         break;
1511                 case 3: /* render anim */
1512                         BIF_do_render(1);
1513                         break;
1514                 case 4: /* passepartout */
1515                 {
1516                         Camera *ca= NULL;
1517                         if(G.vd->camera==NULL) return;
1518                         
1519                         if(G.vd->camera->type==OB_CAMERA)
1520                                 ca= G.vd->camera->data;
1521                         else return;
1522                                 
1523                         if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT))
1524                                 ca->flag &= ~CAM_SHOWPASSEPARTOUT;
1525                         else
1526                                 ca->flag |= CAM_SHOWPASSEPARTOUT;
1527                         allqueue(REDRAWVIEW3D, 0);
1528                 }
1529                         break;
1530                 case 5: /*preview render */
1531                         toggle_blockhandler(curarea, VIEW3D_HANDLER_PREVIEW, 0);
1532                         scrarea_queue_winredraw(curarea);
1533                         break;
1534         }
1535 }
1536
1537 static TBitem tb_render[]= {
1538         {       0, "Passepartout",                      4, NULL},
1539         {       0, "Set Border|Shift B",                1, NULL},
1540         {       0, "SEPR",                              0, NULL},
1541         {       0, "Render|F12",                        2, NULL},
1542         {       0, "Anim|Ctrl F12",                     3, NULL},
1543         {       0, "Preview|Shift P",                   5, NULL},
1544         {  -1, "",                      0, tb_do_render}};
1545
1546 /* ************************* NODES *********************** */
1547
1548
1549 /* dynamic items */
1550
1551 static TBitem tb_node_addsh[]= {
1552         {       0, "Input",                     1, NULL},
1553         {       0, "Output",            2, NULL},
1554         {       0, "Color",                     3, NULL},
1555         {       0, "Vector",            4, NULL},
1556         {       0, "Convertor", 5, NULL},
1557         {       0, "Group",             6, NULL},
1558         {  -1, "",                      0, NULL}};
1559
1560 static TBitem tb_node_addcomp[]= {
1561         {       0, "Input",                     1, NULL},
1562         {       0, "Output",            2, NULL},
1563         {       0, "Color",                     3, NULL},
1564         {       0, "Vector",            4, NULL},
1565         {       0, "Filter",            5, NULL},
1566         {       0, "Convertor", 6, NULL},
1567         {       0, "Matte",             7, NULL},
1568         {       0, "Distort",   8, NULL},
1569         {       0, "Group",             9, NULL},
1570         {       -1, "",                 0, NULL}};
1571
1572 /* do_node_addmenu() in header_node.c, prototype in BSE_headerbuttons.h */
1573
1574 /* dynamic toolbox sublevel */
1575 static TBitem *node_add_sublevel(ListBase *storage, bNodeTree *ntree, int nodeclass)
1576 {
1577         static TBitem _addmenu[]= { {   0, " ",         0, NULL}, {  -1, "",                    0, NULL}};
1578         Link *link;
1579         bNodeType **typedefs;
1580         TBitem *addmenu;
1581         int tot= 0, a;
1582         
1583         if(ntree) {
1584                 if(nodeclass==NODE_CLASS_GROUP) {
1585                         bNodeTree *ngroup= G.main->nodetree.first;
1586                         for(; ngroup; ngroup= ngroup->id.next)
1587                                 if(ngroup->type==ntree->type)
1588                                         tot++;
1589                 }
1590                 else {
1591                         for(typedefs= ntree->alltypes; *typedefs; typedefs++)
1592                                 if( (*typedefs)->nclass == nodeclass )
1593                                         tot++;
1594                 }
1595         }       
1596         if(tot==0) {
1597                 return _addmenu;
1598         }
1599         
1600         link= MEM_callocN(sizeof(Link) + sizeof(TBitem)*(tot+1), "types menu");
1601         BLI_addtail(storage, link);
1602         addmenu= (TBitem *)(link+1);
1603         
1604         if(nodeclass==NODE_CLASS_GROUP) {
1605                 bNodeTree *ngroup= G.main->nodetree.first;
1606                 for(tot=0, a=0; ngroup; ngroup= ngroup->id.next, tot++) {
1607                         if(ngroup->type==ntree->type) {
1608                                 addmenu[a].name= ngroup->id.name+2;
1609                                 addmenu[a].retval= NODE_GROUP_MENU+tot; /* so we can use BLI_findlink() */
1610                                 a++;
1611                         }
1612                 }
1613         }
1614         else {
1615                 for(a=0, typedefs= ntree->alltypes; *typedefs; typedefs++) {
1616                         if( (*typedefs)->nclass == nodeclass ) {
1617                                 addmenu[a].name= (*typedefs)->name;
1618                                 addmenu[a].retval= (*typedefs)->type;
1619                                 a++;
1620                         }
1621                 }
1622         }
1623
1624         addmenu[a].icon= -1;    /* end signal */
1625         addmenu[a].name= "";
1626         addmenu[a].retval= a;
1627         addmenu[a].poin= do_node_addmenu;
1628         
1629         return addmenu;
1630 }
1631
1632
1633 static TBitem tb_node_node[]= {
1634         {       0, "Duplicate|Shift D", TB_SHIFT|'d',           NULL},
1635         {       0, "Delete|X", 'x',             NULL},
1636         {       0, "SEPR",              0, NULL},
1637         {       0, "Make Group|Ctrl G", TB_CTRL|'g',            NULL},
1638         {       0, "Ungroup|Alt G", TB_ALT|'g',                 NULL},
1639         {       0, "Edit Group|Tab", TB_TAB, NULL},
1640         {       0, "SEPR",              0, NULL},
1641         {       0, "Hide/Unhide|H", 'h', NULL},
1642         {       0, "SEPR",              0, NULL},
1643         {       0, "Read Saved Render Results|R", 'r', NULL},
1644         {       0, "Show Cyclic Dependencies|C", 'c', NULL},
1645         {  -1, "",                      0, tb_do_hotkey}};
1646
1647 static TBitem tb_node_select[]= {
1648         {       0, "Select/Deselect All|A",     'a', NULL},
1649         {       0, "Border Select|B",   'b', NULL},
1650         {  -1, "",                      0, tb_do_hotkey}};
1651
1652 static TBitem tb_node_transform[]= {
1653         {       0, "Grab/Move|G", 'g',          NULL},
1654         {  -1, "",                      0, tb_do_hotkey}};
1655
1656 static TBitem tb_node_view[]= {
1657         {       0, "Zoom In|NumPad +",  TB_PAD|'+', NULL},
1658         {       0, "Zoom Out|NumPad -", TB_PAD|'-', NULL},
1659         {       0, "View All|Home",     TB_PAD|'h', NULL},
1660         {  -1, "",                      0, tb_do_hotkey}};
1661
1662
1663 /* *********************************************** */
1664
1665 static uiBlock *tb_makemenu(void *arg)
1666 {
1667         static int counter=0;
1668         TBitem *item= arg, *itemt;
1669         uiBlock *block;
1670         int xco= 0, yco= 0;
1671         char str[10];
1672         
1673         if(arg==NULL) return NULL;
1674         
1675         sprintf(str, "tb %d", counter++);
1676         block= uiNewBlock(&tb_listb, str, UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
1677         uiBlockSetCol(block, TH_MENU_ITEM);
1678
1679         // last item has do_menu func, has to be stored in each button
1680         itemt= item;
1681         while(itemt->icon != -1) itemt++;
1682         uiBlockSetButmFunc(block, itemt->poin, NULL);
1683
1684         // now make the buttons
1685         while(item->icon != -1) {
1686
1687                 if(strcmp(item->name, "SEPR")==0) {
1688                         uiDefBut(block, SEPR, 0, "", xco, yco-=6, 50, 6, NULL, 0.0, 0.0, 0, 0, "");
1689                 }
1690                 else if(item->icon) {
1691                         uiDefIconTextBut(block, BUTM, 1, item->icon, item->name, xco, yco-=20, 80, 19, NULL, 0.0, 0.0, 0, item->retval, "");
1692                 }
1693                 else if(item->poin) {
1694                         uiDefIconTextBlockBut(block, tb_makemenu, item->poin, ICON_RIGHTARROW_THIN, item->name, 0, yco-=20, 80, 19, "");
1695                 }
1696                 else {
1697                         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, item->name, xco, yco-=20, 80, 19, NULL, 0.0, 0.0, 0, item->retval, "");
1698                 }
1699                 
1700                 if(yco <= -600) {
1701                         yco = 0;
1702                         xco += 80;
1703                 }
1704                 
1705                 item++;
1706         }
1707         
1708         uiTextBoundsBlock(block, 60);
1709         
1710         /* direction is also set in the function that calls this */
1711         if(U.uiflag & USER_PLAINMENUS)
1712                 uiBlockSetDirection(block, UI_RIGHT);
1713         else
1714                 uiBlockSetDirection(block, UI_RIGHT|UI_CENTRE);
1715
1716         return block;
1717 }
1718
1719 static int tb_mainx= 1234, tb_mainy= 0;
1720 static void store_main(void *arg1, void *arg2)
1721 {
1722         tb_mainx= (int)arg1;
1723         tb_mainy= (int)arg2;
1724 }
1725
1726 static void do_group_addmenu(void *arg, int event)
1727 {
1728         Object *ob;
1729         
1730         if(event<0) return;
1731         
1732         add_object_draw(OB_EMPTY);
1733         ob= OBACT;
1734         
1735         ob->dup_group= BLI_findlink(&G.main->group, event);
1736         if(ob->dup_group) {
1737                 id_us_plus((ID *)ob->dup_group);
1738                 ob->transflag |= OB_DUPLIGROUP;
1739                 DAG_scene_sort(G.scene);
1740         }
1741 }
1742
1743 /* helper for create group menu */
1744 static void tag_groups_for_toolbox(void)
1745 {
1746         Group *group;
1747         GroupObject *go;
1748         
1749         for(group= G.main->group.first; group; group= group->id.next)
1750                 group->id.flag |= LIB_DOIT;
1751         
1752         for(group= G.main->group.first; group; group= group->id.next) {
1753                 if(group->id.flag & LIB_DOIT)
1754                         for(go= group->gobject.first; go; go= go->next) 
1755                                 if(go->ob && go->ob->dup_group)
1756                                         go->ob->dup_group->id.flag &= ~LIB_DOIT;
1757         }
1758 }
1759
1760 /* helper for create group menu */
1761 static int count_group_libs(void)
1762 {
1763         Group *group;
1764         Library *lib;
1765         int tot= 0;
1766         
1767         for(lib= G.main->library.first; lib; lib= lib->id.next)
1768                 lib->id.flag |= LIB_DOIT;
1769         
1770         for(group= G.main->group.first; group; group= group->id.next) {
1771                 if(group->id.lib && (group->id.lib->id.flag & LIB_DOIT)) {
1772                         group->id.lib->id.flag &= ~LIB_DOIT;
1773                         tot++;
1774                 }
1775         }
1776         return tot;
1777 }
1778
1779 /* dynamic toolbox sublevel */
1780 static TBitem *create_group_sublevel(ListBase *storage, Library *lib)
1781 {
1782         static TBitem addmenu[]= { {    0, "No Groups",         0, NULL}, {  -1, "",                    0, NULL}};
1783         Link *link;
1784         TBitem *groupmenu, *gm;
1785         Group *group;
1786         int a;
1787         int tot= BLI_countlist(&G.main->group);
1788         
1789         if(tot==0) {
1790                 return addmenu;
1791         }
1792         
1793         /* build menu, we insert a Link before the array of TBitems */
1794         link= MEM_callocN(sizeof(Link) + sizeof(TBitem)*(tot+1), "group menu lib");
1795         BLI_addtail(storage, link);
1796         gm= groupmenu= (TBitem *)(link+1);
1797         for(a=0, group= G.main->group.first; group; group= group->id.next, a++) {
1798                 if(group->id.lib==lib && (group->id.flag & LIB_DOIT)) {
1799                         gm->name= group->id.name+2;
1800                         gm->retval= a;
1801                         gm++;
1802                 }
1803         }
1804         gm->icon= -1;   /* end signal */
1805         gm->name= "";
1806         gm->retval= a;
1807         gm->poin= do_group_addmenu;
1808         
1809         return groupmenu;
1810 }
1811
1812 static TBitem *create_group_all_sublevels(ListBase *storage)
1813 {
1814         Library *lib;
1815         Group *group;
1816         Link *link;
1817         TBitem *groupmenu, *gm;
1818         int a;
1819         int totlevel= count_group_libs();
1820         int totlocal= 0;
1821         
1822         /* we add totlevel + local groups entries */
1823         
1824         /* let's skip group-in-group */
1825         tag_groups_for_toolbox();
1826         
1827         for(group= G.main->group.first; group; group= group->id.next)
1828                 if(group->id.flag & LIB_DOIT)
1829                         if(group->id.lib==NULL)
1830                                 totlocal++;
1831         
1832         if(totlocal+totlevel==0)
1833                 return create_group_sublevel(storage, NULL);
1834         
1835         /* build menu, we insert a Link before the array of TBitems */
1836         link= MEM_callocN(sizeof(Link) + sizeof(TBitem)*(totlocal+totlevel+1), "group menu");
1837         BLI_addtail(storage, link);
1838         gm= groupmenu= (TBitem *)(link+1);
1839         
1840         /* first all levels. libs with groups are not tagged */
1841         for(lib= G.main->library.first; lib; lib= lib->id.next) {
1842                 if(!(lib->id.flag & LIB_DOIT)) {
1843                         char *str;
1844                         /* do some tricks to get .blend file name without extension */
1845                         link= MEM_callocN(sizeof(Link) + 128, "string");
1846                         BLI_addtail(storage, link);
1847                         str= (char *)(link+1);
1848                         BLI_strncpy(str, BLI_last_slash(lib->filename)+1, 128);
1849                         if(strlen(str)>6) str[strlen(str)-6]= 0;
1850                         gm->name= str;
1851                         gm->retval= -1;
1852                         gm->poin= create_group_sublevel(storage, lib);
1853                         gm++;
1854                 }
1855         }
1856         /* remaining groups */
1857         for(a=0, group= G.main->group.first; group; group= group->id.next, a++) {
1858                 if(group->id.lib==NULL && (group->id.flag & LIB_DOIT)) {
1859                         gm->name= group->id.name+2;
1860                         gm->retval= a;
1861                         gm++;
1862                 }
1863         }
1864         gm->icon= -1;   /* end signal */
1865         gm->name= "";
1866         gm->retval= a;
1867         gm->poin= do_group_addmenu;
1868         
1869         return groupmenu;
1870 }
1871
1872
1873 void toolbox_n(void)
1874 {
1875         uiBlock *block;
1876         uiBut *but;
1877         ListBase storage= {NULL, NULL};
1878         TBitem *menu1=NULL, *menu2=NULL, *menu3=NULL; 
1879         TBitem *menu4=NULL, *menu5=NULL, *menu6=NULL;
1880         TBitem *menu7=NULL;
1881         int dx=0;
1882         short event, mval[2], tot=0;
1883         char *str1=NULL, *str2=NULL, *str3=NULL, *str4=NULL, *str5=NULL, *str6=NULL, *str7=NULL;
1884         
1885         /* temporal too... when this flag is (was) saved, it should initialize OK */
1886         if(tb_mainx==1234) {
1887                 if(U.uiflag & USER_PLAINMENUS) {
1888                         tb_mainx= -32;
1889                         tb_mainy= -5;
1890                 } else {
1891                         tb_mainx= 0;
1892                         tb_mainy= -5;
1893                 }
1894         }
1895         
1896         mywinset(G.curscreen->mainwin); // we go to screenspace
1897         
1898         block= uiNewBlock(&tb_listb, "toolbox", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
1899         uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
1900         uiBlockSetCol(block, TH_MENU_ITEM);
1901         
1902         /* select context for main items */
1903         if(curarea->spacetype==SPACE_VIEW3D) {
1904
1905                 /* dynamic menu entries */
1906                 tb_add[TB_ADD_GROUP].poin= create_group_all_sublevels(&storage);
1907                 
1908                 /* static */
1909                 if (G.scene->r.renderer==R_YAFRAY)
1910                         tb_add[TB_ADD_LAMP].poin= addmenu_YF_lamp;
1911                 else
1912                         tb_add[TB_ADD_LAMP].poin= addmenu_lamp;
1913                 
1914                 if(U.uiflag & USER_PLAINMENUS) {
1915                         menu1= tb_add; str1= "Add";
1916                         menu2= tb_object_edit; str2= "Edit";
1917                         menu3= tb_object_select; str3= "Select";
1918                         menu4= tb_transform; str4= "Transform";
1919                         menu5= tb_object; str5= "Object";
1920                         menu6= tb_view; str6= "View";
1921                         menu7= tb_render; str7= "Render";
1922
1923                         dx= 96;
1924                         tot= 7;
1925                 } else {
1926                         /* 3x2 layout menu */
1927                         menu1= tb_object; str1= "Object";
1928                         menu2= tb_add; str2= "Add";
1929                         menu3= tb_object_select; str3= "Select";
1930                         menu4= tb_object_edit; str4= "Edit";
1931                         menu5= tb_transform; str5= "Transform";
1932                         menu6= tb_view; str6= "View";
1933
1934                         dx= 64;
1935                         tot= 6;
1936                 }
1937                 
1938                 if(G.obedit) {
1939                         if(U.uiflag & USER_PLAINMENUS) {
1940                                 switch(G.obedit->type){
1941                                 case OB_MESH:
1942                                         menu1= addmenu_mesh;
1943                                         menu2= tb_mesh_edit;
1944                                         menu3= tb_mesh_select;
1945                                         menu4= tb_transform_editmode1;
1946                                         menu5= tb_mesh; str5= "Mesh";
1947                                 break;
1948                                 case OB_CURVE:
1949                                         menu1= addmenu_curve;
1950                                         menu2= tb_curve_edit;
1951                                         menu3= tb_curve_select;
1952                                         menu4= tb_transform_editmode1;
1953                                         menu5= tb_curve; str5= "Curve";
1954                                 break;
1955                                 case OB_SURF:
1956                                         menu1= addmenu_surf;
1957                                         menu2= tb_curve_edit;
1958                                         menu3= tb_curve_select;
1959                                         menu4= tb_transform_editmode1;
1960                                         menu5= tb_curve; str5= "Surface";
1961                                 break;
1962                                 case OB_MBALL:
1963                                         menu1= addmenu_meta;
1964                                         menu2= tb_edit;
1965                                         menu3= tb__select;
1966                                         menu4= tb_transform_editmode2;
1967                                         menu5= tb_obdata; str5= "Meta";
1968                                 break;
1969                                 case OB_ARMATURE:
1970                                         menu1= addmenu_armature;
1971                                         menu2= tb_edit;
1972                                         menu3= tb__select;
1973                                         menu4= tb_transform_editmode2;
1974                                         menu5= tb_obdata;str5= "Armature";
1975                                 break;
1976                                 case OB_LATTICE:
1977                                         menu1= tb_empty;
1978                                         menu2= tb_edit;
1979                                         menu3= tb__select;
1980                                         menu4= tb_transform_editmode1;
1981                                         menu5= tb_empty;str5= "Lattice";
1982                                 break;
1983                                 }
1984                         } else {
1985                                 if(G.obedit->type==OB_MESH) {
1986                                         menu1= tb_mesh; str1= "Mesh";
1987                                         menu2= addmenu_mesh; 
1988                                         menu3= tb_mesh_select;
1989                                         menu4= tb_mesh_edit; 
1990                                         menu5= tb_transform_editmode1;
1991                                 }
1992                                 else if(G.obedit->type==OB_CURVE) {
1993                                         menu1= tb_curve; str1= "Curve";
1994                                         menu2= addmenu_curve;
1995                                         menu3= tb_curve_select;
1996                                         menu4= tb_curve_edit;
1997                                         menu5= tb_transform_editmode1;
1998                                 }
1999                                 else if(G.obedit->type==OB_SURF) {
2000                                         menu1= tb_curve; str1= "Surface";
2001                                         menu2= addmenu_surf; 
2002                                         menu3= tb_curve_select;
2003                                         menu4= tb_curve_edit;
2004                                         menu5= tb_transform_editmode1;
2005                                 }
2006                                 else if(G.obedit->type==OB_MBALL) {
2007                                         menu1= tb_obdata; str1= "Meta";
2008                                         menu2= addmenu_meta;
2009                                         menu3= tb__select;
2010                                         menu4= tb_edit;
2011                                         menu5= tb_transform_editmode2;
2012                                 }
2013                                 else if(G.obedit->type==OB_ARMATURE) {
2014                                         menu1= tb_obdata;str1= "Armature";
2015                                         menu2= addmenu_armature;
2016                                         menu3= tb__select;
2017                                         menu4= tb_edit;
2018                                         menu5= tb_transform_editmode2;
2019                                 }
2020                                 else if(G.obedit->type==OB_LATTICE) {
2021                                         menu1= tb_empty;str1= "Lattice";
2022                                         menu2= tb_empty;
2023                                         menu3= tb__select;
2024                                         menu4= tb_edit;
2025                                         menu5= tb_transform_editmode1;
2026                                 }
2027                         }
2028                 }
2029                 else if (G.f & G_FACESELECT) {
2030                         menu3 = tb_face_select;
2031                 }
2032         }
2033         else if(curarea->spacetype==SPACE_NODE) {
2034                 SpaceNode *snode= curarea->spacedata.first;
2035                 
2036                 if(snode->treetype==NTREE_COMPOSIT)
2037                         menu1= tb_node_addcomp; 
2038                 else
2039                         menu1= tb_node_addsh; 
2040                 str1= "Add";
2041                 menu2= tb_node_node; str2= "Node";
2042                 menu3= tb_node_select; str3= "Select";
2043                 menu4= tb_node_transform; str4= "Transform";
2044                 menu5= tb_node_view; str5= "View";
2045                 
2046                 if(snode->treetype==NTREE_SHADER) {
2047                         menu1[0].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_INPUT);
2048                         menu1[1].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_OUTPUT);
2049                         menu1[2].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_OP_COLOR);
2050                         menu1[3].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_OP_VECTOR);
2051                         menu1[4].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_CONVERTOR);
2052                         menu1[5].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_GROUP);
2053                 }
2054                 else if(snode->treetype==NTREE_COMPOSIT) {
2055                         menu1[0].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_INPUT);
2056                         menu1[1].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_OUTPUT);
2057                         menu1[2].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_OP_COLOR);
2058                         menu1[3].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_OP_VECTOR);
2059                         menu1[4].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_OP_FILTER);
2060                         menu1[5].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_CONVERTOR);
2061                         menu1[6].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_MATTE);
2062                         menu1[7].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_DISTORT);
2063                         menu1[8].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_GROUP);
2064
2065                 }
2066                 
2067                 dx= 96;
2068                 tot= 5;
2069                 
2070         }
2071         
2072         getmouseco_sc(mval);
2073         
2074         /* create the main buttons menu */
2075         if(tot==6) {
2076         
2077                 /* check if it fits */
2078                 if(mval[0]-1.5*dx+tb_mainx < 6) mval[0]= 6 + 1.5*dx -tb_mainx;
2079                 else if(mval[0]+1.5*dx+tb_mainx > G.curscreen->sizex-6) 
2080                         mval[0]= G.curscreen->sizex-6-1.5*dx-tb_mainx;
2081
2082                 if(mval[1]-20+tb_mainy < 6) mval[1]= 6+20 -tb_mainy;
2083                 else if(mval[1]+20+tb_mainy > G.curscreen->sizey-6) 
2084                         mval[1]= G.curscreen->sizey-6-20-tb_mainy;
2085         
2086                 but=uiDefBlockBut(block, tb_makemenu, menu1, str1,      mval[0]-(1.5*dx)+tb_mainx,mval[1]+tb_mainy, dx, 19, "");
2087                 uiButSetFlag(but, UI_MAKE_TOP|UI_MAKE_RIGHT);
2088                 uiButSetFunc(but, store_main, (void *)dx, (void *)-5);
2089
2090                 but=uiDefBlockBut(block, tb_makemenu, menu2, str2,      mval[0]-(0.5*dx)+tb_mainx,mval[1]+tb_mainy, dx, 19, "");
2091                 uiButSetFlag(but, UI_MAKE_TOP);
2092                 uiButSetFunc(but, store_main, (void *)0, (void *)-5);
2093
2094                 but=uiDefBlockBut(block, tb_makemenu, menu3, str3,      mval[0]+(0.5*dx)+tb_mainx,mval[1]+tb_mainy, dx, 19, "");
2095                 uiButSetFlag(but, UI_MAKE_TOP|UI_MAKE_LEFT);
2096                 uiButSetFunc(but, store_main, (void *)-dx, (void *)-5);
2097
2098                 but=uiDefBlockBut(block, tb_makemenu, menu4, str4,      mval[0]-(1.5*dx)+tb_mainx,mval[1]+tb_mainy-20, dx, 19, "");
2099                 uiButSetFlag(but, UI_MAKE_DOWN|UI_MAKE_RIGHT);
2100                 uiButSetFunc(but, store_main, (void *)dx, (void *)5);
2101
2102                 but=uiDefBlockBut(block, tb_makemenu, menu5, str5,      mval[0]-(0.5*dx)+tb_mainx,mval[1]+tb_mainy-20, dx, 19, "");
2103                 uiButSetFlag(but, UI_MAKE_DOWN);
2104                 uiButSetFunc(but, store_main, (void *)0, (void *)5);
2105
2106                 but=uiDefBlockBut(block, tb_makemenu, menu6, str6,      mval[0]+(0.5*dx)+tb_mainx,mval[1]+tb_mainy-20, dx, 19, "");
2107                 uiButSetFlag(but, UI_MAKE_DOWN|UI_MAKE_LEFT);
2108                 uiButSetFunc(but, store_main, (void *)-dx, (void *)5);
2109         } else if (tot==5 || tot==7) {
2110                 /* check if it fits, dubious */
2111                 if(mval[0]-0.25*dx+tb_mainx < 6) mval[0]= 6 + 0.25*dx -tb_mainx;
2112                 else if(mval[0]+0.25*dx+tb_mainx > G.curscreen->sizex-6)
2113                 mval[0]= G.curscreen->sizex-6-0.25*dx-tb_mainx;
2114
2115                 if(mval[1]-20+tb_mainy < 6) mval[1]= 6+20 -tb_mainy;
2116                 else if(mval[1]+20+tb_mainy > G.curscreen->sizey-6)
2117                         mval[1]= G.curscreen->sizey-6-20-tb_mainy;
2118
2119                 but=uiDefIconTextBlockBut(block, tb_makemenu, menu1, ICON_RIGHTARROW_THIN, str1, mval[0]+tb_mainx,mval[1]+tb_mainy, dx, 19, "");
2120                 uiButSetFlag(but, UI_MAKE_RIGHT);
2121                 uiButSetFunc(but, store_main, (void *)-32, (void *)-5);
2122
2123                 but=uiDefIconTextBlockBut(block, tb_makemenu, menu2, ICON_RIGHTARROW_THIN, str2, mval[0]+tb_mainx,mval[1]+tb_mainy-20, dx, 19, "");
2124                 uiButSetFlag(but, UI_MAKE_RIGHT);
2125                 uiButSetFunc(but, store_main, (void *)-32, (void *)15);
2126
2127                 but=uiDefIconTextBlockBut(block, tb_makemenu, menu3, ICON_RIGHTARROW_THIN, str3, mval[0]+tb_mainx,mval[1]+tb_mainy-40, dx, 19, "");
2128                 uiButSetFlag(but, UI_MAKE_RIGHT);
2129                 uiButSetFunc(but, store_main, (void *)-32, (void *)35);
2130
2131                 but=uiDefIconTextBlockBut(block, tb_makemenu, menu4, ICON_RIGHTARROW_THIN, str4, mval[0]+tb_mainx,mval[1]+tb_mainy-60, dx, 19, "");
2132                 uiButSetFlag(but, UI_MAKE_RIGHT);
2133                 uiButSetFunc(but, store_main, (void *)-32, (void *)55);
2134
2135                 but=uiDefIconTextBlockBut(block, tb_makemenu, menu5, ICON_RIGHTARROW_THIN, str5, mval[0]+tb_mainx,mval[1]+tb_mainy-80, dx, 19, "");
2136                 uiButSetFlag(but, UI_MAKE_RIGHT);
2137                 uiButSetFunc(but, store_main, (void *)-32, (void *)75);
2138                 
2139                 if(tot>5) {
2140                         but=uiDefIconTextBlockBut(block, tb_makemenu, menu6, ICON_RIGHTARROW_THIN, str6, mval[0]+tb_mainx,mval[1]+tb_mainy-100, dx, 19, "");
2141                         uiButSetFlag(but, UI_MAKE_RIGHT);
2142                         uiButSetFunc(but, store_main, (void *)-32, (void *)95);
2143                 }
2144                 if(tot>6) {
2145                         but=uiDefIconTextBlockBut(block, tb_makemenu, menu7, ICON_RIGHTARROW_THIN, str7, mval[0]+tb_mainx,mval[1]+tb_mainy-120, dx, 19, "");
2146                         uiButSetFlag(but, UI_MAKE_RIGHT);
2147                         uiButSetFunc(but, store_main, (void *)-32, (void *)105);
2148                 }
2149         }
2150         
2151         uiBoundsBlock(block, 2);
2152         event= uiDoBlocks(&tb_listb, 0);
2153         
2154         /* free all dynamic entries... */
2155         BLI_freelistN(&storage);
2156         
2157         mywinset(curarea->win);
2158 }
2159
2160 void toolbox_n_add(void)
2161 {
2162         reset_toolbox();
2163         toolbox_n();
2164 }
2165
2166 void reset_toolbox(void)
2167 {
2168         if(U.uiflag & USER_PLAINMENUS) {
2169                 tb_mainx= -32;
2170                 tb_mainy= -5;
2171         } else {
2172                 tb_mainx= 0;
2173                 tb_mainy= -5;
2174         }
2175 }