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