ee22393c08faa8157b18ac4fe96d8da2c1ea8eca
[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
50 #include "RNA_access.h"
51
52 #include "BIF_gl.h"
53 #include "BIF_glutil.h"
54
55 #include "BLF_api.h"
56
57 #include "UI_interface.h"
58 #include "UI_interface_icons.h"
59
60
61 #include "interface_intern.h"
62
63 /* ************** widget base functions ************** */
64 /*
65  * - in: roundbox codes for corner types and radius
66  * - return: array of [size][2][x,y] points, the edges of the roundbox, + UV coords
67  *
68  * - draw black box with alpha 0 on exact button boundbox
69  * - for ever AA step:
70  *    - draw the inner part for a round filled box, with color blend codes or texture coords
71  *    - draw outline in outline color
72  *    - draw outer part, bottom half, extruded 1 pixel to bottom, for emboss shadow
73  *    - draw extra decorations
74  * - draw background color box with alpha 1 on exact button boundbox
75  */
76
77 /* fill this struct with polygon info to draw AA'ed */
78 /* it has outline, back, and two optional tria meshes */
79
80 typedef struct uiWidgetTrias {
81         unsigned int tot;
82         
83         float vec[32][2];
84         unsigned int (*index)[3];
85         
86 } uiWidgetTrias;
87
88 /* max as used by round_box__edges */
89 #define WIDGET_CURVE_RESOLU 9
90 #define WIDGET_SIZE_MAX (WIDGET_CURVE_RESOLU * 4)
91
92 typedef struct uiWidgetBase {
93         
94         int totvert, halfwayvert;
95         float outer_v[WIDGET_SIZE_MAX][2];
96         float inner_v[WIDGET_SIZE_MAX][2];
97         float inner_uv[WIDGET_SIZE_MAX][2];
98         
99         short inner, outline, emboss; /* set on/off */
100         short shadedir;
101         
102         uiWidgetTrias tria1;
103         uiWidgetTrias tria2;
104         
105 } uiWidgetBase;
106
107 /* uiWidgetType: for time being only for visual appearance,
108  * later, a handling callback can be added too 
109  */
110 typedef struct uiWidgetType {
111         
112         /* pointer to theme color definition */
113         uiWidgetColors *wcol_theme;
114         uiWidgetStateColors *wcol_state;
115         
116         /* converted colors for state */
117         uiWidgetColors wcol;
118         
119         void (*state)(struct uiWidgetType *, int state);
120         void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign);
121         void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign);
122         void (*text)(uiFontStyle *, uiWidgetColors *, uiBut *, rcti *);
123         
124 } uiWidgetType;
125
126
127 /* *********************** draw data ************************** */
128
129 static float cornervec[WIDGET_CURVE_RESOLU][2] = {
130         {0.0, 0.0}, {0.195, 0.02}, {0.383, 0.067},
131         {0.55, 0.169}, {0.707, 0.293}, {0.831, 0.45},
132         {0.924, 0.617}, {0.98, 0.805}, {1.0, 1.0}
133 };
134
135 #define WIDGET_AA_JITTER 8
136 static float jit[WIDGET_AA_JITTER][2] = {
137         { 0.468813, -0.481430}, {-0.155755, -0.352820},
138         { 0.219306, -0.238501}, {-0.393286, -0.110949},
139         {-0.024699,  0.013908}, { 0.343805,  0.147431},
140         {-0.272855,  0.269918}, { 0.095909,  0.388710}
141 };
142
143 static float num_tria_vert[3][2] = {
144         {-0.352077, 0.532607}, {-0.352077, -0.549313}, {0.330000, -0.008353}
145 };
146
147 static unsigned int num_tria_face[1][3] = {
148         {0, 1, 2}
149 };
150
151 static float scroll_circle_vert[16][2] = {
152         {0.382684, 0.923879}, {0.000001, 1.000000}, {-0.382683, 0.923880}, {-0.707107, 0.707107},
153         {-0.923879, 0.382684}, {-1.000000, 0.000000}, {-0.923880, -0.382684}, {-0.707107, -0.707107},
154         {-0.382683, -0.923880}, {0.000000, -1.000000}, {0.382684, -0.923880}, {0.707107, -0.707107},
155         {0.923880, -0.382684}, {1.000000, -0.000000}, {0.923880, 0.382683}, {0.707107, 0.707107}
156 };
157
158 static unsigned int scroll_circle_face[14][3] = {
159         {0, 1, 2}, {2, 0, 3}, {3, 0, 15}, {3, 15, 4}, {4, 15, 14}, {4, 14, 5}, {5, 14, 13}, {5, 13, 6},
160         {6, 13, 12}, {6, 12, 7}, {7, 12, 11}, {7, 11, 8}, {8, 11, 10}, {8, 10, 9}
161 };
162
163
164 static float menu_tria_vert[6][2] = {
165         {-0.33, 0.16}, {0.33, 0.16}, {0, 0.82},
166         {0, -0.82}, {-0.33, -0.16}, {0.33, -0.16}
167 };
168
169
170
171 static unsigned int menu_tria_face[2][3] = {{2, 0, 1}, {3, 5, 4}};
172
173 static float check_tria_vert[6][2] = {
174         {-0.578579, 0.253369},  {-0.392773, 0.412794},  {-0.004241, -0.328551},
175         {-0.003001, 0.034320},  {1.055313, 0.864744},   {0.866408, 1.026895}
176 };
177
178 static unsigned int check_tria_face[4][3] = {
179         {3, 2, 4}, {3, 4, 5}, {1, 0, 3}, {0, 2, 3}
180 };
181
182 GLubyte checker_stipple_sml[32 * 32 / 8] =
183 {
184         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
185         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
186         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
187         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
188         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
189         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
190         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
191         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
192 };
193
194 /* ************************************************* */
195
196 void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3)
197 {
198         float tri_arr[3][2] = {{x1, y1}, {x2, y2}, {x3, y3}};
199         float color[4];
200         int j;
201         
202         glEnable(GL_BLEND);
203         glGetFloatv(GL_CURRENT_COLOR, color);
204         color[3] *= 0.125f;
205         glColor4fv(color);
206
207         glEnableClientState(GL_VERTEX_ARRAY);
208         glVertexPointer(2, GL_FLOAT, 0, tri_arr);
209
210         /* for each AA step */
211         for (j = 0; j < WIDGET_AA_JITTER; j++) {
212                 glTranslatef(1.0f * jit[j][0], 1.0f * jit[j][1], 0.0f);
213                 glDrawArrays(GL_TRIANGLES, 0, 3);
214                 glTranslatef(-1.0f * jit[j][0], -1.0f * jit[j][1], 0.0f);
215         }
216
217         glDisableClientState(GL_VERTEX_ARRAY);
218         glDisable(GL_BLEND);
219 }
220
221 void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad)
222 {
223         float color[4];
224         int j;
225         
226         glEnable(GL_BLEND);
227         glGetFloatv(GL_CURRENT_COLOR, color);
228         color[3] *= 0.125f;
229         glColor4fv(color);
230         
231         for (j = 0; j < WIDGET_AA_JITTER; j++) {
232                 glTranslatef(1.0f * jit[j][0], 1.0f * jit[j][1], 0.0f);
233                 uiDrawBox(mode, minx, miny, maxx, maxy, rad);
234                 glTranslatef(-1.0f * jit[j][0], -1.0f * jit[j][1], 0.0f);
235         }
236
237         glDisable(GL_BLEND);
238 }
239
240 static void widget_init(uiWidgetBase *wtb)
241 {
242         wtb->totvert = wtb->halfwayvert = 0;
243         wtb->tria1.tot = 0;
244         wtb->tria2.tot = 0;
245
246         wtb->inner = 1;
247         wtb->outline = 1;
248         wtb->emboss = 1;
249         wtb->shadedir = 1;
250 }
251
252 /* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
253 /* return tot */
254 static int round_box_shadow_edges(float (*vert)[2], rcti *rect, float rad, int roundboxalign, float step)
255 {
256         float vec[WIDGET_CURVE_RESOLU][2];
257         float minx, miny, maxx, maxy;
258         int a, tot = 0;
259         
260         rad += step;
261         
262         if (2.0f * rad > BLI_RCT_SIZE_Y(rect))
263                 rad = 0.5f * BLI_RCT_SIZE_Y(rect);
264         
265         minx = rect->xmin - step;
266         miny = rect->ymin - step;
267         maxx = rect->xmax + step;
268         maxy = rect->ymax + step;
269         
270         /* mult */
271         for (a = 0; a < WIDGET_CURVE_RESOLU; a++) {
272                 vec[a][0] = rad * cornervec[a][0];
273                 vec[a][1] = rad * cornervec[a][1];
274         }
275         
276         /* start with left-top, anti clockwise */
277         if (roundboxalign & UI_CNR_TOP_LEFT) {
278                 for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
279                         vert[tot][0] = minx + rad - vec[a][0];
280                         vert[tot][1] = maxy - vec[a][1];
281                 }
282         }
283         else {
284                 for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
285                         vert[tot][0] = minx;
286                         vert[tot][1] = maxy;
287                 }
288         }
289         
290         if (roundboxalign & UI_CNR_BOTTOM_LEFT) {
291                 for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
292                         vert[tot][0] = minx + vec[a][1];
293                         vert[tot][1] = miny + rad - vec[a][0];
294                 }
295         }
296         else {
297                 for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
298                         vert[tot][0] = minx;
299                         vert[tot][1] = miny;
300                 }
301         }
302         
303         if (roundboxalign & UI_CNR_BOTTOM_RIGHT) {
304                 for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
305                         vert[tot][0] = maxx - rad + vec[a][0];
306                         vert[tot][1] = miny + vec[a][1];
307                 }
308         }
309         else {
310                 for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
311                         vert[tot][0] = maxx;
312                         vert[tot][1] = miny;
313                 }
314         }
315         
316         if (roundboxalign & UI_CNR_TOP_RIGHT) {
317                 for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
318                         vert[tot][0] = maxx - vec[a][1];
319                         vert[tot][1] = maxy - rad + vec[a][0];
320                 }
321         }
322         else {
323                 for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
324                         vert[tot][0] = maxx;
325                         vert[tot][1] = maxy;
326                 }
327         }
328         return tot;
329 }
330
331 /* this call has 1 extra arg to allow mask outline */
332 static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, float rad, float radi)
333 {
334         float vec[WIDGET_CURVE_RESOLU][2], veci[WIDGET_CURVE_RESOLU][2];
335         float minx = rect->xmin, miny = rect->ymin, maxx = rect->xmax, maxy = rect->ymax;
336         float minxi = minx + 1.0f; /* boundbox inner */
337         float maxxi = maxx - 1.0f;
338         float minyi = miny + 1.0f;
339         float maxyi = maxy - 1.0f;
340         float facxi = (maxxi != minxi) ? 1.0f / (maxxi - minxi) : 0.0f; /* for uv, can divide by zero */
341         float facyi = (maxyi != minyi) ? 1.0f / (maxyi - minyi) : 0.0f;
342         int a, tot = 0, minsize;
343         const int hnum = ((roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT)) == (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT) ||
344                           (roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT)) == (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT)) ? 1 : 2;
345         const int vnum = ((roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)) == (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT) ||
346                           (roundboxalign & (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) == (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) ? 1 : 2;
347
348         minsize = mini(BLI_RCT_SIZE_X(rect) * hnum,
349                        BLI_RCT_SIZE_Y(rect) * 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 = mini(BLI_RCT_SIZE_X(rect), BLI_RCT_SIZE_Y(rect));
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 = mini(BLI_RCT_SIZE_X(rect), BLI_RCT_SIZE_Y(rect));
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 * BLI_RCT_SIZE_Y(rect);
574         centy = rect->ymin + 0.5f * BLI_RCT_SIZE_Y(rect);
575         size = 0.4f * BLI_RCT_SIZE_Y(rect);
576         
577         /* XXX exception */
578         asp = ((float)BLI_RCT_SIZE_X(rect)) / ((float)BLI_RCT_SIZE_Y(rect));
579         if (asp > 1.2f && asp < 2.6f)
580                 centx = rect->xmax - 0.3f * BLI_RCT_SIZE_Y(rect);
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 * BLI_RCT_SIZE_Y(rect);
598         centy = rect->ymin + 0.5f * BLI_RCT_SIZE_Y(rect);
599         size = 0.5f * BLI_RCT_SIZE_Y(rect);
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 = BLI_RCT_SIZE_X(rect);
844         h = BLI_RCT_SIZE_Y(rect);
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 = BLI_RCT_SIZE_X(rect) - 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 = BLI_RCT_SIZE_X(rect) - 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;  // UNUSED
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 = UI_BITBUT_TEST(*(((short *)but->poin) + 1), but->bitnr);
1260                         else if (but->pointype == INT)
1261                                 dualset = UI_BITBUT_TEST(*(((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 - BLI_RCT_SIZE_Y(rect) - 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 * BLI_RCT_SIZE_Y(&rect1))
1763                 rect1.ymax -= 0.2f * BLI_RCT_SIZE_Y(&rect1);
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 = BLI_RCT_CENTER_X_FL(rect);
1846         float centy = BLI_RCT_CENTER_Y_FL(rect);
1847         float radius, dist;
1848         
1849         if (BLI_RCT_SIZE_X(rect) > BLI_RCT_SIZE_Y(rect))
1850                 radius = (float)BLI_RCT_SIZE_Y(rect) / 2;
1851         else
1852                 radius = (float)BLI_RCT_SIZE_X(rect) / 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 = FALSE;
1876         
1877         radstep = 2.0f * (float)M_PI / (float)tot;
1878         centx = BLI_RCT_CENTER_X_FL(rect);
1879         centy = BLI_RCT_CENTER_Y_FL(rect);
1880         
1881         if (BLI_RCT_SIZE_X(rect) > BLI_RCT_SIZE_Y(rect))
1882                 radius = (float)BLI_RCT_SIZE_Y(rect) / 2;
1883         else
1884                 radius = (float)BLI_RCT_SIZE_X(rect) / 2;
1885         
1886         /* color */
1887         ui_get_but_vectorf(but, rgb);
1888         /* copy_v3_v3(hsv, ui_block_hsv_get(but->block)); */ /* UNUSED */
1889
1890         rgb_to_hsv_compat_v(rgb, hsvo);
1891
1892         if (color_profile)
1893                 ui_block_to_display_space_v3(but->block, rgb);
1894
1895         rgb_to_hsv_compat_v(rgb, hsv);
1896         
1897         /* exception: if 'lock' is set
1898          * lock the value of the color wheel to 1.
1899          * Useful for color correction tools where you're only interested in hue. */
1900         if (but->flag & UI_BUT_COLOR_LOCK)
1901                 hsv[2] = 1.f;
1902         
1903         hsv_to_rgb(0.f, 0.f, hsv[2], colcent, colcent + 1, colcent + 2);
1904         
1905         glShadeModel(GL_SMOOTH);
1906
1907         glBegin(GL_TRIANGLE_FAN);
1908         glColor3fv(colcent);
1909         glVertex2f(centx, centy);
1910         
1911         for (a = 0; a <= tot; a++, ang += radstep) {
1912                 float si = sin(ang);
1913                 float co = cos(ang);
1914                 
1915                 ui_hsvcircle_vals_from_pos(hsv, hsv + 1, rect, centx + co * radius, centy + si * radius);
1916                 CLAMP(hsv[2], 0.0f, 1.0f); /* for display only */
1917
1918                 hsv_to_rgb_v(hsv, col);
1919                 glColor3fv(col);
1920                 glVertex2f(centx + co * radius, centy + si * radius);
1921         }
1922         glEnd();
1923         
1924         glShadeModel(GL_FLAT);
1925         
1926         /* fully rounded outline */
1927         glPushMatrix();
1928         glTranslatef(centx, centy, 0.0f);
1929         glEnable(GL_BLEND);
1930         glEnable(GL_LINE_SMOOTH);
1931         glColor3ubv((unsigned char *)wcol->outline);
1932         glutil_draw_lined_arc(0.0f, M_PI * 2.0, radius, tot + 1);
1933         glDisable(GL_BLEND);
1934         glDisable(GL_LINE_SMOOTH);
1935         glPopMatrix();
1936
1937         /* cursor */
1938         ang = 2.0f * (float)M_PI * hsvo[0] + 0.5f * (float)M_PI;
1939
1940         if (but->flag & UI_BUT_COLOR_CUBIC)
1941                 cursor_radius = (1.0f - powf(1.0f - hsvo[1], 3.0f));
1942         else
1943                 cursor_radius = hsvo[1];
1944
1945         radius = CLAMPIS(cursor_radius, 0.0f, 1.0f) * radius;
1946         ui_hsv_cursor(centx + cosf(-ang) * radius, centy + sinf(-ang) * radius);
1947 }
1948
1949 /* ************ custom buttons, old stuff ************** */
1950
1951 /* draws in resolution of 20x4 colors */
1952 void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const float alpha)
1953 {
1954         const float color_step = (type == UI_GRAD_H) ? 0.02 : 0.05f;
1955         int a;
1956         float h = hsv[0], s = hsv[1], v = hsv[2];
1957         float dx, dy, sx1, sx2, sy;
1958         float col0[4][3];   /* left half, rect bottom to top */
1959         float col1[4][3];   /* right half, rect bottom to top */
1960
1961         /* draw series of gouraud rects */
1962         glShadeModel(GL_SMOOTH);
1963         
1964         switch (type) {
1965                 case UI_GRAD_SV:
1966                         hsv_to_rgb(h, 0.0, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1967                         hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]);
1968                         hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
1969                         hsv_to_rgb(h, 1.0, 0.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1970                         break;
1971                 case UI_GRAD_HV:
1972                         hsv_to_rgb(0.0, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1973                         hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
1974                         hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
1975                         hsv_to_rgb(0.0, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
1976                         break;
1977                 case UI_GRAD_HS:
1978                         hsv_to_rgb(0.0, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
1979                         hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
1980                         hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
1981                         hsv_to_rgb(0.0, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
1982                         break;
1983                 case UI_GRAD_H:
1984                         hsv_to_rgb(0.0, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
1985                         copy_v3_v3(col1[1], col1[0]);
1986                         copy_v3_v3(col1[2], col1[0]);
1987                         copy_v3_v3(col1[3], col1[0]);
1988                         break;
1989                 case UI_GRAD_S:
1990                         hsv_to_rgb(1.0, 0.0, 1.0,   &col1[1][0], &col1[1][1], &col1[1][2]);
1991                         copy_v3_v3(col1[0], col1[1]);
1992                         copy_v3_v3(col1[2], col1[1]);
1993                         copy_v3_v3(col1[3], col1[1]);
1994                         break;
1995                 case UI_GRAD_V:
1996                         hsv_to_rgb(1.0, 1.0, 0.0,   &col1[2][0], &col1[2][1], &col1[2][2]);
1997                         copy_v3_v3(col1[0], col1[2]);
1998                         copy_v3_v3(col1[1], col1[2]);
1999                         copy_v3_v3(col1[3], col1[2]);
2000                         break;
2001                 default:
2002                         assert(!"invalid 'type' argument");
2003                         hsv_to_rgb(1.0, 1.0, 1.0,   &col1[2][0], &col1[2][1], &col1[2][2]);
2004                         copy_v3_v3(col1[0], col1[2]);
2005                         copy_v3_v3(col1[1], col1[2]);
2006                         copy_v3_v3(col1[3], col1[2]);
2007         }
2008         
2009         /* old below */
2010         
2011         for (dx = 0.0f; dx < 1.0f; dx += color_step) {
2012                 /* previous color */
2013                 copy_v3_v3(col0[0], col1[0]);
2014                 copy_v3_v3(col0[1], col1[1]);
2015                 copy_v3_v3(col0[2], col1[2]);
2016                 copy_v3_v3(col0[3], col1[3]);
2017                 
2018                 /* new color */
2019                 switch (type) {
2020                         case UI_GRAD_SV:
2021                                 hsv_to_rgb(h, 0.0, dx,   &col1[0][0], &col1[0][1], &col1[0][2]);
2022                                 hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]);
2023                                 hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
2024                                 hsv_to_rgb(h, 1.0, dx,   &col1[3][0], &col1[3][1], &col1[3][2]);
2025                                 break;
2026                         case UI_GRAD_HV:
2027                                 hsv_to_rgb(dx, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2028                                 hsv_to_rgb(dx, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
2029                                 hsv_to_rgb(dx, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
2030                                 hsv_to_rgb(dx, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
2031                                 break;
2032                         case UI_GRAD_HS:
2033                                 hsv_to_rgb(dx, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
2034                                 hsv_to_rgb(dx, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
2035                                 hsv_to_rgb(dx, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
2036                                 hsv_to_rgb(dx, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
2037                                 break;
2038                         case UI_GRAD_H:
2039                         {
2040                                 /* annoying but without this the color shifts - could be solved some other way
2041                                  * - campbell */
2042                                 hsv_to_rgb(dx + color_step, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2043                                 copy_v3_v3(col1[1], col1[0]);
2044                                 copy_v3_v3(col1[2], col1[0]);
2045                                 copy_v3_v3(col1[3], col1[0]);
2046                                 break;
2047                         }
2048                         case UI_GRAD_S:
2049                                 hsv_to_rgb(h, dx, 1.0,   &col1[1][0], &col1[1][1], &col1[1][2]);
2050                                 copy_v3_v3(col1[0], col1[1]);
2051                                 copy_v3_v3(col1[2], col1[1]);
2052                                 copy_v3_v3(col1[3], col1[1]);
2053                                 break;
2054                         case UI_GRAD_V:
2055                                 hsv_to_rgb(h, 1.0, dx,   &col1[2][0], &col1[2][1], &col1[2][2]);
2056                                 copy_v3_v3(col1[0], col1[2]);
2057                                 copy_v3_v3(col1[1], col1[2]);
2058                                 copy_v3_v3(col1[3], col1[2]);
2059                                 break;
2060                 }
2061                 
2062                 /* rect */
2063                 sx1 = rect->xmin +  dx               * BLI_RCT_SIZE_X(rect);
2064                 sx2 = rect->xmin + (dx + color_step) * BLI_RCT_SIZE_X(rect);
2065                 sy = rect->ymin;
2066                 dy = BLI_RCT_SIZE_Y(rect) / 3.0;
2067                 
2068                 glBegin(GL_QUADS);
2069                 for (a = 0; a < 3; a++, sy += dy) {
2070                         glColor4f(col0[a][0], col0[a][1], col0[a][2], alpha);
2071                         glVertex2f(sx1, sy);
2072                         
2073                         glColor4f(col1[a][0], col1[a][1], col1[a][2], alpha);
2074                         glVertex2f(sx2, sy);
2075
2076                         glColor4f(col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
2077                         glVertex2f(sx2, sy + dy);
2078                         
2079                         glColor4f(col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha);
2080                         glVertex2f(sx1, sy + dy);
2081                 }
2082                 glEnd();
2083         }
2084         
2085         glShadeModel(GL_FLAT);
2086         
2087 }
2088
2089
2090
2091 static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect)
2092 {
2093         float rgb[3];
2094         float x = 0.0f, y = 0.0f;
2095         float *hsv = ui_block_hsv_get(but->block);
2096         float hsv_n[3];
2097         
2098         copy_v3_v3(hsv_n, hsv);
2099         
2100         ui_get_but_vectorf(but, rgb);
2101         rgb_to_hsv_compat_v(rgb, hsv_n);
2102         
2103         ui_draw_gradient(rect, hsv_n, but->a1, 1.0f);
2104         
2105         switch ((int)but->a1) {
2106                 case UI_GRAD_SV:
2107                         x = hsv_n[2]; y = hsv_n[1]; break;
2108                 case UI_GRAD_HV:
2109                         x = hsv_n[0]; y = hsv_n[2]; break;
2110                 case UI_GRAD_HS:
2111                         x = hsv_n[0]; y = hsv_n[1]; break;
2112                 case UI_GRAD_H:
2113                         x = hsv_n[0]; y = 0.5; break;
2114                 case UI_GRAD_S:
2115                         x = hsv_n[1]; y = 0.5; break;
2116                 case UI_GRAD_V:
2117                         x = hsv_n[2]; y = 0.5; break;
2118         }
2119         
2120         /* cursor */
2121         x = rect->xmin + x * BLI_RCT_SIZE_X(rect);
2122         y = rect->ymin + y * BLI_RCT_SIZE_Y(rect);
2123         CLAMP(x, rect->xmin + 3.0f, rect->xmax - 3.0f);
2124         CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
2125         
2126         ui_hsv_cursor(x, y);
2127         
2128         /* outline */
2129         glColor3ub(0,  0,  0);
2130         fdrawbox((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
2131 }
2132
2133 /* vertical 'value' slider, using new widget code */
2134 static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
2135 {
2136         uiWidgetBase wtb;
2137         float rad = 0.5f * BLI_RCT_SIZE_X(rect);
2138         float x, y;
2139         float rgb[3], hsv[3], v, range;
2140         int color_profile = but->block->color_profile;
2141         
2142         if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
2143                 color_profile = FALSE;
2144
2145         ui_get_but_vectorf(but, rgb);
2146
2147         if (color_profile)
2148                 ui_block_to_display_space_v3(but->block, rgb);
2149
2150         rgb_to_hsv_v(rgb, hsv);
2151         v = hsv[2];
2152         
2153         /* map v from property range to [0,1] */
2154         range = but->softmax - but->softmin;
2155         v = (v - but->softmin) / range;
2156         
2157         widget_init(&wtb);
2158         
2159         /* fully rounded */
2160         round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
2161         
2162         /* setup temp colors */
2163         wcol_tmp.outline[0] = wcol_tmp.outline[1] = wcol_tmp.outline[2] = 0;
2164         wcol_tmp.inner[0] = wcol_tmp.inner[1] = wcol_tmp.inner[2] = 128;
2165         wcol_tmp.shadetop = 127;
2166         wcol_tmp.shadedown = -128;
2167         wcol_tmp.shaded = 1;
2168         
2169         widgetbase_draw(&wtb, &wcol_tmp);
2170
2171         /* cursor */
2172         x = rect->xmin + 0.5f * BLI_RCT_SIZE_X(rect);
2173         y = rect->ymin + v    * BLI_RCT_SIZE_Y(rect);
2174         CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
2175         
2176         ui_hsv_cursor(x, y);
2177         
2178 }
2179
2180
2181 /* ************ separator, for menus etc ***************** */
2182 static void ui_draw_separator(rcti *rect,  uiWidgetColors *wcol)
2183 {
2184         int y = rect->ymin + BLI_RCT_SIZE_Y(rect) / 2 - 1;
2185         unsigned char col[4];
2186         
2187         col[0] = wcol->text[0];
2188         col[1] = wcol->text[1];
2189         col[2] = wcol->text[2];
2190         col[3] = 7;
2191         
2192         glEnable(GL_BLEND);
2193         glColor4ubv(col);
2194         sdrawline(rect->xmin, y, rect->xmax, y);
2195         glDisable(GL_BLEND);
2196 }
2197
2198 /* ************ button callbacks, draw ***************** */
2199
2200 static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2201 {
2202         uiWidgetBase wtb;
2203         float rad = 0.5f * BLI_RCT_SIZE_Y(rect);
2204         float textofs = rad * 0.75f;
2205
2206         if (state & UI_SELECT)
2207                 SWAP(short, wcol->shadetop, wcol->shadedown);
2208         
2209         widget_init(&wtb);
2210         
2211         /* fully rounded */
2212         round_box_edges(&wtb, roundboxalign, rect, rad);
2213         
2214         /* decoration */
2215         if (!(state & UI_TEXTINPUT)) {
2216                 widget_num_tria(&wtb.tria1, rect, 0.6f, 'l');
2217                 widget_num_tria(&wtb.tria2, rect, 0.6f, 'r');
2218         }
2219
2220         widgetbase_draw(&wtb, wcol);
2221         
2222         /* text space */
2223         rect->xmin += textofs;
2224         rect->xmax -= textofs;
2225 }
2226
2227 int ui_link_bezier_points(rcti *rect, float coord_array[][2], int resol)
2228 {
2229         float dist, vec[4][2];
2230
2231         vec[0][0] = rect->xmin;
2232         vec[0][1] = rect->ymin;
2233         vec[3][0] = rect->xmax;
2234         vec[3][1] = rect->ymax;
2235         
2236         dist = 0.5f * ABS(vec[0][0] - vec[3][0]);
2237         
2238         vec[1][0] = vec[0][0] + dist;
2239         vec[1][1] = vec[0][1];
2240         
2241         vec[2][0] = vec[3][0] - dist;
2242         vec[2][1] = vec[3][1];
2243         
2244         BKE_curve_forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, sizeof(float) * 2);
2245         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);
2246         
2247         return 1;
2248 }
2249
2250 #define LINK_RESOL  24
2251 void ui_draw_link_bezier(rcti *rect)
2252 {
2253         float coord_array[LINK_RESOL + 1][2];
2254         
2255         if (ui_link_bezier_points(rect, coord_array, LINK_RESOL)) {
2256                 /* we can reuse the dist variable here to increment the GL curve eval amount*/
2257                 // const float dist = 1.0f / (float)LINK_RESOL; // UNUSED
2258
2259                 glEnable(GL_BLEND);
2260                 glEnable(GL_LINE_SMOOTH);
2261
2262                 glEnableClientState(GL_VERTEX_ARRAY);
2263                 glVertexPointer(2, GL_FLOAT, 0, coord_array);
2264                 glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL);
2265                 glDisableClientState(GL_VERTEX_ARRAY);
2266
2267                 glDisable(GL_BLEND);
2268                 glDisable(GL_LINE_SMOOTH);
2269
2270         }
2271 }
2272
2273 /* function in use for buttons and for view2d sliders */
2274 void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int state)
2275 {
2276         uiWidgetBase wtb;
2277         float rad;
2278         int horizontal;
2279         short outline = 0;
2280
2281         widget_init(&wtb);
2282
2283         /* determine horizontal/vertical */
2284         horizontal = (BLI_RCT_SIZE_X(rect) > BLI_RCT_SIZE_Y(rect));
2285         
2286         if (horizontal)
2287                 rad = 0.5f * BLI_RCT_SIZE_Y(rect);
2288         else
2289                 rad = 0.5f * BLI_RCT_SIZE_X(rect);
2290         
2291         wtb.shadedir = (horizontal) ? 1 : 0;
2292         
2293         /* draw back part, colors swapped and shading inverted */
2294         if (horizontal)
2295                 SWAP(short, wcol->shadetop, wcol->shadedown);
2296         
2297         round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
2298         widgetbase_draw(&wtb, wcol);
2299         
2300         /* slider */
2301         if ((BLI_RCT_SIZE_X(slider) < 2) || (BLI_RCT_SIZE_Y(slider) < 2)) {
2302                 /* pass */
2303         }
2304         else {
2305                 SWAP(short, wcol->shadetop, wcol->shadedown);
2306                 
2307                 copy_v4_v4_char(wcol->inner, wcol->item);
2308                 
2309                 if (wcol->shadetop > wcol->shadedown)
2310                         wcol->shadetop += 20;   /* XXX violates themes... */
2311                 else wcol->shadedown += 20;
2312                 
2313                 if (state & UI_SCROLL_PRESSED) {
2314                         wcol->inner[0] = wcol->inner[0] >= 250 ? 255 : wcol->inner[0] + 5;
2315                         wcol->inner[1] = wcol->inner[1] >= 250 ? 255 : wcol->inner[1] + 5;
2316                         wcol->inner[2] = wcol->inner[2] >= 250 ? 255 : wcol->inner[2] + 5;
2317                 }
2318
2319                 /* draw */
2320                 wtb.emboss = 0; /* only emboss once */
2321                 
2322                 /* exception for progress bar */
2323                 if (state & UI_SCROLL_NO_OUTLINE)       
2324                         SWAP(short, outline, wtb.outline);
2325                 
2326                 round_box_edges(&wtb, UI_CNR_ALL, slider, rad);
2327                 
2328                 if (state & UI_SCROLL_ARROWS) {
2329                         if (wcol->item[0] > 48) wcol->item[0] -= 48;
2330                         if (wcol->item[1] > 48) wcol->item[1] -= 48;
2331                         if (wcol->item[2] > 48) wcol->item[2] -= 48;
2332                         wcol->item[3] = 255;
2333                         
2334                         if (horizontal) {
2335                                 widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
2336                                 widget_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
2337                         }
2338                         else {
2339                                 widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
2340                                 widget_scroll_circle(&wtb.tria2, slider, 0.6f, 't');
2341                         }
2342                 }
2343                 widgetbase_draw(&wtb, wcol);
2344                 
2345                 if (state & UI_SCROLL_NO_OUTLINE)
2346                         SWAP(short, outline, wtb.outline);
2347         }       
2348 }
2349
2350 static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2351 {
2352         rcti rect1;
2353         double value;
2354         float fac, size, min;
2355         int horizontal;
2356
2357         /* calculate slider part */
2358         value = ui_get_but_val(but);
2359
2360         size = (but->softmax + but->a1 - but->softmin);
2361         size = MAX2(size, 2);
2362         
2363         /* position */
2364         rect1 = *rect;
2365
2366         /* determine horizontal/vertical */
2367         horizontal = (BLI_RCT_SIZE_X(rect) > BLI_RCT_SIZE_Y(rect));
2368         
2369         if (horizontal) {
2370                 fac = BLI_RCT_SIZE_X(rect) / size;
2371                 rect1.xmin = rect1.xmin + ceilf(fac * ((float)value - but->softmin));
2372                 rect1.xmax = rect1.xmin + ceilf(fac * (but->a1 - but->softmin));
2373
2374                 /* ensure minimium size */
2375                 min = BLI_RCT_SIZE_Y(rect);
2376
2377                 if (BLI_RCT_SIZE_X(&rect1) < min) {
2378                         rect1.xmax = rect1.xmin + min;
2379
2380                         if (rect1.xmax > rect->xmax) {
2381                                 rect1.xmax = rect->xmax;
2382                                 rect1.xmin = maxi(rect1.xmax - min, rect->xmin);
2383                         }
2384                 }
2385         }
2386         else {
2387                 fac = BLI_RCT_SIZE_Y(rect) / size;
2388                 rect1.ymax = rect1.ymax - ceilf(fac * ((float)value - but->softmin));
2389                 rect1.ymin = rect1.ymax - ceilf(fac * (but->a1 - but->softmin));
2390
2391                 /* ensure minimium size */
2392                 min = BLI_RCT_SIZE_X(rect);
2393
2394                 if (BLI_RCT_SIZE_Y(&rect1) < min) {
2395                         rect1.ymax = rect1.ymin + min;
2396
2397                         if (rect1.ymax > rect->ymax) {
2398                                 rect1.ymax = rect->ymax;
2399                                 rect1.ymin = MAX2(rect1.ymax - min, rect->ymin);
2400                         }
2401                 }
2402         }
2403
2404         if (state & UI_SELECT)
2405                 state = UI_SCROLL_PRESSED;
2406         else
2407                 state = 0;
2408         uiWidgetScrollDraw(wcol, rect, &rect1, state);
2409 }
2410
2411 static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2412 {
2413         rcti rect_prog = *rect, rect_bar = *rect;
2414         float value = but->a1;
2415         float w, min;
2416         
2417         /* make the progress bar a proportion of the original height */
2418         /* hardcoded 4px high for now */
2419         rect_prog.ymax = rect_prog.ymin + 4;
2420         rect_bar.ymax = rect_bar.ymin + 4;
2421         
2422         w = value * BLI_RCT_SIZE_X(&rect_prog);
2423         
2424         /* ensure minimium size */
2425         min = BLI_RCT_SIZE_Y(&rect_prog);
2426         w = MAX2(w, min);
2427         
2428         rect_bar.xmax = rect_bar.xmin + w;
2429                 
2430         uiWidgetScrollDraw(wcol, &rect_prog, &rect_bar, UI_SCROLL_NO_OUTLINE);
2431         
2432         /* raise text a bit */
2433         rect->ymin += 6;
2434         rect->xmin -= 6;
2435 }
2436
2437 static void widget_link(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2438 {
2439         
2440         if (but->flag & UI_SELECT) {
2441                 rcti rectlink;
2442                 
2443                 UI_ThemeColor(TH_TEXT_HI);
2444                 
2445                 rectlink.xmin = BLI_RCT_CENTER_X(rect);
2446                 rectlink.ymin = BLI_RCT_CENTER_Y(rect);
2447                 rectlink.xmax = but->linkto[0];
2448                 rectlink.ymax = but->linkto[1];
2449                 
2450                 ui_draw_link_bezier(&rectlink);
2451         }
2452 }
2453
2454 static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2455 {
2456         uiWidgetBase wtb, wtb1;
2457         rcti rect1;
2458         double value;
2459         float offs, toffs, fac;
2460         char outline[3];
2461
2462         widget_init(&wtb);
2463         widget_init(&wtb1);
2464         
2465         /* backdrop first */
2466         
2467         /* fully rounded */
2468         offs = 0.5f * BLI_RCT_SIZE_Y(rect);
2469         toffs = offs * 0.75f;
2470         round_box_edges(&wtb, roundboxalign, rect, offs);
2471
2472         wtb.outline = 0;
2473         widgetbase_draw(&wtb, wcol);
2474         
2475         /* draw left/right parts only when not in text editing */
2476         if (!(state & UI_TEXTINPUT)) {
2477                 
2478                 /* slider part */
2479                 copy_v3_v3_char(outline, wcol->outline);
2480                 copy_v3_v3_char(wcol->outline, wcol->item);
2481                 copy_v3_v3_char(wcol->inner, wcol->item);
2482
2483                 if (!(state & UI_SELECT))
2484                         SWAP(short, wcol->shadetop, wcol->shadedown);
2485                 
2486                 rect1 = *rect;
2487                 
2488                 value = ui_get_but_val(but);
2489                 fac = ((float)value - but->softmin) * (BLI_RCT_SIZE_X(&rect1) - offs) / (but->softmax - but->softmin);
2490                 
2491                 /* left part of slider, always rounded */
2492                 rect1.xmax = rect1.xmin + ceil(offs + 1.0f);
2493                 round_box_edges(&wtb1, roundboxalign & ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT), &rect1, offs);
2494                 wtb1.outline = 0;
2495                 widgetbase_draw(&wtb1, wcol);
2496                 
2497                 /* right part of slider, interpolate roundness */
2498                 rect1.xmax = rect1.xmin + fac + offs;
2499                 rect1.xmin +=  floor(offs - 1.0f);
2500                 if (rect1.xmax + offs > rect->xmax)
2501                         offs *= (rect1.xmax + offs - rect->xmax) / offs;
2502                 else 
2503                         offs = 0.0f;
2504                 round_box_edges(&wtb1, roundboxalign & ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT), &rect1, offs);
2505                 
2506                 widgetbase_draw(&wtb1, wcol);
2507                 copy_v3_v3_char(wcol->outline, outline);
2508                 
2509                 if (!(state & UI_SELECT))
2510                         SWAP(short, wcol->shadetop, wcol->shadedown);
2511         }
2512         
2513         /* outline */
2514         wtb.outline = 1;
2515         wtb.inner = 0;
2516         widgetbase_draw(&wtb, wcol);
2517         
2518         /* text space */
2519         rect->xmin += toffs;
2520         rect->xmax -= toffs;
2521 }
2522
2523 /* I think 3 is sufficient border to indicate keyed status */
2524 #define SWATCH_KEYED_BORDER 3
2525
2526 static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2527 {
2528         uiWidgetBase wtb;
2529         float col[4];
2530         int color_profile = but->block->color_profile;
2531         
2532         col[3] = 1.0f;
2533
2534         if (but->rnaprop) {
2535                 if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
2536                         color_profile = FALSE;
2537
2538                 if (RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4) {
2539                         col[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
2540                 }
2541         }
2542         
2543         widget_init(&wtb);
2544         
2545         /* half rounded */
2546         round_box_edges(&wtb, roundboxalign, rect, 5.0f);
2547                 
2548         ui_get_but_vectorf(but, col);
2549
2550         if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
2551                 /* draw based on state - color for keyed etc */
2552                 widgetbase_draw(&wtb, wcol);
2553
2554                 /* inset to draw swatch color */
2555                 rect->xmin += SWATCH_KEYED_BORDER;
2556                 rect->xmax -= SWATCH_KEYED_BORDER;
2557                 rect->ymin += SWATCH_KEYED_BORDER;
2558                 rect->ymax -= SWATCH_KEYED_BORDER;
2559                 
2560                 round_box_edges(&wtb, roundboxalign, rect, 5.0f);
2561         }
2562         
2563         if (color_profile)
2564                 ui_block_to_display_space_v3(but->block, col);
2565         
2566         rgba_float_to_uchar((unsigned char *)wcol->inner, col);
2567
2568         wcol->shaded = 0;
2569         wcol->alpha_check = (wcol->inner[3] < 255);
2570
2571         widgetbase_draw(&wtb, wcol);
2572         
2573 }
2574
2575 static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2576 {
2577         if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
2578                 uiWidgetBase wtb;
2579         
2580                 widget_init(&wtb);
2581                 wtb.outline = 0;
2582                 
2583                 /* rounded */
2584                 round_box_edges(&wtb, UI_CNR_ALL, rect, 10.0f);
2585                 widgetbase_draw(&wtb, wcol);
2586         }       
2587 }
2588
2589
2590 static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2591 {
2592         uiWidgetBase wtb;
2593         
2594         if (state & UI_SELECT)
2595                 SWAP(short, wcol->shadetop, wcol->shadedown);
2596         
2597         widget_init(&wtb);
2598         
2599         /* half rounded */
2600         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2601         
2602         widgetbase_draw(&wtb, wcol);
2603
2604 }
2605
2606
2607 static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2608 {
2609         uiWidgetBase wtb;
2610         
2611         widget_init(&wtb);
2612         
2613         /* half rounded */
2614         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2615         
2616         /* decoration */
2617         widget_menu_trias(&wtb.tria1, rect);
2618         
2619         widgetbase_draw(&wtb, wcol);
2620         
2621         /* text space */
2622         rect->xmax -= BLI_RCT_SIZE_Y(rect);
2623 }
2624
2625 static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2626 {
2627         uiWidgetBase wtb;
2628         
2629         widget_init(&wtb);
2630         
2631         /* half rounded */
2632         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2633         
2634         /* decoration */
2635         widgetbase_draw(&wtb, wcol);
2636 }
2637
2638 static void widget_menunodebut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2639 {
2640         /* silly node link button hacks */
2641         uiWidgetBase wtb;
2642         uiWidgetColors wcol_backup = *wcol;
2643         
2644         widget_init(&wtb);
2645         
2646         /* half rounded */
2647         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2648
2649         wcol->inner[0] += 15;
2650         wcol->inner[1] += 15;
2651         wcol->inner[2] += 15;
2652         wcol->outline[0] += 15;
2653         wcol->outline[1] += 15;
2654         wcol->outline[2] += 15;
2655         
2656         /* decoration */
2657         widgetbase_draw(&wtb, wcol);
2658         *wcol = wcol_backup;
2659 }
2660
2661 static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2662 {
2663         if (state & UI_ACTIVE) {
2664                 uiWidgetBase wtb;
2665                 float rad = 0.5f * BLI_RCT_SIZE_Y(rect);  /* 4.0f */
2666                 
2667                 widget_init(&wtb);
2668                 
2669                 /* half rounded */
2670                 round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
2671                 
2672                 widgetbase_draw(&wtb, wcol);
2673         }
2674 }
2675
2676 static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2677 {
2678         uiWidgetBase wtb;
2679         
2680         widget_init(&wtb);
2681         
2682         /* not rounded, no outline */
2683         wtb.outline = 0;
2684         round_box_edges(&wtb, 0, rect, 0.0f);
2685         
2686         widgetbase_draw(&wtb, wcol);
2687 }
2688
2689 static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2690 {
2691         uiWidgetBase wtb;
2692         
2693         widget_init(&wtb);
2694         
2695         /* rounded, but no outline */
2696         wtb.outline = 0;
2697         round_box_edges(&wtb, UI_CNR_ALL, rect, 4.0f);
2698         
2699         widgetbase_draw(&wtb, wcol);
2700 }
2701
2702 static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2703 {
2704         uiWidgetBase wtb;
2705         rcti recttemp = *rect;
2706         int delta;
2707         
2708         widget_init(&wtb);
2709         
2710         /* square */
2711         recttemp.xmax = recttemp.xmin + BLI_RCT_SIZE_Y(&recttemp);
2712         
2713         /* smaller */
2714         delta = 1 + BLI_RCT_SIZE_Y(&recttemp) / 8;
2715         recttemp.xmin += delta;
2716         recttemp.ymin += delta;
2717         recttemp.xmax -= delta;
2718         recttemp.ymax -= delta;
2719         
2720         /* half rounded */
2721         round_box_edges(&wtb, UI_CNR_ALL, &recttemp, 4.0f);
2722         
2723         /* decoration */
2724         if (state & UI_SELECT) {
2725                 widget_check_trias(&wtb.tria1, &recttemp);
2726         }
2727         
2728         widgetbase_draw(&wtb, wcol);
2729         
2730         /* text space */
2731         rect->xmin += BLI_RCT_SIZE_Y(rect) * 0.7 + delta;
2732 }
2733
2734
2735 static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2736 {
2737         uiWidgetBase wtb;
2738         
2739         widget_init(&wtb);
2740         
2741         /* half rounded */
2742         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2743         
2744         widgetbase_draw(&wtb, wcol);
2745
2746 }
2747
2748 static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2749 {
2750         uiWidgetBase wtb;
2751         char old_col[3];
2752         
2753         widget_init(&wtb);
2754         
2755         copy_v3_v3_char(old_col, wcol->inner);
2756         
2757         /* abuse but->hsv - if it's non-zero, use this color as the box's background */
2758         if (but->col[3]) {
2759                 wcol->inner[0] = but->col[0];
2760                 wcol->inner[1] = but->col[1];
2761                 wcol->inner[2] = but->col[2];
2762         }
2763         
2764         /* half rounded */
2765         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2766         
2767         widgetbase_draw(&wtb, wcol);
2768         
2769         /* store the box bg as gl clearcolor, to retrieve later when drawing semi-transparent rects
2770          * over the top to indicate disabled buttons */
2771         /* XXX, this doesnt work right since the color applies to buttons outside the box too. */
2772         glClearColor(wcol->inner[0] / 255.0, wcol->inner[1] / 255.0, wcol->inner[2] / 255.0, 1.0);
2773         
2774         copy_v3_v3_char(wcol->inner, old_col);
2775 }
2776
2777 static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2778 {
2779         uiWidgetBase wtb;
2780         
2781         widget_init(&wtb);
2782         
2783         /* half rounded */
2784         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2785                 
2786         widgetbase_draw(&wtb, wcol);
2787
2788 }
2789
2790 static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2791 {
2792         uiWidgetBase wtb;
2793         float rad = 5.0f;  /* 0.5f * BLI_RCT_SIZE_Y(rect); */
2794         
2795         widget_init(&wtb);
2796         
2797         /* half rounded */
2798         round_box_edges(&wtb, roundboxalign, rect, rad);
2799
2800         widgetbase_draw(&wtb, wcol);
2801 }
2802
2803 static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
2804 {
2805         uiWidgetBase wtb;
2806         unsigned char col[4];
2807         
2808         /* state copy! */
2809         wt->wcol = *(wt->wcol_theme);
2810         
2811         widget_init(&wtb);
2812         
2813         if (but->block->drawextra) {
2814                 /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
2815                 but->block->drawextra(C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect);
2816                 
2817                 /* make mask to draw over image */
2818                 UI_GetThemeColor3ubv(TH_BACK, col);
2819                 glColor3ubv(col);
2820                 
2821                 round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, 4.0);
2822                 widgetbase_outline(&wtb);
2823         }
2824         
2825         /* outline */
2826         round_box_edges(&wtb, UI_CNR_ALL, rect, 5.0f);
2827         wtb.outline = 1;
2828         wtb.inner = 0;
2829         widgetbase_draw(&wtb, &wt->wcol);
2830         
2831 }
2832
2833
2834 static void widget_disabled(rcti *rect)
2835 {
2836         float col[4];
2837         
2838         glEnable(GL_BLEND);
2839         
2840         /* can't use theme TH_BACK or TH_PANEL... undefined */
2841         glGetFloatv(GL_COLOR_CLEAR_VALUE, col);
2842         glColor4f(col[0], col[1], col[2], 0.5f);
2843
2844         /* need -1 and +1 to make it work right for aligned buttons,
2845          * but problem may be somewhere else? */
2846         glRectf(rect->xmin - 1, rect->ymin - 1, rect->xmax, rect->ymax + 1);
2847         
2848         glDisable(GL_BLEND);
2849 }
2850
2851 static uiWidgetType *widget_type(uiWidgetTypeEnum type)
2852 {
2853         bTheme *btheme = UI_GetTheme();
2854         static uiWidgetType wt;
2855         
2856         /* defaults */
2857         wt.wcol_theme = &btheme->tui.wcol_regular;
2858         wt.wcol_state = &btheme->tui.wcol_state;
2859         wt.state = widget_state;
2860         wt.draw = widget_but;
2861         wt.custom = NULL;
2862         wt.text = widget_draw_text_icon;
2863         
2864         switch (type) {
2865                 case UI_WTYPE_REGULAR:
2866                         break;
2867
2868                 case UI_WTYPE_LABEL:
2869                         wt.draw = NULL;
2870                         wt.state = widget_state_label;
2871                         break;
2872                         
2873                 case UI_WTYPE_TOGGLE:
2874                         wt.wcol_theme = &btheme->tui.wcol_toggle;
2875                         break;
2876                         
2877                 case UI_WTYPE_OPTION:
2878                         wt.wcol_theme = &btheme->tui.wcol_option;
2879                         wt.draw = widget_optionbut;
2880                         break;
2881                         
2882                 case UI_WTYPE_RADIO:
2883                         wt.wcol_theme = &btheme->tui.wcol_radio;
2884                         wt.draw = widget_radiobut;
2885                         break;
2886
2887                 case UI_WTYPE_NUMBER:
2888                         wt.wcol_theme = &btheme->tui.wcol_num;
2889                         wt.draw = widget_numbut;
2890                         break;
2891                         
2892                 case UI_WTYPE_SLIDER:
2893                         wt.wcol_theme = &btheme->tui.wcol_numslider;
2894                         wt.custom = widget_numslider;
2895                         wt.state = widget_state_numslider;
2896                         break;
2897                         
2898                 case UI_WTYPE_EXEC:
2899                         wt.wcol_theme = &btheme->tui.wcol_tool;
2900                         wt.draw = widget_roundbut;
2901                         break;
2902
2903                 case UI_WTYPE_TOOLTIP:
2904                         wt.wcol_theme = &btheme->tui.wcol_tooltip;
2905                         wt.draw = widget_menu_back;
2906                         break;
2907                         
2908                         
2909                 /* strings */
2910                 case UI_WTYPE_NAME:
2911                         wt.wcol_theme = &btheme->tui.wcol_text;
2912                         wt.draw = widget_textbut;
2913                         break;
2914                         
2915                 case UI_WTYPE_NAME_LINK:
2916                         break;
2917                         
2918                 case UI_WTYPE_POINTER_LINK:
2919                         break;
2920                         
2921                 case UI_WTYPE_FILENAME:
2922                         break;
2923                         
2924                         
2925                 /* start menus */
2926                 case UI_WTYPE_MENU_RADIO:
2927                         wt.wcol_theme = &btheme->tui.wcol_menu;
2928                         wt.draw = widget_menubut;
2929                         break;
2930
2931                 case UI_WTYPE_MENU_ICON_RADIO:
2932                         wt.wcol_theme = &btheme->tui.wcol_menu;
2933                         wt.draw = widget_menuiconbut;
2934                         break;
2935                         
2936                 case UI_WTYPE_MENU_POINTER_LINK:
2937                         wt.wcol_theme = &btheme->tui.wcol_menu;
2938                         wt.draw = widget_menubut;
2939                         break;
2940
2941                 case UI_WTYPE_MENU_NODE_LINK:
2942                         wt.wcol_theme = &btheme->tui.wcol_menu;
2943                         wt.draw = widget_menunodebut;
2944                         break;
2945                         
2946                 case UI_WTYPE_PULLDOWN:
2947                         wt.wcol_theme = &btheme->tui.wcol_pulldown;
2948                         wt.draw = widget_pulldownbut;
2949                         wt.state = widget_state_pulldown;
2950                         break;
2951                         
2952                 /* in menus */
2953                 case UI_WTYPE_MENU_ITEM:
2954                         wt.wcol_theme = &btheme->tui.wcol_menu_item;
2955                         wt.draw = widget_menu_itembut;
2956                         wt.state = widget_state_menu_item;
2957                         break;
2958                         
2959                 case UI_WTYPE_MENU_BACK:
2960                         wt.wcol_theme = &btheme->tui.wcol_menu_back;
2961                         wt.draw = widget_menu_back;
2962                         break;
2963                         
2964                 /* specials */
2965                 case UI_WTYPE_ICON:
2966                         wt.custom = widget_icon_has_anim;
2967                         break;
2968                         
2969                 case UI_WTYPE_SWATCH:
2970                         wt.custom = widget_swatch;
2971                         break;
2972                         
2973                 case UI_WTYPE_BOX:
2974                         wt.custom = widget_box;
2975                         wt.wcol_theme = &btheme->tui.wcol_box;
2976                         break;
2977                         
2978                 case UI_WTYPE_RGB_PICKER:
2979                         break;
2980                         
2981                 case UI_WTYPE_NORMAL:
2982                         break;
2983
2984                 case UI_WTYPE_SCROLL:
2985                         wt.wcol_theme = &btheme->tui.wcol_scroll;
2986                         wt.state = widget_state_nothing;
2987                         wt.custom = widget_scroll;
2988                         break;
2989
2990                 case UI_WTYPE_LISTITEM:
2991                         wt.wcol_theme = &btheme->tui.wcol_list_item;
2992                         wt.draw = widget_list_itembut;
2993                         break;
2994                         
2995                 case UI_WTYPE_PROGRESSBAR:
2996                         wt.wcol_theme = &btheme->tui.wcol_progress;
2997                         wt.custom = widget_progressbar;
2998                         break;
2999         }
3000         
3001         return &wt;
3002 }
3003
3004
3005 static int widget_roundbox_set(uiBut *but, rcti *rect)
3006 {
3007         /* alignment */
3008         if (but->flag & UI_BUT_ALIGN) {
3009                 
3010                 if (but->flag & UI_BUT_ALIGN_TOP)
3011                         rect->ymax += 1;
3012                 if (but->flag & UI_BUT_ALIGN_LEFT)
3013                         rect->xmin -= 1;
3014                 
3015                 switch (but->flag & UI_BUT_ALIGN) {
3016                         case UI_BUT_ALIGN_TOP:
3017                                 return UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT;
3018                         case UI_BUT_ALIGN_DOWN:
3019                                 return UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
3020                         case UI_BUT_ALIGN_LEFT:
3021                                 return UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT;
3022                         case UI_BUT_ALIGN_RIGHT:
3023                                 return UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT;
3024                         case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_RIGHT:
3025                                 return UI_CNR_TOP_LEFT;
3026                         case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT:
3027                                 return UI_CNR_TOP_RIGHT;
3028                         case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT:
3029                                 return UI_CNR_BOTTOM_LEFT;
3030                         case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT:
3031                                 return UI_CNR_BOTTOM_RIGHT;
3032                         default:
3033                                 return 0;
3034                 }
3035         }
3036
3037         return UI_CNR_ALL;
3038 }
3039
3040 /* conversion from old to new buttons, so still messy */
3041 void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
3042 {
3043         bTheme *btheme = UI_GetTheme();
3044         ThemeUI *tui = &btheme->tui;
3045         uiFontStyle *fstyle = &style->widget;
3046         uiWidgetType *wt = NULL;
3047
3048         /* handle menus separately */
3049         if (but->dt == UI_EMBOSSP) {
3050                 switch (but->type) {
3051                         case LABEL:
3052                                 widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
3053                                 break;
3054                         case SEPR:
3055                                 ui_draw_separator(rect, &tui->wcol_menu_item);
3056                                 break;
3057                                 
3058                         default:
3059                                 wt = widget_type(UI_WTYPE_MENU_ITEM);
3060                 }
3061         }
3062         else if (but->dt == UI_EMBOSSN) {
3063                 /* "nothing" */
3064                 wt = widget_type(UI_WTYPE_ICON);
3065         }
3066         else {
3067                 
3068                 switch (but->type) {
3069                         case LABEL:
3070                                 if (but->block->flag & UI_BLOCK_LOOP)
3071                                         widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
3072                                 else {
3073                                         wt = widget_type(UI_WTYPE_LABEL);
3074                                         fstyle = &style->widgetlabel;
3075                                 }
3076                                 break;
3077                                 
3078                         case SEPR:
3079                                 break;
3080                                 
3081                         case BUT:
3082                                 wt = widget_type(UI_WTYPE_EXEC);
3083                                 break;
3084
3085                         case NUM:
3086                                 wt = widget_type(UI_WTYPE_NUMBER);
3087                                 break;
3088                                 
3089                         case NUMSLI:
3090                         case HSVSLI:
3091                                 wt = widget_type(UI_WTYPE_SLIDER);
3092                                 break;
3093                                 
3094                         case ROW:
3095                                 wt = widget_type(UI_WTYPE_RADIO);
3096                                 break;
3097
3098                         case LISTROW:
3099                                 wt = widget_type(UI_WTYPE_LISTITEM);
3100                                 break;
3101                                 
3102                         case TEX:
3103                                 wt = widget_type(UI_WTYPE_NAME);
3104                                 break;
3105                                 
3106                         case SEARCH_MENU:
3107                                 wt = widget_type(UI_WTYPE_NAME);
3108                                 if (but->block->flag & UI_BLOCK_LOOP)
3109                                         wt->wcol_theme = &btheme->tui.wcol_menu_back;
3110                                 break;
3111                                 
3112                         case TOGBUT:
3113                         case TOG:
3114                         case TOGN:
3115                         case TOG3:
3116                                 wt = widget_type(UI_WTYPE_TOGGLE);
3117                                 break;
3118                                 
3119                         case OPTION:
3120                         case OPTIONN:
3121                                 if (!(but->flag & UI_HAS_ICON)) {
3122                                         wt = widget_type(UI_WTYPE_OPTION);
3123                                         but->flag |= UI_TEXT_LEFT;
3124                                 }
3125                                 else
3126                                         wt = widget_type(UI_WTYPE_TOGGLE);
3127