Blender V2.61 - r43446

interface_icons.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) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * Contributors: Blender Foundation, full recode
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include <math.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 
00035 #ifndef WIN32
00036 #include <unistd.h>
00037 #else
00038 #include <io.h>
00039 #include <direct.h>
00040 #include "BLI_winstuff.h"
00041 #endif   
00042 #include "MEM_guardedalloc.h"
00043 
00044 #include "GPU_extensions.h"
00045 
00046 #include "BLI_math.h"
00047 #include "BLI_blenlib.h"
00048 #include "BLI_utildefines.h"
00049 
00050 #include "DNA_brush_types.h"
00051 #include "DNA_object_types.h"
00052 #include "DNA_screen_types.h"
00053 #include "DNA_space_types.h"
00054 
00055 #include "RNA_access.h"
00056 #include "RNA_enum_types.h"
00057 
00058 #include "BKE_context.h"
00059 #include "BKE_global.h"
00060 #include "BKE_icons.h"
00061 #include "BKE_utildefines.h"
00062 
00063 #include "IMB_imbuf.h"
00064 #include "IMB_imbuf_types.h"
00065 
00066 #include "BIF_gl.h"
00067 #include "BIF_glutil.h"
00068 
00069 #include "ED_datafiles.h"
00070 #include "ED_render.h"
00071 
00072 #include "UI_interface.h"
00073 #include "UI_interface_icons.h"
00074 
00075 #include "interface_intern.h"
00076 
00077 
00078 #define ICON_IMAGE_W        600
00079 #define ICON_IMAGE_H        640
00080 
00081 #define ICON_GRID_COLS      26
00082 #define ICON_GRID_ROWS      30
00083 
00084 #define ICON_GRID_MARGIN    5
00085 #define ICON_GRID_W     16
00086 #define ICON_GRID_H     16
00087 
00088 typedef struct IconImage {
00089     int w;
00090     int h;
00091     unsigned int *rect; 
00092 } IconImage;
00093 
00094 typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
00095 
00096 #define ICON_TYPE_PREVIEW   0
00097 #define ICON_TYPE_TEXTURE   1
00098 #define ICON_TYPE_BUFFER    2
00099 #define ICON_TYPE_VECTOR    3
00100 
00101 typedef struct DrawInfo {
00102     int type;
00103 
00104     union {
00105         /* type specific data */
00106         struct {
00107             VectorDrawFunc func;
00108         } vector;
00109         struct {
00110             IconImage* image;
00111         } buffer;
00112         struct {
00113             int x, y, w, h;
00114         } texture;
00115     } data;
00116 } DrawInfo;
00117 
00118 typedef struct IconTexture {
00119     GLuint id;
00120     int w;
00121     int h;
00122     float invw;
00123     float invh;
00124 } IconTexture;
00125 
00126 /* ******************* STATIC LOCAL VARS ******************* */
00127 /* static here to cache results of icon directory scan, so it's not 
00128  * scanning the filesystem each time the menu is drawn */
00129 static struct ListBase iconfilelist = {NULL, NULL};
00130 static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f};
00131 
00132 /* **************************************************** */
00133 
00134 static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type)
00135 {
00136     Icon *new_icon = NULL;
00137     IconImage *iimg = NULL;
00138     DrawInfo *di;
00139     int y = 0;
00140     int imgsize = 0;
00141 
00142     new_icon = MEM_callocN(sizeof(Icon), "texicon");
00143 
00144     new_icon->obj = NULL; /* icon is not for library object */
00145     new_icon->type = 0; 
00146 
00147     di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
00148     di->type= type;
00149 
00150     if(type == ICON_TYPE_TEXTURE) {
00151         di->data.texture.x= xofs;
00152         di->data.texture.y= yofs;
00153         di->data.texture.w= size;
00154         di->data.texture.h= size;
00155     }
00156     else if(type == ICON_TYPE_BUFFER) {
00157         iimg = MEM_mallocN(sizeof(IconImage), "icon_img");
00158         iimg->rect = MEM_mallocN(size*size*sizeof(unsigned int), "icon_rect");
00159         iimg->w = size;
00160         iimg->h = size;
00161 
00162         /* Here we store the rect in the icon - same as before */
00163         imgsize = bbuf->x;
00164         for (y=0; y<size; y++) {
00165             memcpy(&iimg->rect[y*size], &bbuf->rect[(y+yofs)*imgsize+xofs], size*sizeof(int));
00166         }
00167 
00168         di->data.buffer.image = iimg;
00169     }
00170 
00171     new_icon->drawinfo_free = UI_icons_free_drawinfo;
00172     new_icon->drawinfo = di;
00173 
00174     BKE_icon_set(icon_id, new_icon);
00175 }
00176 
00177 static void def_internal_vicon( int icon_id, VectorDrawFunc drawFunc)
00178 {
00179     Icon *new_icon = NULL;
00180     DrawInfo* di;
00181 
00182     new_icon = MEM_callocN(sizeof(Icon), "texicon");
00183 
00184     new_icon->obj = NULL; /* icon is not for library object */
00185     new_icon->type = 0;
00186 
00187     di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
00188     di->type= ICON_TYPE_VECTOR;
00189     di->data.vector.func =drawFunc;
00190 
00191     new_icon->drawinfo_free = NULL;
00192     new_icon->drawinfo = di;
00193 
00194     BKE_icon_set(icon_id, new_icon);
00195 }
00196 
00197 /* Vector Icon Drawing Routines */
00198 
00199     /* Utilities */
00200 
00201 static void viconutil_set_point(GLint pt[2], int x, int y)
00202 {
00203     pt[0] = x;
00204     pt[1] = y;
00205 }
00206 
00207 static void viconutil_draw_tri(GLint (*pts)[2])
00208 {
00209     glBegin(GL_TRIANGLES);
00210     glVertex2iv(pts[0]);
00211     glVertex2iv(pts[1]);
00212     glVertex2iv(pts[2]);
00213     glEnd();
00214 }
00215 
00216 static void viconutil_draw_lineloop(GLint (*pts)[2], int numPoints)
00217 {
00218     int i;
00219 
00220     glBegin(GL_LINE_LOOP);
00221     for (i=0; i<numPoints; i++) {
00222         glVertex2iv(pts[i]);
00223     }
00224     glEnd();
00225 }
00226 
00227 static void viconutil_draw_lineloop_smooth(GLint (*pts)[2], int numPoints)
00228 {
00229     glEnable(GL_LINE_SMOOTH);
00230     viconutil_draw_lineloop(pts, numPoints);
00231     glDisable(GL_LINE_SMOOTH);
00232 }
00233 
00234 static void viconutil_draw_points(GLint (*pts)[2], int numPoints, int pointSize)
00235 {
00236     int i;
00237 
00238     glBegin(GL_QUADS);
00239     for (i=0; i<numPoints; i++) {
00240         int x = pts[i][0], y = pts[i][1];
00241 
00242         glVertex2i(x-pointSize,y-pointSize);
00243         glVertex2i(x+pointSize,y-pointSize);
00244         glVertex2i(x+pointSize,y+pointSize);
00245         glVertex2i(x-pointSize,y+pointSize);
00246     }
00247     glEnd();
00248 }
00249 
00250     /* Drawing functions */
00251 
00252 static void vicon_x_draw(int x, int y, int w, int h, float alpha)
00253 {
00254     x += 3;
00255     y += 3;
00256     w -= 6;
00257     h -= 6;
00258 
00259     glEnable( GL_LINE_SMOOTH );
00260 
00261     glLineWidth(2.5);
00262     
00263     glColor4f(0.0, 0.0, 0.0, alpha);
00264     glBegin(GL_LINES);
00265     glVertex2i(x  ,y  );
00266     glVertex2i(x+w,y+h);
00267     glVertex2i(x+w,y  );
00268     glVertex2i(x  ,y+h);
00269     glEnd();
00270 
00271     glLineWidth(1.0);
00272     
00273     glDisable( GL_LINE_SMOOTH );
00274 }
00275 
00276 static void vicon_view3d_draw(int x, int y, int w, int h, float alpha)
00277 {
00278     int cx = x + w/2;
00279     int cy = y + h/2;
00280     int d = MAX2(2, h/3);
00281 
00282     glColor4f(0.5, 0.5, 0.5, alpha);
00283     glBegin(GL_LINES);
00284     glVertex2i(x  , cy-d);
00285     glVertex2i(x+w, cy-d);
00286     glVertex2i(x  , cy+d);
00287     glVertex2i(x+w, cy+d);
00288 
00289     glVertex2i(cx-d, y  );
00290     glVertex2i(cx-d, y+h);
00291     glVertex2i(cx+d, y  );
00292     glVertex2i(cx+d, y+h);
00293     glEnd();
00294     
00295     glColor4f(0.0, 0.0, 0.0, alpha);
00296     glBegin(GL_LINES);
00297     glVertex2i(x  , cy);
00298     glVertex2i(x+w, cy);
00299     glVertex2i(cx, y  );
00300     glVertex2i(cx, y+h);
00301     glEnd();
00302 }
00303 
00304 static void vicon_edit_draw(int x, int y, int w, int h, float alpha)
00305 {
00306     GLint pts[4][2];
00307 
00308     viconutil_set_point(pts[0], x+3  , y+3  );
00309     viconutil_set_point(pts[1], x+w-3, y+3  );
00310     viconutil_set_point(pts[2], x+w-3, y+h-3);
00311     viconutil_set_point(pts[3], x+3  , y+h-3);
00312 
00313     glColor4f(0.0, 0.0, 0.0, alpha);
00314     viconutil_draw_lineloop(pts, 4);
00315 
00316     glColor3f(1, 1, 0.0);
00317     viconutil_draw_points(pts, 4, 1);
00318 }
00319 
00320 static void vicon_editmode_hlt_draw(int x, int y, int w, int h, float alpha)
00321 {
00322     GLint pts[3][2];
00323 
00324     viconutil_set_point(pts[0], x+w/2, y+h-2);
00325     viconutil_set_point(pts[1], x+3, y+4);
00326     viconutil_set_point(pts[2], x+w-3, y+4);
00327 
00328     glColor4f(0.5, 0.5, 0.5, alpha);
00329     viconutil_draw_tri(pts);
00330 
00331     glColor4f(0.0, 0.0, 0.0, 1);
00332     viconutil_draw_lineloop_smooth(pts, 3);
00333 
00334     glColor3f(1, 1, 0.0);
00335     viconutil_draw_points(pts, 3, 1);
00336 }
00337 
00338 static void vicon_editmode_dehlt_draw(int x, int y, int w, int h, float UNUSED(alpha))
00339 {
00340     GLint pts[3][2];
00341 
00342     viconutil_set_point(pts[0], x+w/2, y+h-2);
00343     viconutil_set_point(pts[1], x+3, y+4);
00344     viconutil_set_point(pts[2], x+w-3, y+4);
00345 
00346     glColor4f(0.0f, 0.0f, 0.0f, 1);
00347     viconutil_draw_lineloop_smooth(pts, 3);
00348 
00349     glColor3f(.9f, .9f, .9f);
00350     viconutil_draw_points(pts, 3, 1);
00351 }
00352 
00353 static void vicon_disclosure_tri_right_draw(int x, int y, int w, int UNUSED(h), float alpha)
00354 {
00355     GLint pts[3][2];
00356     int cx = x+w/2;
00357     int cy = y+w/2;
00358     int d = w/3, d2 = w/5;
00359 
00360     viconutil_set_point(pts[0], cx-d2, cy+d);
00361     viconutil_set_point(pts[1], cx-d2, cy-d);
00362     viconutil_set_point(pts[2], cx+d2, cy);
00363 
00364     glShadeModel(GL_SMOOTH);
00365     glBegin(GL_TRIANGLES);
00366     glColor4f(0.8f, 0.8f, 0.8f, alpha);
00367     glVertex2iv(pts[0]);
00368     glVertex2iv(pts[1]);
00369     glColor4f(0.3f, 0.3f, 0.3f, alpha);
00370     glVertex2iv(pts[2]);
00371     glEnd();
00372     glShadeModel(GL_FLAT);
00373 
00374     glColor4f(0.0f, 0.0f, 0.0f, 1);
00375     viconutil_draw_lineloop_smooth(pts, 3);
00376 }
00377 
00378 static void vicon_small_tri_right_draw(int x, int y, int w, int UNUSED(h), float alpha)
00379 {
00380     GLint pts[3][2];
00381     int cx = x+w/2-4;
00382     int cy = y+w/2;
00383     int d = w/5, d2 = w/7;
00384 
00385     viconutil_set_point(pts[0], cx-d2, cy+d);
00386     viconutil_set_point(pts[1], cx-d2, cy-d);
00387     viconutil_set_point(pts[2], cx+d2, cy);
00388 
00389     glColor4f(0.2f, 0.2f, 0.2f, alpha);
00390 
00391     glShadeModel(GL_SMOOTH);
00392     glBegin(GL_TRIANGLES);
00393     glVertex2iv(pts[0]);
00394     glVertex2iv(pts[1]);
00395     glVertex2iv(pts[2]);
00396     glEnd();
00397     glShadeModel(GL_FLAT);
00398 }
00399 
00400 static void vicon_disclosure_tri_down_draw(int x, int y, int w, int UNUSED(h), float alpha)
00401 {
00402     GLint pts[3][2];
00403     int cx = x+w/2;
00404     int cy = y+w/2;
00405     int d = w/3, d2 = w/5;
00406 
00407     viconutil_set_point(pts[0], cx+d, cy+d2);
00408     viconutil_set_point(pts[1], cx-d, cy+d2);
00409     viconutil_set_point(pts[2], cx, cy-d2);
00410 
00411     glShadeModel(GL_SMOOTH);
00412     glBegin(GL_TRIANGLES);
00413     glColor4f(0.8f, 0.8f, 0.8f, alpha);
00414     glVertex2iv(pts[0]);
00415     glVertex2iv(pts[1]);
00416     glColor4f(0.3f, 0.3f, 0.3f, alpha);
00417     glVertex2iv(pts[2]);
00418     glEnd();
00419     glShadeModel(GL_FLAT);
00420 
00421     glColor4f(0.0f, 0.0f, 0.0f, 1);
00422     viconutil_draw_lineloop_smooth(pts, 3);
00423 }
00424 
00425 static void vicon_move_up_draw(int x, int y, int w, int h, float UNUSED(alpha))
00426 {
00427     int d=-2;
00428 
00429     glEnable(GL_LINE_SMOOTH);
00430     glLineWidth(1);
00431     glColor3f(0.0, 0.0, 0.0);
00432 
00433     glBegin(GL_LINE_STRIP);
00434     glVertex2i(x+w/2-d*2, y+h/2+d);
00435     glVertex2i(x+w/2, y+h/2-d + 1);
00436     glVertex2i(x+w/2+d*2, y+h/2+d);
00437     glEnd();
00438 
00439     glLineWidth(1.0);
00440     glDisable(GL_LINE_SMOOTH);
00441 }
00442 
00443 static void vicon_move_down_draw(int x, int y, int w, int h, float UNUSED(alpha))
00444 {
00445     int d=2;
00446 
00447     glEnable(GL_LINE_SMOOTH);
00448     glLineWidth(1);
00449     glColor3f(0.0, 0.0, 0.0);
00450 
00451     glBegin(GL_LINE_STRIP);
00452     glVertex2i(x+w/2-d*2, y+h/2+d);
00453     glVertex2i(x+w/2, y+h/2-d - 1);
00454     glVertex2i(x+w/2+d*2, y+h/2+d);
00455     glEnd();
00456 
00457     glLineWidth(1.0);
00458     glDisable(GL_LINE_SMOOTH);
00459 }
00460 
00461 #ifndef WITH_HEADLESS
00462 static void init_brush_icons(void)
00463 {
00464 
00465 #define INIT_BRUSH_ICON(icon_id, name)                                         \
00466     bbuf = IMB_ibImageFromMemory((unsigned char*)datatoc_ ##name## _png,       \
00467                      datatoc_ ##name## _png_size, IB_rect, "<brush icon>");    \
00468     def_internal_icon(bbuf, icon_id, 0, 0, w, ICON_TYPE_BUFFER);               \
00469     IMB_freeImBuf(bbuf);
00470     // end INIT_BRUSH_ICON
00471 
00472     ImBuf *bbuf;
00473     const int w = 96;
00474 
00475     INIT_BRUSH_ICON(ICON_BRUSH_ADD, add);
00476     INIT_BRUSH_ICON(ICON_BRUSH_BLOB, blob);
00477     INIT_BRUSH_ICON(ICON_BRUSH_BLUR, blur);
00478     INIT_BRUSH_ICON(ICON_BRUSH_CLAY, clay);
00479     INIT_BRUSH_ICON(ICON_BRUSH_CLONE, clone);
00480     INIT_BRUSH_ICON(ICON_BRUSH_CREASE, crease);
00481     INIT_BRUSH_ICON(ICON_BRUSH_DARKEN, darken);
00482     INIT_BRUSH_ICON(ICON_BRUSH_SCULPT_DRAW, draw);
00483     INIT_BRUSH_ICON(ICON_BRUSH_FILL, fill);
00484     INIT_BRUSH_ICON(ICON_BRUSH_FLATTEN, flatten);
00485     INIT_BRUSH_ICON(ICON_BRUSH_GRAB, grab);
00486     INIT_BRUSH_ICON(ICON_BRUSH_INFLATE, inflate);
00487     INIT_BRUSH_ICON(ICON_BRUSH_LAYER, layer);
00488     INIT_BRUSH_ICON(ICON_BRUSH_LIGHTEN, lighten);
00489     INIT_BRUSH_ICON(ICON_BRUSH_MIX, mix);
00490     INIT_BRUSH_ICON(ICON_BRUSH_MULTIPLY, multiply);
00491     INIT_BRUSH_ICON(ICON_BRUSH_NUDGE, nudge);
00492     INIT_BRUSH_ICON(ICON_BRUSH_PINCH, pinch);
00493     INIT_BRUSH_ICON(ICON_BRUSH_SCRAPE, scrape);
00494     INIT_BRUSH_ICON(ICON_BRUSH_SMEAR, smear);
00495     INIT_BRUSH_ICON(ICON_BRUSH_SMOOTH, smooth);
00496     INIT_BRUSH_ICON(ICON_BRUSH_SNAKE_HOOK, snake_hook);
00497     INIT_BRUSH_ICON(ICON_BRUSH_SOFTEN, soften);
00498     INIT_BRUSH_ICON(ICON_BRUSH_SUBTRACT, subtract);
00499     INIT_BRUSH_ICON(ICON_BRUSH_TEXDRAW, texdraw);
00500     INIT_BRUSH_ICON(ICON_BRUSH_THUMB, thumb);
00501     INIT_BRUSH_ICON(ICON_BRUSH_ROTATE, twist);
00502     INIT_BRUSH_ICON(ICON_BRUSH_VERTEXDRAW, vertexdraw);
00503 
00504 #undef INIT_BRUSH_ICON
00505 }
00506 
00507 static void init_internal_icons(void)
00508 {
00509     bTheme *btheme= UI_GetTheme();
00510     ImBuf *bbuf= NULL;
00511     int x, y, icontype;
00512     char iconfilestr[FILE_MAX];
00513     
00514     if ((btheme!=NULL) && btheme->tui.iconfile[0]) {
00515         char *icondir= BLI_get_folder(BLENDER_DATAFILES, "icons");
00516         if (icondir) {
00517             BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile);
00518             bbuf = IMB_loadiffname(iconfilestr, IB_rect); /* if the image is missing bbuf will just be NULL */
00519             if(bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) {
00520                 printf("\n***WARNING***\nIcons file %s too small.\nUsing built-in Icons instead\n", iconfilestr);
00521                 IMB_freeImBuf(bbuf);
00522                 bbuf= NULL;
00523             }
00524         }
00525         else {
00526             printf("%s: 'icons' data path not found, continuing\n", __func__);
00527         }
00528     }
00529     if(bbuf==NULL)
00530         bbuf = IMB_ibImageFromMemory((unsigned char*)datatoc_blender_icons_png, datatoc_blender_icons_png_size, IB_rect, "<blender icons>");
00531 
00532     if(bbuf) {
00533         /* free existing texture if any */
00534         if(icongltex.id) {
00535             glDeleteTextures(1, &icongltex.id);
00536             icongltex.id= 0;
00537         }
00538 
00539         /* we only use a texture for cards with non-power of two */
00540         if(GPU_non_power_of_two_support()) {
00541             glGenTextures(1, &icongltex.id);
00542 
00543             if(icongltex.id) {
00544                 icongltex.w = bbuf->x;
00545                 icongltex.h = bbuf->y;
00546                 icongltex.invw = 1.0f/bbuf->x;
00547                 icongltex.invh = 1.0f/bbuf->y;
00548 
00549                 glBindTexture(GL_TEXTURE_2D, icongltex.id);
00550                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bbuf->x, bbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, bbuf->rect);
00551                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00552                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00553                 glBindTexture(GL_TEXTURE_2D, 0);
00554 
00555                 if(glGetError() == GL_OUT_OF_MEMORY) {
00556                     glDeleteTextures(1, &icongltex.id);
00557                     icongltex.id= 0;
00558                 }
00559             }
00560         }
00561     }
00562 
00563     if(icongltex.id)
00564         icontype= ICON_TYPE_TEXTURE;
00565     else
00566         icontype= ICON_TYPE_BUFFER;
00567     
00568     if(bbuf) {
00569         for (y=0; y<ICON_GRID_ROWS; y++) {
00570             for (x=0; x<ICON_GRID_COLS; x++) {
00571                 def_internal_icon(bbuf, BIFICONID_FIRST + y*ICON_GRID_COLS + x,
00572                     x*(ICON_GRID_W+ICON_GRID_MARGIN)+ICON_GRID_MARGIN,
00573                     y*(ICON_GRID_H+ICON_GRID_MARGIN)+ICON_GRID_MARGIN, ICON_GRID_W,
00574                     icontype);
00575             }
00576         }
00577     }
00578 
00579     def_internal_vicon(VICO_VIEW3D_VEC, vicon_view3d_draw);
00580     def_internal_vicon(VICO_EDIT_VEC, vicon_edit_draw);
00581     def_internal_vicon(VICO_EDITMODE_DEHLT, vicon_editmode_dehlt_draw);
00582     def_internal_vicon(VICO_EDITMODE_HLT, vicon_editmode_hlt_draw);
00583     def_internal_vicon(VICO_DISCLOSURE_TRI_RIGHT_VEC, vicon_disclosure_tri_right_draw);
00584     def_internal_vicon(VICO_DISCLOSURE_TRI_DOWN_VEC, vicon_disclosure_tri_down_draw);
00585     def_internal_vicon(VICO_MOVE_UP_VEC, vicon_move_up_draw);
00586     def_internal_vicon(VICO_MOVE_DOWN_VEC, vicon_move_down_draw);
00587     def_internal_vicon(VICO_X_VEC, vicon_x_draw);
00588     def_internal_vicon(VICO_SMALL_TRI_RIGHT_VEC, vicon_small_tri_right_draw);
00589 
00590     IMB_freeImBuf(bbuf);
00591 }
00592 #endif // WITH_HEADLESS
00593 
00594 static void init_iconfile_list(struct ListBase *list)
00595 {
00596     IconFile *ifile;
00597     struct direntry *dir;
00598     int restoredir = 1; /* restore to current directory */
00599     int totfile, i, index=1;
00600     const char *icondir;
00601     char olddir[FILE_MAX];
00602 
00603     list->first = list->last = NULL;
00604     icondir = BLI_get_folder(BLENDER_DATAFILES, "icons");
00605 
00606     if(icondir==NULL)
00607         return;
00608     
00609     /* since BLI_dir_contents changes the current working directory, restore it 
00610        back to old value afterwards */
00611     if(!BLI_current_working_dir(olddir, sizeof(olddir))) 
00612         restoredir = 0;
00613     totfile = BLI_dir_contents(icondir, &dir);
00614     if (restoredir && !chdir(olddir)) {} /* fix warning about checking return value */
00615 
00616     for(i=0; i<totfile; i++) {
00617         if( (dir[i].type & S_IFREG) ) {
00618             char *filename = dir[i].relname;
00619             
00620             if(BLI_testextensie(filename, ".png")) {
00621                 /* loading all icons on file start is overkill & slows startup
00622                  * its possible they change size after blender load anyway. */
00623 #if 0
00624                 int ifilex, ifiley;
00625                 char iconfilestr[FILE_MAX+16]; /* allow 256 chars for file+dir */
00626                 ImBuf *bbuf= NULL;
00627                 /* check to see if the image is the right size, continue if not */
00628                 /* copying strings here should go ok, assuming that we never get back
00629                    a complete path to file longer than 256 chars */
00630                 BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, filename);
00631                 bbuf= IMB_loadiffname(iconfilestr, IB_rect);
00632 
00633                 if(bbuf) {
00634                     ifilex = bbuf->x;
00635                     ifiley = bbuf->y;
00636                     IMB_freeImBuf(bbuf);
00637                 }
00638                 else {
00639                     ifilex= ifiley= 0;
00640                 }
00641                 
00642                 /* bad size or failed to load */
00643                 if ((ifilex != ICON_IMAGE_W) || (ifiley != ICON_IMAGE_H)) {
00644                     printf("icon '%s' is wrong size %dx%d\n", iconfilestr, ifilex, ifiley);
00645                     continue;
00646                 }
00647 #endif          /* removed */
00648 
00649                 /* found a potential icon file, so make an entry for it in the cache list */
00650                 ifile = MEM_callocN(sizeof(IconFile), "IconFile");
00651                 
00652                 BLI_strncpy(ifile->filename, filename, sizeof(ifile->filename));
00653                 ifile->index = index;
00654 
00655                 BLI_addtail(list, ifile);
00656                 
00657                 index++;
00658             }
00659         }
00660     }
00661     
00662     /* free temporary direntry structure that's been created by BLI_dir_contents() */
00663     i= totfile-1;
00664     
00665     for(; i>=0; i--){
00666         MEM_freeN(dir[i].relname);
00667         MEM_freeN(dir[i].path);
00668         if (dir[i].string) MEM_freeN(dir[i].string);
00669     }
00670     free(dir);
00671     dir= NULL;
00672 }
00673 
00674 static void free_iconfile_list(struct ListBase *list)
00675 {
00676     IconFile *ifile=NULL, *next_ifile=NULL;
00677     
00678     for(ifile=list->first; ifile; ifile=next_ifile) {
00679         next_ifile = ifile->next;
00680         BLI_freelinkN(list, ifile);
00681     }
00682 }
00683 
00684 int UI_iconfile_get_index(const char *filename)
00685 {
00686     IconFile *ifile;
00687     ListBase *list=&(iconfilelist);
00688     
00689     for(ifile=list->first; ifile; ifile=ifile->next) {
00690         if (BLI_path_cmp(filename, ifile->filename) == 0) {
00691             return ifile->index;
00692         }
00693     }
00694     
00695     return 0;
00696 }
00697 
00698 ListBase *UI_iconfile_list(void)
00699 {
00700     ListBase *list=&(iconfilelist);
00701     
00702     return list;
00703 }
00704 
00705 
00706 void UI_icons_free(void)
00707 {
00708 #ifndef WITH_HEADLESS
00709     if(icongltex.id) {
00710         glDeleteTextures(1, &icongltex.id);
00711         icongltex.id= 0;
00712     }
00713 
00714     free_iconfile_list(&iconfilelist);
00715     BKE_icons_free();
00716 #endif
00717 }
00718 
00719 void UI_icons_free_drawinfo(void *drawinfo)
00720 {
00721     DrawInfo *di = drawinfo;
00722 
00723     if(di) {
00724         if(di->type == ICON_TYPE_BUFFER) {
00725             if(di->data.buffer.image) {
00726                 MEM_freeN(di->data.buffer.image->rect);
00727                 MEM_freeN(di->data.buffer.image);
00728             }
00729         }
00730 
00731         MEM_freeN(di);
00732     }
00733 }
00734 
00735 static DrawInfo *icon_create_drawinfo(void)
00736 {
00737     DrawInfo *di = NULL;
00738 
00739     di = MEM_callocN(sizeof(DrawInfo), "di_icon");
00740     di->type= ICON_TYPE_PREVIEW;
00741 
00742     return di;
00743 }
00744 
00745 /* note!, returns unscaled by DPI, may need to multiply result by UI_DPI_ICON_FAC */
00746 int UI_icon_get_width(int icon_id)
00747 {
00748     Icon *icon = NULL;
00749     DrawInfo *di = NULL;
00750 
00751     icon = BKE_icon_get(icon_id);
00752     
00753     if (icon==NULL) {
00754         if (G.f & G_DEBUG)
00755             printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
00756         return 0;
00757     }
00758     
00759     di = (DrawInfo *)icon->drawinfo;
00760     if (!di) {
00761         di = icon_create_drawinfo();
00762         icon->drawinfo = di;
00763     }
00764 
00765     if (di)
00766         return ICON_DEFAULT_WIDTH;
00767 
00768     return 0;
00769 }
00770 
00771 int UI_icon_get_height(int icon_id)
00772 {
00773     Icon *icon = NULL;
00774     DrawInfo *di = NULL;
00775 
00776     icon = BKE_icon_get(icon_id);
00777     
00778     if (icon==NULL) {
00779         if (G.f & G_DEBUG)
00780             printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
00781         return 0;
00782     }
00783     
00784     di = (DrawInfo*)icon->drawinfo;
00785 
00786     if (!di) {
00787         di = icon_create_drawinfo();
00788         icon->drawinfo = di;
00789     }
00790     
00791     if (di)
00792         return ICON_DEFAULT_HEIGHT;
00793 
00794     return 0;
00795 }
00796 
00797 void UI_icons_init(int first_dyn_id)
00798 {
00799 #ifdef WITH_HEADLESS
00800     (void)first_dyn_id;
00801 #else
00802     init_iconfile_list(&iconfilelist);
00803     BKE_icons_init(first_dyn_id);
00804     init_internal_icons();
00805     init_brush_icons();
00806 #endif
00807 }
00808 
00809 /* Render size for preview images and icons
00810  */
00811 static int preview_render_size(enum eIconSizes size)
00812 {
00813     switch (size) {
00814         case ICON_SIZE_ICON:    return 32;
00815         case ICON_SIZE_PREVIEW: return PREVIEW_DEFAULT_HEIGHT;
00816     }
00817     return 0;
00818 }
00819 
00820 /* Create rect for the icon
00821  */
00822 static void icon_create_rect(struct PreviewImage* prv_img, enum eIconSizes size) 
00823 {
00824     unsigned int render_size = preview_render_size(size);
00825 
00826     if (!prv_img) {
00827         if (G.f & G_DEBUG)
00828             printf("%s, error: requested preview image does not exist", __func__);
00829     }
00830     if (!prv_img->rect[size]) {
00831         prv_img->w[size] = render_size;
00832         prv_img->h[size] = render_size;
00833         prv_img->changed[size] = 1;
00834         prv_img->changed_timestamp[size] = 0;
00835         prv_img->rect[size] = MEM_callocN(render_size*render_size*sizeof(unsigned int), "prv_rect"); 
00836     }
00837 }
00838 
00839 /* only called when icon has changed */
00840 /* only call with valid pointer from UI_icon_draw */
00841 static void icon_set_image(bContext *C, ID *id, PreviewImage* prv_img, enum eIconSizes size)
00842 {
00843     if (!prv_img) {
00844         if (G.f & G_DEBUG)
00845             printf("%s: no preview image for this ID: %s\n", __func__, id->name);
00846         return;
00847     }   
00848 
00849     icon_create_rect(prv_img, size);
00850 
00851     ED_preview_icon_job(C, prv_img, id, prv_img->rect[size],
00852         prv_img->w[size], prv_img->h[size]);
00853 }
00854 
00855 static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh, unsigned int *rect, float alpha, float *rgb, short is_preview)
00856 {
00857     ImBuf *ima= NULL;
00858 
00859     /* sanity check */
00860     if(w<=0 || h<=0 || w>2000 || h>2000) {
00861         printf("%s: icons are %i x %i pixels?\n", __func__, w, h);
00862         BLI_assert(!"invalid icon size");
00863         return;
00864     }
00865 
00866     /* modulate color */
00867     if(alpha != 1.0f)
00868         glPixelTransferf(GL_ALPHA_SCALE, alpha);
00869 
00870     if(rgb) {
00871         glPixelTransferf(GL_RED_SCALE, rgb[0]);
00872         glPixelTransferf(GL_GREEN_SCALE, rgb[1]);
00873         glPixelTransferf(GL_BLUE_SCALE, rgb[2]);
00874     }
00875 
00876     /* rect contains image in 'rendersize', we only scale if needed */
00877     if(rw!=w && rh!=h) {
00878         /* first allocate imbuf for scaling and copy preview into it */
00879         ima = IMB_allocImBuf(rw, rh, 32, IB_rect);
00880         memcpy(ima->rect, rect, rw*rh*sizeof(unsigned int));    
00881         IMB_scaleImBuf(ima, w, h); /* scale it */
00882         rect= ima->rect;
00883     }
00884 
00885     /* draw */
00886     if(is_preview) {
00887         glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, rect);
00888     }
00889     else {
00890         glRasterPos2f(x, y);
00891         glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
00892     }
00893 
00894     if(ima)
00895         IMB_freeImBuf(ima);
00896 
00897     /* restore color */
00898     if(alpha != 0.0f)
00899         glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
00900     
00901     if(rgb) {
00902         glPixelTransferf(GL_RED_SCALE, 1.0f);
00903         glPixelTransferf(GL_GREEN_SCALE, 1.0f);
00904         glPixelTransferf(GL_BLUE_SCALE, 1.0f);
00905     }
00906 }
00907 
00908 static void icon_draw_texture(float x, float y, float w, float h, int ix, int iy, int UNUSED(iw), int ih, float alpha, float *rgb)
00909 {
00910     float x1, x2, y1, y2;
00911 
00912     if(rgb) glColor4f(rgb[0], rgb[1], rgb[2], alpha);
00913     else glColor4f(1.0f, 1.0f, 1.0f, alpha);
00914 
00915     x1= ix*icongltex.invw;
00916     x2= (ix + ih)*icongltex.invw;
00917     y1= iy*icongltex.invh;
00918     y2= (iy + ih)*icongltex.invh;
00919 
00920     glEnable(GL_TEXTURE_2D);
00921     glBindTexture(GL_TEXTURE_2D, icongltex.id);
00922 
00923     glBegin(GL_QUADS);
00924     glTexCoord2f(x1, y1);
00925     glVertex2f(x, y);
00926 
00927     glTexCoord2f(x2, y1);
00928     glVertex2f(x+w, y);
00929 
00930     glTexCoord2f(x2, y2);
00931     glVertex2f(x+w, y+h);
00932 
00933     glTexCoord2f(x1, y2);
00934     glVertex2f(x, y+h);
00935     glEnd();
00936 
00937     glBindTexture(GL_TEXTURE_2D, 0);
00938     glDisable(GL_TEXTURE_2D);
00939 }
00940 
00941 /* Drawing size for preview images */
00942 static int get_draw_size(enum eIconSizes size)
00943 {
00944     switch (size) {
00945         case ICON_SIZE_ICON: return ICON_DEFAULT_HEIGHT;
00946         case ICON_SIZE_PREVIEW: return PREVIEW_DEFAULT_HEIGHT;
00947     }
00948     return 0;
00949 }
00950 
00951 static void icon_draw_size(float x, float y, int icon_id, float aspect, float alpha, float *rgb, enum eIconSizes size, int draw_size, int UNUSED(nocreate), short is_preview)
00952 {
00953     bTheme *btheme= UI_GetTheme();
00954     Icon *icon = NULL;
00955     DrawInfo *di = NULL;
00956     IconImage *iimg;
00957     float fdraw_size= is_preview ? draw_size : (draw_size * UI_DPI_ICON_FAC);
00958     int w, h;
00959     
00960     icon = BKE_icon_get(icon_id);
00961     alpha *= btheme->tui.icon_alpha;
00962     
00963     if (icon==NULL) {
00964         if (G.f & G_DEBUG)
00965             printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
00966         return;
00967     }
00968 
00969     di = (DrawInfo*)icon->drawinfo;
00970     
00971     if (!di) {
00972         di = icon_create_drawinfo();
00973     
00974         icon->drawinfo = di;        
00975         icon->drawinfo_free = UI_icons_free_drawinfo;       
00976     }
00977     
00978     /* scale width and height according to aspect */
00979     w = (int)(fdraw_size/aspect + 0.5f);
00980     h = (int)(fdraw_size/aspect + 0.5f);
00981     
00982     if(di->type == ICON_TYPE_VECTOR) {
00983         /* vector icons use the uiBlock transformation, they are not drawn
00984         with untransformed coordinates like the other icons */
00985         di->data.vector.func((int)x, (int)y, ICON_DEFAULT_HEIGHT, ICON_DEFAULT_HEIGHT, 1.0f); 
00986     } 
00987     else if(di->type == ICON_TYPE_TEXTURE) {
00988         icon_draw_texture(x, y, (float)w, (float)h, di->data.texture.x, di->data.texture.y,
00989             di->data.texture.w, di->data.texture.h, alpha, rgb);
00990     }
00991     else if(di->type == ICON_TYPE_BUFFER) {
00992         /* it is a builtin icon */      
00993         iimg= di->data.buffer.image;
00994 
00995         if(!iimg->rect) return; /* something has gone wrong! */
00996 
00997         icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, is_preview);
00998     }
00999     else if(di->type == ICON_TYPE_PREVIEW) {
01000         PreviewImage* pi = BKE_previewimg_get((ID*)icon->obj); 
01001 
01002         if(pi) {            
01003             /* no create icon on this level in code */
01004             if(!pi->rect[size]) return; /* something has gone wrong! */
01005             
01006             /* preview images use premul alpha ... */
01007             glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
01008             icon_draw_rect(x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], 1.0f, NULL, is_preview);
01009             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01010         }
01011     }
01012 }
01013 
01014 static void ui_id_icon_render(bContext *C, ID *id, int big)
01015 {
01016     PreviewImage *pi = BKE_previewimg_get(id); 
01017     
01018     if (pi) {           
01019         if ((pi->changed[0] ||!pi->rect[0])) /* changed only ever set by dynamic icons */
01020         {
01021             /* create the rect if necessary */              
01022             
01023             icon_set_image(C, id, pi, ICON_SIZE_ICON);      /* icon size */
01024             if (big)
01025                 icon_set_image(C, id, pi, ICON_SIZE_PREVIEW);   /* bigger preview size */
01026             
01027             pi->changed[0] = 0;
01028         }
01029     }
01030 }
01031 
01032 static void ui_id_brush_render(bContext *C, ID *id)
01033 {
01034     PreviewImage *pi = BKE_previewimg_get(id); 
01035     enum eIconSizes i;
01036     
01037     if(!pi)
01038         return;
01039     
01040     for(i = 0; i < NUM_ICON_SIZES; i++) {
01041         /* check if rect needs to be created; changed
01042          only set by dynamic icons */
01043         if((pi->changed[i] || !pi->rect[i])) {
01044             icon_set_image(C, id, pi, i);
01045             pi->changed[i] = 0;
01046         }
01047     }
01048 }
01049 
01050 
01051 static int ui_id_brush_get_icon(bContext *C, ID *id)
01052 {
01053     Brush *br = (Brush*)id;
01054 
01055     if(br->flag & BRUSH_CUSTOM_ICON) {
01056         BKE_icon_getid(id);
01057         ui_id_brush_render(C, id);
01058     }
01059     else {
01060         Object *ob = CTX_data_active_object(C);
01061         SpaceImage *sima;
01062         EnumPropertyItem *items = NULL;
01063         int tool, mode = 0;
01064 
01065         /* XXX: this is not nice, should probably make brushes
01066            be strictly in one paint mode only to avoid
01067            checking various context stuff here */
01068 
01069         if(CTX_wm_view3d(C) && ob) {
01070             if(ob->mode & OB_MODE_SCULPT)
01071                 mode = OB_MODE_SCULPT;
01072             else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT))
01073                 mode = OB_MODE_VERTEX_PAINT;
01074             else if(ob->mode & OB_MODE_TEXTURE_PAINT)
01075                 mode = OB_MODE_TEXTURE_PAINT;
01076         }
01077         else if((sima = CTX_wm_space_image(C)) &&
01078             (sima->flag & SI_DRAWTOOL)) {
01079             mode = OB_MODE_TEXTURE_PAINT;
01080         }
01081 
01082         /* reset the icon */
01083         if(mode == OB_MODE_SCULPT) {
01084             items = brush_sculpt_tool_items;
01085             tool = br->sculpt_tool;
01086         }
01087         else if(mode == OB_MODE_VERTEX_PAINT) {
01088             items = brush_vertex_tool_items;
01089             tool = br->vertexpaint_tool;
01090         }
01091         else if(mode == OB_MODE_TEXTURE_PAINT) {
01092             items = brush_image_tool_items;
01093             tool = br->imagepaint_tool;
01094         }
01095 
01096         if(!items || !RNA_enum_icon_from_value(items, tool, &id->icon_id))
01097             id->icon_id = 0;
01098     }
01099 
01100     return id->icon_id;
01101 }
01102 
01103 int ui_id_icon_get(bContext *C, ID *id, int big)
01104 {
01105     int iconid= 0;
01106     
01107     /* icon */
01108     switch(GS(id->name)) {
01109         case ID_BR:
01110             iconid= ui_id_brush_get_icon(C, id);
01111             break;
01112         case ID_MA: /* fall through */
01113         case ID_TE: /* fall through */
01114         case ID_IM: /* fall through */
01115         case ID_WO: /* fall through */
01116         case ID_LA: /* fall through */
01117             iconid= BKE_icon_getid(id);
01118             /* checks if not exists, or changed */
01119             ui_id_icon_render(C, id, big);
01120             break;
01121         default:
01122             break;
01123     }
01124 
01125     return iconid;
01126 }
01127 
01128 static void icon_draw_at_size(float x, float y, int icon_id, float aspect, float alpha, enum eIconSizes size, int nocreate)
01129 {
01130     int draw_size = get_draw_size(size);
01131     icon_draw_size(x, y, icon_id, aspect, alpha, NULL, size, draw_size, nocreate, FALSE);
01132 }
01133 
01134 void UI_icon_draw_aspect(float x, float y, int icon_id, float aspect, float alpha)
01135 {
01136     icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, 0);
01137 }
01138 
01139 void UI_icon_draw_aspect_color(float x, float y, int icon_id, float aspect, float *rgb)
01140 {
01141     int draw_size = get_draw_size(ICON_SIZE_ICON);
01142     icon_draw_size(x, y, icon_id, aspect, 1.0f, rgb, ICON_SIZE_ICON, draw_size, FALSE, FALSE);
01143 }
01144 
01145 void UI_icon_draw(float x, float y, int icon_id)
01146 {
01147     UI_icon_draw_aspect(x, y, icon_id, 1.0f, 1.0f);
01148 }
01149 
01150 void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha)
01151 {
01152     icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, TRUE, FALSE);
01153 }
01154 
01155 void UI_icon_draw_preview(float x, float y, int icon_id)
01156 {
01157     icon_draw_at_size(x, y, icon_id, 1.0f, 1.0f, ICON_SIZE_PREVIEW, 0);
01158 }
01159 
01160 void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect)
01161 {
01162     icon_draw_at_size(x, y, icon_id, aspect, 1.0f, ICON_SIZE_PREVIEW, 0);
01163 }
01164 
01165 void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, int size)
01166 {
01167     icon_draw_size(x, y, icon_id, aspect, 1.0f, NULL, ICON_SIZE_PREVIEW, size, FALSE, TRUE);
01168 }
01169