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