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