Movie Clip Node: skip putting frame to cache when rendering animation
[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 color */
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], const int type, const float alpha)
1950 {
1951         const float color_step = (type == UI_GRAD_H) ? 0.02 : 0.05f;
1952         int a;
1953         float h = hsv[0], s = hsv[1], v = hsv[2];
1954         float dx, dy, sx1, sx2, sy;
1955         float col0[4][3];   /* left half, rect bottom to top */
1956         float col1[4][3];   /* right half, rect bottom to top */
1957
1958         /* draw series of gouraud rects */
1959         glShadeModel(GL_SMOOTH);
1960         
1961         switch (type) {
1962                 case UI_GRAD_SV:
1963                         hsv_to_rgb(h, 0.0, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1964                         hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]);
1965                         hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
1966                         hsv_to_rgb(h, 1.0, 0.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1967                         break;
1968                 case UI_GRAD_HV:
1969                         hsv_to_rgb(0.0, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1970                         hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
1971                         hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
1972                         hsv_to_rgb(0.0, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1973                         break;
1974                 case UI_GRAD_HS:
1975                         hsv_to_rgb(0.0, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
1976                         hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
1977                         hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
1978                         hsv_to_rgb(0.0, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
1979                         break;
1980                 case UI_GRAD_H:
1981                         hsv_to_rgb(0.0, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1982                         copy_v3_v3(col1[1], col1[0]);
1983                         copy_v3_v3(col1[2], col1[0]);
1984                         copy_v3_v3(col1[3], col1[0]);
1985                         break;
1986                 case UI_GRAD_S:
1987                         hsv_to_rgb(1.0, 0.0, 1.0,   &col1[1][0], &col1[1][1], &col1[1][2]);
1988                         copy_v3_v3(col1[0], col1[1]);
1989                         copy_v3_v3(col1[2], col1[1]);
1990                         copy_v3_v3(col1[3], col1[1]);
1991                         break;
1992                 case UI_GRAD_V:
1993                         hsv_to_rgb(1.0, 1.0, 0.0,   &col1[2][0], &col1[2][1], &col1[2][2]);
1994                         copy_v3_v3(col1[0], col1[2]);
1995                         copy_v3_v3(col1[1], col1[2]);
1996                         copy_v3_v3(col1[3], col1[2]);
1997                         break;
1998                 default:
1999                         assert(!"invalid 'type' argument");
2000                         hsv_to_rgb(1.0, 1.0, 1.0,   &col1[2][0], &col1[2][1], &col1[2][2]);
2001                         copy_v3_v3(col1[0], col1[2]);
2002                         copy_v3_v3(col1[1], col1[2]);
2003                         copy_v3_v3(col1[3], col1[2]);
2004         }
2005         
2006         /* old below */
2007         
2008         for (dx = 0.0f; dx < 1.0f; dx += color_step) {
2009                 // previous color
2010                 copy_v3_v3(col0[0], col1[0]);
2011                 copy_v3_v3(col0[1], col1[1]);
2012                 copy_v3_v3(col0[2], col1[2]);
2013                 copy_v3_v3(col0[3], col1[3]);
2014                 
2015                 // new color
2016                 switch (type) {
2017                         case UI_GRAD_SV:
2018                                 hsv_to_rgb(h, 0.0, dx,   &col1[0][0], &col1[0][1], &col1[0][2]);
2019                                 hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]);
2020                                 hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
2021                                 hsv_to_rgb(h, 1.0, dx,   &col1[3][0], &col1[3][1], &col1[3][2]);
2022                                 break;
2023                         case UI_GRAD_HV:
2024                                 hsv_to_rgb(dx, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2025                                 hsv_to_rgb(dx, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
2026                                 hsv_to_rgb(dx, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
2027                                 hsv_to_rgb(dx, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
2028                                 break;
2029                         case UI_GRAD_HS:
2030                                 hsv_to_rgb(dx, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
2031                                 hsv_to_rgb(dx, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
2032                                 hsv_to_rgb(dx, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
2033                                 hsv_to_rgb(dx, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
2034                                 break;
2035                         case UI_GRAD_H:
2036                         {
2037                                 /* annoying but without this the color shifts - could be solved some other way
2038                                  * - campbell */
2039                                 hsv_to_rgb(dx + color_step, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2040                                 copy_v3_v3(col1[1], col1[0]);
2041                                 copy_v3_v3(col1[2], col1[0]);
2042                                 copy_v3_v3(col1[3], col1[0]);
2043                                 break;
2044                         }
2045                         case UI_GRAD_S:
2046                                 hsv_to_rgb(h, dx, 1.0,   &col1[1][0], &col1[1][1], &col1[1][2]);
2047                                 copy_v3_v3(col1[0], col1[1]);
2048                                 copy_v3_v3(col1[2], col1[1]);
2049                                 copy_v3_v3(col1[3], col1[1]);
2050                                 break;
2051                         case UI_GRAD_V:
2052                                 hsv_to_rgb(h, 1.0, dx,   &col1[2][0], &col1[2][1], &col1[2][2]);
2053                                 copy_v3_v3(col1[0], col1[2]);
2054                                 copy_v3_v3(col1[1], col1[2]);
2055                                 copy_v3_v3(col1[3], col1[2]);
2056                                 break;
2057                 }
2058                 
2059                 // rect
2060                 sx1 = rect->xmin + dx * (rect->xmax - rect->xmin);
2061                 sx2 = rect->xmin + (dx + color_step) * (rect->xmax - rect->xmin);
2062                 sy = rect->ymin;
2063                 dy = (rect->ymax - rect->ymin) / 3.0;
2064                 
2065                 glBegin(GL_QUADS);
2066                 for (a = 0; a < 3; a++, sy += dy) {
2067                         glColor4f(col0[a][0], col0[a][1], col0[a][2], alpha);
2068                         glVertex2f(sx1, sy);
2069                         
2070                         glColor4f(col1[a][0], col1[a][1], col1[a][2], alpha);
2071                         glVertex2f(sx2, sy);
2072
2073                         glColor4f(col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
2074                         glVertex2f(sx2, sy + dy);
2075                         
2076                         glColor4f(col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha);
2077                         glVertex2f(sx1, sy + dy);
2078                 }
2079                 glEnd();
2080         }
2081         
2082         glShadeModel(GL_FLAT);
2083         
2084 }
2085
2086
2087
2088 static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect)
2089 {
2090         float rgb[3];
2091         float x = 0.0f, y = 0.0f;
2092         float *hsv = ui_block_hsv_get(but->block);
2093         float hsv_n[3];
2094         
2095         copy_v3_v3(hsv_n, hsv);
2096         
2097         ui_get_but_vectorf(but, rgb);
2098         rgb_to_hsv_compat_v(rgb, hsv_n);
2099         
2100         ui_draw_gradient(rect, hsv_n, but->a1, 1.0f);
2101         
2102         switch ((int)but->a1) {
2103                 case UI_GRAD_SV:
2104                         x = hsv_n[2]; y = hsv_n[1]; break;
2105                 case UI_GRAD_HV:
2106                         x = hsv_n[0]; y = hsv_n[2]; break;
2107                 case UI_GRAD_HS:
2108                         x = hsv_n[0]; y = hsv_n[1]; break;
2109                 case UI_GRAD_H:
2110                         x = hsv_n[0]; y = 0.5; break;
2111                 case UI_GRAD_S:
2112                         x = hsv_n[1]; y = 0.5; break;
2113                 case UI_GRAD_V:
2114                         x = hsv_n[2]; y = 0.5; break;
2115         }
2116         
2117         /* cursor */
2118         x = rect->xmin + x * (rect->xmax - rect->xmin);
2119         y = rect->ymin + y * (rect->ymax - rect->ymin);
2120         CLAMP(x, rect->xmin + 3.0f, rect->xmax - 3.0f);
2121         CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
2122         
2123         ui_hsv_cursor(x, y);
2124         
2125         /* outline */
2126         glColor3ub(0,  0,  0);
2127         fdrawbox((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
2128 }
2129
2130 /* vertical 'value' slider, using new widget code */
2131 static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
2132 {
2133         uiWidgetBase wtb;
2134         float rad = 0.5f * (rect->xmax - rect->xmin);
2135         float x, y;
2136         float rgb[3], hsv[3], v, range;
2137         int color_profile = but->block->color_profile;
2138         
2139         if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
2140                 color_profile = BLI_PR_NONE;
2141
2142         ui_get_but_vectorf(but, rgb);
2143         rgb_to_hsv_v(rgb, hsv);
2144         v = hsv[2];
2145         
2146         if (color_profile)
2147                 v = linearrgb_to_srgb(v);
2148
2149         /* map v from property range to [0,1] */
2150         range = but->softmax - but->softmin;
2151         v = (v - but->softmin) / range;
2152         
2153         widget_init(&wtb);
2154         
2155         /* fully rounded */
2156         round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
2157         
2158         /* setup temp colors */
2159         wcol_tmp.outline[0] = wcol_tmp.outline[1] = wcol_tmp.outline[2] = 0;
2160         wcol_tmp.inner[0] = wcol_tmp.inner[1] = wcol_tmp.inner[2] = 128;
2161         wcol_tmp.shadetop = 127;
2162         wcol_tmp.shadedown = -128;
2163         wcol_tmp.shaded = 1;
2164         
2165         widgetbase_draw(&wtb, &wcol_tmp);
2166
2167         /* cursor */
2168         x = rect->xmin + 0.5f * (rect->xmax - rect->xmin);
2169         y = rect->ymin + v * (rect->ymax - rect->ymin);
2170         CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
2171         
2172         ui_hsv_cursor(x, y);
2173         
2174 }
2175
2176
2177 /* ************ separator, for menus etc ***************** */
2178 static void ui_draw_separator(rcti *rect,  uiWidgetColors *wcol)
2179 {
2180         int y = rect->ymin + (rect->ymax - rect->ymin) / 2 - 1;
2181         unsigned char col[4];
2182         
2183         col[0] = wcol->text[0];
2184         col[1] = wcol->text[1];
2185         col[2] = wcol->text[2];
2186         col[3] = 7;
2187         
2188         glEnable(GL_BLEND);
2189         glColor4ubv(col);
2190         sdrawline(rect->xmin, y, rect->xmax, y);
2191         glDisable(GL_BLEND);
2192 }
2193
2194 /* ************ button callbacks, draw ***************** */
2195
2196 static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2197 {
2198         uiWidgetBase wtb;
2199         float rad = 0.5f * (rect->ymax - rect->ymin);
2200         float textofs = rad * 0.75f;
2201
2202         if (state & UI_SELECT)
2203                 SWAP(short, wcol->shadetop, wcol->shadedown);
2204         
2205         widget_init(&wtb);
2206         
2207         /* fully rounded */
2208         round_box_edges(&wtb, roundboxalign, rect, rad);
2209         
2210         /* decoration */
2211         if (!(state & UI_TEXTINPUT)) {
2212                 widget_num_tria(&wtb.tria1, rect, 0.6f, 'l');
2213                 widget_num_tria(&wtb.tria2, rect, 0.6f, 'r');
2214         }
2215
2216         widgetbase_draw(&wtb, wcol);
2217         
2218         /* text space */
2219         rect->xmin += textofs;
2220         rect->xmax -= textofs;
2221 }
2222
2223 //static int ui_link_bezier_points(rcti *rect, float coord_array[][2], int resol)
2224 int ui_link_bezier_points(rcti *rect, float coord_array[][2], int resol)
2225 {
2226         float dist, vec[4][2];
2227
2228         vec[0][0] = rect->xmin;
2229         vec[0][1] = rect->ymin;
2230         vec[3][0] = rect->xmax;
2231         vec[3][1] = rect->ymax;
2232         
2233         dist = 0.5f * ABS(vec[0][0] - vec[3][0]);
2234         
2235         vec[1][0] = vec[0][0] + dist;
2236         vec[1][1] = vec[0][1];
2237         
2238         vec[2][0] = vec[3][0] - dist;
2239         vec[2][1] = vec[3][1];
2240         
2241         BKE_curve_forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, sizeof(float) * 2);
2242         BKE_curve_forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0] + 1, resol, sizeof(float) * 2);
2243         
2244         return 1;
2245 }
2246
2247 #define LINK_RESOL  24
2248 void ui_draw_link_bezier(rcti *rect)
2249 {
2250         float coord_array[LINK_RESOL + 1][2];
2251         
2252         if (ui_link_bezier_points(rect, coord_array, LINK_RESOL)) {
2253                 /* we can reuse the dist variable here to increment the GL curve eval amount*/
2254                 // const float dist = 1.0f/(float)LINK_RESOL; // UNUSED
2255
2256                 glEnable(GL_BLEND);
2257                 glEnable(GL_LINE_SMOOTH);
2258
2259                 glEnableClientState(GL_VERTEX_ARRAY);
2260                 glVertexPointer(2, GL_FLOAT, 0, coord_array);
2261                 glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL);
2262                 glDisableClientState(GL_VERTEX_ARRAY);
2263
2264                 glDisable(GL_BLEND);
2265                 glDisable(GL_LINE_SMOOTH);
2266
2267         }
2268 }
2269
2270 /* function in use for buttons and for view2d sliders */
2271 void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int state)
2272 {
2273         uiWidgetBase wtb;
2274         float rad;
2275         int horizontal;
2276         short outline = 0;
2277
2278         widget_init(&wtb);
2279
2280         /* determine horizontal/vertical */
2281         horizontal = (rect->xmax - rect->xmin > rect->ymax - rect->ymin);
2282         
2283         if (horizontal)
2284                 rad = 0.5f * (rect->ymax - rect->ymin);
2285         else
2286                 rad = 0.5f * (rect->xmax - rect->xmin);
2287         
2288         wtb.shadedir = (horizontal) ? 1 : 0;
2289         
2290         /* draw back part, colors swapped and shading inverted */
2291         if (horizontal)
2292                 SWAP(short, wcol->shadetop, wcol->shadedown);
2293         
2294         round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
2295         widgetbase_draw(&wtb, wcol);
2296         
2297         /* slider */
2298         if (slider->xmax - slider->xmin < 2 || slider->ymax - slider->ymin < 2) ;
2299         else {
2300                 
2301                 SWAP(short, wcol->shadetop, wcol->shadedown);
2302                 
2303                 copy_v4_v4_char(wcol->inner, wcol->item);
2304                 
2305                 if (wcol->shadetop > wcol->shadedown)
2306                         wcol->shadetop += 20;   /* XXX violates themes... */
2307                 else wcol->shadedown += 20;
2308                 
2309                 if (state & UI_SCROLL_PRESSED) {
2310                         wcol->inner[0] = wcol->inner[0] >= 250 ? 255 : wcol->inner[0] + 5;
2311                         wcol->inner[1] = wcol->inner[1] >= 250 ? 255 : wcol->inner[1] + 5;
2312                         wcol->inner[2] = wcol->inner[2] >= 250 ? 255 : wcol->inner[2] + 5;
2313                 }
2314
2315                 /* draw */
2316                 wtb.emboss = 0; /* only emboss once */
2317                 
2318                 /* exception for progress bar */
2319                 if (state & UI_SCROLL_NO_OUTLINE)       
2320                         SWAP(short, outline, wtb.outline);
2321                 
2322                 round_box_edges(&wtb, UI_CNR_ALL, slider, rad);
2323                 
2324                 if (state & UI_SCROLL_ARROWS) {
2325                         if (wcol->item[0] > 48) wcol->item[0] -= 48;
2326                         if (wcol->item[1] > 48) wcol->item[1] -= 48;
2327                         if (wcol->item[2] > 48) wcol->item[2] -= 48;
2328                         wcol->item[3] = 255;
2329                         
2330                         if (horizontal) {
2331                                 widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
2332                                 widget_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
2333                         }
2334                         else {
2335                                 widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
2336                                 widget_scroll_circle(&wtb.tria2, slider, 0.6f, 't');
2337                         }
2338                 }
2339                 widgetbase_draw(&wtb, wcol);
2340                 
2341                 if (state & UI_SCROLL_NO_OUTLINE)
2342                         SWAP(short, outline, wtb.outline);
2343         }       
2344 }
2345
2346 static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2347 {
2348         rcti rect1;
2349         double value;
2350         float fac, size, min;
2351         int horizontal;
2352
2353         /* calculate slider part */
2354         value = ui_get_but_val(but);
2355
2356         size = (but->softmax + but->a1 - but->softmin);
2357         size = MAX2(size, 2);
2358         
2359         /* position */
2360         rect1 = *rect;
2361
2362         /* determine horizontal/vertical */
2363         horizontal = (rect->xmax - rect->xmin > rect->ymax - rect->ymin);
2364         
2365         if (horizontal) {
2366                 fac = (rect->xmax - rect->xmin) / (size);
2367                 rect1.xmin = rect1.xmin + ceilf(fac * ((float)value - but->softmin));
2368                 rect1.xmax = rect1.xmin + ceilf(fac * (but->a1 - but->softmin));
2369
2370                 /* ensure minimium size */
2371                 min = rect->ymax - rect->ymin;
2372
2373                 if (rect1.xmax - rect1.xmin < min) {
2374                         rect1.xmax = rect1.xmin + min;
2375
2376                         if (rect1.xmax > rect->xmax) {
2377                                 rect1.xmax = rect->xmax;
2378                                 rect1.xmin = MAX2(rect1.xmax - min, rect->xmin);
2379                         }
2380                 }
2381         }
2382         else {
2383                 fac = (rect->ymax - rect->ymin) / (size);
2384                 rect1.ymax = rect1.ymax - ceilf(fac * ((float)value - but->softmin));
2385                 rect1.ymin = rect1.ymax - ceilf(fac * (but->a1 - but->softmin));
2386
2387                 /* ensure minimium size */
2388                 min = rect->xmax - rect->xmin;
2389
2390                 if (rect1.ymax - rect1.ymin < min) {
2391                         rect1.ymax = rect1.ymin + min;
2392
2393                         if (rect1.ymax > rect->ymax) {
2394                                 rect1.ymax = rect->ymax;
2395                                 rect1.ymin = MAX2(rect1.ymax - min, rect->ymin);
2396                         }
2397                 }
2398         }
2399
2400         if (state & UI_SELECT)
2401                 state = UI_SCROLL_PRESSED;
2402         else
2403                 state = 0;
2404         uiWidgetScrollDraw(wcol, rect, &rect1, state);
2405 }
2406
2407 static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2408 {
2409         rcti rect_prog = *rect, rect_bar = *rect;
2410         float value = but->a1;
2411         float w, min;
2412         
2413         /* make the progress bar a proportion of the original height */
2414         /* hardcoded 4px high for now */
2415         rect_prog.ymax = rect_prog.ymin + 4;
2416         rect_bar.ymax = rect_bar.ymin + 4;
2417         
2418         w = value * (rect_prog.xmax - rect_prog.xmin);
2419         
2420         /* ensure minimium size */
2421         min = rect_prog.ymax - rect_prog.ymin;
2422         w = MAX2(w, min);
2423         
2424         rect_bar.xmax = rect_bar.xmin + w;
2425                 
2426         uiWidgetScrollDraw(wcol, &rect_prog, &rect_bar, UI_SCROLL_NO_OUTLINE);
2427         
2428         /* raise text a bit */
2429         rect->ymin += 6;
2430         rect->xmin -= 6;
2431 }
2432
2433 static void widget_link(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2434 {
2435         
2436         if (but->flag & UI_SELECT) {
2437                 rcti rectlink;
2438                 
2439                 UI_ThemeColor(TH_TEXT_HI);
2440                 
2441                 rectlink.xmin = (rect->xmin + rect->xmax) / 2;
2442                 rectlink.ymin = (rect->ymin + rect->ymax) / 2;
2443                 rectlink.xmax = but->linkto[0];
2444                 rectlink.ymax = but->linkto[1];
2445                 
2446                 ui_draw_link_bezier(&rectlink);
2447         }
2448 }
2449
2450 static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2451 {
2452         uiWidgetBase wtb, wtb1;
2453         rcti rect1;
2454         double value;
2455         float offs, toffs, fac;
2456         char outline[3];
2457
2458         widget_init(&wtb);
2459         widget_init(&wtb1);
2460         
2461         /* backdrop first */
2462         
2463         /* fully rounded */
2464         offs = 0.5f * (rect->ymax - rect->ymin);
2465         toffs = offs * 0.75f;
2466         round_box_edges(&wtb, roundboxalign, rect, offs);
2467
2468         wtb.outline = 0;
2469         widgetbase_draw(&wtb, wcol);
2470         
2471         /* draw left/right parts only when not in text editing */
2472         if (!(state & UI_TEXTINPUT)) {
2473                 
2474                 /* slider part */
2475                 copy_v3_v3_char(outline, wcol->outline);
2476                 copy_v3_v3_char(wcol->outline, wcol->item);
2477                 copy_v3_v3_char(wcol->inner, wcol->item);
2478
2479                 if (!(state & UI_SELECT))
2480                         SWAP(short, wcol->shadetop, wcol->shadedown);
2481                 
2482                 rect1 = *rect;
2483                 
2484                 value = ui_get_but_val(but);
2485                 fac = ((float)value - but->softmin) * (rect1.xmax - rect1.xmin - offs) / (but->softmax - but->softmin);
2486                 
2487                 /* left part of slider, always rounded */
2488                 rect1.xmax = rect1.xmin + ceil(offs + 1.0f);
2489                 round_box_edges(&wtb1, roundboxalign & ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT), &rect1, offs);
2490                 wtb1.outline = 0;
2491                 widgetbase_draw(&wtb1, wcol);
2492                 
2493                 /* right part of slider, interpolate roundness */
2494                 rect1.xmax = rect1.xmin + fac + offs;
2495                 rect1.xmin +=  floor(offs - 1.0f);
2496                 if (rect1.xmax + offs > rect->xmax)
2497                         offs *= (rect1.xmax + offs - rect->xmax) / offs;
2498                 else 
2499                         offs = 0.0f;
2500                 round_box_edges(&wtb1, roundboxalign & ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT), &rect1, offs);
2501                 
2502                 widgetbase_draw(&wtb1, wcol);
2503                 copy_v3_v3_char(wcol->outline, outline);
2504                 
2505                 if (!(state & UI_SELECT))
2506                         SWAP(short, wcol->shadetop, wcol->shadedown);
2507         }
2508         
2509         /* outline */
2510         wtb.outline = 1;
2511         wtb.inner = 0;
2512         widgetbase_draw(&wtb, wcol);
2513         
2514         /* text space */
2515         rect->xmin += toffs;
2516         rect->xmax -= toffs;
2517 }
2518
2519 /* I think 3 is sufficient border to indicate keyed status */
2520 #define SWATCH_KEYED_BORDER 3
2521
2522 static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2523 {
2524         uiWidgetBase wtb;
2525         float col[4];
2526         int color_profile = but->block->color_profile;
2527         
2528         col[3] = 1.0f;
2529
2530         if (but->rnaprop) {
2531                 if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
2532                         color_profile = BLI_PR_NONE;
2533
2534                 if (RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4) {
2535                         col[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
2536                 }
2537         }
2538         
2539         widget_init(&wtb);
2540         
2541         /* half rounded */
2542         round_box_edges(&wtb, roundboxalign, rect, 5.0f);
2543                 
2544         ui_get_but_vectorf(but, col);
2545
2546         if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
2547                 /* draw based on state - color for keyed etc */
2548                 widgetbase_draw(&wtb, wcol);
2549
2550                 /* inset to draw swatch color */
2551                 rect->xmin += SWATCH_KEYED_BORDER;
2552                 rect->xmax -= SWATCH_KEYED_BORDER;
2553                 rect->ymin += SWATCH_KEYED_BORDER;
2554                 rect->ymax -= SWATCH_KEYED_BORDER;
2555                 
2556                 round_box_edges(&wtb, roundboxalign, rect, 5.0f);
2557         }
2558         
2559         if (color_profile)
2560                 linearrgb_to_srgb_v3_v3(col, col);
2561         
2562         rgba_float_to_uchar((unsigned char *)wcol->inner, col);
2563
2564         wcol->shaded = 0;
2565         wcol->alpha_check = (wcol->inner[3] < 255);
2566
2567         widgetbase_draw(&wtb, wcol);
2568         
2569 }
2570
2571 static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2572 {
2573         if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
2574                 uiWidgetBase wtb;
2575         
2576                 widget_init(&wtb);
2577                 wtb.outline = 0;
2578                 
2579                 /* rounded */
2580                 round_box_edges(&wtb, UI_CNR_ALL, rect, 10.0f);
2581                 widgetbase_draw(&wtb, wcol);
2582         }       
2583 }
2584
2585
2586 static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2587 {
2588         uiWidgetBase wtb;
2589         
2590         if (state & UI_SELECT)
2591                 SWAP(short, wcol->shadetop, wcol->shadedown);
2592         
2593         widget_init(&wtb);
2594         
2595         /* half rounded */
2596         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2597         
2598         widgetbase_draw(&wtb, wcol);
2599
2600 }
2601
2602
2603 static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2604 {
2605         uiWidgetBase wtb;
2606         
2607         widget_init(&wtb);
2608         
2609         /* half rounded */
2610         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2611         
2612         /* decoration */
2613         widget_menu_trias(&wtb.tria1, rect);
2614         
2615         widgetbase_draw(&wtb, wcol);
2616         
2617         /* text space */
2618         rect->xmax -= (rect->ymax - rect->ymin);
2619 }
2620
2621 static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2622 {
2623         uiWidgetBase wtb;
2624         
2625         widget_init(&wtb);
2626         
2627         /* half rounded */
2628         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2629         
2630         /* decoration */
2631         widgetbase_draw(&wtb, wcol);
2632 }
2633
2634 static void widget_menunodebut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2635 {
2636         /* silly node link button hacks */
2637         uiWidgetBase wtb;
2638         uiWidgetColors wcol_backup = *wcol;
2639         
2640         widget_init(&wtb);
2641         
2642         /* half rounded */
2643         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2644
2645         wcol->inner[0] += 15;
2646         wcol->inner[1] += 15;
2647         wcol->inner[2] += 15;
2648         wcol->outline[0] += 15;
2649         wcol->outline[1] += 15;
2650         wcol->outline[2] += 15;
2651         
2652         /* decoration */
2653         widgetbase_draw(&wtb, wcol);
2654         *wcol = wcol_backup;
2655 }
2656
2657 static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2658 {
2659         if (state & UI_ACTIVE) {
2660                 uiWidgetBase wtb;
2661                 float rad = 0.5f * (rect->ymax - rect->ymin); // 4.0f
2662                 
2663                 widget_init(&wtb);
2664                 
2665                 /* half rounded */
2666                 round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
2667                 
2668                 widgetbase_draw(&wtb, wcol);
2669         }
2670 }
2671
2672 static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2673 {
2674         uiWidgetBase wtb;
2675         
2676         widget_init(&wtb);
2677         
2678         /* not rounded, no outline */
2679         wtb.outline = 0;
2680         round_box_edges(&wtb, 0, rect, 0.0f);
2681         
2682         widgetbase_draw(&wtb, wcol);
2683 }
2684
2685 static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2686 {
2687         uiWidgetBase wtb;
2688         
2689         widget_init(&wtb);
2690         
2691         /* rounded, but no outline */
2692         wtb.outline = 0;
2693         round_box_edges(&wtb, UI_CNR_ALL, rect, 4.0f);
2694         
2695         widgetbase_draw(&wtb, wcol);
2696 }
2697
2698 static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2699 {
2700         uiWidgetBase wtb;
2701         rcti recttemp = *rect;
2702         int delta;
2703         
2704         widget_init(&wtb);
2705         
2706         /* square */
2707         recttemp.xmax = recttemp.xmin + (recttemp.ymax - recttemp.ymin);
2708         
2709         /* smaller */
2710         delta = 1 + (recttemp.ymax - recttemp.ymin) / 8;
2711         recttemp.xmin += delta;
2712         recttemp.ymin += delta;
2713         recttemp.xmax -= delta;
2714         recttemp.ymax -= delta;
2715         
2716         /* half rounded */
2717         round_box_edges(&wtb, UI_CNR_ALL, &recttemp, 4.0f);
2718         
2719         /* decoration */
2720         if (state & UI_SELECT) {
2721                 widget_check_trias(&wtb.tria1, &recttemp);
2722         }
2723         
2724         widgetbase_draw(&wtb, wcol);
2725         
2726         /* text space */
2727         rect->xmin += (rect->ymax - rect->ymin) * 0.7 + delta;
2728 }
2729
2730
2731 static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2732 {
2733         uiWidgetBase wtb;
2734         
2735         widget_init(&wtb);
2736         
2737         /* half rounded */
2738         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2739         
2740         widgetbase_draw(&wtb, wcol);
2741
2742 }
2743
2744 static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2745 {
2746         uiWidgetBase wtb;
2747         char old_col[3];
2748         
2749         widget_init(&wtb);
2750         
2751         copy_v3_v3_char(old_col, wcol->inner);
2752         
2753         /* abuse but->hsv - if it's non-zero, use this color as the box's background */
2754         if (but->col[3]) {
2755                 wcol->inner[0] = but->col[0];
2756                 wcol->inner[1] = but->col[1];
2757                 wcol->inner[2] = but->col[2];
2758         }
2759         
2760         /* half rounded */
2761         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2762         
2763         widgetbase_draw(&wtb, wcol);
2764         
2765         /* store the box bg as gl clearcolor, to retrieve later when drawing semi-transparent rects
2766          * over the top to indicate disabled buttons */
2767         /* XXX, this doesnt work right since the color applies to buttons outside the box too. */
2768         glClearColor(wcol->inner[0] / 255.0, wcol->inner[1] / 255.0, wcol->inner[2] / 255.0, 1.0);
2769         
2770         copy_v3_v3_char(wcol->inner, old_col);
2771 }
2772
2773 static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2774 {
2775         uiWidgetBase wtb;
2776         
2777         widget_init(&wtb);
2778         
2779         /* half rounded */
2780         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2781                 
2782         widgetbase_draw(&wtb, wcol);
2783
2784 }
2785
2786 static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2787 {
2788         uiWidgetBase wtb;
2789         float rad = 5.0f; //0.5f*(rect->ymax - rect->ymin);
2790         
2791         widget_init(&wtb);
2792         
2793         /* half rounded */
2794         round_box_edges(&wtb, roundboxalign, rect, rad);
2795
2796         widgetbase_draw(&wtb, wcol);
2797 }
2798
2799 static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
2800 {
2801         uiWidgetBase wtb;
2802         unsigned char col[4];
2803         
2804         /* state copy! */
2805         wt->wcol = *(wt->wcol_theme);
2806         
2807         widget_init(&wtb);
2808         
2809         if (but->block->drawextra) {
2810                 /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
2811                 but->block->drawextra(C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect);
2812                 
2813                 /* make mask to draw over image */
2814                 UI_GetThemeColor3ubv(TH_BACK, col);
2815                 glColor3ubv(col);
2816                 
2817                 round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, 4.0);
2818                 widgetbase_outline(&wtb);
2819         }
2820         
2821         /* outline */
2822         round_box_edges(&wtb, UI_CNR_ALL, rect, 5.0f);
2823         wtb.outline = 1;
2824         wtb.inner = 0;
2825         widgetbase_draw(&wtb, &wt->wcol);
2826         
2827 }
2828
2829
2830 static void widget_disabled(rcti *rect)
2831 {
2832         float col[4];
2833         
2834         glEnable(GL_BLEND);
2835         
2836         /* can't use theme TH_BACK or TH_PANEL... undefined */
2837         glGetFloatv(GL_COLOR_CLEAR_VALUE, col);
2838         glColor4f(col[0], col[1], col[2], 0.5f);
2839
2840         /* need -1 and +1 to make it work right for aligned buttons,
2841          * but problem may be somewhere else? */
2842         glRectf(rect->xmin - 1, rect->ymin - 1, rect->xmax, rect->ymax + 1);
2843         
2844         glDisable(GL_BLEND);
2845 }
2846
2847 static uiWidgetType *widget_type(uiWidgetTypeEnum type)
2848 {
2849         bTheme *btheme = UI_GetTheme();
2850         static uiWidgetType wt;
2851         
2852         /* defaults */
2853         wt.wcol_theme = &btheme->tui.wcol_regular;
2854         wt.wcol_state = &btheme->tui.wcol_state;
2855         wt.state = widget_state;
2856         wt.draw = widget_but;
2857         wt.custom = NULL;
2858         wt.text = widget_draw_text_icon;
2859         
2860         switch (type) {
2861                 case UI_WTYPE_REGULAR:
2862                         break;
2863
2864                 case UI_WTYPE_LABEL:
2865                         wt.draw = NULL;
2866                         wt.state = widget_state_label;
2867                         break;
2868                         
2869                 case UI_WTYPE_TOGGLE:
2870                         wt.wcol_theme = &btheme->tui.wcol_toggle;
2871                         break;
2872                         
2873                 case UI_WTYPE_OPTION:
2874                         wt.wcol_theme = &btheme->tui.wcol_option;
2875                         wt.draw = widget_optionbut;
2876                         break;
2877                         
2878                 case UI_WTYPE_RADIO:
2879                         wt.wcol_theme = &btheme->tui.wcol_radio;
2880                         wt.draw = widget_radiobut;
2881                         break;
2882
2883                 case UI_WTYPE_NUMBER:
2884                         wt.wcol_theme = &btheme->tui.wcol_num;
2885                         wt.draw = widget_numbut;
2886                         break;
2887                         
2888                 case UI_WTYPE_SLIDER:
2889                         wt.wcol_theme = &btheme->tui.wcol_numslider;
2890                         wt.custom = widget_numslider;
2891                         wt.state = widget_state_numslider;
2892                         break;
2893                         
2894                 case UI_WTYPE_EXEC:
2895                         wt.wcol_theme = &btheme->tui.wcol_tool;
2896                         wt.draw = widget_roundbut;
2897                         break;
2898
2899                 case UI_WTYPE_TOOLTIP:
2900                         wt.wcol_theme = &btheme->tui.wcol_tooltip;
2901                         wt.draw = widget_menu_back;
2902                         break;
2903                         
2904                         
2905                 /* strings */
2906                 case UI_WTYPE_NAME:
2907                         wt.wcol_theme = &btheme->tui.wcol_text;
2908                         wt.draw = widget_textbut;
2909                         break;
2910                         
2911                 case UI_WTYPE_NAME_LINK:
2912                         break;
2913                         
2914                 case UI_WTYPE_POINTER_LINK:
2915                         break;
2916                         
2917                 case UI_WTYPE_FILENAME:
2918                         break;
2919                         
2920                         
2921                 /* start menus */
2922                 case UI_WTYPE_MENU_RADIO:
2923                         wt.wcol_theme = &btheme->tui.wcol_menu;
2924                         wt.draw = widget_menubut;
2925                         break;
2926
2927                 case UI_WTYPE_MENU_ICON_RADIO:
2928                         wt.wcol_theme = &btheme->tui.wcol_menu;
2929                         wt.draw = widget_menuiconbut;
2930                         break;
2931                         
2932                 case UI_WTYPE_MENU_POINTER_LINK:
2933                         wt.wcol_theme = &btheme->tui.wcol_menu;
2934                         wt.draw = widget_menubut;
2935                         break;
2936
2937                 case UI_WTYPE_MENU_NODE_LINK:
2938                         wt.wcol_theme = &btheme->tui.wcol_menu;
2939                         wt.draw = widget_menunodebut;
2940                         break;
2941                         
2942                 case UI_WTYPE_PULLDOWN:
2943                         wt.wcol_theme = &btheme->tui.wcol_pulldown;
2944                         wt.draw = widget_pulldownbut;
2945                         wt.state = widget_state_pulldown;
2946                         break;
2947                         
2948                 /* in menus */
2949                 case UI_WTYPE_MENU_ITEM:
2950                         wt.wcol_theme = &btheme->tui.wcol_menu_item;
2951                         wt.draw = widget_menu_itembut;
2952                         wt.state = widget_state_menu_item;
2953                         break;
2954                         
2955                 case UI_WTYPE_MENU_BACK:
2956                         wt.wcol_theme = &btheme->tui.wcol_menu_back;
2957                         wt.draw = widget_menu_back;
2958                         break;
2959                         
2960                 /* specials */
2961                 case UI_WTYPE_ICON:
2962                         wt.custom = widget_icon_has_anim;
2963                         break;
2964                         
2965                 case UI_WTYPE_SWATCH:
2966                         wt.custom = widget_swatch;
2967                         break;
2968                         
2969                 case UI_WTYPE_BOX:
2970                         wt.custom = widget_box;
2971                         wt.wcol_theme = &btheme->tui.wcol_box;
2972                         break;
2973                         
2974                 case UI_WTYPE_RGB_PICKER:
2975                         break;
2976                         
2977                 case UI_WTYPE_NORMAL:
2978                         break;
2979
2980                 case UI_WTYPE_SCROLL:
2981                         wt.wcol_theme = &btheme->tui.wcol_scroll;
2982                         wt.state = widget_state_nothing;
2983                         wt.custom = widget_scroll;
2984                         break;
2985
2986                 case UI_WTYPE_LISTITEM:
2987                         wt.wcol_theme = &btheme->tui.wcol_list_item;
2988                         wt.draw = widget_list_itembut;
2989                         break;
2990                         
2991                 case UI_WTYPE_PROGRESSBAR:
2992                         wt.wcol_theme = &btheme->tui.wcol_progress;
2993                         wt.custom = widget_progressbar;
2994                         break;
2995         }
2996         
2997         return &wt;
2998 }
2999
3000
3001 static int widget_roundbox_set(uiBut *but, rcti *rect)
3002 {
3003         /* alignment */
3004         if (but->flag & UI_BUT_ALIGN) {
3005                 
3006                 if (but->flag & UI_BUT_ALIGN_TOP)
3007                         rect->ymax += 1;
3008                 if (but->flag & UI_BUT_ALIGN_LEFT)
3009                         rect->xmin -= 1;
3010                 
3011                 switch (but->flag & UI_BUT_ALIGN) {
3012                         case UI_BUT_ALIGN_TOP:
3013                                 return UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT;
3014                         case UI_BUT_ALIGN_DOWN:
3015                                 return UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
3016                         case UI_BUT_ALIGN_LEFT:
3017                                 return UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT;
3018                         case UI_BUT_ALIGN_RIGHT:
3019                                 return UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT;
3020                         case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_RIGHT:
3021                                 return UI_CNR_TOP_LEFT;
3022                         case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT:
3023                                 return UI_CNR_TOP_RIGHT;
3024                         case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT:
3025                                 return UI_CNR_BOTTOM_LEFT;
3026                         case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT:
3027                                 return UI_CNR_BOTTOM_RIGHT;
3028                         default:
3029                                 return 0;
3030                 }
3031         }
3032
3033         return UI_CNR_ALL;
3034 }
3035
3036 /* conversion from old to new buttons, so still messy */
3037 void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
3038 {
3039         bTheme *btheme = UI_GetTheme();
3040         ThemeUI *tui = &btheme->tui;
3041         uiFontStyle *fstyle = &style->widget;
3042         uiWidgetType *wt = NULL;
3043
3044         /* handle menus separately */
3045         if (but->dt == UI_EMBOSSP) {
3046                 switch (but->type) {
3047                         case LABEL:
3048                                 widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
3049                                 break;
3050                         case SEPR:
3051                                 ui_draw_separator(rect, &tui->wcol_menu_item);
3052                                 break;
3053                                 
3054                         default:
3055                                 wt = widget_type(UI_WTYPE_MENU_ITEM);
3056                 }
3057         }
3058         else if (but->dt == UI_EMBOSSN) {
3059                 /* "nothing" */
3060                 wt = widget_type(UI_WTYPE_ICON);
3061         }
3062         else {
3063                 
3064                 switch (but->type) {
3065                         case LABEL:
3066                                 if (but->block->flag & UI_BLOCK_LOOP)
3067                                         widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
3068                                 else {
3069                                         wt = widget_type(UI_WTYPE_LABEL);
3070                                         fstyle = &style->widgetlabel;
3071                                 }
3072                                 break;
3073                                 
3074                         case SEPR:
3075                                 break;
3076                                 
3077                         case BUT:
3078                                 wt = widget_type(UI_WTYPE_EXEC);
3079                                 break;
3080
3081                         case NUM:
3082                                 wt = widget_type(UI_WTYPE_NUMBER);
3083                                 break;
3084                                 
3085                         case NUMSLI:
3086                         case HSVSLI:
3087                                 wt = widget_type(UI_WTYPE_SLIDER);
3088                                 break;
3089                                 
3090                         case ROW:
3091                                 wt = widget_type(UI_WTYPE_RADIO);
3092                                 break;
3093
3094                         case LISTROW:
3095                                 wt = widget_type(UI_WTYPE_LISTITEM);
3096                                 break;
3097                                 
3098                         case TEX:
3099                                 wt = widget_type(UI_WTYPE_NAME);
3100                                 break;
3101                                 
3102                         case SEARCH_MENU:
3103                                 wt = widget_type(UI_WTYPE_NAME);
3104                                 if (but->block->flag & UI_BLOCK_LOOP)
3105                                         wt->wcol_theme = &btheme->tui.wcol_menu_back;
3106                                 break;
3107                                 
3108                         case TOGBUT:
3109                         case TOG:
3110                         case TOGN:
3111                         case TOG3:
3112                                 wt = widget_type(UI_WTYPE_TOGGLE);
3113                                 break;
3114                                 
3115                         case OPTION:
3116                         case OPTIONN:
3117                                 if (!(but->flag & UI_HAS_ICON)) {
3118                                         wt = widget_type(UI_WTYPE_OPTION);
3119                                         but->flag |= UI_TEXT_LEFT;
3120                                 }
3121                                 else
3122                                         wt = widget_type(UI_WTYPE_TOGGLE);
3123                                 
3124                                 /* option buttons have strings outside, on menus use different colors */
3125                                 if (but->block->flag & UI_BLOCK_LOOP)
3126                                         wt->state = widget_state_option_menu;