59436aa9d5c496001f48bf7ee37ff81873569cce
[blender.git] / source / blender / src / interface_draw.c
1
2 /**
3  * $Id$
4  *
5  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version. The Blender
11  * Foundation also sells licenses for use in proprietary software under
12  * the Blender License.  See http://www.blender.org/BL/ for information
13  * about this.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  *
24  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
25  * All rights reserved.
26  *
27  * The Original Code is: all of this file.
28  *
29  * Contributor(s): none yet.
30  *
31  * ***** END GPL/BL DUAL LICENSE BLOCK *****
32  */
33
34 /* 
35      a full doc with API notes can be found in bf-blender/blender/doc/interface_API.txt
36
37  */
38  
39
40 #include <math.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <ctype.h>
44
45 #ifndef WIN32
46 #include <unistd.h>
47 #else
48 #include <io.h>
49 #endif   
50
51 #include "MEM_guardedalloc.h"
52
53 #include "PIL_time.h"
54
55 #include "BLI_blenlib.h"
56 #include "BLI_arithb.h"
57
58 #include "DNA_color_types.h"
59 #include "DNA_key_types.h"
60 #include "DNA_packedFile_types.h"
61 #include "DNA_screen_types.h"
62 #include "DNA_space_types.h"
63 #include "DNA_texture_types.h"
64 #include "DNA_userdef_types.h"
65 #include "DNA_vec_types.h"
66 #include "DNA_vfont_types.h"
67
68 #include "BKE_blender.h"
69 #include "BKE_colortools.h"
70 #include "BKE_font.h"
71 #include "BKE_global.h"
72 #include "BKE_key.h"
73 #include "BKE_utildefines.h"
74
75 #include "datatoc.h"            /* std font */
76
77 #include "BIF_gl.h"
78 #include "BIF_graphics.h"
79 #include "BIF_keyval.h"
80 #include "BIF_mainqueue.h"
81
82 #include "BIF_screen.h"
83 #include "BIF_toolbox.h"
84 #include "BIF_mywindow.h"
85 #include "BIF_space.h"
86 #include "BIF_glutil.h"
87 #include "BIF_interface.h"
88 #include "BIF_interface_icons.h"
89 #include "BIF_butspace.h"
90 #include "BIF_language.h"
91
92 #include "BSE_view.h"
93
94 #ifdef INTERNATIONAL
95 #include "FTF_Api.h"
96 #endif
97
98 #include "mydevice.h"
99 #include "interface.h"
100 #include "blendef.h"
101
102 // globals
103 extern float UIwinmat[4][4];
104
105
106 /* ************** safe rasterpos for pixmap alignment with pixels ************* */
107
108 void ui_rasterpos_safe(float x, float y, float aspect)
109 {
110         float vals[4], remainder;
111         int doit=0;
112         
113         glRasterPos2f(x, y);
114         glGetFloatv(GL_CURRENT_RASTER_POSITION, vals);
115
116         remainder= vals[0] - floor(vals[0]);
117         if(remainder > 0.4 && remainder < 0.6) {
118                 if(remainder < 0.5) x -= 0.1*aspect;
119                 else x += 0.1*aspect;
120                 doit= 1;
121         }
122         remainder= vals[1] - floor(vals[1]);
123         if(remainder > 0.4 && remainder < 0.6) {
124                 if(remainder < 0.5) y -= 0.1*aspect;
125                 else y += 0.1*aspect;
126                 doit= 1;
127         }
128         
129         if(doit) glRasterPos2f(x, y);
130
131         BIF_RasterPos(x, y);
132         BIF_SetScale(aspect);
133 }
134
135 /* ************** generic embossed rect, for window sliders etc ************* */
136
137 void uiEmboss(float x1, float y1, float x2, float y2, int sel)
138 {
139         
140         /* below */
141         if(sel) glColor3ub(200,200,200);
142         else glColor3ub(50,50,50);
143         fdrawline(x1, y1, x2, y1);
144
145         /* right */
146         fdrawline(x2, y1, x2, y2);
147         
148         /* top */
149         if(sel) glColor3ub(50,50,50);
150         else glColor3ub(200,200,200);
151         fdrawline(x1, y2, x2, y2);
152
153         /* left */
154         fdrawline(x1, y1, x1, y2);
155         
156 }
157
158 /* ************** GENERIC ICON DRAW, NO THEME HERE ************* */
159
160 /* icons have been standardized... and this call draws in untransformed coordinates */
161 #define ICON_HEIGHT             16.0f
162
163 static void ui_draw_icon(uiBut *but, BIFIconID icon)
164 {
165         float xs=0, ys=0, aspect, height;
166         int blend= 0;
167
168         /* this icon doesn't need draw... */
169         if(icon==ICON_BLANK1) return;
170         
171         /* we need aspect from block, for menus... these buttons are scaled in uiPositionBlock() */
172         aspect= but->block->aspect;
173         if(aspect != but->aspect) {
174                 /* prevent scaling up icon in pupmenu */
175                 if (aspect < 1.0f) {                    
176                         height= ICON_HEIGHT;
177                         aspect = 1.0f;
178                         
179                 }
180                 else 
181                         height= ICON_HEIGHT/aspect;
182         }
183         else
184                 height= ICON_HEIGHT;
185         
186         if(but->flag & UI_ICON_LEFT) {
187                 if (but->type==BUTM) {
188                         xs= but->x1+1.0;
189                 }
190                 else if ((but->type==ICONROW) || (but->type==ICONTEXTROW)) {
191                         xs= but->x1+4.0;
192                 }
193                 else {
194                         xs= but->x1+6.0;
195                 }
196                 ys= (but->y1+but->y2- height)/2.0;
197         }
198         if(but->flag & UI_ICON_RIGHT) {
199                 xs= but->x2-17.0;
200                 ys= (but->y1+but->y2- height)/2.0;
201         }
202         if (!((but->flag & UI_ICON_RIGHT) || (but->flag & UI_ICON_LEFT))) {
203                 xs= (but->x1+but->x2- height)/2.0;
204                 ys= (but->y1+but->y2- height)/2.0;
205         }
206
207         /* aspect for the icon has to be stored */
208         BIF_icon_set_aspect(icon, aspect);
209
210         glEnable(GL_BLEND);
211
212         /* calculate blend color */
213         if ELEM4(but->type, ICONTOG, TOG, ROW, TOGN) {
214                 if(but->flag & UI_SELECT);
215                 else if(but->flag & UI_ACTIVE);
216                 else blend= -60;
217         }
218         BIF_icon_draw_blended(xs, ys, icon, but->themecol, blend);
219         
220         glDisable(GL_BLEND);
221
222 }
223
224
225 /* ************** DEFAULT THEME, SHADED BUTTONS ************* */
226
227
228 #define M_WHITE         BIF_ThemeColorShade(colorid, 80)
229
230 #define M_ACT_LIGHT     BIF_ThemeColorShade(colorid, 55)
231 #define M_LIGHT         BIF_ThemeColorShade(colorid, 45)
232 #define M_HILITE        BIF_ThemeColorShade(colorid, 25)
233 #define M_LMEDIUM       BIF_ThemeColorShade(colorid, 10)
234 #define M_MEDIUM        BIF_ThemeColor(colorid)
235 #define M_LGREY         BIF_ThemeColorShade(colorid, -20)
236 #define M_GREY          BIF_ThemeColorShade(colorid, -45)
237 #define M_DARK          BIF_ThemeColorShade(colorid, -80)
238
239 #define M_NUMTEXT                               BIF_ThemeColorShade(colorid, 25)
240 #define M_NUMTEXT_ACT_LIGHT             BIF_ThemeColorShade(colorid, 35)
241
242 #define MM_WHITE        BIF_ThemeColorShade(TH_BUT_NEUTRAL, 120)
243
244 /* Used for the subtle sunken effect around buttons.
245  * One option is to hardcode to white, with alpha, however it causes a 
246  * weird 'building up' efect, so it's commented out for now.
247  */
248  
249 /*
250 #define MM_WHITE_OP     glColor4ub(255, 255, 255, 60)
251 #define MM_WHITE_TR     glColor4ub(255, 255, 255, 0)
252  */
253
254 #define MM_WHITE_OP     BIF_ThemeColorShadeAlpha(TH_BACK, 55, -100)
255 #define MM_WHITE_TR     BIF_ThemeColorShadeAlpha(TH_BACK, 55, -255)
256
257 #define MM_LIGHT        BIF_ThemeColorShade(TH_BUT_OUTLINE, 45)
258 #define MM_MEDIUM       BIF_ThemeColor(TH_BUT_OUTLINE)
259 #define MM_GREY         BIF_ThemeColorShade(TH_BUT_OUTLINE, -45)
260 #define MM_DARK         BIF_ThemeColorShade(TH_BUT_OUTLINE, -80)
261
262 /* base shaded button */
263 static void shaded_button(float x1, float y1, float x2, float y2, float asp, int colorid, int flag, int mid)
264 {
265         /* 'mid' arg determines whether the button is in the middle of
266          * an alignment group or not. 0 = not middle, 1 = is in the middle.
267          * Done to allow cleaner drawing
268          */
269          
270         /* *** SHADED BUTTON BASE *** */
271         glShadeModel(GL_SMOOTH);
272         glBegin(GL_QUADS);
273         
274         if(flag & UI_SELECT) {
275                 if(flag & UI_ACTIVE) M_MEDIUM;
276                 else M_LGREY;
277         } else {
278                 if(flag & UI_ACTIVE) M_LIGHT;
279                 else M_HILITE;
280         }
281
282         glVertex2f(x1,y1);
283         glVertex2f(x2,y1);
284
285         if(flag & UI_SELECT) {
286                 if(flag & UI_ACTIVE) M_LGREY;
287                 else M_GREY;
288         } else {
289                 if(flag & UI_ACTIVE) M_ACT_LIGHT;
290                 else M_LIGHT;
291         }
292
293         glVertex2f(x2,(y2-(y2-y1)/3));
294         glVertex2f(x1,(y2-(y2-y1)/3));
295         glEnd();
296         
297
298         glShadeModel(GL_FLAT);
299         glBegin(GL_QUADS);
300         
301         if(flag & UI_SELECT) {
302                 if(flag & UI_ACTIVE) M_LGREY;
303                 else M_GREY;
304         } else {
305                 if(flag & UI_ACTIVE) M_ACT_LIGHT;
306                 else M_LIGHT;
307         }
308         
309         glVertex2f(x1,(y2-(y2-y1)/3));
310         glVertex2f(x2,(y2-(y2-y1)/3));
311         glVertex2f(x2,y2);
312         glVertex2f(x1,y2);
313
314         glEnd();
315         /* *** END SHADED BUTTON BASE *** */
316         
317         /* *** INNER OUTLINE *** */
318         /* left */
319         if(!(flag & UI_SELECT)) {
320                 glShadeModel(GL_SMOOTH);
321                 glBegin(GL_LINES);
322                 M_MEDIUM;
323                 glVertex2f(x1+1,y1+2);
324                 M_WHITE;
325                 glVertex2f(x1+1,y2);
326                 glEnd();
327         }
328         
329         /* right */
330                 if(!(flag & UI_SELECT)) {
331                 glShadeModel(GL_SMOOTH);
332                 glBegin(GL_LINES);
333                 M_MEDIUM;
334                 glVertex2f(x2-1,y1+2);
335                 M_WHITE;
336                 glVertex2f(x2-1,y2);
337                 glEnd();
338         }
339         
340         glShadeModel(GL_FLAT);
341         
342         /* top */
343         if(flag & UI_SELECT) {
344                 if(flag & UI_ACTIVE) M_LGREY;
345                 else M_GREY;
346         } else {
347                 if(flag & UI_ACTIVE) M_WHITE;
348                 else M_WHITE;
349         }
350
351         fdrawline(x1, (y2-1), x2, (y2-1));
352         
353         /* bottom */
354         if(flag & UI_SELECT) {
355                 if(flag & UI_ACTIVE) M_MEDIUM;
356                 else M_LGREY;
357         } else {
358                 if(flag & UI_ACTIVE) M_LMEDIUM;
359                 else M_MEDIUM;
360         }
361         fdrawline(x1, (y1+1), x2, (y1+1));
362         /* *** END INNER OUTLINE *** */
363         
364         /* *** OUTER OUTLINE *** */
365         if (mid) {
366                 // we draw full outline, its not AA, and it works better button mouse-over hilite
367                 MM_DARK;
368                 
369                 // left right
370                 fdrawline(x1, y1, x1, y2);
371                 fdrawline(x2, y1, x2, y2);
372         
373                 // top down
374                 fdrawline(x1, y2, x2, y2);
375                 fdrawline(x1, y1, x2, y1); 
376         } else {
377                 MM_DARK;
378                 gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 1.5);
379         }
380         /* END OUTER OUTLINE */
381 }
382
383 /* base flat button */
384 static void flat_button(float x1, float y1, float x2, float y2, float asp, int colorid, int flag, int mid)
385 {
386         /* 'mid' arg determines whether the button is in the middle of
387          * an alignment group or not. 0 = not middle, 1 = is in the middle.
388          * Done to allow cleaner drawing
389          */
390          
391         /* *** FLAT TEXT/NUM FIELD *** */
392         glShadeModel(GL_FLAT);
393         if(flag & UI_SELECT) {
394                 if(flag & UI_ACTIVE) M_LGREY;
395                 else M_GREY;
396         }
397         else {
398                 if(flag & UI_ACTIVE) M_NUMTEXT_ACT_LIGHT;
399                 else M_NUMTEXT;
400         }
401
402         glRectf(x1, y1, x2, y2);
403         /* *** END FLAT TEXT/NUM FIELD *** */
404         
405         /* *** OUTER OUTLINE *** */
406         if (mid) {
407                 // we draw full outline, its not AA, and it works better button mouse-over hilite
408                 MM_DARK;
409                 
410                 // left right
411                 fdrawline(x1, y1, x1, y2);
412                 fdrawline(x2, y1, x2, y2);
413         
414                 // top down
415                 fdrawline(x1, y2, x2, y2);
416                 fdrawline(x1, y1, x2, y1); 
417         } else {
418                 MM_DARK;
419                 gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 1.5);
420         }
421         /* END OUTER OUTLINE */
422 }
423
424 /* small side double arrow for iconrow */
425 static void ui_default_iconrow_arrows(float x1, float y1, float x2, float y2)
426 {
427         glEnable( GL_POLYGON_SMOOTH );
428         glEnable( GL_BLEND );
429         
430         glShadeModel(GL_FLAT);
431         glBegin(GL_TRIANGLES);
432         glVertex2f((short)x2-2,(short)(y2-(y2-y1)/2)+1);
433         glVertex2f((short)x2-6,(short)(y2-(y2-y1)/2)+1);
434         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2)+4);
435         glEnd();
436                 
437         glBegin(GL_TRIANGLES);
438         glVertex2f((short)x2-2,(short)(y2-(y2-y1)/2) -1);
439         glVertex2f((short)x2-6,(short)(y2-(y2-y1)/2) -1);
440         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2) -4);
441         glEnd();
442         
443         glDisable( GL_BLEND );
444         glDisable( GL_POLYGON_SMOOTH );
445 }
446
447 /* side double arrow for menu */
448 static void ui_default_menu_arrows(float x1, float y1, float x2, float y2)
449 {
450         glEnable( GL_POLYGON_SMOOTH );
451         glEnable( GL_BLEND );
452         
453         glShadeModel(GL_FLAT);
454         glBegin(GL_TRIANGLES);
455         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2)+1);
456         glVertex2f((short)x2-12,(short)(y2-(y2-y1)/2)+1);
457         glVertex2f((short)x2-8,(short)(y2-(y2-y1)/2)+4);
458         glEnd();
459                 
460         glBegin(GL_TRIANGLES);
461         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2) -1);
462         glVertex2f((short)x2-12,(short)(y2-(y2-y1)/2) -1);
463         glVertex2f((short)x2-8,(short)(y2-(y2-y1)/2) -4);
464         glEnd();
465         
466         glDisable( GL_BLEND );
467         glDisable( GL_POLYGON_SMOOTH );
468 }
469
470 /* left/right arrows for number fields */
471 static void ui_default_num_arrows(float x1, float y1, float x2, float y2)
472 {
473         if( x2-x1 > 25) {       // 25 is a bit arbitrary, but small buttons cant have arrows
474
475                 glEnable( GL_POLYGON_SMOOTH );
476                 glEnable( GL_BLEND );
477                 
478                 glShadeModel(GL_FLAT);
479                 glBegin(GL_TRIANGLES);
480                 
481                 glVertex2f((short)x1+5,(short)(y2-(y2-y1)/2));
482                 glVertex2f((short)x1+10,(short)(y2-(y2-y1)/2)+4);
483                 glVertex2f((short)x1+10,(short)(y2-(y2-y1)/2)-4);
484                 glEnd();
485
486                 /* right */
487                 glShadeModel(GL_FLAT);
488                 glBegin(GL_TRIANGLES);
489
490                 glVertex2f((short)x2-5,(short)(y2-(y2-y1)/2));
491                 glVertex2f((short)x2-10,(short)(y2-(y2-y1)/2)-4);
492                 glVertex2f((short)x2-10,(short)(y2-(y2-y1)/2)+4);
493                 glEnd();
494                 
495                 glDisable( GL_BLEND );
496                 glDisable( GL_POLYGON_SMOOTH );
497         }
498 }
499
500 /* changing black/white for TOG3 buts */
501 static void ui_tog3_invert(float x1, float y1, float x2, float y2, int seltype)
502 {
503         short alpha = 30;
504         
505         if (seltype == 0) {
506                 glEnable(GL_BLEND);
507                 
508                 glColor4ub(0, 0, 0, alpha);
509                 glRectf(x2-6, y1, x2, (y1+(y2-y1)/2));
510                 
511                 glColor4ub(255, 255, 255, alpha);
512                 glRectf(x2-6, (y1+(y2-y1)/2), x2, y2);
513                 
514                 glDisable(GL_BLEND);
515         } else {
516                 glEnable(GL_BLEND);
517                 
518                 glColor4ub(255, 255, 255, alpha);
519                 glRectf(x2-6, y1, x2, (y1+(y2-y1)/2));
520                 
521                 glColor4ub(0, 0, 0, alpha);
522                 glRectf(x2-6, (y1+(y2-y1)/2), x2, y2);
523                 
524                 glDisable(GL_BLEND);
525         }
526 }
527
528 /* button/popup menu/iconrow drawing code */
529 static void ui_default_button(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
530 {
531         int align= (flag & UI_BUT_ALIGN);
532
533         if(align) {
534         
535                 /* *** BOTTOM OUTER SUNKEN EFFECT *** */
536                 if (!((align == UI_BUT_ALIGN_DOWN) ||
537                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT)) ||
538                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT)))) {
539                         glEnable(GL_BLEND);
540                         MM_WHITE_OP;
541                         fdrawline(x1, y1-1, x2, y1-1);  
542                         glDisable(GL_BLEND);
543                 }
544                 /* *** END BOTTOM OUTER SUNKEN EFFECT *** */
545                 
546                 switch(align) {
547                 case UI_BUT_ALIGN_TOP:
548                         uiSetRoundBox(12);
549                         
550                         /* last arg in shaded_button() determines whether the button is in the middle of
551                          * an alignment group or not. 0 = not middle, 1 = is in the middle.
552                          * Done to allow cleaner drawing
553                          */
554                          
555                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
556                         break;
557                 case UI_BUT_ALIGN_DOWN:
558                         uiSetRoundBox(3);
559                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
560                         break;
561                 case UI_BUT_ALIGN_LEFT:
562                         
563                         /* RIGHT OUTER SUNKEN EFFECT */
564                         glEnable(GL_BLEND);
565                         glShadeModel(GL_SMOOTH);
566                         glBegin(GL_LINES);
567                         MM_WHITE_OP;
568                         glVertex2f(x2+1,y1);
569                         MM_WHITE_TR;
570                         glVertex2f(x2+1,y2);
571                         glEnd();
572                         glDisable(GL_BLEND);
573                         
574                         uiSetRoundBox(6);
575                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
576                         break;
577                 case UI_BUT_ALIGN_RIGHT:
578                 
579                         /* LEFT OUTER SUNKEN EFFECT */
580                         glEnable(GL_BLEND);
581                         glShadeModel(GL_SMOOTH);
582                         glBegin(GL_LINES);
583                         MM_WHITE_OP;
584                         glVertex2f(x1-1,y1);
585                         MM_WHITE_TR;
586                         glVertex2f(x1-1,y2);
587                         glEnd();
588                         glDisable(GL_BLEND);
589                 
590                         uiSetRoundBox(9);
591                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
592                         break;
593                         
594                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
595                         uiSetRoundBox(1);
596                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
597                         break;
598                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
599                         uiSetRoundBox(2);
600                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
601                         break;
602                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
603                 
604                         /* LEFT OUTER SUNKEN EFFECT */
605                         glEnable(GL_BLEND);
606                         glShadeModel(GL_SMOOTH);
607                         glBegin(GL_LINES);
608                         MM_WHITE_OP;
609                         glVertex2f(x1-1,y1);
610                         MM_WHITE_TR;
611                         glVertex2f(x1-1,y2);
612                         glEnd();
613                         glDisable(GL_BLEND);
614                 
615                         uiSetRoundBox(8);
616                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
617                         break;
618                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
619                 
620                         /* RIGHT OUTER SUNKEN EFFECT */
621                         glEnable(GL_BLEND);
622                         glShadeModel(GL_SMOOTH);
623                         glBegin(GL_LINES);
624                         MM_WHITE_OP;
625                         glVertex2f(x2+1,y1);
626                         MM_WHITE_TR;
627                         glVertex2f(x2+1,y2);
628                         glEnd();
629                         glDisable(GL_BLEND);
630                         
631                         uiSetRoundBox(4);
632                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
633                         break;
634                         
635                 default:
636                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 1);
637                         break;
638                 }
639         } 
640         else {  
641                 glEnable(GL_BLEND);
642                 glShadeModel(GL_SMOOTH);
643                 
644                 /* BOTTOM OUTER SUNKEN EFFECT */
645                 MM_WHITE_OP;
646                 fdrawline(x1, y1-1, x2, y1-1);  
647                 
648                 /* LEFT OUTER SUNKEN EFFECT */
649                 glBegin(GL_LINES);
650                 MM_WHITE_OP;
651                 glVertex2f(x1-1,y1);
652                 MM_WHITE_TR;
653                 glVertex2f(x1-1,y2);
654                 glEnd();
655                 
656                 /* RIGHT OUTER SUNKEN EFFECT */
657                 glBegin(GL_LINES);
658                 MM_WHITE_OP;
659                 glVertex2f(x2+1,y1);
660                 MM_WHITE_TR;
661                 glVertex2f(x2+1,y2);
662                 glEnd();
663                 
664                 glDisable(GL_BLEND);
665         
666                 uiSetRoundBox(15);
667                 shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
668         }
669         
670         /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */
671         switch(type) {
672         case ICONROW:
673         case ICONTEXTROW:
674                 /* DARKENED AREA */
675                 glEnable(GL_BLEND);
676                 
677                 glColor4ub(0, 0, 0, 30);
678                 glRectf(x2-9, y1, x2, y2);
679         
680                 glDisable(GL_BLEND);
681                 /* END DARKENED AREA */
682         
683                 /* ICONROW DOUBLE-ARROW  */
684                 M_DARK;
685                 ui_default_iconrow_arrows(x1, y1, x2, y2);
686                 /* END ICONROW DOUBLE-ARROW */
687                 break;
688         case MENU:
689                 /* DARKENED AREA */
690                 glEnable(GL_BLEND);
691                 
692                 glColor4ub(0, 0, 0, 30);
693                 glRectf(x2-18, y1, x2, y2);
694         
695                 glDisable(GL_BLEND);
696                 /* END DARKENED AREA */
697         
698                 /* MENU DOUBLE-ARROW  */
699                 M_DARK;
700                 ui_default_menu_arrows(x1, y1, x2, y2);
701                 /* MENU DOUBLE-ARROW */
702                 break;
703         }       
704 }
705
706
707 /* number/text field drawing code */
708 static void ui_default_flat(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
709 {
710         int align= (flag & UI_BUT_ALIGN);
711
712         if(align) {
713         
714                 /* *** BOTTOM OUTER SUNKEN EFFECT *** */
715                 if (!((align == UI_BUT_ALIGN_DOWN) ||
716                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT)) ||
717                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT)))) {
718                         glEnable(GL_BLEND);
719                         MM_WHITE_OP;
720                         fdrawline(x1, y1-1, x2, y1-1);  
721                         glDisable(GL_BLEND);
722                 }
723                 /* *** END BOTTOM OUTER SUNKEN EFFECT *** */
724                 
725                 switch(align) {
726                 case UI_BUT_ALIGN_TOP:
727                         uiSetRoundBox(12);
728                         
729                         /* last arg in shaded_button() determines whether the button is in the middle of
730                          * an alignment group or not. 0 = not middle, 1 = is in the middle.
731                          * Done to allow cleaner drawing
732                          */
733                          
734                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
735                         break;
736                 case UI_BUT_ALIGN_DOWN:
737                         uiSetRoundBox(3);
738                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
739                         break;
740                 case UI_BUT_ALIGN_LEFT:
741                         
742                         /* RIGHT OUTER SUNKEN EFFECT */
743                         glEnable(GL_BLEND);
744                         glShadeModel(GL_SMOOTH);
745                         glBegin(GL_LINES);
746                         MM_WHITE_OP;
747                         glVertex2f(x2+1,y1);
748                         MM_WHITE_TR;
749                         glVertex2f(x2+1,y2);
750                         glEnd();
751                         glDisable(GL_BLEND);
752                         
753                         uiSetRoundBox(6);
754                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
755                         break;
756                 case UI_BUT_ALIGN_RIGHT:
757                 
758                         /* LEFT OUTER SUNKEN EFFECT */
759                         glEnable(GL_BLEND);
760                         glShadeModel(GL_SMOOTH);
761                         glBegin(GL_LINES);
762                         MM_WHITE_OP;
763                         glVertex2f(x1-1,y1);
764                         MM_WHITE_TR;
765                         glVertex2f(x1-1,y2);
766                         glEnd();
767                         glDisable(GL_BLEND);
768                 
769                         uiSetRoundBox(9);
770                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
771                         break;
772                         
773                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
774                         uiSetRoundBox(1);
775                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
776                         break;
777                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
778                         uiSetRoundBox(2);
779                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
780                         break;
781                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
782                 
783                         /* LEFT OUTER SUNKEN EFFECT */
784                         glEnable(GL_BLEND);
785                         glShadeModel(GL_SMOOTH);
786                         glBegin(GL_LINES);
787                         MM_WHITE_OP;
788                         glVertex2f(x1-1,y1);
789                         MM_WHITE_TR;
790                         glVertex2f(x1-1,y2);
791                         glEnd();
792                         glDisable(GL_BLEND);
793                 
794                         uiSetRoundBox(8);
795                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
796                         break;
797                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
798                 
799                         /* RIGHT OUTER SUNKEN EFFECT */
800                         glEnable(GL_BLEND);
801                         glShadeModel(GL_SMOOTH);
802                         glBegin(GL_LINES);
803                         MM_WHITE_OP;
804                         glVertex2f(x2+1,y1);
805                         MM_WHITE_TR;
806                         glVertex2f(x2+1,y2);
807                         glEnd();
808                         glDisable(GL_BLEND);
809                         
810                         uiSetRoundBox(4);
811                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
812                         break;
813                         
814                 default:
815                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 1);
816                         break;
817                 }
818         } 
819         else {
820         
821                 glEnable(GL_BLEND);
822                 glShadeModel(GL_SMOOTH);
823                 
824                 /* BOTTOM OUTER SUNKEN EFFECT */
825                 MM_WHITE_OP;
826                 fdrawline(x1, y1-1, x2, y1-1);  
827                 
828                 /* LEFT OUTER SUNKEN EFFECT */
829                 glBegin(GL_LINES);
830                 MM_WHITE_OP;
831                 glVertex2f(x1-1,y1);
832                 MM_WHITE_TR;
833                 glVertex2f(x1-1,y2);
834                 glEnd();
835                 
836                 /* RIGHT OUTER SUNKEN EFFECT */
837                 glBegin(GL_LINES);
838                 MM_WHITE_OP;
839                 glVertex2f(x2+1,y1);
840                 MM_WHITE_TR;
841                 glVertex2f(x2+1,y2);
842                 glEnd();
843                 
844                 glDisable(GL_BLEND);
845
846                 uiSetRoundBox(15);
847                 flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
848         }
849         
850         /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */
851         switch(type) {
852         case NUM:
853                 /* SIDE ARROWS */
854                 /* left */
855                 if(flag & UI_SELECT) {
856                         if(flag & UI_ACTIVE) M_DARK;
857                         else M_DARK;
858                 } else {
859                         if(flag & UI_ACTIVE) M_GREY;
860                         else M_LGREY;
861                 }
862                 
863                 ui_default_num_arrows(x1, y1, x2, y2);
864                 /* END SIDE ARROWS */
865         }
866 }
867
868 static void ui_default_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag)
869 {
870         float ymid, yc;
871
872         /* the slider background line */
873         ymid= (y1+y2)/2.0;
874         //yc= 2.5*aspect;       // height of center line
875         yc = 2.3; // height of center line
876         
877         if(flag & UI_SELECT) 
878                         BIF_ThemeColorShade(TH_BUT_NUM, -5);
879         else
880                 if(flag & UI_ACTIVE) 
881                         BIF_ThemeColorShade(TH_BUT_NUM, +35); 
882                 else
883                         BIF_ThemeColorShade(TH_BUT_NUM, +25); 
884
885         glRectf(x1, ymid-yc, x2, ymid+yc);
886         
887         /* top inner bevel */
888         if(flag & UI_SELECT) BIF_ThemeColorShade(TH_BUT_NUM, -40); 
889         else BIF_ThemeColorShade(TH_BUT_NUM, -5); 
890         fdrawline(x1+1, ymid+yc, x2, ymid+yc);
891         
892         /* bottom inner bevel */
893         if(flag & UI_SELECT) BIF_ThemeColorShade(TH_BUT_NUM, +15); 
894         else BIF_ThemeColorShade(TH_BUT_NUM, +45); 
895         fdrawline(x1+1, ymid-yc, x2, ymid-yc);
896         
897         
898         /* the movable slider */
899         if(flag & UI_SELECT) BIF_ThemeColorShade(TH_BUT_NUM, +80); 
900         else BIF_ThemeColorShade(TH_BUT_NUM, -45); 
901
902         glShadeModel(GL_SMOOTH);
903         glBegin(GL_QUADS);
904
905         BIF_ThemeColorShade(TH_BUT_NUM, -45); 
906
907         glVertex2f(x1,     y1+2.5);
908         glVertex2f(x1+fac, y1+2.5);
909
910         BIF_ThemeColor(TH_BUT_NUM); 
911
912         glVertex2f(x1+fac, y2-2.5);
913         glVertex2f(x1,     y2-2.5);
914
915         glEnd();
916         
917
918         /* slider handle center */
919         glShadeModel(GL_SMOOTH);
920         glBegin(GL_QUADS);
921
922         BIF_ThemeColor(TH_BUT_NUM); 
923         glVertex2f(x1+fac-3, y1+2);
924         glVertex2f(x1+fac, y1+4);
925         BIF_ThemeColorShade(TH_BUT_NUM, +80); 
926         glVertex2f(x1+fac, y2-2);
927         glVertex2f(x1+fac-3, y2-2);
928
929         glEnd();
930         
931         /* slider handle left bevel */
932         BIF_ThemeColorShade(TH_BUT_NUM, +70); 
933         fdrawline(x1+fac-3, y2-2, x1+fac-3, y1+2);
934         
935         /* slider handle right bevel */
936         BIF_ThemeColorShade(TH_BUT_NUM, -35); 
937         fdrawline(x1+fac, y2-2, x1+fac, y1+2);
938
939         glShadeModel(GL_FLAT);
940 }
941
942 /* default theme callback */
943 static void ui_draw_default(int type, int colorid, float aspect, float x1, float y1, float x2, float y2, int flag)
944 {
945
946         switch(type) {
947         case TEX:
948         case IDPOIN:
949         case NUM:
950                 ui_default_flat(type, colorid, aspect, x1, y1, x2, y2, flag);
951                 break;
952         case ICONROW: 
953         case ICONTEXTROW: 
954         case MENU: 
955         default: 
956                 ui_default_button(type, colorid, aspect, x1, y1, x2, y2, flag);
957         }
958
959 }
960
961
962 /* *************** OLDSKOOL THEME ***************** */
963
964 static void ui_draw_outlineX(float x1, float y1, float x2, float y2, float asp1)
965 {
966         float vec[2];
967         
968         glBegin(GL_LINE_LOOP);
969         vec[0]= x1+asp1; vec[1]= y1-asp1;
970         glVertex2fv(vec);
971         vec[0]= x2-asp1; 
972         glVertex2fv(vec);
973         vec[0]= x2+asp1; vec[1]= y1+asp1;
974         glVertex2fv(vec);
975         vec[1]= y2-asp1;
976         glVertex2fv(vec);
977         vec[0]= x2-asp1; vec[1]= y2+asp1;
978         glVertex2fv(vec);
979         vec[0]= x1+asp1;
980         glVertex2fv(vec);
981         vec[0]= x1-asp1; vec[1]= y2-asp1;
982         glVertex2fv(vec);
983         vec[1]= y1+asp1;
984         glVertex2fv(vec);
985         glEnd();                
986         
987 }
988
989
990 static void ui_draw_oldskool(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
991 {
992         /* paper */
993         if(flag & UI_SELECT) {
994                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, -40);
995                 else BIF_ThemeColorShade(colorid, -30);
996         }
997         else {
998                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, +30);
999                 else BIF_ThemeColorShade(colorid, +20);
1000         }
1001         
1002         glRectf(x1+1, y1+1, x2-1, y2-1);
1003
1004         x1+= asp;
1005         x2-= asp;
1006         y1+= asp;
1007         y2-= asp;
1008
1009         /* below */
1010         if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, 0);
1011         else BIF_ThemeColorShade(colorid, -30);
1012         fdrawline(x1, y1, x2, y1);
1013
1014         /* right */
1015         fdrawline(x2, y1, x2, y2);
1016         
1017         /* top */
1018         if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -30);
1019         else BIF_ThemeColorShade(colorid, 0);
1020         fdrawline(x1, y2, x2, y2);
1021
1022         /* left */
1023         fdrawline(x1, y1, x1, y2);
1024         
1025         /* outline */
1026         glColor3ub(0,0,0);
1027         ui_draw_outlineX(x1, y1, x2, y2, asp);
1028         
1029         
1030         /* special type decorations */
1031         switch(type) {
1032         case NUM:
1033                 if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -60);
1034                 else BIF_ThemeColorShade(colorid, -30);
1035                 ui_default_num_arrows(x1, y1, x2, y2);
1036                 break;
1037
1038         case ICONROW: 
1039         case ICONTEXTROW: 
1040                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1041                 else BIF_ThemeColorShade(colorid, -10);
1042                 glRectf(x2-9, y1+asp, x2-asp, y2-asp);
1043
1044                 BIF_ThemeColorShade(colorid, -50);
1045                 ui_default_iconrow_arrows(x1, y1, x2, y2);
1046                 break;
1047                 
1048         case MENU: 
1049                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1050                 else BIF_ThemeColorShade(colorid, -10);
1051                 glRectf(x2-17, y1+asp, x2-asp, y2-asp);
1052
1053                 BIF_ThemeColorShade(colorid, -50);
1054                 ui_default_menu_arrows(x1, y1, x2, y2);
1055                 break;
1056         }
1057         
1058 }
1059
1060 /* *************** BASIC ROUNDED THEME ***************** */
1061
1062 static void round_button(float x1, float y1, float x2, float y2, float asp, 
1063                                                  int colorid, int round, int menudeco, int curshade)
1064 {
1065         float rad;
1066         char col[4];
1067         
1068         rad= (y2-y1)/2.0;
1069         if(rad>7.0) rad= 7.0;
1070         
1071         uiSetRoundBox(round);
1072         gl_round_box(GL_POLYGON, x1, y1, x2, y2, rad);
1073
1074         if(menudeco) {
1075                 uiSetRoundBox(round & ~9);
1076                 BIF_ThemeColorShade(colorid, curshade-20);
1077                 gl_round_box(GL_POLYGON, x2-menudeco, y1, x2, y2, rad);
1078         }
1079         
1080         /* fake AA */
1081         uiSetRoundBox(round);
1082         glEnable( GL_BLEND );
1083
1084         BIF_GetThemeColor3ubv(colorid, col);
1085                 
1086         if(col[0]<100) col[0]= 0; else col[0]-= 100;
1087         if(col[1]<100) col[1]= 0; else col[1]-= 100;
1088         if(col[2]<100) col[2]= 0; else col[2]-= 100;
1089         col[3]= 80;
1090         glColor4ubv(col);
1091         gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, rad - asp);
1092         gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, rad + asp);
1093         col[3]= 180;
1094         glColor4ubv(col);
1095         gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, rad);
1096
1097         glDisable( GL_BLEND );
1098 }
1099
1100 /* button in midst of alignment row */
1101 static void round_button_mid(float x1, float y1, float x2, float y2, float asp, 
1102                                                          int colorid, int align, int menudeco, int curshade)
1103 {
1104         glRectf(x1, y1, x2, y2);
1105         
1106         if(menudeco) {
1107                 BIF_ThemeColorShade(colorid, curshade-20);
1108                 glRectf(x2-menudeco, y1, x2, y2);
1109         }
1110         
1111         BIF_ThemeColorBlendShade(colorid, TH_BACK, 0.5, -70);
1112         // we draw full outline, its not AA, and it works better button mouse-over hilite
1113         
1114         // left right
1115         fdrawline(x1, y1, x1, y2);
1116         fdrawline(x2, y1, x2, y2);
1117
1118         // top down
1119         fdrawline(x1, y2, x2, y2);
1120         fdrawline(x1, y1, x2, y1);   
1121 }
1122
1123 static void ui_draw_round(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1124 {
1125         int align= (flag & UI_BUT_ALIGN);
1126         int curshade= 0, menudeco= 0;
1127         
1128         if(type==ICONROW || type==ICONTEXTROW) menudeco= 9;
1129         else if((type==MENU || type==BLOCK) && x2-x1>24) menudeco= 16;
1130         
1131         /* paper */
1132         if(flag & UI_SELECT) {
1133                 if(flag & UI_ACTIVE) curshade= -40;
1134                 else curshade= -30;
1135         }
1136         else {
1137                 if(flag & UI_ACTIVE) curshade= 30;
1138                 else curshade= +20;
1139         }
1140         
1141         BIF_ThemeColorShade(colorid, curshade);
1142
1143         if(align) {
1144                 switch(align) {
1145                 case UI_BUT_ALIGN_TOP:
1146                         round_button(x1, y1, x2, y2, asp, colorid, 12, menudeco, curshade);
1147                         break;
1148                 case UI_BUT_ALIGN_DOWN:
1149                         round_button(x1, y1, x2, y2, asp, colorid, 3, menudeco, curshade);
1150                         break;
1151                 case UI_BUT_ALIGN_LEFT:
1152                         round_button(x1, y1, x2, y2, asp, colorid, 6, menudeco, curshade);
1153                         break;
1154                 case UI_BUT_ALIGN_RIGHT:
1155                         round_button(x1, y1, x2, y2, asp, colorid, 9, menudeco, curshade);
1156                         break;
1157                         
1158                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
1159                         round_button(x1, y1, x2, y2, asp, colorid, 1, menudeco, curshade);
1160                         break;
1161                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
1162                         round_button(x1, y1, x2, y2, asp, colorid, 2, menudeco, curshade);
1163                         break;
1164                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
1165                         round_button(x1, y1, x2, y2, asp, colorid, 8, menudeco, curshade);
1166                         break;
1167                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
1168                         round_button(x1, y1, x2, y2, asp, colorid, 4, menudeco, curshade);
1169                         break;
1170                         
1171                 default:
1172                         round_button_mid(x1, y1, x2, y2, asp, colorid, align, menudeco, curshade);
1173                         break;
1174                 }
1175         } 
1176         else {
1177                 round_button(x1, y1, x2, y2, asp, colorid, 15, menudeco, curshade);
1178         }
1179
1180         /* special type decorations */
1181         switch(type) {
1182         case NUM:
1183                 BIF_ThemeColorShade(colorid, curshade-60);
1184                 ui_default_num_arrows(x1, y1, x2, y2);
1185                 break;
1186
1187         case ICONROW: 
1188         case ICONTEXTROW: 
1189                 BIF_ThemeColorShade(colorid, curshade-60);
1190                 ui_default_iconrow_arrows(x1, y1, x2, y2);
1191                 break;
1192                 
1193         case MENU: 
1194         case BLOCK: 
1195                 BIF_ThemeColorShade(colorid, curshade-60);
1196                 ui_default_menu_arrows(x1, y1, x2, y2);
1197                 break;
1198         }
1199 }
1200
1201 /* *************** MINIMAL THEME ***************** */
1202
1203 // theme can define an embosfunc and sliderfunc, text+icon drawing is standard, no theme.
1204
1205
1206
1207 /* super minimal button as used in logic menu */
1208 static void ui_draw_minimal(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1209 {
1210         /* too much space between buttons */
1211         /* 
1212         x1+= asp;
1213         x2-= asp;
1214         y1+= asp;
1215         y2-= asp;
1216         */
1217         
1218         /* Less space between buttons looks nicer */
1219         y2-= asp;
1220         x2-= asp;
1221         
1222         /* paper */
1223         if(flag & UI_SELECT) {
1224                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, -40);
1225                 else BIF_ThemeColorShade(colorid, -30);
1226         }
1227         else {
1228                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, +20);
1229                 else BIF_ThemeColorShade(colorid, +10);
1230         }
1231         
1232         glRectf(x1, y1, x2, y2);
1233
1234         if(flag & UI_SELECT) {
1235                 BIF_ThemeColorShade(colorid, -60);
1236
1237                 /* top */
1238                 fdrawline(x1, y2, x2, y2);
1239                 /* left */
1240                 fdrawline(x1, y1, x1, y2);
1241                 BIF_ThemeColorShade(colorid, +40);
1242
1243                 /* below */
1244                 fdrawline(x1, y1, x2, y1);
1245                 /* right */
1246                 fdrawline(x2, y1, x2, y2);
1247         }
1248         else {
1249                 BIF_ThemeColorShade(colorid, +40);
1250
1251                 /* top */
1252                 fdrawline(x1, y2, x2, y2);
1253                 /* left */
1254                 fdrawline(x1, y1, x1, y2);
1255                 
1256                 BIF_ThemeColorShade(colorid, -60);
1257                 /* below */
1258                 fdrawline(x1, y1, x2, y1);
1259                 /* right */
1260                 fdrawline(x2, y1, x2, y2);
1261         }
1262         
1263         /* special type decorations */
1264         switch(type) {
1265         case NUM:
1266                 if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -60);
1267                 else BIF_ThemeColorShade(colorid, -30);
1268                 ui_default_num_arrows(x1, y1, x2, y2);
1269                 break;
1270
1271         case ICONROW: 
1272         case ICONTEXTROW: 
1273                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1274                 else BIF_ThemeColorShade(colorid, -10);
1275                 glRectf(x2-9, y1+asp, x2-asp, y2-asp);
1276
1277                 BIF_ThemeColorShade(colorid, -50);
1278                 ui_default_iconrow_arrows(x1, y1, x2, y2);
1279                 break;
1280                 
1281         case MENU: 
1282         case BLOCK: 
1283                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1284                 else BIF_ThemeColorShade(colorid, -10);
1285                 glRectf(x2-17, y1+asp, x2-asp, y2-asp);
1286
1287                 BIF_ThemeColorShade(colorid, -50);
1288                 ui_default_menu_arrows(x1, y1, x2, y2);
1289                 break;
1290         }
1291         
1292         
1293 }
1294
1295
1296 /* fac is the slider handle position between x1 and x2 */
1297 static void ui_draw_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag)
1298 {
1299         float ymid, yc;
1300
1301         /* the slider background line */
1302         ymid= (y1+y2)/2.0;
1303         yc= 1.7*aspect; 
1304
1305         if(flag & UI_ACTIVE) 
1306                 BIF_ThemeColorShade(colorid, -50); 
1307         else 
1308                 BIF_ThemeColorShade(colorid, -40); 
1309
1310         /* left part */
1311         glRectf(x1, ymid-2.0*yc, x1+fac, ymid+2.0*yc);
1312         /* right part */
1313         glRectf(x1+fac, ymid-yc, x2, ymid+yc);
1314
1315         /* the movable slider */
1316         
1317         BIF_ThemeColorShade(colorid, +70); 
1318         glRectf(x1+fac-aspect, ymid-2.0*yc, x1+fac+aspect, ymid+2.0*yc);
1319
1320 }
1321
1322 /* ************** STANDARD MENU DRAWING FUNCTION ************* */
1323
1324
1325 static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha)
1326 {
1327         glEnable(GL_BLEND);
1328         glShadeModel(GL_SMOOTH);
1329         
1330         /* right quad */
1331         glBegin(GL_POLYGON);
1332         glColor4ub(0, 0, 0, alpha);
1333         glVertex2f(maxx, miny);
1334         glVertex2f(maxx, maxy-shadsize);
1335         glColor4ub(0, 0, 0, 0);
1336         glVertex2f(maxx+shadsize, maxy-shadsize-shadsize);
1337         glVertex2f(maxx+shadsize, miny);
1338         glEnd();
1339         
1340         /* corner shape */
1341         glBegin(GL_POLYGON);
1342         glColor4ub(0, 0, 0, alpha);
1343         glVertex2f(maxx, miny);
1344         glColor4ub(0, 0, 0, 0);
1345         glVertex2f(maxx+shadsize, miny);
1346         glVertex2f(maxx+0.7*shadsize, miny-0.7*shadsize);
1347         glVertex2f(maxx, miny-shadsize);
1348         glEnd();
1349         
1350         /* bottom quad */               
1351         glBegin(GL_POLYGON);
1352         glColor4ub(0, 0, 0, alpha);
1353         glVertex2f(minx+shadsize, miny);
1354         glVertex2f(maxx, miny);
1355         glColor4ub(0, 0, 0, 0);
1356         glVertex2f(maxx, miny-shadsize);
1357         glVertex2f(minx+shadsize+shadsize, miny-shadsize);
1358         glEnd();
1359         
1360         glDisable(GL_BLEND);
1361         glShadeModel(GL_FLAT);
1362 }
1363
1364 void uiDrawBoxShadow(unsigned char alpha, float minx, float miny, float maxx, float maxy)
1365 {
1366         /* accumulated outline boxes to make shade not linear, is more pleasant */
1367         ui_shadowbox(minx, miny, maxx, maxy, 6.0, (30*alpha)>>8);
1368         ui_shadowbox(minx, miny, maxx, maxy, 4.0, (70*alpha)>>8);
1369         ui_shadowbox(minx, miny, maxx, maxy, 2.0, (100*alpha)>>8);
1370         
1371 }
1372
1373 // background for pulldowns, pullups, and other drawing temporal menus....
1374 // has to be made themable still (now only color)
1375
1376 void uiDrawMenuBox(float minx, float miny, float maxx, float maxy, short flag)
1377 {
1378         char col[4];
1379         BIF_GetThemeColor4ubv(TH_MENU_BACK, col);
1380         
1381         if( (flag & UI_BLOCK_NOSHADOW)==0) {
1382                 /* accumulated outline boxes to make shade not linear, is more pleasant */
1383                 ui_shadowbox(minx, miny, maxx, maxy, 6.0, (30*col[3])>>8);
1384                 ui_shadowbox(minx, miny, maxx, maxy, 4.0, (70*col[3])>>8);
1385                 ui_shadowbox(minx, miny, maxx, maxy, 2.0, (100*col[3])>>8);
1386                 
1387                 glEnable(GL_BLEND);
1388                 glColor4ubv(col);
1389                 glRectf(minx-1, miny, minx, maxy);      // 1 pixel on left, to distinguish sublevel menus
1390         }
1391         glEnable(GL_BLEND);
1392         glColor4ubv(col);
1393         glRectf(minx, miny, maxx, maxy);
1394         glDisable(GL_BLEND);
1395 }
1396
1397
1398
1399 /* pulldown menu item */
1400 static void ui_draw_pulldown_item(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1401 {
1402         char col[4];
1403         
1404         BIF_GetThemeColor4ubv(TH_MENU_BACK, col);
1405         if(col[3]!=255) {
1406                 glEnable(GL_BLEND);
1407         }
1408         
1409         if((flag & UI_ACTIVE) && type!=LABEL) {
1410                 BIF_ThemeColor4(TH_MENU_HILITE);
1411                 glRectf(x1, y1, x2, y2);
1412         
1413
1414         } else {
1415                 BIF_ThemeColor4(colorid);       // is set at TH_MENU_ITEM when pulldown opened.
1416                 glRectf(x1, y1, x2, y2);
1417         }
1418
1419         glDisable(GL_BLEND);
1420 }
1421
1422 /* pulldown menu calling button */
1423 static void ui_draw_pulldown_round(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1424 {
1425         
1426         if(flag & UI_ACTIVE) {
1427                 BIF_ThemeColor(TH_MENU_HILITE);
1428
1429                 uiSetRoundBox(15);
1430                 gl_round_box(GL_POLYGON, x1, y1+3, x2, y2-3, 7.0);
1431
1432                 glEnable( GL_LINE_SMOOTH );
1433                 glEnable( GL_BLEND );
1434                 gl_round_box(GL_LINE_LOOP, x1, y1+3, x2, y2-3, 7.0);
1435                 glDisable( GL_LINE_SMOOTH );
1436                 glDisable( GL_BLEND );
1437                 
1438         } else {
1439                 BIF_ThemeColor(colorid);        // is set at TH_MENU_ITEM when pulldown opened.
1440                 glRectf(x1-1, y1+2, x2+1, y2-2);
1441         }
1442         
1443 }
1444
1445
1446 /* ************** TEXT AND ICON DRAWING FUNCTIONS ************* */
1447
1448
1449
1450 /* draws text and icons for buttons */
1451 static void ui_draw_text_icon(uiBut *but)
1452 {
1453         float x;
1454         int len;
1455         char *cpoin;
1456         short t, pos, ch;
1457         short selsta_tmp, selend_tmp, selsta_draw, selwidth_draw;
1458         
1459         /* check for button text label */
1460         if (but->type == ICONTEXTROW) {
1461                 ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
1462         }
1463         else {
1464
1465                 /* text button selection and cursor */
1466                 if(but->pos != -1) {
1467                 
1468                         if (SELWIDTH > 0) {
1469                                 /* text button selection */
1470                                 selsta_tmp = but->selsta + strlen(but->str);
1471                                 selend_tmp = but->selend + strlen(but->str);
1472                                 if (but->ofs >= strlen(but->str))
1473                                         selsta_tmp += (but->ofs - strlen(but->str));
1474                                         
1475                                 if(but->drawstr[0]!=0) {
1476                                         ch= but->drawstr[selsta_tmp];
1477                                         but->drawstr[selsta_tmp]= 0;
1478                                         
1479                                         selsta_draw = but->aspect*BIF_GetStringWidth(but->font, but->drawstr+but->ofs, (U.transopts & USER_TR_BUTTONS)) + 3;
1480                                         
1481                                         but->drawstr[selsta_tmp]= ch;
1482                                         
1483                                         
1484                                         ch= but->drawstr[selend_tmp];
1485                                         but->drawstr[selend_tmp]= 0;
1486                                         
1487                                         selwidth_draw = but->aspect*BIF_GetStringWidth(but->font, but->drawstr+but->ofs, (U.transopts & USER_TR_BUTTONS)) + 3;
1488                                         
1489                                         but->drawstr[selend_tmp]= ch;
1490                                         
1491                                         BIF_ThemeColor(TH_BUT_TEXTFIELD_HI);
1492                                         glRects(but->x1+selsta_draw+1, but->y1+2, but->x1+selwidth_draw+1, but->y2-2);
1493                                 }
1494                         } else {
1495                                 /* text cursor */
1496                                 pos= but->pos+strlen(but->str);
1497                                 if(pos >= but->ofs) {
1498                                         if(but->drawstr[0]!=0) {
1499                                                 ch= but->drawstr[pos];
1500                                                 but->drawstr[pos]= 0;
1501                         
1502                                                 t= but->aspect*BIF_GetStringWidth(but->font, but->drawstr+but->ofs, (U.transopts & USER_TR_BUTTONS)) + 3;
1503                                                 
1504                                                 but->drawstr[pos]= ch;
1505                                         }
1506                                         else t= 3;
1507                                         
1508                                         glColor3ub(255,0,0);
1509                                         glRects(but->x1+t, but->y1+2, but->x1+t+2, but->y2-2);
1510                                 }
1511                         }
1512                 }
1513                 if(but->drawstr[0]!=0) {
1514                         int transopts;
1515                         int tog3= 0;
1516                         
1517                         // cut string in 2 parts
1518                         cpoin= strchr(but->drawstr, '|');
1519                         if(cpoin) *cpoin= 0;
1520
1521                         /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
1522                         and offset the text label to accomodate it */
1523                         
1524                         if ( (but->flag & UI_HAS_ICON) && (but->flag & UI_ICON_LEFT) ) {
1525                                 ui_draw_icon(but, but->icon);
1526
1527                                 if(but->flag & UI_TEXT_LEFT) x= but->x1 + but->aspect*BIF_icon_get_width(but->icon)+5.0;
1528                                 else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1529                         }
1530                         else {
1531                                 if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
1532                                 else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1533                         }
1534                         
1535                         /* tog3 button exception; draws with glColor! */
1536                         if(but->type==TOG3 && (but->flag & UI_SELECT)) {
1537                                 
1538                                 if( but->pointype==CHA ) {
1539                                         if( BTST( *(but->poin+2), but->bitnr )) tog3= 1;
1540                                 }
1541                                 else if( but->pointype ==SHO ) {
1542                                         short *sp= (short *)but->poin;
1543                                         if( BTST( sp[1], but->bitnr )) tog3= 1;
1544                                 }
1545                                 
1546                                 ui_tog3_invert(but->x1,but->y1,but->x2,but->y2, tog3);
1547                                 if (tog3) glColor3ub(255, 255, 0);
1548                         }
1549                         
1550                         /* text color, with pulldown item exception */
1551                         if(tog3);       // color already set
1552                         else if(but->dt==UI_EMBOSSP) {
1553                                 if((but->flag & (UI_SELECT|UI_ACTIVE)) && but->type!=LABEL) {   // LABEL = title in pulldowns
1554                                         BIF_ThemeColor(TH_MENU_TEXT_HI);
1555                                 } else {
1556                                         BIF_ThemeColor(TH_MENU_TEXT);
1557                                 }
1558                         }
1559                         else {
1560                                 if(but->flag & UI_SELECT) {             
1561                                         BIF_ThemeColor(TH_BUT_TEXT_HI);
1562                                 } else {
1563                                         BIF_ThemeColor(TH_BUT_TEXT);
1564                                 }
1565                         }
1566
1567                         /* LABEL button exception */
1568                         if(but->type==LABEL && but->min!=0.0) BIF_ThemeColor(TH_BUT_TEXT_HI);
1569                 
1570                         ui_rasterpos_safe(x, (but->y1+but->y2- 9.0)/2.0, but->aspect);
1571                         if(but->type==TEX || but->type==IDPOIN) transopts= 0;   // no translation, of course!
1572                         else transopts= (U.transopts & USER_TR_BUTTONS);
1573                         BIF_DrawString(but->font, but->drawstr+but->ofs, transopts);
1574
1575                         /* part text right aligned */
1576                         if(cpoin) {
1577                                 len= BIF_GetStringWidth(but->font, cpoin+1, (U.transopts & USER_TR_BUTTONS));
1578                                 ui_rasterpos_safe( but->x2 - len*but->aspect-3, (but->y1+but->y2- 9.0)/2.0, but->aspect);
1579                                 BIF_DrawString(but->font, cpoin+1, (U.transopts & USER_TR_BUTTONS));
1580                                 *cpoin= '|';
1581                         }
1582                 }
1583                 /* if there's no text label, then check to see if there's an icon only and draw it */
1584                 else if( but->flag & UI_HAS_ICON ) {
1585                         ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
1586                 }
1587         }
1588 }
1589
1590 static void ui_draw_but_COL(uiBut *but)
1591 {
1592         float *fp;
1593         char colr, colg, colb;
1594         
1595         if( but->pointype==FLO ) {
1596                 fp= (float *)but->poin;
1597                 colr= floor(255.0*fp[0]+0.5);
1598                 colg= floor(255.0*fp[1]+0.5);
1599                 colb= floor(255.0*fp[2]+0.5);
1600         }
1601         else {
1602                 char *cp= (char *)but->poin;
1603                 colr= cp[0];
1604                 colg= cp[1];
1605                 colb= cp[2];
1606         }
1607         
1608         /* exception... hrms, but can't simply use the emboss callback for this now. */
1609         /* this button type needs review, and nice integration with rest of API here */
1610         if(but->embossfunc == ui_draw_round) {
1611                 char *cp= BIF_ThemeGetColorPtr(U.themes.first, 0, TH_CUSTOM);
1612                 cp[0]= colr; cp[1]= colg; cp[2]= colb;
1613                 but->flag &= ~UI_SELECT;
1614                 but->embossfunc(but->type, TH_CUSTOM, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
1615         }
1616         else {
1617                 
1618                 glColor3ub(colr,  colg,  colb);
1619                 glRectf((but->x1), (but->y1), (but->x2), (but->y2));
1620                 glColor3ub(0,  0,  0);
1621                 fdrawbox((but->x1), (but->y1), (but->x2), (but->y2));
1622         }
1623 }
1624
1625 /* draws in resolution of 20x4 colors */
1626 static void ui_draw_but_HSVCUBE(uiBut *but)
1627 {
1628         int a;
1629         float h,s,v;
1630         float dx, dy, sx1, sx2, sy, x, y;
1631         float col0[4][3];       // left half, rect bottom to top
1632         float col1[4][3];       // right half, rect bottom to top
1633         
1634         h= but->hsv[0];
1635         s= but->hsv[1];
1636         v= but->hsv[2];
1637         
1638         /* draw series of gouraud rects */
1639         glShadeModel(GL_SMOOTH);
1640         
1641         if(but->a1==0) {        // H and V vary
1642                 hsv_to_rgb(0.0, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1643                 hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
1644                 hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
1645                 hsv_to_rgb(0.0, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1646                 x= h; y= v;
1647         }
1648         else if(but->a1==1) {   // H and S vary
1649                 hsv_to_rgb(0.0, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
1650                 hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
1651                 hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
1652                 hsv_to_rgb(0.0, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
1653                 x= h; y= s;
1654         }
1655         else if(but->a1==2) {   // S and V vary
1656                 hsv_to_rgb(h, 0.0, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1657                 hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]);
1658                 hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
1659                 hsv_to_rgb(h, 1.0, 0.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1660                 x= v; y= s;
1661         }
1662         else {          // only hue slider
1663                 hsv_to_rgb(0.0, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1664                 VECCOPY(col1[1], col1[0]);
1665                 VECCOPY(col1[2], col1[0]);
1666                 VECCOPY(col1[3], col1[0]);
1667                 x= h; y= 0.5;
1668         }
1669         
1670         for(dx=0.0; dx<1.0; dx+= 0.05) {
1671                 // previous color
1672                 VECCOPY(col0[0], col1[0]);
1673                 VECCOPY(col0[1], col1[1]);
1674                 VECCOPY(col0[2], col1[2]);
1675                 VECCOPY(col0[3], col1[3]);
1676
1677                 // new color
1678                 if(but->a1==0) {        // H and V vary
1679                         hsv_to_rgb(dx, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1680                         hsv_to_rgb(dx, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
1681                         hsv_to_rgb(dx, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
1682                         hsv_to_rgb(dx, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1683                 }
1684                 else if(but->a1==1) {   // H and S vary
1685                         hsv_to_rgb(dx, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
1686                         hsv_to_rgb(dx, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
1687                         hsv_to_rgb(dx, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
1688                         hsv_to_rgb(dx, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
1689                 }
1690                 else if(but->a1==2) {   // S and V vary
1691                         hsv_to_rgb(h, 0.0, dx,   &col1[0][0], &col1[0][1], &col1[0][2]);
1692                         hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]);
1693                         hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
1694                         hsv_to_rgb(h, 1.0, dx,   &col1[3][0], &col1[3][1], &col1[3][2]);
1695                 }
1696                 else {  // only H
1697                         hsv_to_rgb(dx, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1698                         VECCOPY(col1[1], col1[0]);
1699                         VECCOPY(col1[2], col1[0]);
1700                         VECCOPY(col1[3], col1[0]);
1701                 }
1702                 
1703                 // rect
1704                 sx1= but->x1 + dx*(but->x2-but->x1);
1705                 sx2= but->x1 + (dx+0.05)*(but->x2-but->x1);
1706                 sy= but->y1;
1707                 dy= (but->y2-but->y1)/3.0;
1708                 
1709                 glBegin(GL_QUADS);
1710                 for(a=0; a<3; a++, sy+=dy) {
1711                         glColor3fv(col0[a]);
1712                         glVertex2f(sx1, sy);
1713
1714                         glColor3fv(col1[a]);
1715                         glVertex2f(sx2, sy);
1716                         
1717                         glColor3fv(col1[a+1]);
1718                         glVertex2f(sx2, sy+dy);
1719                         
1720                         glColor3fv(col0[a+1]);
1721                         glVertex2f(sx1, sy+dy);
1722                 }
1723                 glEnd();
1724         }
1725
1726         glShadeModel(GL_FLAT);
1727
1728         /* cursor */
1729         x= but->x1 + x*(but->x2-but->x1);
1730         y= but->y1 + y*(but->y2-but->y1);
1731         CLAMP(x, but->x1+3.0, but->x2-3.0);
1732         CLAMP(y, but->y1+3.0, but->y2-3.0);
1733         
1734         fdrawXORcirc(x, y, 3.1);
1735
1736         /* outline */
1737         glColor3ub(0,  0,  0);
1738         fdrawbox((but->x1), (but->y1), (but->x2), (but->y2));
1739 }
1740
1741 #ifdef INTERNATIONAL
1742 static void ui_draw_but_CHARTAB(uiBut *but)
1743 {
1744         /* Some local variables */
1745         float sx, sy, ex, ey;
1746         float width, height;
1747         float butw, buth;
1748         int x, y, cs;
1749         wchar_t wstr[2];
1750         unsigned char ustr[16];
1751         PackedFile *pf;
1752         int result = 0;
1753         int charmax = G.charmax;
1754
1755         /* <builtin> font in use. There are TTF <builtin> and non-TTF <builtin> fonts */
1756         if(!strcmp(G.selfont->name, "<builtin>"))
1757         {
1758                 if(G.ui_international == TRUE)
1759                 {
1760                         charmax = 0xff;
1761                 }
1762                 else
1763                 {
1764                         charmax = 0xff;
1765                 }
1766         }
1767
1768         /* Category list exited without selecting the area */
1769         if(G.charmax == 0)
1770                 charmax = G.charmax = 0xffff;
1771
1772         /* Calculate the size of the button */
1773         width = abs(but->x2 - but->x1);
1774         height = abs(but->y2 - but->y1);
1775         
1776         butw = floor(width / 12);
1777         buth = floor(height / 6);
1778         
1779         /* Initialize variables */
1780         sx = but->x1;
1781         ex = but->x1 + butw;
1782         sy = but->y1 + height - buth;
1783         ey = but->y1 + height;
1784
1785         cs = G.charstart;
1786
1787         /* Set the font, in case it is not <builtin> font */
1788         if(G.selfont && strcmp(G.selfont->name, "<builtin>"))
1789         {
1790                 char tmpStr[256];
1791
1792                 // Is the font file packed, if so then use the packed file
1793                 if(G.selfont->packedfile)
1794                 {
1795                         pf = G.selfont->packedfile;             
1796                         FTF_SetFont(pf->data, pf->size, 14.0);
1797                 }
1798                 else
1799                 {
1800                         int err;
1801
1802                         strcpy(tmpStr, G.selfont->name);
1803                         BLI_convertstringcode(tmpStr, G.sce, 0);
1804                         err = FTF_SetFont((unsigned char *)tmpStr, 0, 14.0);
1805                 }
1806         }
1807         else
1808         {
1809                 if(G.ui_international == TRUE)
1810                 {
1811                         FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, 14.0);
1812                 }
1813         }
1814
1815         /* Start drawing the button itself */
1816         glShadeModel(GL_SMOOTH);
1817
1818         glColor3ub(200,  200,  200);
1819         glRectf((but->x1), (but->y1), (but->x2), (but->y2));
1820
1821         glColor3ub(0,  0,  0);
1822         for(y = 0; y < 6; y++)
1823         {
1824                 // Do not draw more than the category allows
1825                 if(cs > charmax) break;
1826
1827                 for(x = 0; x < 12; x++)
1828                 {
1829                         // Do not draw more than the category allows
1830                         if(cs > charmax) break;
1831
1832                         // Draw one grid cell
1833                         glBegin(GL_LINE_LOOP);
1834                                 glVertex2f(sx, sy);
1835                                 glVertex2f(ex, sy);
1836                                 glVertex2f(ex, ey);
1837                                 glVertex2f(sx, ey);                             
1838                         glEnd();        
1839
1840                         // Draw character inside the cell
1841                         memset(wstr, 0, sizeof(wchar_t)*2);
1842                         memset(ustr, 0, 16);
1843
1844                         // Set the font to be either unicode or <builtin>                               
1845                         wstr[0] = cs;
1846                         if(strcmp(G.selfont->name, "<builtin>"))
1847                         {
1848                                 wcs2utf8s((char *)ustr, (wchar_t *)wstr);
1849                         }
1850                         else
1851                         {
1852                                 if(G.ui_international == TRUE)
1853                                 {
1854                                         wcs2utf8s((char *)ustr, (wchar_t *)wstr);
1855                                 }
1856                                 else
1857                                 {
1858                                         ustr[0] = cs;
1859                                         ustr[1] = 0;
1860                                 }
1861                         }
1862
1863                         if((G.selfont && strcmp(G.selfont->name, "<builtin>")) || (G.selfont && !strcmp(G.selfont->name, "<builtin>") && G.ui_international == TRUE))
1864                         {
1865                                 float wid;
1866                                 float llx, lly, llz, urx, ury, urz;
1867                                 float dx, dy;
1868                                 float px, py;
1869         
1870                                 // Calculate the position
1871                                 wid = FTF_GetStringWidth((char *) ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
1872                                 FTF_GetBoundingBox((char *) ustr, &llx,&lly,&llz,&urx,&ury,&urz, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
1873                                 dx = urx-llx;
1874                                 dy = ury-lly;
1875
1876                                 // This isn't fully functional since the but->aspect isn't working like I suspected
1877                                 px = sx + ((butw/but->aspect)-dx)/2;
1878                                 py = sy + ((buth/but->aspect)-dy)/2;
1879
1880                                 // Set the position and draw the character
1881                                 ui_rasterpos_safe(px, py, but->aspect);
1882                                 FTF_DrawString((char *) ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
1883                         }
1884                         else
1885                         {
1886                                 ui_rasterpos_safe(sx + butw/2, sy + buth/2, but->aspect);
1887                                 BIF_DrawString(but->font, (char *) ustr, 0);
1888                         }
1889         
1890                         // Calculate the next position and character
1891                         sx += butw; ex +=butw;
1892                         cs++;
1893                 }
1894                 /* Add the y position and reset x position */
1895                 sy -= buth; 
1896                 ey -= buth;
1897                 sx = but->x1;
1898                 ex = but->x1 + butw;
1899         }       
1900         glShadeModel(GL_FLAT);
1901
1902         /* Return Font Settings to original */
1903         if(U.fontsize && U.fontname[0])
1904         {
1905                 result = FTF_SetFont((unsigned char *)U.fontname, 0, U.fontsize);
1906         }
1907         else if (U.fontsize)
1908         {
1909                 result = FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, U.fontsize);
1910         }
1911
1912         if (result == 0)
1913         {
1914                 result = FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, 11);
1915         }
1916 }
1917
1918 #endif // INTERNATIONAL
1919
1920 static void ui_draw_but_COLORBAND(uiBut *but)
1921 {
1922         ColorBand *coba= (ColorBand *)but->poin;
1923         CBData *cbd;
1924         float x1, y1, sizex, sizey;
1925         float dx, v3[2], v1[2], v2[2];
1926         int a;
1927                 
1928         if(coba==NULL) return;
1929         
1930         x1= but->x1;
1931         y1= but->y1;
1932         sizex= but->x2-x1;
1933         sizey= but->y2-y1;
1934         
1935         /* first background, to show tranparency */
1936         dx= sizex/12.0;
1937         v1[0]= x1;
1938         for(a=0; a<12; a++) {
1939                 if(a & 1) glColor3f(0.3, 0.3, 0.3); else glColor3f(0.8, 0.8, 0.8);
1940                 glRectf(v1[0], y1, v1[0]+dx, y1+0.5*sizey);
1941                 if(a & 1) glColor3f(0.8, 0.8, 0.8); else glColor3f(0.3, 0.3, 0.3);
1942                 glRectf(v1[0], y1+0.5*sizey, v1[0]+dx, y1+sizey);
1943                 v1[0]+= dx;
1944         }
1945         
1946         glShadeModel(GL_SMOOTH);
1947         glEnable(GL_BLEND);
1948         
1949         cbd= coba->data;
1950         
1951         v1[0]= v2[0]= x1;
1952         v1[1]= y1;
1953         v2[1]= y1+sizey;
1954         
1955         glBegin(GL_QUAD_STRIP);
1956         
1957         glColor4fv( &cbd->r );
1958         glVertex2fv(v1); glVertex2fv(v2);
1959         
1960         for(a=0; a<coba->tot; a++, cbd++) {
1961                 
1962                 v1[0]=v2[0]= x1+ cbd->pos*sizex;
1963                 
1964                 glColor4fv( &cbd->r );
1965                 glVertex2fv(v1); glVertex2fv(v2);
1966         }
1967         
1968         v1[0]=v2[0]= x1+ sizex;
1969         glVertex2fv(v1); glVertex2fv(v2);
1970         
1971         glEnd();
1972         glShadeModel(GL_FLAT);
1973         glDisable(GL_BLEND);
1974         
1975         /* outline */
1976         v1[0]= x1; v1[1]= y1;
1977         
1978         cpack(0x0);
1979         glBegin(GL_LINE_LOOP);
1980         glVertex2fv(v1);
1981         v1[0]+= sizex;
1982         glVertex2fv(v1);
1983         v1[1]+= sizey;
1984         glVertex2fv(v1);
1985         v1[0]-= sizex;
1986         glVertex2fv(v1);
1987         glEnd();
1988         
1989         
1990         /* help lines */
1991         v1[0]= v2[0]=v3[0]= x1;
1992         v1[1]= y1;
1993         v2[1]= y1+0.5*sizey;
1994         v3[1]= y1+sizey;
1995         
1996         cbd= coba->data;
1997         glBegin(GL_LINES);
1998         for(a=0; a<coba->tot; a++, cbd++) {
1999                 v1[0]=v2[0]=v3[0]= x1+ cbd->pos*sizex;
2000                 
2001                 glColor3ub(0, 0, 0);
2002                 glVertex2fv(v1);
2003                 glVertex2fv(v2);
2004                 
2005                 if(a==coba->cur) {
2006                         glVertex2f(v1[0]-1, v1[1]);
2007                         glVertex2f(v2[0]-1, v2[1]);
2008                         glVertex2f(v1[0]+1, v1[1]);
2009                         glVertex2f(v2[0]+1, v2[1]);
2010                 }
2011                 
2012                 glColor3ub(255, 255, 255);
2013                 glVertex2fv(v2);
2014                 glVertex2fv(v3);
2015                 
2016                 if(a==coba->cur) {
2017                         if(cbd->pos>0.01) {
2018                                 glVertex2f(v2[0]-1, v2[1]);
2019                                 glVertex2f(v3[0]-1, v3[1]);
2020                         }
2021                         if(cbd->pos<0.99) {
2022                                 glVertex2f(v2[0]+1, v2[1]);
2023                                 glVertex2f(v3[0]+1, v3[1]);
2024                         }
2025                 }
2026         }
2027         glEnd();
2028 }
2029
2030 static void ui_draw_but_NORMAL(uiBut *but)
2031 {
2032         static GLuint displist=0;
2033         int a, old[8];
2034         GLfloat diff[4], diffn[4]={1.0f, 1.0f, 1.0f, 1.0f};
2035         float vec0[4]={0.0f, 0.0f, 0.0f, 0.0f};
2036         float dir[4], size;
2037         
2038         /* store stuff */
2039         glGetMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
2040                 
2041         /* backdrop */
2042         BIF_ThemeColor(TH_BUT_NEUTRAL);
2043         uiSetRoundBox(15);
2044         gl_round_box(GL_POLYGON, but->x1, but->y1, but->x2, but->y2, 5.0f);
2045         
2046         /* sphere color */
2047         glMaterialfv(GL_FRONT, GL_DIFFUSE, diffn);
2048         glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
2049         
2050         /* disable blender light */
2051         for(a=0; a<8; a++) {
2052                 old[a]= glIsEnabled(GL_LIGHT0+a);
2053                 glDisable(GL_LIGHT0+a);
2054         }
2055         
2056         /* own light */
2057         glEnable(GL_LIGHT7);
2058         glEnable(GL_LIGHTING);
2059         
2060         VECCOPY(dir, (float *)but->poin);
2061         dir[3]= 0.0f;   /* glLight needs 4 args, 0.0 is sun */
2062         glLightfv(GL_LIGHT7, GL_POSITION, dir); 
2063         glLightfv(GL_LIGHT7, GL_DIFFUSE, diffn); 
2064         glLightfv(GL_LIGHT7, GL_SPECULAR, vec0); 
2065         glLightf(GL_LIGHT7, GL_CONSTANT_ATTENUATION, 1.0f);
2066         glLightf(GL_LIGHT7, GL_LINEAR_ATTENUATION, 0.0f);
2067         
2068         /* transform to button */
2069         glPushMatrix();
2070         glTranslatef(but->x1 + 0.5f*(but->x2-but->x1), but->y1+ 0.5f*(but->y2-but->y1), 0.0f);
2071         size= (but->x2-but->x1)/200.f;
2072         glScalef(size, size, size);
2073                          
2074         if(displist==0) {
2075                 GLUquadricObj   *qobj;
2076                 
2077                 displist= glGenLists(1);
2078                 glNewList(displist, GL_COMPILE_AND_EXECUTE);
2079                 
2080                 qobj= gluNewQuadric();
2081                 gluQuadricDrawStyle(qobj, GLU_FILL); 
2082                 glShadeModel(GL_SMOOTH);
2083                 gluSphere( qobj, 100.0, 32, 24);
2084                 glShadeModel(GL_FLAT);
2085                 gluDeleteQuadric(qobj);  
2086                 
2087                 glEndList();
2088         }
2089         else glCallList(displist);
2090         
2091         /* restore */
2092         glPopMatrix();
2093         glDisable(GL_LIGHTING);
2094         glDisable(GL_CULL_FACE);
2095         glMaterialfv(GL_FRONT, GL_DIFFUSE, diff); 
2096         
2097         glDisable(GL_LIGHT7);
2098         
2099         /* enable blender light */
2100         for(a=0; a<8; a++) {
2101                 if(old[a])
2102                         glEnable(GL_LIGHT0+a);
2103         }
2104 }
2105
2106 static void ui_draw_but_curve_grid(uiBut *but, float zoomx, float zoomy, float offsx, float offsy, float step)
2107 {
2108         float dx, dy, fx, fy;
2109         
2110         glBegin(GL_LINES);
2111         dx= step*zoomx;
2112         fx= but->x1 + zoomx*(-offsx);
2113         if(fx > but->x1) fx -= dx*( floor(fx-but->x1));
2114         while(fx < but->x2) {
2115                 glVertex2f(fx, but->y1); 
2116                 glVertex2f(fx, but->y2);
2117                 fx+= dx;
2118         }
2119         
2120         dy= step*zoomy;
2121         fy= but->y1 + zoomy*(-offsy);
2122         if(fy > but->y1) fy -= dy*( floor(fy-but->y1));
2123         while(fy < but->y2) {
2124                 glVertex2f(but->x1, fy); 
2125                 glVertex2f(but->x2, fy);
2126                 fy+= dy;
2127         }
2128         glEnd();
2129         
2130 }
2131
2132 static void ui_draw_but_CURVE(uiBut *but)
2133 {
2134         CurveMapping *cumap= (CurveMapping *)but->poin;
2135         CurveMap *cuma= cumap->cm+cumap->cur;
2136         CurveMapPoint *cmp;
2137         float fx, fy, dx, dy, fac[2], zoomx, zoomy, offsx, offsy;
2138         GLint scissor[4];
2139         int a;
2140         
2141         /* need scissor test, curve can draw outside of boundary */
2142         glGetIntegerv(GL_VIEWPORT, scissor);
2143         fx= but->x1; fy= but->y1;
2144         ui_graphics_to_window(but->win, &fx, &fy);
2145         dx= but->x2; dy= but->y2;
2146         ui_graphics_to_window(but->win, &dx, &dy);
2147         glScissor((int)floor(fx), (int)floor(fy), (int)ceil(dx-fx), (int)ceil(dy-fy));
2148         
2149         /* calculate offset and zoom */
2150         zoomx= (but->x2-but->x1-2.0*but->aspect)/(cumap->curr.xmax - cumap->curr.xmin);
2151         zoomy= (but->y2-but->y1-2.0*but->aspect)/(cumap->curr.ymax - cumap->curr.ymin);
2152         offsx= cumap->curr.xmin-but->aspect/zoomx;
2153         offsy= cumap->curr.ymin-but->aspect/zoomy;
2154         
2155         /* backdrop */
2156         if(cumap->flag & CUMA_DO_CLIP) {
2157                 BIF_ThemeColorShade(TH_BUT_NEUTRAL, -20);
2158                 glRectf(but->x1, but->y1, but->x2, but->y2);
2159                 BIF_ThemeColor(TH_BUT_NEUTRAL);
2160                 glRectf(but->x1 + zoomx*(cumap->clipr.xmin-offsx),
2161                                 but->y1 + zoomy*(cumap->clipr.ymin-offsy),
2162                                 but->x1 + zoomx*(cumap->clipr.xmax-offsx),
2163                                 but->y1 + zoomy*(cumap->clipr.ymax-offsy));
2164         }
2165         else {
2166                 BIF_ThemeColor(TH_BUT_NEUTRAL);
2167                 glRectf(but->x1, but->y1, but->x2, but->y2);
2168         }
2169         
2170         /* grid, every .25 step */
2171         BIF_ThemeColorBlend(TH_BUT_NEUTRAL, TH_BUT_OUTLINE, 0.06f);
2172         ui_draw_but_curve_grid(but, zoomx, zoomy, offsx, offsy, 0.25f);
2173         /* grid, every 1.0 step */
2174         BIF_ThemeColorBlend(TH_BUT_NEUTRAL, TH_BUT_OUTLINE, 0.12f);
2175         ui_draw_but_curve_grid(but, zoomx, zoomy, offsx, offsy, 1.0f);
2176         /* axes */
2177         BIF_ThemeColorBlend(TH_BUT_NEUTRAL, TH_BUT_OUTLINE, 0.25f);
2178         glBegin(GL_LINES);
2179         glVertex2f(but->x1, but->y1 + zoomy*(-offsy));
2180         glVertex2f(but->x2, but->y1 + zoomy*(-offsy));
2181         glVertex2f(but->x1 + zoomx*(-offsx), but->y1);
2182         glVertex2f(but->x1 + zoomx*(-offsx), but->y2);
2183         glEnd();
2184         
2185         /* the curve */
2186         BIF_ThemeColor(TH_TEXT);
2187         glBegin(GL_LINE_STRIP);
2188         
2189         if(cuma->table==NULL)
2190                 curvemapping_changed(cumap, 0); /* 0 = no remove doubles */
2191         cmp= cuma->table;
2192         
2193         glVertex2f(but->x1, but->y1 + zoomy*(cmp[0].y-offsy));  /* first point */
2194         for(a=0; a<=CM_TABLE; a++) {
2195                 fx= but->x1 + zoomx*(cmp[a].x-offsx);
2196                 fy= but->y1 + zoomy*(cmp[a].y-offsy);
2197                 glVertex2f(fx, fy);
2198         }
2199         glVertex2f(but->x2, but->y1 + zoomy*(cmp[a-1].y-offsy));        /* last point */
2200         glEnd();
2201
2202         /* the points, use aspect to make them visible on edges */
2203         cmp= cuma->curve;
2204         glPointSize(3.0f);
2205         bglBegin(GL_POINTS);
2206         for(a=0; a<cuma->totpoint; a++) {
2207                 if(cmp[a].flag & SELECT)
2208                         BIF_ThemeColor(TH_TEXT_HI);
2209                 else
2210                         BIF_ThemeColor(TH_TEXT);
2211                 fac[0]= but->x1 + zoomx*(cmp[a].x-offsx);
2212                 fac[1]= but->y1 + zoomy*(cmp[a].y-offsy);
2213                 bglVertex2fv(fac);
2214         }
2215         bglEnd();
2216         glPointSize(1.0f);
2217         
2218         /* restore scissortest */
2219         glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
2220
2221         /* outline */
2222         BIF_ThemeColor(TH_BUT_OUTLINE);
2223         fdrawbox(but->x1, but->y1, but->x2, but->y2);
2224
2225 }
2226
2227 static void ui_draw_roundbox(uiBut *but)
2228 {
2229         glEnable(GL_BLEND);
2230         
2231         BIF_ThemeColorShadeAlpha(TH_PANEL, but->a2, but->a2);
2232
2233         uiSetRoundBox(but->a1);
2234         gl_round_box(GL_POLYGON, but->x1, but->y1, but->x2, but->y2, but->min);
2235
2236         glDisable(GL_BLEND);
2237 }
2238
2239
2240 /* nothing! */
2241 static void ui_draw_nothing(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
2242 {
2243 }
2244
2245
2246 /* ************** EXTERN, called from interface.c ************* */
2247 /* ************** MAIN CALLBACK FUNCTION          ************* */
2248
2249 void ui_set_embossfunc(uiBut *but, int drawtype)
2250 {
2251         // this aded for evaluating textcolor for example
2252         but->dt= drawtype;
2253         
2254         // not really part of standard minimal themes, just make sure it is set
2255         but->sliderfunc= ui_draw_slider;
2256
2257         // standard builtin first:
2258         if(but->type==LABEL || but->type==ROUNDBOX) but->embossfunc= ui_draw_nothing;
2259         else if(but->type==PULLDOWN) but->embossfunc= ui_draw_pulldown_round;
2260         else if(drawtype==UI_EMBOSSM) but->embossfunc= ui_draw_minimal;
2261         else if(drawtype==UI_EMBOSSN) but->embossfunc= ui_draw_nothing;
2262         else if(drawtype==UI_EMBOSSP) but->embossfunc= ui_draw_pulldown_item;
2263         else if(drawtype==UI_EMBOSSR) but->embossfunc= ui_draw_round;
2264         else {
2265                 int theme= BIF_GetThemeValue(TH_BUT_DRAWTYPE);
2266                 
2267                 // and the themes
2268                 if(theme==1) {
2269                         but->embossfunc= ui_draw_default;
2270                         but->sliderfunc= ui_default_slider;
2271                 }
2272                 else if(theme==2) {
2273                         but->embossfunc= ui_draw_round;
2274                 }
2275                 else if(theme==3) {
2276                         but->embossfunc= ui_draw_oldskool;
2277                 }
2278                 else {
2279                         but->embossfunc= ui_draw_minimal;
2280                 }
2281         }
2282         
2283         // note: if you want aligning, adapt the call uiBlockEndAlign in interface.c 
2284 }
2285
2286 void ui_draw_but(uiBut *but)
2287 {
2288         double value;
2289         float x1, x2, y1, y2, fac;
2290         
2291         if(but==NULL) return;
2292
2293         /* signal for frontbuf flush buttons and menus, not when normal drawing */
2294         if(but->block->in_use) ui_block_set_flush(but->block, but);
2295                 
2296         switch (but->type) {
2297
2298         case NUMSLI:
2299         case HSVSLI:
2300         
2301                 but->embossfunc(but->type, but->themecol, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
2302                 ui_draw_text_icon(but);
2303
2304                 x1= (but->x1+but->x2)/2;
2305                 x2= but->x2 - 5.0*but->aspect;
2306                 y1= but->y1 + 2.0*but->aspect;
2307                 y2= but->y2 - 2.0*but->aspect;
2308                 
2309                 value= ui_get_but_val(but);
2310                 fac= (value-but->min)*(x2-x1)/(but->max - but->min);
2311                 
2312                 but->sliderfunc(but->themecol, fac, but->aspect, x1, y1, x2, y2, but->flag);
2313                 break;
2314                 
2315         case SEPR:
2316                 //  only background
2317                 break;
2318                 
2319         case COL:
2320                 ui_draw_but_COL(but);  // black box with color
2321                 break;
2322
2323         case HSVCUBE:
2324                 ui_draw_but_HSVCUBE(but);  // box for colorpicker, three types
2325                 break;
2326
2327 #ifdef INTERNATIONAL
2328         case CHARTAB:
2329                 value= ui_get_but_val(but);
2330                 ui_draw_but_CHARTAB(but);
2331                 break;
2332 #endif
2333
2334         case LINK:
2335         case INLINK:
2336                 ui_draw_icon(but, but->icon);
2337                 break;
2338                 
2339         case ROUNDBOX:
2340                 ui_draw_roundbox(but);
2341                 break;
2342                 
2343         case BUT_COLORBAND:
2344                 ui_draw_but_COLORBAND(but);
2345                 break;
2346         case BUT_NORMAL:
2347                 ui_draw_but_NORMAL(but);
2348                 break;
2349         case BUT_CURVE:
2350                 ui_draw_but_CURVE(but);
2351                 break;
2352                 
2353         default:
2354                 but->embossfunc(but->type, but->themecol, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
2355                 ui_draw_text_icon(but);
2356         
2357         }
2358 }
2359