3c944781d80f45f1c354b5dd086f06396439d470
[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;  // UNUSED
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 = BLI_RCT_CENTER_X_FL(rect);
1847         float centy = BLI_RCT_CENTER_Y_FL(rect);
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 = BLI_RCT_CENTER_X_FL(rect);
1880         centy = BLI_RCT_CENTER_Y_FL(rect);
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 int ui_link_bezier_points(rcti *rect, float coord_array[][2], int resol)
2225 {
2226         float dist, vec[4][2];
2227
2228         vec[0][0] = rect->xmin;
2229         vec[0][1] = rect->ymin;
2230         vec[3][0] = rect->xmax;
2231         vec[3][1] = rect->ymax;
2232         
2233         dist = 0.5f * ABS(vec[0][0] - vec[3][0]);
2234         
2235         vec[1][0] = vec[0][0] + dist;
2236         vec[1][1] = vec[0][1];
2237         
2238         vec[2][0] = vec[3][0] - dist;
2239         vec[2][1] = vec[3][1];
2240         
2241         BKE_curve_forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, sizeof(float) * 2);
2242         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);
2243         
2244         return 1;
2245 }
2246
2247 #define LINK_RESOL  24
2248 void ui_draw_link_bezier(rcti *rect)
2249 {
2250         float coord_array[LINK_RESOL + 1][2];
2251         
2252         if (ui_link_bezier_points(rect, coord_array, LINK_RESOL)) {
2253                 /* we can reuse the dist variable here to increment the GL curve eval amount*/
2254                 // const float dist = 1.0f / (float)LINK_RESOL; // UNUSED
2255
2256                 glEnable(GL_BLEND);
2257                 glEnable(GL_LINE_SMOOTH);
2258
2259                 glEnableClientState(GL_VERTEX_ARRAY);
2260                 glVertexPointer(2, GL_FLOAT, 0, coord_array);
2261                 glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL);
2262                 glDisableClientState(GL_VERTEX_ARRAY);
2263
2264                 glDisable(GL_BLEND);
2265                 glDisable(GL_LINE_SMOOTH);
2266
2267         }
2268 }
2269
2270 /* function in use for buttons and for view2d sliders */
2271 void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int state)
2272 {
2273         uiWidgetBase wtb;
2274         float rad;
2275         int horizontal;
2276         short outline = 0;
2277
2278         widget_init(&wtb);
2279
2280         /* determine horizontal/vertical */
2281         horizontal = (rect->xmax - rect->xmin > rect->ymax - rect->ymin);
2282         
2283         if (horizontal)
2284                 rad = 0.5f * (rect->ymax - rect->ymin);
2285         else
2286                 rad = 0.5f * (rect->xmax - rect->xmin);
2287         
2288         wtb.shadedir = (horizontal) ? 1 : 0;
2289         
2290         /* draw back part, colors swapped and shading inverted */
2291         if (horizontal)
2292                 SWAP(short, wcol->shadetop, wcol->shadedown);
2293         
2294         round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
2295         widgetbase_draw(&wtb, wcol);
2296         
2297         /* slider */
2298         if (slider->xmax - slider->xmin < 2 || slider->ymax - slider->ymin < 2) ;
2299         else {
2300                 
2301                 SWAP(short, wcol->shadetop, wcol->shadedown);
2302                 
2303                 copy_v4_v4_char(wcol->inner, wcol->item);
2304                 
2305                 if (wcol->shadetop > wcol->shadedown)
2306                         wcol->shadetop += 20;   /* XXX violates themes... */
2307                 else wcol->shadedown += 20;
2308                 
2309                 if (state & UI_SCROLL_PRESSED) {
2310                         wcol->inner[0] = wcol->inner[0] >= 250 ? 255 : wcol->inner[0] + 5;
2311                         wcol->inner[1] = wcol->inner[1] >= 250 ? 255 : wcol->inner[1] + 5;
2312                         wcol->inner[2] = wcol->inner[2] >= 250 ? 255 : wcol->inner[2] + 5;
2313                 }
2314
2315                 /* draw */
2316                 wtb.emboss = 0; /* only emboss once */
2317                 
2318                 /* exception for progress bar */
2319                 if (state & UI_SCROLL_NO_OUTLINE)       
2320                         SWAP(short, outline, wtb.outline);
2321                 
2322                 round_box_edges(&wtb, UI_CNR_ALL, slider, rad);
2323                 
2324                 if (state & UI_SCROLL_ARROWS) {
2325                         if (wcol->item[0] > 48) wcol->item[0] -= 48;
2326                         if (wcol->item[1] > 48) wcol->item[1] -= 48;
2327                         if (wcol->item[2] > 48) wcol->item[2] -= 48;
2328                         wcol->item[3] = 255;
2329                         
2330                         if (horizontal) {
2331                                 widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
2332                                 widget_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
2333                         }
2334                         else {
2335                                 widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
2336                                 widget_scroll_circle(&wtb.tria2, slider, 0.6f, 't');
2337                         }
2338                 }
2339                 widgetbase_draw(&wtb, wcol);
2340                 
2341                 if (state & UI_SCROLL_NO_OUTLINE)
2342                         SWAP(short, outline, wtb.outline);
2343         }       
2344 }
2345
2346 static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2347 {
2348         rcti rect1;
2349         double value;
2350         float fac, size, min;
2351         int horizontal;
2352
2353         /* calculate slider part */
2354         value = ui_get_but_val(but);
2355
2356         size = (but->softmax + but->a1 - but->softmin);
2357         size = MAX2(size, 2);
2358         
2359         /* position */
2360         rect1 = *rect;
2361
2362         /* determine horizontal/vertical */
2363         horizontal = (rect->xmax - rect->xmin > rect->ymax - rect->ymin);
2364         
2365         if (horizontal) {
2366                 fac = (rect->xmax - rect->xmin) / (size);
2367                 rect1.xmin = rect1.xmin + ceilf(fac * ((float)value - but->softmin));
2368                 rect1.xmax = rect1.xmin + ceilf(fac * (but->a1 - but->softmin));
2369
2370                 /* ensure minimium size */
2371                 min = rect->ymax - rect->ymin;
2372
2373                 if (rect1.xmax - rect1.xmin < min) {
2374                         rect1.xmax = rect1.xmin + min;
2375
2376                         if (rect1.xmax > rect->xmax) {
2377                                 rect1.xmax = rect->xmax;
2378                                 rect1.xmin = MAX2(rect1.xmax - min, rect->xmin);
2379                         }
2380                 }
2381         }
2382         else {
2383                 fac = (rect->ymax - rect->ymin) / (size);
2384                 rect1.ymax = rect1.ymax - ceilf(fac * ((float)value - but->softmin));
2385                 rect1.ymin = rect1.ymax - ceilf(fac * (but->a1 - but->softmin));
2386
2387                 /* ensure minimium size */
2388                 min = rect->xmax - rect->xmin;
2389
2390                 if (rect1.ymax - rect1.ymin < min) {
2391                         rect1.ymax = rect1.ymin + min;
2392
2393                         if (rect1.ymax > rect->ymax) {
2394                                 rect1.ymax = rect->ymax;
2395                                 rect1.ymin = MAX2(rect1.ymax - min, rect->ymin);
2396                         }
2397                 }
2398         }
2399
2400         if (state & UI_SELECT)
2401                 state = UI_SCROLL_PRESSED;
2402         else
2403                 state = 0;
2404         uiWidgetScrollDraw(wcol, rect, &rect1, state);
2405 }
2406
2407 static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2408 {
2409         rcti rect_prog = *rect, rect_bar = *rect;
2410         float value = but->a1;
2411         float w, min;
2412         
2413         /* make the progress bar a proportion of the original height */
2414         /* hardcoded 4px high for now */
2415         rect_prog.ymax = rect_prog.ymin + 4;
2416         rect_bar.ymax = rect_bar.ymin + 4;
2417         
2418         w = value * (rect_prog.xmax - rect_prog.xmin);
2419         
2420         /* ensure minimium size */
2421         min = rect_prog.ymax - rect_prog.ymin;
2422         w = MAX2(w, min);
2423         
2424         rect_bar.xmax = rect_bar.xmin + w;
2425                 
2426         uiWidgetScrollDraw(wcol, &rect_prog, &rect_bar, UI_SCROLL_NO_OUTLINE);
2427         
2428         /* raise text a bit */
2429         rect->ymin += 6;
2430         rect->xmin -= 6;
2431 }
2432
2433 static void widget_link(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2434 {
2435         
2436         if (but->flag & UI_SELECT) {
2437                 rcti rectlink;
2438                 
2439                 UI_ThemeColor(TH_TEXT_HI);
2440                 
2441                 rectlink.xmin = BLI_RCT_CENTER_X(rect);
2442                 rectlink.ymin = BLI_RCT_CENTER_Y(rect);
2443                 rectlink.xmax = but->linkto[0];
2444                 rectlink.ymax = but->linkto[1];
2445                 
2446                 ui_draw_link_bezier(&rectlink);
2447         }
2448 }
2449
2450 static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2451 {
2452         uiWidgetBase wtb, wtb1;
2453         rcti rect1;
2454         double value;
2455         float offs, toffs, fac;
2456         char outline[3];
2457
2458         widget_init(&wtb);
2459         widget_init(&wtb1);
2460         
2461         /* backdrop first */
2462         
2463         /* fully rounded */
2464         offs = 0.5f * (rect->ymax - rect->ymin);
2465         toffs = offs * 0.75f;
2466         round_box_edges(&wtb, roundboxalign, rect, offs);
2467
2468         wtb.outline = 0;
2469         widgetbase_draw(&wtb, wcol);
2470         
2471         /* draw left/right parts only when not in text editing */
2472         if (!(state & UI_TEXTINPUT)) {
2473                 
2474                 /* slider part */
2475                 copy_v3_v3_char(outline, wcol->outline);
2476                 copy_v3_v3_char(wcol->outline, wcol->item);
2477                 copy_v3_v3_char(wcol->inner, wcol->item);
2478
2479                 if (!(state & UI_SELECT))
2480                         SWAP(short, wcol->shadetop, wcol->shadedown);
2481                 
2482                 rect1 = *rect;
2483                 
2484                 value = ui_get_but_val(but);
2485                 fac = ((float)value - but->softmin) * (rect1.xmax - rect1.xmin - offs) / (but->softmax - but->softmin);
2486                 
2487                 /* left part of slider, always rounded */
2488                 rect1.xmax = rect1.xmin + ceil(offs + 1.0f);
2489                 round_box_edges(&wtb1, roundboxalign & ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT), &rect1, offs);
2490                 wtb1.outline = 0;
2491                 widgetbase_draw(&wtb1, wcol);
2492                 
2493                 /* right part of slider, interpolate roundness */
2494                 rect1.xmax = rect1.xmin + fac + offs;
2495                 rect1.xmin +=  floor(offs - 1.0f);
2496                 if (rect1.xmax + offs > rect->xmax)
2497                         offs *= (rect1.xmax + offs - rect->xmax) / offs;
2498                 else 
2499                         offs = 0.0f;
2500                 round_box_edges(&wtb1, roundboxalign & ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT), &rect1, offs);
2501                 
2502                 widgetbase_draw(&wtb1, wcol);
2503                 copy_v3_v3_char(wcol->outline, outline);
2504                 
2505                 if (!(state & UI_SELECT))
2506                         SWAP(short, wcol->shadetop, wcol->shadedown);
2507         }
2508         
2509         /* outline */
2510         wtb.outline = 1;
2511         wtb.inner = 0;
2512         widgetbase_draw(&wtb, wcol);
2513         
2514         /* text space */
2515         rect->xmin += toffs;
2516         rect->xmax -= toffs;
2517 }
2518
2519 /* I think 3 is sufficient border to indicate keyed status */
2520 #define SWATCH_KEYED_BORDER 3
2521
2522 static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2523 {
2524         uiWidgetBase wtb;
2525         float col[4];
2526         int color_profile = but->block->color_profile;
2527         
2528         col[3] = 1.0f;
2529
2530         if (but->rnaprop) {
2531                 if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
2532                         color_profile = BLI_PR_NONE;
2533
2534                 if (RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4) {
2535                         col[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
2536                 }
2537         }
2538         
2539         widget_init(&wtb);
2540         
2541         /* half rounded */
2542         round_box_edges(&wtb, roundboxalign, rect, 5.0f);
2543                 
2544         ui_get_but_vectorf(but, col);
2545
2546         if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
2547                 /* draw based on state - color for keyed etc */
2548                 widgetbase_draw(&wtb, wcol);
2549
2550                 /* inset to draw swatch color */
2551                 rect->xmin += SWATCH_KEYED_BORDER;
2552                 rect->xmax -= SWATCH_KEYED_BORDER;
2553                 rect->ymin += SWATCH_KEYED_BORDER;
2554                 rect->ymax -= SWATCH_KEYED_BORDER;
2555                 
2556                 round_box_edges(&wtb, roundboxalign, rect, 5.0f);
2557         }
2558         
2559         if (color_profile)
2560                 linearrgb_to_srgb_v3_v3(col, col);
2561         
2562         rgba_float_to_uchar((unsigned char *)wcol->inner, col);
2563
2564         wcol->shaded = 0;
2565         wcol->alpha_check = (wcol->inner[3] < 255);
2566
2567         widgetbase_draw(&wtb, wcol);
2568         
2569 }
2570
2571 static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2572 {
2573         if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
2574                 uiWidgetBase wtb;
2575         
2576                 widget_init(&wtb);
2577                 wtb.outline = 0;
2578                 
2579                 /* rounded */
2580                 round_box_edges(&wtb, UI_CNR_ALL, rect, 10.0f);
2581                 widgetbase_draw(&wtb, wcol);
2582         }       
2583 }
2584
2585
2586 static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2587 {
2588         uiWidgetBase wtb;
2589         
2590         if (state & UI_SELECT)
2591                 SWAP(short, wcol->shadetop, wcol->shadedown);
2592         
2593         widget_init(&wtb);
2594         
2595         /* half rounded */
2596         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2597         
2598         widgetbase_draw(&wtb, wcol);
2599
2600 }
2601
2602
2603 static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2604 {
2605         uiWidgetBase wtb;
2606         
2607         widget_init(&wtb);
2608         
2609         /* half rounded */
2610         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2611         
2612         /* decoration */
2613         widget_menu_trias(&wtb.tria1, rect);
2614         
2615         widgetbase_draw(&wtb, wcol);
2616         
2617         /* text space */
2618         rect->xmax -= (rect->ymax - rect->ymin);
2619 }
2620
2621 static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2622 {
2623         uiWidgetBase wtb;
2624         
2625         widget_init(&wtb);
2626         
2627         /* half rounded */
2628         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2629         
2630         /* decoration */
2631         widgetbase_draw(&wtb, wcol);
2632 }
2633
2634 static void widget_menunodebut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2635 {
2636         /* silly node link button hacks */
2637         uiWidgetBase wtb;
2638         uiWidgetColors wcol_backup = *wcol;
2639         
2640         widget_init(&wtb);
2641         
2642         /* half rounded */
2643         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2644
2645         wcol->inner[0] += 15;
2646         wcol->inner[1] += 15;
2647         wcol->inner[2] += 15;
2648         wcol->outline[0] += 15;
2649         wcol->outline[1] += 15;
2650         wcol->outline[2] += 15;
2651         
2652         /* decoration */
2653         widgetbase_draw(&wtb, wcol);
2654         *wcol = wcol_backup;
2655 }
2656
2657 static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2658 {
2659         if (state & UI_ACTIVE) {
2660                 uiWidgetBase wtb;
2661                 float rad = 0.5f * (rect->ymax - rect->ymin);  /* 4.0f */
2662                 
2663                 widget_init(&wtb);
2664                 
2665                 /* half rounded */
2666                 round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
2667                 
2668                 widgetbase_draw(&wtb, wcol);
2669         }
2670 }
2671
2672 static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2673 {
2674         uiWidgetBase wtb;
2675         
2676         widget_init(&wtb);
2677         
2678         /* not rounded, no outline */
2679         wtb.outline = 0;
2680         round_box_edges(&wtb, 0, rect, 0.0f);
2681         
2682         widgetbase_draw(&wtb, wcol);
2683 }
2684
2685 static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2686 {
2687         uiWidgetBase wtb;
2688         
2689         widget_init(&wtb);
2690         
2691         /* rounded, but no outline */
2692         wtb.outline = 0;
2693         round_box_edges(&wtb, UI_CNR_ALL, rect, 4.0f);
2694         
2695         widgetbase_draw(&wtb, wcol);
2696 }
2697
2698 static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2699 {
2700         uiWidgetBase wtb;
2701         rcti recttemp = *rect;
2702         int delta;
2703         
2704         widget_init(&wtb);
2705         
2706         /* square */
2707         recttemp.xmax = recttemp.xmin + (recttemp.ymax - recttemp.ymin);
2708         
2709         /* smaller */
2710         delta = 1 + (recttemp.ymax - recttemp.ymin) / 8;
2711         recttemp.xmin += delta;
2712         recttemp.ymin += delta;
2713         recttemp.xmax -= delta;
2714         recttemp.ymax -= delta;
2715         
2716         /* half rounded */
2717         round_box_edges(&wtb, UI_CNR_ALL, &recttemp, 4.0f);
2718         
2719         /* decoration */
2720         if (state & UI_SELECT) {
2721                 widget_check_trias(&wtb.tria1, &recttemp);
2722         }
2723         
2724         widgetbase_draw(&wtb, wcol);
2725         
2726         /* text space */
2727         rect->xmin += (rect->ymax - rect->ymin) * 0.7 + delta;
2728 }
2729
2730
2731 static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2732 {
2733         uiWidgetBase wtb;
2734         
2735         widget_init(&wtb);
2736         
2737         /* half rounded */
2738         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2739         
2740         widgetbase_draw(&wtb, wcol);
2741
2742 }
2743
2744 static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2745 {
2746         uiWidgetBase wtb;
2747         char old_col[3];
2748         
2749         widget_init(&wtb);
2750         
2751         copy_v3_v3_char(old_col, wcol->inner);
2752         
2753         /* abuse but->hsv - if it's non-zero, use this color as the box's background */
2754         if (but->col[3]) {
2755                 wcol->inner[0] = but->col[0];
2756                 wcol->inner[1] = but->col[1];
2757                 wcol->inner[2] = but->col[2];
2758         }
2759         
2760         /* half rounded */
2761         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2762         
2763         widgetbase_draw(&wtb, wcol);
2764         
2765         /* store the box bg as gl clearcolor, to retrieve later when drawing semi-transparent rects
2766          * over the top to indicate disabled buttons */
2767         /* XXX, this doesnt work right since the color applies to buttons outside the box too. */
2768         glClearColor(wcol->inner[0] / 255.0, wcol->inner[1] / 255.0, wcol->inner[2] / 255.0, 1.0);
2769         
2770         copy_v3_v3_char(wcol->inner, old_col);
2771 }
2772
2773 static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2774 {
2775         uiWidgetBase wtb;
2776         
2777         widget_init(&wtb);
2778         
2779         /* half rounded */
2780         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2781                 
2782         widgetbase_draw(&wtb, wcol);
2783
2784 }
2785
2786 static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2787 {
2788         uiWidgetBase wtb;
2789         float rad = 5.0f;  /* 0.5f * (rect->ymax - rect->ymin); */
2790         
2791         widget_init(&wtb);
2792         
2793         /* half rounded */
2794         round_box_edges(&wtb, roundboxalign, rect, rad);
2795
2796         widgetbase_draw(&wtb, wcol);
2797 }
2798
2799 static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
2800 {
2801         uiWidgetBase wtb;
2802         unsigned char col[4];
2803         
2804         /* state copy! */
2805         wt->wcol = *(wt->wcol_theme);
2806         
2807         widget_init(&wtb);
2808         
2809         if (but->block->drawextra) {
2810                 /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
2811                 but->block->drawextra(C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect);
2812                 
2813                 /* make mask to draw over image */
2814                 UI_GetThemeColor3ubv(TH_BACK, col);
2815                 glColor3ubv(col);
2816                 
2817                 round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, 4.0);
2818                 widgetbase_outline(&wtb);
2819         }
2820         
2821         /* outline */
2822         round_box_edges(&wtb, UI_CNR_ALL, rect, 5.0f);
2823         wtb.outline = 1;
2824         wtb.inner = 0;
2825         widgetbase_draw(&wtb, &wt->wcol);
2826         
2827 }
2828
2829
2830 static void widget_disabled(rcti *rect)
2831 {
2832         float col[4];
2833         
2834         glEnable(GL_BLEND);
2835         
2836         /* can't use theme TH_BACK or TH_PANEL... undefined */
2837         glGetFloatv(GL_COLOR_CLEAR_VALUE, col);
2838         glColor4f(col[0], col[1], col[2], 0.5f);
2839
2840         /* need -1 and +1 to make it work right for aligned buttons,
2841          * but problem may be somewhere else? */
2842         glRectf(rect->xmin - 1, rect->ymin - 1, rect->xmax, rect->ymax + 1);
2843         
2844         glDisable(GL_BLEND);
2845 }
2846
2847 static uiWidgetType *widget_type(uiWidgetTypeEnum type)
2848 {
2849         bTheme *btheme = UI_GetTheme();
2850         static uiWidgetType wt;
2851         
2852         /* defaults */
2853         wt.wcol_theme = &btheme->tui.wcol_regular;
2854         wt.wcol_state = &btheme->tui.wcol_state;
2855         wt.state = widget_state;
2856         wt.draw = widget_but;
2857         wt.custom = NULL;
2858         wt.text = widget_draw_text_icon;
2859         
2860         switch (type) {
2861                 case UI_WTYPE_REGULAR:
2862                         break;
2863
2864                 case UI_WTYPE_LABEL:
2865                         wt.draw = NULL;
2866                         wt.state = widget_state_label;
2867                         break;
2868                         
2869                 case UI_WTYPE_TOGGLE:
2870                         wt.wcol_theme = &btheme->tui.wcol_toggle;
2871                         break;
2872                         
2873                 case UI_WTYPE_OPTION:
2874                         wt.wcol_theme = &btheme->tui.wcol_option;
2875                         wt.draw = widget_optionbut;
2876                         break;
2877                         
2878                 case UI_WTYPE_RADIO:
2879                         wt.wcol_theme = &btheme->tui.wcol_radio;
2880                         wt.draw = widget_radiobut;
2881                         break;
2882
2883                 case UI_WTYPE_NUMBER:
2884                         wt.wcol_theme = &btheme->tui.wcol_num;
2885                         wt.draw = widget_numbut;
2886                         break;
2887                         
2888                 case UI_WTYPE_SLIDER:
2889                         wt.wcol_theme = &btheme->tui.wcol_numslider;
2890                         wt.custom = widget_numslider;
2891                         wt.state = widget_state_numslider;
2892                         break;
2893                         
2894                 case UI_WTYPE_EXEC:
2895                         wt.wcol_theme = &btheme->tui.wcol_tool;
2896                         wt.draw = widget_roundbut;
2897                         break;
2898
2899                 case UI_WTYPE_TOOLTIP:
2900                         wt.wcol_theme = &btheme->tui.wcol_tooltip;
2901                         wt.draw = widget_menu_back;
2902                         break;
2903                         
2904                         
2905                 /* strings */
2906                 case UI_WTYPE_NAME:
2907                         wt.wcol_theme = &btheme->tui.wcol_text;
2908                         wt.draw = widget_textbut;
2909                         break;
2910                         
2911                 case UI_WTYPE_NAME_LINK:
2912                         break;
2913                         
2914                 case UI_WTYPE_POINTER_LINK:
2915                         break;
2916                         
2917                 case UI_WTYPE_FILENAME:
2918                         break;
2919                         
2920                         
2921                 /* start menus */
2922                 case UI_WTYPE_MENU_RADIO:
2923                         wt.wcol_theme = &btheme->tui.wcol_menu;
2924                         wt.draw = widget_menubut;
2925                         break;
2926
2927                 case UI_WTYPE_MENU_ICON_RADIO:
2928                         wt.wcol_theme = &btheme->tui.wcol_menu;
2929                         wt.draw = widget_menuiconbut;
2930                         break;
2931                         
2932                 case UI_WTYPE_MENU_POINTER_LINK:
2933                         wt.wcol_theme = &btheme->tui.wcol_menu;
2934                         wt.draw = widget_menubut;
2935                         break;
2936
2937                 case UI_WTYPE_MENU_NODE_LINK:
2938                         wt.wcol_theme = &btheme->tui.wcol_menu;
2939                         wt.draw = widget_menunodebut;
2940                         break;
2941                         
2942                 case UI_WTYPE_PULLDOWN:
2943                         wt.wcol_theme = &btheme->tui.wcol_pulldown;
2944                         wt.draw = widget_pulldownbut;
2945                         wt.state = widget_state_pulldown;
2946                         break;
2947                         
2948                 /* in menus */
2949                 case UI_WTYPE_MENU_ITEM:
2950                         wt.wcol_theme = &btheme->tui.wcol_menu_item;
2951                         wt.draw = widget_menu_itembut;
2952                         wt.state = widget_state_menu_item;
2953                         break;
2954                         
2955                 case UI_WTYPE_MENU_BACK:
2956                         wt.wcol_theme = &btheme->tui.wcol_menu_back;
2957                         wt.draw = widget_menu_back;
2958                         break;
2959                         
2960                 /* specials */
2961                 case UI_WTYPE_ICON:
2962                         wt.custom = widget_icon_has_anim;
2963                         break;
2964                         
2965                 case UI_WTYPE_SWATCH:
2966                         wt.custom = widget_swatch;
2967                         break;
2968                         
2969                 case UI_WTYPE_BOX:
2970                         wt.custom = widget_box;
2971                         wt.wcol_theme = &btheme->tui.wcol_box;
2972                         break;
2973                         
2974                 case UI_WTYPE_RGB_PICKER:
2975                         break;
2976                         
2977                 case UI_WTYPE_NORMAL:
2978                         break;
2979
2980                 case UI_WTYPE_SCROLL:
2981                         wt.wcol_theme = &btheme->tui.wcol_scroll;
2982                         wt.state = widget_state_nothing;
2983                         wt.custom = widget_scroll;
2984                         break;
2985
2986                 case UI_WTYPE_LISTITEM:
2987                         wt.wcol_theme = &btheme->tui.wcol_list_item;
2988                         wt.draw = widget_list_itembut;
2989                         break;
2990                         
2991                 case UI_WTYPE_PROGRESSBAR:
2992                         wt.wcol_theme = &btheme->tui.wcol_progress;
2993                         wt.custom = widget_progressbar;
2994                         break;
2995         }
2996         
2997         return &wt;
2998 }
2999
3000
3001 static int widget_roundbox_set(uiBut *but, rcti *rect)
3002 {
3003         /* alignment */
3004         if (but->flag & UI_BUT_ALIGN) {
3005                 
3006                 if (but->flag & UI_BUT_ALIGN_TOP)
3007                         rect->ymax += 1;
3008                 if (but->flag & UI_BUT_ALIGN_LEFT)
3009                         rect->xmin -= 1;
3010                 
3011                 switch (but->flag & UI_BUT_ALIGN) {
3012                         case UI_BUT_ALIGN_TOP:
3013                                 return UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT;
3014                         case UI_BUT_ALIGN_DOWN:
3015                                 return UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
3016                         case UI_BUT_ALIGN_LEFT:
3017                                 return UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT;
3018                         case UI_BUT_ALIGN_RIGHT:
3019                                 return UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT;
3020                         case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_RIGHT:
3021                                 return UI_CNR_TOP_LEFT;
3022                         case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT:
3023                                 return UI_CNR_TOP_RIGHT;
3024                         case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT:
3025                                 return UI_CNR_BOTTOM_LEFT;
3026                         case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT:
3027                                 return UI_CNR_BOTTOM_RIGHT;
3028                         default:
3029                                 return 0;
3030                 }
3031         }
3032
3033         return UI_CNR_ALL;
3034 }
3035
3036 /* conversion from old to new buttons, so still messy */
3037 void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
3038 {
3039         bTheme *btheme = UI_GetTheme();
3040         ThemeUI *tui = &btheme->tui;
3041         uiFontStyle *fstyle = &style->widget;
3042         uiWidgetType *wt = NULL;
3043
3044         /* handle menus separately */
3045         if (but->dt == UI_EMBOSSP) {
3046                 switch (but->type) {
3047                         case LABEL:
3048                                 widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
3049                                 break;
3050                         case SEPR:
3051                                 ui_draw_separator(rect, &tui->wcol_menu_item);
3052                                 break;
3053                                 
3054                         default:
3055                                 wt = widget_type(UI_WTYPE_MENU_ITEM);
3056                 }
3057         }
3058         else if (but->dt == UI_EMBOSSN) {
3059                 /* "nothing" */
3060                 wt = widget_type(UI_WTYPE_ICON);
3061         }
3062         else {
3063                 
3064                 switch (but->type) {
3065                         case LABEL:
3066                                 if (but->block->flag & UI_BLOCK_LOOP)
3067                                         widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
3068                                 else {
3069                                         wt = widget_type(UI_WTYPE_LABEL);
3070                                         fstyle = &style->widgetlabel;
3071                                 }
3072                                 break;
3073                                 
3074                         case SEPR:
3075                                 break;
3076                                 
3077                         case BUT:
3078                                 wt = widget_type(UI_WTYPE_EXEC);
3079                                 break;
3080
3081                         case NUM:
3082                                 wt = widget_type(UI_WTYPE_NUMBER);
3083                                 break;
3084                                 
3085                         case NUMSLI:
3086                         case HSVSLI:
3087                                 wt = widget_type(UI_WTYPE_SLIDER);
3088                                 break;
3089                                 
3090                         case ROW:
3091                                 wt = widget_type(UI_WTYPE_RADIO);
3092                                 break;
3093
3094                         case LISTROW:
3095                                 wt = widget_type(UI_WTYPE_LISTITEM);
3096                                 break;
3097                                 
3098                         case TEX:
3099                                 wt = widget_type(UI_WTYPE_NAME);
3100                                 break;
3101                                 
3102                         case SEARCH_MENU:
3103                                 wt = widget_type(UI_WTYPE_NAME);
3104                                 if (but->block->flag & UI_BLOCK_LOOP)
3105                                         wt->wcol_theme = &btheme->tui.wcol_menu_back;
3106                                 break;
3107                                 
3108                         case TOGBUT:
3109                         case TOG:
3110                         case TOGN:
3111                         case TOG3:
3112                                 wt = widget_type(UI_WTYPE_TOGGLE);
3113                                 break;
3114                                 
3115                         case OPTION:
3116                         case OPTIONN:
3117                                 if (!(but->flag & UI_HAS_ICON)) {
3118                                         wt = widget_type(UI_WTYPE_OPTION);
3119                                         but->flag |= UI_TEXT_LEFT;
3120                                 }
3121                                 else
3122                                         wt = widget_type(UI_WTYPE_TOGGLE);
3123