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