Blender V2.61 - r43446

interface_widgets.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2009 Blender Foundation.
00019  * All rights reserved.
00020  * 
00021  * Contributor(s): Blender Foundation
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include <limits.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <assert.h>
00035 
00036 
00037 #include "DNA_screen_types.h"
00038 #include "DNA_userdef_types.h"
00039 
00040 #include "BLI_math.h"
00041 #include "BLI_listbase.h"
00042 #include "BLI_rect.h"
00043 #include "BLI_string.h"
00044 #include "BLI_utildefines.h"
00045 
00046 #include "BKE_context.h"
00047 #include "BKE_curve.h"
00048 #include "BKE_utildefines.h"
00049 
00050 #include "RNA_access.h"
00051 
00052 #include "BIF_gl.h"
00053 #include "BIF_glutil.h"
00054 
00055 #include "BLF_api.h"
00056 
00057 #include "UI_interface.h"
00058 #include "UI_interface_icons.h"
00059 
00060 
00061 #include "interface_intern.h"
00062 
00063 /* ************** widget base functions ************** */
00064 /*
00065      - in: roundbox codes for corner types and radius
00066      - return: array of [size][2][x,y] points, the edges of the roundbox, + UV coords
00067  
00068      - draw black box with alpha 0 on exact button boundbox
00069      - for ever AA step:
00070         - draw the inner part for a round filled box, with color blend codes or texture coords
00071         - draw outline in outline color
00072         - draw outer part, bottom half, extruded 1 pixel to bottom, for emboss shadow
00073         - draw extra decorations
00074      - draw background color box with alpha 1 on exact button boundbox
00075  
00076  */
00077 
00078 /* fill this struct with polygon info to draw AA'ed */
00079 /* it has outline, back, and two optional tria meshes */
00080 
00081 typedef struct uiWidgetTrias {
00082     unsigned int tot;
00083     
00084     float vec[32][2];
00085     unsigned int (*index)[3];
00086     
00087 } uiWidgetTrias;
00088 
00089 /* max as used by round_box__edges */
00090 #define WIDGET_CURVE_RESOLU 9
00091 #define WIDGET_SIZE_MAX (WIDGET_CURVE_RESOLU*4)
00092 
00093 typedef struct uiWidgetBase {
00094     
00095     int totvert, halfwayvert;
00096     float outer_v[WIDGET_SIZE_MAX][2];
00097     float inner_v[WIDGET_SIZE_MAX][2];
00098     float inner_uv[WIDGET_SIZE_MAX][2];
00099     
00100     short inner, outline, emboss; /* set on/off */
00101     short shadedir;
00102     
00103     uiWidgetTrias tria1;
00104     uiWidgetTrias tria2;
00105     
00106 } uiWidgetBase;
00107 
00108 /* uiWidgetType: for time being only for visual appearance,
00109    later, a handling callback can be added too 
00110 */
00111 typedef struct uiWidgetType {
00112     
00113     /* pointer to theme color definition */
00114     uiWidgetColors *wcol_theme;
00115     uiWidgetStateColors *wcol_state;
00116     
00117     /* converted colors for state */
00118     uiWidgetColors wcol;
00119     
00120     void (*state)(struct uiWidgetType *, int state);
00121     void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign);
00122     void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign);
00123     void (*text)(uiFontStyle *, uiWidgetColors *, uiBut *, rcti *);
00124     
00125 } uiWidgetType;
00126 
00127 
00128 /* *********************** draw data ************************** */
00129 
00130 static float cornervec[WIDGET_CURVE_RESOLU][2]= {{0.0, 0.0}, {0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169},
00131 {0.707, 0.293}, {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}, {1.0, 1.0}};
00132 
00133 #define WIDGET_AA_JITTER 8
00134 static float jit[WIDGET_AA_JITTER][2]= {
00135     { 0.468813 , -0.481430}, {-0.155755 , -0.352820},
00136     { 0.219306 , -0.238501}, {-0.393286 , -0.110949},
00137     {-0.024699 ,  0.013908}, { 0.343805 ,  0.147431},
00138     {-0.272855 ,  0.269918}, { 0.095909 ,  0.388710}};
00139 
00140 static float num_tria_vert[3][2]= { 
00141 {-0.352077, 0.532607}, {-0.352077, -0.549313}, {0.330000, -0.008353}};
00142 
00143 static unsigned int num_tria_face[1][3]= {
00144 {0, 1, 2}};
00145 
00146 static float scroll_circle_vert[16][2]= {
00147 {0.382684, 0.923879}, {0.000001, 1.000000}, {-0.382683, 0.923880}, {-0.707107, 0.707107},
00148 {-0.923879, 0.382684}, {-1.000000, 0.000000}, {-0.923880, -0.382684}, {-0.707107, -0.707107},
00149 {-0.382683, -0.923880}, {0.000000, -1.000000}, {0.382684, -0.923880}, {0.707107, -0.707107},
00150 {0.923880, -0.382684}, {1.000000, -0.000000}, {0.923880, 0.382683}, {0.707107, 0.707107}};
00151 
00152 static unsigned int scroll_circle_face[14][3]= {
00153 {0, 1, 2}, {2, 0, 3}, {3, 0, 15}, {3, 15, 4}, {4, 15, 14}, {4, 14, 5}, {5, 14, 13}, {5, 13, 6}, 
00154 {6, 13, 12}, {6, 12, 7}, {7, 12, 11}, {7, 11, 8}, {8, 11, 10}, {8, 10, 9}};
00155 
00156 static float menu_tria_vert[6][2]= {
00157 {-0.41, 0.16}, {0.41, 0.16}, {0, 0.82}, 
00158 {0, -0.82}, {-0.41, -0.16}, {0.41, -0.16}};
00159 
00160 static unsigned int menu_tria_face[2][3]= {{2, 0, 1}, {3, 5, 4}};
00161 
00162 static float check_tria_vert[6][2]= {
00163 {-0.578579, 0.253369},  {-0.392773, 0.412794},  {-0.004241, -0.328551}, 
00164 {-0.003001, 0.034320},  {1.055313, 0.864744},   {0.866408, 1.026895}};
00165 
00166 static unsigned int check_tria_face[4][3]= {
00167 {3, 2, 4}, {3, 4, 5}, {1, 0, 3}, {0, 2, 3}};
00168 
00169 GLubyte checker_stipple_sml[32*32/8] =
00170 {
00171     255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,
00172     255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,
00173     0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,
00174     0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,
00175     255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,
00176     255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,
00177     0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,
00178     0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,
00179 };
00180 
00181 /* ************************************************* */
00182 
00183 void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3)
00184 {
00185     float tri_arr[3][2]= {{x1, y1}, {x2, y2}, {x3, y3}};
00186     float color[4];
00187     int j;
00188     
00189     glEnable(GL_BLEND);
00190     glGetFloatv(GL_CURRENT_COLOR, color);
00191     color[3] *= 0.125f;
00192     glColor4fv(color);
00193 
00194     glEnableClientState(GL_VERTEX_ARRAY);
00195     glVertexPointer(2, GL_FLOAT, 0, tri_arr);
00196 
00197     /* for each AA step */
00198     for (j = 0; j < WIDGET_AA_JITTER; j++) {
00199         glTranslatef(1.0f * jit[j][0], 1.0f * jit[j][1], 0.0f);
00200         glDrawArrays(GL_TRIANGLES, 0, 3);
00201         glTranslatef(-1.0f * jit[j][0], -1.0f * jit[j][1], 0.0f);
00202     }
00203 
00204     glDisableClientState(GL_VERTEX_ARRAY);
00205     glDisable(GL_BLEND);
00206 }
00207 
00208 void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad)
00209 {
00210     float color[4];
00211     int j;
00212     
00213     glEnable(GL_BLEND);
00214     glGetFloatv(GL_CURRENT_COLOR, color);
00215     color[3] *= 0.125f;
00216     glColor4fv(color);
00217     
00218     for (j = 0;  j < WIDGET_AA_JITTER; j++) {
00219         glTranslatef(1.0f * jit[j][0], 1.0f * jit[j][1], 0.0f);
00220         uiDrawBox(mode, minx, miny, maxx, maxy, rad);
00221         glTranslatef(-1.0f * jit[j][0], -1.0f * jit[j][1], 0.0f);
00222     }
00223 
00224     glDisable(GL_BLEND);
00225 }
00226 
00227 static void widget_init(uiWidgetBase *wtb)
00228 {
00229     wtb->totvert= wtb->halfwayvert= 0;
00230     wtb->tria1.tot= 0;
00231     wtb->tria2.tot= 0;
00232     
00233     wtb->inner= 1;
00234     wtb->outline= 1;
00235     wtb->emboss= 1;
00236     wtb->shadedir= 1;
00237 }
00238 
00239 /* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
00240 /* return tot */
00241 static int round_box_shadow_edges(float (*vert)[2], rcti *rect, float rad, int roundboxalign, float step)
00242 {
00243     float vec[WIDGET_CURVE_RESOLU][2];
00244     float minx, miny, maxx, maxy;
00245     int a, tot= 0;
00246     
00247     rad+= step;
00248     
00249     if(2.0f*rad > rect->ymax-rect->ymin)
00250         rad= 0.5f*(rect->ymax-rect->ymin);
00251     
00252     minx= rect->xmin-step;
00253     miny= rect->ymin-step;
00254     maxx= rect->xmax+step;
00255     maxy= rect->ymax+step;
00256     
00257     /* mult */
00258     for(a=0; a < WIDGET_CURVE_RESOLU; a++) {
00259         vec[a][0]= rad*cornervec[a][0]; 
00260         vec[a][1]= rad*cornervec[a][1]; 
00261     }
00262     
00263     /* start with left-top, anti clockwise */
00264     if(roundboxalign & UI_CNR_TOP_LEFT) {
00265         for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
00266             vert[tot][0]= minx+rad-vec[a][0];
00267             vert[tot][1]= maxy-vec[a][1];
00268         }
00269     }
00270     else {
00271         for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
00272             vert[tot][0]= minx;
00273             vert[tot][1]= maxy;
00274         }
00275     }
00276     
00277     if(roundboxalign & UI_CNR_BOTTOM_LEFT) {
00278         for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
00279             vert[tot][0]= minx+vec[a][1];
00280             vert[tot][1]= miny+rad-vec[a][0];
00281         }
00282     }
00283     else {
00284         for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
00285             vert[tot][0]= minx;
00286             vert[tot][1]= miny;
00287         }
00288     }
00289     
00290     if(roundboxalign & UI_CNR_BOTTOM_RIGHT) {
00291         for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
00292             vert[tot][0]= maxx-rad+vec[a][0];
00293             vert[tot][1]= miny+vec[a][1];
00294         }
00295     }
00296     else {
00297         for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
00298             vert[tot][0]= maxx;
00299             vert[tot][1]= miny;
00300         }
00301     }
00302     
00303     if(roundboxalign & UI_CNR_TOP_RIGHT) {
00304         for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
00305             vert[tot][0]= maxx-vec[a][1];
00306             vert[tot][1]= maxy-rad+vec[a][0];
00307         }
00308     }
00309     else {
00310         for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
00311             vert[tot][0]= maxx;
00312             vert[tot][1]= maxy;
00313         }
00314     }
00315     return tot;
00316 }
00317 
00318 /* this call has 1 extra arg to allow mask outline */
00319 static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, float rad, float radi)
00320 {
00321     float vec[WIDGET_CURVE_RESOLU][2], veci[WIDGET_CURVE_RESOLU][2];
00322     float minx= rect->xmin, miny= rect->ymin, maxx= rect->xmax, maxy= rect->ymax;
00323     float minxi= minx + 1.0f; /* boundbox inner */
00324     float maxxi= maxx - 1.0f;
00325     float minyi= miny + 1.0f;
00326     float maxyi= maxy - 1.0f;
00327     float facxi= (maxxi!=minxi) ? 1.0f/(maxxi-minxi) : 0.0f; /* for uv, can divide by zero */
00328     float facyi= (maxyi!=minyi) ? 1.0f/(maxyi-minyi) : 0.0f;
00329     int a, tot= 0, minsize;
00330     const int hnum= ((roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT))==(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT) ||
00331                      (roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT))==(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT)) ? 1 : 2;
00332     const int vnum= ((roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT))==(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT) ||
00333                      (roundboxalign & (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT))==(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) ? 1 : 2;
00334 
00335     minsize= MIN2((rect->xmax-rect->xmin)*hnum, (rect->ymax-rect->ymin)*vnum);
00336     
00337     if(2.0f*rad > minsize)
00338         rad= 0.5f*minsize;
00339 
00340     if(2.0f*(radi+1.0f) > minsize)
00341         radi= 0.5f*minsize - 1.0f;
00342     
00343     /* mult */
00344     for(a=0; a < WIDGET_CURVE_RESOLU; a++) {
00345         veci[a][0]= radi*cornervec[a][0]; 
00346         veci[a][1]= radi*cornervec[a][1]; 
00347         vec[a][0]= rad*cornervec[a][0]; 
00348         vec[a][1]= rad*cornervec[a][1]; 
00349     }
00350     
00351     /* corner left-bottom */
00352     if(roundboxalign & UI_CNR_BOTTOM_LEFT) {
00353         
00354         for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
00355             wt->inner_v[tot][0]= minxi+veci[a][1];
00356             wt->inner_v[tot][1]= minyi+radi-veci[a][0];
00357             
00358             wt->outer_v[tot][0]= minx+vec[a][1];
00359             wt->outer_v[tot][1]= miny+rad-vec[a][0];
00360             
00361             wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
00362             wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
00363         }
00364     }
00365     else {
00366         wt->inner_v[tot][0]= minxi;
00367         wt->inner_v[tot][1]= minyi;
00368         
00369         wt->outer_v[tot][0]= minx;
00370         wt->outer_v[tot][1]= miny;
00371 
00372         wt->inner_uv[tot][0]= 0.0f;
00373         wt->inner_uv[tot][1]= 0.0f;
00374         
00375         tot++;
00376     }
00377     
00378     /* corner right-bottom */
00379     if(roundboxalign & UI_CNR_BOTTOM_RIGHT) {
00380         
00381         for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
00382             wt->inner_v[tot][0]= maxxi-radi+veci[a][0];
00383             wt->inner_v[tot][1]= minyi+veci[a][1];
00384             
00385             wt->outer_v[tot][0]= maxx-rad+vec[a][0];
00386             wt->outer_v[tot][1]= miny+vec[a][1];
00387             
00388             wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
00389             wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
00390         }
00391     }
00392     else {
00393         wt->inner_v[tot][0]= maxxi;
00394         wt->inner_v[tot][1]= minyi;
00395         
00396         wt->outer_v[tot][0]= maxx;
00397         wt->outer_v[tot][1]= miny;
00398 
00399         wt->inner_uv[tot][0]= 1.0f;
00400         wt->inner_uv[tot][1]= 0.0f;
00401         
00402         tot++;
00403     }
00404     
00405     wt->halfwayvert= tot;
00406     
00407     /* corner right-top */
00408     if(roundboxalign & UI_CNR_TOP_RIGHT) {
00409         
00410         for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
00411             wt->inner_v[tot][0]= maxxi-veci[a][1];
00412             wt->inner_v[tot][1]= maxyi-radi+veci[a][0];
00413             
00414             wt->outer_v[tot][0]= maxx-vec[a][1];
00415             wt->outer_v[tot][1]= maxy-rad+vec[a][0];
00416             
00417             wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
00418             wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
00419         }
00420     }
00421     else {
00422         wt->inner_v[tot][0]= maxxi;
00423         wt->inner_v[tot][1]= maxyi;
00424         
00425         wt->outer_v[tot][0]= maxx;
00426         wt->outer_v[tot][1]= maxy;
00427         
00428         wt->inner_uv[tot][0]= 1.0f;
00429         wt->inner_uv[tot][1]= 1.0f;
00430         
00431         tot++;
00432     }
00433     
00434     /* corner left-top */
00435     if(roundboxalign & UI_CNR_TOP_LEFT) {
00436         
00437         for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
00438             wt->inner_v[tot][0]= minxi+radi-veci[a][0];
00439             wt->inner_v[tot][1]= maxyi-veci[a][1];
00440             
00441             wt->outer_v[tot][0]= minx+rad-vec[a][0];
00442             wt->outer_v[tot][1]= maxy-vec[a][1];
00443             
00444             wt->inner_uv[tot][0]= facxi*(wt->inner_v[tot][0] - minxi);
00445             wt->inner_uv[tot][1]= facyi*(wt->inner_v[tot][1] - minyi);
00446         }
00447         
00448     }
00449     else {
00450         
00451         wt->inner_v[tot][0]= minxi;
00452         wt->inner_v[tot][1]= maxyi;
00453         
00454         wt->outer_v[tot][0]= minx;
00455         wt->outer_v[tot][1]= maxy;
00456         
00457         wt->inner_uv[tot][0]= 0.0f;
00458         wt->inner_uv[tot][1]= 1.0f;
00459         
00460         tot++;
00461     }
00462 
00463     BLI_assert(tot <= WIDGET_SIZE_MAX);
00464 
00465     wt->totvert= tot;
00466 }
00467 
00468 static void round_box_edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, float rad)
00469 {
00470     round_box__edges(wt, roundboxalign, rect, rad, rad-1.0f);
00471 }
00472 
00473 
00474 /* based on button rect, return scaled array of triangles */
00475 static void widget_num_tria(uiWidgetTrias *tria, rcti *rect, float triasize, char where)
00476 {
00477     float centx, centy, sizex, sizey, minsize;
00478     int a, i1=0, i2=1;
00479     
00480     minsize= MIN2(rect->xmax-rect->xmin, rect->ymax-rect->ymin);
00481     
00482     /* center position and size */
00483     centx= (float)rect->xmin + 0.5f*minsize;
00484     centy= (float)rect->ymin + 0.5f*minsize;
00485     sizex= sizey= -0.5f*triasize*minsize;
00486 
00487     if(where=='r') {
00488         centx= (float)rect->xmax - 0.5f*minsize;
00489         sizex= -sizex;
00490     }   
00491     else if(where=='t') {
00492         centy= (float)rect->ymax - 0.5f*minsize;
00493         sizey= -sizey;
00494         i2=0; i1= 1;
00495     }   
00496     else if(where=='b') {
00497         sizex= -sizex;
00498         i2=0; i1= 1;
00499     }   
00500     
00501     for(a=0; a<3; a++) {
00502         tria->vec[a][0]= sizex*num_tria_vert[a][i1] + centx;
00503         tria->vec[a][1]= sizey*num_tria_vert[a][i2] + centy;
00504     }
00505     
00506     tria->tot= 1;
00507     tria->index= num_tria_face;
00508 }
00509 
00510 static void widget_scroll_circle(uiWidgetTrias *tria, rcti *rect, float triasize, char where)
00511 {
00512     float centx, centy, sizex, sizey, minsize;
00513     int a, i1=0, i2=1;
00514     
00515     minsize= MIN2(rect->xmax-rect->xmin, rect->ymax-rect->ymin);
00516     
00517     /* center position and size */
00518     centx= (float)rect->xmin + 0.5f*minsize;
00519     centy= (float)rect->ymin + 0.5f*minsize;
00520     sizex= sizey= -0.5f*triasize*minsize;
00521 
00522     if(where=='r') {
00523         centx= (float)rect->xmax - 0.5f*minsize;
00524         sizex= -sizex;
00525     }   
00526     else if(where=='t') {
00527         centy= (float)rect->ymax - 0.5f*minsize;
00528         sizey= -sizey;
00529         i2=0; i1= 1;
00530     }   
00531     else if(where=='b') {
00532         sizex= -sizex;
00533         i2=0; i1= 1;
00534     }   
00535     
00536     for(a=0; a<16; a++) {
00537         tria->vec[a][0]= sizex*scroll_circle_vert[a][i1] + centx;
00538         tria->vec[a][1]= sizey*scroll_circle_vert[a][i2] + centy;
00539     }
00540     
00541     tria->tot= 14;
00542     tria->index= scroll_circle_face;
00543 }
00544 
00545 static void widget_trias_draw(uiWidgetTrias *tria)
00546 {
00547     glEnableClientState(GL_VERTEX_ARRAY);
00548     glVertexPointer(2, GL_FLOAT, 0, tria->vec);
00549     glDrawElements(GL_TRIANGLES, tria->tot*3, GL_UNSIGNED_INT, tria->index);
00550     glDisableClientState(GL_VERTEX_ARRAY);
00551 }
00552 
00553 static void widget_menu_trias(uiWidgetTrias *tria, rcti *rect)
00554 {
00555     float centx, centy, size, asp;
00556     int a;
00557         
00558     /* center position and size */
00559     centx= rect->xmax - 0.5f*(rect->ymax-rect->ymin);
00560     centy= rect->ymin + 0.5f*(rect->ymax-rect->ymin);
00561     size= 0.4f*(rect->ymax-rect->ymin);
00562     
00563     /* XXX exception */
00564     asp= ((float)rect->xmax-rect->xmin)/((float)rect->ymax-rect->ymin);
00565     if(asp > 1.2f && asp < 2.6f)
00566         centx= rect->xmax - 0.3f*(rect->ymax-rect->ymin);
00567     
00568     for(a=0; a<6; a++) {
00569         tria->vec[a][0]= size*menu_tria_vert[a][0] + centx;
00570         tria->vec[a][1]= size*menu_tria_vert[a][1] + centy;
00571     }
00572 
00573     tria->tot= 2;
00574     tria->index= menu_tria_face;
00575 }
00576 
00577 static void widget_check_trias(uiWidgetTrias *tria, rcti *rect)
00578 {
00579     float centx, centy, size;
00580     int a;
00581     
00582     /* center position and size */
00583     centx= rect->xmin + 0.5f*(rect->ymax-rect->ymin);
00584     centy= rect->ymin + 0.5f*(rect->ymax-rect->ymin);
00585     size= 0.5f*(rect->ymax-rect->ymin);
00586     
00587     for(a=0; a<6; a++) {
00588         tria->vec[a][0]= size*check_tria_vert[a][0] + centx;
00589         tria->vec[a][1]= size*check_tria_vert[a][1] + centy;
00590     }
00591     
00592     tria->tot= 4;
00593     tria->index= check_tria_face;
00594 }
00595 
00596 
00597 /* prepares shade colors */
00598 static void shadecolors4(char coltop[4], char *coldown, const char *color, short shadetop, short shadedown)
00599 {
00600     
00601     coltop[0]= CLAMPIS(color[0]+shadetop, 0, 255);
00602     coltop[1]= CLAMPIS(color[1]+shadetop, 0, 255);
00603     coltop[2]= CLAMPIS(color[2]+shadetop, 0, 255);
00604     coltop[3]= color[3];
00605 
00606     coldown[0]= CLAMPIS(color[0]+shadedown, 0, 255);
00607     coldown[1]= CLAMPIS(color[1]+shadedown, 0, 255);
00608     coldown[2]= CLAMPIS(color[2]+shadedown, 0, 255);
00609     coldown[3]= color[3];   
00610 }
00611 
00612 static void round_box_shade_col4_r(unsigned char col_r[4], const char col1[4], const char col2[4], const float fac)
00613 {
00614     const int faci= FTOCHAR(fac);
00615     const int facm= 255-faci;
00616 
00617     col_r[0]= (faci*col1[0] + facm*col2[0])>>8;
00618     col_r[1]= (faci*col1[1] + facm*col2[1])>>8;
00619     col_r[2]= (faci*col1[2] + facm*col2[2])>>8;
00620     col_r[3]= (faci*col1[3] + facm*col2[3])>>8;
00621 }
00622 
00623 static void widget_verts_to_quad_strip(uiWidgetBase *wtb, const int totvert, float quad_strip[WIDGET_SIZE_MAX*2+2][2])
00624 {
00625     int a;
00626     for(a=0; a<totvert; a++) {
00627         copy_v2_v2(quad_strip[a*2], wtb->outer_v[a]);
00628         copy_v2_v2(quad_strip[a*2+1], wtb->inner_v[a]);
00629     }
00630     copy_v2_v2(quad_strip[a*2], wtb->outer_v[0]);
00631     copy_v2_v2(quad_strip[a*2+1], wtb->inner_v[0]);
00632 }
00633 
00634 static void widget_verts_to_quad_strip_open(uiWidgetBase *wtb, const int totvert, float quad_strip[WIDGET_SIZE_MAX*2][2])
00635 {
00636     int a;
00637     for(a=0; a<totvert; a++) {
00638         quad_strip[a*2][0]= wtb->outer_v[a][0];
00639         quad_strip[a*2][1]= wtb->outer_v[a][1];
00640         quad_strip[a*2+1][0]= wtb->outer_v[a][0];
00641         quad_strip[a*2+1][1]= wtb->outer_v[a][1] - 1.0f;
00642     }
00643 }
00644 
00645 static void widgetbase_outline(uiWidgetBase *wtb)
00646 {
00647     float quad_strip[WIDGET_SIZE_MAX*2+2][2]; /* + 2 because the last pair is wrapped */
00648     widget_verts_to_quad_strip(wtb, wtb->totvert, quad_strip);
00649 
00650     glEnableClientState(GL_VERTEX_ARRAY);
00651     glVertexPointer(2, GL_FLOAT, 0, quad_strip);
00652     glDrawArrays(GL_QUAD_STRIP, 0, wtb->totvert*2 + 2);
00653     glDisableClientState(GL_VERTEX_ARRAY);
00654 }
00655 
00656 static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
00657 {
00658     int j, a;
00659     
00660     glEnable(GL_BLEND);
00661 
00662     /* backdrop non AA */
00663     if(wtb->inner) {
00664         if(wcol->shaded==0) {
00665             if (wcol->alpha_check) {
00666                 float inner_v_half[WIDGET_SIZE_MAX][2];
00667                 float x_mid= 0.0f; /* used for dumb clamping of values */
00668 
00669                 /* dark checkers */
00670                 glColor4ub(UI_TRANSP_DARK, UI_TRANSP_DARK, UI_TRANSP_DARK, 255);
00671                 glEnableClientState(GL_VERTEX_ARRAY);
00672                 glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
00673                 glDrawArrays(GL_POLYGON, 0, wtb->totvert);
00674                 glDisableClientState(GL_VERTEX_ARRAY);
00675 
00676                 /* light checkers */
00677                 glEnable(GL_POLYGON_STIPPLE);
00678                 glColor4ub(UI_TRANSP_LIGHT, UI_TRANSP_LIGHT, UI_TRANSP_LIGHT, 255);
00679                 glPolygonStipple(checker_stipple_sml);
00680 
00681                 glEnableClientState(GL_VERTEX_ARRAY);
00682                 glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
00683                 glDrawArrays(GL_POLYGON, 0, wtb->totvert);
00684                 glDisableClientState(GL_VERTEX_ARRAY);
00685 
00686                 glDisable(GL_POLYGON_STIPPLE);
00687 
00688                 /* alpha fill */
00689                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00690 
00691                 glColor4ubv((unsigned char*)wcol->inner);
00692                 glEnableClientState(GL_VERTEX_ARRAY);
00693 
00694                 for(a=0; a<wtb->totvert; a++) {
00695                     x_mid += wtb->inner_v[a][0];
00696                 }
00697                 x_mid /= wtb->totvert;
00698 
00699                 glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
00700                 glDrawArrays(GL_POLYGON, 0, wtb->totvert);
00701                 glDisableClientState(GL_VERTEX_ARRAY);
00702 
00703                 /* 1/2 solid color */
00704                 glColor4ub(wcol->inner[0], wcol->inner[1], wcol->inner[2], 255);
00705 
00706                 for(a=0; a<wtb->totvert; a++) {
00707                     inner_v_half[a][0]= MIN2(wtb->inner_v[a][0], x_mid);
00708                     inner_v_half[a][1]= wtb->inner_v[a][1];
00709                 }
00710 
00711                 glEnableClientState(GL_VERTEX_ARRAY);
00712                 glVertexPointer(2, GL_FLOAT, 0, inner_v_half);
00713                 glDrawArrays(GL_POLYGON, 0, wtb->totvert);
00714                 glDisableClientState(GL_VERTEX_ARRAY);
00715             }
00716             else {
00717                 /* simple fill */
00718                 glColor4ubv((unsigned char*)wcol->inner);
00719 
00720                 glEnableClientState(GL_VERTEX_ARRAY);
00721                 glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
00722                 glDrawArrays(GL_POLYGON, 0, wtb->totvert);
00723                 glDisableClientState(GL_VERTEX_ARRAY);
00724             }
00725         }
00726         else {
00727             char col1[4], col2[4];
00728             unsigned char col_array[WIDGET_SIZE_MAX * 4];
00729             unsigned char *col_pt= col_array;
00730             
00731             shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown);
00732             
00733             glShadeModel(GL_SMOOTH);
00734             for(a=0; a<wtb->totvert; a++, col_pt += 4) {
00735                 round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->shadedir]);
00736             }
00737 
00738             glEnableClientState(GL_VERTEX_ARRAY);
00739             glEnableClientState(GL_COLOR_ARRAY);
00740             glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
00741             glColorPointer(4, GL_UNSIGNED_BYTE, 0, col_array);
00742             glDrawArrays(GL_POLYGON, 0, wtb->totvert);
00743             glDisableClientState(GL_VERTEX_ARRAY);
00744             glDisableClientState(GL_COLOR_ARRAY);
00745 
00746             glShadeModel(GL_FLAT);
00747         }
00748     }
00749     
00750     /* for each AA step */
00751     if(wtb->outline) {
00752         float quad_strip[WIDGET_SIZE_MAX*2+2][2]; /* + 2 because the last pair is wrapped */
00753         float quad_strip_emboss[WIDGET_SIZE_MAX*2][2]; /* only for emboss */
00754 
00755         const unsigned char tcol[4] = {wcol->outline[0],
00756                                        wcol->outline[1],
00757                                        wcol->outline[2],
00758                                        UCHAR_MAX / WIDGET_AA_JITTER};
00759 
00760         widget_verts_to_quad_strip(wtb, wtb->totvert, quad_strip);
00761 
00762         if(wtb->emboss) {
00763             widget_verts_to_quad_strip_open(wtb, wtb->halfwayvert, quad_strip_emboss);
00764         }
00765 
00766         glEnableClientState(GL_VERTEX_ARRAY);
00767 
00768         for (j = 0; j < WIDGET_AA_JITTER; j++) {
00769             glTranslatef(1.0f * jit[j][0], 1.0f * jit[j][1], 0.0f);
00770             
00771             /* outline */
00772             glColor4ubv(tcol);
00773 
00774             glVertexPointer(2, GL_FLOAT, 0, quad_strip);
00775             glDrawArrays(GL_QUAD_STRIP, 0, wtb->totvert*2 + 2);
00776         
00777             /* emboss bottom shadow */
00778             if(wtb->emboss) {
00779                 glColor4f(1.0f, 1.0f, 1.0f, 0.02f);
00780 
00781                 glVertexPointer(2, GL_FLOAT, 0, quad_strip_emboss);
00782                 glDrawArrays(GL_QUAD_STRIP, 0, wtb->halfwayvert*2);
00783             }
00784             
00785             glTranslatef(-1.0f * jit[j][0], -1.0f * jit[j][1], 0.0f);
00786         }
00787 
00788         glDisableClientState(GL_VERTEX_ARRAY);
00789     }
00790     
00791     /* decoration */
00792     if(wtb->tria1.tot || wtb->tria2.tot) {
00793         const unsigned char tcol[4] = {wcol->item[0],
00794                                        wcol->item[1],
00795                                        wcol->item[2],
00796                                        (unsigned char)((float)wcol->item[3] / WIDGET_AA_JITTER)};
00797         /* for each AA step */
00798         for (j = 0; j < WIDGET_AA_JITTER; j++) {
00799             glTranslatef(1.0f * jit[j][0], 1.0f * jit[j][1], 0.0f);
00800 
00801             if(wtb->tria1.tot) {
00802                 glColor4ubv(tcol);
00803                 widget_trias_draw(&wtb->tria1);
00804             }
00805             if(wtb->tria2.tot) {
00806                 glColor4ubv(tcol);
00807                 widget_trias_draw(&wtb->tria2);
00808             }
00809         
00810             glTranslatef(-1.0f * jit[j][0], -1.0f * jit[j][1], 0.0f);
00811         }
00812     }
00813 
00814     glDisable(GL_BLEND);
00815     
00816 }
00817 
00818 /* *********************** text/icon ************************************** */
00819 
00820 #define PREVIEW_PAD 4
00821 
00822 static void widget_draw_preview(BIFIconID icon, float UNUSED(alpha), rcti *rect)
00823 {
00824     int w, h, size;
00825 
00826     if(icon==ICON_NONE)
00827         return;
00828 
00829     w = rect->xmax - rect->xmin;
00830     h = rect->ymax - rect->ymin;
00831     size = MIN2(w, h);
00832     size -= PREVIEW_PAD*2;  /* padding */
00833 
00834     if(size > 0) {
00835         int x = rect->xmin + w/2 - size/2;
00836         int y = rect->ymin + h/2 - size/2;
00837 
00838         UI_icon_draw_preview_aspect_size(x, y, icon, 1.0f, size);
00839     }
00840 }
00841 
00842 
00843 static int ui_but_draw_menu_icon(uiBut *but)
00844 {
00845     return (but->flag & UI_ICON_SUBMENU) && (but->dt == UI_EMBOSSP);
00846 }
00847 
00848 /* icons have been standardized... and this call draws in untransformed coordinates */
00849 
00850 static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect)
00851 {
00852     int xs=0, ys=0;
00853     float aspect, height;
00854     
00855     if (but->flag & UI_ICON_PREVIEW) {
00856         widget_draw_preview(icon, alpha, rect);
00857         return;
00858     }
00859     
00860     /* this icon doesn't need draw... */
00861     if(icon==ICON_BLANK1 && (but->flag & UI_ICON_SUBMENU)==0) return;
00862     
00863     /* we need aspect from block, for menus... these buttons are scaled in uiPositionBlock() */
00864     aspect= but->block->aspect;
00865     if(aspect != but->aspect) {
00866         /* prevent scaling up icon in pupmenu */
00867         if (aspect < 1.0f) {            
00868             height= UI_DPI_ICON_SIZE;
00869             aspect = 1.0f;
00870             
00871         }
00872         else 
00873             height= UI_DPI_ICON_SIZE/aspect;
00874     }
00875     else
00876         height= UI_DPI_ICON_SIZE;
00877     
00878     /* calculate blend color */
00879     if ELEM4(but->type, TOG, ROW, TOGN, LISTROW) {
00880         if(but->flag & UI_SELECT);
00881         else if(but->flag & UI_ACTIVE);
00882         else alpha= 0.5f;
00883     }
00884     
00885     /* extra feature allows more alpha blending */
00886     if(but->type==LABEL && but->a1==1.0f) alpha *= but->a2;
00887     
00888     glEnable(GL_BLEND);
00889     
00890     if(icon && icon!=ICON_BLANK1) {
00891         if(but->flag & UI_ICON_LEFT) {
00892             if (but->type==BUT_TOGDUAL) {
00893                 if (but->drawstr[0]) {
00894                     xs= rect->xmin-1;
00895                 } else {
00896                     xs= (rect->xmin+rect->xmax- height)/2;
00897                 }
00898             }
00899             else if (but->block->flag & UI_BLOCK_LOOP) {
00900                 if(but->type==SEARCH_MENU)
00901                     xs= rect->xmin+4;
00902                 else
00903                     xs= rect->xmin+1;
00904             }
00905             else if ((but->type==ICONROW) || (but->type==ICONTEXTROW)) {
00906                 xs= rect->xmin+3;
00907             }
00908             else {
00909                 xs= rect->xmin+4;
00910             }
00911             ys= (rect->ymin+rect->ymax- height)/2;
00912         }
00913         else {
00914             xs= (rect->xmin+rect->xmax- height)/2;
00915             ys= (rect->ymin+rect->ymax- height)/2;
00916         }
00917         
00918         /* to indicate draggable */
00919         if(but->dragpoin && (but->flag & UI_ACTIVE)) {
00920             float rgb[3]= {1.25f, 1.25f, 1.25f};
00921             UI_icon_draw_aspect_color(xs, ys, icon, aspect, rgb);
00922         }
00923         else
00924             UI_icon_draw_aspect(xs, ys, icon, aspect, alpha);
00925     }
00926 
00927     if (ui_but_draw_menu_icon(but)) {
00928         xs= rect->xmax-17;
00929         ys= (rect->ymin+rect->ymax- height)/2;
00930         
00931         UI_icon_draw_aspect(xs, ys, ICON_RIGHTARROW_THIN, aspect, alpha);
00932     }
00933     
00934     glDisable(GL_BLEND);
00935 }
00936 
00937 /* sets but->ofs to make sure text is correctly visible */
00938 static void ui_text_leftclip(uiFontStyle *fstyle, uiBut *but, rcti *rect)
00939 {
00940     int border= (but->flag & UI_BUT_ALIGN_RIGHT)? 8: 10;
00941     int okwidth= rect->xmax-rect->xmin - border;
00942     
00943     if (but->flag & UI_HAS_ICON) okwidth -= UI_DPI_ICON_SIZE;
00944     
00945     /* need to set this first */
00946     uiStyleFontSet(fstyle);
00947     
00948     if (fstyle->kerning==1) /* for BLF_width */
00949         BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
00950 
00951     /* if text editing we define ofs dynamically */
00952     if(but->editstr && but->pos >= 0) {
00953         if(but->ofs > but->pos)
00954             but->ofs= but->pos;
00955     }
00956     else but->ofs= 0;
00957     
00958     but->strwidth= BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
00959     
00960     while(but->strwidth > okwidth) {
00961         
00962         /* textbut exception, clip right when... */
00963         if(but->editstr && but->pos >= 0) {
00964             float width;
00965             char buf[UI_MAX_DRAW_STR];
00966             
00967             /* copy draw string */
00968             BLI_strncpy(buf, but->drawstr, sizeof(buf));
00969             /* string position of cursor */
00970             buf[but->pos]= 0;
00971             width= BLF_width(fstyle->uifont_id, buf+but->ofs);
00972             
00973             /* if cursor is at 20 pixels of right side button we clip left */
00974             if(width > okwidth-20)
00975                 but->ofs++;
00976             else {
00977                 /* shift string to the left */
00978                 if(width < 20 && but->ofs > 0)
00979                     but->ofs--;
00980                 but->drawstr[ strlen(but->drawstr)-1 ]= 0;
00981             }
00982         }
00983         else
00984             but->ofs++;
00985 
00986         but->strwidth= BLF_width(fstyle->uifont_id, but->drawstr+but->ofs);
00987         
00988         if(but->strwidth < 10) break;
00989     }
00990     
00991     if (fstyle->kerning==1)
00992         BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
00993 }
00994 
00995 static void ui_text_label_rightclip(uiFontStyle *fstyle, uiBut *but, rcti *rect)
00996 {
00997     int border= (but->flag & UI_BUT_ALIGN_RIGHT)? 8: 10;
00998     int okwidth= rect->xmax-rect->xmin - border;
00999     char *cpoin=NULL;
01000     char *cpend = but->drawstr + strlen(but->drawstr);
01001     
01002     /* need to set this first */
01003     uiStyleFontSet(fstyle);
01004     
01005     if (fstyle->kerning==1) /* for BLF_width */
01006         BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
01007     
01008     but->strwidth= BLF_width(fstyle->uifont_id, but->drawstr);
01009     but->ofs= 0;
01010     
01011     /* find the space after ':' separator */
01012     cpoin= strrchr(but->drawstr, ':');
01013     
01014     if (cpoin && (cpoin < cpend-2)) {
01015         char *cp2 = cpoin;
01016         
01017         /* chop off the leading text, starting from the right */
01018         while (but->strwidth > okwidth && cp2 > but->drawstr) {
01019             /* shift the text after and including cp2 back by 1 char, +1 to include null terminator */
01020             memmove(cp2-1, cp2, strlen(cp2)+1);
01021             cp2--;
01022             
01023             but->strwidth= BLF_width(fstyle->uifont_id, but->drawstr+but->ofs);
01024             if(but->strwidth < 10) break;
01025         }
01026     
01027     
01028         /* after the leading text is gone, chop off the : and following space, with ofs */
01029         while ((but->strwidth > okwidth) && (but->ofs < 2))
01030         {
01031             but->ofs++;
01032             but->strwidth= BLF_width(fstyle->uifont_id, but->drawstr+but->ofs);
01033             if(but->strwidth < 10) break;
01034         }
01035         
01036     }
01037 
01038     /* once the label's gone, chop off the least significant digits */
01039     while(but->strwidth > okwidth ) {
01040         int pos= strlen(but->drawstr);
01041         
01042         but->drawstr[ pos-1 ] = 0;
01043         pos--;
01044         
01045         but->strwidth= BLF_width(fstyle->uifont_id, but->drawstr+but->ofs);
01046         if(but->strwidth < 10) break;
01047     }
01048     
01049     if (fstyle->kerning==1)
01050         BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
01051 }
01052 
01053 
01054 static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
01055 {
01056 //  int transopts;
01057     char *cpoin = NULL;
01058     
01059     /* for underline drawing */
01060     float font_xofs, font_yofs;
01061 
01062     uiStyleFontSet(fstyle);
01063     
01064     if(but->editstr || (but->flag & UI_TEXT_LEFT))
01065         fstyle->align= UI_STYLE_TEXT_LEFT;
01066     else
01067         fstyle->align= UI_STYLE_TEXT_CENTER;            
01068     
01069     if (fstyle->kerning==1) /* for BLF_width */
01070         BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
01071     
01072     /* text button selection and cursor */
01073     if(but->editstr && but->pos != -1) {
01074         short t=0, pos=0, ch;
01075         short selsta_tmp, selend_tmp, selsta_draw, selwidth_draw;
01076 
01077         if ((but->selend - but->selsta) > 0) {
01078             /* text button selection */
01079             selsta_tmp = but->selsta;
01080             selend_tmp = but->selend;
01081             
01082             if(but->drawstr[0]!=0) {
01083 
01084                 if (but->selsta >= but->ofs) {
01085                     ch= but->drawstr[selsta_tmp];
01086                     but->drawstr[selsta_tmp]= 0;
01087                     
01088                     selsta_draw = BLF_width(fstyle->uifont_id, but->drawstr+but->ofs);
01089                     
01090                     but->drawstr[selsta_tmp]= ch;
01091                 } else
01092                     selsta_draw = 0;
01093                 
01094                 ch= but->drawstr[selend_tmp];
01095                 but->drawstr[selend_tmp]= 0;
01096                 
01097                 selwidth_draw = BLF_width(fstyle->uifont_id, but->drawstr+but->ofs);
01098                 
01099                 but->drawstr[selend_tmp]= ch;
01100 
01101                 glColor3ubv((unsigned char*)wcol->item);
01102                 glRects(rect->xmin+selsta_draw, rect->ymin+2, rect->xmin+selwidth_draw, rect->ymax-2);
01103             }
01104         } else {
01105             /* text cursor */
01106             pos= but->pos;
01107             if(pos >= but->ofs) {
01108                 if(but->drawstr[0]!=0) {
01109                     ch= but->drawstr[pos];
01110                     but->drawstr[pos]= 0;
01111                     
01112                     t= BLF_width(fstyle->uifont_id, but->drawstr+but->ofs) / but->aspect;
01113                     
01114                     but->drawstr[pos]= ch;
01115                 }
01116 
01117                 glColor3f(0.20, 0.6, 0.9);
01118                 glRects(rect->xmin+t, rect->ymin+2, rect->xmin+t+2, rect->ymax-2);
01119             }
01120         }
01121     }
01122     
01123     if (fstyle->kerning == 1)
01124         BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
01125     
01126     //  ui_rasterpos_safe(x, y, but->aspect);
01127 //  if(but->type==IDPOIN) transopts= 0; // no translation, of course!
01128 //  else transopts= ui_translate_buttons();
01129     
01130     /* cut string in 2 parts - only for menu entries */
01131     if((but->block->flag & UI_BLOCK_LOOP)) {
01132         if(ELEM5(but->type, SLI, NUM, TEX, NUMSLI, NUMABS)==0) {
01133             cpoin= strchr(but->drawstr, '|');
01134             if(cpoin) *cpoin= 0;        
01135         }
01136     }
01137     
01138     glColor3ubv((unsigned char*)wcol->text);
01139 
01140     uiStyleFontDrawExt(fstyle, rect, but->drawstr+but->ofs, &font_xofs, &font_yofs);
01141 
01142     if(but->menu_key != '\0') {
01143         char fixedbuf[128];
01144         char *str;
01145 
01146         BLI_strncpy(fixedbuf, but->drawstr + but->ofs, sizeof(fixedbuf));
01147 
01148         str= strchr(fixedbuf, but->menu_key-32); /* upper case */
01149         if(str==NULL)
01150             str= strchr(fixedbuf, but->menu_key);
01151 
01152         if(str) {
01153             int ul_index= -1;
01154             float ul_advance;
01155 
01156             ul_index= (int)(str - fixedbuf);
01157 
01158             if (fstyle->kerning == 1) {
01159                 BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
01160             }
01161 
01162             fixedbuf[ul_index]= '\0';
01163             ul_advance= BLF_width(fstyle->uifont_id, fixedbuf);
01164 
01165             BLF_position(fstyle->uifont_id, rect->xmin+font_xofs + ul_advance, rect->ymin+font_yofs, 0.0f);
01166             BLF_draw(fstyle->uifont_id, "_", 2);
01167 
01168             if (fstyle->kerning == 1) {
01169                 BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
01170             }
01171         }
01172     }
01173 
01174     /* part text right aligned */
01175     if(cpoin) {
01176         fstyle->align= UI_STYLE_TEXT_RIGHT;
01177         rect->xmax -= ui_but_draw_menu_icon(but) ? UI_DPI_ICON_SIZE : 5;
01178         uiStyleFontDraw(fstyle, rect, cpoin+1);
01179         *cpoin= '|';
01180     }
01181 }
01182 
01183 /* draws text and icons for buttons */
01184 static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
01185 {
01186     
01187     if(but==NULL) return;
01188 
01189     /* clip but->drawstr to fit in available space */
01190     if (but->editstr && but->pos >= 0) {
01191         ui_text_leftclip(fstyle, but, rect);
01192     }
01193     else if (ELEM4(but->type, NUM, NUMABS, NUMSLI, SLI)) {
01194         ui_text_label_rightclip(fstyle, but, rect);
01195     }
01196     else if (ELEM(but->type, TEX, SEARCH_MENU)) {
01197         ui_text_leftclip(fstyle, but, rect);
01198     }
01199     else if ((but->block->flag & UI_BLOCK_LOOP) && (but->type == BUT)) {
01200         ui_text_leftclip(fstyle, but, rect);
01201     }
01202     else but->ofs= 0;
01203     
01204     /* check for button text label */
01205     if (but->type == ICONTEXTROW) {
01206         widget_draw_icon(but, (BIFIconID) (but->icon+but->iconadd), 1.0f, rect);
01207     }
01208     else {
01209                 
01210         if(but->type==BUT_TOGDUAL) {
01211             int dualset= 0;
01212             if(but->pointype==SHO)
01213                 dualset= BTST( *(((short *)but->poin)+1), but->bitnr);
01214             else if(but->pointype==INT)
01215                 dualset= BTST( *(((int *)but->poin)+1), but->bitnr);
01216             
01217             widget_draw_icon(but, ICON_DOT, dualset?1.0f:0.25f, rect);
01218         }
01219         else if(but->type==MENU && (but->flag & UI_BUT_NODE_LINK)) {
01220             int tmp = rect->xmin;
01221             rect->xmin = rect->xmax - (rect->ymax - rect->ymin) - 1;
01222             widget_draw_icon(but, ICON_LAYER_USED, 1.0f, rect);
01223             rect->xmin = tmp;
01224         }
01225         
01226         /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
01227         and offset the text label to accommodate it */
01228         
01229         if (but->flag & UI_HAS_ICON) {
01230             widget_draw_icon(but, but->icon+but->iconadd, 1.0f, rect);
01231             
01232             rect->xmin += (int)((float)UI_icon_get_width(but->icon+but->iconadd) * UI_DPI_ICON_FAC);
01233             
01234             if(but->editstr || (but->flag & UI_TEXT_LEFT)) 
01235                 rect->xmin += 5;
01236         }
01237         else if((but->flag & UI_TEXT_LEFT)) 
01238             rect->xmin += 5;
01239         
01240         /* always draw text for textbutton cursor */
01241         widget_draw_text(fstyle, wcol, but, rect);
01242 
01243     }
01244 }
01245 
01246 
01247 
01248 /* *********************** widget types ************************************* */
01249 
01250 
01251 /*   uiWidgetStateColors
01252     char inner_anim[4];
01253     char inner_anim_sel[4];
01254     char inner_key[4];
01255     char inner_key_sel[4];
01256     char inner_driven[4];
01257     char inner_driven_sel[4];
01258     float blend;
01259  
01260 */
01261 
01262 static struct uiWidgetStateColors wcol_state_colors= {
01263     {115, 190, 76, 255},
01264     {90, 166, 51, 255},
01265     {240, 235, 100, 255},
01266     {215, 211, 75, 255},
01267     {180, 0, 255, 255},
01268     {153, 0, 230, 255},
01269     0.5f, 0.0f
01270 };
01271 
01272 /*  uiWidgetColors
01273     float outline[3];
01274     float inner[4];
01275     float inner_sel[4];
01276     float item[3];
01277     float text[3];
01278     float text_sel[3];
01279 
01280     short shaded;
01281     float shadetop, shadedown;
01282 */  
01283 
01284 static struct uiWidgetColors wcol_num= {
01285     {25, 25, 25, 255},
01286     {180, 180, 180, 255},
01287     {153, 153, 153, 255},
01288     {90, 90, 90, 255},
01289     
01290     {0, 0, 0, 255},
01291     {255, 255, 255, 255},
01292     
01293     1,
01294     -20, 0
01295 };
01296 
01297 static struct uiWidgetColors wcol_numslider= {
01298     {25, 25, 25, 255},
01299     {180, 180, 180, 255},
01300     {153, 153, 153, 255},
01301     {128, 128, 128, 255},
01302     
01303     {0, 0, 0, 255},
01304     {255, 255, 255, 255},
01305     
01306     1,
01307     -20, 0
01308 };
01309 
01310 static struct uiWidgetColors wcol_text= {
01311     {25, 25, 25, 255},
01312     {153, 153, 153, 255},
01313     {153, 153, 153, 255},
01314     {90, 90, 90, 255},
01315     
01316     {0, 0, 0, 255},
01317     {255, 255, 255, 255},
01318     
01319     1,
01320     0, 25
01321 };
01322 
01323 static struct uiWidgetColors wcol_option= {
01324     {0, 0, 0, 255},
01325     {70, 70, 70, 255},
01326     {70, 70, 70, 255},
01327     {255, 255, 255, 255},
01328     
01329     {0, 0, 0, 255},
01330     {255, 255, 255, 255},
01331     
01332     1,
01333     15, -15
01334 };
01335 
01336 /* button that shows popup */
01337 static struct uiWidgetColors wcol_menu= {
01338     {0, 0, 0, 255},
01339     {70, 70, 70, 255},
01340     {70, 70, 70, 255},
01341     {255, 255, 255, 255},
01342     
01343     {255, 255, 255, 255},
01344     {204, 204, 204, 255},
01345     
01346     1,
01347     15, -15
01348 };
01349 
01350 /* button that starts pulldown */
01351 static struct uiWidgetColors wcol_pulldown= {
01352     {0, 0, 0, 255},
01353     {63, 63, 63, 255},
01354     {86, 128, 194, 255},
01355     {255, 255, 255, 255},
01356     
01357     {0, 0, 0, 255},
01358     {0, 0, 0, 255},
01359     
01360     0,
01361     25, -20
01362 };
01363 
01364 /* button inside menu */
01365 static struct uiWidgetColors wcol_menu_item= {
01366     {0, 0, 0, 255},
01367     {0, 0, 0, 0},
01368     {86, 128, 194, 255},
01369     {255, 255, 255, 255},
01370     
01371     {255, 255, 255, 255},
01372     {0, 0, 0, 255},
01373     
01374     1,
01375     38, 0
01376 };
01377 
01378 /* backdrop menu + title text color */
01379 static struct uiWidgetColors wcol_menu_back= {
01380     {0, 0, 0, 255},
01381     {25, 25, 25, 230},
01382     {45, 45, 45, 230},
01383     {100, 100, 100, 255},
01384     
01385     {160, 160, 160, 255},
01386     {255, 255, 255, 255},
01387     
01388     0,
01389     25, -20
01390 };
01391 
01392 
01393 static struct uiWidgetColors wcol_radio= {
01394     {0, 0, 0, 255},
01395     {70, 70, 70, 255},
01396     {86, 128, 194, 255},
01397     {255, 255, 255, 255},
01398     
01399     {255, 255, 255, 255},
01400     {0, 0, 0, 255},
01401     
01402     1,
01403     15, -15
01404 };
01405 
01406 static struct uiWidgetColors wcol_regular= {
01407     {25, 25, 25, 255},
01408     {153, 153, 153, 255},
01409     {100, 100, 100, 255},
01410     {25, 25, 25, 255},
01411     
01412     {0, 0, 0, 255},
01413     {255, 255, 255, 255},
01414     
01415     0,
01416     0, 0
01417 };
01418 
01419 static struct uiWidgetColors wcol_tool= {
01420     {25, 25, 25, 255},
01421     {153, 153, 153, 255},
01422     {100, 100, 100, 255},
01423     {25, 25, 25, 255},
01424     
01425     {0, 0, 0, 255},
01426     {255, 255, 255, 255},
01427     
01428     1,
01429     15, -15
01430 };
01431 
01432 static struct uiWidgetColors wcol_box= {
01433     {25, 25, 25, 255},
01434     {128, 128, 128, 255},
01435     {100, 100, 100, 255},
01436     {25, 25, 25, 255},
01437     
01438     {0, 0, 0, 255},
01439     {255, 255, 255, 255},
01440     
01441     0,
01442     0, 0
01443 };
01444 
01445 static struct uiWidgetColors wcol_toggle= {
01446     {25, 25, 25, 255},
01447     {153, 153, 153, 255},
01448     {100, 100, 100, 255},
01449     {25, 25, 25, 255},
01450     
01451     {0, 0, 0, 255},
01452     {255, 255, 255, 255},
01453     
01454     0,
01455     0, 0
01456 };
01457 
01458 static struct uiWidgetColors wcol_scroll= {
01459     {50, 50, 50, 180},
01460     {80, 80, 80, 180},
01461     {100, 100, 100, 180},
01462     {128, 128, 128, 255},
01463     
01464     {0, 0, 0, 255},
01465     {255, 255, 255, 255},
01466     
01467     1,
01468     5, -5
01469 };
01470 
01471 static struct uiWidgetColors wcol_progress= {
01472     {0, 0, 0, 255},
01473     {190, 190, 190, 255},
01474     {100, 100, 100, 180},
01475     {68, 68, 68, 255},
01476     
01477     {0, 0, 0, 255},
01478     {255, 255, 255, 255},
01479     
01480     0,
01481     0, 0
01482 };
01483 
01484 static struct uiWidgetColors wcol_list_item= {
01485     {0, 0, 0, 255},
01486     {0, 0, 0, 0},
01487     {86, 128, 194, 255},
01488     {0, 0, 0, 255},
01489     
01490     {0, 0, 0, 255},
01491     {0, 0, 0, 255},
01492     
01493     0,
01494     0, 0
01495 };
01496 
01497 /* free wcol struct to play with */
01498 static struct uiWidgetColors wcol_tmp= {
01499     {0, 0, 0, 255},
01500     {128, 128, 128, 255},
01501     {100, 100, 100, 255},
01502     {25, 25, 25, 255},
01503     
01504     {0, 0, 0, 255},
01505     {255, 255, 255, 255},
01506     
01507     0,
01508     0, 0
01509 };
01510 
01511 
01512 /* called for theme init (new theme) and versions */
01513 void ui_widget_color_init(ThemeUI *tui)
01514 {
01515     tui->wcol_regular= wcol_regular;
01516     tui->wcol_tool= wcol_tool;
01517     tui->wcol_text= wcol_text;
01518     tui->wcol_radio= wcol_radio;
01519     tui->wcol_option= wcol_option;
01520     tui->wcol_toggle= wcol_toggle;
01521     tui->wcol_num= wcol_num;
01522     tui->wcol_numslider= wcol_numslider;
01523     tui->wcol_menu= wcol_menu;
01524     tui->wcol_pulldown= wcol_pulldown;
01525     tui->wcol_menu_back= wcol_menu_back;
01526     tui->wcol_menu_item= wcol_menu_item;
01527     tui->wcol_box= wcol_box;
01528     tui->wcol_scroll= wcol_scroll;
01529     tui->wcol_list_item= wcol_list_item;
01530     tui->wcol_progress= wcol_progress;
01531 
01532     tui->wcol_state= wcol_state_colors;
01533 }
01534 
01535 /* ************ button callbacks, state ***************** */
01536 
01537 static void widget_state_blend(char cp[3], const char cpstate[3], const float fac)
01538 {
01539     if(fac != 0.0f) {
01540         cp[0]= (int)((1.0f-fac)*cp[0] + fac*cpstate[0]);
01541         cp[1]= (int)((1.0f-fac)*cp[1] + fac*cpstate[1]);
01542         cp[2]= (int)((1.0f-fac)*cp[2] + fac*cpstate[2]);
01543     }
01544 }
01545 
01546 /* copy colors from theme, and set changes in it based on state */
01547 static void widget_state(uiWidgetType *wt, int state)
01548 {
01549     uiWidgetStateColors *wcol_state= wt->wcol_state;
01550 
01551     wt->wcol= *(wt->wcol_theme);
01552     
01553     if(state & UI_SELECT) {
01554         copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
01555 
01556         if(state & UI_BUT_ANIMATED_KEY)
01557             widget_state_blend(wt->wcol.inner, wcol_state->inner_key_sel, wcol_state->blend);
01558         else if(state & UI_BUT_ANIMATED)
01559             widget_state_blend(wt->wcol.inner, wcol_state->inner_anim_sel, wcol_state->blend);
01560         else if(state & UI_BUT_DRIVEN)
01561             widget_state_blend(wt->wcol.inner, wcol_state->inner_driven_sel, wcol_state->blend);
01562 
01563         copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
01564         
01565         if(state & UI_SELECT)
01566             SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
01567     }
01568     else {
01569         if(state & UI_BUT_ANIMATED_KEY)
01570             widget_state_blend(wt->wcol.inner, wcol_state->inner_key, wcol_state->blend);
01571         else if(state & UI_BUT_ANIMATED)
01572             widget_state_blend(wt->wcol.inner, wcol_state->inner_anim, wcol_state->blend);
01573         else if(state & UI_BUT_DRIVEN)
01574             widget_state_blend(wt->wcol.inner, wcol_state->inner_driven, wcol_state->blend);
01575 
01576         if(state & UI_ACTIVE) { /* mouse over? */
01577             wt->wcol.inner[0]= wt->wcol.inner[0]>=240? 255 : wt->wcol.inner[0]+15;
01578             wt->wcol.inner[1]= wt->wcol.inner[1]>=240? 255 : wt->wcol.inner[1]+15;
01579             wt->wcol.inner[2]= wt->wcol.inner[2]>=240? 255 : wt->wcol.inner[2]+15;
01580         }
01581     }
01582 
01583     if(state & UI_BUT_REDALERT) {
01584         char red[4]= {255, 0, 0};
01585         widget_state_blend(wt->wcol.inner, red, 0.4f);
01586     }
01587     if(state & UI_BUT_NODE_ACTIVE) {
01588         char blue[4]= {86, 128, 194};
01589         widget_state_blend(wt->wcol.inner, blue, 0.3f);
01590     }
01591 }
01592 
01593 /* sliders use special hack which sets 'item' as inner when drawing filling */
01594 static void widget_state_numslider(uiWidgetType *wt, int state)
01595 {
01596     uiWidgetStateColors *wcol_state= wt->wcol_state;
01597     float blend= wcol_state->blend - 0.2f; // XXX special tweak to make sure that bar will still be visible
01598 
01599     /* call this for option button */
01600     widget_state(wt, state);
01601     
01602     /* now, set the inner-part so that it reflects state settings too */
01603     // TODO: maybe we should have separate settings for the blending colors used for this case?
01604     if(state & UI_SELECT) {
01605         
01606         if(state & UI_BUT_ANIMATED_KEY)
01607             widget_state_blend(wt->wcol.item, wcol_state->inner_key_sel, blend);
01608         else if(state & UI_BUT_ANIMATED)
01609             widget_state_blend(wt->wcol.item, wcol_state->inner_anim_sel, blend);
01610         else if(state & UI_BUT_DRIVEN)
01611             widget_state_blend(wt->wcol.item, wcol_state->inner_driven_sel, blend);
01612         
01613         if(state & UI_SELECT)
01614             SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
01615     }
01616     else {
01617         if(state & UI_BUT_ANIMATED_KEY)
01618             widget_state_blend(wt->wcol.item, wcol_state->inner_key, blend);
01619         else if(state & UI_BUT_ANIMATED)
01620             widget_state_blend(wt->wcol.item, wcol_state->inner_anim, blend);
01621         else if(state & UI_BUT_DRIVEN)
01622             widget_state_blend(wt->wcol.item, wcol_state->inner_driven, blend);
01623     }
01624 }
01625 
01626 /* labels use theme colors for text */
01627 static void widget_state_label(uiWidgetType *wt, int state)
01628 {
01629     /* call this for option button */
01630     widget_state(wt, state);
01631 
01632     if(state & UI_SELECT)
01633         UI_GetThemeColor4ubv(TH_TEXT_HI, (unsigned char *)wt->wcol.text);
01634     else
01635         UI_GetThemeColor4ubv(TH_TEXT, (unsigned char *)wt->wcol.text);
01636     
01637 }
01638 
01639 /* labels use theme colors for text */
01640 static void widget_state_option_menu(uiWidgetType *wt, int state)
01641 {
01642     
01643     /* call this for option button */
01644     widget_state(wt, state);
01645     
01646     /* if not selected we get theme from menu back */
01647     if(state & UI_SELECT)
01648         UI_GetThemeColor4ubv(TH_TEXT_HI, (unsigned char *)wt->wcol.text);
01649     else {
01650         bTheme *btheme= UI_GetTheme(); /* XXX */
01651 
01652         copy_v3_v3_char(wt->wcol.text, btheme->tui.wcol_menu_back.text);
01653     }
01654 }
01655 
01656 
01657 static void widget_state_nothing(uiWidgetType *wt, int UNUSED(state))
01658 {
01659     wt->wcol= *(wt->wcol_theme);
01660 }   
01661 
01662 /* special case, button that calls pulldown */
01663 static void widget_state_pulldown(uiWidgetType *wt, int state)
01664 {
01665     wt->wcol= *(wt->wcol_theme);
01666     
01667     copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
01668     copy_v3_v3_char(wt->wcol.outline, wt->wcol.inner);
01669 
01670     if(state & UI_ACTIVE)
01671         copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
01672 }
01673 
01674 /* special case, menu items */
01675 static void widget_state_menu_item(uiWidgetType *wt, int state)
01676 {
01677     wt->wcol= *(wt->wcol_theme);
01678     
01679     if(state & (UI_BUT_DISABLED|UI_BUT_INACTIVE)) {
01680         wt->wcol.text[0]= 0.5f*(wt->wcol.text[0]+wt->wcol.text_sel[0]);
01681         wt->wcol.text[1]= 0.5f*(wt->wcol.text[1]+wt->wcol.text_sel[1]);
01682         wt->wcol.text[2]= 0.5f*(wt->wcol.text[2]+wt->wcol.text_sel[2]);
01683     }
01684     else if(state & UI_ACTIVE) {
01685         copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
01686         copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
01687     }
01688 }
01689 
01690 
01691 /* ************ menu backdrop ************************* */
01692 
01693 /* outside of rect, rad to left/bottom/right */
01694 static void widget_softshadow(rcti *rect, int roundboxalign, float radin, float radout)
01695 {
01696     uiWidgetBase wtb;
01697     rcti rect1= *rect;
01698     float alpha, alphastep;
01699     int step, totvert;
01700     float quad_strip[WIDGET_SIZE_MAX*2][2];
01701     
01702     /* prevent tooltips to not show round shadow */
01703     if( 2.0f*radout > 0.2f*(rect1.ymax-rect1.ymin) )
01704         rect1.ymax -= 0.2f*(rect1.ymax-rect1.ymin);
01705     else
01706         rect1.ymax -= 2.0f*radout;
01707     
01708     /* inner part */
01709     totvert= round_box_shadow_edges(wtb.inner_v, &rect1, radin, roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT), 0.0f);
01710 
01711     /* inverse linear shadow alpha */
01712     alpha= 0.15;
01713     alphastep= 0.67;
01714     
01715     glEnableClientState(GL_VERTEX_ARRAY);
01716 
01717     for(step= 1; step<=radout; step++, alpha*=alphastep) {
01718         round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step);
01719         
01720         glColor4f(0.0f, 0.0f, 0.0f, alpha);
01721 
01722         widget_verts_to_quad_strip_open(&wtb, totvert, quad_strip);
01723 
01724         glVertexPointer(2, GL_FLOAT, 0, quad_strip);
01725         glDrawArrays(GL_QUAD_STRIP, 0, totvert*2);
01726     }
01727 
01728     glDisableClientState(GL_VERTEX_ARRAY);
01729 }
01730 
01731 static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction)
01732 {
01733     uiWidgetBase wtb;
01734     int roundboxalign= UI_CNR_ALL;
01735     
01736     widget_init(&wtb);
01737     
01738     /* menu is 2nd level or deeper */
01739     if (flag & UI_BLOCK_POPUP) {
01740         //rect->ymin -= 4.0;
01741         //rect->ymax += 4.0;
01742     }
01743     else if (direction == UI_DOWN) {
01744         roundboxalign= (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
01745         rect->ymin -= 4.0;
01746     } 
01747     else if (direction == UI_TOP) {
01748         roundboxalign= UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
01749         rect->ymax += 4.0;
01750     }
01751     
01752     glEnable(GL_BLEND);
01753     widget_softshadow(rect, roundboxalign, 5.0f, 8.0f);
01754     
01755     round_box_edges(&wtb, roundboxalign, rect, 5.0f);
01756     wtb.emboss= 0;
01757     widgetbase_draw(&wtb, wcol);
01758     
01759     glDisable(GL_BLEND);
01760 }
01761 
01762 
01763 static void ui_hsv_cursor(float x, float y)
01764 {
01765     
01766     glPushMatrix();
01767     glTranslatef(x, y, 0.0f);
01768     
01769     glColor3f(1.0f, 1.0f, 1.0f);
01770     glutil_draw_filled_arc(0.0f, M_PI*2.0, 3.0f, 8);
01771     
01772     glEnable(GL_BLEND);
01773     glEnable(GL_LINE_SMOOTH );
01774     glColor3f(0.0f, 0.0f, 0.0f);
01775     glutil_draw_lined_arc(0.0f, M_PI*2.0, 3.0f, 12);
01776     glDisable(GL_BLEND);
01777     glDisable(GL_LINE_SMOOTH );
01778     
01779     glPopMatrix();
01780     
01781 }
01782 
01783 void ui_hsvcircle_vals_from_pos(float *valrad, float *valdist, rcti *rect, float mx, float my)
01784 {
01785     /* duplication of code... well, simple is better now */
01786     float centx= (float)(rect->xmin + rect->xmax)/2;
01787     float centy= (float)(rect->ymin + rect->ymax)/2;
01788     float radius, dist;
01789     
01790     if( rect->xmax-rect->xmin > rect->ymax-rect->ymin )
01791         radius= (float)(rect->ymax - rect->ymin)/2; 
01792     else
01793         radius= (float)(rect->xmax - rect->xmin)/2; 
01794 
01795     mx-= centx;
01796     my-= centy;
01797     dist= sqrt( mx*mx + my*my);
01798     if(dist < radius)
01799         *valdist= dist/radius;
01800     else
01801         *valdist= 1.0f;
01802     
01803     *valrad= atan2f(mx, my)/(2.0f*(float)M_PI) + 0.5f;
01804 }
01805 
01806 static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect)
01807 {
01808     /* gouraud triangle fan */
01809     float radstep, ang= 0.0f;
01810     float centx, centy, radius, cursor_radius;
01811     float rgb[3], hsvo[3], hsv[3], col[3], colcent[3];
01812     int a, tot= 32;
01813     int color_profile = but->block->color_profile;
01814     
01815     if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
01816         color_profile = BLI_PR_NONE;
01817     
01818     radstep= 2.0f*(float)M_PI/(float)tot;
01819     centx= (float)(rect->xmin + rect->xmax)/2;
01820     centy= (float)(rect->ymin + rect->ymax)/2;
01821     
01822     if( rect->xmax-rect->xmin > rect->ymax-rect->ymin )
01823         radius= (float)(rect->ymax - rect->ymin)/2; 
01824     else
01825         radius= (float)(rect->xmax - rect->xmin)/2; 
01826     
01827     /* color */
01828     ui_get_but_vectorf(but, rgb);
01829     copy_v3_v3(hsv, ui_block_hsv_get(but->block));
01830     rgb_to_hsv_compat(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
01831     copy_v3_v3(hsvo, hsv);
01832     
01833     /* exception: if 'lock' is set
01834      * lock the value of the color wheel to 1.
01835      * Useful for color correction tools where you're only interested in hue. */
01836     if (but->flag & UI_BUT_COLOR_LOCK)
01837         hsv[2] = 1.f;
01838     else if (color_profile)
01839         hsv[2] = linearrgb_to_srgb(hsv[2]);
01840     
01841     hsv_to_rgb(0.f, 0.f, hsv[2], colcent, colcent+1, colcent+2);
01842     
01843     glShadeModel(GL_SMOOTH);
01844 
01845     glBegin(GL_TRIANGLE_FAN);
01846     glColor3fv(colcent);
01847     glVertex2f( centx, centy);
01848     
01849     for(a=0; a<=tot; a++, ang+=radstep) {
01850         float si= sin(ang);
01851         float co= cos(ang);
01852         
01853         ui_hsvcircle_vals_from_pos(hsv, hsv+1, rect, centx + co*radius, centy + si*radius);
01854         CLAMP(hsv[2], 0.0f, 1.0f); /* for display only */
01855 
01856         hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2);
01857         glColor3fv(col);
01858         glVertex2f( centx + co*radius, centy + si*radius);
01859     }
01860     glEnd();
01861     
01862     glShadeModel(GL_FLAT);
01863     
01864     /* fully rounded outline */
01865     glPushMatrix();
01866     glTranslatef(centx, centy, 0.0f);
01867     glEnable(GL_BLEND);
01868     glEnable(GL_LINE_SMOOTH );
01869     glColor3ubv((unsigned char*)wcol->outline);
01870     glutil_draw_lined_arc(0.0f, M_PI*2.0, radius, tot + 1);
01871     glDisable(GL_BLEND);
01872     glDisable(GL_LINE_SMOOTH );
01873     glPopMatrix();
01874 
01875     /* cursor */
01876     ang= 2.0f*(float)M_PI*hsvo[0] + 0.5f*(float)M_PI;
01877 
01878     if(but->flag & UI_BUT_COLOR_CUBIC)
01879         cursor_radius = (1.0f - powf(1.0f - hsvo[1], 3.0f));
01880     else
01881         cursor_radius = hsvo[1];
01882 
01883     radius= CLAMPIS(cursor_radius, 0.0f, 1.0f) * radius;
01884     ui_hsv_cursor(centx + cosf(-ang)*radius, centy + sinf(-ang)*radius);
01885 }
01886 
01887 /* ************ custom buttons, old stuff ************** */
01888 
01889 /* draws in resolution of 20x4 colors */
01890 void ui_draw_gradient(rcti *rect, const float hsv[3], int type, float alpha)
01891 {
01892     int a;
01893     float h= hsv[0], s= hsv[1], v= hsv[2];
01894     float dx, dy, sx1, sx2, sy;
01895     float col0[4][3];   // left half, rect bottom to top
01896     float col1[4][3];   // right half, rect bottom to top
01897 
01898     /* draw series of gouraud rects */
01899     glShadeModel(GL_SMOOTH);
01900     
01901     switch(type) {
01902         case UI_GRAD_SV:
01903             hsv_to_rgb(h, 0.0, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
01904             hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]);
01905             hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
01906             hsv_to_rgb(h, 1.0, 0.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
01907             break;
01908         case UI_GRAD_HV:
01909             hsv_to_rgb(0.0, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
01910             hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
01911             hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
01912             hsv_to_rgb(0.0, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
01913             break;
01914         case UI_GRAD_HS:
01915             hsv_to_rgb(0.0, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
01916             hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
01917             hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
01918             hsv_to_rgb(0.0, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
01919             break;
01920         case UI_GRAD_H:
01921             hsv_to_rgb(0.0, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
01922             copy_v3_v3(col1[1], col1[0]);
01923             copy_v3_v3(col1[2], col1[0]);
01924             copy_v3_v3(col1[3], col1[0]);
01925             break;
01926         case UI_GRAD_S:
01927             hsv_to_rgb(1.0, 0.0, 1.0,   &col1[1][0], &col1[1][1], &col1[1][2]);
01928             copy_v3_v3(col1[0], col1[1]);
01929             copy_v3_v3(col1[2], col1[1]);
01930             copy_v3_v3(col1[3], col1[1]);
01931             break;
01932         case UI_GRAD_V:
01933             hsv_to_rgb(1.0, 1.0, 0.0,   &col1[2][0], &col1[2][1], &col1[2][2]);
01934             copy_v3_v3(col1[0], col1[2]);
01935             copy_v3_v3(col1[1], col1[2]);
01936             copy_v3_v3(col1[3], col1[2]);
01937             break;
01938         default:
01939             assert(!"invalid 'type' argument");
01940             hsv_to_rgb(1.0, 1.0, 1.0,   &col1[2][0], &col1[2][1], &col1[2][2]);
01941             copy_v3_v3(col1[0], col1[2]);
01942             copy_v3_v3(col1[1], col1[2]);
01943             copy_v3_v3(col1[3], col1[2]);
01944     }
01945     
01946     /* old below */
01947     
01948     for(dx=0.0f; dx<1.0f; dx+= 0.05f) {
01949         // previous color
01950         copy_v3_v3(col0[0], col1[0]);
01951         copy_v3_v3(col0[1], col1[1]);
01952         copy_v3_v3(col0[2], col1[2]);
01953         copy_v3_v3(col0[3], col1[3]);
01954         
01955         // new color
01956         switch(type) {
01957             case UI_GRAD_SV:
01958                 hsv_to_rgb(h, 0.0, dx,   &col1[0][0], &col1[0][1], &col1[0][2]);
01959                 hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]);
01960                 hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
01961                 hsv_to_rgb(h, 1.0, dx,   &col1[3][0], &col1[3][1], &col1[3][2]);
01962                 break;
01963             case UI_GRAD_HV:
01964                 hsv_to_rgb(dx, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
01965                 hsv_to_rgb(dx, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
01966                 hsv_to_rgb(dx, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
01967                 hsv_to_rgb(dx, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
01968                 break;
01969             case UI_GRAD_HS:
01970                 hsv_to_rgb(dx, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
01971                 hsv_to_rgb(dx, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
01972                 hsv_to_rgb(dx, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
01973                 hsv_to_rgb(dx, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
01974                 break;
01975             case UI_GRAD_H:
01976                 hsv_to_rgb(dx, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
01977                 copy_v3_v3(col1[1], col1[0]);
01978                 copy_v3_v3(col1[2], col1[0]);
01979                 copy_v3_v3(col1[3], col1[0]);
01980                 break;
01981             case UI_GRAD_S:
01982                 hsv_to_rgb(h, dx, 1.0,   &col1[1][0], &col1[1][1], &col1[1][2]);
01983                 copy_v3_v3(col1[0], col1[1]);
01984                 copy_v3_v3(col1[2], col1[1]);
01985                 copy_v3_v3(col1[3], col1[1]);
01986                 break;
01987             case UI_GRAD_V:
01988                 hsv_to_rgb(h, 1.0, dx,   &col1[2][0], &col1[2][1], &col1[2][2]);
01989                 copy_v3_v3(col1[0], col1[2]);
01990                 copy_v3_v3(col1[1], col1[2]);
01991                 copy_v3_v3(col1[3], col1[2]);
01992                 break;
01993         }
01994         
01995         // rect
01996         sx1= rect->xmin + dx*(rect->xmax-rect->xmin);
01997         sx2= rect->xmin + (dx+0.05f)*(rect->xmax-rect->xmin);
01998         sy= rect->ymin;
01999         dy= (rect->ymax-rect->ymin)/3.0;
02000         
02001         glBegin(GL_QUADS);
02002         for(a=0; a<3; a++, sy+=dy) {
02003             glColor4f(col0[a][0], col0[a][1], col0[a][2], alpha);
02004             glVertex2f(sx1, sy);
02005             
02006             glColor4f(col1[a][0], col1[a][1], col1[a][2], alpha);
02007             glVertex2f(sx2, sy);
02008 
02009             glColor4f(col1[a+1][0], col1[a+1][1], col1[a+1][2], alpha);
02010             glVertex2f(sx2, sy+dy);
02011             
02012             glColor4f(col0[a+1][0], col0[a+1][1], col0[a+1][2], alpha);
02013             glVertex2f(sx1, sy+dy);
02014         }
02015         glEnd();
02016     }
02017     
02018     glShadeModel(GL_FLAT);
02019     
02020 }
02021 
02022 
02023 
02024 static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect)
02025 {
02026     float rgb[3], h,s,v;
02027     float x=0.0f, y=0.0f;
02028     float *hsv= ui_block_hsv_get(but->block);
02029     float hsvn[3];
02030     
02031     h= hsv[0];
02032     s= hsv[1];
02033     v= hsv[2];
02034     
02035     ui_get_but_vectorf(but, rgb);
02036     rgb_to_hsv_compat(rgb[0], rgb[1], rgb[2], &h, &s, &v);
02037 
02038     hsvn[0]= h;
02039     hsvn[1]= s;
02040     hsvn[2]= v;
02041     
02042     ui_draw_gradient(rect, hsvn, but->a1, 1.f);
02043     
02044     switch((int)but->a1) {
02045         case UI_GRAD_SV:
02046             x= v; y= s; break;
02047         case UI_GRAD_HV:
02048             x= h; y= v; break;
02049         case UI_GRAD_HS:
02050             x= h; y= s; break;
02051         case UI_GRAD_H:
02052             x= h; y= 0.5; break;
02053         case UI_GRAD_S:
02054             x= s; y= 0.5; break;
02055         case UI_GRAD_V:
02056             x= v; y= 0.5; break;
02057     }
02058     
02059     /* cursor */
02060     x= rect->xmin + x*(rect->xmax-rect->xmin);
02061     y= rect->ymin + y*(rect->ymax-rect->ymin);
02062     CLAMP(x, rect->xmin+3.0f, rect->xmax-3.0f);
02063     CLAMP(y, rect->ymin+3.0f, rect->ymax-3.0f);
02064     
02065     ui_hsv_cursor(x, y);
02066     
02067     /* outline */
02068     glColor3ub(0,  0,  0);
02069     fdrawbox((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
02070 }
02071 
02072 /* vertical 'value' slider, using new widget code */
02073 static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
02074 {
02075     uiWidgetBase wtb;
02076     float rad= 0.5f*(rect->xmax - rect->xmin);
02077     float x, y;
02078     float rgb[3], hsv[3], v, range;
02079     int color_profile = but->block->color_profile;
02080     
02081     if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
02082         color_profile = BLI_PR_NONE;
02083 
02084     ui_get_but_vectorf(but, rgb);
02085     rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
02086     v = hsv[2];
02087     
02088     if (color_profile)
02089         v = linearrgb_to_srgb(v);
02090 
02091     /* map v from property range to [0,1] */
02092     range = but->softmax - but->softmin;
02093     v = (v - but->softmin)/range;
02094     
02095     widget_init(&wtb);
02096     
02097     /* fully rounded */
02098     round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
02099     
02100     /* setup temp colors */
02101     wcol_tmp.outline[0]= wcol_tmp.outline[1]= wcol_tmp.outline[2]= 0;
02102     wcol_tmp.inner[0]= wcol_tmp.inner[1]= wcol_tmp.inner[2]= 128;
02103     wcol_tmp.shadetop= 127;
02104     wcol_tmp.shadedown= -128;
02105     wcol_tmp.shaded= 1;
02106     
02107     widgetbase_draw(&wtb, &wcol_tmp);
02108 
02109     /* cursor */
02110     x= rect->xmin + 0.5f * (rect->xmax-rect->xmin);
02111     y= rect->ymin + v * (rect->ymax-rect->ymin);
02112     CLAMP(y, rect->ymin+3.0f, rect->ymax-3.0f);
02113     
02114     ui_hsv_cursor(x, y);
02115     
02116 }
02117 
02118 
02119 /* ************ separator, for menus etc ***************** */
02120 static void ui_draw_separator(rcti *rect,  uiWidgetColors *wcol)
02121 {
02122     int y = rect->ymin + (rect->ymax - rect->ymin)/2 - 1;
02123     unsigned char col[4];
02124     
02125     col[0] = wcol->text[0];
02126     col[1] = wcol->text[1];
02127     col[2] = wcol->text[2];
02128     col[3] = 7;
02129     
02130     glEnable(GL_BLEND);
02131     glColor4ubv(col);
02132     sdrawline(rect->xmin, y, rect->xmax, y);
02133     glDisable(GL_BLEND);
02134 }
02135 
02136 /* ************ button callbacks, draw ***************** */
02137 
02138 static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
02139 {
02140     uiWidgetBase wtb;
02141     float rad= 0.5f*(rect->ymax - rect->ymin);
02142     float textofs = rad*0.75f;
02143 
02144     if(state & UI_SELECT)
02145         SWAP(short, wcol->shadetop, wcol->shadedown);
02146     
02147     widget_init(&wtb);
02148     
02149     /* fully rounded */
02150     round_box_edges(&wtb, roundboxalign, rect, rad);
02151     
02152     /* decoration */
02153     if(!(state & UI_TEXTINPUT)) {
02154         widget_num_tria(&wtb.tria1, rect, 0.6f, 'l');
02155         widget_num_tria(&wtb.tria2, rect, 0.6f, 'r');
02156     }
02157 
02158     widgetbase_draw(&wtb, wcol);
02159     
02160     /* text space */
02161     rect->xmin += textofs;
02162     rect->xmax -= textofs;
02163 }
02164 
02165 //static int ui_link_bezier_points(rcti *rect, float coord_array[][2], int resol)
02166 int ui_link_bezier_points(rcti *rect, float coord_array[][2], int resol)
02167 {
02168     float dist, vec[4][2];
02169 
02170     vec[0][0]= rect->xmin;
02171     vec[0][1]= rect->ymin;
02172     vec[3][0]= rect->xmax;
02173     vec[3][1]= rect->ymax;
02174     
02175     dist= 0.5f*ABS(vec[0][0] - vec[3][0]);
02176     
02177     vec[1][0]= vec[0][0]+dist;
02178     vec[1][1]= vec[0][1];
02179     
02180     vec[2][0]= vec[3][0]-dist;
02181     vec[2][1]= vec[3][1];
02182     
02183     forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, sizeof(float)*2);
02184     forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0]+1, resol, sizeof(float)*2);
02185     
02186     return 1;
02187 }
02188 
02189 #define LINK_RESOL  24
02190 void ui_draw_link_bezier(rcti *rect)
02191 {
02192     float coord_array[LINK_RESOL+1][2];
02193     
02194     if(ui_link_bezier_points(rect, coord_array, LINK_RESOL)) {
02195         /* we can reuse the dist variable here to increment the GL curve eval amount*/
02196         // const float dist= 1.0f/(float)LINK_RESOL; // UNUSED
02197 
02198         glEnable(GL_BLEND);
02199         glEnable(GL_LINE_SMOOTH);
02200 
02201         glEnableClientState(GL_VERTEX_ARRAY);
02202         glVertexPointer(2, GL_FLOAT, 0, coord_array);
02203         glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL);
02204         glDisableClientState(GL_VERTEX_ARRAY);
02205 
02206         glDisable(GL_BLEND);
02207         glDisable(GL_LINE_SMOOTH);
02208 
02209     }
02210 }
02211 
02212 /* function in use for buttons and for view2d sliders */
02213 void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int state)
02214 {
02215     uiWidgetBase wtb;
02216     float rad;
02217     int horizontal;
02218     short outline=0;
02219 
02220     widget_init(&wtb);
02221 
02222     /* determine horizontal/vertical */
02223     horizontal= (rect->xmax - rect->xmin > rect->ymax - rect->ymin);
02224     
02225     if(horizontal)
02226         rad= 0.5f*(rect->ymax - rect->ymin);
02227     else
02228         rad= 0.5f*(rect->xmax - rect->xmin);
02229     
02230     wtb.shadedir= (horizontal)? 1: 0;
02231     
02232     /* draw back part, colors swapped and shading inverted */
02233     if(horizontal)
02234         SWAP(short, wcol->shadetop, wcol->shadedown);
02235     
02236     round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
02237     widgetbase_draw(&wtb, wcol);
02238     
02239     /* slider */
02240     if(slider->xmax-slider->xmin<2 || slider->ymax-slider->ymin<2);
02241     else {
02242         
02243         SWAP(short, wcol->shadetop, wcol->shadedown);
02244         
02245         copy_v4_v4_char(wcol->inner, wcol->item);
02246         
02247         if(wcol->shadetop>wcol->shadedown)
02248             wcol->shadetop+= 20;    /* XXX violates themes... */
02249         else wcol->shadedown+= 20;
02250         
02251         if(state & UI_SCROLL_PRESSED) {
02252             wcol->inner[0]= wcol->inner[0]>=250? 255 : wcol->inner[0]+5;
02253             wcol->inner[1]= wcol->inner[1]>=250? 255 : wcol->inner[1]+5;
02254             wcol->inner[2]= wcol->inner[2]>=250? 255 : wcol->inner[2]+5;
02255         }
02256 
02257         /* draw */
02258         wtb.emboss= 0; /* only emboss once */
02259         
02260         /* exception for progress bar */
02261         if (state & UI_SCROLL_NO_OUTLINE)   
02262             SWAP(short, outline, wtb.outline);
02263         
02264         round_box_edges(&wtb, UI_CNR_ALL, slider, rad);
02265         
02266         if(state & UI_SCROLL_ARROWS) {
02267             if(wcol->item[0] > 48) wcol->item[0]-= 48;
02268             if(wcol->item[1] > 48) wcol->item[1]-= 48;
02269             if(wcol->item[2] > 48) wcol->item[2]-= 48;
02270             wcol->item[3]= 255;
02271             
02272             if(horizontal) {
02273                 widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
02274                 widget_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
02275             }
02276             else {
02277                 widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
02278                 widget_scroll_circle(&wtb.tria2, slider, 0.6f, 't');
02279             }
02280         }
02281         widgetbase_draw(&wtb, wcol);
02282         
02283         if (state & UI_SCROLL_NO_OUTLINE)
02284             SWAP(short, outline, wtb.outline);
02285     }   
02286 }
02287 
02288 static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
02289 {
02290     rcti rect1;
02291     double value;
02292     float fac, size, min;
02293     int horizontal;
02294 
02295     /* calculate slider part */
02296     value= ui_get_but_val(but);
02297 
02298     size= (but->softmax + but->a1 - but->softmin);
02299     size= MAX2(size, 2);
02300     
02301     /* position */
02302     rect1= *rect;
02303 
02304     /* determine horizontal/vertical */
02305     horizontal= (rect->xmax - rect->xmin > rect->ymax - rect->ymin);
02306     
02307     if(horizontal) {
02308         fac= (rect->xmax - rect->xmin)/(size);
02309         rect1.xmin= rect1.xmin + ceilf(fac*((float)value - but->softmin));
02310         rect1.xmax= rect1.xmin + ceilf(fac*(but->a1 - but->softmin));
02311 
02312         /* ensure minimium size */
02313         min= rect->ymax - rect->ymin;
02314 
02315         if(rect1.xmax - rect1.xmin < min) {
02316             rect1.xmax= rect1.xmin + min;
02317 
02318             if(rect1.xmax > rect->xmax) {
02319                 rect1.xmax= rect->xmax;
02320                 rect1.xmin= MAX2(rect1.xmax - min, rect->xmin);
02321             }
02322         }
02323     }
02324     else {
02325         fac= (rect->ymax - rect->ymin)/(size);
02326         rect1.ymax= rect1.ymax - ceilf(fac*((float)value - but->softmin));
02327         rect1.ymin= rect1.ymax - ceilf(fac*(but->a1 - but->softmin));
02328 
02329         /* ensure minimium size */
02330         min= rect->xmax - rect->xmin;
02331 
02332         if(rect1.ymax - rect1.ymin < min) {
02333             rect1.ymax= rect1.ymin + min;
02334 
02335             if(rect1.ymax > rect->ymax) {
02336                 rect1.ymax= rect->ymax;
02337                 rect1.ymin= MAX2(rect1.ymax - min, rect->ymin);
02338             }
02339         }
02340     }
02341 
02342     if(state & UI_SELECT)
02343         state= UI_SCROLL_PRESSED;
02344     else
02345         state= 0;
02346     uiWidgetScrollDraw(wcol, rect, &rect1, state);
02347 }
02348 
02349 static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
02350 {
02351     rcti rect_prog = *rect, rect_bar = *rect;
02352     float value = but->a1;
02353     float w, min;
02354     
02355     /* make the progress bar a proportion of the original height */
02356     /* hardcoded 4px high for now */
02357     rect_prog.ymax = rect_prog.ymin + 4;
02358     rect_bar.ymax = rect_bar.ymin + 4;
02359     
02360     w = value * (rect_prog.xmax - rect_prog.xmin);
02361     
02362     /* ensure minimium size */
02363     min= rect_prog.ymax - rect_prog.ymin;
02364     w = MAX2(w, min);
02365     
02366     rect_bar.xmax = rect_bar.xmin + w;
02367         
02368     uiWidgetScrollDraw(wcol, &rect_prog, &rect_bar, UI_SCROLL_NO_OUTLINE);
02369     
02370     /* raise text a bit */
02371     rect->ymin += 6;
02372     rect->xmin -= 6;
02373 }
02374 
02375 static void widget_link(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
02376 {
02377     
02378     if(but->flag & UI_SELECT) {
02379         rcti rectlink;
02380         
02381         UI_ThemeColor(TH_TEXT_HI);
02382         
02383         rectlink.xmin= (rect->xmin+rect->xmax)/2;
02384         rectlink.ymin= (rect->ymin+rect->ymax)/2;
02385         rectlink.xmax= but->linkto[0];
02386         rectlink.ymax= but->linkto[1];
02387         
02388         ui_draw_link_bezier(&rectlink);
02389     }
02390 }
02391 
02392 static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
02393 {
02394     uiWidgetBase wtb, wtb1;
02395     rcti rect1;
02396     double value;
02397     float offs, toffs, fac;
02398     char outline[3];
02399 
02400     widget_init(&wtb);
02401     widget_init(&wtb1);
02402     
02403     /* backdrop first */
02404     
02405     /* fully rounded */
02406     offs= 0.5f*(rect->ymax - rect->ymin);
02407     toffs = offs*0.75f;
02408     round_box_edges(&wtb, roundboxalign, rect, offs);
02409 
02410     wtb.outline= 0;
02411     widgetbase_draw(&wtb, wcol);
02412     
02413     /* draw left/right parts only when not in text editing */
02414     if(!(state & UI_TEXTINPUT)) {
02415         
02416             /* slider part */
02417         copy_v3_v3_char(outline, wcol->outline);
02418         copy_v3_v3_char(wcol->outline, wcol->item);
02419         copy_v3_v3_char(wcol->inner, wcol->item);
02420 
02421         if(!(state & UI_SELECT))
02422             SWAP(short, wcol->shadetop, wcol->shadedown);
02423         
02424         rect1= *rect;
02425         
02426         value= ui_get_but_val(but);
02427         fac= ((float)value-but->softmin)*(rect1.xmax - rect1.xmin - offs)/(but->softmax - but->softmin);
02428         
02429         /* left part of slider, always rounded */
02430         rect1.xmax= rect1.xmin + ceil(offs+1.0f);
02431         round_box_edges(&wtb1, roundboxalign & ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT), &rect1, offs);
02432         wtb1.outline= 0;
02433         widgetbase_draw(&wtb1, wcol);
02434         
02435         /* right part of slider, interpolate roundness */
02436         rect1.xmax= rect1.xmin + fac + offs;
02437         rect1.xmin+=  floor(offs-1.0f);
02438         if(rect1.xmax + offs > rect->xmax)
02439             offs*= (rect1.xmax + offs - rect->xmax)/offs;
02440         else 
02441             offs= 0.0f;
02442         round_box_edges(&wtb1, roundboxalign & ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT), &rect1, offs);
02443         
02444         widgetbase_draw(&wtb1, wcol);
02445         copy_v3_v3_char(wcol->outline, outline);
02446         
02447         if(!(state & UI_SELECT))
02448             SWAP(short, wcol->shadetop, wcol->shadedown);
02449     }
02450     
02451     /* outline */
02452     wtb.outline= 1;
02453     wtb.inner= 0;
02454     widgetbase_draw(&wtb, wcol);
02455     
02456     /* text space */
02457     rect->xmin += toffs;
02458     rect->xmax -= toffs;
02459 }
02460 
02461 /* I think 3 is sufficient border to indicate keyed status */
02462 #define SWATCH_KEYED_BORDER 3
02463 
02464 static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
02465 {
02466     uiWidgetBase wtb;
02467     float col[4];
02468     int color_profile = but->block->color_profile;
02469     
02470     col[3]= 1.0f;
02471 
02472     if (but->rnaprop) {
02473         if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
02474             color_profile = BLI_PR_NONE;
02475 
02476         if(RNA_property_array_length(&but->rnapoin, but->rnaprop)==4) {
02477             col[3]= RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
02478         }
02479     }
02480     
02481     widget_init(&wtb);
02482     
02483     /* half rounded */
02484     round_box_edges(&wtb, roundboxalign, rect, 5.0f);
02485         
02486     ui_get_but_vectorf(but, col);
02487     
02488     if(state & (UI_BUT_ANIMATED|UI_BUT_ANIMATED_KEY|UI_BUT_DRIVEN|UI_BUT_REDALERT)) {
02489         // draw based on state - color for keyed etc
02490         widgetbase_draw(&wtb, wcol);
02491         
02492         // inset to draw swatch color
02493         rect->xmin+= SWATCH_KEYED_BORDER;
02494         rect->xmax-= SWATCH_KEYED_BORDER;
02495         rect->ymin+= SWATCH_KEYED_BORDER;
02496         rect->ymax-= SWATCH_KEYED_BORDER;
02497         
02498         round_box_edges(&wtb, roundboxalign, rect, 5.0f);
02499     }
02500     
02501     if (color_profile)
02502         linearrgb_to_srgb_v3_v3(col, col);
02503     
02504     F4TOCHAR4(col, wcol->inner);
02505 
02506     wcol->shaded = 0;
02507     wcol->alpha_check = (wcol->inner[3] < 255);
02508 
02509     widgetbase_draw(&wtb, wcol);
02510     
02511 }
02512 
02513 static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
02514 {
02515     if(state & (UI_BUT_ANIMATED|UI_BUT_ANIMATED_KEY|UI_BUT_DRIVEN|UI_BUT_REDALERT)) {
02516         uiWidgetBase wtb;
02517     
02518         widget_init(&wtb);
02519         wtb.outline= 0;
02520         
02521         /* rounded */
02522         round_box_edges(&wtb, UI_CNR_ALL, rect, 10.0f);
02523         widgetbase_draw(&wtb, wcol);
02524     }   
02525 }
02526 
02527 
02528 static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
02529 {
02530     uiWidgetBase wtb;
02531     
02532     if(state & UI_SELECT)
02533         SWAP(short, wcol->shadetop, wcol->shadedown);
02534     
02535     widget_init(&wtb);
02536     
02537     /* half rounded */
02538     round_box_edges(&wtb, roundboxalign, rect, 4.0f);
02539     
02540     widgetbase_draw(&wtb, wcol);
02541 
02542 }
02543 
02544 
02545 static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
02546 {
02547     uiWidgetBase wtb;
02548     
02549     widget_init(&wtb);
02550     
02551     /* half rounded */
02552     round_box_edges(&wtb, roundboxalign, rect, 4.0f);
02553     
02554     /* decoration */
02555     widget_menu_trias(&wtb.tria1, rect);
02556     
02557     widgetbase_draw(&wtb, wcol);
02558     
02559     /* text space */
02560     rect->xmax -= (rect->ymax-rect->ymin);
02561 }
02562 
02563 static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
02564 {
02565     uiWidgetBase wtb;
02566     
02567     widget_init(&wtb);
02568     
02569     /* half rounded */
02570     round_box_edges(&wtb, roundboxalign, rect, 4.0f);
02571     
02572     /* decoration */
02573     widgetbase_draw(&wtb, wcol);
02574 }
02575 
02576 static void widget_menunodebut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
02577 {
02578     /* silly node link button hacks */
02579     uiWidgetBase wtb;
02580     uiWidgetColors wcol_backup= *wcol;
02581     
02582     widget_init(&wtb);
02583     
02584     /* half rounded */
02585     round_box_edges(&wtb, roundboxalign, rect, 4.0f);
02586 
02587     wcol->inner[0] += 15;
02588     wcol->inner[1] += 15;
02589     wcol->inner[2] += 15;
02590     wcol->outline[0] += 15;
02591     wcol->outline[1] += 15;
02592     wcol->outline[2] += 15;
02593     
02594     /* decoration */
02595     widgetbase_draw(&wtb, wcol);
02596     *wcol= wcol_backup;
02597 }
02598 
02599 static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
02600 {
02601     if(state & UI_ACTIVE) {
02602         uiWidgetBase wtb;
02603         float rad= 0.5f*(rect->ymax - rect->ymin); // 4.0f
02604         
02605         widget_init(&wtb);
02606         
02607         /* half rounded */
02608         round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
02609         
02610         widgetbase_draw(&wtb, wcol);
02611     }
02612 }
02613 
02614 static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
02615 {
02616     uiWidgetBase wtb;
02617     
02618     widget_init(&wtb);
02619     
02620     /* not rounded, no outline */
02621     wtb.outline= 0;
02622     round_box_edges(&wtb, 0, rect, 0.0f);
02623     
02624     widgetbase_draw(&wtb, wcol);
02625 }
02626 
02627 static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
02628 {
02629     uiWidgetBase wtb;
02630     
02631     widget_init(&wtb);
02632     
02633     /* rounded, but no outline */
02634     wtb.outline= 0;
02635     round_box_edges(&wtb, UI_CNR_ALL, rect, 4.0f);
02636     
02637     widgetbase_draw(&wtb, wcol);
02638 }
02639 
02640 static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
02641 {
02642     uiWidgetBase wtb;
02643     rcti recttemp= *rect;
02644     int delta;
02645     
02646     widget_init(&wtb);
02647     
02648     /* square */
02649     recttemp.xmax= recttemp.xmin + (recttemp.ymax-recttemp.ymin);
02650     
02651     /* smaller */
02652     delta= 1 + (recttemp.ymax-recttemp.ymin)/8;
02653     recttemp.xmin+= delta;
02654     recttemp.ymin+= delta;
02655     recttemp.xmax-= delta;
02656     recttemp.ymax-= delta;
02657     
02658     /* half rounded */
02659     round_box_edges(&wtb, UI_CNR_ALL, &recttemp, 4.0f);
02660     
02661     /* decoration */
02662     if(state & UI_SELECT) {
02663         widget_check_trias(&wtb.tria1, &recttemp);
02664     }
02665     
02666     widgetbase_draw(&wtb, wcol);
02667     
02668     /* text space */
02669     rect->xmin += (rect->ymax-rect->ymin)*0.7 + delta;
02670 }
02671 
02672 
02673 static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
02674 {
02675     uiWidgetBase wtb;
02676     
02677     widget_init(&wtb);
02678     
02679     /* half rounded */
02680     round_box_edges(&wtb, roundboxalign, rect, 4.0f);
02681     
02682     widgetbase_draw(&wtb, wcol);
02683 
02684 }
02685 
02686 static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
02687 {
02688     uiWidgetBase wtb;
02689     char old_col[3];
02690     
02691     widget_init(&wtb);
02692     
02693     copy_v3_v3_char(old_col, wcol->inner);
02694     
02695     /* abuse but->hsv - if it's non-zero, use this color as the box's background */
02696     if (but->col[3]) {
02697         wcol->inner[0] = but->col[0];
02698         wcol->inner[1] = but->col[1];
02699         wcol->inner[2] = but->col[2];
02700     }
02701     
02702     /* half rounded */
02703     round_box_edges(&wtb, roundboxalign, rect, 4.0f);
02704     
02705     widgetbase_draw(&wtb, wcol);
02706     
02707     /* store the box bg as gl clearcolor, to retrieve later when drawing semi-transparent rects
02708      * over the top to indicate disabled buttons */
02709     /* XXX, this doesnt work right since the color applies to buttons outside the box too. */
02710     glClearColor(wcol->inner[0]/255.0, wcol->inner[1]/255.0, wcol->inner[2]/255.0, 1.0);
02711     
02712     copy_v3_v3_char(wcol->inner, old_col);
02713 }
02714 
02715 static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
02716 {
02717     uiWidgetBase wtb;
02718     
02719     widget_init(&wtb);
02720     
02721     /* half rounded */
02722     round_box_edges(&wtb, roundboxalign, rect, 4.0f);
02723         
02724     widgetbase_draw(&wtb, wcol);
02725 
02726 }
02727 
02728 static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
02729 {
02730     uiWidgetBase wtb;
02731     float rad= 5.0f; //0.5f*(rect->ymax - rect->ymin);
02732     
02733     widget_init(&wtb);
02734     
02735     /* half rounded */
02736     round_box_edges(&wtb, roundboxalign, rect, rad);
02737 
02738     widgetbase_draw(&wtb, wcol);
02739 }
02740 
02741 static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
02742 {
02743     uiWidgetBase wtb;
02744     unsigned char col[4];
02745     
02746     /* state copy! */
02747     wt->wcol= *(wt->wcol_theme);
02748     
02749     widget_init(&wtb);
02750     
02751     if(but->block->drawextra) {
02752         /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
02753         but->block->drawextra(C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect);
02754         
02755         /* make mask to draw over image */
02756         UI_GetThemeColor3ubv(TH_BACK, col);
02757         glColor3ubv(col);
02758         
02759         round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, 4.0);
02760         widgetbase_outline(&wtb);
02761     }
02762     
02763     /* outline */
02764     round_box_edges(&wtb, UI_CNR_ALL, rect, 5.0f);
02765     wtb.outline= 1;
02766     wtb.inner= 0;
02767     widgetbase_draw(&wtb, &wt->wcol);
02768     
02769 }
02770 
02771 
02772 static void widget_disabled(rcti *rect)
02773 {
02774     float col[4];
02775     
02776     glEnable(GL_BLEND);
02777     
02778     /* can't use theme TH_BACK or TH_PANEL... undefined */
02779     glGetFloatv(GL_COLOR_CLEAR_VALUE, col);
02780     glColor4f(col[0], col[1], col[2], 0.5f);
02781 
02782     /* need -1 and +1 to make it work right for aligned buttons,
02783      * but problem may be somewhere else? */
02784     glRectf(rect->xmin-1, rect->ymin-1, rect->xmax, rect->ymax+1);
02785     
02786     glDisable(GL_BLEND);
02787 }
02788 
02789 static uiWidgetType *widget_type(uiWidgetTypeEnum type)
02790 {
02791     bTheme *btheme= UI_GetTheme();
02792     static uiWidgetType wt;
02793     
02794     /* defaults */
02795     wt.wcol_theme= &btheme->tui.wcol_regular;
02796     wt.wcol_state= &btheme->tui.wcol_state;
02797     wt.state= widget_state;
02798     wt.draw= widget_but;
02799     wt.custom= NULL;
02800     wt.text= widget_draw_text_icon;
02801     
02802     switch(type) {
02803         case UI_WTYPE_REGULAR:
02804             break;
02805 
02806         case UI_WTYPE_LABEL:
02807             wt.draw= NULL;
02808             wt.state= widget_state_label;
02809             break;
02810             
02811         case UI_WTYPE_TOGGLE:
02812             wt.wcol_theme= &btheme->tui.wcol_toggle;
02813             break;
02814             
02815         case UI_WTYPE_OPTION:
02816             wt.wcol_theme= &btheme->tui.wcol_option;
02817             wt.draw= widget_optionbut;
02818             break;
02819             
02820         case UI_WTYPE_RADIO:
02821             wt.wcol_theme= &btheme->tui.wcol_radio;
02822             wt.draw= widget_radiobut;
02823             break;
02824 
02825         case UI_WTYPE_NUMBER:
02826             wt.wcol_theme= &btheme->tui.wcol_num;
02827             wt.draw= widget_numbut;
02828             break;
02829             
02830         case UI_WTYPE_SLIDER:
02831             wt.wcol_theme= &btheme->tui.wcol_numslider;
02832             wt.custom= widget_numslider;
02833             wt.state= widget_state_numslider;
02834             break;
02835             
02836         case UI_WTYPE_EXEC:
02837             wt.wcol_theme= &btheme->tui.wcol_tool;
02838             wt.draw= widget_roundbut;
02839             break;
02840             
02841             
02842             /* strings */
02843         case UI_WTYPE_NAME:
02844             wt.wcol_theme= &btheme->tui.wcol_text;
02845             wt.draw= widget_textbut;
02846             break;
02847             
02848         case UI_WTYPE_NAME_LINK:
02849             break;
02850             
02851         case UI_WTYPE_POINTER_LINK:
02852             break;
02853             
02854         case UI_WTYPE_FILENAME:
02855             break;
02856             
02857             
02858             /* start menus */
02859         case UI_WTYPE_MENU_RADIO:
02860             wt.wcol_theme= &btheme->tui.wcol_menu;
02861             wt.draw= widget_menubut;
02862             break;
02863 
02864         case UI_WTYPE_MENU_ICON_RADIO:
02865             wt.wcol_theme= &btheme->tui.wcol_menu;
02866             wt.draw= widget_menuiconbut;
02867             break;
02868             
02869         case UI_WTYPE_MENU_POINTER_LINK:
02870             wt.wcol_theme= &btheme->tui.wcol_menu;
02871             wt.draw= widget_menubut;
02872             break;
02873 
02874         case UI_WTYPE_MENU_NODE_LINK:
02875             wt.wcol_theme= &btheme->tui.wcol_menu;
02876             wt.draw= widget_menunodebut;
02877             break;
02878             
02879         case UI_WTYPE_PULLDOWN:
02880             wt.wcol_theme= &btheme->tui.wcol_pulldown;
02881             wt.draw= widget_pulldownbut;
02882             wt.state= widget_state_pulldown;
02883             break;
02884             
02885             /* in menus */
02886         case UI_WTYPE_MENU_ITEM:
02887             wt.wcol_theme= &btheme->tui.wcol_menu_item;
02888             wt.draw= widget_menu_itembut;
02889             wt.state= widget_state_menu_item;
02890             break;
02891             
02892         case UI_WTYPE_MENU_BACK:
02893             wt.wcol_theme= &btheme->tui.wcol_menu_back;
02894             wt.draw= widget_menu_back;
02895             break;
02896             
02897             /* specials */
02898         case UI_WTYPE_ICON:
02899             wt.custom= widget_icon_has_anim;
02900             break;
02901             
02902         case UI_WTYPE_SWATCH:
02903             wt.custom= widget_swatch;
02904             break;
02905             
02906         case UI_WTYPE_BOX:
02907             wt.custom= widget_box;
02908             wt.wcol_theme= &btheme->tui.wcol_box;
02909             break;
02910             
02911         case UI_WTYPE_RGB_PICKER:
02912             break;
02913             
02914         case UI_WTYPE_NORMAL:
02915             break;
02916 
02917         case UI_WTYPE_SCROLL:
02918             wt.wcol_theme= &btheme->tui.wcol_scroll;
02919             wt.state= widget_state_nothing;
02920             wt.custom= widget_scroll;
02921             break;
02922 
02923         case UI_WTYPE_LISTITEM:
02924             wt.wcol_theme= &btheme->tui.wcol_list_item;
02925             wt.draw= widget_list_itembut;
02926             break;
02927             
02928         case UI_WTYPE_PROGRESSBAR:
02929             wt.wcol_theme= &btheme->tui.wcol_progress;
02930             wt.custom= widget_progressbar;
02931             break;
02932     }
02933     
02934     return &wt;
02935 }
02936 
02937 
02938 static int widget_roundbox_set(uiBut *but, rcti *rect)
02939 {
02940     /* alignment */
02941     if(but->flag & UI_BUT_ALIGN) {
02942         
02943         if(but->flag & UI_BUT_ALIGN_TOP)
02944             rect->ymax+= 1;
02945         if(but->flag & UI_BUT_ALIGN_LEFT)
02946             rect->xmin-= 1;
02947         
02948         switch(but->flag & UI_BUT_ALIGN) {
02949             case UI_BUT_ALIGN_TOP:
02950                 return UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT;
02951             case UI_BUT_ALIGN_DOWN:
02952                 return UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
02953             case UI_BUT_ALIGN_LEFT:
02954                 return UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT;
02955             case UI_BUT_ALIGN_RIGHT:
02956                 return UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT;
02957             case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_RIGHT:
02958                 return UI_CNR_TOP_LEFT;
02959             case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT:
02960                 return UI_CNR_TOP_RIGHT;
02961             case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT:
02962                 return UI_CNR_BOTTOM_LEFT;
02963             case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT:
02964                 return UI_CNR_BOTTOM_RIGHT;
02965             default:
02966                 return 0;
02967         }
02968     }
02969 
02970     return UI_CNR_ALL;
02971 }
02972 
02973 /* conversion from old to new buttons, so still messy */
02974 void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
02975 {
02976     bTheme *btheme= UI_GetTheme();
02977     ThemeUI *tui= &btheme->tui;
02978     uiFontStyle *fstyle= &style->widget;
02979     uiWidgetType *wt= NULL;
02980 
02981     /* handle menus separately */
02982     if(but->dt==UI_EMBOSSP) {
02983         switch (but->type) {
02984             case LABEL:
02985                 widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
02986                 break;
02987             case SEPR:
02988                 ui_draw_separator(rect, &tui->wcol_menu_item);
02989                 break;
02990                 
02991             default:
02992                 wt= widget_type(UI_WTYPE_MENU_ITEM);
02993         }
02994     }
02995     else if(but->dt==UI_EMBOSSN) {
02996         /* "nothing" */
02997         wt= widget_type(UI_WTYPE_ICON);
02998     }
02999     else {
03000         
03001         switch (but->type) {
03002             case LABEL:
03003                 if(but->block->flag & UI_BLOCK_LOOP)
03004                     widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
03005                 else {
03006                     wt= widget_type(UI_WTYPE_LABEL);
03007                     fstyle= &style->widgetlabel;
03008                 }
03009                 break;
03010                 
03011             case SEPR:
03012                 break;
03013                 
03014             case BUT:
03015                 wt= widget_type(UI_WTYPE_EXEC);
03016                 break;
03017 
03018             case NUM:
03019                 wt= widget_type(UI_WTYPE_NUMBER);
03020                 break;
03021                 
03022             case NUMSLI:
03023             case HSVSLI:
03024                 wt= widget_type(UI_WTYPE_SLIDER);
03025                 break;
03026                 
03027             case ROW:
03028                 wt= widget_type(UI_WTYPE_RADIO);
03029                 break;
03030 
03031             case LISTROW:
03032                 wt= widget_type(UI_WTYPE_LISTITEM);
03033                 break;
03034                 
03035             case TEX:
03036                 wt= widget_type(UI_WTYPE_NAME);
03037                 break;
03038                 
03039             case SEARCH_MENU:
03040                 wt= widget_type(UI_WTYPE_NAME);
03041                 if(but->block->flag & UI_BLOCK_LOOP)
03042                     wt->wcol_theme= &btheme->tui.wcol_menu_back;
03043                 break;
03044                 
03045             case TOGBUT:
03046             case TOG:
03047             case TOGN:
03048             case TOG3:
03049                 wt= widget_type(UI_WTYPE_TOGGLE);
03050                 break;
03051                 
03052             case OPTION:
03053             case OPTIONN:
03054                 if (!(but->flag & UI_HAS_ICON)) {
03055                     wt= widget_type(UI_WTYPE_OPTION);
03056                     but->flag |= UI_TEXT_LEFT;
03057                 }
03058                 else
03059                     wt= widget_type(UI_WTYPE_TOGGLE);
03060                 
03061                 /* option buttons have strings outside, on menus use different colors */
03062                 if(but->block->flag & UI_BLOCK_LOOP)
03063                     wt->state= widget_state_option_menu;
03064                 
03065                 break;
03066                 
03067             case MENU:
03068             case BLOCK:
03069             case ICONTEXTROW:
03070                 if(but->flag & UI_BUT_NODE_LINK)
03071                     wt= widget_type(UI_WTYPE_MENU_NODE_LINK);
03072                 else if(!but->str[0] && but->icon)
03073                     wt= widget_type(UI_WTYPE_MENU_ICON_RADIO);
03074                 else
03075                     wt= widget_type(UI_WTYPE_MENU_RADIO);
03076                 break;
03077                 
03078             case PULLDOWN:
03079                 wt= widget_type(UI_WTYPE_PULLDOWN);
03080                 break;
03081             
03082             case BUTM:
03083                 wt= widget_type(UI_WTYPE_MENU_ITEM);
03084                 break;
03085                 
03086             case COL:
03087                 wt= widget_type(UI_WTYPE_SWATCH);
03088                 break;
03089                 
03090             case ROUNDBOX:
03091             case LISTBOX:
03092                 wt= widget_type(UI_WTYPE_BOX);
03093                 break;
03094                 
03095             case LINK:
03096             case INLINK:
03097                 wt= widget_type(UI_WTYPE_ICON);
03098                 wt->custom= widget_link;
03099                 
03100                 break;
03101             
03102             case BUT_EXTRA:
03103                 widget_draw_extra_mask(C, but, widget_type(UI_WTYPE_BOX), rect);
03104                 break;
03105                 
03106             case HSVCUBE:
03107                 if(but->a1 == UI_GRAD_V_ALT) // vertical V slider, uses new widget draw now
03108                     ui_draw_but_HSV_v(but, rect);
03109                 else  // other HSV pickers...
03110                     ui_draw_but_HSVCUBE(but, rect);
03111                 break;
03112                 
03113             case HSVCIRCLE:
03114                 ui_draw_but_HSVCIRCLE(but, &tui->wcol_regular, rect);
03115                 break;
03116                 
03117             case BUT_COLORBAND:
03118                 ui_draw_but_COLORBAND(but, &tui->wcol_regular, rect);
03119                 break;
03120                 
03121             case BUT_NORMAL:
03122                 ui_draw_but_NORMAL(but, &tui->wcol_regular, rect);
03123                 break;
03124                 
03125             case BUT_IMAGE:
03126                 ui_draw_but_IMAGE(ar, but, &tui->wcol_regular, rect);
03127                 break;
03128             
03129             case HISTOGRAM:
03130                 ui_draw_but_HISTOGRAM(ar, but, &tui->wcol_regular, rect);
03131                 break;
03132                 
03133             case WAVEFORM:
03134                 ui_draw_but_WAVEFORM(ar, but, &tui->wcol_regular, rect);
03135                 break;
03136                 
03137             case VECTORSCOPE:
03138                 ui_draw_but_VECTORSCOPE(ar, but, &tui->wcol_regular, rect);
03139                 break;
03140                     
03141             case BUT_CURVE:
03142                 ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect);
03143                 break;
03144                 
03145             case PROGRESSBAR:
03146                 wt= widget_type(UI_WTYPE_PROGRESSBAR);
03147                 fstyle= &style->widgetlabel;
03148                 break;
03149 
03150             case SCROLL:
03151                 wt= widget_type(UI_WTYPE_SCROLL);
03152                 break;
03153 
03154             case TRACKPREVIEW:
03155                 ui_draw_but_TRACKPREVIEW(ar, but, &tui->wcol_regular, rect);
03156                 break;
03157 
03158             default:
03159                 wt= widget_type(UI_WTYPE_REGULAR);
03160         }
03161     }
03162     
03163     if(wt) {
03164         rcti disablerect= *rect; /* rect gets clipped smaller for text */
03165         int roundboxalign, state;
03166         
03167         roundboxalign= widget_roundbox_set(but, rect);
03168 
03169         state= but->flag;
03170         if(but->editstr) state |= UI_TEXTINPUT;
03171         
03172         wt->state(wt, state);
03173         if(wt->custom)
03174             wt->custom(but, &wt->wcol, rect, state, roundboxalign);
03175         else if(wt->draw)
03176             wt->draw(&wt->wcol, rect, state, roundboxalign);
03177         wt->text(fstyle, &wt->wcol, but, rect);
03178         
03179         if(state & (UI_BUT_DISABLED|UI_BUT_INACTIVE))
03180             if(but->dt!=UI_EMBOSSP)
03181                 widget_disabled(&disablerect);
03182     }
03183 }
03184 
03185 void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
03186 {
03187     uiWidgetType *wt= widget_type(UI_WTYPE_MENU_BACK);
03188     
03189     wt->state(wt, 0);
03190     if(block)
03191         wt->draw(&wt->wcol, rect, block->flag, block->direction);
03192     else
03193         wt->draw(&wt->wcol, rect, 0, 0);
03194     
03195     if(block) {
03196         if(block->flag & UI_BLOCK_CLIPTOP) {
03197             /* XXX no scaling for UI here yet */
03198             glColor3ubv((unsigned char*)wt->wcol.text);
03199             UI_DrawTriIcon((rect->xmax+rect->xmin)/2, rect->ymax-8, 't');
03200         }
03201         if(block->flag & UI_BLOCK_CLIPBOTTOM) {
03202             /* XXX no scaling for UI here yet */
03203             glColor3ubv((unsigned char*)wt->wcol.text);
03204             UI_DrawTriIcon((rect->xmax+rect->xmin)/2, rect->ymin+10, 'v');
03205         }
03206     }   
03207 }
03208 
03209 void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
03210 {
03211     uiWidgetType *wt= widget_type(UI_WTYPE_BOX);
03212     
03213     glEnable(GL_BLEND);
03214     widget_softshadow(rect, UI_CNR_ALL, 5.0f, 8.0f);
03215     glDisable(GL_BLEND);
03216 
03217     wt->state(wt, 0);
03218     if(block)
03219         wt->draw(&wt->wcol, rect, block->flag, UI_CNR_ALL);
03220     else
03221         wt->draw(&wt->wcol, rect, 0, UI_CNR_ALL);
03222     
03223 }
03224 
03225 
03226 /* helper call to draw a menu item without button */
03227 /* state: UI_ACTIVE or 0 */
03228 void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state)
03229 {
03230     uiWidgetType *wt= widget_type(UI_WTYPE_MENU_ITEM);
03231     rcti _rect= *rect;
03232     char *cpoin;
03233     
03234     wt->state(wt, state);
03235     wt->draw(&wt->wcol, rect, 0, 0);
03236     
03237     uiStyleFontSet(fstyle);
03238     fstyle->align= UI_STYLE_TEXT_LEFT;
03239     
03240     /* text location offset */
03241     rect->xmin+=5;
03242     if(iconid) rect->xmin+= UI_DPI_ICON_SIZE;
03243 
03244     /* cut string in 2 parts? */
03245     cpoin= strchr(name, '|');
03246     if(cpoin) {
03247         *cpoin= 0;
03248         rect->xmax -= BLF_width(fstyle->uifont_id, cpoin+1) + 10;
03249     }
03250     
03251     glColor3ubv((unsigned char*)wt->wcol.text);
03252     uiStyleFontDraw(fstyle, rect, name);
03253     
03254     /* part text right aligned */
03255     if(cpoin) {
03256         fstyle->align= UI_STYLE_TEXT_RIGHT;
03257         rect->xmax= _rect.xmax - 5;
03258         uiStyleFontDraw(fstyle, rect, cpoin+1);
03259         *cpoin= '|';
03260     }
03261     
03262     /* restore rect, was messed with */
03263     *rect= _rect;
03264 
03265     if(iconid) {
03266         int xs= rect->xmin+4;
03267         int ys= 1 + (rect->ymin+rect->ymax- UI_DPI_ICON_SIZE)/2;
03268         glEnable(GL_BLEND);
03269         UI_icon_draw_aspect(xs, ys, iconid, 1.2f, 0.5f); /* XXX scale weak get from fstyle? */
03270         glDisable(GL_BLEND);
03271     }
03272 }
03273 
03274 void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state)
03275 {
03276     rcti trect = *rect;
03277     float font_dims[2] = {0.0f, 0.0f};
03278     uiWidgetType *wt= widget_type(UI_WTYPE_MENU_ITEM);
03279     
03280     wt->state(wt, state);
03281     wt->draw(&wt->wcol, rect, 0, 0);
03282     
03283     widget_draw_preview(iconid, 1.0f, rect);
03284     
03285     if (state == UI_ACTIVE)
03286         glColor3ubv((unsigned char*)wt->wcol.text);
03287     else
03288         glColor3ubv((unsigned char*)wt->wcol.text_sel);
03289 
03290     BLF_width_and_height(fstyle->uifont_id, name, &font_dims[0], &font_dims[1]);
03291 
03292     trect.xmin += 0;
03293     trect.xmax = trect.xmin + font_dims[0] + 10;
03294     trect.ymin += 10;
03295     trect.ymax = trect.ymin + font_dims[1];
03296     uiStyleFontDraw(fstyle, &trect, name);
03297 }