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