To end the issues with AA (International) Fonts; the .bfont.tff now is
[blender.git] / source / blender / src / interface_draw.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 /* 
34      a full doc with API notes can be found in bf-blender/blender/doc/interface_API.txt
35
36  */
37  
38
39 #include <math.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <ctype.h>
43
44 #ifdef HAVE_CONFIG_H
45 #include <config.h>
46 #endif
47
48 #ifndef WIN32
49 #include <unistd.h>
50 #else
51 #include <io.h>
52 #include "BLI_winstuff.h"
53 #endif   
54
55 #include "MEM_guardedalloc.h"
56
57 #include "PIL_time.h"
58
59 #include "BLI_blenlib.h"
60 #include "BLI_arithb.h"
61
62 #include "DNA_screen_types.h"
63 #include "DNA_space_types.h"
64 #include "DNA_userdef_types.h"
65 #include "DNA_vec_types.h"
66
67 #include "BKE_blender.h"
68 #include "BKE_utildefines.h"
69 #include "BKE_global.h"
70
71 #include "BIF_gl.h"
72 #include "BIF_graphics.h"
73 #include "BIF_keyval.h"
74 #include "BIF_mainqueue.h"
75
76 #include "BIF_screen.h"
77 #include "BIF_toolbox.h"
78 #include "BIF_mywindow.h"
79 #include "BIF_space.h"
80 #include "BIF_glutil.h"
81 #include "BIF_interface.h"
82 #include "BIF_butspace.h"
83 #include "BIF_language.h"
84
85 #include "BSE_view.h"
86
87 #include "mydevice.h"
88 #include "interface.h"
89 #include "blendef.h"
90
91 // globals
92 extern float UIwinmat[4][4];
93
94 /* ************** safe rasterpos for pixmap alignment with pixels ************* */
95
96 void ui_rasterpos_safe(float x, float y, float aspect)
97 {
98         float vals[4], remainder;
99         int doit=0;
100         
101         glRasterPos2f(x, y);
102         glGetFloatv(GL_CURRENT_RASTER_POSITION, vals);
103
104         remainder= vals[0] - floor(vals[0]);
105         if(remainder > 0.4 && remainder < 0.6) {
106                 if(remainder < 0.5) x -= 0.1*aspect;
107                 else x += 0.1*aspect;
108                 doit= 1;
109         }
110         remainder= vals[1] - floor(vals[1]);
111         if(remainder > 0.4 && remainder < 0.6) {
112                 if(remainder < 0.5) y -= 0.1*aspect;
113                 else y += 0.1*aspect;
114                 doit= 1;
115         }
116         
117         if(doit) glRasterPos2f(x, y);
118 }
119
120 /* ************** generic embossed rect, for window sliders etc ************* */
121
122 void uiEmboss(float x1, float y1, float x2, float y2, int sel)
123 {
124         
125         /* below */
126         if(sel) glColor3ub(200,200,200);
127         else glColor3ub(50,50,50);
128         fdrawline(x1, y1, x2, y1);
129
130         /* right */
131         fdrawline(x2, y1, x2, y2);
132         
133         /* top */
134         if(sel) glColor3ub(50,50,50);
135         else glColor3ub(200,200,200);
136         fdrawline(x1, y2, x2, y2);
137
138         /* left */
139         fdrawline(x1, y1, x1, y2);
140         
141 }
142
143 /* ************** GENERIC ICON DRAW, NO THEME HERE ************* */
144
145 static void ui_draw_icon(uiBut *but, BIFIconID icon)
146 {
147         void BIF_icon_pos(float xs, float ys);
148         int blend= 0;
149         float xs=0, ys=0;
150
151         // this icon doesn't need draw...
152         if(icon==ICON_BLANK1) return;
153
154         if(but->flag & UI_ICON_LEFT) {
155                 if (but->type==BUTM) {
156                         xs= but->x1+1.0;
157                 }
158                 else if ((but->type==ICONROW) || (but->type==ICONTEXTROW)) {
159                         xs= but->x1+4.0;
160                 }
161                 else {
162                         xs= but->x1+6.0;
163                 }
164                 ys= (but->y1+but->y2- BIF_get_icon_height(icon))/2.0;
165         }
166         if(but->flag & UI_ICON_RIGHT) {
167                 xs= but->x2-17.0;
168                 ys= (but->y1+but->y2- BIF_get_icon_height(icon))/2.0;
169         }
170         if (!((but->flag & UI_ICON_RIGHT) || (but->flag & UI_ICON_LEFT))) {
171                 xs= (but->x1+but->x2- BIF_get_icon_width(icon))/2.0;
172                 ys= (but->y1+but->y2- BIF_get_icon_height(icon))/2.0;
173         }
174
175         glRasterPos2f(xs, ys);
176         // BIF_icon_pos(xs, ys);
177
178         if(but->aspect>1.1) glPixelZoom(1.0/but->aspect, 1.0/but->aspect);
179         else if(but->aspect<0.9) glPixelZoom(1.0/but->aspect, 1.0/but->aspect);
180
181         glEnable(GL_BLEND);
182         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
183
184         /* calculate blend color */
185         if ELEM4(but->type, ICONTOG, TOG, ROW, TOGN) {
186                 if(but->flag & UI_SELECT);
187                 else if(but->flag & UI_ACTIVE);
188                 else blend= -60;
189         }
190         BIF_draw_icon_blended(icon, but->themecol, blend);
191         
192         glBlendFunc(GL_ONE, GL_ZERO);
193         glDisable(GL_BLEND);
194
195         glPixelZoom(1.0, 1.0);
196 }
197
198
199 /* ************** DEFAULT THEME, SHADED BUTTONS ************* */
200
201
202 #define M_WHITE         BIF_ThemeColorShade(colorid, 80)
203
204 #define M_ACT_LIGHT     BIF_ThemeColorShade(colorid, 55)
205 #define M_LIGHT         BIF_ThemeColorShade(colorid, 45)
206 #define M_HILITE        BIF_ThemeColorShade(colorid, 25)
207 #define M_LMEDIUM       BIF_ThemeColorShade(colorid, 10)
208 #define M_MEDIUM        BIF_ThemeColor(colorid)
209 #define M_LGREY         BIF_ThemeColorShade(colorid, -20)
210 #define M_GREY          BIF_ThemeColorShade(colorid, -45)
211 #define M_DARK          BIF_ThemeColorShade(colorid, -80)
212
213 #define M_NUMTEXT                               BIF_ThemeColorShade(colorid, 25)
214 #define M_NUMTEXT_ACT_LIGHT             BIF_ThemeColorShade(colorid, 35)
215
216 #define MM_WHITE        BIF_ThemeColorShade(TH_BUT_NEUTRAL, 120)
217
218 /* Used for the subtle sunken effect around buttons.
219  * One option is to hardcode to white, with alpha, however it causes a 
220  * weird 'building up' efect, so it's commented out for now.
221  */
222  
223 /*
224 #define MM_WHITE_OP     glColor4ub(255, 255, 255, 60)
225 #define MM_WHITE_TR     glColor4ub(255, 255, 255, 0)
226  */
227
228 #define MM_WHITE_OP     BIF_ThemeColorShadeAlpha(TH_BACK, 55, -100)
229 #define MM_WHITE_TR     BIF_ThemeColorShadeAlpha(TH_BACK, 55, -255)
230
231 #define MM_LIGHT        BIF_ThemeColorShade(TH_BUT_OUTLINE, 45)
232 #define MM_MEDIUM       BIF_ThemeColor(TH_BUT_OUTLINE)
233 #define MM_GREY         BIF_ThemeColorShade(TH_BUT_OUTLINE, -45)
234 #define MM_DARK         BIF_ThemeColorShade(TH_BUT_OUTLINE, -80)
235
236 /* base shaded button */
237 static void shaded_button(float x1, float y1, float x2, float y2, float asp, int colorid, int flag, int mid)
238 {
239         /* 'mid' arg determines whether the button is in the middle of
240          * an alignment group or not. 0 = not middle, 1 = is in the middle.
241          * Done to allow cleaner drawing
242          */
243          
244         /* *** SHADED BUTTON BASE *** */
245         glShadeModel(GL_SMOOTH);
246         glBegin(GL_QUADS);
247         
248         if(flag & UI_SELECT) {
249                 if(flag & UI_ACTIVE) M_MEDIUM;
250                 else M_LGREY;
251         } else {
252                 if(flag & UI_ACTIVE) M_LIGHT;
253                 else M_HILITE;
254         }
255
256         glVertex2f(x1,y1);
257         glVertex2f(x2,y1);
258
259         if(flag & UI_SELECT) {
260                 if(flag & UI_ACTIVE) M_LGREY;
261                 else M_GREY;
262         } else {
263                 if(flag & UI_ACTIVE) M_ACT_LIGHT;
264                 else M_LIGHT;
265         }
266
267         glVertex2f(x2,(y2-(y2-y1)/3));
268         glVertex2f(x1,(y2-(y2-y1)/3));
269         glEnd();
270         
271
272         glShadeModel(GL_FLAT);
273         glBegin(GL_QUADS);
274         
275         if(flag & UI_SELECT) {
276                 if(flag & UI_ACTIVE) M_LGREY;
277                 else M_GREY;
278         } else {
279                 if(flag & UI_ACTIVE) M_ACT_LIGHT;
280                 else M_LIGHT;
281         }
282         
283         glVertex2f(x1,(y2-(y2-y1)/3));
284         glVertex2f(x2,(y2-(y2-y1)/3));
285         glVertex2f(x2,y2);
286         glVertex2f(x1,y2);
287
288         glEnd();
289         /* *** END SHADED BUTTON BASE *** */
290         
291         /* *** INNER OUTLINE *** */
292         /* left */
293         if(!(flag & UI_SELECT)) {
294                 glShadeModel(GL_SMOOTH);
295                 glBegin(GL_LINES);
296                 M_MEDIUM;
297                 glVertex2f(x1+1,y1+2);
298                 M_WHITE;
299                 glVertex2f(x1+1,y2);
300                 glEnd();
301         }
302         
303         /* right */
304                 if(!(flag & UI_SELECT)) {
305                 glShadeModel(GL_SMOOTH);
306                 glBegin(GL_LINES);
307                 M_MEDIUM;
308                 glVertex2f(x2-1,y1+2);
309                 M_WHITE;
310                 glVertex2f(x2-1,y2);
311                 glEnd();
312         }
313         
314         glShadeModel(GL_FLAT);
315         
316         /* top */
317         if(flag & UI_SELECT) {
318                 if(flag & UI_ACTIVE) M_LGREY;
319                 else M_GREY;
320         } else {
321                 if(flag & UI_ACTIVE) M_WHITE;
322                 else M_WHITE;
323         }
324
325         fdrawline(x1, (y2-1), x2, (y2-1));
326         
327         /* bottom */
328         if(flag & UI_SELECT) {
329                 if(flag & UI_ACTIVE) M_MEDIUM;
330                 else M_LGREY;
331         } else {
332                 if(flag & UI_ACTIVE) M_LMEDIUM;
333                 else M_MEDIUM;
334         }
335         fdrawline(x1, (y1+1), x2, (y1+1));
336         /* *** END INNER OUTLINE *** */
337         
338         /* *** OUTER OUTLINE *** */
339         if (mid) {
340                 // we draw full outline, its not AA, and it works better button mouse-over hilite
341                 MM_DARK;
342                 
343                 // left right
344                 fdrawline(x1, y1, x1, y2);
345                 fdrawline(x2, y1, x2, y2);
346         
347                 // top down
348                 fdrawline(x1, y2, x2, y2);
349                 fdrawline(x1, y1, x2, y1); 
350         } else {
351                 MM_DARK;
352                 gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 1.5);
353         }
354         /* END OUTER OUTLINE */
355 }
356
357 /* base flat button */
358 static void flat_button(float x1, float y1, float x2, float y2, float asp, int colorid, int flag, int mid)
359 {
360         /* 'mid' arg determines whether the button is in the middle of
361          * an alignment group or not. 0 = not middle, 1 = is in the middle.
362          * Done to allow cleaner drawing
363          */
364          
365         /* *** FLAT TEXT/NUM FIELD *** */
366         glShadeModel(GL_FLAT);
367         if(flag & UI_SELECT) {
368                 if(flag & UI_ACTIVE) M_LGREY;
369                 else M_GREY;
370         }
371         else {
372                 if(flag & UI_ACTIVE) M_NUMTEXT_ACT_LIGHT;
373                 else M_NUMTEXT;
374         }
375
376         glRectf(x1, y1, x2, y2);
377         /* *** END FLAT TEXT/NUM FIELD *** */
378         
379         /* *** OUTER OUTLINE *** */
380         if (mid) {
381                 // we draw full outline, its not AA, and it works better button mouse-over hilite
382                 MM_DARK;
383                 
384                 // left right
385                 fdrawline(x1, y1, x1, y2);
386                 fdrawline(x2, y1, x2, y2);
387         
388                 // top down
389                 fdrawline(x1, y2, x2, y2);
390                 fdrawline(x1, y1, x2, y1); 
391         } else {
392                 MM_DARK;
393                 gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 1.5);
394         }
395         /* END OUTER OUTLINE */
396 }
397
398 /* small side double arrow for iconrow */
399 static void ui_default_iconrow_arrows(float x1, float y1, float x2, float y2)
400 {
401         glEnable( GL_POLYGON_SMOOTH );
402         glEnable( GL_BLEND );
403         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
404         
405         glShadeModel(GL_FLAT);
406         glBegin(GL_TRIANGLES);
407         glVertex2f((short)x2-2,(short)(y2-(y2-y1)/2)+1);
408         glVertex2f((short)x2-6,(short)(y2-(y2-y1)/2)+1);
409         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2)+4);
410         glEnd();
411                 
412         glBegin(GL_TRIANGLES);
413         glVertex2f((short)x2-2,(short)(y2-(y2-y1)/2) -1);
414         glVertex2f((short)x2-6,(short)(y2-(y2-y1)/2) -1);
415         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2) -4);
416         glEnd();
417         
418         glDisable( GL_BLEND );
419         glDisable( GL_POLYGON_SMOOTH );
420 }
421
422 /* side double arrow for menu */
423 static void ui_default_menu_arrows(float x1, float y1, float x2, float y2)
424 {
425         glEnable( GL_POLYGON_SMOOTH );
426         glEnable( GL_BLEND );
427         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
428         
429         glShadeModel(GL_FLAT);
430         glBegin(GL_TRIANGLES);
431         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2)+1);
432         glVertex2f((short)x2-12,(short)(y2-(y2-y1)/2)+1);
433         glVertex2f((short)x2-8,(short)(y2-(y2-y1)/2)+4);
434         glEnd();
435                 
436         glBegin(GL_TRIANGLES);
437         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2) -1);
438         glVertex2f((short)x2-12,(short)(y2-(y2-y1)/2) -1);
439         glVertex2f((short)x2-8,(short)(y2-(y2-y1)/2) -4);
440         glEnd();
441         
442         glDisable( GL_BLEND );
443         glDisable( GL_POLYGON_SMOOTH );
444 }
445
446 /* left/right arrows for number fields */
447 static void ui_default_num_arrows(float x1, float y1, float x2, float y2)
448 {
449         if( x2-x1 > 25) {       // 25 is a bit arbitrary, but small buttons cant have arrows
450
451                 glEnable( GL_POLYGON_SMOOTH );
452                 glEnable( GL_BLEND );
453                 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
454                 
455                 glShadeModel(GL_FLAT);
456                 glBegin(GL_TRIANGLES);
457                 
458                 glVertex2f((short)x1+5,(short)(y2-(y2-y1)/2));
459                 glVertex2f((short)x1+10,(short)(y2-(y2-y1)/2)+4);
460                 glVertex2f((short)x1+10,(short)(y2-(y2-y1)/2)-4);
461                 glEnd();
462
463                 /* right */
464                 glShadeModel(GL_FLAT);
465                 glBegin(GL_TRIANGLES);
466
467                 glVertex2f((short)x2-5,(short)(y2-(y2-y1)/2));
468                 glVertex2f((short)x2-10,(short)(y2-(y2-y1)/2)-4);
469                 glVertex2f((short)x2-10,(short)(y2-(y2-y1)/2)+4);
470                 glEnd();
471                 
472                 glDisable( GL_BLEND );
473                 glDisable( GL_POLYGON_SMOOTH );
474         }
475 }
476
477 /* changing black/white for TOG3 buts */
478 static void ui_tog3_invert(float x1, float y1, float x2, float y2, int seltype)
479 {
480         short alpha = 30;
481         
482         if (seltype == 0) {
483                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
484                 glEnable(GL_BLEND);
485                 
486                 glColor4ub(0, 0, 0, alpha);
487                 glRectf(x2-6, y1, x2, (y1+(y2-y1)/2));
488                 
489                 glColor4ub(255, 255, 255, alpha);
490                 glRectf(x2-6, (y1+(y2-y1)/2), x2, y2);
491                 
492                 glDisable(GL_BLEND);
493         } else {
494                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
495                 glEnable(GL_BLEND);
496                 
497                 glColor4ub(255, 255, 255, alpha);
498                 glRectf(x2-6, y1, x2, (y1+(y2-y1)/2));
499                 
500                 glColor4ub(0, 0, 0, alpha);
501                 glRectf(x2-6, (y1+(y2-y1)/2), x2, y2);
502                 
503                 glDisable(GL_BLEND);
504         }
505 }
506
507 /* button/popup menu/iconrow drawing code */
508 static void ui_default_button(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
509 {
510         int align= (flag & UI_BUT_ALIGN);
511
512         if(align) {
513         
514                 /* *** BOTTOM OUTER SUNKEN EFFECT *** */
515                 if (!((align == UI_BUT_ALIGN_DOWN) ||
516                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT)) ||
517                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT)))) {
518                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
519                         glEnable(GL_BLEND);
520                         MM_WHITE_OP;
521                         fdrawline(x1, y1-1, x2, y1-1);  
522                         glDisable(GL_BLEND);
523                 }
524                 /* *** END BOTTOM OUTER SUNKEN EFFECT *** */
525                 
526                 switch(align) {
527                 case UI_BUT_ALIGN_TOP:
528                         uiSetRoundBox(12);
529                         
530                         /* last arg in shaded_button() determines whether the button is in the middle of
531                          * an alignment group or not. 0 = not middle, 1 = is in the middle.
532                          * Done to allow cleaner drawing
533                          */
534                          
535                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
536                         break;
537                 case UI_BUT_ALIGN_DOWN:
538                         uiSetRoundBox(3);
539                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
540                         break;
541                 case UI_BUT_ALIGN_LEFT:
542                         
543                         /* RIGHT OUTER SUNKEN EFFECT */
544                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
545                         glEnable(GL_BLEND);
546                         glShadeModel(GL_SMOOTH);
547                         glBegin(GL_LINES);
548                         MM_WHITE_OP;
549                         glVertex2f(x2+1,y1);
550                         MM_WHITE_TR;
551                         glVertex2f(x2+1,y2);
552                         glEnd();
553                         glDisable(GL_BLEND);
554                         
555                         uiSetRoundBox(6);
556                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
557                         break;
558                 case UI_BUT_ALIGN_RIGHT:
559                 
560                         /* LEFT OUTER SUNKEN EFFECT */
561                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
562                         glEnable(GL_BLEND);
563                         glShadeModel(GL_SMOOTH);
564                         glBegin(GL_LINES);
565                         MM_WHITE_OP;
566                         glVertex2f(x1-1,y1);
567                         MM_WHITE_TR;
568                         glVertex2f(x1-1,y2);
569                         glEnd();
570                         glDisable(GL_BLEND);
571                 
572                         uiSetRoundBox(9);
573                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
574                         break;
575                         
576                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
577                         uiSetRoundBox(1);
578                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
579                         break;
580                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
581                         uiSetRoundBox(2);
582                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
583                         break;
584                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
585                 
586                         /* LEFT OUTER SUNKEN EFFECT */
587                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
588                         glEnable(GL_BLEND);
589                         glShadeModel(GL_SMOOTH);
590                         glBegin(GL_LINES);
591                         MM_WHITE_OP;
592                         glVertex2f(x1-1,y1);
593                         MM_WHITE_TR;
594                         glVertex2f(x1-1,y2);
595                         glEnd();
596                         glDisable(GL_BLEND);
597                 
598                         uiSetRoundBox(8);
599                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
600                         break;
601                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
602                 
603                         /* RIGHT OUTER SUNKEN EFFECT */
604                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
605                         glEnable(GL_BLEND);
606                         glShadeModel(GL_SMOOTH);
607                         glBegin(GL_LINES);
608                         MM_WHITE_OP;
609                         glVertex2f(x2+1,y1);
610                         MM_WHITE_TR;
611                         glVertex2f(x2+1,y2);
612                         glEnd();
613                         glDisable(GL_BLEND);
614                         
615                         uiSetRoundBox(4);
616                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
617                         break;
618                         
619                 default:
620                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 1);
621                         break;
622                 }
623         } 
624         else {  
625                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
626                 glEnable(GL_BLEND);
627                 glShadeModel(GL_SMOOTH);
628                 
629                 /* BOTTOM OUTER SUNKEN EFFECT */
630                 MM_WHITE_OP;
631                 fdrawline(x1, y1-1, x2, y1-1);  
632                 
633                 /* LEFT OUTER SUNKEN EFFECT */
634                 glBegin(GL_LINES);
635                 MM_WHITE_OP;
636                 glVertex2f(x1-1,y1);
637                 MM_WHITE_TR;
638                 glVertex2f(x1-1,y2);
639                 glEnd();
640                 
641                 /* RIGHT OUTER SUNKEN EFFECT */
642                 glBegin(GL_LINES);
643                 MM_WHITE_OP;
644                 glVertex2f(x2+1,y1);
645                 MM_WHITE_TR;
646                 glVertex2f(x2+1,y2);
647                 glEnd();
648                 
649                 glDisable(GL_BLEND);
650         
651                 uiSetRoundBox(15);
652                 shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
653         }
654         
655         /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */
656         switch(type) {
657         case ICONROW:
658         case ICONTEXTROW:
659                 /* DARKENED AREA */
660                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
661                 glEnable(GL_BLEND);
662                 
663                 glColor4ub(0, 0, 0, 30);
664                 glRectf(x2-9, y1, x2, y2);
665         
666                 glDisable(GL_BLEND);
667                 /* END DARKENED AREA */
668         
669                 /* ICONROW DOUBLE-ARROW  */
670                 M_DARK;
671                 ui_default_iconrow_arrows(x1, y1, x2, y2);
672                 /* END ICONROW DOUBLE-ARROW */
673                 break;
674         case MENU:
675                 /* DARKENED AREA */
676                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
677                 glEnable(GL_BLEND);
678                 
679                 glColor4ub(0, 0, 0, 30);
680                 glRectf(x2-18, y1, x2, y2);
681         
682                 glDisable(GL_BLEND);
683                 /* END DARKENED AREA */
684         
685                 /* MENU DOUBLE-ARROW  */
686                 M_DARK;
687                 ui_default_menu_arrows(x1, y1, x2, y2);
688                 /* MENU DOUBLE-ARROW */
689                 break;
690         }       
691 }
692
693
694 /* number/text field drawing code */
695 static void ui_default_flat(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
696 {
697         int align= (flag & UI_BUT_ALIGN);
698
699         if(align) {
700         
701                 /* *** BOTTOM OUTER SUNKEN EFFECT *** */
702                 if (!((align == UI_BUT_ALIGN_DOWN) ||
703                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT)) ||
704                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT)))) {
705                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
706                         glEnable(GL_BLEND);
707                         MM_WHITE_OP;
708                         fdrawline(x1, y1-1, x2, y1-1);  
709                         glDisable(GL_BLEND);
710                 }
711                 /* *** END BOTTOM OUTER SUNKEN EFFECT *** */
712                 
713                 switch(align) {
714                 case UI_BUT_ALIGN_TOP:
715                         uiSetRoundBox(12);
716                         
717                         /* last arg in shaded_button() determines whether the button is in the middle of
718                          * an alignment group or not. 0 = not middle, 1 = is in the middle.
719                          * Done to allow cleaner drawing
720                          */
721                          
722                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
723                         break;
724                 case UI_BUT_ALIGN_DOWN:
725                         uiSetRoundBox(3);
726                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
727                         break;
728                 case UI_BUT_ALIGN_LEFT:
729                         
730                         /* RIGHT OUTER SUNKEN EFFECT */
731                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
732                         glEnable(GL_BLEND);
733                         glShadeModel(GL_SMOOTH);
734                         glBegin(GL_LINES);
735                         MM_WHITE_OP;
736                         glVertex2f(x2+1,y1);
737                         MM_WHITE_TR;
738                         glVertex2f(x2+1,y2);
739                         glEnd();
740                         glDisable(GL_BLEND);
741                         
742                         uiSetRoundBox(6);
743                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
744                         break;
745                 case UI_BUT_ALIGN_RIGHT:
746                 
747                         /* LEFT OUTER SUNKEN EFFECT */
748                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
749                         glEnable(GL_BLEND);
750                         glShadeModel(GL_SMOOTH);
751                         glBegin(GL_LINES);
752                         MM_WHITE_OP;
753                         glVertex2f(x1-1,y1);
754                         MM_WHITE_TR;
755                         glVertex2f(x1-1,y2);
756                         glEnd();
757                         glDisable(GL_BLEND);
758                 
759                         uiSetRoundBox(9);
760                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
761                         break;
762                         
763                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
764                         uiSetRoundBox(1);
765                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
766                         break;
767                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
768                         uiSetRoundBox(2);
769                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
770                         break;
771                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
772                 
773                         /* LEFT OUTER SUNKEN EFFECT */
774                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
775                         glEnable(GL_BLEND);
776                         glShadeModel(GL_SMOOTH);
777                         glBegin(GL_LINES);
778                         MM_WHITE_OP;
779                         glVertex2f(x1-1,y1);
780                         MM_WHITE_TR;
781                         glVertex2f(x1-1,y2);
782                         glEnd();
783                         glDisable(GL_BLEND);
784                 
785                         uiSetRoundBox(8);
786                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
787                         break;
788                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
789                 
790                         /* RIGHT OUTER SUNKEN EFFECT */
791                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
792                         glEnable(GL_BLEND);
793                         glShadeModel(GL_SMOOTH);
794                         glBegin(GL_LINES);
795                         MM_WHITE_OP;
796                         glVertex2f(x2+1,y1);
797                         MM_WHITE_TR;
798                         glVertex2f(x2+1,y2);
799                         glEnd();
800                         glDisable(GL_BLEND);
801                         
802                         uiSetRoundBox(4);
803                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
804                         break;
805                         
806                 default:
807                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 1);
808                         break;
809                 }
810         } 
811         else {
812         
813                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
814                 glEnable(GL_BLEND);
815                 glShadeModel(GL_SMOOTH);
816                 
817                 /* BOTTOM OUTER SUNKEN EFFECT */
818                 MM_WHITE_OP;
819                 fdrawline(x1, y1-1, x2, y1-1);  
820                 
821                 /* LEFT OUTER SUNKEN EFFECT */
822                 glBegin(GL_LINES);
823                 MM_WHITE_OP;
824                 glVertex2f(x1-1,y1);
825                 MM_WHITE_TR;
826                 glVertex2f(x1-1,y2);
827                 glEnd();
828                 
829                 /* RIGHT OUTER SUNKEN EFFECT */
830                 glBegin(GL_LINES);
831                 MM_WHITE_OP;
832                 glVertex2f(x2+1,y1);
833                 MM_WHITE_TR;
834                 glVertex2f(x2+1,y2);
835                 glEnd();
836                 
837                 glDisable(GL_BLEND);
838
839                 uiSetRoundBox(15);
840                 flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
841         }
842         
843         /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */
844         switch(type) {
845         case NUM:
846                 /* SIDE ARROWS */
847                 /* left */
848                 if(flag & UI_SELECT) {
849                         if(flag & UI_ACTIVE) M_DARK;
850                         else M_DARK;
851                 } else {
852                         if(flag & UI_ACTIVE) M_GREY;
853                         else M_LGREY;
854                 }
855                 
856                 ui_default_num_arrows(x1, y1, x2, y2);
857                 /* END SIDE ARROWS */
858         }
859 }
860
861 static void ui_default_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag)
862 {
863         float ymid, yc;
864
865         /* the slider background line */
866         ymid= (y1+y2)/2.0;
867         //yc= 2.5*aspect;       // height of center line
868         yc = 2.3; // height of center line
869         
870         if(flag & UI_SELECT) 
871                         BIF_ThemeColorShade(TH_BUT_NUM, -5);
872         else
873                 if(flag & UI_ACTIVE) 
874                         BIF_ThemeColorShade(TH_BUT_NUM, +35); 
875                 else
876                         BIF_ThemeColorShade(TH_BUT_NUM, +25); 
877
878         glRectf(x1, ymid-yc, x2, ymid+yc);
879         
880         /* top inner bevel */
881         if(flag & UI_SELECT) BIF_ThemeColorShade(TH_BUT_NUM, -40); 
882         else BIF_ThemeColorShade(TH_BUT_NUM, -5); 
883         fdrawline(x1+1, ymid+yc, x2, ymid+yc);
884         
885         /* bottom inner bevel */
886         if(flag & UI_SELECT) BIF_ThemeColorShade(TH_BUT_NUM, +15); 
887         else BIF_ThemeColorShade(TH_BUT_NUM, +45); 
888         fdrawline(x1+1, ymid-yc, x2, ymid-yc);
889         
890         
891         /* the movable slider */
892         if(flag & UI_SELECT) BIF_ThemeColorShade(TH_BUT_NUM, +80); 
893         else BIF_ThemeColorShade(TH_BUT_NUM, -45); 
894
895         glShadeModel(GL_SMOOTH);
896         glBegin(GL_QUADS);
897
898         BIF_ThemeColorShade(TH_BUT_NUM, -45); 
899
900         glVertex2f(x1,     y1+2.5);
901         glVertex2f(x1+fac, y1+2.5);
902
903         BIF_ThemeColor(TH_BUT_NUM); 
904
905         glVertex2f(x1+fac, y2-2.5);
906         glVertex2f(x1,     y2-2.5);
907
908         glEnd();
909         
910
911         /* slider handle center */
912         glShadeModel(GL_SMOOTH);
913         glBegin(GL_QUADS);
914
915         BIF_ThemeColor(TH_BUT_NUM); 
916         glVertex2f(x1+fac-3, y1+2);
917         glVertex2f(x1+fac, y1+4);
918         BIF_ThemeColorShade(TH_BUT_NUM, +80); 
919         glVertex2f(x1+fac, y2-2);
920         glVertex2f(x1+fac-3, y2-2);
921
922         glEnd();
923         
924         /* slider handle left bevel */
925         BIF_ThemeColorShade(TH_BUT_NUM, +70); 
926         fdrawline(x1+fac-3, y2-2, x1+fac-3, y1+2);
927         
928         /* slider handle right bevel */
929         BIF_ThemeColorShade(TH_BUT_NUM, -35); 
930         fdrawline(x1+fac, y2-2, x1+fac, y1+2);
931
932         glShadeModel(GL_FLAT);
933 }
934
935 /* default theme callback */
936 static void ui_draw_default(int type, int colorid, float aspect, float x1, float y1, float x2, float y2, int flag)
937 {
938
939         switch(type) {
940         case TEX:
941         case IDPOIN:
942         case NUM:
943                 ui_default_flat(type, colorid, aspect, x1, y1, x2, y2, flag);
944                 break;
945         case ICONROW: 
946         case ICONTEXTROW: 
947         case MENU: 
948         default: 
949                 ui_default_button(type, colorid, aspect, x1, y1, x2, y2, flag);
950         }
951
952 }
953
954
955 /* *************** OLDSKOOL THEME ***************** */
956
957 static void ui_draw_outlineX(float x1, float y1, float x2, float y2, float asp1)
958 {
959         float vec[2];
960         
961         glBegin(GL_LINE_LOOP);
962         vec[0]= x1+asp1; vec[1]= y1-asp1;
963         glVertex2fv(vec);
964         vec[0]= x2-asp1; 
965         glVertex2fv(vec);
966         vec[0]= x2+asp1; vec[1]= y1+asp1;
967         glVertex2fv(vec);
968         vec[1]= y2-asp1;
969         glVertex2fv(vec);
970         vec[0]= x2-asp1; vec[1]= y2+asp1;
971         glVertex2fv(vec);
972         vec[0]= x1+asp1;
973         glVertex2fv(vec);
974         vec[0]= x1-asp1; vec[1]= y2-asp1;
975         glVertex2fv(vec);
976         vec[1]= y1+asp1;
977         glVertex2fv(vec);
978         glEnd();                
979         
980 }
981
982
983 static void ui_draw_oldskool(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
984 {
985         /* paper */
986         if(flag & UI_SELECT) {
987                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, -40);
988                 else BIF_ThemeColorShade(colorid, -30);
989         }
990         else {
991                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, +30);
992                 else BIF_ThemeColorShade(colorid, +20);
993         }
994         
995         glRectf(x1+1, y1+1, x2-1, y2-1);
996
997         x1+= asp;
998         x2-= asp;
999         y1+= asp;
1000         y2-= asp;
1001
1002         /* below */
1003         if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, 0);
1004         else BIF_ThemeColorShade(colorid, -30);
1005         fdrawline(x1, y1, x2, y1);
1006
1007         /* right */
1008         fdrawline(x2, y1, x2, y2);
1009         
1010         /* top */
1011         if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -30);
1012         else BIF_ThemeColorShade(colorid, 0);
1013         fdrawline(x1, y2, x2, y2);
1014
1015         /* left */
1016         fdrawline(x1, y1, x1, y2);
1017         
1018         /* outline */
1019         glColor3ub(0,0,0);
1020         ui_draw_outlineX(x1, y1, x2, y2, asp);
1021         
1022         
1023         /* special type decorations */
1024         switch(type) {
1025         case NUM:
1026                 if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -60);
1027                 else BIF_ThemeColorShade(colorid, -30);
1028                 ui_default_num_arrows(x1, y1, x2, y2);
1029                 break;
1030
1031         case ICONROW: 
1032         case ICONTEXTROW: 
1033                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1034                 else BIF_ThemeColorShade(colorid, -10);
1035                 glRectf(x2-9, y1+asp, x2-asp, y2-asp);
1036
1037                 BIF_ThemeColorShade(colorid, -50);
1038                 ui_default_iconrow_arrows(x1, y1, x2, y2);
1039                 break;
1040                 
1041         case MENU: 
1042                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1043                 else BIF_ThemeColorShade(colorid, -10);
1044                 glRectf(x2-17, y1+asp, x2-asp, y2-asp);
1045
1046                 BIF_ThemeColorShade(colorid, -50);
1047                 ui_default_menu_arrows(x1, y1, x2, y2);
1048                 break;
1049         }
1050         
1051 }
1052
1053 /* *************** BASIC ROUNDED THEME ***************** */
1054
1055 static void round_button(float x1, float y1, float x2, float y2, float asp, 
1056                                                  int colorid, int round, int menudeco, int curshade)
1057 {
1058         float rad;
1059         char col[4];
1060         
1061         rad= (y2-y1)/2.0;
1062         if(rad>7.0) rad= 7.0;
1063         
1064         uiSetRoundBox(round);
1065         gl_round_box(GL_POLYGON, x1, y1, x2, y2, rad);
1066
1067         if(menudeco) {
1068                 uiSetRoundBox(round & ~9);
1069                 BIF_ThemeColorShade(colorid, curshade-20);
1070                 gl_round_box(GL_POLYGON, x2-menudeco, y1, x2, y2, rad);
1071         }
1072         
1073         /* fake AA */
1074         uiSetRoundBox(round);
1075         glEnable( GL_BLEND );
1076         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1077
1078         BIF_GetThemeColor3ubv(colorid, col);
1079                 
1080         if(col[0]<100) col[0]= 0; else col[0]-= 100;
1081         if(col[1]<100) col[1]= 0; else col[1]-= 100;
1082         if(col[2]<100) col[2]= 0; else col[2]-= 100;
1083         col[3]= 80;
1084         glColor4ubv(col);
1085         gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, rad - asp);
1086         gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, rad + asp);
1087         col[3]= 180;
1088         glColor4ubv(col);
1089         gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, rad);
1090
1091         glDisable( GL_BLEND );
1092 }
1093
1094 /* button in midst of alignment row */
1095 static void round_button_mid(float x1, float y1, float x2, float y2, float asp, 
1096                                                          int colorid, int align, int menudeco, int curshade)
1097 {
1098         glRectf(x1, y1, x2, y2);
1099         
1100         if(menudeco) {
1101                 BIF_ThemeColorShade(colorid, curshade-20);
1102                 glRectf(x2-menudeco, y1, x2, y2);
1103         }
1104         
1105         BIF_ThemeColorBlendShade(colorid, TH_BACK, 0.5, -70);
1106         // we draw full outline, its not AA, and it works better button mouse-over hilite
1107         
1108         // left right
1109         fdrawline(x1, y1, x1, y2);
1110         fdrawline(x2, y1, x2, y2);
1111
1112         // top down
1113         fdrawline(x1, y2, x2, y2);
1114         fdrawline(x1, y1, x2, y1);   
1115 }
1116
1117 static void ui_draw_round(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1118 {
1119         int align= (flag & UI_BUT_ALIGN);
1120         int curshade= 0, menudeco= 0;
1121         
1122         if(type==ICONROW || type==ICONTEXTROW) menudeco= 9;
1123         else if((type==MENU || type==BLOCK) && x2-x1>24) menudeco= 16;
1124         
1125         /* paper */
1126         if(flag & UI_SELECT) {
1127                 if(flag & UI_ACTIVE) curshade= -40;
1128                 else curshade= -30;
1129         }
1130         else {
1131                 if(flag & UI_ACTIVE) curshade= 30;
1132                 else curshade= +20;
1133         }
1134         
1135         BIF_ThemeColorShade(colorid, curshade);
1136
1137         if(align) {
1138                 switch(align) {
1139                 case UI_BUT_ALIGN_TOP:
1140                         round_button(x1, y1, x2, y2, asp, colorid, 12, menudeco, curshade);
1141                         break;
1142                 case UI_BUT_ALIGN_DOWN:
1143                         round_button(x1, y1, x2, y2, asp, colorid, 3, menudeco, curshade);
1144                         break;
1145                 case UI_BUT_ALIGN_LEFT:
1146                         round_button(x1, y1, x2, y2, asp, colorid, 6, menudeco, curshade);
1147                         break;
1148                 case UI_BUT_ALIGN_RIGHT:
1149                         round_button(x1, y1, x2, y2, asp, colorid, 9, menudeco, curshade);
1150                         break;
1151                         
1152                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
1153                         round_button(x1, y1, x2, y2, asp, colorid, 1, menudeco, curshade);
1154                         break;
1155                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
1156                         round_button(x1, y1, x2, y2, asp, colorid, 2, menudeco, curshade);
1157                         break;
1158                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
1159                         round_button(x1, y1, x2, y2, asp, colorid, 8, menudeco, curshade);
1160                         break;
1161                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
1162                         round_button(x1, y1, x2, y2, asp, colorid, 4, menudeco, curshade);
1163                         break;
1164                         
1165                 default:
1166                         round_button_mid(x1, y1, x2, y2, asp, colorid, align, menudeco, curshade);
1167                         break;
1168                 }
1169         } 
1170         else {
1171                 round_button(x1, y1, x2, y2, asp, colorid, 15, menudeco, curshade);
1172         }
1173
1174         /* special type decorations */
1175         switch(type) {
1176         case NUM:
1177                 BIF_ThemeColorShade(colorid, curshade-60);
1178                 ui_default_num_arrows(x1, y1, x2, y2);
1179                 break;
1180
1181         case ICONROW: 
1182         case ICONTEXTROW: 
1183                 BIF_ThemeColorShade(colorid, curshade-60);
1184                 ui_default_iconrow_arrows(x1, y1, x2, y2);
1185                 break;
1186                 
1187         case MENU: 
1188         case BLOCK: 
1189                 BIF_ThemeColorShade(colorid, curshade-60);
1190                 ui_default_menu_arrows(x1, y1, x2, y2);
1191                 break;
1192         }
1193 }
1194
1195 /* *************** MINIMAL THEME ***************** */
1196
1197 // theme can define an embosfunc and sliderfunc, text+icon drawing is standard, no theme.
1198
1199
1200
1201 /* super minimal button as used in logic menu */
1202 static void ui_draw_minimal(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1203 {
1204         
1205         x1+= asp;
1206         x2-= asp;
1207         y1+= asp;
1208         y2-= asp;
1209
1210         /* paper */
1211         if(flag & UI_SELECT) {
1212                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, -40);
1213                 else BIF_ThemeColorShade(colorid, -30);
1214         }
1215         else {
1216                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, +20);
1217                 else BIF_ThemeColorShade(colorid, +10);
1218         }
1219         
1220         glRectf(x1, y1, x2, y2);
1221
1222         if(flag & UI_SELECT) {
1223                 BIF_ThemeColorShade(colorid, -60);
1224
1225                 /* top */
1226                 fdrawline(x1, y2, x2, y2);
1227                 /* left */
1228                 fdrawline(x1, y1, x1, y2);
1229                 BIF_ThemeColorShade(colorid, +40);
1230
1231                 /* below */
1232                 fdrawline(x1, y1, x2, y1);
1233                 /* right */
1234                 fdrawline(x2, y1, x2, y2);
1235         }
1236         else {
1237                 BIF_ThemeColorShade(colorid, +40);
1238
1239                 /* top */
1240                 fdrawline(x1, y2, x2, y2);
1241                 /* left */
1242                 fdrawline(x1, y1, x1, y2);
1243                 
1244                 BIF_ThemeColorShade(colorid, -60);
1245                 /* below */
1246                 fdrawline(x1, y1, x2, y1);
1247                 /* right */
1248                 fdrawline(x2, y1, x2, y2);
1249         }
1250         
1251         /* special type decorations */
1252         switch(type) {
1253         case NUM:
1254                 if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -60);
1255                 else BIF_ThemeColorShade(colorid, -30);
1256                 ui_default_num_arrows(x1, y1, x2, y2);
1257                 break;
1258
1259         case ICONROW: 
1260         case ICONTEXTROW: 
1261                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1262                 else BIF_ThemeColorShade(colorid, -10);
1263                 glRectf(x2-9, y1+asp, x2-asp, y2-asp);
1264
1265                 BIF_ThemeColorShade(colorid, -50);
1266                 ui_default_iconrow_arrows(x1, y1, x2, y2);
1267                 break;
1268                 
1269         case MENU: 
1270         case BLOCK: 
1271                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1272                 else BIF_ThemeColorShade(colorid, -10);
1273                 glRectf(x2-17, y1+asp, x2-asp, y2-asp);
1274
1275                 BIF_ThemeColorShade(colorid, -50);
1276                 ui_default_menu_arrows(x1, y1, x2, y2);
1277                 break;
1278         }
1279         
1280         
1281 }
1282
1283
1284 /* fac is the slider handle position between x1 and x2 */
1285 static void ui_draw_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag)
1286 {
1287         float ymid, yc;
1288
1289         /* the slider background line */
1290         ymid= (y1+y2)/2.0;
1291         yc= 1.7*aspect; 
1292
1293         if(flag & UI_ACTIVE) 
1294                 BIF_ThemeColorShade(colorid, -50); 
1295         else 
1296                 BIF_ThemeColorShade(colorid, -40); 
1297
1298         /* left part */
1299         glRectf(x1, ymid-2.0*yc, x1+fac, ymid+2.0*yc);
1300         /* right part */
1301         glRectf(x1+fac, ymid-yc, x2, ymid+yc);
1302
1303         /* the movable slider */
1304         
1305         BIF_ThemeColorShade(colorid, +70); 
1306         glRectf(x1+fac-aspect, ymid-2.0*yc, x1+fac+aspect, ymid+2.0*yc);
1307
1308 }
1309
1310 /* ************** STANDARD MENU DRAWING FUNCTION ************* */
1311
1312
1313 static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha)
1314 {
1315         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1316         glEnable(GL_BLEND);
1317         glShadeModel(GL_SMOOTH);
1318         
1319         /* right quad */
1320         glBegin(GL_POLYGON);
1321         glColor4ub(0, 0, 0, alpha);
1322         glVertex2f(maxx, miny);
1323         glVertex2f(maxx, maxy-shadsize);
1324         glColor4ub(0, 0, 0, 0);
1325         glVertex2f(maxx+shadsize, maxy-shadsize-shadsize);
1326         glVertex2f(maxx+shadsize, miny);
1327         glEnd();
1328         
1329         /* corner shape */
1330         glBegin(GL_POLYGON);
1331         glColor4ub(0, 0, 0, alpha);
1332         glVertex2f(maxx, miny);
1333         glColor4ub(0, 0, 0, 0);
1334         glVertex2f(maxx+shadsize, miny);
1335         glVertex2f(maxx+0.7*shadsize, miny-0.7*shadsize);
1336         glVertex2f(maxx, miny-shadsize);
1337         glEnd();
1338         
1339         /* bottom quad */               
1340         glBegin(GL_POLYGON);
1341         glColor4ub(0, 0, 0, alpha);
1342         glVertex2f(minx+shadsize, miny);
1343         glVertex2f(maxx, miny);
1344         glColor4ub(0, 0, 0, 0);
1345         glVertex2f(maxx, miny-shadsize);
1346         glVertex2f(minx+shadsize+shadsize, miny-shadsize);
1347         glEnd();
1348         
1349         glDisable(GL_BLEND);
1350         glShadeModel(GL_FLAT);
1351 }
1352
1353 // background for pulldowns, pullups, and other drawing temporal menus....
1354 // has to be made themable still (now only color)
1355
1356 void uiDrawMenuBox(float minx, float miny, float maxx, float maxy, short flag)
1357 {
1358         char col[4];
1359         BIF_GetThemeColor4ubv(TH_MENU_BACK, col);
1360         
1361         if( (flag & UI_BLOCK_NOSHADOW)==0) {
1362                 /* accumulated outline boxes to make shade not linear, is more pleasant */
1363                 ui_shadowbox(minx, miny, maxx, maxy, 6.0, (30*col[3])>>8);
1364                 ui_shadowbox(minx, miny, maxx, maxy, 4.0, (70*col[3])>>8);
1365                 ui_shadowbox(minx, miny, maxx, maxy, 2.0, (100*col[3])>>8);
1366                 
1367                 glEnable(GL_BLEND);
1368                 glColor4ubv(col);
1369                 glRectf(minx-1, miny, minx, maxy);      // 1 pixel on left, to distinguish sublevel menus
1370         }
1371         glEnable(GL_BLEND);
1372         glColor4ubv(col);
1373         glRectf(minx, miny, maxx, maxy);
1374         glDisable(GL_BLEND);
1375 }
1376
1377 /* pulldown menu item */
1378 static void ui_draw_pulldown_item(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1379 {
1380         char col[4];
1381         
1382         BIF_GetThemeColor4ubv(TH_MENU_BACK, col);
1383         if(col[3]!=255) {
1384                 glEnable(GL_BLEND);
1385                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1386         }
1387         
1388         if((flag & UI_ACTIVE) && type!=LABEL) {
1389                 BIF_ThemeColor4(TH_MENU_HILITE);
1390                 glRectf(x1, y1, x2, y2);
1391         
1392
1393         } else {
1394                 BIF_ThemeColor4(colorid);       // is set at TH_MENU_ITEM when pulldown opened.
1395                 glRectf(x1, y1, x2, y2);
1396         }
1397
1398         glDisable(GL_BLEND);
1399 }
1400
1401 /* pulldown menu calling button */
1402 static void ui_draw_pulldown_round(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1403 {
1404         
1405         if(flag & UI_ACTIVE) {
1406                 BIF_ThemeColor(TH_MENU_HILITE);
1407
1408                 uiSetRoundBox(15);
1409                 gl_round_box(GL_POLYGON, x1, y1+3, x2, y2-3, 7.0);
1410
1411                 glEnable( GL_LINE_SMOOTH );
1412                 glEnable( GL_BLEND );
1413                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1414                 gl_round_box(GL_LINE_LOOP, x1, y1+3, x2, y2-3, 7.0);
1415                 glDisable( GL_LINE_SMOOTH );
1416                 glDisable( GL_BLEND );
1417                 
1418         } else {
1419                 BIF_ThemeColor(colorid);        // is set at TH_MENU_ITEM when pulldown opened.
1420                 glRectf(x1-1, y1+2, x2+1, y2-2);
1421         }
1422         
1423 }
1424
1425
1426 /* ************** TEXT AND ICON DRAWING FUNCTIONS ************* */
1427
1428
1429
1430 /* draws text and icons for buttons */
1431 static void ui_draw_text_icon(uiBut *but)
1432 {
1433         float x;
1434         int len;
1435         char *cpoin;
1436         
1437         /* check for button text label */
1438         if (but->type == ICONTEXTROW) {
1439                 ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
1440         }
1441         else {
1442
1443                 // text button cursor
1444                 if(but->pos != -1) {
1445                         short t, pos, ch;
1446                         
1447                         pos= but->pos+strlen(but->str);
1448                         if(pos >= but->ofs) {
1449                                 if(but->drawstr[0]!=0) {
1450                                         ch= but->drawstr[pos];
1451                                         but->drawstr[pos]= 0;
1452                 
1453                                         t= but->aspect*BIF_GetStringWidth(but->font, but->drawstr+but->ofs, (U.transopts & USER_TR_BUTTONS)) + 3;
1454                 
1455                                         but->drawstr[pos]= ch;
1456                                 }
1457                                 else t= 3;
1458                                 
1459                                 glColor3ub(255,0,0);
1460                                 glRects(but->x1+t, but->y1+2, but->x1+t+3, but->y2-2);
1461                         }       
1462                 }
1463                 if(but->drawstr[0]!=0) {
1464                         // cut string in 2 parts
1465                         cpoin= strchr(but->drawstr, '|');
1466                         if(cpoin) *cpoin= 0;
1467
1468                         /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
1469                         and offset the text label to accomodate it */
1470                         
1471                         if ( (but->flag & UI_HAS_ICON) && (but->flag & UI_ICON_LEFT) ) {
1472                                 ui_draw_icon(but, but->icon);
1473
1474                                 if(but->flag & UI_TEXT_LEFT) x= but->x1+24.0;
1475                                 else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1476                         }
1477                         else {
1478                                 if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
1479                                 else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1480                         }
1481                         
1482                         /* text color, with pulldown item exception */
1483                         if(but->dt==UI_EMBOSSP) {
1484                                 if((but->flag & (UI_SELECT|UI_ACTIVE)) && but->type!=LABEL) {   // LABEL = title in pulldowns
1485                                         BIF_ThemeColor(TH_MENU_TEXT_HI);
1486                                 } else {
1487                                         BIF_ThemeColor(TH_MENU_TEXT);
1488                                 }
1489                         }
1490                         else {
1491                                 if(but->flag & UI_SELECT) {             
1492                                         BIF_ThemeColor(TH_BUT_TEXT_HI);
1493                                 } else {
1494                                         BIF_ThemeColor(TH_BUT_TEXT);
1495                                 }
1496                         }
1497
1498                         /* tog3 button exception */
1499                         if(but->type==TOG3 && (but->flag & UI_SELECT)) {
1500                                 int ok= 0;
1501                                 
1502                                 if( but->pointype==CHA ) {
1503                                         if( BTST( *(but->poin+2), but->bitnr )) ok= 1;
1504                                 }
1505                                 else if( but->pointype ==SHO ) {
1506                                         short *sp= (short *)but->poin;
1507                                         if( BTST( sp[1], but->bitnr )) ok= 1;
1508                                 }
1509                                 
1510                                 ui_tog3_invert(but->x1,but->y1,but->x2,but->y2, ok);
1511                                 if (ok) glColor3ub(255, 255, 0);
1512                         }
1513                         
1514                         /* LABEL button exception */
1515                         if(but->type==LABEL && but->min!=0.0) BIF_ThemeColor(TH_BUT_TEXT_HI);
1516                 
1517                         ui_rasterpos_safe(x, (but->y1+but->y2- 9.0)/2.0, but->aspect);
1518                         BIF_DrawString(but->font, but->drawstr+but->ofs, (U.transopts & USER_TR_BUTTONS));
1519
1520                         /* part text right aligned */
1521                         if(cpoin) {
1522                                 len= BIF_GetStringWidth(but->font, cpoin+1, (U.transopts & USER_TR_BUTTONS));
1523                                 ui_rasterpos_safe( but->x2 - len*but->aspect-3, (but->y1+but->y2- 9.0)/2.0, but->aspect);
1524                                 BIF_DrawString(but->font, cpoin+1, (U.transopts & USER_TR_BUTTONS));
1525                                 *cpoin= '|';
1526                         }
1527                 }
1528                 /* if there's no text label, then check to see if there's an icon only and draw it */
1529                 else if( but->flag & UI_HAS_ICON ) {
1530                         ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
1531                 }
1532         }
1533 }
1534
1535 static void ui_draw_but_COL(uiBut *but)
1536 {
1537         float *fp;
1538         char colr, colg, colb;
1539         
1540         if( but->pointype==FLO ) {
1541                 fp= (float *)but->poin;
1542                 colr= floor(255.0*fp[0]+0.5);
1543                 colg= floor(255.0*fp[1]+0.5);
1544                 colb= floor(255.0*fp[2]+0.5);
1545         }
1546         else {
1547                 char *cp= (char *)but->poin;
1548                 colr= cp[0];
1549                 colg= cp[1];
1550                 colb= cp[2];
1551         }
1552         
1553         /* exception... hrms, but can't simply use the emboss callback for this now. */
1554         /* this button type needs review, and nice integration with rest of API here */
1555         if(but->embossfunc == ui_draw_round) {
1556                 char *cp= BIF_ThemeGetColorPtr(U.themes.first, 0, TH_CUSTOM);
1557                 cp[0]= colr; cp[1]= colg; cp[2]= colb;
1558                 but->flag &= ~UI_SELECT;
1559                 but->embossfunc(but->type, TH_CUSTOM, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
1560         }
1561         else {
1562                 
1563                 glColor3ub(colr,  colg,  colb);
1564                 glRectf((but->x1), (but->y1), (but->x2), (but->y2));
1565                 glColor3ub(0,  0,  0);
1566                 fdrawbox((but->x1), (but->y1), (but->x2), (but->y2));
1567         }
1568 }
1569
1570 /* draws in resolution of 20x4 colors */
1571 static void ui_draw_but_HSVCUBE(uiBut *but)
1572 {
1573         int a;
1574         float h,s,v;
1575         float dx, dy, sx1, sx2, sy, x, y;
1576         float col0[4][3];       // left half, rect bottom to top
1577         float col1[4][3];       // right half, rect bottom to top
1578         
1579         h= but->hsv[0];
1580         s= but->hsv[1];
1581         v= but->hsv[2];
1582         
1583         /* draw series of gouraud rects */
1584         glShadeModel(GL_SMOOTH);
1585         
1586         if(but->a1==0) {        // H and V vary
1587                 hsv_to_rgb(0.0, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1588                 hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
1589                 hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
1590                 hsv_to_rgb(0.0, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1591                 x= h; y= v;
1592         }
1593         else if(but->a1==1) {   // H and S vary
1594                 hsv_to_rgb(0.0, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
1595                 hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
1596                 hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
1597                 hsv_to_rgb(0.0, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
1598                 x= h; y= s;
1599         }
1600         else if(but->a1==2) {   // S and V vary
1601                 hsv_to_rgb(h, 0.0, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1602                 hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]);
1603                 hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
1604                 hsv_to_rgb(h, 1.0, 0.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1605                 x= v; y= s;
1606         }
1607         else {          // only hue slider
1608                 hsv_to_rgb(0.0, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1609                 VECCOPY(col1[1], col1[0]);
1610                 VECCOPY(col1[2], col1[0]);
1611                 VECCOPY(col1[3], col1[0]);
1612                 x= h; y= 0.5;
1613         }
1614         
1615         for(dx=0.0; dx<1.0; dx+= 0.05) {
1616                 // previous color
1617                 VECCOPY(col0[0], col1[0]);
1618                 VECCOPY(col0[1], col1[1]);
1619                 VECCOPY(col0[2], col1[2]);
1620                 VECCOPY(col0[3], col1[3]);
1621
1622                 // new color
1623                 if(but->a1==0) {        // H and V vary
1624                         hsv_to_rgb(dx, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1625                         hsv_to_rgb(dx, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
1626                         hsv_to_rgb(dx, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
1627                         hsv_to_rgb(dx, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1628                 }
1629                 else if(but->a1==1) {   // H and S vary
1630                         hsv_to_rgb(dx, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
1631                         hsv_to_rgb(dx, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
1632                         hsv_to_rgb(dx, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
1633                         hsv_to_rgb(dx, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
1634                 }
1635                 else if(but->a1==2) {   // S and V vary
1636                         hsv_to_rgb(h, 0.0, dx,   &col1[0][0], &col1[0][1], &col1[0][2]);
1637                         hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]);
1638                         hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
1639                         hsv_to_rgb(h, 1.0, dx,   &col1[3][0], &col1[3][1], &col1[3][2]);
1640                 }
1641                 else {  // only H
1642                         hsv_to_rgb(dx, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1643                         VECCOPY(col1[1], col1[0]);
1644                         VECCOPY(col1[2], col1[0]);
1645                         VECCOPY(col1[3], col1[0]);
1646                 }
1647                 
1648                 // rect
1649                 sx1= but->x1 + dx*(but->x2-but->x1);
1650                 sx2= but->x1 + (dx+0.05)*(but->x2-but->x1);
1651                 sy= but->y1;
1652                 dy= (but->y2-but->y1)/3.0;
1653                 
1654                 glBegin(GL_QUADS);
1655                 for(a=0; a<3; a++, sy+=dy) {
1656                         glColor3fv(col0[a]);
1657                         glVertex2f(sx1, sy);
1658
1659                         glColor3fv(col1[a]);
1660                         glVertex2f(sx2, sy);
1661                         
1662                         glColor3fv(col1[a+1]);
1663                         glVertex2f(sx2, sy+dy);
1664                         
1665                         glColor3fv(col0[a+1]);
1666                         glVertex2f(sx1, sy+dy);
1667                 }
1668                 glEnd();
1669         }
1670
1671         glShadeModel(GL_FLAT);
1672
1673         /* cursor */
1674         x= but->x1 + x*(but->x2-but->x1);
1675         y= but->y1 + y*(but->y2-but->y1);
1676         CLAMP(x, but->x1+3.0, but->x2-3.0);
1677         CLAMP(y, but->y1+3.0, but->y2-3.0);
1678         
1679         fdrawXORcirc(x, y, 3.1);
1680
1681         /* outline */
1682         glColor3ub(0,  0,  0);
1683         fdrawbox((but->x1), (but->y1), (but->x2), (but->y2));
1684 }
1685
1686 /* nothing! */
1687 static void ui_draw_nothing(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1688 {
1689 }
1690
1691
1692 /* ************** EXTERN, called from interface.c ************* */
1693 /* ************** MAIN CALLBACK FUNCTION          ************* */
1694
1695 void ui_set_embossfunc(uiBut *but, int drawtype)
1696 {
1697         // this aded for evaluating textcolor for example
1698         but->dt= drawtype;
1699         
1700         // not really part of standard minimal themes, just make sure it is set
1701         but->sliderfunc= ui_draw_slider;
1702
1703         // standard builtin first:
1704         if(but->type==LABEL) but->embossfunc= ui_draw_nothing;
1705         else if(but->type==PULLDOWN) but->embossfunc= ui_draw_pulldown_round;
1706         else if(drawtype==UI_EMBOSSM) but->embossfunc= ui_draw_minimal;
1707         else if(drawtype==UI_EMBOSSN) but->embossfunc= ui_draw_nothing;
1708         else if(drawtype==UI_EMBOSSP) but->embossfunc= ui_draw_pulldown_item;
1709         else {
1710                 int theme= BIF_GetThemeValue(TH_BUT_DRAWTYPE);
1711                 
1712                 // and the themes
1713                 if(theme==1) {
1714                         but->embossfunc= ui_draw_default;
1715                         but->sliderfunc= ui_default_slider;
1716                 }
1717                 else if(theme==2) {
1718                         but->embossfunc= ui_draw_round;
1719                 }
1720                 else if(theme==3) {
1721                         but->embossfunc= ui_draw_oldskool;
1722                 }
1723                 else {
1724                         but->embossfunc= ui_draw_minimal;
1725                 }
1726         }
1727         
1728         // note: if you want aligning, adapt the call uiBlockEndAlign in interface.c 
1729 }
1730
1731
1732 void ui_draw_but(uiBut *but)
1733 {
1734         double value;
1735         float x1, x2, y1, y2, fac;
1736         
1737         if(but==NULL) return;
1738
1739         /* signal for frontbuf flush buttons and menus, not when normal drawing */
1740         if(but->block->in_use) ui_block_set_flush(but->block, but);
1741                 
1742         switch (but->type) {
1743
1744         case NUMSLI:
1745         case HSVSLI:
1746         
1747                 but->embossfunc(but->type, but->themecol, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
1748                 ui_draw_text_icon(but);
1749
1750                 x1= (but->x1+but->x2)/2;
1751                 x2= but->x2 - 5.0*but->aspect;
1752                 y1= but->y1 + 2.0*but->aspect;
1753                 y2= but->y2 - 2.0*but->aspect;
1754                 
1755                 value= ui_get_but_val(but);
1756                 fac= (value-but->min)*(x2-x1)/(but->max - but->min);
1757                 
1758                 but->sliderfunc(but->themecol, fac, but->aspect, x1, y1, x2, y2, but->flag);
1759                 break;
1760                 
1761         case SEPR:
1762                 //  only background
1763                 break;
1764                 
1765         case COL:
1766                 ui_draw_but_COL(but);  // black box with color
1767                 break;
1768
1769         case HSVCUBE:
1770                 ui_draw_but_HSVCUBE(but);  // box for colorpicker, three types
1771                 break;
1772
1773         case LINK:
1774         case INLINK:
1775                 ui_draw_icon(but, but->icon);
1776                 break;
1777
1778         default:
1779                 but->embossfunc(but->type, but->themecol, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
1780                 ui_draw_text_icon(but);
1781         
1782         }
1783 }
1784