c4b80f0a42fe526dc6dd5a180bf252521fb7e2e3
[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_rcti_size_y(rect))
263                 rad = 0.5f * BLI_rcti_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 = min_ii(BLI_rcti_size_x(rect) * hnum,
349                        BLI_rcti_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 = min_ii(BLI_rcti_size_x(rect), BLI_rcti_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 = min_ii(BLI_rcti_size_x(rect), BLI_rcti_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_rcti_size_y(rect);
574         centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
575         size = 0.4f * (float)BLI_rcti_size_y(rect);
576         
577         /* XXX exception */
578         asp = ((float)BLI_rcti_size_x(rect)) / ((float)BLI_rcti_size_y(rect));
579         if (asp > 1.2f && asp < 2.6f)
580                 centx = rect->xmax - 0.4f * (float)BLI_rcti_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_rcti_size_y(rect);
598         centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
599         size = 0.5f * BLI_rcti_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->inner_v[a][0];
655                 quad_strip[a * 2 + 1][1] = wtb->inner_v[a][1];
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_rcti_size_x(rect);
844         h = BLI_rcti_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 /**
969  * Cut off the start of the text to fit into the width of \a rect
970  *
971  * \note Sets but->ofs to make sure text is correctly visible.
972  * \note Clips right in some cases, this function could be cleaned up.
973  */
974 static void ui_text_clip_left(uiFontStyle *fstyle, uiBut *but, rcti *rect)
975 {
976         int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
977         int okwidth = BLI_rcti_size_x(rect) - border;
978         if (but->flag & UI_HAS_ICON) okwidth -= UI_DPI_ICON_SIZE;
979
980         /* need to set this first */
981         uiStyleFontSet(fstyle);
982         
983         if (fstyle->kerning == 1) /* for BLF_width */
984                 BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
985
986         but->ofs = 0;
987         but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr);
988
989         while (but->strwidth > okwidth) {
990                 ui_text_clip_give_next_off(but);
991                 but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
992                 if (but->strwidth < 10) break;
993         }
994
995         if (fstyle->kerning == 1) {
996                 BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
997         }
998 }
999
1000 /**
1001  * Cut off the text, taking into account the cursor location (text display while editing).
1002  */
1003 static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, rcti *rect)
1004 {
1005         int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
1006         int okwidth = BLI_rcti_size_x(rect) - border;
1007         if (but->flag & UI_HAS_ICON) okwidth -= UI_DPI_ICON_SIZE;
1008
1009         BLI_assert(but->editstr && but->pos >= 0);
1010
1011         /* need to set this first */
1012         uiStyleFontSet(fstyle);
1013
1014         if (fstyle->kerning == 1) /* for BLF_width */
1015                 BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
1016
1017         /* define ofs dynamically */
1018         if (but->ofs > but->pos)
1019                 but->ofs = but->pos;
1020
1021         if (BLF_width(fstyle->uifont_id, but->drawstr) <= okwidth)
1022                 but->ofs = 0;
1023
1024         but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
1025
1026         while (but->strwidth > okwidth) {
1027                 float width;
1028                 char buf[UI_MAX_DRAW_STR];
1029
1030                 /* copy draw string */
1031                 BLI_strncpy_utf8(buf, but->drawstr, sizeof(buf));
1032                 /* string position of cursor */
1033                 buf[but->pos] = 0;
1034                 width = BLF_width(fstyle->uifont_id, buf + but->ofs);
1035
1036                 /* if cursor is at 20 pixels of right side button we clip left */
1037                 if (width > okwidth - 20) {
1038                         ui_text_clip_give_next_off(but);
1039                 }
1040                 else {
1041                         int len, bytes;
1042                         /* shift string to the left */
1043                         if (width < 20 && but->ofs > 0)
1044                                 ui_text_clip_give_prev_off(but);
1045                         len = strlen(but->drawstr);
1046                         bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->drawstr, but->drawstr + len));
1047                         if (bytes < 0)
1048                                 bytes = 1;
1049                         but->drawstr[len - bytes] = 0;
1050                 }
1051
1052                 but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
1053
1054                 if (but->strwidth < 10) break;
1055         }
1056
1057         if (fstyle->kerning == 1) {
1058                 BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
1059         }
1060 }
1061
1062 /**
1063  * Cut off the end of text to fit into the width of \a rect.
1064  *
1065  * \note deals with ': ' especially for number buttons
1066  */
1067 static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, rcti *rect)
1068 {
1069         int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
1070         int okwidth = BLI_rcti_size_x(rect) - border;
1071         char *cpoin = NULL;
1072         int drawstr_len = strlen(but->drawstr);
1073         char *cpend = but->drawstr + drawstr_len;
1074         
1075         /* need to set this first */
1076         uiStyleFontSet(fstyle);
1077         
1078         if (fstyle->kerning == 1) /* for BLF_width */
1079                 BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
1080         
1081         but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr);
1082         but->ofs = 0;
1083         
1084
1085         /* First shorten num-buttopns eg,
1086          *   Translucency: 0.000
1087          * becomes
1088          *   Trans: 0.000
1089          */
1090
1091         /* find the space after ':' separator */
1092         cpoin = strrchr(but->drawstr, ':');
1093         
1094         if (cpoin && (cpoin < cpend - 2)) {
1095                 char *cp2 = cpoin;
1096                 
1097                 /* chop off the leading text, starting from the right */
1098                 while (but->strwidth > okwidth && cp2 > but->drawstr) {
1099                         char *prev_utf8 = BLI_str_find_prev_char_utf8(but->drawstr, cp2);
1100                         int bytes = cp2 - prev_utf8;
1101
1102                         /* shift the text after and including cp2 back by 1 char, +1 to include null terminator */
1103                         memmove(cp2 - bytes, cp2, drawstr_len + 1);
1104                         cp2 -= bytes;
1105
1106                         drawstr_len -= bytes;
1107                         // BLI_assert(strlen(but->drawstr) == drawstr_len);
1108                         
1109                         but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
1110                         if (but->strwidth < 10) break;
1111                 }
1112         
1113         
1114                 /* after the leading text is gone, chop off the : and following space, with ofs */
1115                 while ((but->strwidth > okwidth) && (but->ofs < 2)) {
1116                         ui_text_clip_give_next_off(but);
1117                         but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
1118                         if (but->strwidth < 10) break;
1119                 }
1120                 
1121         }
1122
1123
1124         /* Now just remove trailing chars */
1125         /* once the label's gone, chop off the least significant digits */
1126         while (but->strwidth > okwidth) {
1127                 int bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->drawstr, but->drawstr + drawstr_len));
1128                 if (bytes < 0)
1129                         bytes = 1;
1130
1131                 drawstr_len -= bytes;
1132                 but->drawstr[drawstr_len] = 0;
1133                 // BLI_assert(strlen(but->drawstr) == drawstr_len);
1134                 
1135                 but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
1136                 if (but->strwidth < 10) break;
1137         }
1138         
1139         if (fstyle->kerning == 1)
1140                 BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
1141 }
1142
1143
1144 static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
1145 {
1146         //int transopts;  // UNUSED
1147         char *cpoin = NULL;
1148         
1149         /* for underline drawing */
1150         float font_xofs, font_yofs;
1151
1152         uiStyleFontSet(fstyle);
1153         
1154         if (but->editstr || (but->flag & UI_TEXT_LEFT))
1155                 fstyle->align = UI_STYLE_TEXT_LEFT;
1156         else
1157                 fstyle->align = UI_STYLE_TEXT_CENTER;
1158         
1159         if (fstyle->kerning == 1) /* for BLF_width */
1160                 BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
1161         
1162         /* text button selection and cursor */
1163         if (but->editstr && but->pos != -1) {
1164                 short t = 0, pos = 0, ch;
1165                 short selsta_tmp, selend_tmp, selsta_draw, selwidth_draw;
1166
1167                 if ((but->selend - but->selsta) > 0) {
1168                         /* text button selection */
1169                         selsta_tmp = but->selsta;
1170                         selend_tmp = but->selend;
1171                         
1172                         if (but->drawstr[0] != 0) {
1173
1174                                 if (but->selsta >= but->ofs) {
1175                                         ch = but->drawstr[selsta_tmp];
1176                                         but->drawstr[selsta_tmp] = 0;
1177                                         
1178                                         selsta_draw = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
1179                                         
1180                                         but->drawstr[selsta_tmp] = ch;
1181                                 }
1182                                 else {
1183                                         selsta_draw = 0;
1184                                 }
1185                                 
1186                                 ch = but->drawstr[selend_tmp];
1187                                 but->drawstr[selend_tmp] = 0;
1188                                 
1189                                 selwidth_draw = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
1190                                 
1191                                 but->drawstr[selend_tmp] = ch;
1192
1193                                 glColor3ubv((unsigned char *)wcol->item);
1194                                 glRects(rect->xmin + selsta_draw, rect->ymin + 2, rect->xmin + selwidth_draw, rect->ymax - 2);
1195                         }
1196                 }
1197                 else {
1198                         /* text cursor */
1199                         pos = but->pos;
1200                         if (pos >= but->ofs) {
1201                                 if (but->drawstr[0] != 0) {
1202                                         ch = but->drawstr[pos];
1203                                         but->drawstr[pos] = 0;
1204                                         
1205                                         t = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs) / but->aspect;
1206                                         
1207                                         but->drawstr[pos] = ch;
1208                                 }
1209
1210                                 glColor3f(0.20, 0.6, 0.9);
1211                                 glRects(rect->xmin + t, rect->ymin + 2, rect->xmin + t + 2, rect->ymax - 2);
1212                         }
1213                 }
1214         }
1215         
1216         if (fstyle->kerning == 1)
1217                 BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
1218
1219 #if 0
1220         ui_rasterpos_safe(x, y, but->aspect);
1221         if (but->type == IDPOIN) transopts = 0;  /* no translation, of course! */
1222         else transopts = ui_translate_buttons();
1223 #endif
1224
1225         /* cut string in 2 parts - only for menu entries */
1226         if ((but->block->flag & UI_BLOCK_LOOP)) {
1227                 if (ELEM5(but->type, SLI, NUM, TEX, NUMSLI, NUMABS) == 0) {
1228                         cpoin = strchr(but->drawstr, '|');
1229                         if (cpoin) *cpoin = 0;
1230                 }
1231         }
1232         
1233         glColor3ubv((unsigned char *)wcol->text);
1234
1235         uiStyleFontDrawExt(fstyle, rect, but->drawstr + but->ofs, &font_xofs, &font_yofs);
1236
1237         if (but->menu_key != '\0') {
1238                 char fixedbuf[128];
1239                 char *str;
1240
1241                 BLI_strncpy(fixedbuf, but->drawstr + but->ofs, sizeof(fixedbuf));
1242
1243                 str = strchr(fixedbuf, but->menu_key - 32); /* upper case */
1244                 if (str == NULL)
1245                         str = strchr(fixedbuf, but->menu_key);
1246
1247                 if (str) {
1248                         int ul_index = -1;
1249                         float ul_advance;
1250
1251                         ul_index = (int)(str - fixedbuf);
1252
1253                         if (fstyle->kerning == 1) {
1254                                 BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
1255                         }
1256
1257                         fixedbuf[ul_index] = '\0';
1258                         ul_advance = BLF_width(fstyle->uifont_id, fixedbuf);
1259
1260                         BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f);
1261                         BLF_draw(fstyle->uifont_id, "_", 2);
1262
1263                         if (fstyle->kerning == 1) {
1264                                 BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
1265                         }
1266                 }
1267         }
1268
1269         /* part text right aligned */
1270         if (cpoin) {
1271                 fstyle->align = UI_STYLE_TEXT_RIGHT;
1272                 rect->xmax -= ui_but_draw_menu_icon(but) ? UI_DPI_ICON_SIZE : 5;
1273                 uiStyleFontDraw(fstyle, rect, cpoin + 1);
1274                 *cpoin = '|';
1275         }
1276 }
1277
1278 /* draws text and icons for buttons */
1279 static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
1280 {
1281         char password_str[UI_MAX_DRAW_STR];
1282
1283         if (but == NULL)
1284                 return;
1285
1286         ui_button_text_password_hide(password_str, but, FALSE);
1287
1288         /* clip but->drawstr to fit in available space */
1289         if (but->editstr && but->pos >= 0) {
1290                 ui_text_clip_cursor(fstyle, but, rect);
1291         }
1292         else if (ELEM4(but->type, NUM, NUMABS, NUMSLI, SLI)) {
1293                 ui_text_clip_right_label(fstyle, but, rect);
1294         }
1295         else if (ELEM(but->type, TEX, SEARCH_MENU)) {
1296                 ui_text_clip_left(fstyle, but, rect);
1297         }
1298         else if ((but->block->flag & UI_BLOCK_LOOP) && (but->type == BUT)) {
1299                 ui_text_clip_left(fstyle, but, rect);
1300         }
1301         else but->ofs = 0;
1302
1303         /* check for button text label */
1304         if (but->type == ICONTEXTROW) {
1305                 widget_draw_icon(but, (BIFIconID) (but->icon + but->iconadd), 1.0f, rect);
1306         }
1307         else {
1308
1309                 if (but->type == BUT_TOGDUAL) {
1310                         int dualset = 0;
1311                         if (but->pointype == UI_BUT_POIN_SHORT) {
1312                                 dualset = UI_BITBUT_TEST(*(((short *)but->poin) + 1), but->bitnr);
1313                         }
1314                         else if (but->pointype == UI_BUT_POIN_INT) {
1315                                 dualset = UI_BITBUT_TEST(*(((int *)but->poin) + 1), but->bitnr);
1316                         }
1317
1318                         widget_draw_icon(but, ICON_DOT, dualset ? 1.0f : 0.25f, rect);
1319                 }
1320                 else if (but->type == MENU && (but->flag & UI_BUT_NODE_LINK)) {
1321                         int tmp = rect->xmin;
1322                         rect->xmin = rect->xmax - BLI_rcti_size_y(rect) - 1;
1323                         widget_draw_icon(but, ICON_LAYER_USED, 1.0f, rect);
1324                         rect->xmin = tmp;
1325                 }
1326
1327                 /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
1328                  * and offset the text label to accommodate it */
1329
1330                 if (but->flag & UI_HAS_ICON) {
1331                         widget_draw_icon(but, but->icon + but->iconadd, 1.0f, rect);
1332
1333                         rect->xmin += (int)((float)UI_icon_get_width(but->icon + but->iconadd) * UI_DPI_ICON_FAC);
1334
1335                         if (but->editstr || (but->flag & UI_TEXT_LEFT))
1336                                 rect->xmin += 5;
1337                 }
1338                 else if ((but->flag & UI_TEXT_LEFT))
1339                         rect->xmin += 5;
1340
1341                 /* always draw text for textbutton cursor */
1342                 widget_draw_text(fstyle, wcol, but, rect);
1343
1344         }
1345
1346         ui_button_text_password_hide(password_str, but, TRUE);
1347 }
1348
1349
1350
1351 /* *********************** widget types ************************************* */
1352
1353
1354 /* uiWidgetStateColors
1355  *     char inner_anim[4];
1356  *     char inner_anim_sel[4];
1357  *     char inner_key[4];
1358  *     char inner_key_sel[4];
1359  *     char inner_driven[4];
1360  *     char inner_driven_sel[4];
1361  *     float blend;
1362  */
1363
1364 static struct uiWidgetStateColors wcol_state_colors = {
1365         {115, 190, 76, 255},
1366         {90, 166, 51, 255},
1367         {240, 235, 100, 255},
1368         {215, 211, 75, 255},
1369         {180, 0, 255, 255},
1370         {153, 0, 230, 255},
1371         0.5f, 0.0f
1372 };
1373
1374 /* uiWidgetColors
1375  *     float outline[3];
1376  *     float inner[4];
1377  *     float inner_sel[4];
1378  *     float item[3];
1379  *     float text[3];
1380  *     float text_sel[3];
1381  *     
1382  *     short shaded;
1383  *     float shadetop, shadedown;
1384  */
1385
1386 static struct uiWidgetColors wcol_num = {
1387         {25, 25, 25, 255},
1388         {180, 180, 180, 255},
1389         {153, 153, 153, 255},
1390         {90, 90, 90, 255},
1391         
1392         {0, 0, 0, 255},
1393         {255, 255, 255, 255},
1394         
1395         1,
1396         -20, 0
1397 };
1398
1399 static struct uiWidgetColors wcol_numslider = {
1400         {25, 25, 25, 255},
1401         {180, 180, 180, 255},
1402         {153, 153, 153, 255},
1403         {128, 128, 128, 255},
1404         
1405         {0, 0, 0, 255},
1406         {255, 255, 255, 255},
1407         
1408         1,
1409         -20, 0
1410 };
1411
1412 static struct uiWidgetColors wcol_text = {
1413         {25, 25, 25, 255},
1414         {153, 153, 153, 255},
1415         {153, 153, 153, 255},
1416         {90, 90, 90, 255},
1417         
1418         {0, 0, 0, 255},
1419         {255, 255, 255, 255},
1420         
1421         1,
1422         0, 25
1423 };
1424
1425 static struct uiWidgetColors wcol_option = {
1426         {0, 0, 0, 255},
1427         {70, 70, 70, 255},
1428         {70, 70, 70, 255},
1429         {255, 255, 255, 255},
1430         
1431         {0, 0, 0, 255},
1432         {255, 255, 255, 255},
1433         
1434         1,
1435         15, -15
1436 };
1437
1438 /* button that shows popup */
1439 static struct uiWidgetColors wcol_menu = {
1440         {0, 0, 0, 255},
1441         {70, 70, 70, 255},
1442         {70, 70, 70, 255},
1443         {255, 255, 255, 255},
1444         
1445         {255, 255, 255, 255},
1446         {204, 204, 204, 255},
1447         
1448         1,
1449         15, -15
1450 };
1451
1452 /* button that starts pulldown */
1453 static struct uiWidgetColors wcol_pulldown = {
1454         {0, 0, 0, 255},
1455         {63, 63, 63, 255},
1456         {86, 128, 194, 255},
1457         {255, 255, 255, 255},
1458         
1459         {0, 0, 0, 255},
1460         {0, 0, 0, 255},
1461         
1462         0,
1463         25, -20
1464 };
1465
1466 /* button inside menu */
1467 static struct uiWidgetColors wcol_menu_item = {
1468         {0, 0, 0, 255},
1469         {0, 0, 0, 0},
1470         {86, 128, 194, 255},
1471         {172, 172, 172, 128},
1472         
1473         {255, 255, 255, 255},
1474         {0, 0, 0, 255},
1475         
1476         1,
1477         38, 0
1478 };
1479
1480 /* backdrop menu + title text color */
1481 static struct uiWidgetColors wcol_menu_back = {
1482         {0, 0, 0, 255},
1483         {25, 25, 25, 230},
1484         {45, 45, 45, 230},
1485         {100, 100, 100, 255},
1486         
1487         {160, 160, 160, 255},
1488         {255, 255, 255, 255},
1489         
1490         0,
1491         25, -20
1492 };
1493
1494 /* tooltip color */
1495 static struct uiWidgetColors wcol_tooltip = {
1496         {0, 0, 0, 255},
1497         {25, 25, 25, 230},
1498         {45, 45, 45, 230},
1499         {100, 100, 100, 255},
1500
1501         {160, 160, 160, 255},
1502         {255, 255, 255, 255},
1503
1504         0,
1505         25, -20
1506 };
1507
1508 static struct uiWidgetColors wcol_radio = {
1509         {0, 0, 0, 255},
1510         {70, 70, 70, 255},
1511         {86, 128, 194, 255},
1512         {255, 255, 255, 255},
1513         
1514         {255, 255, 255, 255},
1515         {0, 0, 0, 255},
1516         
1517         1,
1518         15, -15
1519 };
1520
1521 static struct uiWidgetColors wcol_regular = {
1522         {25, 25, 25, 255},
1523         {153, 153, 153, 255},
1524         {100, 100, 100, 255},
1525         {25, 25, 25, 255},
1526         
1527         {0, 0, 0, 255},
1528         {255, 255, 255, 255},
1529         
1530         0,
1531         0, 0
1532 };
1533
1534 static struct uiWidgetColors wcol_tool = {
1535         {25, 25, 25, 255},
1536         {153, 153, 153, 255},
1537         {100, 100, 100, 255},
1538         {25, 25, 25, 255},
1539         
1540         {0, 0, 0, 255},
1541         {255, 255, 255, 255},
1542         
1543         1,
1544         15, -15
1545 };
1546
1547 static struct uiWidgetColors wcol_box = {
1548         {25, 25, 25, 255},
1549         {128, 128, 128, 255},
1550         {100, 100, 100, 255},
1551         {25, 25, 25, 255},
1552         
1553         {0, 0, 0, 255},
1554         {255, 255, 255, 255},
1555         
1556         0,
1557         0, 0
1558 };
1559
1560 static struct uiWidgetColors wcol_toggle = {
1561         {25, 25, 25, 255},
1562         {153, 153, 153, 255},
1563         {100, 100, 100, 255},
1564         {25, 25, 25, 255},
1565         
1566         {0, 0, 0, 255},
1567         {255, 255, 255, 255},
1568         
1569         0,
1570         0, 0
1571 };
1572
1573 static struct uiWidgetColors wcol_scroll = {
1574         {50, 50, 50, 180},
1575         {80, 80, 80, 180},
1576         {100, 100, 100, 180},
1577         {128, 128, 128, 255},
1578         
1579         {0, 0, 0, 255},
1580         {255, 255, 255, 255},
1581         
1582         1,
1583         5, -5
1584 };
1585
1586 static struct uiWidgetColors wcol_progress = {
1587         {0, 0, 0, 255},
1588         {190, 190, 190, 255},
1589         {100, 100, 100, 180},
1590         {68, 68, 68, 255},
1591         
1592         {0, 0, 0, 255},
1593         {255, 255, 255, 255},
1594         
1595         0,
1596         0, 0
1597 };
1598
1599 static struct uiWidgetColors wcol_list_item = {
1600         {0, 0, 0, 255},
1601         {0, 0, 0, 0},
1602         {86, 128, 194, 255},
1603         {0, 0, 0, 255},
1604         
1605         {0, 0, 0, 255},
1606         {0, 0, 0, 255},
1607         
1608         0,
1609         0, 0
1610 };
1611
1612 /* free wcol struct to play with */
1613 static struct uiWidgetColors wcol_tmp = {
1614         {0, 0, 0, 255},
1615         {128, 128, 128, 255},
1616         {100, 100, 100, 255},
1617         {25, 25, 25, 255},
1618         
1619         {0, 0, 0, 255},
1620         {255, 255, 255, 255},
1621         
1622         0,
1623         0, 0
1624 };
1625
1626
1627 /* called for theme init (new theme) and versions */
1628 void ui_widget_color_init(ThemeUI *tui)
1629 {
1630         tui->wcol_regular = wcol_regular;
1631         tui->wcol_tool = wcol_tool;
1632         tui->wcol_text = wcol_text;
1633         tui->wcol_radio = wcol_radio;
1634         tui->wcol_option = wcol_option;
1635         tui->wcol_toggle = wcol_toggle;
1636         tui->wcol_num = wcol_num;
1637         tui->wcol_numslider = wcol_numslider;
1638         tui->wcol_menu = wcol_menu;
1639         tui->wcol_pulldown = wcol_pulldown;
1640         tui->wcol_menu_back = wcol_menu_back;
1641         tui->wcol_tooltip = wcol_tooltip;
1642         tui->wcol_menu_item = wcol_menu_item;
1643         tui->wcol_box = wcol_box;
1644         tui->wcol_scroll = wcol_scroll;
1645         tui->wcol_list_item = wcol_list_item;
1646         tui->wcol_progress = wcol_progress;
1647
1648         tui->wcol_state = wcol_state_colors;
1649 }
1650
1651 /* ************ button callbacks, state ***************** */
1652
1653 static void widget_state_blend(char cp[3], const char cpstate[3], const float fac)
1654 {
1655         if (fac != 0.0f) {
1656                 cp[0] = (int)((1.0f - fac) * cp[0] + fac * cpstate[0]);
1657                 cp[1] = (int)((1.0f - fac) * cp[1] + fac * cpstate[1]);
1658                 cp[2] = (int)((1.0f - fac) * cp[2] + fac * cpstate[2]);
1659         }
1660 }
1661
1662 /* copy colors from theme, and set changes in it based on state */
1663 static void widget_state(uiWidgetType *wt, int state)
1664 {
1665         uiWidgetStateColors *wcol_state = wt->wcol_state;
1666
1667         wt->wcol = *(wt->wcol_theme);
1668         
1669         if (state & UI_SELECT) {
1670                 copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
1671
1672                 if (state & UI_BUT_ANIMATED_KEY)
1673                         widget_state_blend(wt->wcol.inner, wcol_state->inner_key_sel, wcol_state->blend);
1674                 else if (state & UI_BUT_ANIMATED)
1675                         widget_state_blend(wt->wcol.inner, wcol_state->inner_anim_sel, wcol_state->blend);
1676                 else if (state & UI_BUT_DRIVEN)
1677                         widget_state_blend(wt->wcol.inner, wcol_state->inner_driven_sel, wcol_state->blend);
1678
1679                 copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
1680                 
1681                 if (state & UI_SELECT)
1682                         SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
1683         }
1684         else {
1685                 if (state & UI_BUT_ANIMATED_KEY)
1686                         widget_state_blend(wt->wcol.inner, wcol_state->inner_key, wcol_state->blend);
1687                 else if (state & UI_BUT_ANIMATED)
1688                         widget_state_blend(wt->wcol.inner, wcol_state->inner_anim, wcol_state->blend);
1689                 else if (state & UI_BUT_DRIVEN)
1690                         widget_state_blend(wt->wcol.inner, wcol_state->inner_driven, wcol_state->blend);
1691
1692                 if (state & UI_ACTIVE) { /* mouse over? */
1693                         wt->wcol.inner[0] = wt->wcol.inner[0] >= 240 ? 255 : wt->wcol.inner[0] + 15;
1694                         wt->wcol.inner[1] = wt->wcol.inner[1] >= 240 ? 255 : wt->wcol.inner[1] + 15;
1695                         wt->wcol.inner[2] = wt->wcol.inner[2] >= 240 ? 255 : wt->wcol.inner[2] + 15;
1696                 }
1697         }
1698
1699         if (state & UI_BUT_REDALERT) {
1700                 char red[4] = {255, 0, 0};
1701                 widget_state_blend(wt->wcol.inner, red, 0.4f);
1702         }
1703         if (state & UI_BUT_NODE_ACTIVE) {
1704                 char blue[4] = {86, 128, 194};
1705                 widget_state_blend(wt->wcol.inner, blue, 0.3f);
1706         }
1707 }
1708
1709 /* sliders use special hack which sets 'item' as inner when drawing filling */
1710 static void widget_state_numslider(uiWidgetType *wt, int state)
1711 {
1712         uiWidgetStateColors *wcol_state = wt->wcol_state;
1713         float blend = wcol_state->blend - 0.2f; /* XXX special tweak to make sure that bar will still be visible */
1714
1715         /* call this for option button */
1716         widget_state(wt, state);
1717         
1718         /* now, set the inner-part so that it reflects state settings too */
1719         /* TODO: maybe we should have separate settings for the blending colors used for this case? */
1720         if (state & UI_SELECT) {
1721                 
1722                 if (state & UI_BUT_ANIMATED_KEY)
1723                         widget_state_blend(wt->wcol.item, wcol_state->inner_key_sel, blend);
1724                 else if (state & UI_BUT_ANIMATED)
1725                         widget_state_blend(wt->wcol.item, wcol_state->inner_anim_sel, blend);
1726                 else if (state & UI_BUT_DRIVEN)
1727                         widget_state_blend(wt->wcol.item, wcol_state->inner_driven_sel, blend);
1728                 
1729                 if (state & UI_SELECT)
1730                         SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
1731         }
1732         else {
1733                 if (state & UI_BUT_ANIMATED_KEY)
1734                         widget_state_blend(wt->wcol.item, wcol_state->inner_key, blend);
1735                 else if (state & UI_BUT_ANIMATED)
1736                         widget_state_blend(wt->wcol.item, wcol_state->inner_anim, blend);
1737                 else if (state & UI_BUT_DRIVEN)
1738                         widget_state_blend(wt->wcol.item, wcol_state->inner_driven, blend);
1739         }
1740 }
1741
1742 /* labels use theme colors for text */
1743 static void widget_state_label(uiWidgetType *wt, int state)
1744 {
1745         /* call this for option button */
1746         widget_state(wt, state);
1747
1748         if (state & UI_SELECT)
1749                 UI_GetThemeColor4ubv(TH_TEXT_HI, (unsigned char *)wt->wcol.text);
1750         else
1751                 UI_GetThemeColor4ubv(TH_TEXT, (unsigned char *)wt->wcol.text);
1752         
1753 }
1754
1755 /* labels use theme colors for text */
1756 static void widget_state_option_menu(uiWidgetType *wt, int state)
1757 {
1758         
1759         /* call this for option button */
1760         widget_state(wt, state);
1761         
1762         /* if not selected we get theme from menu back */
1763         if (state & UI_SELECT)
1764                 UI_GetThemeColor4ubv(TH_TEXT_HI, (unsigned char *)wt->wcol.text);
1765         else {
1766                 bTheme *btheme = UI_GetTheme(); /* XXX */
1767
1768                 copy_v3_v3_char(wt->wcol.text, btheme->tui.wcol_menu_back.text);
1769         }
1770 }
1771
1772
1773 static void widget_state_nothing(uiWidgetType *wt, int UNUSED(state))
1774 {
1775         wt->wcol = *(wt->wcol_theme);
1776 }       
1777
1778 /* special case, button that calls pulldown */
1779 static void widget_state_pulldown(uiWidgetType *wt, int state)
1780 {
1781         wt->wcol = *(wt->wcol_theme);
1782         
1783         copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
1784         copy_v3_v3_char(wt->wcol.outline, wt->wcol.inner);
1785
1786         if (state & UI_ACTIVE)
1787                 copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
1788 }
1789
1790 /* special case, menu items */
1791 static void widget_state_menu_item(uiWidgetType *wt, int state)
1792 {
1793         wt->wcol = *(wt->wcol_theme);
1794         
1795         if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
1796                 wt->wcol.text[0] = 0.5f * (wt->wcol.text[0] + wt->wcol.text_sel[0]);
1797                 wt->wcol.text[1] = 0.5f * (wt->wcol.text[1] + wt->wcol.text_sel[1]);
1798                 wt->wcol.text[2] = 0.5f * (wt->wcol.text[2] + wt->wcol.text_sel[2]);
1799         }
1800         else if (state & UI_ACTIVE) {
1801                 copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
1802                 copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
1803         }
1804 }
1805
1806
1807 /* ************ menu backdrop ************************* */
1808
1809 /* outside of rect, rad to left/bottom/right */
1810 static void widget_softshadow(rcti *rect, int roundboxalign, float radin, float radout)
1811 {
1812         uiWidgetBase wtb;
1813         rcti rect1 = *rect;
1814         float alpha, alphastep;
1815         int step, totvert;
1816         float quad_strip[WIDGET_SIZE_MAX * 2][2];
1817         
1818         /* prevent tooltips to not show round shadow */
1819         if (2.0f * radout > 0.2f * BLI_rcti_size_y(&rect1))
1820                 rect1.ymax -= 0.2f * BLI_rcti_size_y(&rect1);
1821         else
1822                 rect1.ymax -= 2.0f * radout;
1823         
1824         /* inner part */
1825         totvert = round_box_shadow_edges(wtb.inner_v, &rect1, radin, roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT), 0.0f);
1826
1827         /* inverse linear shadow alpha */
1828         alpha = 0.15;
1829         alphastep = 0.67;
1830         
1831         glEnableClientState(GL_VERTEX_ARRAY);
1832
1833         for (step = 1; step <= radout; step++, alpha *= alphastep) {
1834                 round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step);
1835                 
1836                 glColor4f(0.0f, 0.0f, 0.0f, alpha);
1837
1838                 widget_verts_to_quad_strip_open(&wtb, totvert, quad_strip);
1839
1840                 glVertexPointer(2, GL_FLOAT, 0, quad_strip);
1841                 glDrawArrays(GL_QUAD_STRIP, 0, totvert * 2);
1842         }
1843
1844         glDisableClientState(GL_VERTEX_ARRAY);
1845 }
1846
1847 static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction)
1848 {
1849         uiWidgetBase wtb;
1850         int roundboxalign = UI_CNR_ALL;
1851         
1852         widget_init(&wtb);
1853         
1854         /* menu is 2nd level or deeper */
1855         if (flag & UI_BLOCK_POPUP) {
1856                 //rect->ymin -= 4.0;
1857                 //rect->ymax += 4.0;
1858         }
1859         else if (direction == UI_DOWN) {
1860                 roundboxalign = (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
1861                 rect->ymin -= 4.0;
1862         }
1863         else if (direction == UI_TOP) {
1864                 roundboxalign = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
1865                 rect->ymax += 4.0;
1866         }
1867         
1868         glEnable(GL_BLEND);
1869         widget_softshadow(rect, roundboxalign, 5.0f, 8.0f);
1870         
1871         round_box_edges(&wtb, roundboxalign, rect, 5.0f);
1872         wtb.emboss = 0;
1873         widgetbase_draw(&wtb, wcol);
1874         
1875         glDisable(GL_BLEND);
1876 }
1877
1878
1879 static void ui_hsv_cursor(float x, float y)
1880 {
1881         
1882         glPushMatrix();
1883         glTranslatef(x, y, 0.0f);
1884         
1885         glColor3f(1.0f, 1.0f, 1.0f);
1886         glutil_draw_filled_arc(0.0f, M_PI * 2.0, 3.0f, 8);
1887         
1888         glEnable(GL_BLEND);
1889         glEnable(GL_LINE_SMOOTH);
1890         glColor3f(0.0f, 0.0f, 0.0f);
1891         glutil_draw_lined_arc(0.0f, M_PI * 2.0, 3.0f, 12);
1892         glDisable(GL_BLEND);
1893         glDisable(GL_LINE_SMOOTH);
1894         
1895         glPopMatrix();
1896         
1897 }
1898
1899 void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect,
1900                                 const float mx, const float my)
1901 {
1902         /* duplication of code... well, simple is better now */
1903         const float centx = BLI_rcti_cent_x_fl(rect);
1904         const float centy = BLI_rcti_cent_y_fl(rect);
1905         const float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
1906         const float m_delta[2] = {mx - centx, my - centy};
1907         const float dist_squared = len_squared_v2(m_delta);
1908
1909         *val_dist = (dist_squared < (radius * radius)) ? sqrtf(dist_squared) / radius : 1.0f;
1910         *val_rad = atan2f(m_delta[0], m_delta[1]) / (2.0f * (float)M_PI) + 0.5f;
1911 }
1912
1913 static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
1914 {
1915         const int tot = 32;
1916         const float radstep = 2.0f * (float)M_PI / (float)tot;
1917
1918         const float centx = BLI_rcti_cent_x_fl(rect);
1919         const float centy = BLI_rcti_cent_y_fl(rect);
1920         float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
1921
1922         /* gouraud triangle fan */
1923         const float *hsv_ptr = ui_block_hsv_get(but->block);
1924         float ang = 0.0f;
1925         float cursor_radius;
1926         float rgb[3], hsvo[3], hsv[3], col[3], colcent[3];
1927         int a;
1928         int color_profile = but->block->color_profile;
1929         
1930         if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
1931                 color_profile = FALSE;
1932         
1933         /* color */
1934         ui_get_but_vectorf(but, rgb);
1935
1936         /* since we use compat functions on both 'hsv' and 'hsvo', they need to be initialized */
1937         hsvo[0] = hsv[0] = hsv_ptr[0];
1938         hsvo[1] = hsv[1] = hsv_ptr[1];
1939         hsvo[2] = hsv[2] = hsv_ptr[2];
1940
1941         rgb_to_hsv_compat_v(rgb, hsvo);
1942
1943         if (color_profile)
1944                 ui_block_to_display_space_v3(but->block, rgb);
1945
1946         rgb_to_hsv_compat_v(rgb, hsv);
1947         
1948         /* exception: if 'lock' is set
1949          * lock the value of the color wheel to 1.
1950          * Useful for color correction tools where you're only interested in hue. */
1951         if (but->flag & UI_BUT_COLOR_LOCK)
1952                 hsv[2] = 1.f;
1953         
1954         hsv_to_rgb(0.f, 0.f, hsv[2], colcent, colcent + 1, colcent + 2);
1955         
1956         glShadeModel(GL_SMOOTH);
1957
1958         glBegin(GL_TRIANGLE_FAN);
1959         glColor3fv(colcent);
1960         glVertex2f(centx, centy);
1961         
1962         for (a = 0; a <= tot; a++, ang += radstep) {
1963                 float si = sin(ang);
1964                 float co = cos(ang);
1965                 
1966                 ui_hsvcircle_vals_from_pos(hsv, hsv + 1, rect, centx + co * radius, centy + si * radius);
1967                 CLAMP(hsv[2], 0.0f, 1.0f); /* for display only */
1968
1969                 hsv_to_rgb_v(hsv, col);
1970                 glColor3fv(col);
1971                 glVertex2f(centx + co * radius, centy + si * radius);
1972         }
1973         glEnd();
1974         
1975         glShadeModel(GL_FLAT);
1976         
1977         /* fully rounded outline */
1978         glPushMatrix();
1979         glTranslatef(centx, centy, 0.0f);
1980         glEnable(GL_BLEND);
1981         glEnable(GL_LINE_SMOOTH);
1982         glColor3ubv((unsigned char *)wcol->outline);
1983         glutil_draw_lined_arc(0.0f, M_PI * 2.0, radius, tot + 1);
1984         glDisable(GL_BLEND);
1985         glDisable(GL_LINE_SMOOTH);
1986         glPopMatrix();
1987
1988         /* cursor */
1989         ang = 2.0f * (float)M_PI * hsvo[0] + 0.5f * (float)M_PI;
1990
1991         if (but->flag & UI_BUT_COLOR_CUBIC)
1992                 cursor_radius = (1.0f - powf(1.0f - hsvo[1], 3.0f));
1993         else
1994                 cursor_radius = hsvo[1];
1995
1996         radius = CLAMPIS(cursor_radius, 0.0f, 1.0f) * radius;
1997         ui_hsv_cursor(centx + cosf(-ang) * radius, centy + sinf(-ang) * radius);
1998 }
1999
2000 /* ************ custom buttons, old stuff ************** */
2001
2002 /* draws in resolution of 20x4 colors */
2003 void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const float alpha)
2004 {
2005         const float color_step = (type == UI_GRAD_H) ? 0.02f : 0.05f;
2006         int a;
2007         float h = hsv[0], s = hsv[1], v = hsv[2];
2008         float dx, dy, sx1, sx2, sy;
2009         float col0[4][3];   /* left half, rect bottom to top */
2010         float col1[4][3];   /* right half, rect bottom to top */
2011
2012         /* draw series of gouraud rects */
2013         glShadeModel(GL_SMOOTH);
2014         
2015         switch (type) {
2016                 case UI_GRAD_SV:
2017                         hsv_to_rgb(h, 0.0, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2018                         hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]);
2019                         hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
2020                         hsv_to_rgb(h, 1.0, 0.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
2021                         break;
2022                 case UI_GRAD_HV:
2023                         hsv_to_rgb(0.0, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2024                         hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
2025                         hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
2026                         hsv_to_rgb(0.0, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
2027                         break;
2028                 case UI_GRAD_HS:
2029                         hsv_to_rgb(0.0, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
2030                         hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
2031                         hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
2032                         hsv_to_rgb(0.0, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
2033                         break;
2034                 case UI_GRAD_H:
2035                         hsv_to_rgb(0.0, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2036                         copy_v3_v3(col1[1], col1[0]);
2037                         copy_v3_v3(col1[2], col1[0]);
2038                         copy_v3_v3(col1[3], col1[0]);
2039                         break;
2040                 case UI_GRAD_S:
2041                         hsv_to_rgb(1.0, 0.0, 1.0,   &col1[1][0], &col1[1][1], &col1[1][2]);
2042                         copy_v3_v3(col1[0], col1[1]);
2043                         copy_v3_v3(col1[2], col1[1]);
2044                         copy_v3_v3(col1[3], col1[1]);
2045                         break;
2046                 case UI_GRAD_V:
2047                         hsv_to_rgb(1.0, 1.0, 0.0,   &col1[2][0], &col1[2][1], &col1[2][2]);
2048                         copy_v3_v3(col1[0], col1[2]);
2049                         copy_v3_v3(col1[1], col1[2]);
2050                         copy_v3_v3(col1[3], col1[2]);
2051                         break;
2052                 default:
2053                         assert(!"invalid 'type' argument");
2054                         hsv_to_rgb(1.0, 1.0, 1.0,   &col1[2][0], &col1[2][1], &col1[2][2]);
2055                         copy_v3_v3(col1[0], col1[2]);
2056                         copy_v3_v3(col1[1], col1[2]);
2057                         copy_v3_v3(col1[3], col1[2]);
2058         }
2059         
2060         /* old below */
2061         
2062         for (dx = 0.0f; dx < 0.999f; dx += color_step) { /* 0.999 = prevent float inaccuracy for steps */
2063                 /* previous color */
2064                 copy_v3_v3(col0[0], col1[0]);
2065                 copy_v3_v3(col0[1], col1[1]);
2066                 copy_v3_v3(col0[2], col1[2]);
2067                 copy_v3_v3(col0[3], col1[3]);
2068                 
2069                 /* new color */
2070                 switch (type) {
2071                         case UI_GRAD_SV:
2072                                 hsv_to_rgb(h, 0.0, dx,   &col1[0][0], &col1[0][1], &col1[0][2]);
2073                                 hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]);
2074                                 hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
2075                                 hsv_to_rgb(h, 1.0, dx,   &col1[3][0], &col1[3][1], &col1[3][2]);
2076                                 break;
2077                         case UI_GRAD_HV:
2078                                 hsv_to_rgb(dx, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2079                                 hsv_to_rgb(dx, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
2080                                 hsv_to_rgb(dx, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
2081                                 hsv_to_rgb(dx, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
2082                                 break;
2083                         case UI_GRAD_HS:
2084                                 hsv_to_rgb(dx, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
2085                                 hsv_to_rgb(dx, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
2086                                 hsv_to_rgb(dx, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
2087                                 hsv_to_rgb(dx, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
2088                                 break;
2089                         case UI_GRAD_H:
2090                         {
2091                                 /* annoying but without this the color shifts - could be solved some other way
2092                                  * - campbell */
2093                                 hsv_to_rgb(dx + color_step, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2094                                 copy_v3_v3(col1[1], col1[0]);
2095                                 copy_v3_v3(col1[2], col1[0]);
2096                                 copy_v3_v3(col1[3], col1[0]);
2097                                 break;
2098                         }
2099                         case UI_GRAD_S:
2100                                 hsv_to_rgb(h, dx, 1.0,   &col1[1][0], &col1[1][1], &col1[1][2]);
2101                                 copy_v3_v3(col1[0], col1[1]);
2102                                 copy_v3_v3(col1[2], col1[1]);
2103                                 copy_v3_v3(col1[3], col1[1]);
2104                                 break;
2105                         case UI_GRAD_V:
2106                                 hsv_to_rgb(h, 1.0, dx,   &col1[2][0], &col1[2][1], &col1[2][2]);
2107                                 copy_v3_v3(col1[0], col1[2]);
2108                                 copy_v3_v3(col1[1], col1[2]);
2109                                 copy_v3_v3(col1[3], col1[2]);
2110                                 break;
2111                 }
2112                 
2113                 /* rect */
2114                 sx1 = rect->xmin +  dx               * BLI_rcti_size_x(rect);
2115                 sx2 = rect->xmin + (dx + color_step) * BLI_rcti_size_x(rect);
2116                 sy = rect->ymin;
2117                 dy = (float)BLI_rcti_size_y(rect) / 3.0f;
2118                 
2119                 glBegin(GL_QUADS);
2120                 for (a = 0; a < 3; a++, sy += dy) {
2121                         glColor4f(col0[a][0], col0[a][1], col0[a][2], alpha);
2122                         glVertex2f(sx1, sy);
2123                         
2124                         glColor4f(col1[a][0], col1[a][1], col1[a][2], alpha);
2125                         glVertex2f(sx2, sy);
2126
2127                         glColor4f(col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
2128                         glVertex2f(sx2, sy + dy);
2129                         
2130                         glColor4f(col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha);
2131                         glVertex2f(sx1, sy + dy);
2132                 }
2133                 glEnd();
2134         }
2135         
2136         glShadeModel(GL_FLAT);
2137         
2138 }
2139
2140
2141
2142 static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect)
2143 {
2144         float rgb[3];
2145         float x = 0.0f, y = 0.0f;
2146         float *hsv = ui_block_hsv_get(but->block);
2147         float hsv_n[3];
2148         
2149         copy_v3_v3(hsv_n, hsv);
2150         
2151         ui_get_but_vectorf(but, rgb);
2152         rgb_to_hsv_compat_v(rgb, hsv_n);
2153         
2154         ui_draw_gradient(rect, hsv_n, but->a1, 1.0f);
2155         
2156         switch ((int)but->a1) {
2157                 case UI_GRAD_SV:
2158                         x = hsv_n[2]; y = hsv_n[1]; break;
2159                 case UI_GRAD_HV:
2160                         x = hsv_n[0]; y = hsv_n[2]; break;
2161                 case UI_GRAD_HS:
2162                         x = hsv_n[0]; y = hsv_n[1]; break;
2163                 case UI_GRAD_H:
2164                         x = hsv_n[0]; y = 0.5; break;
2165                 case UI_GRAD_S:
2166                         x = hsv_n[1]; y = 0.5; break;
2167                 case UI_GRAD_V:
2168                         x = hsv_n[2]; y = 0.5; break;
2169         }
2170         
2171         /* cursor */
2172         x = rect->xmin + x * BLI_rcti_size_x(rect);
2173         y = rect->ymin + y * BLI_rcti_size_y(rect);
2174         CLAMP(x, rect->xmin + 3.0f, rect->xmax - 3.0f);
2175         CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
2176         
2177         ui_hsv_cursor(x, y);
2178         
2179         /* outline */
2180         glColor3ub(0,  0,  0);
2181         fdrawbox((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
2182 }
2183
2184 /* vertical 'value' slider, using new widget code */
2185 static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
2186 {
2187         uiWidgetBase wtb;
2188         float rad = 0.5f * BLI_rcti_size_x(rect);
2189         float x, y;
2190         float rgb[3], hsv[3], v, range;
2191         int color_profile = but->block->color_profile;
2192         
2193         if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
2194                 color_profile = FALSE;
2195
2196         ui_get_but_vectorf(but, rgb);
2197
2198         if (color_profile)
2199                 ui_block_to_display_space_v3(but->block, rgb);
2200
2201         rgb_to_hsv_v(rgb, hsv);
2202         v = hsv[2];
2203         
2204         /* map v from property range to [0,1] */
2205         range = but->softmax - but->softmin;
2206         v = (v - but->softmin) / range;
2207         
2208         widget_init(&wtb);
2209         
2210         /* fully rounded */
2211         round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
2212         
2213         /* setup temp colors */
2214         wcol_tmp.outline[0] = wcol_tmp.outline[1] = wcol_tmp.outline[2] = 0;
2215         wcol_tmp.inner[0] = wcol_tmp.inner[1] = wcol_tmp.inner[2] = 128;
2216         wcol_tmp.shadetop = 127;
2217         wcol_tmp.shadedown = -128;
2218         wcol_tmp.shaded = 1;
2219         
2220         widgetbase_draw(&wtb, &wcol_tmp);
2221
2222         /* cursor */
2223         x = rect->xmin + 0.5f * BLI_rcti_size_x(rect);
2224         y = rect->ymin + v    * BLI_rcti_size_y(rect);
2225         CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f);
2226         
2227         ui_hsv_cursor(x, y);
2228         
2229 }
2230
2231
2232 /* ************ separator, for menus etc ***************** */
2233 static void ui_draw_separator(rcti *rect,  uiWidgetColors *wcol)
2234 {
2235         int y = rect->ymin + BLI_rcti_size_y(rect) / 2 - 1;
2236         unsigned char col[4];
2237         
2238         col[0] = wcol->text[0];
2239         col[1] = wcol->text[1];
2240         col[2] = wcol->text[2];
2241         col[3] = 7;
2242         
2243         glEnable(GL_BLEND);
2244         glColor4ubv(col);
2245         sdrawline(rect->xmin, y, rect->xmax, y);
2246         glDisable(GL_BLEND);
2247 }
2248
2249 /* ************ button callbacks, draw ***************** */
2250
2251 static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2252 {
2253         uiWidgetBase wtb;
2254         float rad = 0.5f * BLI_rcti_size_y(rect);
2255         float textofs = rad * 0.75f;
2256
2257         if (state & UI_SELECT)
2258                 SWAP(short, wcol->shadetop, wcol->shadedown);
2259         
2260         widget_init(&wtb);
2261         
2262         /* fully rounded */
2263         round_box_edges(&wtb, roundboxalign, rect, rad);
2264         
2265         /* decoration */
2266         if (!(state & UI_TEXTINPUT)) {
2267                 widget_num_tria(&wtb.tria1, rect, 0.6f, 'l');
2268                 widget_num_tria(&wtb.tria2, rect, 0.6f, 'r');
2269         }
2270
2271         widgetbase_draw(&wtb, wcol);
2272         
2273         /* text space */
2274         rect->xmin += textofs;
2275         rect->xmax -= textofs;
2276 }
2277
2278 int ui_link_bezier_points(rcti *rect, float coord_array[][2], int resol)
2279 {
2280         float dist, vec[4][2];
2281
2282         vec[0][0] = rect->xmin;
2283         vec[0][1] = rect->ymin;
2284         vec[3][0] = rect->xmax;
2285         vec[3][1] = rect->ymax;
2286         
2287         dist = 0.5f * ABS(vec[0][0] - vec[3][0]);
2288         
2289         vec[1][0] = vec[0][0] + dist;
2290         vec[1][1] = vec[0][1];
2291         
2292         vec[2][0] = vec[3][0] - dist;
2293         vec[2][1] = vec[3][1];
2294         
2295         BKE_curve_forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, sizeof(float) * 2);
2296         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);
2297         
2298         return 1;
2299 }
2300
2301 #define LINK_RESOL  24
2302 void ui_draw_link_bezier(rcti *rect)
2303 {
2304         float coord_array[LINK_RESOL + 1][2];
2305         
2306         if (ui_link_bezier_points(rect, coord_array, LINK_RESOL)) {
2307                 /* we can reuse the dist variable here to increment the GL curve eval amount*/
2308                 // const float dist = 1.0f / (float)LINK_RESOL; // UNUSED
2309
2310                 glEnable(GL_BLEND);
2311                 glEnable(GL_LINE_SMOOTH);
2312
2313                 glEnableClientState(GL_VERTEX_ARRAY);
2314                 glVertexPointer(2, GL_FLOAT, 0, coord_array);
2315                 glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL);
2316                 glDisableClientState(GL_VERTEX_ARRAY);
2317
2318                 glDisable(GL_BLEND);
2319                 glDisable(GL_LINE_SMOOTH);
2320
2321         }
2322 }
2323
2324 /* function in use for buttons and for view2d sliders */
2325 void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int state)
2326 {
2327         uiWidgetBase wtb;
2328         float rad;
2329         int horizontal;
2330         short outline = 0;
2331
2332         widget_init(&wtb);
2333
2334         /* determine horizontal/vertical */
2335         horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect));
2336         
2337         if (horizontal)
2338                 rad = 0.5f * BLI_rcti_size_y(rect);
2339         else
2340                 rad = 0.5f * BLI_rcti_size_x(rect);
2341         
2342         wtb.shadedir = (horizontal) ? 1 : 0;
2343         
2344         /* draw back part, colors swapped and shading inverted */
2345         if (horizontal)
2346                 SWAP(short, wcol->shadetop, wcol->shadedown);
2347         
2348         round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
2349         widgetbase_draw(&wtb, wcol);
2350         
2351         /* slider */
2352         if ((BLI_rcti_size_x(slider) < 2) || (BLI_rcti_size_y(slider) < 2)) {
2353                 /* pass */
2354         }
2355         else {
2356                 SWAP(short, wcol->shadetop, wcol->shadedown);
2357                 
2358                 copy_v4_v4_char(wcol->inner, wcol->item);
2359                 
2360                 if (wcol->shadetop > wcol->shadedown)
2361                         wcol->shadetop += 20;   /* XXX violates themes... */
2362                 else wcol->shadedown += 20;
2363                 
2364                 if (state & UI_SCROLL_PRESSED) {
2365                         wcol->inner[0] = wcol->inner[0] >= 250 ? 255 : wcol->inner[0] + 5;
2366                         wcol->inner[1] = wcol->inner[1] >= 250 ? 255 : wcol->inner[1] + 5;
2367                         wcol->inner[2] = wcol->inner[2] >= 250 ? 255 : wcol->inner[2] + 5;
2368                 }
2369
2370                 /* draw */
2371                 wtb.emboss = 0; /* only emboss once */
2372                 
2373                 /* exception for progress bar */
2374                 if (state & UI_SCROLL_NO_OUTLINE)
2375                         SWAP(short, outline, wtb.outline);
2376                 
2377                 round_box_edges(&wtb, UI_CNR_ALL, slider, rad);
2378                 
2379                 if (state & UI_SCROLL_ARROWS) {
2380                         if (wcol->item[0] > 48) wcol->item[0] -= 48;
2381                         if (wcol->item[1] > 48) wcol->item[1] -= 48;
2382                         if (wcol->item[2] > 48) wcol->item[2] -= 48;
2383                         wcol->item[3] = 255;
2384                         
2385                         if (horizontal) {
2386                                 widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
2387                                 widget_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
2388                         }
2389                         else {
2390                                 widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
2391                                 widget_scroll_circle(&wtb.tria2, slider, 0.6f, 't');
2392                         }
2393                 }
2394                 widgetbase_draw(&wtb, wcol);
2395                 
2396                 if (state & UI_SCROLL_NO_OUTLINE)
2397                         SWAP(short, outline, wtb.outline);
2398         }
2399 }
2400
2401 static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2402 {
2403         rcti rect1;
2404         double value;
2405         float fac, size, min;
2406         int horizontal;
2407
2408         /* calculate slider part */
2409         value = ui_get_but_val(but);
2410
2411         size = (but->softmax + but->a1 - but->softmin);
2412         size = max_ff(size, 2.0f);
2413         
2414         /* position */
2415         rect1 = *rect;
2416
2417         /* determine horizontal/vertical */
2418         horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect));
2419         
2420         if (horizontal) {
2421                 fac = BLI_rcti_size_x(rect) / size;
2422                 rect1.xmin = rect1.xmin + ceilf(fac * ((float)value - but->softmin));
2423                 rect1.xmax = rect1.xmin + ceilf(fac * (but->a1 - but->softmin));
2424
2425                 /* ensure minimium size */
2426                 min = BLI_rcti_size_y(rect);
2427
2428                 if (BLI_rcti_size_x(&rect1) < min) {
2429                         rect1.xmax = rect1.xmin + min;
2430
2431                         if (rect1.xmax > rect->xmax) {
2432                                 rect1.xmax = rect->xmax;
2433                                 rect1.xmin = max_ii(rect1.xmax - min, rect->xmin);
2434                         }
2435                 }
2436         }
2437         else {
2438                 fac = BLI_rcti_size_y(rect) / size;
2439                 rect1.ymax = rect1.ymax - ceilf(fac * ((float)value - but->softmin));
2440                 rect1.ymin = rect1.ymax - ceilf(fac * (but->a1 - but->softmin));
2441
2442                 /* ensure minimium size */
2443                 min = BLI_rcti_size_x(rect);
2444
2445                 if (BLI_rcti_size_y(&rect1) < min) {
2446                         rect1.ymax = rect1.ymin + min;
2447
2448                         if (rect1.ymax > rect->ymax) {
2449                                 rect1.ymax = rect->ymax;
2450                                 rect1.ymin = max_ii(rect1.ymax - min, rect->ymin);
2451                         }
2452                 }
2453         }
2454
2455         if (state & UI_SELECT)
2456                 state = UI_SCROLL_PRESSED;
2457         else
2458                 state = 0;
2459         uiWidgetScrollDraw(wcol, rect, &rect1, state);
2460 }
2461
2462 static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2463 {
2464         rcti rect_prog = *rect, rect_bar = *rect;
2465         float value = but->a1;
2466         float w, min;
2467         
2468         /* make the progress bar a proportion of the original height */
2469         /* hardcoded 4px high for now */
2470         rect_prog.ymax = rect_prog.ymin + 4;
2471         rect_bar.ymax = rect_bar.ymin + 4;
2472         
2473         w = value * BLI_rcti_size_x(&rect_prog);
2474         
2475         /* ensure minimium size */
2476         min = BLI_rcti_size_y(&rect_prog);
2477         w = MAX2(w, min);
2478         
2479         rect_bar.xmax = rect_bar.xmin + w;
2480                 
2481         uiWidgetScrollDraw(wcol, &rect_prog, &rect_bar, UI_SCROLL_NO_OUTLINE);
2482         
2483         /* raise text a bit */
2484         rect->ymin += 6;
2485         rect->xmin -= 6;
2486 }
2487
2488 static void widget_link(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2489 {
2490         
2491         if (but->flag & UI_SELECT) {
2492                 rcti rectlink;
2493                 
2494                 UI_ThemeColor(TH_TEXT_HI);
2495                 
2496                 rectlink.xmin = BLI_rcti_cent_x(rect);
2497                 rectlink.ymin = BLI_rcti_cent_y(rect);
2498                 rectlink.xmax = but->linkto[0];
2499                 rectlink.ymax = but->linkto[1];
2500                 
2501                 ui_draw_link_bezier(&rectlink);
2502         }
2503 }
2504
2505 static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2506 {
2507         uiWidgetBase wtb, wtb1;
2508         rcti rect1;
2509         double value;
2510         float offs, toffs, fac;
2511         char outline[3];
2512
2513         widget_init(&wtb);
2514         widget_init(&wtb1);
2515         
2516         /* backdrop first */
2517         
2518         /* fully rounded */
2519         offs = 0.5f * BLI_rcti_size_y(rect);
2520         toffs = offs * 0.75f;
2521         round_box_edges(&wtb, roundboxalign, rect, offs);
2522
2523         wtb.outline = 0;
2524         widgetbase_draw(&wtb, wcol);
2525         
2526         /* draw left/right parts only when not in text editing */
2527         if (!(state & UI_TEXTINPUT)) {
2528                 
2529                 /* slider part */
2530                 copy_v3_v3_char(outline, wcol->outline);
2531                 copy_v3_v3_char(wcol->outline, wcol->item);
2532                 copy_v3_v3_char(wcol->inner, wcol->item);
2533
2534                 if (!(state & UI_SELECT))
2535                         SWAP(short, wcol->shadetop, wcol->shadedown);
2536                 
2537                 rect1 = *rect;
2538                 
2539                 value = ui_get_but_val(but);
2540                 fac = ((float)value - but->softmin) * (BLI_rcti_size_x(&rect1) - offs) / (but->softmax - but->softmin);
2541                 
2542                 /* left part of slider, always rounded */
2543                 rect1.xmax = rect1.xmin + ceil(offs + 1.0f);
2544                 round_box_edges(&wtb1, roundboxalign & ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT), &rect1, offs);
2545                 wtb1.outline = 0;
2546                 widgetbase_draw(&wtb1, wcol);
2547                 
2548                 /* right part of slider, interpolate roundness */
2549                 rect1.xmax = rect1.xmin + fac + offs;
2550                 rect1.xmin +=  floor(offs - 1.0f);
2551                 if (rect1.xmax + offs > rect->xmax)
2552                         offs *= (rect1.xmax + offs - rect->xmax) / offs;
2553                 else 
2554                         offs = 0.0f;
2555                 round_box_edges(&wtb1, roundboxalign & ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT), &rect1, offs);
2556                 
2557                 widgetbase_draw(&wtb1, wcol);
2558                 copy_v3_v3_char(wcol->outline, outline);
2559                 
2560                 if (!(state & UI_SELECT))
2561                         SWAP(short, wcol->shadetop, wcol->shadedown);
2562         }
2563         
2564         /* outline */
2565         wtb.outline = 1;
2566         wtb.inner = 0;
2567         widgetbase_draw(&wtb, wcol);
2568         
2569         /* text space */
2570         rect->xmin += toffs;
2571         rect->xmax -= toffs;
2572 }
2573
2574 /* I think 3 is sufficient border to indicate keyed status */
2575 #define SWATCH_KEYED_BORDER 3
2576
2577 static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2578 {
2579         uiWidgetBase wtb;
2580         float col[4];
2581         int color_profile = but->block->color_profile;
2582         
2583         col[3] = 1.0f;
2584
2585         if (but->rnaprop) {
2586                 if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
2587                         color_profile = FALSE;
2588
2589                 if (RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4) {
2590                         col[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
2591                 }
2592         }
2593         
2594         widget_init(&wtb);
2595         
2596         /* half rounded */
2597         round_box_edges(&wtb, roundboxalign, rect, 5.0f);
2598                 
2599         ui_get_but_vectorf(but, col);
2600
2601         if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
2602                 /* draw based on state - color for keyed etc */
2603                 widgetbase_draw(&wtb, wcol);
2604
2605                 /* inset to draw swatch color */
2606                 rect->xmin += SWATCH_KEYED_BORDER;
2607                 rect->xmax -= SWATCH_KEYED_BORDER;
2608                 rect->ymin += SWATCH_KEYED_BORDER;
2609                 rect->ymax -= SWATCH_KEYED_BORDER;
2610                 
2611                 round_box_edges(&wtb, roundboxalign, rect, 5.0f);
2612         }
2613         
2614         if (color_profile)
2615                 ui_block_to_display_space_v3(but->block, col);
2616         
2617         rgba_float_to_uchar((unsigned char *)wcol->inner, col);
2618
2619         wcol->shaded = 0;
2620         wcol->alpha_check = (wcol->inner[3] < 255);
2621
2622         widgetbase_draw(&wtb, wcol);
2623         
2624 }
2625
2626 static void widget_normal(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2627 {
2628         ui_draw_but_NORMAL(but, wcol, rect);
2629 }
2630
2631 static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2632 {
2633         if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
2634                 uiWidgetBase wtb;
2635         
2636                 widget_init(&wtb);
2637                 wtb.outline = 0;
2638                 
2639                 /* rounded */
2640                 round_box_edges(&wtb, UI_CNR_ALL, rect, 10.0f);
2641                 widgetbase_draw(&wtb, wcol);
2642         }
2643 }
2644
2645
2646 static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2647 {
2648         uiWidgetBase wtb;
2649         
2650         if (state & UI_SELECT)
2651                 SWAP(short, wcol->shadetop, wcol->shadedown);
2652         
2653         widget_init(&wtb);
2654         
2655         /* half rounded */
2656         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2657         
2658         widgetbase_draw(&wtb, wcol);
2659
2660 }
2661
2662
2663 static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2664 {
2665         uiWidgetBase wtb;
2666         
2667         widget_init(&wtb);
2668         
2669         /* half rounded */
2670         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2671         
2672         /* decoration */
2673         widget_menu_trias(&wtb.tria1, rect);
2674         
2675         widgetbase_draw(&wtb, wcol);
2676         
2677         /* text space, arrows are about 0.6 height of button */
2678         rect->xmax -= (6 * BLI_rcti_size_y(rect)) / 10;
2679 }
2680
2681 static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2682 {
2683         uiWidgetBase wtb;
2684         
2685         widget_init(&wtb);
2686         
2687         /* half rounded */
2688         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2689         
2690         /* decoration */
2691         widgetbase_draw(&wtb, wcol);
2692 }
2693
2694 static void widget_menunodebut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2695 {
2696         /* silly node link button hacks */
2697         uiWidgetBase wtb;
2698         uiWidgetColors wcol_backup = *wcol;
2699         
2700         widget_init(&wtb);
2701         
2702         /* half rounded */
2703         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2704
2705         wcol->inner[0] += 15;
2706         wcol->inner[1] += 15;
2707         wcol->inner[2] += 15;
2708         wcol->outline[0] += 15;
2709         wcol->outline[1] += 15;
2710         wcol->outline[2] += 15;
2711         
2712         /* decoration */
2713         widgetbase_draw(&wtb, wcol);
2714         *wcol = wcol_backup;
2715 }
2716
2717 static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
2718 {
2719         if (state & UI_ACTIVE) {
2720                 uiWidgetBase wtb;
2721                 float rad = 0.25f * BLI_rcti_size_y(rect);  /* 4.0f */
2722
2723                 widget_init(&wtb);
2724
2725                 /* half rounded */
2726                 round_box_edges(&wtb, roundboxalign, rect, rad);
2727                 
2728                 widgetbase_draw(&wtb, wcol);
2729         }
2730 }
2731
2732 static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2733 {
2734         uiWidgetBase wtb;
2735         
2736         widget_init(&wtb);
2737         
2738         /* not rounded, no outline */
2739         wtb.outline = 0;
2740         round_box_edges(&wtb, 0, rect, 0.0f);
2741         
2742         widgetbase_draw(&wtb, wcol);
2743 }
2744
2745 static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
2746 {
2747         uiWidgetBase wtb;
2748         
2749         widget_init(&wtb);
2750         
2751         /* rounded, but no outline */
2752         wtb.outline = 0;
2753         round_box_edges(&wtb, UI_CNR_ALL, rect, 4.0f);
2754         
2755         widgetbase_draw(&wtb, wcol);
2756 }
2757
2758 static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
2759 {
2760         uiWidgetBase wtb;
2761         rcti recttemp = *rect;
2762         int delta;
2763         
2764         widget_init(&wtb);
2765         
2766         /* square */
2767         recttemp.xmax = recttemp.xmin + BLI_rcti_size_y(&recttemp);
2768         
2769         /* smaller */
2770         delta = 1 + BLI_rcti_size_y(&recttemp) / 8;
2771         recttemp.xmin += delta;
2772         recttemp.ymin += delta;
2773         recttemp.xmax -= delta;
2774         recttemp.ymax -= delta;
2775         
2776         /* half rounded */
2777         round_box_edges(&wtb, UI_CNR_ALL, &recttemp, 4.0f);
2778         
2779         /* decoration */
2780         if (state & UI_SELECT) {
2781                 widget_check_trias(&wtb.tria1, &recttemp);
2782         }
2783         
2784         widgetbase_draw(&wtb, wcol);
2785         
2786         /* text space */
2787         rect->xmin += BLI_rcti_size_y(rect) * 0.7 + delta;
2788 }
2789
2790
2791 static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2792 {
2793         uiWidgetBase wtb;
2794         
2795         widget_init(&wtb);
2796         
2797         /* half rounded */
2798         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2799         
2800         widgetbase_draw(&wtb, wcol);
2801
2802 }
2803
2804 static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2805 {
2806         uiWidgetBase wtb;
2807         char old_col[3];
2808         
2809         widget_init(&wtb);
2810         
2811         copy_v3_v3_char(old_col, wcol->inner);
2812         
2813         /* abuse but->hsv - if it's non-zero, use this color as the box's background */
2814         if (but->col[3]) {
2815                 wcol->inner[0] = but->col[0];
2816                 wcol->inner[1] = but->col[1];
2817                 wcol->inner[2] = but->col[2];
2818         }
2819         
2820         /* half rounded */
2821         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2822         
2823         widgetbase_draw(&wtb, wcol);
2824         
2825         /* store the box bg as gl clearcolor, to retrieve later when drawing semi-transparent rects
2826          * over the top to indicate disabled buttons */
2827         /* XXX, this doesnt work right since the color applies to buttons outside the box too. */
2828         glClearColor(wcol->inner[0] / 255.0, wcol->inner[1] / 255.0, wcol->inner[2] / 255.0, 1.0);
2829         
2830         copy_v3_v3_char(wcol->inner, old_col);
2831 }
2832
2833 static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2834 {
2835         uiWidgetBase wtb;
2836         
2837         widget_init(&wtb);
2838         
2839         /* half rounded */
2840         round_box_edges(&wtb, roundboxalign, rect, 4.0f);
2841                 
2842         widgetbase_draw(&wtb, wcol);
2843
2844 }
2845
2846 static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
2847 {
2848         uiWidgetBase wtb;
2849         float rad = 5.0f;  /* 0.5f * BLI_rcti_size_y(rect); */
2850         
2851         widget_init(&wtb);
2852         
2853         /* half rounded */
2854         round_box_edges(&wtb, roundboxalign, rect, rad);
2855
2856         widgetbase_draw(&wtb, wcol);
2857 }
2858
2859 static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
2860 {
2861         uiWidgetBase wtb;
2862         unsigned char col[4];
2863         
2864         /* state copy! */
2865         wt->wcol = *(wt->wcol_theme);
2866         
2867         widget_init(&wtb);
2868         
2869         if (but->block->drawextra) {
2870                 /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
2871                 but->block->drawextra(C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect);
2872                 
2873                 /* make mask to draw over image */
2874                 UI_GetThemeColor3ubv(TH_BACK, col);
2875                 glColor3ubv(col);
2876                 
2877                 round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, 4.0);
2878                 widgetbase_outline(&wtb);
2879         }
2880         
2881         /* outline */
2882         round_box_edges(&wtb, UI_CNR_ALL, rect, 5.0f);
2883         wtb.outline = 1;
2884         wtb.inner = 0;
2885         widgetbase_draw(&wtb, &wt->wcol);
2886         
2887 }
2888
2889
2890 static void widget_disabled(rcti *rect)
2891 {
2892         float col[4];
2893         
2894         glEnable(GL_BLEND);
2895         
2896         /* can't use theme TH_BACK or TH_PANEL... undefined */
2897         glGetFloatv(GL_COLOR_CLEAR_VALUE, col);
2898         glColor4f(col[0], col[1], col[2], 0.5f);
2899
2900         /* need -1 and +1 to make it work right for aligned buttons,
2901          * but problem may be somewhere else? */
2902         glRectf(rect->xmin - 1, rect->ymin - 1, rect->xmax, rect->ymax + 1);
2903         
2904         glDisable(GL_BLEND);
2905 }
2906
2907 static uiWidgetType *widget_type(uiWidgetTypeEnum type)
2908 {
2909         bTheme *btheme = UI_GetTheme();
2910         static uiWidgetType wt;
2911         
2912         /* defaults */
2913         wt.wcol_theme = &btheme->tui.wcol_regular;
2914         wt.wcol_state = &btheme->tui.wcol_state;
2915         wt.state = widget_state;
2916         wt.draw = widget_but;
2917         wt.custom = NULL;
2918         wt.text = widget_draw_text_icon;
2919         
2920         switch (type) {
2921                 case UI_WTYPE_REGULAR:
2922                         break;
2923
2924                 case UI_WTYPE_LABEL:
2925                         wt.draw = NULL;
2926                         wt.state = widget_state_label;
2927                         break;
2928                         
2929                 case UI_WTYPE_TOGGLE:
2930                         wt.wcol_theme = &btheme->tui.wcol_toggle;
2931                         break;
2932                         
2933                 case UI_WTYPE_OPTION:
2934                         wt.wcol_theme = &btheme->tui.wcol_option;
2935                         wt.draw = widget_optionbut;
2936                         break;
2937                         
2938                 case UI_WTYPE_RADIO:
2939                         wt.wcol_theme = &btheme->tui.wcol_radio;
2940                         wt.draw = widget_radiobut;
2941                         break;
2942
2943                 case UI_WTYPE_NUMBER:
2944                         wt.wcol_theme = &btheme->tui.wcol_num;
2945                         wt.draw = widget_numbut;
2946                         break;
2947                         
2948                 case UI_WTYPE_SLIDER:
2949                         wt.wcol_theme = &btheme->tui.wcol_numslider;
2950                         wt.custom = widget_numslider;
2951                         wt.state = widget_state_numslider;
2952                         break;
2953                         
2954                 case UI_WTYPE_EXEC:
2955                         wt.wcol_theme = &btheme->tui.wcol_tool;
2956                         wt.draw = widget_roundbut;
2957                         break;
2958
2959                 case UI_WTYPE_TOOLTIP:
2960                         wt.wcol_theme = &btheme->tui.wcol_tooltip;
2961                         wt.draw = widget_menu_back;
2962                         break;
2963                         
2964                         
2965                 /* strings */
2966                 case UI_WTYPE_NAME:
2967                         wt.wcol_theme = &btheme->tui.wcol_text;
2968                         wt.draw = widget_textbut;
2969                         break;
2970                         
2971                 case UI_WTYPE_NAME_LINK:
2972                         break;
2973                         
2974                 case UI_WTYPE_POINTER_LINK:
2975                         break;
2976                         
2977                 case UI_WTYPE_FILENAME:
2978                         break;
2979                         
2980                         
2981                 /* start menus */
2982                 case UI_WTYPE_MENU_RADIO:
2983                         wt.wcol_theme = &btheme->tui.wcol_menu;
2984                         wt.draw = widget_menubut;
2985                         break;
2986
2987                 case UI_WTYPE_MENU_ICON_RADIO:
2988                         wt.wcol_theme = &btheme->tui.wcol_menu;
2989                         wt.draw = widget_menuiconbut;
2990                         break;
2991                         
2992                 case UI_WTYPE_MENU_POINTER_LINK:
2993                         wt.wcol_theme = &btheme->tui.wcol_menu;
2994                         wt.draw = widget_menubut;
2995                         break;
2996
2997                 case UI_WTYPE_MENU_NODE_LINK:
2998                         wt.wcol_theme = &btheme->tui.wcol_menu;
2999                         wt.draw = widget_menunodebut;
3000                         break;
3001                         
3002                 case UI_WTYPE_PULLDOWN:
3003                         wt.wcol_theme = &btheme->tui.wcol_pulldown;
3004                         wt.draw = widget_pulldownbut;
3005                         wt.state = widget_state_pulldown;
3006                         break;
3007                         
3008                 /* in menus */
3009                 case UI_WTYPE_MENU_ITEM:
3010                         wt.wcol_theme = &btheme->tui.wcol_menu_item;
3011                         wt.draw = widget_menu_itembut;
3012                         wt.state = widget_state_menu_item;
3013                         break;
3014                         
3015                 case UI_WTYPE_MENU_BACK:
3016                         wt.wcol_theme = &btheme->tui.wcol_menu_back;
3017                         wt.draw = widget_menu_back;
3018                         break;
3019                         
3020                 /* specials */
3021                 case UI_WTYPE_ICON:
3022                         wt.custom = widget_icon_has_anim;
3023                         break;
3024                         
3025                 case UI_WTYPE_SWATCH:
3026                         wt.custom = widget_swatch;
3027                         break;
3028                         
3029                 case UI_WTYPE_BOX:
3030                         wt.custom = widget_box;
3031                         wt.wcol_theme = &btheme->tui.wcol_box;
3032                         break;
3033                         
3034                 case UI_WTYPE_RGB_PICKER:
3035                         break;
3036                         
3037                 case UI_WTYPE_NORMAL:
3038                         wt.custom = widget_normal;
3039                         break;
3040
3041                 case UI_WTYPE_SCROLL:
3042                         wt.wcol_theme = &btheme->tui.wcol_scroll;
3043                         wt.state = widget_state_nothing;
3044                         wt.custom = widget_scroll;
3045                         break;
3046
3047                 case UI_WTYPE_LISTITEM:
3048                         wt.wcol_theme = &btheme->tui.wcol_list_item;
3049                         wt.draw = widget_list_itembut;
3050                         break;
3051                         
3052                 case UI_WTYPE_PROGRESSBAR:
3053                         wt.wcol_theme = &btheme->tui.wcol_progress;
3054                         wt.custom = widget_progressbar;
3055                         break;
3056         }
3057         
3058         return &wt;
3059 }
3060
3061
3062 static int widget_roundbox_set(uiBut *but, rcti *rect)
3063 {
3064         int roundbox = UI_CNR_ALL;
3065
3066         /* alignment */
3067         if ((but->flag & UI_BUT_ALIGN) && but->type != PULLDOWN) {
3068                 
3069                 /* ui_block_position has this correction too, keep in sync */
3070                 if (but->flag & UI_BUT_ALIGN_TOP)
3071                         rect->ymax += 1;
3072                 if (but->flag & UI_BUT_ALIGN_LEFT)
3073                         rect->xmin -= 1;
3074                 
3075                 switch (but->flag & UI_BUT_ALIGN) {
3076                         case UI_BUT_ALIGN_TOP:
3077                                 roundbox = UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT;
3078                                 break;
3079                         case UI_BUT_ALIGN_DOWN:
3080                                 roundbox = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
3081                                 break;
3082                         case UI_BUT_ALIGN_LEFT:
3083                                 roundbox = UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT;
3084                                 break;
3085                         case UI_BUT_ALIGN_RIGHT:
3086                                 roundbox = UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT;
3087                                 break;
3088                         case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_RIGHT:
3089                                 roundbox = UI_CNR_TOP_LEFT;
3090                                 break;
3091                         case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT:
3092                                 roundbox = UI_CNR_TOP_RIGHT;
3093                                 break;
3094                         case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT:
3095                                 roundbox = UI_CNR_BOTTOM_LEFT;
3096                                 break;
3097                         case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT:
3098                                 roundbox = UI_CNR_BOTTOM_RIGHT;
3099                                 break;
3100                         default:
3101                                 roundbox = 0;
3102                                 break;
3103                 }
3104         }
3105
3106         /* align with open menu */
3107         if (but->active) {
3108                 int direction = ui_button_open_menu_direction(but);
3109
3110                 if      (direction == UI_TOP)   roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_TOP_LEFT);
3111                 else if (direction == UI_DOWN)  roundbox &= ~(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
3112                 else if (direction == UI_LEFT)  roundbox &= ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
3113                 else if (direction == UI_RIGHT) roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
3114         }
3115
3116         return roundbox;
3117 }
3118
3119 /* conversion from old to new buttons, so still messy */
3120 void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
3121 {
3122         bTheme *btheme = UI_GetTheme();
3123         ThemeUI *tui = &btheme->tui;
3124         uiFontStyle *fstyle = &style->widget;
3125         uiWidgetType *wt = NULL;
3126
3127         /* handle menus separately */
3128         if (but->dt == UI_EMBOSSP) {
3129                 switch (but->type) {
3130                         case LABEL:
3131                                 widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
3132                                 break;
3133                         case SEPR:
3134                                 ui_draw_separator(rect, &tui->wcol_menu_item);
3135                                 break;
3136                                 
3137                         default:
3138                                 wt = widget_type(UI_WTYPE_MENU_ITEM);
3139                 }
3140         }
3141         else if (but->dt == UI_EMBOSSN) {
3142                 /* "nothing" */
3143                 wt = widget_type(UI_WTYPE_ICON);
3144         }
3145         else {
3146                 
3147                 switch (but->type) {
3148                         case LABEL:
3149                                 if (but->block->flag & UI_BLOCK_LOOP)
3150                                         widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
3151                                 else {
3152                                         wt = widget_type(UI_WTYPE_LABEL);