* Fixed a silly problem when changing the colours of the 'Neutral' button theme entry...
[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
95
96 /* ************** generic embossed rect, for window sliders etc ************* */
97
98 void uiEmboss(float x1, float y1, float x2, float y2, int sel)
99 {
100         
101         /* below */
102         if(sel) glColor3ub(200,200,200);
103         else glColor3ub(50,50,50);
104         fdrawline(x1, y1, x2, y1);
105
106         /* right */
107         fdrawline(x2, y1, x2, y2);
108         
109         /* top */
110         if(sel) glColor3ub(50,50,50);
111         else glColor3ub(200,200,200);
112         fdrawline(x1, y2, x2, y2);
113
114         /* left */
115         fdrawline(x1, y1, x1, y2);
116         
117 }
118
119 /* ************** GENERIC ICON DRAW, NO THEME HERE ************* */
120
121 static void ui_draw_icon(uiBut *but, BIFIconID icon)
122 {
123         int blend= 0;
124         float xs=0, ys=0;
125
126         if(but->flag & UI_ICON_LEFT) {
127                 if (but->type==BUTM) {
128                         xs= but->x1+1.0;
129                 }
130                 else if ((but->type==ICONROW) || (but->type==ICONTEXTROW)) {
131                         xs= but->x1+4.0;
132                 }
133                 else {
134                         xs= but->x1+6.0;
135                 }
136                 ys= (but->y1+but->y2- BIF_get_icon_height(icon))/2.0;
137         }
138         if(but->flag & UI_ICON_RIGHT) {
139                 xs= but->x2-17.0;
140                 ys= (but->y1+but->y2- BIF_get_icon_height(icon))/2.0;
141         }
142         if (!((but->flag & UI_ICON_RIGHT) || (but->flag & UI_ICON_LEFT))) {
143                 xs= (but->x1+but->x2- BIF_get_icon_width(icon))/2.0;
144                 ys= (but->y1+but->y2- BIF_get_icon_height(icon))/2.0;
145         }
146
147         glRasterPos2f(xs, ys);
148
149         if(but->aspect>1.1) glPixelZoom(1.0/but->aspect, 1.0/but->aspect);
150
151         glEnable(GL_BLEND);
152         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
153
154         /* calculate blend color */
155         if ELEM4(but->type, ICONTOG, TOG, ROW, TOGN) {
156                 if(but->flag & UI_SELECT);
157                 else if(but->flag & UI_ACTIVE);
158                 else blend= -60;
159         }
160         BIF_draw_icon_blended(icon, but->themecol, blend);
161         
162 /* old blending method... hrums */
163 /*      if(but->flag & UI_SELECT) {
164                 if(but->flag & UI_ACTIVE) {
165                         BIF_draw_icon_blended(icon, but->themecol, -80);
166                 } else {
167                         BIF_draw_icon_blended(icon, but->themecol, -45);
168                 }
169         }
170         else {
171                 if ((but->flag & UI_ACTIVE) && but->type==BUTM) {
172                         BIF_draw_icon_blended(icon, but->themecol, 0);
173                 } else if (but->flag & UI_ACTIVE) {
174                         BIF_draw_icon_blended(icon, but->themecol, 25);
175                 } else {
176                         BIF_draw_icon_blended(icon, but->themecol, 45);
177                 }
178         }
179 */
180         glBlendFunc(GL_ONE, GL_ZERO);
181         glDisable(GL_BLEND);
182
183         glPixelZoom(1.0, 1.0);
184 }
185
186
187 /* ************** DEFAULT THEME, SHADED BUTTONS ************* */
188
189
190 #define M_WHITE         BIF_ThemeColorShade(colorid, 80)
191
192 #define M_ACT_LIGHT     BIF_ThemeColorShade(colorid, 55)
193 #define M_LIGHT         BIF_ThemeColorShade(colorid, 45)
194 #define M_HILITE        BIF_ThemeColorShade(colorid, 25)
195 #define M_LMEDIUM       BIF_ThemeColorShade(colorid, 10)
196 #define M_MEDIUM        BIF_ThemeColor(colorid)
197 #define M_LGREY         BIF_ThemeColorShade(colorid, -20)
198 #define M_GREY          BIF_ThemeColorShade(colorid, -45)
199 #define M_DARK          BIF_ThemeColorShade(colorid, -80)
200
201 #define M_NUMTEXT                               BIF_ThemeColorShade(colorid, 25)
202 #define M_NUMTEXT_ACT_LIGHT             BIF_ThemeColorShade(colorid, 35)
203
204 #define MM_WHITE        BIF_ThemeColorShade(TH_BUT_NEUTRAL, 120)
205
206 /* Used for the subtle sunken effect around buttons. This is hardcoded to 
207  * white to make sure the highlight properly adds to the colour underneath
208  */
209 #define MM_WHITE_OP     glColor4ub(255, 255, 255, 60)
210 #define MM_WHITE_TR     glColor4ub(255, 255, 255, 0)
211
212 #define MM_LIGHT        BIF_ThemeColorShade(TH_BUT_OUTLINE, 45)
213 #define MM_MEDIUM       BIF_ThemeColor(TH_BUT_OUTLINE)
214 #define MM_GREY         BIF_ThemeColorShade(TH_BUT_OUTLINE, -45)
215 #define MM_DARK         BIF_ThemeColorShade(TH_BUT_OUTLINE, -80)
216
217 /* base shaded button */
218 static void shaded_button(float x1, float y1, float x2, float y2, float asp, int colorid, int flag, int mid)
219 {
220         /* 'mid' arg determines whether the button is in the middle of
221          * an alignment group or not. 0 = not middle, 1 = is in the middle.
222          * Done to allow cleaner drawing
223          */
224          
225         /* *** SHADED BUTTON BASE *** */
226         glShadeModel(GL_SMOOTH);
227         glBegin(GL_QUADS);
228         
229         if(flag & UI_SELECT) {
230                 if(flag & UI_ACTIVE) M_MEDIUM;
231                 else M_LGREY;
232         } else {
233                 if(flag & UI_ACTIVE) M_LIGHT;
234                 else M_HILITE;
235         }
236
237         glVertex2f(x1,y1);
238         glVertex2f(x2,y1);
239
240         if(flag & UI_SELECT) {
241                 if(flag & UI_ACTIVE) M_LGREY;
242                 else M_GREY;
243         } else {
244                 if(flag & UI_ACTIVE) M_ACT_LIGHT;
245                 else M_LIGHT;
246         }
247
248         glVertex2f(x2,(y2-(y2-y1)/3));
249         glVertex2f(x1,(y2-(y2-y1)/3));
250         glEnd();
251         
252
253         glShadeModel(GL_FLAT);
254         glBegin(GL_QUADS);
255         
256         if(flag & UI_SELECT) {
257                 if(flag & UI_ACTIVE) M_LGREY;
258                 else M_GREY;
259         } else {
260                 if(flag & UI_ACTIVE) M_ACT_LIGHT;
261                 else M_LIGHT;
262         }
263         
264         glVertex2f(x1,(y2-(y2-y1)/3));
265         glVertex2f(x2,(y2-(y2-y1)/3));
266         glVertex2f(x2,y2);
267         glVertex2f(x1,y2);
268
269         glEnd();
270         /* *** END SHADED BUTTON BASE *** */
271         
272         /* *** INNER OUTLINE *** */
273         /* left */
274         if(!(flag & UI_SELECT)) {
275                 glShadeModel(GL_SMOOTH);
276                 glBegin(GL_LINES);
277                 M_MEDIUM;
278                 glVertex2f(x1+1,y1+2);
279                 M_WHITE;
280                 glVertex2f(x1+1,y2);
281                 glEnd();
282         }
283         
284         /* right */
285                 if(!(flag & UI_SELECT)) {
286                 glShadeModel(GL_SMOOTH);
287                 glBegin(GL_LINES);
288                 M_MEDIUM;
289                 glVertex2f(x2-1,y1+2);
290                 M_WHITE;
291                 glVertex2f(x2-1,y2);
292                 glEnd();
293         }
294         
295         glShadeModel(GL_FLAT);
296         
297         /* top */
298         if(flag & UI_SELECT) {
299                 if(flag & UI_ACTIVE) M_LGREY;
300                 else M_GREY;
301         } else {
302                 if(flag & UI_ACTIVE) M_WHITE;
303                 else M_WHITE;
304         }
305
306         fdrawline(x1, (y2-1), x2, (y2-1));
307         
308         /* bottom */
309         if(flag & UI_SELECT) {
310                 if(flag & UI_ACTIVE) M_MEDIUM;
311                 else M_LGREY;
312         } else {
313                 if(flag & UI_ACTIVE) M_LMEDIUM;
314                 else M_MEDIUM;
315         }
316         fdrawline(x1, (y1+1), x2, (y1+1));
317         /* *** END INNER OUTLINE *** */
318         
319         /* *** OUTER OUTLINE *** */
320         if (mid) {
321                 // we draw full outline, its not AA, and it works better button mouse-over hilite
322                 MM_DARK;
323                 
324                 // left right
325                 fdrawline(x1, y1, x1, y2);
326                 fdrawline(x2, y1, x2, y2);
327         
328                 // top down
329                 fdrawline(x1, y2, x2, y2);
330                 fdrawline(x1, y1, x2, y1); 
331         } else {
332                 MM_DARK;
333                 glBegin(GL_LINE_LOOP);
334                 gl_round_box(x1, y1, x2, y2, 1.0);
335                 glEnd();
336         }
337         /* END OUTER OUTLINE */
338 }
339
340 /* base flat button */
341 static void flat_button(float x1, float y1, float x2, float y2, float asp, int colorid, int flag, int mid)
342 {
343         /* 'mid' arg determines whether the button is in the middle of
344          * an alignment group or not. 0 = not middle, 1 = is in the middle.
345          * Done to allow cleaner drawing
346          */
347          
348         /* *** FLAT TEXT/NUM FIELD *** */
349         glShadeModel(GL_FLAT);
350         if(flag & UI_SELECT) {
351                 if(flag & UI_ACTIVE) M_LGREY;
352                 else M_GREY;
353         }
354         else {
355                 if(flag & UI_ACTIVE) M_NUMTEXT_ACT_LIGHT;
356                 else M_NUMTEXT;
357         }
358
359         glRectf(x1, y1, x2, y2);
360         /* *** END FLAT TEXT/NUM FIELD *** */
361         
362         /* *** OUTER OUTLINE *** */
363         if (mid) {
364                 // we draw full outline, its not AA, and it works better button mouse-over hilite
365                 MM_DARK;
366                 
367                 // left right
368                 fdrawline(x1, y1, x1, y2);
369                 fdrawline(x2, y1, x2, y2);
370         
371                 // top down
372                 fdrawline(x1, y2, x2, y2);
373                 fdrawline(x1, y1, x2, y1); 
374         } else {
375                 MM_DARK;
376                 glBegin(GL_LINE_LOOP);
377                 gl_round_box(x1, y1, x2, y2, 1.0);
378                 glEnd();
379         }
380         /* END OUTER OUTLINE */
381 }
382
383 /* small side double arrow for iconrow */
384 static void ui_default_iconrow_arrows(float x1, float y1, float x2, float y2)
385 {
386         glEnable( GL_POLYGON_SMOOTH );
387         glEnable( GL_BLEND );
388         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
389         
390         glShadeModel(GL_FLAT);
391         glBegin(GL_TRIANGLES);
392         glVertex2f((short)x2-2,(short)(y2-(y2-y1)/2)+1);
393         glVertex2f((short)x2-6,(short)(y2-(y2-y1)/2)+1);
394         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2)+4);
395         glEnd();
396                 
397         glBegin(GL_TRIANGLES);
398         glVertex2f((short)x2-2,(short)(y2-(y2-y1)/2) -1);
399         glVertex2f((short)x2-6,(short)(y2-(y2-y1)/2) -1);
400         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2) -4);
401         glEnd();
402         
403         glDisable( GL_BLEND );
404         glDisable( GL_POLYGON_SMOOTH );
405 }
406
407 /* side double arrow for menu */
408 static void ui_default_menu_arrows(float x1, float y1, float x2, float y2)
409 {
410         glEnable( GL_POLYGON_SMOOTH );
411         glEnable( GL_BLEND );
412         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
413         
414         glShadeModel(GL_FLAT);
415         glBegin(GL_TRIANGLES);
416         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2)+1);
417         glVertex2f((short)x2-12,(short)(y2-(y2-y1)/2)+1);
418         glVertex2f((short)x2-8,(short)(y2-(y2-y1)/2)+4);
419         glEnd();
420                 
421         glBegin(GL_TRIANGLES);
422         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2) -1);
423         glVertex2f((short)x2-12,(short)(y2-(y2-y1)/2) -1);
424         glVertex2f((short)x2-8,(short)(y2-(y2-y1)/2) -4);
425         glEnd();
426         
427         glDisable( GL_BLEND );
428         glDisable( GL_POLYGON_SMOOTH );
429 }
430
431 /* left/right arrows for number fields */
432 static void ui_default_num_arrows(float x1, float y1, float x2, float y2)
433 {
434         glEnable( GL_POLYGON_SMOOTH );
435         glEnable( GL_BLEND );
436         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
437         
438         glShadeModel(GL_FLAT);
439         glBegin(GL_TRIANGLES);
440         
441         glVertex2f((short)x1+5,(short)(y2-(y2-y1)/2));
442         glVertex2f((short)x1+10,(short)(y2-(y2-y1)/2)+4);
443         glVertex2f((short)x1+10,(short)(y2-(y2-y1)/2)-4);
444         glEnd();
445
446         /* right */
447         glShadeModel(GL_FLAT);
448         glBegin(GL_TRIANGLES);
449
450         glVertex2f((short)x2-5,(short)(y2-(y2-y1)/2));
451         glVertex2f((short)x2-10,(short)(y2-(y2-y1)/2)-4);
452         glVertex2f((short)x2-10,(short)(y2-(y2-y1)/2)+4);
453         glEnd();
454         
455         glDisable( GL_BLEND );
456         glDisable( GL_POLYGON_SMOOTH );
457 }
458
459 /* changing black/white for TOG3 buts */
460 static void ui_tog3_invert(float x1, float y1, float x2, float y2, int seltype)
461 {
462         short alpha = 30;
463         
464         if (seltype == 0) {
465                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
466                 glEnable(GL_BLEND);
467                 
468                 glColor4ub(0, 0, 0, alpha);
469                 glRectf(x2-6, y1, x2, (y1+(y2-y1)/2));
470                 
471                 glColor4ub(255, 255, 255, alpha);
472                 glRectf(x2-6, (y1+(y2-y1)/2), x2, y2);
473                 
474                 glDisable(GL_BLEND);
475         } else {
476                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
477                 glEnable(GL_BLEND);
478                 
479                 glColor4ub(255, 255, 255, alpha);
480                 glRectf(x2-6, y1, x2, (y1+(y2-y1)/2));
481                 
482                 glColor4ub(0, 0, 0, alpha);
483                 glRectf(x2-6, (y1+(y2-y1)/2), x2, y2);
484                 
485                 glDisable(GL_BLEND);
486         }
487 }
488
489 /* button/popup menu/iconrow drawing code */
490 static void ui_default_button(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
491 {
492         int align= (flag & UI_BUT_ALIGN);
493
494         if(align) {
495         
496                 /* *** BOTTOM OUTER SUNKEN EFFECT *** */
497                 if (!((align == UI_BUT_ALIGN_DOWN) ||
498                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT)) ||
499                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT)))) {
500                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
501                         glEnable(GL_BLEND);
502                         MM_WHITE_OP;
503                         fdrawline(x1, y1-1, x2, y1-1);  
504                         glDisable(GL_BLEND);
505                 }
506                 /* *** END BOTTOM OUTER SUNKEN EFFECT *** */
507                 
508                 switch(align) {
509                 case UI_BUT_ALIGN_TOP:
510                         uiSetRoundBox(12);
511                         
512                         /* last arg in shaded_button() determines whether the button is in the middle of
513                          * an alignment group or not. 0 = not middle, 1 = is in the middle.
514                          * Done to allow cleaner drawing
515                          */
516                          
517                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
518                         break;
519                 case UI_BUT_ALIGN_DOWN:
520                         uiSetRoundBox(3);
521                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
522                         break;
523                 case UI_BUT_ALIGN_LEFT:
524                         
525                         /* RIGHT OUTER SUNKEN EFFECT */
526                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
527                         glEnable(GL_BLEND);
528                         glShadeModel(GL_SMOOTH);
529                         glBegin(GL_LINES);
530                         MM_WHITE_OP;
531                         glVertex2f(x2+1,y1);
532                         MM_WHITE_TR;
533                         glVertex2f(x2+1,y2);
534                         glEnd();
535                         glDisable(GL_BLEND);
536                         
537                         uiSetRoundBox(6);
538                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
539                         break;
540                 case UI_BUT_ALIGN_RIGHT:
541                 
542                         /* LEFT OUTER SUNKEN EFFECT */
543                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
544                         glEnable(GL_BLEND);
545                         glShadeModel(GL_SMOOTH);
546                         glBegin(GL_LINES);
547                         MM_WHITE_OP;
548                         glVertex2f(x1-1,y1);
549                         MM_WHITE_TR;
550                         glVertex2f(x1-1,y2);
551                         glEnd();
552                         glDisable(GL_BLEND);
553                 
554                         uiSetRoundBox(9);
555                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
556                         break;
557                         
558                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
559                         uiSetRoundBox(1);
560                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
561                         break;
562                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
563                         uiSetRoundBox(2);
564                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
565                         break;
566                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
567                 
568                         /* LEFT OUTER SUNKEN EFFECT */
569                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
570                         glEnable(GL_BLEND);
571                         glShadeModel(GL_SMOOTH);
572                         glBegin(GL_LINES);
573                         MM_WHITE_OP;
574                         glVertex2f(x1-1,y1);
575                         MM_WHITE_TR;
576                         glVertex2f(x1-1,y2);
577                         glEnd();
578                         glDisable(GL_BLEND);
579                 
580                         uiSetRoundBox(8);
581                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
582                         break;
583                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
584                 
585                         /* RIGHT OUTER SUNKEN EFFECT */
586                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
587                         glEnable(GL_BLEND);
588                         glShadeModel(GL_SMOOTH);
589                         glBegin(GL_LINES);
590                         MM_WHITE_OP;
591                         glVertex2f(x2+1,y1);
592                         MM_WHITE_TR;
593                         glVertex2f(x2+1,y2);
594                         glEnd();
595                         glDisable(GL_BLEND);
596                         
597                         uiSetRoundBox(4);
598                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
599                         break;
600                         
601                 default:
602                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 1);
603                         break;
604                 }
605         } 
606         else {  
607                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
608                 glEnable(GL_BLEND);
609                 glShadeModel(GL_SMOOTH);
610                 
611                 /* BOTTOM OUTER SUNKEN EFFECT */
612                 MM_WHITE_OP;
613                 fdrawline(x1, y1-1, x2, y1-1);  
614                 
615                 /* LEFT OUTER SUNKEN EFFECT */
616                 glBegin(GL_LINES);
617                 MM_WHITE_OP;
618                 glVertex2f(x1-1,y1);
619                 MM_WHITE_TR;
620                 glVertex2f(x1-1,y2);
621                 glEnd();
622                 
623                 /* RIGHT OUTER SUNKEN EFFECT */
624                 glBegin(GL_LINES);
625                 MM_WHITE_OP;
626                 glVertex2f(x2+1,y1);
627                 MM_WHITE_TR;
628                 glVertex2f(x2+1,y2);
629                 glEnd();
630                 
631                 glDisable(GL_BLEND);
632         
633                 uiSetRoundBox(15);
634                 shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
635         }
636         
637         /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */
638         switch(type) {
639         case ICONROW:
640         case ICONTEXTROW:
641                 /* DARKENED AREA */
642                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
643                 glEnable(GL_BLEND);
644                 
645                 glColor4ub(0, 0, 0, 30);
646                 glRectf(x2-9, y1, x2, y2);
647         
648                 glDisable(GL_BLEND);
649                 /* END DARKENED AREA */
650         
651                 /* ICONROW DOUBLE-ARROW  */
652                 M_DARK;
653                 ui_default_iconrow_arrows(x1, y1, x2, y2);
654                 /* END ICONROW DOUBLE-ARROW */
655                 break;
656         case MENU:
657                 /* DARKENED AREA */
658                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
659                 glEnable(GL_BLEND);
660                 
661                 glColor4ub(0, 0, 0, 30);
662                 glRectf(x2-18, y1, x2, y2);
663         
664                 glDisable(GL_BLEND);
665                 /* END DARKENED AREA */
666         
667                 /* MENU DOUBLE-ARROW  */
668                 M_DARK;
669                 ui_default_menu_arrows(x1, y1, x2, y2);
670                 /* MENU DOUBLE-ARROW */
671                 break;
672         }       
673 }
674
675
676 /* number/text field drawing code */
677 static void ui_default_flat(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
678 {
679         int align= (flag & UI_BUT_ALIGN);
680
681         if(align) {
682         
683                 /* *** BOTTOM OUTER SUNKEN EFFECT *** */
684                 if (!((align == UI_BUT_ALIGN_DOWN) ||
685                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT)) ||
686                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT)))) {
687                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
688                         glEnable(GL_BLEND);
689                         MM_WHITE_OP;
690                         fdrawline(x1, y1-1, x2, y1-1);  
691                         glDisable(GL_BLEND);
692                 }
693                 /* *** END BOTTOM OUTER SUNKEN EFFECT *** */
694                 
695                 switch(align) {
696                 case UI_BUT_ALIGN_TOP:
697                         uiSetRoundBox(12);
698                         
699                         /* last arg in shaded_button() determines whether the button is in the middle of
700                          * an alignment group or not. 0 = not middle, 1 = is in the middle.
701                          * Done to allow cleaner drawing
702                          */
703                          
704                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
705                         break;
706                 case UI_BUT_ALIGN_DOWN:
707                         uiSetRoundBox(3);
708                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
709                         break;
710                 case UI_BUT_ALIGN_LEFT:
711                         
712                         /* RIGHT OUTER SUNKEN EFFECT */
713                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
714                         glEnable(GL_BLEND);
715                         glShadeModel(GL_SMOOTH);
716                         glBegin(GL_LINES);
717                         MM_WHITE_OP;
718                         glVertex2f(x2+1,y1);
719                         MM_WHITE_TR;
720                         glVertex2f(x2+1,y2);
721                         glEnd();
722                         glDisable(GL_BLEND);
723                         
724                         uiSetRoundBox(6);
725                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
726                         break;
727                 case UI_BUT_ALIGN_RIGHT:
728                 
729                         /* LEFT OUTER SUNKEN EFFECT */
730                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
731                         glEnable(GL_BLEND);
732                         glShadeModel(GL_SMOOTH);
733                         glBegin(GL_LINES);
734                         MM_WHITE_OP;
735                         glVertex2f(x1-1,y1);
736                         MM_WHITE_TR;
737                         glVertex2f(x1-1,y2);
738                         glEnd();
739                         glDisable(GL_BLEND);
740                 
741                         uiSetRoundBox(9);
742                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
743                         break;
744                         
745                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
746                         uiSetRoundBox(1);
747                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
748                         break;
749                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
750                         uiSetRoundBox(2);
751                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
752                         break;
753                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
754                 
755                         /* LEFT OUTER SUNKEN EFFECT */
756                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
757                         glEnable(GL_BLEND);
758                         glShadeModel(GL_SMOOTH);
759                         glBegin(GL_LINES);
760                         MM_WHITE_OP;
761                         glVertex2f(x1-1,y1);
762                         MM_WHITE_TR;
763                         glVertex2f(x1-1,y2);
764                         glEnd();
765                         glDisable(GL_BLEND);
766                 
767                         uiSetRoundBox(8);
768                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
769                         break;
770                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
771                 
772                         /* RIGHT OUTER SUNKEN EFFECT */
773                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
774                         glEnable(GL_BLEND);
775                         glShadeModel(GL_SMOOTH);
776                         glBegin(GL_LINES);
777                         MM_WHITE_OP;
778                         glVertex2f(x2+1,y1);
779                         MM_WHITE_TR;
780                         glVertex2f(x2+1,y2);
781                         glEnd();
782                         glDisable(GL_BLEND);
783                         
784                         uiSetRoundBox(4);
785                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
786                         break;
787                         
788                 default:
789                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 1);
790                         break;
791                 }
792         } 
793         else {
794         
795                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
796                 glEnable(GL_BLEND);
797                 glShadeModel(GL_SMOOTH);
798                 
799                 /* BOTTOM OUTER SUNKEN EFFECT */
800                 MM_WHITE_OP;
801                 fdrawline(x1, y1-1, x2, y1-1);  
802                 
803                 /* LEFT OUTER SUNKEN EFFECT */
804                 glBegin(GL_LINES);
805                 MM_WHITE_OP;
806                 glVertex2f(x1-1,y1);
807                 MM_WHITE_TR;
808                 glVertex2f(x1-1,y2);
809                 glEnd();
810                 
811                 /* RIGHT OUTER SUNKEN EFFECT */
812                 glBegin(GL_LINES);
813                 MM_WHITE_OP;
814                 glVertex2f(x2+1,y1);
815                 MM_WHITE_TR;
816                 glVertex2f(x2+1,y2);
817                 glEnd();
818                 
819                 glDisable(GL_BLEND);
820
821                 uiSetRoundBox(15);
822                 flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
823         }
824         
825         /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */
826         switch(type) {
827         case NUM:
828                 /* SIDE ARROWS */
829                 /* left */
830                 if(flag & UI_SELECT) {
831                         if(flag & UI_ACTIVE) M_DARK;
832                         else M_DARK;
833                 } else {
834                         if(flag & UI_ACTIVE) M_GREY;
835                         else M_LGREY;
836                 }
837                 
838                 ui_default_num_arrows(x1, y1, x2, y2);
839                 /* END SIDE ARROWS */
840         }
841 }
842
843 static void ui_default_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag)
844 {
845         float ymid, yc;
846
847         /* the slider background line */
848         ymid= (y1+y2)/2.0;
849         //yc= 2.5*aspect;       // height of center line
850         yc = 2.3; // height of center line
851         
852         if(flag & UI_SELECT) 
853                         BIF_ThemeColorShade(TH_BUT_NUM, -5);
854         else
855                 if(flag & UI_ACTIVE) 
856                         BIF_ThemeColorShade(TH_BUT_NUM, +35); 
857                 else
858                         BIF_ThemeColorShade(TH_BUT_NUM, +25); 
859
860         glRectf(x1, ymid-yc, x2, ymid+yc);
861         
862         /* top inner bevel */
863         if(flag & UI_SELECT) BIF_ThemeColorShade(TH_BUT_NUM, -40); 
864         else BIF_ThemeColorShade(TH_BUT_NUM, -5); 
865         fdrawline(x1+1, ymid+yc, x2, ymid+yc);
866         
867         /* bottom inner bevel */
868         if(flag & UI_SELECT) BIF_ThemeColorShade(TH_BUT_NUM, +15); 
869         else BIF_ThemeColorShade(TH_BUT_NUM, +45); 
870         fdrawline(x1+1, ymid-yc, x2, ymid-yc);
871         
872         
873         /* the movable slider */
874         if(flag & UI_SELECT) BIF_ThemeColorShade(TH_BUT_NUM, +80); 
875         else BIF_ThemeColorShade(TH_BUT_NUM, -45); 
876
877         glShadeModel(GL_SMOOTH);
878         glBegin(GL_QUADS);
879
880         BIF_ThemeColorShade(TH_BUT_NUM, -45); 
881
882         glVertex2f(x1,     y1+2.5);
883         glVertex2f(x1+fac, y1+2.5);
884
885         BIF_ThemeColor(TH_BUT_NUM); 
886
887         glVertex2f(x1+fac, y2-2.5);
888         glVertex2f(x1,     y2-2.5);
889
890         glEnd();
891         
892
893         /* slider handle center */
894         glShadeModel(GL_SMOOTH);
895         glBegin(GL_QUADS);
896
897         BIF_ThemeColor(TH_BUT_NUM); 
898         glVertex2f(x1+fac-3, y1+2);
899         glVertex2f(x1+fac, y1+4);
900         BIF_ThemeColorShade(TH_BUT_NUM, +80); 
901         glVertex2f(x1+fac, y2-2);
902         glVertex2f(x1+fac-3, y2-2);
903
904         glEnd();
905         
906         /* slider handle left bevel */
907         BIF_ThemeColorShade(TH_BUT_NUM, +70); 
908         fdrawline(x1+fac-3, y2-2, x1+fac-3, y1+2);
909         
910         /* slider handle right bevel */
911         BIF_ThemeColorShade(TH_BUT_NUM, -35); 
912         fdrawline(x1+fac, y2-2, x1+fac, y1+2);
913
914         glShadeModel(GL_FLAT);
915 }
916
917 /* default theme callback */
918 static void ui_draw_default(int type, int colorid, float aspect, float x1, float y1, float x2, float y2, int flag)
919 {
920
921         switch(type) {
922         case TEX:
923         case IDPOIN:
924         case NUM:
925                 ui_default_flat(type, colorid, aspect, x1, y1, x2, y2, flag);
926                 break;
927         case ICONROW: 
928         case ICONTEXTROW: 
929         case MENU: 
930         default: 
931                 ui_default_button(type, colorid, aspect, x1, y1, x2, y2, flag);
932         }
933
934 }
935
936
937 /* *************** OLDSKOOL THEME ***************** */
938
939 static void ui_draw_outlineX(float x1, float y1, float x2, float y2, float asp1)
940 {
941         float vec[2];
942         
943         glBegin(GL_LINE_LOOP);
944         vec[0]= x1+asp1; vec[1]= y1-asp1;
945         glVertex2fv(vec);
946         vec[0]= x2-asp1; 
947         glVertex2fv(vec);
948         vec[0]= x2+asp1; vec[1]= y1+asp1;
949         glVertex2fv(vec);
950         vec[1]= y2-asp1;
951         glVertex2fv(vec);
952         vec[0]= x2-asp1; vec[1]= y2+asp1;
953         glVertex2fv(vec);
954         vec[0]= x1+asp1;
955         glVertex2fv(vec);
956         vec[0]= x1-asp1; vec[1]= y2-asp1;
957         glVertex2fv(vec);
958         vec[1]= y1+asp1;
959         glVertex2fv(vec);
960         glEnd();                
961         
962 }
963
964
965 static void ui_draw_oldskool(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
966 {
967         /* paper */
968         if(flag & UI_SELECT) {
969                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, -40);
970                 else BIF_ThemeColorShade(colorid, -30);
971         }
972         else {
973                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, +30);
974                 else BIF_ThemeColorShade(colorid, +20);
975         }
976         
977         glRectf(x1+1, y1+1, x2-1, y2-1);
978
979         x1+= asp;
980         x2-= asp;
981         y1+= asp;
982         y2-= asp;
983
984         /* below */
985         if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, 0);
986         else BIF_ThemeColorShade(colorid, -30);
987         fdrawline(x1, y1, x2, y1);
988
989         /* right */
990         fdrawline(x2, y1, x2, y2);
991         
992         /* top */
993         if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -30);
994         else BIF_ThemeColorShade(colorid, 0);
995         fdrawline(x1, y2, x2, y2);
996
997         /* left */
998         fdrawline(x1, y1, x1, y2);
999         
1000         /* outline */
1001         glColor3ub(0,0,0);
1002         ui_draw_outlineX(x1, y1, x2, y2, asp);
1003         
1004         
1005         /* special type decorations */
1006         switch(type) {
1007         case NUM:
1008                 if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -60);
1009                 else BIF_ThemeColorShade(colorid, -30);
1010                 ui_default_num_arrows(x1, y1, x2, y2);
1011                 break;
1012
1013         case ICONROW: 
1014         case ICONTEXTROW: 
1015                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1016                 else BIF_ThemeColorShade(colorid, -10);
1017                 glRectf(x2-9, y1+asp, x2-asp, y2-asp);
1018
1019                 BIF_ThemeColorShade(colorid, -50);
1020                 ui_default_iconrow_arrows(x1, y1, x2, y2);
1021                 break;
1022                 
1023         case MENU: 
1024                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1025                 else BIF_ThemeColorShade(colorid, -10);
1026                 glRectf(x2-17, y1+asp, x2-asp, y2-asp);
1027
1028                 BIF_ThemeColorShade(colorid, -50);
1029                 ui_default_menu_arrows(x1, y1, x2, y2);
1030                 break;
1031         }
1032         
1033 }
1034
1035 /* *************** BASIC ROUNDED THEME ***************** */
1036
1037 static void round_button(float x1, float y1, float x2, float y2, float asp, int colorid)
1038 {
1039         float rad;
1040         
1041         rad= (y2-y1)/2.0;
1042         if(rad>7.0) rad= 7.0;
1043         
1044         glBegin(GL_POLYGON);
1045         gl_round_box(x1, y1, x2, y2, rad);
1046         glEnd();
1047         
1048         BIF_ThemeColorBlendShade(colorid, TH_BACK, 0.5, -70);
1049         
1050         glBegin(GL_LINE_LOOP);
1051         gl_round_box(x1, y1, x2, y2, rad);
1052         glEnd();
1053 }
1054
1055 /* button in midst of alignment row */
1056 static void round_button_mid(float x1, float y1, float x2, float y2, float asp, int colorid, int align)
1057 {
1058         glRectf(x1, y1, x2, y2);
1059         
1060         BIF_ThemeColorBlendShade(colorid, TH_BACK, 0.5, -70);
1061         // we draw full outline, its not AA, and it works better button mouse-over hilite
1062         
1063         // left right
1064         fdrawline(x1, y1, x1, y2);
1065         fdrawline(x2, y1, x2, y2);
1066
1067         // top down
1068         fdrawline(x1, y2, x2, y2);
1069         fdrawline(x1, y1, x2, y1);   
1070 }
1071
1072 static void ui_draw_round(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1073 {
1074         int align= (flag & UI_BUT_ALIGN);
1075         
1076         /* paper */
1077         if(flag & UI_SELECT) {
1078                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, -40);
1079                 else BIF_ThemeColorShade(colorid, -30);
1080         }
1081         else {
1082                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, +30);
1083                 else BIF_ThemeColorShade(colorid, +20);
1084         }
1085         
1086         if(align) {
1087                 switch(align) {
1088                 case UI_BUT_ALIGN_TOP:
1089                         uiSetRoundBox(12);
1090                         round_button(x1, y1, x2, y2, asp, colorid);
1091                         break;
1092                 case UI_BUT_ALIGN_DOWN:
1093                         uiSetRoundBox(3);
1094                         round_button(x1, y1, x2, y2, asp, colorid);
1095                         break;
1096                 case UI_BUT_ALIGN_LEFT:
1097                         uiSetRoundBox(6);
1098                         round_button(x1, y1, x2, y2, asp, colorid);
1099                         break;
1100                 case UI_BUT_ALIGN_RIGHT:
1101                         uiSetRoundBox(9);
1102                         round_button(x1, y1, x2, y2, asp, colorid);
1103                         break;
1104                         
1105                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
1106                         uiSetRoundBox(1);
1107                         round_button(x1, y1, x2, y2, asp, colorid);
1108                         break;
1109                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
1110                         uiSetRoundBox(2);
1111                         round_button(x1, y1, x2, y2, asp, colorid);
1112                         break;
1113                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
1114                         uiSetRoundBox(8);
1115                         round_button(x1, y1, x2, y2, asp, colorid);
1116                         break;
1117                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
1118                         uiSetRoundBox(4);
1119                         round_button(x1, y1, x2, y2, asp, colorid);
1120                         break;
1121                         
1122                 default:
1123                         round_button_mid(x1, y1, x2, y2, asp, colorid, align);
1124                         break;
1125                 }
1126         } 
1127         else {
1128                 uiSetRoundBox(15);
1129                 round_button(x1, y1, x2, y2, asp, colorid);
1130         }
1131         
1132         /* special type decorations */
1133         switch(type) {
1134         case NUM:
1135                 if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -60);
1136                 else BIF_ThemeColorShade(colorid, -30);
1137                 ui_default_num_arrows(x1, y1, x2, y2);
1138                 break;
1139
1140         case ICONROW: 
1141         case ICONTEXTROW: 
1142                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1143                 else BIF_ThemeColorShade(colorid, -10);
1144                 // assuming its not inside alignment...
1145                 uiSetRoundBox(6);
1146                 glBegin(GL_POLYGON);
1147                 gl_round_box(x2-9, y1+asp, x2-asp, y2-asp, 7.0);
1148                 glEnd();
1149
1150                 BIF_ThemeColorShade(colorid, -60);
1151                 ui_default_iconrow_arrows(x1, y1, x2, y2);
1152                 break;
1153                 
1154         case MENU: 
1155                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1156                 else BIF_ThemeColorShade(colorid, -10);
1157                 // assuming its not inside alignment...
1158                 if(x2-x1 > 24) {
1159                         uiSetRoundBox(6);
1160                         glBegin(GL_POLYGON);
1161                         gl_round_box(x2-16, y1+asp, x2-asp, y2-asp, 7.0);
1162                         glEnd();
1163                 }
1164                 BIF_ThemeColorShade(colorid, -60);
1165                 ui_default_menu_arrows(x1, y1, x2, y2);
1166                 break;
1167         }
1168 }
1169
1170 /* *************** MINIMAL THEME ***************** */
1171
1172 // theme can define an embosfunc and sliderfunc, text+icon drawing is standard, no theme.
1173
1174
1175
1176 /* super minimal button as used in logic menu */
1177 static void ui_draw_minimal(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1178 {
1179         
1180         x1+= asp;
1181         x2-= asp;
1182         y1+= asp;
1183         y2-= asp;
1184
1185         /* paper */
1186         if(flag & UI_SELECT) {
1187                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, -40);
1188                 else BIF_ThemeColorShade(colorid, -30);
1189         }
1190         else {
1191                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, +20);
1192                 else BIF_ThemeColorShade(colorid, +10);
1193         }
1194         
1195         glRectf(x1, y1, x2, y2);
1196
1197         if(flag & UI_SELECT) {
1198                 BIF_ThemeColorShade(colorid, -60);
1199
1200                 /* top */
1201                 fdrawline(x1, y2, x2, y2);
1202                 /* left */
1203                 fdrawline(x1, y1, x1, y2);
1204                 BIF_ThemeColorShade(colorid, +40);
1205
1206                 /* below */
1207                 fdrawline(x1, y1, x2, y1);
1208                 /* right */
1209                 fdrawline(x2, y1, x2, y2);
1210         }
1211         else {
1212                 BIF_ThemeColorShade(colorid, +40);
1213
1214                 /* top */
1215                 fdrawline(x1, y2, x2, y2);
1216                 /* left */
1217                 fdrawline(x1, y1, x1, y2);
1218                 
1219                 BIF_ThemeColorShade(colorid, -60);
1220                 /* below */
1221                 fdrawline(x1, y1, x2, y1);
1222                 /* right */
1223                 fdrawline(x2, y1, x2, y2);
1224         }
1225         
1226         /* special type decorations */
1227         switch(type) {
1228         case NUM:
1229                 if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -60);
1230                 else BIF_ThemeColorShade(colorid, -30);
1231                 ui_default_num_arrows(x1, y1, x2, y2);
1232                 break;
1233
1234         case ICONROW: 
1235         case ICONTEXTROW: 
1236                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1237                 else BIF_ThemeColorShade(colorid, -10);
1238                 glRectf(x2-9, y1+asp, x2-asp, y2-asp);
1239
1240                 BIF_ThemeColorShade(colorid, -50);
1241                 ui_default_iconrow_arrows(x1, y1, x2, y2);
1242                 break;
1243                 
1244         case MENU: 
1245                 if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 0);
1246                 else BIF_ThemeColorShade(colorid, -10);
1247                 glRectf(x2-17, y1+asp, x2-asp, y2-asp);
1248
1249                 BIF_ThemeColorShade(colorid, -50);
1250                 ui_default_menu_arrows(x1, y1, x2, y2);
1251                 break;
1252         }
1253         
1254         
1255 }
1256
1257
1258 /* fac is the slider handle position between x1 and x2 */
1259 static void ui_draw_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag)
1260 {
1261         float ymid, yc;
1262
1263         /* the slider background line */
1264         ymid= (y1+y2)/2.0;
1265         yc= 1.7*aspect; 
1266
1267         if(flag & UI_ACTIVE) 
1268                 BIF_ThemeColorShade(colorid, -50); 
1269         else 
1270                 BIF_ThemeColorShade(colorid, -40); 
1271
1272         /* left part */
1273         glRectf(x1, ymid-2.0*yc, x1+fac, ymid+2.0*yc);
1274         /* right part */
1275         glRectf(x1+fac, ymid-yc, x2, ymid+yc);
1276
1277         /* the movable slider */
1278         
1279         BIF_ThemeColorShade(colorid, +70); 
1280         glRectf(x1+fac-aspect, ymid-2.0*yc, x1+fac+aspect, ymid+2.0*yc);
1281
1282 }
1283
1284 /* ************** STANDARD MENU DRAWING FUNCTION (no callback yet) ************* */
1285
1286
1287 // background for pulldowns, pullups, and other frontbuffer drawing temporal menus....
1288 // has to be made themable still (now only color)
1289
1290 void uiDrawMenuBox(float minx, float miny, float maxx, float maxy)
1291 {
1292         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1293         glEnable(GL_BLEND);
1294         
1295         glColor4ub(0, 0, 0, 20);
1296         
1297         /* to prevent gaps being drawn between box and shadow (rounding errors?) */
1298         fdrawline(minx+3, miny+0.25, maxx+0.25, miny+0.25);
1299         fdrawline(maxx+0.25, miny+0.25, maxx+0.25, maxy-3);
1300         
1301         glColor4ub(0, 0, 0, 70);
1302         fdrawline(minx+3, miny, maxx+1, miny);
1303         fdrawline(maxx+1, miny, maxx+1, maxy-3);
1304         
1305         glColor4ub(0, 0, 0, 70);
1306         fdrawline(minx+3, miny-1, maxx+1, miny-1);
1307         fdrawline(maxx+1, miny-1, maxx+1, maxy-3);
1308
1309         glColor4ub(0, 0, 0, 55);
1310         fdrawline(minx+3, miny-2, maxx+2, miny-2);
1311         fdrawline(maxx+2, miny-2, maxx+2, maxy-3);
1312
1313         glColor4ub(0, 0, 0, 35);
1314         fdrawline(minx+3, miny-3, maxx+3, miny-3);
1315         fdrawline(maxx+3, miny-3, maxx+3, maxy-3);
1316
1317         glColor4ub(0, 0, 0, 20);
1318         fdrawline(minx+3, miny-4, maxx+4, miny-4);
1319         fdrawline(maxx+4, miny-4, maxx+4, maxy-3);
1320         
1321         glDisable(GL_BLEND);
1322         
1323         BIF_ThemeColor(TH_MENU_BACK);
1324
1325         glRectf(minx, miny, maxx, maxy);
1326 }
1327
1328 /* pulldown menu */
1329 static void ui_draw_pulldown(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1330 {
1331
1332         if(flag & UI_ACTIVE) {
1333                 BIF_ThemeColor(TH_MENU_HILITE);
1334                 glRectf(x1-1, y1, x2+2, y2);
1335
1336         } else {
1337                 BIF_ThemeColor(colorid);        // is set at TH_MENU_ITEM when pulldown opened.
1338                 glRectf(x1-1, y1, x2+2, y2);
1339         }
1340
1341 }
1342
1343
1344
1345
1346 /* ************** TEXT AND ICON DRAWING FUNCTIONS ************* */
1347
1348
1349
1350 /* draws text and icons for buttons */
1351 static void ui_draw_text_icon(uiBut *but)
1352 {
1353         float x;
1354         int len;
1355         char *cpoin;
1356         
1357         /* check for button text label */
1358         if (but->type == ICONTEXTROW) {
1359                 ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
1360         }
1361         else if(but->drawstr[0]!=0) {
1362                 
1363                 // text button cursor
1364                 if(but->pos != -1) {
1365                         short t, pos, ch;
1366                         
1367                         pos= but->pos+strlen(but->str);
1368                         if(pos >= but->ofs) {
1369                                 ch= but->drawstr[pos];
1370                                 but->drawstr[pos]= 0;
1371         
1372                                 t= but->aspect*BIF_GetStringWidth(but->font, but->drawstr+but->ofs, (U.transopts & TR_BUTTONS)) + 3;
1373         
1374                                 but->drawstr[pos]= ch;
1375                                 glColor3ub(255,0,0);
1376         
1377                                 glRects(but->x1+t, but->y1+2, but->x1+t+3, but->y2-2);
1378                         }       
1379                 }
1380                 // cut string in 2 parts
1381                 cpoin= strchr(but->drawstr, '|');
1382                 if(cpoin) *cpoin= 0;
1383
1384                 /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
1385                 and offset the text label to accomodate it */
1386                 
1387                 if ( (but->flag & UI_HAS_ICON) && (but->flag & UI_ICON_LEFT) ) {
1388                         ui_draw_icon(but, but->icon);
1389
1390                         if(but->flag & UI_TEXT_LEFT) x= but->x1+24.0;
1391                         else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1392                 }
1393                 else {
1394                         if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
1395                         else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1396                 }
1397                 
1398                 /* text color, with pulldown item exception */
1399                 if(but->embossfunc==ui_draw_pulldown) {
1400                         if(but->flag & (UI_SELECT|UI_ACTIVE)) {         
1401                                 BIF_ThemeColor(TH_MENU_TEXT_HI);
1402                         } else {
1403                                 BIF_ThemeColor(TH_MENU_TEXT);
1404                         }
1405                 }
1406                 else {
1407                         if(but->flag & UI_SELECT) {             
1408                                 BIF_ThemeColor(TH_BUT_TEXT_HI);
1409                         } else {
1410                                 BIF_ThemeColor(TH_BUT_TEXT);
1411                         }
1412                 }
1413
1414                 /* tog3 button exception */
1415                 if(but->type==TOG3 && (but->flag & UI_SELECT)) {
1416                         int ok= 0;
1417                         
1418                         if( but->pointype==CHA ) {
1419                                 if( BTST( *(but->poin+2), but->bitnr )) ok= 1;
1420                         }
1421                         else if( but->pointype ==SHO ) {
1422                                 short *sp= (short *)but->poin;
1423                                 if( BTST( sp[1], but->bitnr )) ok= 1;
1424                         }
1425                         
1426                         ui_tog3_invert(but->x1,but->y1,but->x2,but->y2, ok);
1427                         if (ok) glColor3ub(255, 255, 0);
1428                 }
1429                 
1430                 glRasterPos2f( x, (but->y1+but->y2- 9.0)/2.0);
1431                 BIF_DrawString(but->font, but->drawstr+but->ofs, (U.transopts & TR_BUTTONS));
1432
1433                 /* part text right aligned */
1434                 if(cpoin) {
1435                         len= BIF_GetStringWidth(but->font, cpoin+1, (U.transopts & TR_BUTTONS));
1436                         glRasterPos2f( but->x2 - len*but->aspect-3, (but->y1+but->y2- 9.0)/2.0);
1437                         BIF_DrawString(but->font, cpoin+1, (U.transopts & TR_BUTTONS));
1438                         *cpoin= '|';
1439                 }
1440         }
1441         /* if there's no text label, then check to see if there's an icon only and draw it */
1442         else if( but->flag & UI_HAS_ICON ) {
1443                 ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
1444         }
1445
1446 }
1447
1448 static void ui_draw_but_COL(uiBut *but)
1449 {
1450         float *fp;
1451         char colr, colg, colb;
1452         
1453         if( but->pointype==FLO ) {
1454                 fp= (float *)but->poin;
1455                 colr= floor(255.0*fp[0]+0.5);
1456                 colg= floor(255.0*fp[1]+0.5);
1457                 colb= floor(255.0*fp[2]+0.5);
1458         }
1459         else {
1460                 char *cp= (char *)but->poin;
1461                 colr= cp[0];
1462                 colg= cp[1];
1463                 colb= cp[2];
1464         }
1465         
1466         /* exception... hrms, but can't simply use the emboss callback for this now. */
1467         /* this button type needs review, and nice integration with rest of API here */
1468         if(but->embossfunc == ui_draw_round) {
1469                 char *cp= BIF_ThemeGetColorPtr(U.themes.first, 0, TH_CUSTOM);
1470                 cp[0]= colr; cp[1]= colg; cp[2]= colb;
1471                 but->flag &= ~UI_SELECT;
1472                 but->embossfunc(but->type, TH_CUSTOM, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
1473         }
1474         else {
1475                 
1476                 glColor3ub(colr,  colg,  colb);
1477                 glRectf((but->x1), (but->y1), (but->x2), (but->y2));
1478                 glColor3ub(0,  0,  0);
1479                 fdrawbox((but->x1), (but->y1), (but->x2), (but->y2));
1480         }
1481 }
1482
1483
1484
1485 /* nothing! */
1486 static void ui_draw_nothing(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1487 {
1488 }
1489
1490
1491 /* ************** EXTERN, called from interface.c ************* */
1492 /* ************** MAIN CALLBACK FUNCTION          ************* */
1493
1494 void ui_set_embossfunc(uiBut *but, int drawtype)
1495 {
1496
1497         // not really part of standard minimal themes, just make sure it is set
1498         but->sliderfunc= ui_draw_slider;
1499
1500         // standard builtin first:
1501         if(but->type==LABEL) but->embossfunc= ui_draw_nothing;
1502         else if(drawtype==UI_EMBOSSM) but->embossfunc= ui_draw_minimal;
1503         else if(drawtype==UI_EMBOSSN) but->embossfunc= ui_draw_nothing;
1504         else if(drawtype==UI_EMBOSSP) but->embossfunc= ui_draw_pulldown;
1505         else {
1506                 int theme= BIF_GetThemeValue(TH_BUT_DRAWTYPE);
1507                 
1508                 // and the themes
1509                 if(theme==1) {
1510                         but->embossfunc= ui_draw_default;
1511                         but->sliderfunc= ui_default_slider;
1512                 }
1513                 else if(theme==2) {
1514                         but->embossfunc= ui_draw_round;
1515                 }
1516                 else if(theme==3) {
1517                         but->embossfunc= ui_draw_oldskool;
1518                 }
1519                 else {
1520                         but->embossfunc= ui_draw_minimal;
1521                 }
1522         }
1523         
1524         // note: if you want aligning, adapt the call uiBlockEndAlign in interface.c 
1525 }
1526
1527
1528 void ui_draw_but(uiBut *but)
1529 {
1530         double value;
1531         float x1, x2, y1, y2, fac;
1532         
1533         if(but==0) return;
1534
1535         if(but->block->frontbuf==UI_NEED_DRAW_FRONT) {
1536                 but->block->frontbuf= UI_HAS_DRAW_FRONT;
1537         
1538                 glDrawBuffer(GL_FRONT);
1539                 if(but->win==curarea->headwin) curarea->head_swap= WIN_FRONT_OK;
1540                 else curarea->win_swap= WIN_FRONT_OK;
1541         }
1542         
1543         switch (but->type) {
1544
1545         case NUMSLI:
1546         case HSVSLI:
1547         
1548                 but->embossfunc(but->type, but->themecol, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
1549                 ui_draw_text_icon(but);
1550
1551                 x1= (but->x1+but->x2)/2;
1552                 x2= but->x2 - 5.0*but->aspect;
1553                 y1= but->y1 + 2.0*but->aspect;
1554                 y2= but->y2 - 2.0*but->aspect;
1555                 
1556                 value= ui_get_but_val(but);
1557                 fac= (value-but->min)*(x2-x1)/(but->max - but->min);
1558                 
1559                 but->sliderfunc(but->themecol, fac, but->aspect, x1, y1, x2, y2, but->flag);
1560                 break;
1561                 
1562         case SEPR:
1563                 //  only background
1564                 break;
1565                 
1566         case COL:
1567                 ui_draw_but_COL(but);  // black box with color
1568                 break;
1569
1570         case LINK:
1571         case INLINK:
1572                 ui_draw_icon(but, but->icon);
1573                 break;
1574
1575         default:
1576                 but->embossfunc(but->type, but->themecol, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
1577                 ui_draw_text_icon(but);
1578         
1579         }
1580 }
1581