diff options
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_icons.h | 30 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/icons.c | 124 |
2 files changed, 126 insertions, 28 deletions
diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index 686dba21283..47cac895645 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -36,14 +36,39 @@ typedef void (*DrawInfoFreeFP)(void *drawinfo); +enum { + /** ID preview: obj is #ID. */ + ICON_DATA_ID = 0, + /** Preview: obj is #PreviewImage */ + ICON_DATA_PREVIEW, + /** 2D triangles: obj is #Icon_Geom */ + ICON_DATA_GEOM, +}; + struct Icon { void *drawinfo; + /** + * Data defined by #obj_type + * \note for #ICON_DATA_GEOM the memory is owned by the icon, + * could be made into a flag if we want that to be optional. + */ void *obj; + char obj_type; + /** Internal use only. */ + char flag; /** #ID_Type or 0 when not used for ID preview. */ short id_type; DrawInfoFreeFP drawinfo_free; }; +/** Used for #ICON_DATA_GEOM, assigned to #Icon.obj. */ +struct Icon_Geom { + int icon_id; + int coords_len; + const unsigned char (*coords)[2]; + const unsigned char (*colors)[4]; +}; + typedef struct Icon Icon; struct PreviewImage; @@ -58,6 +83,8 @@ int BKE_icon_id_ensure(struct ID *id); int BKE_icon_preview_ensure(struct ID *id, struct PreviewImage *preview); +int BKE_icon_geom_ensure(struct Icon_Geom *geom); + /* retrieve icon for id */ struct Icon *BKE_icon_get(const int icon_id); @@ -68,7 +95,8 @@ void BKE_icon_set(const int icon_id, struct Icon *icon); /* remove icon and free data if library object becomes invalid */ void BKE_icon_id_delete(struct ID *id); -void BKE_icon_delete(const int icon_id); +bool BKE_icon_delete(const int icon_id); +bool BKE_icon_delete_unmanaged(const int icon_id); /* report changes - icon needs to be recalculated */ void BKE_icon_changed(const int icon_id); diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index 7cf7bb7452a..7097b349125 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -64,6 +64,14 @@ #include "IMB_imbuf_types.h" #include "IMB_thumbs.h" +/** + * Only allow non-managed icons to be removed (by Python for eg). + * Previews & ID's have their own functions to remove icons. + */ +enum { + ICON_FLAG_MANAGED = (1 << 0), +}; + /* GLOBALS */ static GHash *gIcons = NULL; @@ -86,6 +94,13 @@ static void icon_free(void *val) Icon *icon = val; if (icon) { + if (icon->obj_type == ICON_DATA_GEOM) { + struct Icon_Geom *obj = icon->obj; + MEM_freeN((void *)obj->coords); + MEM_freeN((void *)obj->colors); + MEM_freeN(icon->obj); + } + if (icon->drawinfo_free) { icon->drawinfo_free(icon->drawinfo); } @@ -96,6 +111,22 @@ static void icon_free(void *val) } } +static void icon_free_data(Icon *icon) +{ + if (icon->obj_type == ICON_DATA_ID) { + ((ID *)(icon->obj))->icon_id = 0; + } + else if (icon->obj_type == ICON_DATA_PREVIEW) { + ((PreviewImage *)(icon->obj))->icon_id = 0; + } + else if (icon->obj_type == ICON_DATA_GEOM) { + ((struct Icon_Geom *)(icon->obj))->icon_id = 0; + } + else { + BLI_assert(0); + } +} + /* create an id for a new icon and make sure that ids from deleted icons get reused * after the integer number range is used up */ static int get_next_free_id(void) @@ -478,6 +509,7 @@ void BKE_icon_changed(const int icon_id) if (icon) { /* We *only* expect ID-tied icons here, not non-ID icon/preview! */ BLI_assert(icon->id_type != 0); + BLI_assert(icon->obj_type == ICON_DATA_ID); /* Do not enforce creation of previews for valid ID types using BKE_previewimg_id_ensure() here , * we only want to ensure *existing* preview images are properly tagged as changed/invalid, that's all. */ @@ -494,22 +526,31 @@ void BKE_icon_changed(const int icon_id) } } -static int icon_id_ensure_create_icon(struct ID *id) +static Icon *icon_create(int icon_id, int obj_type, void *obj) { - BLI_assert(BLI_thread_is_main()); - - Icon *new_icon = NULL; + Icon *new_icon = MEM_mallocN(sizeof(Icon), __func__); - new_icon = MEM_mallocN(sizeof(Icon), __func__); - - new_icon->obj = id; - new_icon->id_type = GS(id->name); + new_icon->obj_type = obj_type; + new_icon->obj = obj; + new_icon->id_type = 0; + new_icon->flag = 0; /* next two lines make sure image gets created */ new_icon->drawinfo = NULL; new_icon->drawinfo_free = NULL; - BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(id->icon_id), new_icon); + BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(icon_id), new_icon); + + return new_icon; +} + +static int icon_id_ensure_create_icon(struct ID *id) +{ + BLI_assert(BLI_thread_is_main()); + + Icon *icon = icon_create(id->icon_id, ICON_DATA_ID, id); + icon->id_type = GS(id->name); + icon->flag = ICON_FLAG_MANAGED; return id->icon_id; } @@ -544,8 +585,6 @@ int BKE_icon_id_ensure(struct ID *id) */ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview) { - Icon *new_icon = NULL; - if (!preview || G.background) return 0; @@ -576,18 +615,26 @@ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview) return icon_id_ensure_create_icon(id); } - new_icon = MEM_mallocN(sizeof(Icon), __func__); + Icon *icon = icon_create(preview->icon_id, ICON_DATA_PREVIEW, preview); + icon->flag = ICON_FLAG_MANAGED; - new_icon->obj = preview; - new_icon->id_type = 0; /* Special, tags as non-ID icon/preview. */ + return preview->icon_id; +} - /* next two lines make sure image gets created */ - new_icon->drawinfo = NULL; - new_icon->drawinfo_free = NULL; +int BKE_icon_geom_ensure(struct Icon_Geom *geom) +{ + BLI_assert(BLI_thread_is_main()); + + if (geom->icon_id) { + return geom->icon_id; + } - BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(preview->icon_id), new_icon); + geom->icon_id = get_next_free_id(); - return preview->icon_id; + icon_create(geom->icon_id, ICON_DATA_GEOM, geom); + /* Not managed for now, we may want this to be configurable per icon). */ + + return geom->icon_id; } Icon *BKE_icon_get(const int icon_id) @@ -647,21 +694,44 @@ void BKE_icon_id_delete(struct ID *id) /** * Remove icon and free data. */ -void BKE_icon_delete(const int icon_id) +bool BKE_icon_delete(const int icon_id) { - Icon *icon; + if (icon_id == 0) { + /* no icon defined for library object */ + return false; + } - if (!icon_id) return; /* no icon defined for library object */ + Icon *icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL); + if (icon) { + icon_free_data(icon); + icon_free(icon); + return true; + } + else { + return false; + } +} - icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL); +bool BKE_icon_delete_unmanaged(const int icon_id) +{ + if (icon_id == 0) { + /* no icon defined for library object */ + return false; + } + Icon *icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL); if (icon) { - if (icon->id_type != 0) { - ((ID *)(icon->obj))->icon_id = 0; + if (UNLIKELY(icon->flag & ICON_FLAG_MANAGED)) { + BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(icon_id), icon); + return false; } else { - ((PreviewImage *)(icon->obj))->icon_id = 0; + icon_free_data(icon); + icon_free(icon); + return true; } - icon_free(icon); + } + else { + return false; } } |