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