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