Blender  V2.59
interface_icons.c
Go to the documentation of this file.
00001 /*
00002  * $Id: interface_icons.c 39066 2011-08-05 10:45:32Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00021  * All rights reserved.
00022  *
00023  * Contributors: Blender Foundation, full recode
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <math.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 
00037 #ifndef WIN32
00038 #include <unistd.h>
00039 #else
00040 #include <io.h>
00041 #include <direct.h>
00042 #include "BLI_winstuff.h"
00043 #endif   
00044 #include "MEM_guardedalloc.h"
00045 
00046 #include "GPU_extensions.h"
00047 
00048 #include "BLI_math.h"
00049 #include "BLI_blenlib.h"
00050 #include "BLI_storage_types.h"
00051 #include "BLI_utildefines.h"
00052 
00053 #include "DNA_brush_types.h"
00054 #include "DNA_object_types.h"
00055 #include "DNA_screen_types.h"
00056 #include "DNA_space_types.h"
00057 
00058 #include "RNA_access.h"
00059 #include "RNA_enum_types.h"
00060 
00061 #include "BKE_context.h"
00062 #include "BKE_global.h"
00063 #include "BKE_icons.h"
00064 #include "BKE_utildefines.h"
00065 
00066 #include "IMB_imbuf.h"
00067 #include "IMB_imbuf_types.h"
00068 
00069 #include "BIF_gl.h"
00070 #include "BIF_glutil.h"
00071 
00072 #include "ED_datafiles.h"
00073 #include "ED_render.h"
00074 
00075 #include "UI_interface.h"
00076 #include "UI_interface_icons.h"
00077 
00078 #include "interface_intern.h"
00079 
00080 
00081 #define ICON_IMAGE_W            600
00082 #define ICON_IMAGE_H            640
00083 
00084 #define ICON_GRID_COLS          26
00085 #define ICON_GRID_ROWS          30
00086 
00087 #define ICON_GRID_MARGIN        5
00088 #define ICON_GRID_W             16
00089 #define ICON_GRID_H             16
00090 
00091 typedef struct IconImage {
00092         int w;
00093         int h;
00094         unsigned int *rect; 
00095 } IconImage;
00096 
00097 typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
00098 
00099 #define ICON_TYPE_PREVIEW       0
00100 #define ICON_TYPE_TEXTURE       1
00101 #define ICON_TYPE_BUFFER        2
00102 #define ICON_TYPE_VECTOR        3
00103 
00104 typedef struct DrawInfo {
00105         int type;
00106 
00107         union {
00108                 /* type specific data */
00109                 struct {
00110                         VectorDrawFunc func;
00111                 } vector;
00112                 struct {
00113                         IconImage* image;
00114                 } buffer;
00115                 struct {
00116                         int x, y, w, h;
00117                 } texture;
00118         } data;
00119 } DrawInfo;
00120 
00121 typedef struct IconTexture {
00122         GLuint id;
00123         int w;
00124         int h;
00125         float invw;
00126         float invh;
00127 } IconTexture;
00128 
00129 /* ******************* STATIC LOCAL VARS ******************* */
00130 /* static here to cache results of icon directory scan, so it's not 
00131  * scanning the filesystem each time the menu is drawn */
00132 static struct ListBase iconfilelist = {NULL, NULL};
00133 static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f};
00134 
00135 /* **************************************************** */
00136 
00137 static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type)
00138 {
00139         Icon *new_icon = NULL;
00140         IconImage *iimg = NULL;
00141         DrawInfo *di;
00142         int y = 0;
00143         int imgsize = 0;
00144 
00145         new_icon = MEM_callocN(sizeof(Icon), "texicon");
00146 
00147         new_icon->obj = NULL; /* icon is not for library object */
00148         new_icon->type = 0;     
00149 
00150         di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
00151         di->type= type;
00152 
00153         if(type == ICON_TYPE_TEXTURE) {
00154                 di->data.texture.x= xofs;
00155                 di->data.texture.y= yofs;
00156                 di->data.texture.w= size;
00157                 di->data.texture.h= size;
00158         }
00159         else if(type == ICON_TYPE_BUFFER) {
00160                 iimg = MEM_mallocN(sizeof(IconImage), "icon_img");
00161                 iimg->rect = MEM_mallocN(size*size*sizeof(unsigned int), "icon_rect");
00162                 iimg->w = size;
00163                 iimg->h = size;
00164 
00165                 /* Here we store the rect in the icon - same as before */
00166                 imgsize = bbuf->x;
00167                 for (y=0; y<size; y++) {
00168                         memcpy(&iimg->rect[y*size], &bbuf->rect[(y+yofs)*imgsize+xofs], size*sizeof(int));
00169                 }
00170 
00171                 di->data.buffer.image = iimg;
00172         }
00173 
00174         new_icon->drawinfo_free = UI_icons_free_drawinfo;
00175         new_icon->drawinfo = di;
00176 
00177         BKE_icon_set(icon_id, new_icon);
00178 }
00179 
00180 static void def_internal_vicon( int icon_id, VectorDrawFunc drawFunc)
00181 {
00182         Icon *new_icon = NULL;
00183         DrawInfo* di;
00184 
00185         new_icon = MEM_callocN(sizeof(Icon), "texicon");
00186 
00187         new_icon->obj = NULL; /* icon is not for library object */
00188         new_icon->type = 0;
00189 
00190         di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
00191         di->type= ICON_TYPE_VECTOR;
00192         di->data.vector.func =drawFunc;
00193 
00194         new_icon->drawinfo_free = NULL;
00195         new_icon->drawinfo = di;
00196 
00197         BKE_icon_set(icon_id, new_icon);
00198 }
00199 
00200 /* Vector Icon Drawing Routines */
00201 
00202         /* Utilities */
00203 
00204 static void viconutil_set_point(GLint pt[2], int x, int y)
00205 {
00206         pt[0] = x;
00207         pt[1] = y;
00208 }
00209 
00210 static void viconutil_draw_tri(GLint (*pts)[2])
00211 {
00212         glBegin(GL_TRIANGLES);
00213         glVertex2iv(pts[0]);
00214         glVertex2iv(pts[1]);
00215         glVertex2iv(pts[2]);
00216         glEnd();
00217 }
00218 
00219 static void viconutil_draw_lineloop(GLint (*pts)[2], int numPoints)
00220 {
00221         int i;
00222 
00223         glBegin(GL_LINE_LOOP);
00224         for (i=0; i<numPoints; i++) {
00225                 glVertex2iv(pts[i]);
00226         }
00227         glEnd();
00228 }
00229 
00230 static void viconutil_draw_lineloop_smooth(GLint (*pts)[2], int numPoints)
00231 {
00232         glEnable(GL_LINE_SMOOTH);
00233         viconutil_draw_lineloop(pts, numPoints);
00234         glDisable(GL_LINE_SMOOTH);
00235 }
00236 
00237 static void viconutil_draw_points(GLint (*pts)[2], int numPoints, int pointSize)
00238 {
00239         int i;
00240 
00241         glBegin(GL_QUADS);
00242         for (i=0; i<numPoints; i++) {
00243                 int x = pts[i][0], y = pts[i][1];
00244 
00245                 glVertex2i(x-pointSize,y-pointSize);
00246                 glVertex2i(x+pointSize,y-pointSize);
00247                 glVertex2i(x+pointSize,y+pointSize);
00248                 glVertex2i(x-pointSize,y+pointSize);
00249         }
00250         glEnd();
00251 }
00252 
00253         /* Drawing functions */
00254 
00255 static void vicon_x_draw(int x, int y, int w, int h, float alpha)
00256 {
00257         x += 3;
00258         y += 3;
00259         w -= 6;
00260         h -= 6;
00261 
00262         glEnable( GL_LINE_SMOOTH );
00263 
00264         glLineWidth(2.5);
00265         
00266         glColor4f(0.0, 0.0, 0.0, alpha);
00267         glBegin(GL_LINES);
00268         glVertex2i(x  ,y  );
00269         glVertex2i(x+w,y+h);
00270         glVertex2i(x+w,y  );
00271         glVertex2i(x  ,y+h);
00272         glEnd();
00273 
00274         glLineWidth(1.0);
00275         
00276         glDisable( GL_LINE_SMOOTH );
00277 }
00278 
00279 static void vicon_view3d_draw(int x, int y, int w, int h, float alpha)
00280 {
00281         int cx = x + w/2;
00282         int cy = y + h/2;
00283         int d = MAX2(2, h/3);
00284 
00285         glColor4f(0.5, 0.5, 0.5, alpha);
00286         glBegin(GL_LINES);
00287         glVertex2i(x  , cy-d);
00288         glVertex2i(x+w, cy-d);
00289         glVertex2i(x  , cy+d);
00290         glVertex2i(x+w, cy+d);
00291 
00292         glVertex2i(cx-d, y  );
00293         glVertex2i(cx-d, y+h);
00294         glVertex2i(cx+d, y  );
00295         glVertex2i(cx+d, y+h);
00296         glEnd();
00297         
00298         glColor4f(0.0, 0.0, 0.0, alpha);
00299         glBegin(GL_LINES);
00300         glVertex2i(x  , cy);
00301         glVertex2i(x+w, cy);
00302         glVertex2i(cx, y  );
00303         glVertex2i(cx, y+h);
00304         glEnd();
00305 }
00306 
00307 static void vicon_edit_draw(int x, int y, int w, int h, float alpha)
00308 {
00309         GLint pts[4][2];
00310 
00311         viconutil_set_point(pts[0], x+3  , y+3  );
00312         viconutil_set_point(pts[1], x+w-3, y+3  );
00313         viconutil_set_point(pts[2], x+w-3, y+h-3);
00314         viconutil_set_point(pts[3], x+3  , y+h-3);
00315 
00316         glColor4f(0.0, 0.0, 0.0, alpha);
00317         viconutil_draw_lineloop(pts, 4);
00318 
00319         glColor3f(1, 1, 0.0);
00320         viconutil_draw_points(pts, 4, 1);
00321 }
00322 
00323 static void vicon_editmode_hlt_draw(int x, int y, int w, int h, float alpha)
00324 {
00325         GLint pts[3][2];
00326 
00327         viconutil_set_point(pts[0], x+w/2, y+h-2);
00328         viconutil_set_point(pts[1], x+3, y+4);
00329         viconutil_set_point(pts[2], x+w-3, y+4);
00330 
00331         glColor4f(0.5, 0.5, 0.5, alpha);
00332         viconutil_draw_tri(pts);
00333 
00334         glColor4f(0.0, 0.0, 0.0, 1);
00335         viconutil_draw_lineloop_smooth(pts, 3);
00336 
00337         glColor3f(1, 1, 0.0);
00338         viconutil_draw_points(pts, 3, 1);
00339 }
00340 
00341 static void vicon_editmode_dehlt_draw(int x, int y, int w, int h, float UNUSED(alpha))
00342 {
00343         GLint pts[3][2];
00344 
00345         viconutil_set_point(pts[0], x+w/2, y+h-2);
00346         viconutil_set_point(pts[1], x+3, y+4);
00347         viconutil_set_point(pts[2], x+w-3, y+4);
00348 
00349         glColor4f(0.0f, 0.0f, 0.0f, 1);
00350         viconutil_draw_lineloop_smooth(pts, 3);
00351 
00352         glColor3f(.9f, .9f, .9f);
00353         viconutil_draw_points(pts, 3, 1);
00354 }
00355 
00356 static void vicon_disclosure_tri_right_draw(int x, int y, int w, int UNUSED(h), float alpha)
00357 {
00358         GLint pts[3][2];
00359         int cx = x+w/2;
00360         int cy = y+w/2;
00361         int d = w/3, d2 = w/5;
00362 
00363         viconutil_set_point(pts[0], cx-d2, cy+d);
00364         viconutil_set_point(pts[1], cx-d2, cy-d);
00365         viconutil_set_point(pts[2], cx+d2, cy);
00366 
00367         glShadeModel(GL_SMOOTH);
00368         glBegin(GL_TRIANGLES);
00369         glColor4f(0.8f, 0.8f, 0.8f, alpha);
00370         glVertex2iv(pts[0]);
00371         glVertex2iv(pts[1]);
00372         glColor4f(0.3f, 0.3f, 0.3f, alpha);
00373         glVertex2iv(pts[2]);
00374         glEnd();
00375         glShadeModel(GL_FLAT);
00376 
00377         glColor4f(0.0f, 0.0f, 0.0f, 1);
00378         viconutil_draw_lineloop_smooth(pts, 3);
00379 }
00380 
00381 static void vicon_small_tri_right_draw(int x, int y, int w, int UNUSED(h), float alpha)
00382 {
00383         GLint pts[3][2];
00384         int cx = x+w/2-4;
00385         int cy = y+w/2;
00386         int d = w/5, d2 = w/7;
00387 
00388         viconutil_set_point(pts[0], cx-d2, cy+d);
00389         viconutil_set_point(pts[1], cx-d2, cy-d);
00390         viconutil_set_point(pts[2], cx+d2, cy);
00391 
00392         glColor4f(0.2f, 0.2f, 0.2f, alpha);
00393 
00394         glShadeModel(GL_SMOOTH);
00395         glBegin(GL_TRIANGLES);
00396         glVertex2iv(pts[0]);
00397         glVertex2iv(pts[1]);
00398         glVertex2iv(pts[2]);
00399         glEnd();
00400         glShadeModel(GL_FLAT);
00401 }
00402 
00403 static void vicon_disclosure_tri_down_draw(int x, int y, int w, int UNUSED(h), float alpha)
00404 {
00405         GLint pts[3][2];
00406         int cx = x+w/2;
00407         int cy = y+w/2;
00408         int d = w/3, d2 = w/5;
00409 
00410         viconutil_set_point(pts[0], cx+d, cy+d2);
00411         viconutil_set_point(pts[1], cx-d, cy+d2);
00412         viconutil_set_point(pts[2], cx, cy-d2);
00413 
00414         glShadeModel(GL_SMOOTH);
00415         glBegin(GL_TRIANGLES);
00416         glColor4f(0.8f, 0.8f, 0.8f, alpha);
00417         glVertex2iv(pts[0]);
00418         glVertex2iv(pts[1]);
00419         glColor4f(0.3f, 0.3f, 0.3f, alpha);
00420         glVertex2iv(pts[2]);
00421         glEnd();
00422         glShadeModel(GL_FLAT);
00423 
00424         glColor4f(0.0f, 0.0f, 0.0f, 1);
00425         viconutil_draw_lineloop_smooth(pts, 3);
00426 }
00427 
00428 static void vicon_move_up_draw(int x, int y, int w, int h, float UNUSED(alpha))
00429 {
00430         int d=-2;
00431 
00432         glEnable(GL_LINE_SMOOTH);
00433         glLineWidth(1);
00434         glColor3f(0.0, 0.0, 0.0);
00435 
00436         glBegin(GL_LINE_STRIP);
00437         glVertex2i(x+w/2-d*2, y+h/2+d);
00438         glVertex2i(x+w/2, y+h/2-d + 1);
00439         glVertex2i(x+w/2+d*2, y+h/2+d);
00440         glEnd();
00441 
00442         glLineWidth(1.0);
00443         glDisable(GL_LINE_SMOOTH);
00444 }
00445 
00446 static void vicon_move_down_draw(int x, int y, int w, int h, float UNUSED(alpha))
00447 {
00448         int d=2;
00449 
00450         glEnable(GL_LINE_SMOOTH);
00451         glLineWidth(1);
00452         glColor3f(0.0, 0.0, 0.0);
00453 
00454         glBegin(GL_LINE_STRIP);
00455         glVertex2i(x+w/2-d*2, y+h/2+d);
00456         glVertex2i(x+w/2, y+h/2-d - 1);
00457         glVertex2i(x+w/2+d*2, y+h/2+d);
00458         glEnd();
00459 
00460         glLineWidth(1.0);
00461         glDisable(GL_LINE_SMOOTH);
00462 }
00463 
00464 #ifndef WITH_HEADLESS
00465 static void init_brush_icons(void)
00466 {
00467 
00468 #define INIT_BRUSH_ICON(icon_id, name)                                       \
00469         bbuf = IMB_ibImageFromMemory((unsigned char*)datatoc_ ##name## _png, \
00470                                      datatoc_ ##name## _png_size, IB_rect);  \
00471         def_internal_icon(bbuf, icon_id, 0, 0, w, ICON_TYPE_BUFFER);         \
00472         IMB_freeImBuf(bbuf);
00473         // end INIT_BRUSH_ICON
00474 
00475         ImBuf *bbuf;
00476         const int w = 96;
00477 
00478         INIT_BRUSH_ICON(ICON_BRUSH_ADD, add);
00479         INIT_BRUSH_ICON(ICON_BRUSH_BLOB, blob);
00480         INIT_BRUSH_ICON(ICON_BRUSH_BLUR, blur);
00481         INIT_BRUSH_ICON(ICON_BRUSH_CLAY, clay);
00482         INIT_BRUSH_ICON(ICON_BRUSH_CLONE, clone);
00483         INIT_BRUSH_ICON(ICON_BRUSH_CREASE, crease);
00484         INIT_BRUSH_ICON(ICON_BRUSH_DARKEN, darken);
00485         INIT_BRUSH_ICON(ICON_BRUSH_SCULPT_DRAW, draw);
00486         INIT_BRUSH_ICON(ICON_BRUSH_FILL, fill);
00487         INIT_BRUSH_ICON(ICON_BRUSH_FLATTEN, flatten);
00488         INIT_BRUSH_ICON(ICON_BRUSH_GRAB, grab);
00489         INIT_BRUSH_ICON(ICON_BRUSH_INFLATE, inflate);
00490         INIT_BRUSH_ICON(ICON_BRUSH_LAYER, layer);
00491         INIT_BRUSH_ICON(ICON_BRUSH_LIGHTEN, lighten);
00492         INIT_BRUSH_ICON(ICON_BRUSH_MIX, mix);
00493         INIT_BRUSH_ICON(ICON_BRUSH_MULTIPLY, multiply);
00494         INIT_BRUSH_ICON(ICON_BRUSH_NUDGE, nudge);
00495         INIT_BRUSH_ICON(ICON_BRUSH_PINCH, pinch);
00496         INIT_BRUSH_ICON(ICON_BRUSH_SCRAPE, scrape);
00497         INIT_BRUSH_ICON(ICON_BRUSH_SMEAR, smear);
00498         INIT_BRUSH_ICON(ICON_BRUSH_SMOOTH, smooth);
00499         INIT_BRUSH_ICON(ICON_BRUSH_SNAKE_HOOK, snake_hook);
00500         INIT_BRUSH_ICON(ICON_BRUSH_SOFTEN, soften);
00501         INIT_BRUSH_ICON(ICON_BRUSH_SUBTRACT, subtract);
00502         INIT_BRUSH_ICON(ICON_BRUSH_TEXDRAW, texdraw);
00503         INIT_BRUSH_ICON(ICON_BRUSH_THUMB, thumb);
00504         INIT_BRUSH_ICON(ICON_BRUSH_ROTATE, twist);
00505         INIT_BRUSH_ICON(ICON_BRUSH_VERTEXDRAW, vertexdraw);
00506 
00507 #undef INIT_BRUSH_ICON
00508 }
00509 
00510 static void init_internal_icons(void)
00511 {
00512         bTheme *btheme= U.themes.first;
00513         ImBuf *bbuf= NULL;
00514         int x, y, icontype;
00515         char iconfilestr[FILE_MAXDIR+FILE_MAXFILE];
00516         
00517         if ((btheme!=NULL) && btheme->tui.iconfile[0]) {
00518                 char *icondir= BLI_get_folder(BLENDER_DATAFILES, "icons");
00519                 if (icondir) {
00520                         BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile);
00521                         bbuf = IMB_loadiffname(iconfilestr, IB_rect); /* if the image is missing bbuf will just be NULL */
00522                         if(bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) {
00523                                 printf("\n***WARNING***\nIcons file %s too small.\nUsing built-in Icons instead\n", iconfilestr);
00524                                 IMB_freeImBuf(bbuf);
00525                                 bbuf= NULL;
00526                         }
00527                 }
00528         }
00529         if(bbuf==NULL)
00530                 bbuf = IMB_ibImageFromMemory((unsigned char*)datatoc_blenderbuttons, datatoc_blenderbuttons_size, IB_rect);
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_getdir changes the current working directory, restore it 
00610            back to old value afterwards */
00611         if(!BLI_getwdN(olddir, sizeof(olddir))) 
00612                 restoredir = 0;
00613         totfile = BLI_getdir(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_getdir() */
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("UI_icon_get_width: Internal error, no icon for icon ID: %d\n", 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("UI_icon_get_height: Internal error, no icon for icon ID: %d\n", 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("Error: requested preview image does not exist");
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("No preview image for this ID: %s\n", 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("icon_draw_rect: icons are %i x %i pixels?\n", 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), int is_preview)
00952 {
00953         Icon *icon = NULL;
00954         DrawInfo *di = NULL;
00955         IconImage *iimg;
00956         float fdraw_size= UI_DPI_ICON_FAC*draw_size;
00957         int w, h;
00958         
00959         icon = BKE_icon_get(icon_id);
00960         
00961         if (icon==NULL) {
00962                 if (G.f & G_DEBUG)
00963                         printf("icon_draw_mipmap: Internal error, no icon for icon ID: %d\n", icon_id);
00964                 return;
00965         }
00966 
00967         di = (DrawInfo*)icon->drawinfo;
00968         
00969         if (!di) {
00970                 di = icon_create_drawinfo();
00971         
00972                 icon->drawinfo = di;            
00973                 icon->drawinfo_free = UI_icons_free_drawinfo;           
00974         }
00975         
00976         /* scale width and height according to aspect */
00977         w = (int)(fdraw_size/aspect + 0.5f);
00978         h = (int)(fdraw_size/aspect + 0.5f);
00979         
00980         if(di->type == ICON_TYPE_VECTOR) {
00981                 /* vector icons use the uiBlock transformation, they are not drawn
00982                 with untransformed coordinates like the other icons */
00983                 di->data.vector.func((int)x, (int)y, ICON_DEFAULT_HEIGHT, ICON_DEFAULT_HEIGHT, 1.0f); 
00984         } 
00985         else if(di->type == ICON_TYPE_TEXTURE) {
00986                 icon_draw_texture(x, y, (float)w, (float)h, di->data.texture.x, di->data.texture.y,
00987                         di->data.texture.w, di->data.texture.h, alpha, rgb);
00988         }
00989         else if(di->type == ICON_TYPE_BUFFER) {
00990                 /* it is a builtin icon */              
00991                 iimg= di->data.buffer.image;
00992 
00993                 if(!iimg->rect) return; /* something has gone wrong! */
00994 
00995                 icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, is_preview);
00996         }
00997         else if(di->type == ICON_TYPE_PREVIEW) {
00998                 PreviewImage* pi = BKE_previewimg_get((ID*)icon->obj); 
00999 
01000                 if(pi) {                        
01001                         /* no create icon on this level in code */
01002                         if(!pi->rect[size]) return; /* something has gone wrong! */
01003                         
01004                         /* preview images use premul alpha ... */
01005                         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
01006                         icon_draw_rect(x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], 1.0f, NULL, is_preview);
01007                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01008                 }
01009         }
01010 }
01011 
01012 static void ui_id_icon_render(bContext *C, ID *id, int big)
01013 {
01014         PreviewImage *pi = BKE_previewimg_get(id); 
01015         
01016         if (pi) {                       
01017                 if ((pi->changed[0] ||!pi->rect[0])) /* changed only ever set by dynamic icons */
01018                 {
01019                         /* create the rect if necessary */                              
01020                         
01021                         icon_set_image(C, id, pi, 0);           /* icon size */
01022                         if (big)
01023                                 icon_set_image(C, id, pi, 1);   /* bigger preview size */
01024                         
01025                         pi->changed[0] = 0;
01026                 }
01027         }
01028 }
01029 
01030 static void ui_id_brush_render(bContext *C, ID *id)
01031 {
01032         PreviewImage *pi = BKE_previewimg_get(id); 
01033         int i;
01034         
01035         if(!pi)
01036                 return;
01037         
01038         for(i = 0; i < NUM_ICON_SIZES; i++) {
01039                 /* check if rect needs to be created; changed
01040                  only set by dynamic icons */
01041                 if((pi->changed[i] || !pi->rect[i])) {
01042                         icon_set_image(C, id, pi, i);
01043                         pi->changed[i] = 0;
01044                 }
01045         }
01046 }
01047 
01048 
01049 static int ui_id_brush_get_icon(bContext *C, ID *id)
01050 {
01051         Brush *br = (Brush*)id;
01052 
01053         if(br->flag & BRUSH_CUSTOM_ICON) {
01054                 BKE_icon_getid(id);
01055                 ui_id_brush_render(C, id);
01056         }
01057         else {
01058                 Object *ob = CTX_data_active_object(C);
01059                 SpaceImage *sima;
01060                 EnumPropertyItem *items = NULL;
01061                 int tool, mode = 0;
01062 
01063                 /* XXX: this is not nice, should probably make brushes
01064                    be strictly in one paint mode only to avoid
01065                    checking various context stuff here */
01066 
01067                 if(CTX_wm_view3d(C) && ob) {
01068                         if(ob->mode & OB_MODE_SCULPT)
01069                                 mode = OB_MODE_SCULPT;
01070                         else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT))
01071                                 mode = OB_MODE_VERTEX_PAINT;
01072                         else if(ob->mode & OB_MODE_TEXTURE_PAINT)
01073                                 mode = OB_MODE_TEXTURE_PAINT;
01074                 }
01075                 else if((sima = CTX_wm_space_image(C)) &&
01076                         (sima->flag & SI_DRAWTOOL)) {
01077                         mode = OB_MODE_TEXTURE_PAINT;
01078                 }
01079 
01080                 /* reset the icon */
01081                 if(mode == OB_MODE_SCULPT) {
01082                         items = brush_sculpt_tool_items;
01083                         tool = br->sculpt_tool;
01084                 }
01085                 else if(mode == OB_MODE_VERTEX_PAINT) {
01086                         items = brush_vertex_tool_items;
01087                         tool = br->vertexpaint_tool;
01088                 }
01089                 else if(mode == OB_MODE_TEXTURE_PAINT) {
01090                         items = brush_image_tool_items;
01091                         tool = br->imagepaint_tool;
01092                 }
01093 
01094                 if(!items || !RNA_enum_icon_from_value(items, tool, &id->icon_id))
01095                         id->icon_id = 0;
01096         }
01097 
01098         return id->icon_id;
01099 }
01100 
01101 int ui_id_icon_get(bContext *C, ID *id, int big)
01102 {
01103         int iconid= 0;
01104         
01105         /* icon */
01106         switch(GS(id->name))
01107         {
01108                 case ID_BR:
01109                         iconid= ui_id_brush_get_icon(C, id);
01110                         break;
01111                 case ID_MA: /* fall through */
01112                 case ID_TE: /* fall through */
01113                 case ID_IM: /* fall through */
01114                 case ID_WO: /* fall through */
01115                 case ID_LA: /* fall through */
01116                         iconid= BKE_icon_getid(id);
01117                         /* checks if not exists, or changed */
01118                         ui_id_icon_render(C, id, big);
01119                         break;
01120                 default:
01121                         break;
01122         }
01123 
01124         return iconid;
01125 }
01126 
01127 static void icon_draw_at_size(float x, float y, int icon_id, float aspect, float alpha, enum eIconSizes size, int nocreate)
01128 {
01129         int draw_size = get_draw_size(size);
01130         icon_draw_size(x, y, icon_id, aspect, alpha, NULL, size, draw_size, nocreate, FALSE);
01131 }
01132 
01133 void UI_icon_draw_aspect(float x, float y, int icon_id, float aspect, float alpha)
01134 {
01135         icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, 0);
01136 }
01137 
01138 void UI_icon_draw_aspect_color(float x, float y, int icon_id, float aspect, float *rgb)
01139 {
01140         int draw_size = get_draw_size(ICON_SIZE_ICON);
01141         icon_draw_size(x, y, icon_id, aspect, 1.0f, rgb, ICON_SIZE_ICON, draw_size, FALSE, FALSE);
01142 }
01143 
01144 void UI_icon_draw(float x, float y, int icon_id)
01145 {
01146         UI_icon_draw_aspect(x, y, icon_id, 1.0f, 1.0f);
01147 }
01148 
01149 void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha)
01150 {
01151         icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, TRUE, FALSE);
01152 }
01153 
01154 void UI_icon_draw_preview(float x, float y, int icon_id)
01155 {
01156         icon_draw_at_size(x, y, icon_id, 1.0f, 1.0f, ICON_SIZE_PREVIEW, 0);
01157 }
01158 
01159 void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect)
01160 {
01161         icon_draw_at_size(x, y, icon_id, aspect, 1.0f, ICON_SIZE_PREVIEW, 0);
01162 }
01163 
01164 void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, int size)
01165 {
01166         icon_draw_size(x, y, icon_id, aspect, 1.0f, NULL, ICON_SIZE_PREVIEW, size, FALSE, TRUE);
01167 }
01168