Blender V2.61 - r43446
|
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