|
Blender
V2.59
|
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