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