remove unused includes
[blender-staging.git] / source / blender / editors / interface / interface_widgets.c
1 /**
2 * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation.
19  * All rights reserved.
20  * 
21  * Contributor(s): Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 #include <limits.h>
27 #include <math.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_screen_types.h"
34 #include "DNA_userdef_types.h"
35
36 #include "BLI_math.h"
37 #include "BLI_listbase.h"
38 #include "BLI_rect.h"
39
40 #include "BKE_context.h"
41 #include "BKE_curve.h"
42 #include "BKE_utildefines.h"
43
44 #include "RNA_access.h"
45
46 #include "BIF_gl.h"
47 #include "BIF_glutil.h"
48
49 #include "BLF_api.h"
50
51 #include "UI_interface.h"
52 #include "UI_interface_icons.h"
53
54
55 #include "interface_intern.h"
56
57 /* ************** widget base functions ************** */
58 /*
59          - in: roundbox codes for corner types and radius
60          - return: array of [size][2][x,y] points, the edges of the roundbox, + UV coords
61  
62          - draw black box with alpha 0 on exact button boundbox
63          - for ever AA step:
64                 - draw the inner part for a round filled box, with color blend codes or texture coords
65                 - draw outline in outline color
66                 - draw outer part, bottom half, extruded 1 pixel to bottom, for emboss shadow
67                 - draw extra decorations
68          - draw background color box with alpha 1 on exact button boundbox
69  
70  */
71
72 /* fill this struct with polygon info to draw AA'ed */
73 /* it has outline, back, and two optional tria meshes */
74
75 typedef struct uiWidgetTrias {
76         int tot;
77         
78         float vec[32][2];
79         int (*index)[3];
80         
81 } uiWidgetTrias;
82
83 typedef struct uiWidgetBase {
84         
85         int totvert, halfwayvert;
86         float outer_v[64][2];
87         float inner_v[64][2];
88         float inner_uv[64][2];
89         
90         short inner, outline, emboss; /* set on/off */
91         short shadedir;
92         
93         uiWidgetTrias tria1;
94         uiWidgetTrias tria2;
95         
96 } uiWidgetBase;
97
98 /* uiWidgetType: for time being only for visual appearance,
99    later, a handling callback can be added too 
100 */
101 typedef struct uiWidgetType {
102         
103         /* pointer to theme color definition */
104         uiWidgetColors *wcol_theme;
105         uiWidgetStateColors *wcol_state;
106         
107         /* converted colors for state */
108         uiWidgetColors wcol;
109         
110         void (*state)(struct uiWidgetType *, int state);
111         void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign);
112         void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign);
113         void (*text)(uiFontStyle *, uiWidgetColors *, uiBut *, rcti *);
114         
115 } uiWidgetType;
116
117
118 /* *********************** draw data ************************** */
119
120 static float cornervec[9][2]= {{0.0, 0.0}, {0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, 
121 {0.707, 0.293}, {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}, {1.0, 1.0}};
122
123 static float jit[8][2]= {{0.468813 , -0.481430}, {-0.155755 , -0.352820}, 
124 {0.219306 , -0.238501},  {-0.393286 , -0.110949}, {-0.024699 , 0.013908}, 
125 {0.343805 , 0.147431}, {-0.272855 , 0.269918}, {0.095909 , 0.388710}};
126
127 static float num_tria_vert[3][2]= { 
128 {-0.352077, 0.532607}, {-0.352077, -0.549313}, {0.330000, -0.008353}};
129
130 static int num_tria_face[1][3]= {
131 {0, 1, 2}};
132
133 static float scroll_circle_vert[16][2]= {
134 {0.382684, 0.923879}, {0.000001, 1.000000}, {-0.382683, 0.923880}, {-0.707107, 0.707107},
135 {-0.923879, 0.382684}, {-1.000000, 0.000000}, {-0.923880, -0.382684}, {-0.707107, -0.707107},
136 {-0.382683, -0.923880}, {0.000000, -1.000000}, {0.382684, -0.923880}, {0.707107, -0.707107},
137 {0.923880, -0.382684}, {1.000000, -0.000000}, {0.923880, 0.382683}, {0.707107, 0.707107}};
138
139 static int scroll_circle_face[14][3]= {
140 {0, 1, 2}, {2, 0, 3}, {3, 0, 15}, {3, 15, 4}, {4, 15, 14}, {4, 14, 5}, {5, 14, 13}, {5, 13, 6}, 
141 {6, 13, 12}, {6, 12, 7}, {7, 12, 11}, {7, 11, 8}, {8, 11, 10}, {8, 10, 9}};
142
143 static float menu_tria_vert[6][2]= {
144 {-0.41, 0.16}, {0.41, 0.16}, {0, 0.82}, 
145 {0, -0.82}, {-0.41, -0.16}, {0.41, -0.16}};
146
147 static int menu_tria_face[2][3]= {{2, 0, 1}, {3, 5, 4}};
148
149 static float check_tria_vert[6][2]= {
150 {-0.578579, 0.253369},  {-0.392773, 0.412794},  {-0.004241, -0.328551}, 
151 {-0.003001, 0.034320},  {1.055313, 0.864744},   {0.866408, 1.026895}};
152
153 static int check_tria_face[4][3]= {
154 {3, 2, 4}, {3, 4, 5}, {1, 0, 3}, {0, 2, 3}};
155
156 /* ************************************************* */
157
158 void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3)
159 {
160         float color[4];
161         int j;
162         
163         glEnable(GL_BLEND);
164         glGetFloatv(GL_CURRENT_COLOR, color);
165         color[3]= 0.125;
166         glColor4fv(color);
167         
168         /* for each AA step */
169         for(j=0; j<8; j++) {
170                 glTranslatef(1.0*jit[j][0], 1.0*jit[j][1], 0.0f);
171
172                 glBegin(GL_POLYGON);
173                 glVertex2f(x1, y1);
174                 glVertex2f(x2, y2);
175                 glVertex2f(x3, y3);
176                 glEnd();
177                 
178                 glTranslatef(-1.0*jit[j][0], -1.0*jit[j][1], 0.0f);
179         }
180
181         glDisable(GL_BLEND);
182         
183 }
184
185 static void widget_init(uiWidgetBase *wtb)
186 {
187         wtb->totvert= wtb->halfwayvert= 0;
188         wtb->tria1.tot= 0;
189         wtb->tria2.tot= 0;
190         
191         wtb->inner= 1;
192         wtb->outline= 1;
193         wtb->emboss= 1;
194         wtb->shadedir= 1;
195 }
196
197 /* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
198 /* return tot */
199 static int round_box_shadow_edges(float (*vert)[2], rcti *rect, float rad, int roundboxalign, float step)
200 {
201         float vec[9][2];
202         float minx, miny, maxx, maxy;
203         int a, tot= 0;
204         
205         rad+= step;
206         
207         if(2.0f*rad > rect->ymax-rect->ymin)
208                 rad= 0.5f*(rect->ymax-rect->ymin);
209         
210         minx= rect->xmin-step;
211         miny= rect->ymin-step;
212         maxx= rect->xmax+step;
213         maxy= rect->ymax+step;
214         
215         /* mult */
216         for(a=0; a<9; a++) {
217                 vec[a][0]= rad*cornervec[a][0]; 
218                 vec[a][1]= rad*cornervec[a][1]; 
219         }
220         
221         /* start with left-top, anti clockwise */
222         if(roundboxalign & 1) {
223                 for(a=0; a<9; a++, tot++) {
224                         vert[tot][0]= minx+rad-vec[a][0];
225                         vert[tot][1]= maxy-vec[a][1];
226                 }
227         }
228         else {
229                 for(a=0; a<9; a++, tot++) {
230                         vert[tot][0]= minx;
231                         vert[tot][1]= maxy;
232                 }
233         }
234         
235         if(roundboxalign & 8) {
236                 for(a=0; a<9; a++, tot++) {
237                         vert[tot][0]= minx+vec[a][1];
238                         vert[tot][1]= miny+rad-vec[a][0];
239                 }
240         }
241         else {
242                 for(a=0; a<9; a++, tot++) {
243                         vert[tot][0]= minx;
244                         vert[tot][1]= miny;
245                 }
246         }
247         
248         if(roundboxalign & 4) {
249                 for(a=0; a<9; a++, tot++) {
250                         vert[tot][0]= maxx-rad+vec[a][0];
251                         vert[tot][1]= miny+vec[a][1];
252                 }
253         }
254         else {
255                 for(a=0; a<9; a++, tot++) {
256                         vert[tot][0]= maxx;
257                         vert[tot][1]= miny;
258                 }
259         }
260         
261         if(roundboxalign & 2) {
262                 for(a=0; a<9; a++, tot++) {
263                         vert[tot][0]= maxx-vec[a][1];
264                         vert[tot][1]= maxy-rad+vec[a][0];
265                 }
266         }
267         else {
268                 for(a=0; a<9; a++, tot++) {
269                         vert[tot][0]= maxx;
270                         vert[tot][1]= maxy;
271                 }
272         }
273         return tot;
274 }
275
276 /* this call has 1 extra arg to allow mask outline */
277 static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, float rad, float radi)
278 {
279         float vec[9][2], veci[9][2];
280         float minx= rect->xmin, miny= rect->ymin, maxx= rect->xmax, maxy= rect->ymax;
281         float minxi= minx + 1.0f; /* boundbox inner */
282         float maxxi= maxx - 1.0f;
283         float minyi= miny + 1.0f;
284         float maxyi= maxy - 1.0f;
285         float facxi= (maxxi!=minxi) ? 1.0f/(maxxi-minxi) : 0.0f; /* for uv, can divide by zero */
286         float facyi= (maxyi!=minyi) ? 1.0f/(maxyi-minyi) : 0.0f;
287         int a, tot= 0, minsize;
288
289         minsize= MIN2(rect->xmax-rect->xmin, rect->ymax-rect->ymin);
290         
291         if(2.0f*rad > minsize)
292                 rad= 0.5f*minsize;
293
294         if(2.0f*(radi+1.0f) > minsize)
295                 radi= 0.5f*minsize - 1.0f;
296         
297         /* mult */
298         for(a=0; a<9; a++) {
299                 veci[a][0]= radi*cornervec[a][0]; 
300                 veci[a][1]= radi*cornervec[a][1]; 
301                 vec[a][0]= rad*cornervec[a][0]; 
302                 vec[a][1]= rad*cornervec[a][1]; 
303         }
304         
305         /* corner left-bottom */
306         if(roundboxalign & 8) {
307                 
308                 for(a=0; a<9; a++, tot++) {
309                         wt->inner_v[tot][0]= minxi+veci[a][1];
310                         wt->inner_v[tot][1]= minyi+radi-veci[a][0];
311                         
312                         wt->outer_v[tot][0]= minx+vec[a][1];
313                         wt->outer_v[tot][1]= miny+rad-vec[a][0];
314                         
315                         wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
316                         wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
317                 }
318         }
319         else {
320                 wt->inner_v[tot][0]= minxi;
321                 wt->inner_v[tot][1]= minyi;
322                 
323                 wt->outer_v[tot][0]= minx;
324                 wt->outer_v[tot][1]= miny;
325
326                 wt->inner_uv[tot][0]= 0.0f;
327                 wt->inner_uv[tot][1]= 0.0f;
328                 
329                 tot++;
330         }
331         
332         /* corner right-bottom */
333         if(roundboxalign & 4) {
334                 
335                 for(a=0; a<9; a++, tot++) {
336                         wt->inner_v[tot][0]= maxxi-radi+veci[a][0];
337                         wt->inner_v[tot][1]= minyi+veci[a][1];
338                         
339                         wt->outer_v[tot][0]= maxx-rad+vec[a][0];
340                         wt->outer_v[tot][1]= miny+vec[a][1];
341                         
342                         wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
343                         wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
344                 }
345         }
346         else {
347                 wt->inner_v[tot][0]= maxxi;
348                 wt->inner_v[tot][1]= minyi;
349                 
350                 wt->outer_v[tot][0]= maxx;
351                 wt->outer_v[tot][1]= miny;
352
353                 wt->inner_uv[tot][0]= 1.0f;
354                 wt->inner_uv[tot][1]= 0.0f;
355                 
356                 tot++;
357         }
358         
359         wt->halfwayvert= tot;
360         
361         /* corner right-top */
362         if(roundboxalign & 2) {
363                 
364                 for(a=0; a<9; a++, tot++) {
365                         wt->inner_v[tot][0]= maxxi-veci[a][1];
366                         wt->inner_v[tot][1]= maxyi-radi+veci[a][0];
367                         
368                         wt->outer_v[tot][0]= maxx-vec[a][1];
369                         wt->outer_v[tot][1]= maxy-rad+vec[a][0];
370                         
371                         wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
372                         wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
373                 }
374         }
375         else {
376                 wt->inner_v[tot][0]= maxxi;
377                 wt->inner_v[tot][1]= maxyi;
378                 
379                 wt->outer_v[tot][0]= maxx;
380                 wt->outer_v[tot][1]= maxy;
381                 
382                 wt->inner_uv[tot][0]= 1.0f;
383                 wt->inner_uv[tot][1]= 1.0f;
384                 
385                 tot++;
386         }
387         
388         /* corner left-top */
389         if(roundboxalign & 1) {
390                 
391                 for(a=0; a<9; a++, tot++) {
392                         wt->inner_v[tot][0]= minxi+radi-veci[a][0];
393                         wt->inner_v[tot][1]= maxyi-veci[a][1];
394                         
395                         wt->outer_v[tot][0]= minx+rad-vec[a][0];
396                         wt->outer_v[tot][1]= maxy-vec[a][1];
397                         
398                         wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
399                         wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
400                 }
401                 
402         }
403         else {
404                 
405                 wt->inner_v[tot][0]= minxi;
406                 wt->inner_v[tot][1]= maxyi;
407                 
408                 wt->outer_v[tot][0]= minx;
409                 wt->outer_v[tot][1]= maxy;
410                 
411                 wt->inner_uv[tot][0]= 0.0f;
412                 wt->inner_uv[tot][1]= 1.0f;
413                 
414                 tot++;
415         }
416                 
417         wt->totvert= tot;
418 }
419
420 static void round_box_edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, float rad)
421 {
422         round_box__edges(wt, roundboxalign, rect, rad, rad-1.0f);
423 }
424
425
426 /* based on button rect, return scaled array of triangles */
427 static void widget_num_tria(uiWidgetTrias *tria, rcti *rect, float triasize, char where)
428 {
429         float centx, centy, sizex, sizey, minsize;
430         int a, i1=0, i2=1;
431         
432         minsize= MIN2(rect->xmax-rect->xmin, rect->ymax-rect->ymin);
433         
434         /* center position and size */
435         centx= (float)rect->xmin + 0.5f*minsize;
436         centy= (float)rect->ymin + 0.5f*minsize;
437         sizex= sizey= -0.5f*triasize*minsize;
438
439         if(where=='r') {
440                 centx= (float)rect->xmax - 0.5f*minsize;
441                 sizex= -sizex;
442         }       
443         else if(where=='t') {
444                 centy= (float)rect->ymax - 0.5f*minsize;
445                 sizey= -sizey;
446                 i2=0; i1= 1;
447         }       
448         else if(where=='b') {
449                 sizex= -sizex;
450                 i2=0; i1= 1;
451         }       
452         
453         for(a=0; a<3; a++) {
454                 tria->vec[a][0]= sizex*num_tria_vert[a][i1] + centx;
455                 tria->vec[a][1]= sizey*num_tria_vert[a][i2] + centy;
456         }
457         
458         tria->tot= 1;
459         tria->index= num_tria_face;
460 }
461
462 static void widget_scroll_circle(uiWidgetTrias *tria, rcti *rect, float triasize, char where)
463 {
464         float centx, centy, sizex, sizey, minsize;
465         int a, i1=0, i2=1;
466         
467         minsize= MIN2(rect->xmax-rect->xmin, rect->ymax-rect->ymin);
468         
469         /* center position and size */
470         centx= (float)rect->xmin + 0.5f*minsize;
471         centy= (float)rect->ymin + 0.5f*minsize;
472         sizex= sizey= -0.5f*triasize*minsize;
473
474         if(where=='r') {
475                 centx= (float)rect->xmax - 0.5f*minsize;
476                 sizex= -sizex;
477         }       
478         else if(where=='t') {
479                 centy= (float)rect->ymax - 0.5f*minsize;
480                 sizey= -sizey;
481                 i2=0; i1= 1;
482         }       
483         else if(where=='b') {
484                 sizex= -sizex;
485                 i2=0; i1= 1;
486         }       
487         
488         for(a=0; a<16; a++) {
489                 tria->vec[a][0]= sizex*scroll_circle_vert[a][i1] + centx;
490                 tria->vec[a][1]= sizey*scroll_circle_vert[a][i2] + centy;
491         }
492         
493         tria->tot= 14;
494         tria->index= scroll_circle_face;
495 }
496
497 static void widget_trias_draw(uiWidgetTrias *tria)
498 {
499         int a;
500         
501         glBegin(GL_TRIANGLES);
502         for(a=0; a<tria->tot; a++) {
503                 glVertex2fv(tria->vec[ tria->index[a][0] ]);
504                 glVertex2fv(tria->vec[ tria->index[a][1] ]);
505                 glVertex2fv(tria->vec[ tria->index[a][2] ]);
506         }
507         glEnd();
508         
509 }
510
511 static void widget_menu_trias(uiWidgetTrias *tria, rcti *rect)
512 {
513         float centx, centy, size, asp;
514         int a;
515                 
516         /* center position and size */
517         centx= rect->xmax - 0.5f*(rect->ymax-rect->ymin);
518         centy= rect->ymin + 0.5f*(rect->ymax-rect->ymin);
519         size= 0.4f*(rect->ymax-rect->ymin);
520         
521         /* XXX exception */
522         asp= ((float)rect->xmax-rect->xmin)/((float)rect->ymax-rect->ymin);
523         if(asp > 1.2f && asp < 2.6f)
524                 centx= rect->xmax - 0.3f*(rect->ymax-rect->ymin);
525         
526         for(a=0; a<6; a++) {
527                 tria->vec[a][0]= size*menu_tria_vert[a][0] + centx;
528                 tria->vec[a][1]= size*menu_tria_vert[a][1] + centy;
529         }
530
531         tria->tot= 2;
532         tria->index= menu_tria_face;
533 }
534
535 static void widget_check_trias(uiWidgetTrias *tria, rcti *rect)
536 {
537         float centx, centy, size;
538         int a;
539         
540         /* center position and size */
541         centx= rect->xmin + 0.5f*(rect->ymax-rect->ymin);
542         centy= rect->ymin + 0.5f*(rect->ymax-rect->ymin);
543         size= 0.5f*(rect->ymax-rect->ymin);
544         
545         for(a=0; a<6; a++) {
546                 tria->vec[a][0]= size*check_tria_vert[a][0] + centx;
547                 tria->vec[a][1]= size*check_tria_vert[a][1] + centy;
548         }
549         
550         tria->tot= 4;
551         tria->index= check_tria_face;
552 }
553
554
555 /* prepares shade colors */
556 static void shadecolors4(char *coltop, char *coldown, char *color, short shadetop, short shadedown)
557 {
558         
559         coltop[0]= CLAMPIS(color[0]+shadetop, 0, 255);
560         coltop[1]= CLAMPIS(color[1]+shadetop, 0, 255);
561         coltop[2]= CLAMPIS(color[2]+shadetop, 0, 255);
562         coltop[3]= color[3];
563
564         coldown[0]= CLAMPIS(color[0]+shadedown, 0, 255);
565         coldown[1]= CLAMPIS(color[1]+shadedown, 0, 255);
566         coldown[2]= CLAMPIS(color[2]+shadedown, 0, 255);
567         coldown[3]= color[3];   
568 }
569
570 static void round_box_shade_col4(char *col1, char *col2, float fac)
571 {
572         int faci, facm;
573         unsigned char col[4];
574         
575         faci= floor(255.1f*fac);
576         facm= 255-faci;
577         
578         col[0]= (faci*col1[0] + facm*col2[0])>>8;
579         col[1]= (faci*col1[1] + facm*col2[1])>>8;
580         col[2]= (faci*col1[2] + facm*col2[2])>>8;
581         col[3]= (faci*col1[3] + facm*col2[3])>>8;
582         
583         glColor4ubv(col);
584 }
585
586 static void widgetbase_outline(uiWidgetBase *wtb)
587 {
588         int a;
589         
590         /* outline */
591         glBegin(GL_QUAD_STRIP);
592         for(a=0; a<wtb->totvert; a++) {
593                 glVertex2fv(wtb->outer_v[a]);
594                 glVertex2fv(wtb->inner_v[a]);
595         }
596         glVertex2fv(wtb->outer_v[0]);
597         glVertex2fv(wtb->inner_v[0]);
598         glEnd();
599 }
600
601 static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
602 {
603         int j, a;
604         
605         glEnable(GL_BLEND);
606
607         /* backdrop non AA */
608         if(wtb->inner) {
609                 if(wcol->shaded==0) {
610                         if (wcol->alpha_check) {
611                                 GLubyte checker_stipple_sml[32*32/8] =
612                                 {
613                                         255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \
614                                         255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \
615                                         0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \
616                                         0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \
617                                         255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \
618                                         255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \
619                                         0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \
620                                         0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \
621                                 };
622
623                                 float x_mid= 0.0f; /* used for dumb clamping of values */
624
625                                 /* dark checkers */
626                                 glColor4ub(100, 100, 100, 255);
627                                 glBegin(GL_POLYGON);
628                                 for(a=0; a<wtb->totvert; a++) {
629                                         glVertex2fv(wtb->inner_v[a]);
630                                 }
631                                 glEnd();
632
633                                 /* light checkers */
634                                 glEnable(GL_POLYGON_STIPPLE);
635                                 glColor4ub(160, 160, 160, 255);
636                                 glPolygonStipple(checker_stipple_sml);
637                                 glBegin(GL_POLYGON);
638                                 for(a=0; a<wtb->totvert; a++) {
639                                         glVertex2fv(wtb->inner_v[a]);
640                                 }
641                                 glEnd();
642                                 glDisable(GL_POLYGON_STIPPLE);
643
644                                 /* alpha fill */
645                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
646
647                                 glColor4ubv((unsigned char*)wcol->inner);
648                                 glBegin(GL_POLYGON);
649                                 for(a=0; a<wtb->totvert; a++) {
650                                         glVertex2fv(wtb->inner_v[a]);
651                                         x_mid += wtb->inner_v[a][0];
652                                 }
653                                 x_mid /= wtb->totvert;
654                                 glEnd();
655
656                                 /* 1/2 solid color */
657                                 glColor4ub(wcol->inner[0], wcol->inner[1], wcol->inner[2], 255);
658                                 glBegin(GL_POLYGON);
659                                 for(a=0; a<wtb->totvert; a++)
660                                         glVertex2f(MIN2(wtb->inner_v[a][0], x_mid), wtb->inner_v[a][1]);
661                                 glEnd();
662                         }
663                         else {
664                                 /* simple fill */
665                                 glColor4ubv((unsigned char*)wcol->inner);
666                                 glBegin(GL_POLYGON);
667                                 for(a=0; a<wtb->totvert; a++)
668                                         glVertex2fv(wtb->inner_v[a]);
669                                 glEnd();
670                         }
671                 }
672                 else {
673                         char col1[4], col2[4];
674                         
675                         shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown);
676                         
677                         glShadeModel(GL_SMOOTH);
678                         glBegin(GL_POLYGON);
679                         for(a=0; a<wtb->totvert; a++) {
680                                 round_box_shade_col4(col1, col2, wtb->inner_uv[a][wtb->shadedir]);
681                                 glVertex2fv(wtb->inner_v[a]);
682                         }
683                         glEnd();
684                         glShadeModel(GL_FLAT);
685                 }
686         }
687         
688         /* for each AA step */
689         if(wtb->outline) {
690                 for(j=0; j<8; j++) {
691                         glTranslatef(1.0*jit[j][0], 1.0*jit[j][1], 0.0f);
692                         
693                         /* outline */
694                         glColor4ub(wcol->outline[0], wcol->outline[1], wcol->outline[2], 32);
695                         glBegin(GL_QUAD_STRIP);
696                         for(a=0; a<wtb->totvert; a++) {
697                                 glVertex2fv(wtb->outer_v[a]);
698                                 glVertex2fv(wtb->inner_v[a]);
699                         }
700                         glVertex2fv(wtb->outer_v[0]);
701                         glVertex2fv(wtb->inner_v[0]);
702                         glEnd();
703                 
704                         /* emboss bottom shadow */
705                         if(wtb->emboss) {
706                                 glColor4f(1.0f, 1.0f, 1.0f, 0.02f);
707                                 glBegin(GL_QUAD_STRIP);
708                                 for(a=0; a<wtb->halfwayvert; a++) {
709                                         glVertex2fv(wtb->outer_v[a]);
710                                         glVertex2f(wtb->outer_v[a][0], wtb->outer_v[a][1]-1.0f);
711                                 }
712                                 glEnd();
713                         }
714                         
715                         glTranslatef(-1.0*jit[j][0], -1.0*jit[j][1], 0.0f);
716                 }
717         }
718         
719         /* decoration */
720         if(wtb->tria1.tot || wtb->tria2.tot) {
721                 /* for each AA step */
722                 for(j=0; j<8; j++) {
723                         glTranslatef(1.0*jit[j][0], 1.0*jit[j][1], 0.0f);
724
725                         if(wtb->tria1.tot) {
726                                 glColor4ub(wcol->item[0], wcol->item[1], wcol->item[2], 32);
727                                 widget_trias_draw(&wtb->tria1);
728                         }
729                         if(wtb->tria2.tot) {
730                                 glColor4ub(wcol->item[0], wcol->item[1], wcol->item[2], 32);
731                                 widget_trias_draw(&wtb->tria2);
732                         }
733                 
734                         glTranslatef(-1.0*jit[j][0], -1.0*jit[j][1], 0.0f);
735                 }
736         }
737
738         glDisable(GL_BLEND);
739         
740 }
741
742 /* *********************** text/icon ************************************** */
743
744 #define PREVIEW_PAD     4
745
746 static void widget_draw_preview(BIFIconID icon, float aspect, float alpha, rcti *rect)
747 {
748         int w, h, x, y, size;
749
750         if(!icon)
751                 return;
752
753         w = rect->xmax - rect->xmin;
754         h = rect->ymax - rect->ymin;
755         size = MIN2(w, h);
756         size -= PREVIEW_PAD*2;  /* padding */
757         
758         x = rect->xmin + w/2 - size/2;
759         y = rect->ymin + h/2 - size/2;
760         
761         UI_icon_draw_preview_aspect_size(x, y, icon, aspect, size);
762 }
763
764
765 /* icons have been standardized... and this call draws in untransformed coordinates */
766 #define ICON_HEIGHT             16.0f
767
768 static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect)
769 {
770         int xs=0, ys=0;
771         float aspect, height;
772         
773         if (but->flag & UI_ICON_PREVIEW) {
774                 widget_draw_preview(icon, but->block->aspect, alpha, rect);
775                 return;
776         }
777         
778         /* this icon doesn't need draw... */
779         if(icon==ICON_BLANK1 && (but->flag & UI_ICON_SUBMENU)==0) return;
780         
781         /* we need aspect from block, for menus... these buttons are scaled in uiPositionBlock() */
782         aspect= but->block->aspect;
783         if(aspect != but->aspect) {
784                 /* prevent scaling up icon in pupmenu */
785                 if (aspect < 1.0f) {                    
786                         height= ICON_HEIGHT;
787                         aspect = 1.0f;
788                         
789                 }
790                 else 
791                         height= ICON_HEIGHT/aspect;
792         }
793         else
794                 height= ICON_HEIGHT;
795         
796         /* calculate blend color */
797         if ELEM4(but->type, TOG, ROW, TOGN, LISTROW) {
798                 if(but->flag & UI_SELECT);
799                 else if(but->flag & UI_ACTIVE);
800                 else alpha= 0.5f;
801         }
802         
803         /* extra feature allows more alpha blending */
804         if(but->type==LABEL && but->a1==1.0f) alpha *= but->a2;
805         
806         glEnable(GL_BLEND);
807         
808         if(icon && icon!=ICON_BLANK1) {
809                 if(but->flag & UI_ICON_LEFT) {
810                         if (but->type==BUT_TOGDUAL) {
811                                 if (but->drawstr[0]) {
812                                         xs= rect->xmin-1;
813                                 } else {
814                                         xs= (rect->xmin+rect->xmax- height)/2;
815                                 }
816                         }
817                         else if (but->block->flag & UI_BLOCK_LOOP) {
818                                 if(but->type==SEARCH_MENU)
819                                         xs= rect->xmin+4;
820                                 else
821                                         xs= rect->xmin+1;
822                         }
823                         else if ((but->type==ICONROW) || (but->type==ICONTEXTROW)) {
824                                 xs= rect->xmin+3;
825                         }
826                         else {
827                                 xs= rect->xmin+4;
828                         }
829                         ys= (rect->ymin+rect->ymax- height)/2;
830                 }
831                 else {
832                         xs= (rect->xmin+rect->xmax- height)/2;
833                         ys= (rect->ymin+rect->ymax- height)/2;
834                 }
835                 
836                 /* to indicate draggable */
837                 if(but->dragpoin && (but->flag & UI_ACTIVE)) {
838                         float rgb[3]= {1.25f, 1.25f, 1.25f};
839                         UI_icon_draw_aspect_color(xs, ys, icon, aspect, rgb);
840                 }
841                 else
842                         UI_icon_draw_aspect(xs, ys, icon, aspect, alpha);
843         }
844         
845         if(but->flag & UI_ICON_SUBMENU) {
846                 xs= rect->xmax-17;
847                 ys= (rect->ymin+rect->ymax- height)/2;
848                 
849                 UI_icon_draw_aspect(xs, ys, ICON_RIGHTARROW_THIN, aspect, alpha);
850         }
851         
852         glDisable(GL_BLEND);
853 }
854
855 /* sets but->ofs to make sure text is correctly visible */
856 static void ui_text_leftclip(uiFontStyle *fstyle, uiBut *but, rcti *rect)
857 {
858         int border= (but->flag & UI_BUT_ALIGN_RIGHT)? 8: 10;
859         int okwidth= rect->xmax-rect->xmin - border;
860         
861         if (but->flag & UI_HAS_ICON) okwidth -= 16;
862         
863         /* need to set this first */
864         uiStyleFontSet(fstyle);
865         
866         if (fstyle->kerning==1) /* for BLF_width */
867                 BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
868
869         but->strwidth= BLF_width(fstyle->uifont_id, but->drawstr);
870         but->ofs= 0;
871         
872         while(but->strwidth > okwidth ) {
873                 
874                 but->ofs++;
875                 but->strwidth= BLF_width(fstyle->uifont_id, but->drawstr+but->ofs);
876                 
877                 /* textbut exception */
878                 if(but->editstr && but->pos != -1) {
879                         int pos= but->pos+1;
880                         
881                         if(pos-1 < but->ofs) {
882                                 pos= but->ofs-pos+1;
883                                 but->ofs -= pos;
884                                 if(but->ofs<0) {
885                                         but->ofs= 0;
886                                         pos--;
887                                 }
888                                 but->drawstr[ strlen(but->drawstr)-pos ]= 0;
889                         }
890                 }
891                 
892                 if(but->strwidth < 10) break;
893         }
894         
895         if (fstyle->kerning==1)
896                 BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
897 }
898
899 static void ui_text_label_rightclip(uiFontStyle *fstyle, uiBut *but, rcti *rect)
900 {
901         int border= (but->flag & UI_BUT_ALIGN_RIGHT)? 8: 10;
902         int okwidth= rect->xmax-rect->xmin - border;
903         char *cpoin=NULL;
904         char *cpend = but->drawstr + strlen(but->drawstr);
905         
906         /* need to set this first */
907         uiStyleFontSet(fstyle);
908         
909         if (fstyle->kerning==1) /* for BLF_width */
910                 BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
911         
912         but->strwidth= BLF_width(fstyle->uifont_id, but->drawstr);
913         but->ofs= 0;
914         
915         /* find the space after ':' separator */
916         cpoin= strrchr(but->drawstr, ':');
917         
918         if (cpoin && (cpoin < cpend-2)) {
919                 char *cp2 = cpoin;
920                 
921                 /* chop off the leading text, starting from the right */
922                 while (but->strwidth > okwidth && cp2 > but->drawstr) {
923                         /* shift the text after and including cp2 back by 1 char, +1 to include null terminator */
924                         memmove(cp2-1, cp2, strlen(cp2)+1);
925                         cp2--;
926                         
927                         but->strwidth= BLF_width(fstyle->uifont_id, but->drawstr+but->ofs);
928                         if(but->strwidth < 10) break;
929                 }
930         
931         
932                 /* after the leading text is gone, chop off the : and following space, with ofs */
933                 while ((but->strwidth > okwidth) && (but->ofs < 2))
934                 {
935                         but->ofs++;
936                         but->strwidth= BLF_width(fstyle->uifont_id, but->drawstr+but->ofs);
937                         if(but->strwidth < 10) break;
938                 }
939                 
940         }
941
942         /* once the label's gone, chop off the least significant digits */
943         while(but->strwidth > okwidth ) {
944                 int pos= strlen(but->drawstr);
945                 
946                 but->drawstr[ pos-1 ] = 0;
947                 pos--;
948                 
949                 but->strwidth= BLF_width(fstyle->uifont_id, but->drawstr+but->ofs);
950                 if(but->strwidth < 10) break;
951         }
952         
953         if (fstyle->kerning==1)
954                 BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
955 }
956
957
958 static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
959 {
960 //      int transopts;
961         char *cpoin = NULL;
962         
963         uiStyleFontSet(fstyle);
964         
965         if(but->editstr || (but->flag & UI_TEXT_LEFT))
966                 fstyle->align= UI_STYLE_TEXT_LEFT;
967         else
968                 fstyle->align= UI_STYLE_TEXT_CENTER;                    
969         
970         if (fstyle->kerning==1) /* for BLF_width */
971                 BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
972         
973         /* text button selection and cursor */
974         if(but->editstr && but->pos != -1) {
975                 short t=0, pos=0, ch;
976                 short selsta_tmp, selend_tmp, selsta_draw, selwidth_draw;
977
978                 if ((but->selend - but->selsta) > 0) {
979                         /* text button selection */
980                         selsta_tmp = but->selsta;
981                         selend_tmp = but->selend;
982                         
983                         if(but->drawstr[0]!=0) {
984
985                                 if (but->selsta >= but->ofs) {
986                                         ch= but->drawstr[selsta_tmp];
987                                         but->drawstr[selsta_tmp]= 0;
988                                         
989                                         selsta_draw = BLF_width(fstyle->uifont_id, but->drawstr+but->ofs);
990                                         
991                                         but->drawstr[selsta_tmp]= ch;
992                                 } else
993                                         selsta_draw = 0;
994                                 
995                                 ch= but->drawstr[selend_tmp];
996                                 but->drawstr[selend_tmp]= 0;
997                                 
998                                 selwidth_draw = BLF_width(fstyle->uifont_id, but->drawstr+but->ofs);
999                                 
1000                                 but->drawstr[selend_tmp]= ch;
1001
1002                                 glColor3ubv((unsigned char*)wcol->item);
1003                                 glRects(rect->xmin+selsta_draw, rect->ymin+2, rect->xmin+selwidth_draw, rect->ymax-2);
1004                         }
1005                 } else {
1006                         /* text cursor */
1007                         pos= but->pos;
1008                         if(pos >= but->ofs) {
1009                                 if(but->drawstr[0]!=0) {
1010                                         ch= but->drawstr[pos];
1011                                         but->drawstr[pos]= 0;
1012                                         
1013                                         t= BLF_width(fstyle->uifont_id, but->drawstr+but->ofs) / but->aspect;
1014                                         
1015                                         but->drawstr[pos]= ch;
1016                                 }
1017
1018                                 glColor3f(0.20, 0.6, 0.9);
1019                                 glRects(rect->xmin+t, rect->ymin+2, rect->xmin+t+2, rect->ymax-2);
1020                         }
1021                 }
1022         }
1023         
1024         if (fstyle->kerning == 1)
1025                 BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
1026         
1027         //      ui_rasterpos_safe(x, y, but->aspect);
1028 //      if(but->type==IDPOIN) transopts= 0;     // no translation, of course!
1029 //      else transopts= ui_translate_buttons();
1030         
1031         /* cut string in 2 parts - only for menu entries */
1032         if((but->block->flag & UI_BLOCK_LOOP)) {
1033                 if(ELEM5(but->type, SLI, NUM, TEX, NUMSLI, NUMABS)==0) {
1034                         cpoin= strchr(but->drawstr, '|');
1035                         if(cpoin) *cpoin= 0;            
1036                 }
1037         }
1038         
1039         glColor3ubv((unsigned char*)wcol->text);
1040         uiStyleFontDraw(fstyle, rect, but->drawstr+but->ofs);
1041
1042         /* part text right aligned */
1043         if(cpoin) {
1044                 fstyle->align= UI_STYLE_TEXT_RIGHT;
1045                 rect->xmax-=5;
1046                 uiStyleFontDraw(fstyle, rect, cpoin+1);
1047                 *cpoin= '|';
1048         }
1049 }
1050
1051 /* draws text and icons for buttons */
1052 static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
1053 {
1054         
1055         if(but==NULL) return;
1056
1057         /* clip but->drawstr to fit in available space */
1058         if (ELEM4(but->type, NUM, NUMABS, NUMSLI, SLI)) {
1059                 ui_text_label_rightclip(fstyle, but, rect);
1060         }
1061         else if (ELEM(but->type, TEX, SEARCH_MENU)) {
1062                 ui_text_leftclip(fstyle, but, rect);
1063         }
1064         else if ((but->block->flag & UI_BLOCK_LOOP) && (but->type == BUT)) {
1065                 ui_text_leftclip(fstyle, but, rect);
1066         }
1067         else but->ofs= 0;
1068         
1069         /* check for button text label */
1070         if (but->type == ICONTEXTROW) {
1071                 widget_draw_icon(but, (BIFIconID) (but->icon+but->iconadd), 1.0f, rect);
1072         }
1073         else {
1074                                 
1075                 if(but->type==BUT_TOGDUAL) {
1076                         int dualset= 0;
1077                         if(but->pointype==SHO)
1078                                 dualset= BTST( *(((short *)but->poin)+1), but->bitnr);
1079                         else if(but->pointype==INT)
1080                                 dualset= BTST( *(((int *)but->poin)+1), but->bitnr);
1081                         
1082                         widget_draw_icon(but, ICON_DOT, dualset?1.0f:0.25f, rect);
1083                 }
1084                 
1085                 /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
1086                 and offset the text label to accommodate it */
1087                 
1088                 if (but->flag & UI_HAS_ICON) {
1089                         widget_draw_icon(but, but->icon+but->iconadd, 1.0f, rect);
1090                         
1091                         rect->xmin += UI_icon_get_width(but->icon+but->iconadd);
1092                         
1093                         if(but->editstr || (but->flag & UI_TEXT_LEFT)) 
1094                                 rect->xmin += 5;
1095                 }
1096                 else if((but->flag & UI_TEXT_LEFT)) 
1097                         rect->xmin += 5;
1098                 
1099                 /* always draw text for textbutton cursor */
1100                 widget_draw_text(fstyle, wcol, but, rect);
1101
1102         }
1103 }
1104
1105
1106
1107 /* *********************** widget types ************************************* */
1108
1109
1110 /*   uiWidgetStateColors
1111  char inner_anim[4];
1112  char inner_anim_sel[4];
1113  char inner_key[4];
1114  char inner_key_sel[4];
1115  char inner_driven[4];
1116  char inner_driven_sel[4];
1117  float blend;
1118  
1119 */
1120
1121 static struct uiWidgetStateColors wcol_state= {
1122         {115, 190, 76, 255},
1123         {90, 166, 51, 255},
1124         {240, 235, 100, 255},
1125         {215, 211, 75, 255},
1126         {180, 0, 255, 255},
1127         {153, 0, 230, 255},
1128         0.5f, 0.0f
1129 };
1130
1131 /*  uiWidgetColors
1132  float outline[3];
1133  float inner[4];
1134  float inner_sel[4];
1135  float item[3];
1136  float text[3];
1137  float text_sel[3];
1138
1139  short shaded;
1140  float shadetop, shadedown;
1141 */      
1142
1143 static struct uiWidgetColors wcol_num= {
1144         {25, 25, 25, 255},
1145         {180, 180, 180, 255},
1146         {153, 153, 153, 255},
1147         {90, 90, 90, 255},
1148         
1149         {0, 0, 0, 255},
1150         {255, 255, 255, 255},
1151         
1152         1,
1153         -20, 0
1154 };
1155
1156 static struct uiWidgetColors wcol_numslider= {
1157         {25, 25, 25, 255},
1158         {180, 180, 180, 255},
1159         {153, 153, 153, 255},
1160         {128, 128, 128, 255},
1161         
1162         {0, 0, 0, 255},
1163         {255, 255, 255, 255},
1164         
1165         1,
1166         -20, 0
1167 };
1168
1169 static struct uiWidgetColors wcol_text= {
1170         {25, 25, 25, 255},
1171         {153, 153, 153, 255},
1172         {153, 153, 153, 255},
1173         {90, 90, 90, 255},
1174         
1175         {0, 0, 0, 255},
1176         {255, 255, 255, 255},
1177         
1178         1,
1179         0, 25
1180 };
1181
1182 static struct uiWidgetColors wcol_option= {
1183         {0, 0, 0, 255},
1184         {70, 70, 70, 255},
1185         {70, 70, 70, 255},
1186         {255, 255, 255, 255},
1187         
1188         {0, 0, 0, 255},
1189         {255, 255, 255, 255},
1190         
1191         1,
1192         15, -15
1193 };
1194
1195 /* button that shows popup */
1196 static struct uiWidgetColors wcol_menu= {
1197         {0, 0, 0, 255},
1198         {70, 70, 70, 255},
1199         {70, 70, 70, 255},
1200         {255, 255, 255, 255},
1201         
1202         {255, 255, 255, 255},
1203         {204, 204, 204, 255},
1204         
1205         1,
1206         15, -15
1207 };
1208
1209 /* button that starts pulldown */
1210 static struct uiWidgetColors wcol_pulldown= {
1211         {0, 0, 0, 255},
1212         {63, 63, 63, 255},
1213         {86, 128, 194, 255},
1214         {255, 255, 255, 255},
1215         
1216         {0, 0, 0, 255},
1217         {0, 0, 0, 255},
1218         
1219         0,
1220         25, -20
1221 };
1222
1223 /* button inside menu */
1224 static struct uiWidgetColors wcol_menu_item= {
1225         {0, 0, 0, 255},
1226         {0, 0, 0, 0},
1227         {86, 128, 194, 255},
1228         {255, 255, 255, 255},
1229         
1230         {255, 255, 255, 255},
1231         {0, 0, 0, 255},
1232         
1233         0,
1234         38, 0
1235 };
1236
1237 /* backdrop menu + title text color */
1238 static struct uiWidgetColors wcol_menu_back= {
1239         {0, 0, 0, 255},
1240         {25, 25, 25, 230},
1241         {45, 45, 45, 230},
1242         {100, 100, 100, 255},
1243         
1244         {160, 160, 160, 255},
1245         {255, 255, 255, 255},
1246         
1247         0,
1248         25, -20
1249 };
1250
1251
1252 static struct uiWidgetColors wcol_radio= {
1253         {0, 0, 0, 255},
1254         {70, 70, 70, 255},
1255         {86, 128, 194, 255},
1256         {255, 255, 255, 255},
1257         
1258         {255, 255, 255, 255},
1259         {0, 0, 0, 255},
1260         
1261         1,
1262         15, -15
1263 };
1264
1265 static struct uiWidgetColors wcol_regular= {
1266         {25, 25, 25, 255},
1267         {153, 153, 153, 255},
1268         {100, 100, 100, 255},
1269         {25, 25, 25, 255},
1270         
1271         {0, 0, 0, 255},
1272         {255, 255, 255, 255},
1273         
1274         0,
1275         0, 0
1276 };
1277
1278 static struct uiWidgetColors wcol_tool= {
1279         {25, 25, 25, 255},
1280         {153, 153, 153, 255},
1281         {100, 100, 100, 255},
1282         {25, 25, 25, 255},
1283         
1284         {0, 0, 0, 255},
1285         {255, 255, 255, 255},
1286         
1287         1,
1288         15, -15
1289 };
1290
1291 static struct uiWidgetColors wcol_box= {
1292         {25, 25, 25, 255},
1293         {128, 128, 128, 255},
1294         {100, 100, 100, 255},
1295         {25, 25, 25, 255},
1296         
1297         {0, 0, 0, 255},
1298         {255, 255, 255, 255},
1299         
1300         0,
1301         0, 0
1302 };
1303
1304 static struct uiWidgetColors wcol_toggle= {
1305         {25, 25, 25, 255},
1306         {153, 153, 153, 255},
1307         {100, 100, 100, 255},
1308         {25, 25, 25, 255},
1309         
1310         {0, 0, 0, 255},
1311         {255, 255, 255, 255},
1312         
1313         0,
1314         0, 0
1315 };
1316
1317 static struct uiWidgetColors wcol_scroll= {
1318         {50, 50, 50, 180},
1319         {80, 80, 80, 180},
1320         {100, 100, 100, 180},
1321         {128, 128, 128, 255},
1322         
1323         {0, 0, 0, 255},
1324         {255, 255, 255, 255},
1325         
1326         1,
1327         5, -5
1328 };
1329
1330 static struct uiWidgetColors wcol_progress= {
1331         {0, 0, 0, 255},
1332         {190, 190, 190, 255},
1333         {100, 100, 100, 180},
1334         {68, 68, 68, 255},
1335         
1336         {0, 0, 0, 255},
1337         {255, 255, 255, 255},
1338         
1339         0,
1340         0, 0
1341 };
1342
1343 static struct uiWidgetColors wcol_list_item= {
1344         {0, 0, 0, 255},
1345         {0, 0, 0, 0},
1346         {86, 128, 194, 255},
1347         {0, 0, 0, 255},
1348         
1349         {0, 0, 0, 255},
1350         {0, 0, 0, 255},
1351         
1352         0,
1353         0, 0
1354 };
1355
1356 /* free wcol struct to play with */
1357 static struct uiWidgetColors wcol_tmp= {
1358         {0, 0, 0, 255},
1359         {128, 128, 128, 255},
1360         {100, 100, 100, 255},
1361         {25, 25, 25, 255},
1362         
1363         {0, 0, 0, 255},
1364         {255, 255, 255, 255},
1365         
1366         0,
1367         0, 0
1368 };
1369
1370
1371 /* called for theme init (new theme) and versions */
1372 void ui_widget_color_init(ThemeUI *tui)
1373 {
1374         tui->wcol_regular= wcol_regular;
1375         tui->wcol_tool= wcol_tool;
1376         tui->wcol_text= wcol_text;
1377         tui->wcol_radio= wcol_radio;
1378         tui->wcol_option= wcol_option;
1379         tui->wcol_toggle= wcol_toggle;
1380         tui->wcol_num= wcol_num;
1381         tui->wcol_numslider= wcol_numslider;
1382         tui->wcol_menu= wcol_menu;
1383         tui->wcol_pulldown= wcol_pulldown;
1384         tui->wcol_menu_back= wcol_menu_back;
1385         tui->wcol_menu_item= wcol_menu_item;
1386         tui->wcol_box= wcol_box;
1387         tui->wcol_scroll= wcol_scroll;
1388         tui->wcol_list_item= wcol_list_item;
1389         tui->wcol_progress= wcol_progress;
1390
1391         tui->wcol_state= wcol_state;
1392 }
1393
1394 /* ************ button callbacks, state ***************** */
1395
1396 static void widget_state_blend(char *cp, char *cpstate, float fac)
1397 {
1398         if(fac != 0.0f) {
1399                 cp[0]= (int)((1.0f-fac)*cp[0] + fac*cpstate[0]);
1400                 cp[1]= (int)((1.0f-fac)*cp[1] + fac*cpstate[1]);
1401                 cp[2]= (int)((1.0f-fac)*cp[2] + fac*cpstate[2]);
1402         }
1403 }
1404
1405 /* copy colors from theme, and set changes in it based on state */
1406 static void widget_state(uiWidgetType *wt, int state)
1407 {
1408         uiWidgetStateColors *wcol_state= wt->wcol_state;
1409
1410         wt->wcol= *(wt->wcol_theme);
1411         
1412         if(state & UI_SELECT) {
1413                 QUATCOPY(wt->wcol.inner, wt->wcol.inner_sel)
1414
1415                 if(state & UI_BUT_ANIMATED_KEY)
1416                         widget_state_blend(wt->wcol.inner, wcol_state->inner_key_sel, wcol_state->blend);
1417                 else if(state & UI_BUT_ANIMATED)
1418                         widget_state_blend(wt->wcol.inner, wcol_state->inner_anim_sel, wcol_state->blend);
1419                 else if(state & UI_BUT_DRIVEN)
1420                         widget_state_blend(wt->wcol.inner, wcol_state->inner_driven_sel, wcol_state->blend);
1421
1422                 VECCOPY(wt->wcol.text, wt->wcol.text_sel);
1423                 
1424                 if (!(state & UI_TEXTINPUT))
1425                         /* swap for selection - show depressed */
1426                         SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
1427         }
1428         else {
1429                 if(state & UI_BUT_ANIMATED_KEY)
1430                         widget_state_blend(wt->wcol.inner, wcol_state->inner_key, wcol_state->blend);
1431                 else if(state & UI_BUT_ANIMATED)
1432                         widget_state_blend(wt->wcol.inner, wcol_state->inner_anim, wcol_state->blend);
1433                 else if(state & UI_BUT_DRIVEN)
1434                         widget_state_blend(wt->wcol.inner, wcol_state->inner_driven, wcol_state->blend);
1435
1436                 if(state & UI_ACTIVE) { /* mouse over? */
1437                         wt->wcol.inner[0]= wt->wcol.inner[0]>=240? 255 : wt->wcol.inner[0]+15;
1438                         wt->wcol.inner[1]= wt->wcol.inner[1]>=240? 255 : wt->wcol.inner[1]+15;
1439                         wt->wcol.inner[2]= wt->wcol.inner[2]>=240? 255 : wt->wcol.inner[2]+15;
1440                 }
1441         }
1442 }
1443
1444 /* sliders use special hack which sets 'item' as inner when drawing filling */
1445 static void widget_state_numslider(uiWidgetType *wt, int state)
1446 {
1447         uiWidgetStateColors *wcol_state= wt->wcol_state;
1448         float blend= wcol_state->blend - 0.2f; // XXX special tweak to make sure that bar will still be visible
1449
1450         /* call this for option button */
1451         widget_state(wt, state);
1452         
1453         /* now, set the inner-part so that it reflects state settings too */
1454         // TODO: maybe we should have separate settings for the blending colors used for this case?
1455         if(state & UI_SELECT) {
1456                 if(state & UI_BUT_ANIMATED_KEY)
1457                         widget_state_blend(wt->wcol.item, wcol_state->inner_key_sel, blend);
1458                 else if(state & UI_BUT_ANIMATED)
1459                         widget_state_blend(wt->wcol.item, wcol_state->inner_anim_sel, blend);
1460                 else if(state & UI_BUT_DRIVEN)
1461                         widget_state_blend(wt->wcol.item, wcol_state->inner_driven_sel, blend);
1462         }
1463         else {
1464                 if(state & UI_BUT_ANIMATED_KEY)
1465                         widget_state_blend(wt->wcol.item, wcol_state->inner_key, blend);
1466                 else if(state & UI_BUT_ANIMATED)
1467                         widget_state_blend(wt->wcol.item, wcol_state->inner_anim, blend);
1468                 else if(state & UI_BUT_DRIVEN)
1469                         widget_state_blend(wt->wcol.item, wcol_state->inner_driven, blend);
1470         }
1471 }
1472
1473 /* labels use theme colors for text */
1474 static void widget_state_label(uiWidgetType *wt, int state)
1475 {
1476         /* call this for option button */
1477         widget_state(wt, state);
1478
1479         if(state & UI_SELECT)
1480                 UI_GetThemeColor4ubv(TH_TEXT_HI, wt->wcol.text);
1481         else
1482                 UI_GetThemeColor4ubv(TH_TEXT, wt->wcol.text);
1483         
1484 }
1485
1486 static void widget_state_nothing(uiWidgetType *wt, int state)
1487 {
1488         wt->wcol= *(wt->wcol_theme);
1489 }       
1490
1491 /* special case, button that calls pulldown */
1492 static void widget_state_pulldown(uiWidgetType *wt, int state)
1493 {
1494         wt->wcol= *(wt->wcol_theme);
1495         
1496         QUATCOPY(wt->wcol.inner, wt->wcol.inner_sel);
1497         VECCOPY(wt->wcol.outline, wt->wcol.inner);
1498
1499         if(state & UI_ACTIVE)
1500                 VECCOPY(wt->wcol.text, wt->wcol.text_sel);
1501 }
1502
1503 /* special case, menu items */
1504 static void widget_state_menu_item(uiWidgetType *wt, int state)
1505 {
1506         wt->wcol= *(wt->wcol_theme);
1507         
1508         if(state & (UI_BUT_DISABLED|UI_BUT_INACTIVE)) {
1509                 wt->wcol.text[0]= 0.5f*(wt->wcol.text[0]+wt->wcol.text_sel[0]);
1510                 wt->wcol.text[1]= 0.5f*(wt->wcol.text[1]+wt->wcol.text_sel[1]);
1511                 wt->wcol.text[2]= 0.5f*(wt->wcol.text[2]+wt->wcol.text_sel[2]);
1512         }
1513         else if(state & UI_ACTIVE) {
1514                 QUATCOPY(wt->wcol.inner, wt->wcol.inner_sel);
1515                 VECCOPY(wt->wcol.text, wt->wcol.text_sel);
1516                 
1517                 wt->wcol.shaded= 1;
1518         }
1519 }
1520
1521
1522 /* ************ menu backdrop ************************* */
1523
1524 /* outside of rect, rad to left/bottom/right */
1525 static void widget_softshadow(rcti *rect, int roundboxalign, float radin, float radout)
1526 {
1527         uiWidgetBase wtb;
1528         rcti rect1= *rect;
1529         float alpha, alphastep;
1530         int step, tot, a;
1531         
1532         /* prevent tooltips to not show round shadow */
1533         if( 2.0f*radout > 0.2f*(rect1.ymax-rect1.ymin) )
1534                 rect1.ymax -= 0.2f*(rect1.ymax-rect1.ymin);
1535         else
1536                 rect1.ymax -= 2.0f*radout;
1537         
1538         /* inner part */
1539         tot= round_box_shadow_edges(wtb.inner_v, &rect1, radin, roundboxalign & 12, 0.0f);
1540         
1541         /* inverse linear shadow alpha */
1542         alpha= 0.15;
1543         alphastep= 0.67;
1544         
1545         for(step= 1; step<=radout; step++, alpha*=alphastep) {
1546                 round_box_shadow_edges(wtb.outer_v, &rect1, radin, 15, (float)step);
1547                 
1548                 glColor4f(0.0f, 0.0f, 0.0f, alpha);
1549                 
1550                 glBegin(GL_QUAD_STRIP);
1551                 for(a=0; a<tot; a++) {
1552                         glVertex2fv(wtb.outer_v[a]);
1553                         glVertex2fv(wtb.inner_v[a]);
1554                 }
1555                 glEnd();
1556         }
1557         
1558 }
1559
1560 static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction)
1561 {
1562         uiWidgetBase wtb;
1563         int roundboxalign= 15;
1564         
1565         widget_init(&wtb);
1566         
1567         /* menu is 2nd level or deeper */
1568         if (flag & UI_BLOCK_POPUP) {
1569                 //rect->ymin -= 4.0;
1570                 //rect->ymax += 4.0;
1571         }
1572         else if (direction == UI_DOWN) {
1573                 roundboxalign= 12;
1574                 rect->ymin -= 4.0;
1575         } 
1576         else if (direction == UI_TOP) {
1577                 roundboxalign= 3;
1578                 rect->ymax += 4.0;
1579         }
1580         
1581         glEnable(GL_BLEND);
1582         widget_softshadow(rect, roundboxalign, 5.0f, 8.0f);
1583         
1584         round_box_edges(&wtb, roundboxalign, rect, 5.0f);
1585         wtb.emboss= 0;
1586         widgetbase_draw(&wtb, wcol);
1587         
1588         glDisable(GL_BLEND);
1589 }
1590
1591
1592 static void ui_hsv_cursor(float x, float y)
1593 {
1594         
1595         glPushMatrix();
1596         glTranslatef(x, y, 0.0f);
1597         
1598         glColor3f(1.0f, 1.0f, 1.0f);
1599         glutil_draw_filled_arc(0.0f, M_PI*2.0, 3.0f, 8);
1600         
1601         glEnable(GL_BLEND);
1602         glEnable(GL_LINE_SMOOTH );
1603         glColor3f(0.0f, 0.0f, 0.0f);
1604         glutil_draw_lined_arc(0.0f, M_PI*2.0, 3.0f, 12);
1605         glDisable(GL_BLEND);
1606         glDisable(GL_LINE_SMOOTH );
1607         
1608         glPopMatrix();
1609         
1610 }
1611
1612 void ui_hsvcircle_vals_from_pos(float *valrad, float *valdist, rcti *rect, float mx, float my)
1613 {
1614         /* duplication of code... well, simple is better now */
1615         float centx= (float)(rect->xmin + rect->xmax)/2;
1616         float centy= (float)(rect->ymin + rect->ymax)/2;
1617         float radius, dist;
1618         
1619         if( rect->xmax-rect->xmin > rect->ymax-rect->ymin )
1620                 radius= (float)(rect->ymax - rect->ymin)/2; 
1621         else
1622                 radius= (float)(rect->xmax - rect->xmin)/2; 
1623
1624         mx-= centx;
1625         my-= centy;
1626         dist= sqrt( mx*mx + my*my);
1627         if(dist < radius)
1628                 *valdist= dist/radius;
1629         else
1630                 *valdist= 1.0f;
1631         
1632         *valrad= atan2(mx, my)/(2.0f*M_PI) + 0.5f;
1633 }
1634
1635 void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect)
1636 {
1637         /* gouraud triangle fan */
1638         float radstep, ang= 0.0f;
1639         float centx, centy, radius;
1640         float rgb[3], hsv[3], hsvo[3], col[3], colcent[3];
1641         int a, tot= 32;
1642         
1643         radstep= 2.0f*M_PI/(float)tot;
1644         centx= (float)(rect->xmin + rect->xmax)/2;
1645         centy= (float)(rect->ymin + rect->ymax)/2;
1646         
1647         if( rect->xmax-rect->xmin > rect->ymax-rect->ymin )
1648                 radius= (float)(rect->ymax - rect->ymin)/2; 
1649         else
1650                 radius= (float)(rect->xmax - rect->xmin)/2; 
1651         
1652         /* color */
1653         ui_get_but_vectorf(but, rgb);
1654         rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
1655         copy_v3_v3(hsvo, hsv);
1656         
1657         /* exception: if 'lock' is set
1658          * lock the value of the color wheel to 1.
1659          * Useful for color correction tools where you're only interested in hue. */
1660         if (but->flag & UI_BUT_COLOR_LOCK) hsv[2] = 1.f;
1661         
1662         hsv_to_rgb(0.f, 0.f, hsv[2], colcent, colcent+1, colcent+2);
1663         
1664         glShadeModel(GL_SMOOTH);
1665
1666         glBegin(GL_TRIANGLE_FAN);
1667         glColor3fv(colcent);
1668         glVertex2f( centx, centy);
1669         
1670         for(a=0; a<=tot; a++, ang+=radstep) {
1671                 float si= sin(ang);
1672                 float co= cos(ang);
1673                 
1674                 ui_hsvcircle_vals_from_pos(hsv, hsv+1, rect, centx + co*radius, centy + si*radius);
1675                 CLAMP(hsv[2], 0.0f, 1.0f); /* for display only */
1676
1677                 hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2);
1678                 glColor3fv(col);
1679                 glVertex2f( centx + co*radius, centy + si*radius);
1680         }
1681         glEnd();
1682         
1683         glShadeModel(GL_FLAT);
1684         
1685         /* fully rounded outline */
1686         glPushMatrix();
1687         glTranslatef(centx, centy, 0.0f);
1688         glEnable(GL_BLEND);
1689         glEnable(GL_LINE_SMOOTH );
1690         glColor3ubv((unsigned char*)wcol->outline);
1691         glutil_draw_lined_arc(0.0f, M_PI*2.0, radius, tot + 1);
1692         glDisable(GL_BLEND);
1693         glDisable(GL_LINE_SMOOTH );
1694         glPopMatrix();
1695
1696         /* cursor */
1697         ang= 2.0f*M_PI*hsvo[0] + 0.5f*M_PI;
1698
1699         if(but->flag & UI_BUT_COLOR_CUBIC)
1700                 radius= (1.0f - pow(1.0f - hsvo[1], 3.0f)) *radius;
1701         else
1702                 radius= hsvo[1] * radius;
1703
1704         ui_hsv_cursor(centx + cos(-ang)*radius, centy + sin(-ang)*radius);
1705         
1706 }
1707
1708 /* ************ custom buttons, old stuff ************** */
1709
1710 /* draws in resolution of 20x4 colors */
1711 void ui_draw_gradient(rcti *rect, float *rgb, int type, float alpha)
1712 {
1713         int a;
1714         float h, s, v;
1715         float dx, dy, sx1, sx2, sy;
1716         float col0[4][3];       // left half, rect bottom to top
1717         float col1[4][3];       // right half, rect bottom to top
1718         
1719         rgb_to_hsv(rgb[0], rgb[1], rgb[2], &h, &s, &v);
1720         
1721         /* draw series of gouraud rects */
1722         glShadeModel(GL_SMOOTH);
1723         
1724         switch(type) {
1725                 case UI_GRAD_SV:
1726                         hsv_to_rgb(h, 0.0, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1727                         hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]);
1728                         hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
1729                         hsv_to_rgb(h, 1.0, 0.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1730                         break;
1731                 case UI_GRAD_HV:
1732                         hsv_to_rgb(0.0, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1733                         hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
1734                         hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
1735                         hsv_to_rgb(0.0, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1736                         break;
1737                 case UI_GRAD_HS:
1738                         hsv_to_rgb(0.0, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
1739                         hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
1740                         hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
1741                         hsv_to_rgb(0.0, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
1742                         break;
1743                 case UI_GRAD_H:
1744                         hsv_to_rgb(0.0, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1745                         VECCOPY(col1[1], col1[0]);
1746                         VECCOPY(col1[2], col1[0]);
1747                         VECCOPY(col1[3], col1[0]);
1748                         break;
1749                 case UI_GRAD_S:
1750                         hsv_to_rgb(1.0, 0.0, 1.0,   &col1[1][0], &col1[1][1], &col1[1][2]);
1751                         VECCOPY(col1[0], col1[1]);
1752                         VECCOPY(col1[2], col1[1]);
1753                         VECCOPY(col1[3], col1[1]);
1754                         break;
1755                 case UI_GRAD_V:
1756                         hsv_to_rgb(1.0, 1.0, 0.0,   &col1[2][0], &col1[2][1], &col1[2][2]);
1757                         VECCOPY(col1[0], col1[2]);
1758                         VECCOPY(col1[1], col1[2]);
1759                         VECCOPY(col1[3], col1[2]);
1760                         break;
1761         }
1762         
1763         /* old below */
1764         
1765         for(dx=0.0; dx<1.0; dx+= 0.05) {
1766                 // previous color
1767                 VECCOPY(col0[0], col1[0]);
1768                 VECCOPY(col0[1], col1[1]);
1769                 VECCOPY(col0[2], col1[2]);
1770                 VECCOPY(col0[3], col1[3]);
1771                 
1772                 // new color
1773                 switch(type) {
1774                         case UI_GRAD_SV:
1775                                 hsv_to_rgb(h, 0.0, dx,   &col1[0][0], &col1[0][1], &col1[0][2]);
1776                                 hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]);
1777                                 hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
1778                                 hsv_to_rgb(h, 1.0, dx,   &col1[3][0], &col1[3][1], &col1[3][2]);
1779                                 break;
1780                         case UI_GRAD_HV:
1781                                 hsv_to_rgb(dx, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1782                                 hsv_to_rgb(dx, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
1783                                 hsv_to_rgb(dx, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
1784                                 hsv_to_rgb(dx, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1785                                 break;
1786                         case UI_GRAD_HS:
1787                                 hsv_to_rgb(dx, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
1788                                 hsv_to_rgb(dx, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
1789                                 hsv_to_rgb(dx, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
1790                                 hsv_to_rgb(dx, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
1791                                 break;
1792                         case UI_GRAD_H:
1793                                 hsv_to_rgb(dx, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1794                                 VECCOPY(col1[1], col1[0]);
1795                                 VECCOPY(col1[2], col1[0]);
1796                                 VECCOPY(col1[3], col1[0]);
1797                                 break;
1798                         case UI_GRAD_S:
1799                                 hsv_to_rgb(h, dx, 1.0,   &col1[1][0], &col1[1][1], &col1[1][2]);
1800                                 VECCOPY(col1[0], col1[1]);
1801                                 VECCOPY(col1[2], col1[1]);
1802                                 VECCOPY(col1[3], col1[1]);
1803                                 break;
1804                         case UI_GRAD_V:
1805                                 hsv_to_rgb(h, 1.0, dx,   &col1[2][0], &col1[2][1], &col1[2][2]);
1806                                 VECCOPY(col1[0], col1[2]);
1807                                 VECCOPY(col1[1], col1[2]);
1808                                 VECCOPY(col1[3], col1[2]);
1809                                 break;
1810                 }
1811                 
1812                 // rect
1813                 sx1= rect->xmin + dx*(rect->xmax-rect->xmin);
1814                 sx2= rect->xmin + (dx+0.05)*(rect->xmax-rect->xmin);
1815                 sy= rect->ymin;
1816                 dy= (rect->ymax-rect->ymin)/3.0;
1817                 
1818                 glBegin(GL_QUADS);
1819                 for(a=0; a<3; a++, sy+=dy) {
1820                         glColor4f(col0[a][0], col0[a][1], col0[a][2], alpha);
1821                         glVertex2f(sx1, sy);
1822                         
1823                         glColor4f(col1[a][0], col1[a][1], col1[a][2], alpha);
1824                         glVertex2f(sx2, sy);
1825
1826                         glColor4f(col1[a+1][0], col1[a+1][1], col1[a+1][2], alpha);
1827                         glVertex2f(sx2, sy+dy);
1828                         
1829                         glColor4f(col0[a+1][0], col0[a+1][1], col0[a+1][2], alpha);
1830                         glVertex2f(sx1, sy+dy);
1831                 }
1832                 glEnd();
1833         }
1834         
1835         glShadeModel(GL_FLAT);
1836         
1837 }
1838
1839
1840
1841 static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect)
1842 {
1843         float rgb[3], h,s,v;
1844         float x=0.0f, y=0.0f;
1845         
1846         ui_get_but_vectorf(but, rgb);
1847         rgb_to_hsv(rgb[0], rgb[1], rgb[2], &h, &s, &v);
1848         
1849         ui_draw_gradient(rect, rgb, but->a1, 1.f);
1850         
1851         switch((int)but->a1) {
1852                 case UI_GRAD_SV:
1853                         x= v; y= s; break;
1854                 case UI_GRAD_HV:
1855                         x= h; y= v; break;
1856                 case UI_GRAD_HS:
1857                         x= h; y= s; break;
1858                 case UI_GRAD_H:
1859                         x= h; y= 0.5; break;
1860                 case UI_GRAD_S:
1861                         x= s; y= 0.5; break;
1862                 case UI_GRAD_V:
1863                         x= v; y= 0.5; break;
1864         }
1865         
1866         /* cursor */
1867         x= rect->xmin + x*(rect->xmax-rect->xmin);
1868         y= rect->ymin + y*(rect->ymax-rect->ymin);
1869         CLAMP(x, rect->xmin+3.0, rect->xmax-3.0);
1870         CLAMP(y, rect->ymin+3.0, rect->ymax-3.0);
1871         
1872         ui_hsv_cursor(x, y);
1873         
1874         /* outline */
1875         glColor3ub(0,  0,  0);
1876         fdrawbox((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
1877 }
1878
1879 /* vertical 'value' slider, using new widget code */
1880 static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
1881 {
1882         uiWidgetBase wtb;
1883         float rad= 0.5f*(rect->xmax - rect->xmin);
1884         float x, y;
1885         float rgb[3], hsv[3], v, range;
1886         int color_profile = but->block->color_profile;
1887         
1888         if (but->rnaprop) {
1889                 if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
1890                         color_profile = BLI_PR_NONE;
1891                 }
1892         }
1893
1894         ui_get_but_vectorf(but, rgb);
1895         rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
1896         v = hsv[2];
1897         
1898         if (color_profile)
1899                 v = linearrgb_to_srgb(v);
1900
1901         /* map v from property range to [0,1] */
1902         range = but->softmax - but->softmin;
1903         v =     (v - but->softmin)/range;
1904         
1905         widget_init(&wtb);
1906         
1907         /* fully rounded */
1908         round_box_edges(&wtb, 15, rect, rad);
1909         
1910         /* setup temp colors */
1911         wcol_tmp.outline[0]= wcol_tmp.outline[1]= wcol_tmp.outline[2]= 0;
1912         wcol_tmp.inner[0]= wcol_tmp.inner[1]= wcol_tmp.inner[2]= 128;
1913         wcol_tmp.shadetop= 127;
1914         wcol_tmp.shadedown= -128;
1915         wcol_tmp.shaded= 1;
1916         
1917         widgetbase_draw(&wtb, &wcol_tmp);
1918
1919         /* cursor */
1920         x= rect->xmin + 0.5f * (rect->xmax-rect->xmin);
1921         y= rect->ymin + v * (rect->ymax-rect->ymin);
1922         CLAMP(y, rect->ymin+3.0, rect->ymax-3.0);
1923         
1924         ui_hsv_cursor(x, y);
1925         
1926 }
1927
1928
1929 /* ************ separator, for menus etc ***************** */
1930 static void ui_draw_separator(uiBut *but, rcti *rect,  uiWidgetColors *wcol)
1931 {
1932         int y = rect->ymin + (rect->ymax - rect->ymin)/2 - 1;
1933         unsigned char col[4];
1934         
1935         col[0] = wcol->text[0];
1936         col[1] = wcol->text[1];
1937         col[2] = wcol->text[2];
1938         col[3] = 7;
1939         
1940         glEnable(GL_BLEND);
1941         glColor4ubv(col);
1942         sdrawline(rect->xmin, y, rect->xmax, y);
1943         glDisable(GL_BLEND);
1944 }
1945
1946 /* ************ button callbacks, draw ***************** */
1947
1948 static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
1949 {
1950         uiWidgetBase wtb;
1951         float rad= 0.5f*(rect->ymax - rect->ymin);
1952         float textofs = rad*0.75;
1953
1954         widget_init(&wtb);
1955         
1956         /* fully rounded */
1957         round_box_edges(&wtb, roundboxalign, rect, rad);
1958         
1959         /* decoration */
1960         if(!(state & UI_TEXTINPUT)) {
1961                 widget_num_tria(&wtb.tria1, rect, 0.6f, 'l');
1962                 widget_num_tria(&wtb.tria2, rect, 0.6f, 'r');
1963         }
1964
1965         widgetbase_draw(&wtb, wcol);
1966         
1967         /* text space */
1968         rect->xmin += textofs;
1969         rect->xmax -= textofs;
1970 }
1971
1972 //static int ui_link_bezier_points(rcti *rect, float coord_array[][2], int resol)
1973 int ui_link_bezier_points(rcti *rect, float coord_array[][2], int resol)
1974 {
1975         float dist, vec[4][2];
1976
1977         vec[0][0]= rect->xmin;
1978         vec[0][1]= rect->ymin;
1979         vec[3][0]= rect->xmax;
1980         vec[3][1]= rect->ymax;
1981         
1982         dist= 0.5f*ABS(vec[0][0] - vec[3][0]);
1983         
1984         vec[1][0]= vec[0][0]+dist;
1985         vec[1][1]= vec[0][1];
1986         
1987         vec[2][0]= vec[3][0]-dist;
1988         vec[2][1]= vec[3][1];
1989         
1990         forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, sizeof(float)*2);
1991         forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0]+1, resol, sizeof(float)*2);
1992         
1993         return 1;
1994 }
1995
1996 #define LINK_RESOL      24
1997 void ui_draw_link_bezier(rcti *rect)
1998 {
1999         float coord_array[LINK_RESOL+1][2];
2000         
2001         if(ui_link_bezier_points(rect, coord_array, LINK_RESOL)) {
2002                 float dist;
2003                 int i;
2004                 
2005                 /* we can reuse the dist variable here to increment the GL curve eval amount*/
2006                 dist = 1.0f/(float)LINK_RESOL;
2007                 
2008                 glEnable(GL_BLEND);
2009                 glEnable(GL_LINE_SMOOTH);
2010                 
2011                 glBegin(GL_LINE_STRIP);
2012                 for(i=0; i<=LINK_RESOL; i++) {
2013                         glVertex2fv(coord_array[i]);
2014                 }
2015                 glEnd();
2016                 
2017                 glDisable(GL_BLEND);
2018                 glDisable(GL_LINE_SMOOTH);
2019
2020         }
2021 }
2022
2023 /* function in use for buttons and for view2d sliders */
2024 void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int state)
2025 {
2026         uiWidgetBase wtb;
2027         float rad;
2028         int horizontal;
2029         short outline=0;
2030
2031         widget_init(&wtb);
2032
2033         /* determine horizontal/vertical */
2034         horizontal= (rect->xmax - rect->xmin > rect->ymax - rect->ymin);
2035         
2036         if(horizontal)
2037                 rad= 0.5f*(rect->ymax - rect->ymin);
2038         else
2039                 rad= 0.5f*(rect->xmax - rect->xmin);
2040         
2041         wtb.shadedir= (horizontal)? 1: 0;
2042         
2043         /* draw back part, colors swapped and shading inverted */
2044         if(horizontal)
2045                 SWAP(short, wcol->shadetop, wcol->shadedown);
2046         
2047         round_box_edges(&wtb, 15, rect, rad); 
2048         widgetbase_draw(&wtb, wcol);
2049         
2050         /* slider */
2051         if(slider->xmax-slider->xmin<2 || slider->ymax-slider->ymin<2);
2052         else {
2053                 
2054                 SWAP(short, wcol->shadetop, wcol->shadedown);
2055                 
2056                 QUATCOPY(wcol->inner, wcol->item);
2057                 
2058                 if(wcol->shadetop>wcol->shadedown)
2059                         wcol->shadetop+= 20;    /* XXX violates themes... */
2060                 else wcol->shadedown+= 20;
2061                 
2062                 if(state & UI_SCROLL_PRESSED) {
2063                         wcol->inner[0]= wcol->inner[0]>=250? 255 : wcol->inner[0]+5;
2064                         wcol->inner[1]= wcol->inner[1]>=250? 255 : wcol->inner[1]+5;
2065                         wcol->inner[2]= wcol->inner[2]>=250? 255 : wcol->inner[2]+5;
2066                 }
2067
2068                 /* draw */
2069                 wtb.emboss= 0; /* only emboss once */
2070                 
2071                 /* exception for progress bar */
2072                 if (state & UI_SCROLL_NO_OUTLINE)       
2073                         SWAP(short, outline, wtb.outline);
2074                 
2075                 round_box_edges(&wtb, 15, slider, rad); 
2076                 
2077                 if(state & UI_SCROLL_ARROWS) {
2078                         if(wcol->item[0] > 48) wcol->item[0]-= 48;
2079                         if(wcol->item[1] > 48) wcol->item[1]-= 48;
2080                         if(wcol->item[2] > 48) wcol->item[2]-= 48;
2081                         wcol->item[3]= 255;
2082                         
2083                         if(horizontal) {
2084                                 widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
2085                                 widget_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
2086                         }
2087                         else {
2088                                 widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
2089                                 widget_scroll_circle(&wtb.tria2, slider, 0.6f, 't');
2090                         }
2091                 }
2092                 widgetbase_draw(&wtb, wcol);
2093                 
2094                 if (state & UI_SCROLL_NO_OUTLINE)
2095                         SWAP(short, outline, wtb.outline);
2096         }       
2097 }
2098
2099 static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2100 {
2101         rcti rect1;
2102         double value;
2103         float fac, size, min;
2104         int horizontal;
2105
2106         /* calculate slider part */
2107         value= ui_get_but_val(but);
2108
2109         size= (but->softmax + but->a1 - but->softmin);
2110         size= MAX2(size, 2);
2111         
2112         /* position */
2113         rect1= *rect;
2114
2115         /* determine horizontal/vertical */
2116         horizontal= (rect->xmax - rect->xmin > rect->ymax - rect->ymin);
2117         
2118         if(horizontal) {
2119                 fac= (rect->xmax - rect->xmin)/(size);
2120                 rect1.xmin= rect1.xmin + ceil(fac*(value - but->softmin));
2121                 rect1.xmax= rect1.xmin + ceil(fac*(but->a1 - but->softmin));
2122
2123                 /* ensure minimium size */
2124                 min= rect->ymax - rect->ymin;
2125
2126                 if(rect1.xmax - rect1.xmin < min) {
2127                         rect1.xmax= rect1.xmin + min;
2128
2129                         if(rect1.xmax > rect->xmax) {
2130                                 rect1.xmax= rect->xmax;
2131                                 rect1.xmin= MAX2(rect1.xmax - min, rect->xmin);
2132                         }
2133                 }
2134         }
2135         else {
2136                 fac= (rect->ymax - rect->ymin)/(size);
2137                 rect1.ymax= rect1.ymax - ceil(fac*(value - but->softmin));
2138                 rect1.ymin= rect1.ymax - ceil(fac*(but->a1 - but->softmin));
2139
2140                 /* ensure minimium size */
2141                 min= rect->xmax - rect->xmin;
2142
2143                 if(rect1.ymax - rect1.ymin < min) {
2144                         rect1.ymax= rect1.ymin + min;
2145
2146                         if(rect1.ymax > rect->ymax) {
2147                                 rect1.ymax= rect->ymax;
2148                                 rect1.ymin= MAX2(rect1.ymax - min, rect->ymin);
2149                         }
2150                 }
2151         }
2152
2153         if(state & UI_SELECT)
2154                 state= UI_SCROLL_PRESSED;
2155         else
2156                 state= 0;
2157         uiWidgetScrollDraw(wcol, rect, &rect1, state);
2158 }
2159
2160 static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2161 {
2162         rcti rect_prog = *rect, rect_bar = *rect;
2163         float value = but->a1;
2164         float w, min;
2165         
2166         /* make the progress bar a proportion of the original height */
2167         /* hardcoded 4px high for now */
2168         rect_prog.ymax = rect_prog.ymin + 4;
2169         rect_bar.ymax = rect_bar.ymin + 4;
2170         
2171         w = value * (rect_prog.xmax - rect_prog.xmin);
2172         
2173         /* ensure minimium size */
2174         min= rect_prog.ymax - rect_prog.ymin;
2175         w = MAX2(w, min);
2176         
2177         rect_bar.xmax = rect_bar.xmin + w;
2178                 
2179         uiWidgetScrollDraw(wcol, &rect_prog, &rect_bar, UI_SCROLL_NO_OUTLINE);
2180         
2181         /* raise text a bit */
2182         rect->ymin += 6;
2183         rect->xmin -= 6;
2184 }
2185
2186 static void widget_link(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2187 {
2188         
2189         if(but->flag & UI_SELECT) {
2190                 rcti rectlink;
2191                 
2192                 UI_ThemeColor(TH_TEXT_HI);
2193                 
2194                 rectlink.xmin= (rect->xmin+rect->xmax)/2;
2195                 rectlink.ymin= (rect->ymin+rect->ymax)/2;
2196                 rectlink.xmax= but->linkto[0];
2197                 rectlink.ymax= but->linkto[1];
2198                 
2199                 ui_draw_link_bezier(&rectlink);
2200         }
2201 }
2202
2203 static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2204 {
2205         uiWidgetBase wtb, wtb1;
2206         rcti rect1;
2207         double value;
2208         float offs, fac;
2209         char outline[3];
2210         
2211         widget_init(&wtb);
2212         widget_init(&wtb1);
2213         
2214         /* backdrop first */
2215         
2216         /* fully rounded */
2217         offs= 0.5f*(rect->ymax - rect->ymin);
2218         round_box_edges(&wtb, roundboxalign, rect, offs);
2219
2220         wtb.outline= 0;
2221         widgetbase_draw(&wtb, wcol);
2222         
2223         /* slider part */
2224         VECCOPY(outline, wcol->outline);
2225         VECCOPY(wcol->outline, wcol->item);
2226         VECCOPY(wcol->inner, wcol->item);
2227         SWAP(short, wcol->shadetop, wcol->shadedown);
2228         
2229         rect1= *rect;
2230         
2231         value= ui_get_but_val(but);
2232         fac= (value-but->softmin)*(rect1.xmax - rect1.xmin - offs)/(but->softmax - but->softmin);
2233         
2234         /* left part of slider, always rounded */
2235         rect1.xmax= rect1.xmin + ceil(offs+1.0f);
2236         round_box_edges(&wtb1, roundboxalign & ~6, &rect1, offs);
2237         wtb1.outline= 0;
2238         widgetbase_draw(&wtb1, wcol);
2239         
2240         /* right part of slider, interpolate roundness */
2241         rect1.xmax= rect1.xmin + fac + offs;
2242         rect1.xmin+=  floor(offs-1.0f);
2243         if(rect1.xmax + offs > rect->xmax)
2244                 offs*= (rect1.xmax + offs - rect->xmax)/offs;
2245         else 
2246                 offs= 0.0f;
2247         round_box_edges(&wtb1, roundboxalign & ~9, &rect1, offs);
2248         
2249         widgetbase_draw(&wtb1, wcol);
2250         VECCOPY(wcol->outline, outline);
2251         SWAP(short, wcol->shadetop, wcol->shadedown);
2252         
2253         /* outline */
2254         wtb.outline= 1;
2255         wtb.inner= 0;
2256         widgetbase_draw(&wtb, wcol);
2257         
2258         /* text space */
2259         rect->xmin += offs*0.75f;
2260         rect->xmax -= offs*0.75f;
2261 }
2262
2263 static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2264 {
2265         uiWidgetBase wtb;
2266         float col[4];
2267         int color_profile = but->block->color_profile;
2268         
2269         col[3]= 1.0f;
2270
2271         if (but->rnaprop) {
2272                 if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
2273                         color_profile = BLI_PR_NONE;
2274
2275                 if(RNA_property_array_length(&but->rnapoin, but->rnaprop)==4) {
2276                         col[3]= RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
2277                 }
2278         }
2279         
2280         widget_init(&wtb);
2281         
2282         /* half rounded */
2283         round_box_edges(&wtb, roundboxalign, rect, 5.0f);
2284                 
2285         ui_get_but_vectorf(but, col);
2286         
2287         if (color_profile)
2288                 linearrgb_to_srgb_v3_v3(col, col);
2289         
2290         wcol->inner[0]= FTOCHAR(col[0]);
2291         wcol->inner[1]= FTOCHAR(col[1]);
2292         wcol->inner[2]= FTOCHAR(col[2]);
2293         wcol->inner[3]= FTOCHAR(col[3]);
2294         wcol->shaded = 0;
2295         wcol->alpha_check = (wcol->inner[3] < 255);
2296
2297         widgetbase_draw(&wtb, wcol);
2298         
2299 }
2300
2301
2302 static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2303 {
2304         uiWidgetBase wtb;
2305         
2306         widget_init(&wtb);
2307         
2308         /* half rounded */
2309         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2310         
2311         widgetbase_draw(&wtb, wcol);
2312
2313 }
2314
2315
2316 static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2317 {
2318         uiWidgetBase wtb;
2319         
2320         widget_init(&wtb);
2321         
2322         /* half rounded */
2323         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2324         
2325         /* decoration */
2326         widget_menu_trias(&wtb.tria1, rect);
2327         
2328         widgetbase_draw(&wtb, wcol);
2329         
2330         /* text space */
2331         rect->xmax -= (rect->ymax-rect->ymin);
2332 }
2333
2334 static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2335 {
2336         uiWidgetBase wtb;
2337         
2338         widget_init(&wtb);
2339         
2340         /* half rounded */
2341         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2342         
2343         /* decoration */
2344         widgetbase_draw(&wtb, wcol);
2345 }
2346
2347 static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2348 {
2349         if(state & UI_ACTIVE) {
2350                 uiWidgetBase wtb;
2351                 float rad= 0.5f*(rect->ymax - rect->ymin); // 4.0f
2352                 
2353                 widget_init(&wtb);
2354                 
2355                 /* half rounded */
2356                 round_box_edges(&wtb, 15, rect, rad);
2357                 
2358                 widgetbase_draw(&wtb, wcol);
2359         }
2360 }
2361
2362 static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2363 {
2364         uiWidgetBase wtb;
2365         
2366         widget_init(&wtb);
2367         
2368         /* not rounded, no outline */
2369         wtb.outline= 0;
2370         round_box_edges(&wtb, 0, rect, 0.0f);
2371         
2372         widgetbase_draw(&wtb, wcol);
2373 }
2374
2375 static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2376 {
2377         uiWidgetBase wtb;
2378         
2379         widget_init(&wtb);
2380         
2381         /* rounded, but no outline */
2382         wtb.outline= 0;
2383         round_box_edges(&wtb, 15, rect, 4.0f);
2384         
2385         widgetbase_draw(&wtb, wcol);
2386 }
2387
2388 static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2389 {
2390         uiWidgetBase wtb;
2391         rcti recttemp= *rect;
2392         int delta;
2393         
2394         widget_init(&wtb);
2395         
2396         /* square */
2397         recttemp.xmax= recttemp.xmin + (recttemp.ymax-recttemp.ymin);
2398         
2399         /* smaller */
2400         delta= 1 + (recttemp.ymax-recttemp.ymin)/8;
2401         recttemp.xmin+= delta;
2402         recttemp.ymin+= delta;
2403         recttemp.xmax-= delta;
2404         recttemp.ymax-= delta;
2405         
2406         /* half rounded */
2407         round_box_edges(&wtb, 15, &recttemp, 4.0f);
2408         
2409         /* decoration */
2410         if(state & UI_SELECT) {
2411                 widget_check_trias(&wtb.tria1, &recttemp);
2412         }
2413         
2414         widgetbase_draw(&wtb, wcol);
2415         
2416         /* text space */
2417         rect->xmin += (rect->ymax-rect->ymin)*0.7 + delta;
2418 }
2419
2420
2421 static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2422 {
2423         uiWidgetBase wtb;
2424         
2425         widget_init(&wtb);
2426         
2427         /* half rounded */
2428         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2429         
2430         widgetbase_draw(&wtb, wcol);
2431
2432 }
2433
2434 static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2435 {
2436         uiWidgetBase wtb;
2437         char old_col[3];
2438         
2439         widget_init(&wtb);
2440         
2441         VECCOPY(old_col, wcol->inner);
2442         
2443         /* abuse but->hsv - if it's non-zero, use this colour as the box's background */
2444         if ((but->hsv[0] != 0.0) || (but->hsv[1] != 0.0) || (but->hsv[2] != 0.0)) {
2445                 float rgb[3];
2446                 hsv_to_rgb(but->hsv[0], but->hsv[1], but->hsv[2], rgb+0, rgb+1, rgb+2);
2447                 wcol->inner[0] = rgb[0] * 255;
2448                 wcol->inner[1] = rgb[1] * 255;
2449                 wcol->inner[2] = rgb[2] * 255;
2450         }
2451         
2452         /* half rounded */
2453         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2454         
2455         widgetbase_draw(&wtb, wcol);
2456         
2457         /* store the box bg as gl clearcolor, to retrieve later when drawing semi-transparent rects
2458          * over the top to indicate disabled buttons */
2459         glClearColor(wcol->inner[0]/255.0, wcol->inner[1]/255.0, wcol->inner[2]/255.0, 1.0);
2460         
2461         VECCOPY(wcol->inner, old_col);
2462 }
2463
2464 static void widget_but(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2465 {
2466         uiWidgetBase wtb;
2467         
2468         widget_init(&wtb);
2469         
2470         /* half rounded */
2471         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2472                 
2473         widgetbase_draw(&wtb, wcol);
2474
2475 }
2476
2477 static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2478 {
2479         uiWidgetBase wtb;
2480         float rad= 5.0f; //0.5f*(rect->ymax - rect->ymin);
2481         
2482         widget_init(&wtb);
2483         
2484         /* half rounded */
2485         round_box_edges(&wtb, roundboxalign, rect, rad);
2486
2487         widgetbase_draw(&wtb, wcol);
2488 }
2489
2490 static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
2491 {
2492         uiWidgetBase wtb;
2493         char col[4];
2494         
2495         /* state copy! */
2496         wt->wcol= *(wt->wcol_theme);
2497         
2498         widget_init(&wtb);
2499         
2500         if(but->block->drawextra) {
2501                 /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
2502                 but->block->drawextra(C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect);
2503                 
2504                 /* make mask to draw over image */
2505                 UI_GetThemeColor3ubv(TH_BACK, col);
2506                 glColor3ubv((unsigned char*)col);
2507                 
2508                 round_box__edges(&wtb, 15, rect, 0.0f, 4.0);
2509                 widgetbase_outline(&wtb);
2510         }
2511         
2512         /* outline */
2513         round_box_edges(&wtb, 15, rect, 5.0f);
2514         wtb.outline= 1;
2515         wtb.inner= 0;
2516         widgetbase_draw(&wtb, &wt->wcol);
2517         
2518 }
2519
2520
2521 static void widget_disabled(rcti *rect)
2522 {
2523         float col[4];
2524         
2525         glEnable(GL_BLEND);
2526         
2527         /* can't use theme TH_BACK or TH_PANEL... undefined */
2528         glGetFloatv(GL_COLOR_CLEAR_VALUE, col);
2529         glColor4f(col[0], col[1], col[2], 0.5f);
2530
2531         /* need -1 and +1 to make it work right for aligned buttons,
2532          * but problem may be somewhere else? */
2533         glRectf(rect->xmin-1, rect->ymin-1, rect->xmax, rect->ymax+1);
2534         
2535         glDisable(GL_BLEND);
2536 }
2537
2538 static uiWidgetType *widget_type(uiWidgetTypeEnum type)
2539 {
2540         bTheme *btheme= U.themes.first;
2541         static uiWidgetType wt;
2542         
2543         /* defaults */
2544         wt.wcol_theme= &btheme->tui.wcol_regular;
2545         wt.wcol_state= &btheme->tui.wcol_state;
2546         wt.state= widget_state;
2547         wt.draw= widget_but;
2548         wt.custom= NULL;
2549         wt.text= widget_draw_text_icon;
2550         
2551         switch(type) {
2552                 case UI_WTYPE_REGULAR:
2553                         break;
2554
2555                 case UI_WTYPE_LABEL:
2556                         wt.draw= NULL;
2557                         wt.state= widget_state_label;
2558                         break;
2559                         
2560                 case UI_WTYPE_TOGGLE:
2561                         wt.wcol_theme= &btheme->tui.wcol_toggle;
2562                         break;
2563                         
2564                 case UI_WTYPE_OPTION:
2565                         wt.wcol_theme= &btheme->tui.wcol_option;
2566                         wt.draw= widget_optionbut;
2567                         break;
2568                         
2569                 case UI_WTYPE_RADIO:
2570                         wt.wcol_theme= &btheme->tui.wcol_radio;
2571                         wt.draw= widget_radiobut;
2572                         break;
2573
2574                 case UI_WTYPE_NUMBER:
2575                         wt.wcol_theme= &btheme->tui.wcol_num;
2576                         wt.draw= widget_numbut;
2577                         break;
2578                         
2579                 case UI_WTYPE_SLIDER:
2580                         wt.wcol_theme= &btheme->tui.wcol_numslider;
2581                         wt.custom= widget_numslider;
2582                         wt.state= widget_state_numslider;
2583                         break;
2584                         
2585                 case UI_WTYPE_EXEC:
2586                         wt.wcol_theme= &btheme->tui.wcol_tool;
2587                         wt.draw= widget_roundbut;
2588                         break;
2589                         
2590                         
2591                         /* strings */
2592                 case UI_WTYPE_NAME:
2593                         wt.wcol_theme= &btheme->tui.wcol_text;
2594                         wt.draw= widget_textbut;
2595                         break;
2596                         
2597                 case UI_WTYPE_NAME_LINK:
2598                         break;
2599                         
2600                 case UI_WTYPE_POINTER_LINK:
2601                         break;
2602                         
2603                 case UI_WTYPE_FILENAME:
2604                         break;
2605                         
2606                         
2607                         /* start menus */
2608                 case UI_WTYPE_MENU_RADIO:
2609                         wt.wcol_theme= &btheme->tui.wcol_menu;
2610                         wt.draw= widget_menubut;
2611                         break;
2612
2613                 case UI_WTYPE_MENU_ICON_RADIO:
2614                         wt.wcol_theme= &btheme->tui.wcol_menu;
2615                         wt.draw= widget_menuiconbut;
2616                         break;
2617                         
2618                 case UI_WTYPE_MENU_POINTER_LINK:
2619                         wt.wcol_theme= &btheme->tui.wcol_menu;
2620                         wt.draw= widget_menubut;
2621                         break;
2622                         
2623                 case UI_WTYPE_PULLDOWN:
2624                         wt.wcol_theme= &btheme->tui.wcol_pulldown;
2625                         wt.draw= widget_pulldownbut;
2626                         wt.state= widget_state_pulldown;
2627                         break;
2628                         
2629                         /* in menus */
2630                 case UI_WTYPE_MENU_ITEM:
2631                         wt.wcol_theme= &btheme->tui.wcol_menu_item;
2632                         wt.draw= widget_menu_itembut;
2633                         wt.state= widget_state_menu_item;
2634                         break;
2635                         
2636                 case UI_WTYPE_MENU_BACK:
2637                         wt.wcol_theme= &btheme->tui.wcol_menu_back;
2638                         wt.draw= widget_menu_back;
2639                         break;
2640                         
2641                         /* specials */
2642                 case UI_WTYPE_ICON:
2643                         wt.draw= NULL;
2644                         break;
2645                         
2646                 case UI_WTYPE_SWATCH:
2647                         wt.custom= widget_swatch;
2648                         break;
2649                         
2650                 case UI_WTYPE_BOX:
2651                         wt.custom= widget_box;
2652                         wt.wcol_theme= &btheme->tui.wcol_box;
2653                         break;
2654                         
2655                 case UI_WTYPE_RGB_PICKER:
2656                         break;
2657                         
2658                 case UI_WTYPE_NORMAL:
2659                         break;
2660
2661                 case UI_WTYPE_SCROLL:
2662                         wt.wcol_theme= &btheme->tui.wcol_scroll;
2663                         wt.state= widget_state_nothing;
2664                         wt.custom= widget_scroll;
2665                         break;
2666
2667                 case UI_WTYPE_LISTITEM:
2668                         wt.wcol_theme= &btheme->tui.wcol_list_item;
2669                         wt.draw= widget_list_itembut;
2670                         break;
2671                         
2672                 case UI_WTYPE_PROGRESSBAR:
2673                         wt.wcol_theme= &btheme->tui.wcol_progress;
2674                         wt.custom= widget_progressbar;
2675                         break;
2676         }
2677         
2678         return &wt;
2679 }
2680
2681
2682 static int widget_roundbox_set(uiBut *but, rcti *rect)
2683 {
2684         /* alignment */
2685         if(but->flag & UI_BUT_ALIGN) {
2686                 
2687                 if(but->flag & UI_BUT_ALIGN_TOP)
2688                         rect->ymax+= 1;
2689                 if(but->flag & UI_BUT_ALIGN_LEFT)
2690                         rect->xmin-= 1;
2691                 
2692                 switch(but->flag & UI_BUT_ALIGN) {
2693                         case UI_BUT_ALIGN_TOP:
2694                                 return (12);
2695                                 break;
2696                         case UI_BUT_ALIGN_DOWN:
2697                                 return (3);
2698                                 break;
2699                         case UI_BUT_ALIGN_LEFT:
2700                                 return (6);
2701                                 break;
2702                         case UI_BUT_ALIGN_RIGHT:
2703                                 return (9);
2704                                 break;
2705                                 
2706                         case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
2707                                 return (1);
2708                                 break;
2709                         case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
2710                                 return (2);
2711                                 break;
2712                         case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
2713                                 return (8);
2714                                 break;
2715                         case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
2716                                 return (4);
2717                                 break;
2718                                 
2719                         default:
2720                                 return (0);
2721                                 break;
2722                 }
2723         } 
2724         return 15;
2725 }
2726
2727 /* conversion from old to new buttons, so still messy */
2728 void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
2729 {
2730         bTheme *btheme= U.themes.first;
2731         ThemeUI *tui= &btheme->tui;
2732         uiFontStyle *fstyle= &style->widget;
2733         uiWidgetType *wt= NULL;
2734         
2735         /* handle menus separately */
2736         if(but->dt==UI_EMBOSSP) {
2737                 switch (but->type) {
2738                         case LABEL:
2739                                 widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
2740                                 break;
2741                         case SEPR:
2742                                 ui_draw_separator(but, rect, &tui->wcol_menu_item);
2743                                 break;
2744                                 
2745                         default:
2746                                 wt= widget_type(UI_WTYPE_MENU_ITEM);
2747                 }
2748         }
2749         else if(but->dt==UI_EMBOSSN) {
2750                 /* "nothing" */
2751                 wt= widget_type(UI_WTYPE_ICON);
2752         }
2753         else {
2754                 
2755                 switch (but->type) {
2756                         case LABEL:
2757                                 if(but->block->flag & UI_BLOCK_LOOP)
2758                                         widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
2759                                 else {
2760                                         wt= widget_type(UI_WTYPE_LABEL);
2761                                         fstyle= &style->widgetlabel;
2762                                 }
2763                                 break;
2764                                 
2765                         case SEPR:
2766                                 break;
2767                                 
2768                         case BUT:
2769                                 wt= widget_type(UI_WTYPE_EXEC);
2770                                 break;
2771
2772                         case NUM:
2773                                 wt= widget_type(UI_WTYPE_NUMBER);
2774                                 break;
2775                                 
2776                         case NUMSLI:
2777                         case HSVSLI:
2778                                 wt= widget_type(UI_WTYPE_SLIDER);
2779                                 break;
2780                                 
2781                         case ROW:
2782                                 wt= widget_type(UI_WTYPE_RADIO);
2783                                 break;
2784
2785                         case LISTROW:
2786                                 wt= widget_type(UI_WTYPE_LISTITEM);
2787                                 break;
2788                                 
2789                         case TEX:
2790                                 wt= widget_type(UI_WTYPE_NAME);
2791                                 break;
2792                                 
2793                         case SEARCH_MENU:
2794                                 wt= widget_type(UI_WTYPE_NAME);
2795                                 if(but->block->flag & UI_BLOCK_LOOP)
2796                                         wt->wcol_theme= &btheme->tui.wcol_menu_back;
2797                                 break;
2798                                 
2799                         case TOGBUT:
2800                         case TOG:
2801                         case TOGN:
2802                         case TOG3:
2803                                 wt= widget_type(UI_WTYPE_TOGGLE);
2804                                 break;
2805                                 
2806                         case OPTION:
2807                         case OPTIONN:
2808                                 if (!(but->flag & UI_HAS_ICON)) {
2809                                         wt= widget_type(UI_WTYPE_OPTION);
2810                                         but->flag |= UI_TEXT_LEFT;
2811                                 }
2812                                 else
2813                                         wt= widget_type(UI_WTYPE_TOGGLE);
2814                                 break;
2815                                 
2816                         case MENU:
2817                         case BLOCK:
2818                         case ICONTEXTROW:
2819                                 if(!but->str[0] && but->icon)
2820                                         wt= widget_type(UI_WTYPE_MENU_ICON_RADIO);
2821                                 else
2822                                         wt= widget_type(UI_WTYPE_MENU_RADIO);
2823                                 break;
2824                                 
2825                         case PULLDOWN:
2826                                 wt= widget_type(UI_WTYPE_PULLDOWN);
2827                                 break;
2828                         
2829                         case BUTM:
2830                                 wt= widget_type(UI_WTYPE_MENU_ITEM);
2831                                 break;
2832                                 
2833                         case COL:
2834                                 wt= widget_type(UI_WTYPE_SWATCH);
2835                                 break;
2836                                 
2837                         case ROUNDBOX:
2838                         case LISTBOX:
2839                                 wt= widget_type(UI_WTYPE_BOX);
2840                                 break;
2841                                 
2842                         case LINK:
2843                         case INLINK:
2844                                 wt= widget_type(UI_WTYPE_ICON);
2845                                 wt->custom= widget_link;
2846                                 
2847                                 break;
2848                         
2849                         case BUT_EXTRA:
2850                                 widget_draw_extra_mask(C, but, widget_type(UI_WTYPE_BOX), rect);
2851                                 break;
2852                                 
2853                         case HSVCUBE:
2854                                 if(but->a1==9) // vertical V slider, uses new widget draw now
2855                                         ui_draw_but_HSV_v(but, rect);
2856                                 else  // other HSV pickers...
2857                                         ui_draw_but_HSVCUBE(but, rect);
2858                                 break;
2859                                 
2860                         case HSVCIRCLE:
2861                                 ui_draw_but_HSVCIRCLE(but, &tui->wcol_regular, rect);
2862                                 break;
2863                                 
2864                         case BUT_COLORBAND:
2865                                 ui_draw_but_COLORBAND(but, &tui->wcol_regular, rect);
2866                                 break;
2867                                 
2868                         case BUT_NORMAL:
2869                                 ui_draw_but_NORMAL(but, &tui->wcol_regular, rect);
2870                                 break;
2871                                 
2872                         case BUT_IMAGE:
2873                                 ui_draw_but_IMAGE(ar, but, &tui->wcol_regular, rect);
2874                                 break;
2875                         
2876                         case HISTOGRAM:
2877                                 ui_draw_but_HISTOGRAM(ar, but, &tui->wcol_regular, rect);
2878                                 break;
2879                                 
2880                         case WAVEFORM:
2881                                 ui_draw_but_WAVEFORM(ar, but, &tui->wcol_regular, rect);
2882                                 break;
2883                                 
2884                         case VECTORSCOPE:
2885                                 ui_draw_but_VECTORSCOPE(ar, but, &tui->wcol_regular, rect);
2886                                 break;
2887                                         
2888                         case BUT_CURVE:
2889                                 ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect);
2890                                 break;
2891                                 
2892                         case PROGRESSBAR:
2893                                 wt= widget_type(UI_WTYPE_PROGRESSBAR);
2894                                 fstyle= &style->widgetlabel;
2895                                 break;
2896
2897                         case SCROLL:
2898                                 wt= widget_type(UI_WTYPE_SCROLL);
2899                                 break;
2900
2901                         default:
2902                                 wt= widget_type(UI_WTYPE_REGULAR);
2903                 }
2904         }
2905         
2906         if(wt) {
2907                 rcti disablerect= *rect; /* rect gets clipped smaller for text */
2908                 int roundboxalign, state;
2909                 
2910                 roundboxalign= widget_roundbox_set(but, rect);
2911
2912                 state= but->flag;
2913                 if(but->editstr) state |= UI_TEXTINPUT;
2914                 
2915                 wt->state(wt, state);
2916                 if(wt->custom)
2917                         wt->custom(but, &wt->wcol, rect, state, roundboxalign);
2918                 else if(wt->draw)
2919                         wt->draw(&wt->wcol, rect, state, roundboxalign);
2920                 wt->text(fstyle, &wt->wcol, but, rect);
2921                 
2922                 if(state & (UI_BUT_DISABLED|UI_BUT_INACTIVE))
2923                         if(but->dt!=UI_EMBOSSP)
2924                                 widget_disabled(&disablerect);
2925         }
2926 }
2927
2928 void ui_draw_menu_back(uiStyle *style, uiBlock *block, rcti *rect)
2929 {
2930         uiWidgetType *wt= widget_type(UI_WTYPE_MENU_BACK);
2931         
2932         wt->state(wt, 0);
2933         if(block)
2934                 wt->draw(&wt->wcol, rect, block->flag, block->direction);
2935         else
2936                 wt->draw(&wt->wcol, rect, 0, 0);
2937         
2938 }
2939
2940 void ui_draw_search_back(uiStyle *style, uiBlock *block, rcti *rect)
2941 {
2942         uiWidgetType *wt= widget_type(UI_WTYPE_BOX);
2943         
2944         glEnable(GL_BLEND);
2945         widget_softshadow(rect, 15, 5.0f, 8.0f);
2946         glDisable(GL_BLEND);
2947
2948         wt->state(wt, 0);
2949         if(block)
2950                 wt->draw(&wt->wcol, rect, block->flag, 15);
2951         else
2952                 wt->draw(&wt->wcol, rect, 0, 15);
2953         
2954 }
2955
2956
2957 /* helper call to draw a menu item without button */
2958 /* state: UI_ACTIVE or 0 */
2959 void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int iconid, int state)
2960 {
2961         uiWidgetType *wt= widget_type(UI_WTYPE_MENU_ITEM);
2962         rcti _rect= *rect;
2963         char *cpoin;
2964         
2965         wt->state(wt, state);
2966         wt->draw(&wt->wcol, rect, 0, 0);
2967         
2968         uiStyleFontSet(fstyle);
2969         fstyle->align= UI_STYLE_TEXT_LEFT;
2970         
2971         /* text location offset */
2972         rect->xmin+=5;
2973         if(iconid) rect->xmin+= ICON_HEIGHT;
2974
2975         /* cut string in 2 parts? */
2976         cpoin= strchr(name, '|');
2977         if(cpoin) {
2978                 *cpoin= 0;
2979                 rect->xmax -= BLF_width(fstyle->uifont_id, cpoin+1) + 10;
2980         }
2981         
2982         glColor3ubv((unsigned char*)wt->wcol.text);
2983         uiStyleFontDraw(fstyle, rect, name);
2984         
2985         /* part text right aligned */
2986         if(cpoin) {
2987                 fstyle->align= UI_STYLE_TEXT_RIGHT;
2988                 rect->xmax= _rect.xmax - 5;
2989                 uiStyleFontDraw(fstyle, rect, cpoin+1);
2990                 *cpoin= '|';
2991         }
2992         
2993         /* restore rect, was messed with */
2994         *rect= _rect;
2995
2996         if(iconid) {
2997                 int xs= rect->xmin+4;
2998                 int ys= 1 + (rect->ymin+rect->ymax- ICON_HEIGHT)/2;
2999                 glEnable(GL_BLEND);
3000                 UI_icon_draw_aspect(xs, ys, iconid, 1.2f, 0.5f); /* XXX scale weak get from fstyle? */
3001                 glDisable(GL_BLEND);
3002         }
3003 }
3004
3005 void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, char *name, int iconid, int state)
3006 {
3007         rcti trect = *rect;
3008         
3009         uiWidgetType *wt= widget_type(UI_WTYPE_MENU_ITEM);
3010         
3011         wt->state(wt, state);
3012         wt->draw(&wt->wcol, rect, 0, 0);
3013         
3014         widget_draw_preview(iconid, 1.f, 1.f, rect);
3015         
3016         if (state == UI_ACTIVE)
3017                 glColor3ubv((unsigned char*)wt->wcol.text);
3018         else
3019                 glColor3ubv((unsigned char*)wt->wcol.text_sel);
3020         
3021         trect.xmin += 0;
3022         trect.xmax = trect.xmin + BLF_width(fstyle->uifont_id, name) + 10;
3023         trect.ymin += 10;
3024         trect.ymax = trect.ymin + BLF_height(fstyle->uifont_id, name);
3025         uiStyleFontDraw(fstyle, &trect, name);
3026 }