Blender  V2.59
icons.c
Go to the documentation of this file.
00001 /*
00002 * $Id: icons.c 36757 2011-05-18 19:42:30Z elubie $
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) 2006-2007 Blender Foundation.
00021 * All rights reserved.
00022 * 
00023 * The Original Code is: all of this file.
00024 * 
00025 * Contributor(s): none yet.
00026 * 
00027 * ***** END GPL LICENSE BLOCK *****
00028 *
00029 */
00030 
00036 #include <math.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 
00040 #include "MEM_guardedalloc.h"
00041 
00042 #include "DNA_lamp_types.h"
00043 #include "DNA_material_types.h"
00044 #include "DNA_texture_types.h"
00045 #include "DNA_world_types.h"
00046 #include "DNA_brush_types.h"
00047 
00048 #include "BLI_utildefines.h"
00049 #include "BLI_ghash.h"
00050 
00051 #include "BKE_icons.h"
00052 #include "BKE_global.h" /* only for G.background test */
00053 
00054 #include "BLO_sys_types.h" // for intptr_t support
00055 
00056 #define GS(a)   (*((short *)(a)))
00057 
00058 /* GLOBALS */
00059 
00060 static GHash* gIcons = NULL;
00061 
00062 static int gNextIconId = 1;
00063 
00064 static int gFirstIconId = 1;
00065 
00066 
00067 static void icon_free(void *val)
00068 {
00069         Icon* icon = val;
00070 
00071         if (icon)
00072         {
00073                 if (icon->drawinfo_free) {              
00074                         icon->drawinfo_free(icon->drawinfo);
00075                 }
00076                 else if (icon->drawinfo) {
00077                         MEM_freeN(icon->drawinfo);
00078                 }
00079                 MEM_freeN(icon);
00080         }
00081 }
00082 
00083 /* create an id for a new icon and make sure that ids from deleted icons get reused
00084    after the integer number range is used up */
00085 static int get_next_free_id(void)
00086 {
00087         int startId = gFirstIconId;
00088 
00089         /* if we haven't used up the int number range, we just return the next int */
00090         if (gNextIconId>=gFirstIconId)
00091                 return gNextIconId++;
00092         
00093         /* now we try to find the smallest icon id not stored in the gIcons hash */
00094         while (BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(startId)) && startId>=gFirstIconId) 
00095                 startId++;
00096 
00097         /* if we found a suitable one that isnt used yet, return it */
00098         if (startId>=gFirstIconId)
00099                 return startId;
00100 
00101         /* fail */
00102         return 0;
00103 }
00104 
00105 void BKE_icons_init(int first_dyn_id)
00106 {
00107         gNextIconId = first_dyn_id;
00108         gFirstIconId = first_dyn_id;
00109 
00110         if (!gIcons)
00111                 gIcons = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "icons_init gh");
00112 }
00113 
00114 void BKE_icons_free(void)
00115 {
00116         if(gIcons)
00117                 BLI_ghash_free(gIcons, NULL, icon_free);
00118         gIcons = NULL;
00119 }
00120 
00121 struct PreviewImage* BKE_previewimg_create(void) 
00122 {
00123         PreviewImage* prv_img = NULL;
00124         int i;
00125 
00126         prv_img = MEM_callocN(sizeof(PreviewImage), "img_prv");
00127 
00128         for (i=0; i<NUM_ICON_SIZES; ++i) {
00129                 prv_img->changed[i] = 1;
00130                 prv_img->changed_timestamp[i] = 0;
00131         }
00132         return prv_img;
00133 }
00134 
00135 void BKE_previewimg_freefunc(void *link)
00136 {
00137         PreviewImage *prv = (PreviewImage *)link;
00138         if (prv) {
00139                 int i;
00140 
00141                 for (i=0; i<NUM_ICON_SIZES;++i) {
00142                         if (prv->rect[i]) {
00143                                 MEM_freeN(prv->rect[i]);
00144                                 prv->rect[i] = NULL;
00145                         }
00146                 }
00147                 MEM_freeN(prv);
00148         }
00149 }
00150 
00151 void BKE_previewimg_free(PreviewImage **prv)
00152 {
00153         if(prv && (*prv)) {
00154                 BKE_previewimg_freefunc(*prv);
00155                 *prv = NULL;
00156         }
00157 }
00158 
00159 struct PreviewImage* BKE_previewimg_copy(PreviewImage *prv) 
00160 {
00161         PreviewImage* prv_img = NULL;
00162         int i;
00163 
00164         if (prv) {
00165                 prv_img = MEM_dupallocN(prv);
00166                 for (i=0; i < NUM_ICON_SIZES; ++i) {
00167                         if (prv->rect[i]) {
00168                                 prv_img->rect[i] = MEM_dupallocN(prv->rect[i]);
00169                         } else {
00170                                 prv_img->rect[i] = NULL;
00171                         }
00172                 }
00173         }
00174         return prv_img;
00175 }
00176 
00177 void BKE_previewimg_free_id(ID *id) 
00178 {
00179         if (GS(id->name) == ID_MA) {
00180                 Material *mat = (Material*)id;  
00181                 BKE_previewimg_free(&mat->preview);
00182         } else if (GS(id->name) == ID_TE) {
00183                 Tex *tex = (Tex*)id;
00184                 BKE_previewimg_free(&tex->preview);
00185         } else if (GS(id->name) == ID_WO) {
00186                 World *wo = (World*)id;
00187                 BKE_previewimg_free(&wo->preview);
00188         } else if (GS(id->name) == ID_LA) {
00189                 Lamp *la  = (Lamp*)id;
00190                 BKE_previewimg_free(&la->preview);
00191         } else if (GS(id->name) == ID_IM) {
00192                 Image *img  = (Image*)id;
00193                 BKE_previewimg_free(&img->preview);
00194         } else if (GS(id->name) == ID_BR) {
00195                 Brush *br  = (Brush*)id;
00196                 BKE_previewimg_free(&br->preview);
00197         }
00198 }
00199 
00200 PreviewImage* BKE_previewimg_get(ID *id) 
00201 {
00202         PreviewImage* prv_img = NULL;
00203 
00204         if (GS(id->name) == ID_MA) {
00205                 Material *mat = (Material*)id;  
00206                 if (!mat->preview) mat->preview = BKE_previewimg_create();
00207                 prv_img = mat->preview;
00208         } else if (GS(id->name) == ID_TE) {
00209                 Tex *tex = (Tex*)id;
00210                 if (!tex->preview) tex->preview = BKE_previewimg_create();
00211                 prv_img = tex->preview;
00212         } else if (GS(id->name) == ID_WO) {
00213                 World *wo = (World*)id;
00214                 if (!wo->preview) wo->preview = BKE_previewimg_create();
00215                 prv_img = wo->preview;
00216         } else if (GS(id->name) == ID_LA) {
00217                 Lamp *la  = (Lamp*)id;
00218                 if (!la->preview) la->preview = BKE_previewimg_create();
00219                 prv_img = la->preview;
00220         } else if (GS(id->name) == ID_IM) {
00221                 Image *img  = (Image*)id;
00222                 if (!img->preview) img->preview = BKE_previewimg_create();
00223                 prv_img = img->preview;
00224         } else if (GS(id->name) == ID_BR) {
00225                 Brush *br  = (Brush*)id;
00226                 if (!br->preview) br->preview = BKE_previewimg_create();
00227                 prv_img = br->preview;
00228         }
00229 
00230         return prv_img;
00231 }
00232 
00233 void BKE_icon_changed(int id)
00234 {
00235         Icon* icon = NULL;
00236         
00237         if (!id || G.background) return;
00238 
00239         icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(id));
00240         
00241         if (icon)
00242         {
00243                 PreviewImage *prv = BKE_previewimg_get((ID*)icon->obj);
00244 
00245                 /* all previews changed */
00246                 if (prv) {
00247                         int i;
00248                         for (i=0; i<NUM_ICON_SIZES; ++i) {
00249                                 prv->changed[i] = 1;
00250                                 prv->changed_timestamp[i]++;
00251                         }
00252                 }
00253         }       
00254 }
00255 
00256 int BKE_icon_getid(struct ID* id)
00257 {
00258         Icon* new_icon = NULL;
00259 
00260         if (!id || G.background)
00261                 return 0;
00262 
00263         if (id->icon_id)
00264                 return id->icon_id;
00265 
00266         id->icon_id = get_next_free_id();
00267 
00268         if (!id->icon_id){
00269                 printf("BKE_icon_getid: Internal error - not enough IDs\n");
00270                 return 0;
00271         }
00272 
00273         new_icon = MEM_callocN(sizeof(Icon), "texicon");
00274 
00275         new_icon->obj = id;
00276         new_icon->type = GS(id->name);
00277         
00278         /* next two lines make sure image gets created */
00279         new_icon->drawinfo = NULL;
00280         new_icon->drawinfo_free = NULL;
00281 
00282         BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(id->icon_id), new_icon);
00283         
00284         return id->icon_id;
00285 }
00286 
00287 Icon* BKE_icon_get(int icon_id)
00288 {
00289         Icon* icon = NULL;
00290 
00291         icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id));
00292         
00293         if (!icon) {
00294                 printf("BKE_icon_get: Internal error, no icon for icon ID: %d\n", icon_id);
00295                 return NULL;
00296         }
00297 
00298         return icon;
00299 }
00300 
00301 void BKE_icon_set(int icon_id, struct Icon* icon)
00302 {
00303         Icon* old_icon = NULL;
00304 
00305         old_icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id));
00306 
00307         if (old_icon)
00308         {
00309                 printf("BKE_icon_set: Internal error, icon already set: %d\n", icon_id);
00310                 return;
00311         }
00312 
00313         BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(icon_id), icon);
00314 }
00315 
00316 void BKE_icon_delete(struct ID* id)
00317 {
00318 
00319         if (!id->icon_id) return; /* no icon defined for library object */
00320 
00321         BLI_ghash_remove(gIcons, SET_INT_IN_POINTER(id->icon_id), NULL, icon_free);
00322         id->icon_id = 0;
00323 }