[Bf-blender-cvs] [1cb6813] ui-preview-buttons: Rework previews handling to be 'simpler' on py-level, as discussed with Campbell

Bastien Montagne noreply at git.blender.org
Mon Apr 27 18:18:29 CEST 2015


Commit: 1cb68135fd02be478d73e9afa3f0c73e7042814b
Author: Bastien Montagne
Date:   Mon Apr 27 16:59:04 2015 +0200
Branches: ui-preview-buttons
https://developer.blender.org/rB1cb68135fd02be478d73e9afa3f0c73e7042814b

Rework previews handling to be 'simpler' on py-level, as discussed with Campbell

This removes ID-free previews handling from RNA, adds a low-level hidden API
in bpy.app._previews, and the real previews manager in bpy.utils.

There is still lots of cleanup and renaming to be done...

===================================================================

M	release/scripts/modules/bpy/utils.py
M	source/blender/blenkernel/BKE_icons.h
M	source/blender/blenkernel/intern/icons.c
M	source/blender/editors/interface/interface_icons.c
M	source/blender/makesrna/intern/rna_ID.c
M	source/blender/makesrna/intern/rna_brush.c
M	source/blender/makesrna/intern/rna_main_api.c
M	source/blender/python/intern/CMakeLists.txt
M	source/blender/python/intern/bpy_app.c
A	source/blender/python/intern/bpy_app_previews.c
A	source/blender/python/intern/bpy_app_previews.h

===================================================================

diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py
index 5f235ae..3047f02 100644
--- a/release/scripts/modules/bpy/utils.py
+++ b/release/scripts/modules/bpy/utils.py
@@ -38,6 +38,7 @@ __all__ = (
     "unregister_manual_map",
     "make_rna_paths",
     "manual_map",
+    "previews",
     "resource_path",
     "script_path_user",
     "script_path_pref",
@@ -51,6 +52,7 @@ __all__ = (
     )
 
 from _bpy import (
+        app,
         escape_identifier,
         register_class,
         unregister_class,
@@ -697,3 +699,89 @@ def make_rna_paths(struct_name, prop_name, enum_name):
         else:
             src = src_rna = struct_name
     return src, src_rna, src_enum
+
+
+# High-level previews manager.
+class BPyPreviewsManager:
+    """
+    Fake module like class.
+
+    bpy.app.previews_manager
+    """
+    __slots__ = ('_previews_collections',)
+
+    def __init__(self):
+        self._previews_collections = {}
+
+    def __del__(self):
+        self.clear()
+
+    def new(self, name):
+        """
+        Return a new preview collection, or existing one if 'name' already exists.
+        """
+        return self._previews_collections.setdefault(name, BPyPreviewsCollection(name))
+
+    def _remove(self, name):
+        return self._previews_collections.pop(name, None)
+
+    def delete(self, name):
+        pcoll = self._remove(name)
+        if pcoll is not None:
+            del pcoll
+
+    def clear(self):
+        for pcoll in self._previews_collections.values():
+            del pcoll
+        self._previews_collections.clear()
+
+    def __repr__(self):
+        return "<module like class 'bpy.app.previews_manager'>"
+
+
+class BPyPreviewsCollection:
+    """
+    Fake dict-like class of previews.
+    """
+    __slots__ = ('_previews', '_coll_name')
+
+    def __init__(self, name):
+        self._previews = {}
+        self._coll_name = name
+
+    def __del__(self):
+        self.clear()
+
+    def _gen_key(self, name):
+        return self._coll_name + name
+
+    def new(self, name):
+        """
+        Return a new empty preview, or existing one if 'name' already exists.
+        """
+        return self._previews.setdefault(name, app._previews.new(self._gen_key(name)))
+
+    def load(self, name, path, path_type, force_reload=False):
+        """
+        Return a new preview from given file path, or existing one if 'name' already exists.
+        """
+        pkey = self._gen_key(name)
+        if force_reload:
+            self._previews[name] = p = app._previews.load(pkey, path, path_type, True)
+            return p
+        else:
+            return self._previews.setdefault(name, app._previews.load(pkey, path, path_type, False))
+
+    def release(self, name):
+        p = self._previews.pop(name, None)
+        if p is not None:
+            del p
+            app._previews.release(self._gen_key(name))
+
+    def clear(self):
+        for name in self._previews.keys():
+            _previews.release(self._gen_key(name))
+        self._previews.clear()
+
+previews = BPyPreviewsManager()
+
diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h
index 58f3edf..a950caa 100644
--- a/source/blender/blenkernel/BKE_icons.h
+++ b/source/blender/blenkernel/BKE_icons.h
@@ -90,12 +90,16 @@ void BKE_previewimg_free_id(struct ID *id);
 /* create a new preview image */
 struct PreviewImage *BKE_previewimg_create(void);
 
-struct PreviewImage *BKE_previewimg_thumbnail_create(const char *path, const int source, bool force_update);
-
 /* create a copy of the preview image */
 struct PreviewImage *BKE_previewimg_copy(struct PreviewImage *prv);
 
+struct PreviewImage *BKE_previewimg_name_get(const char *name);
+
+struct PreviewImage *BKE_previewimg_thumbnail_get(const char *name, const char *path, const int source, bool force_update);
+
+void BKE_previewimg_name_release(const char *name);
+
 /* retrieve existing or create new preview image */
-struct PreviewImage *BKE_previewimg_get(struct ID *id);
+struct PreviewImage *BKE_previewimg_id_get(struct ID *id);
 
 #endif /*  __BKE_ICONS_H__ */
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index 857fd1d..a54a80e 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -45,6 +45,7 @@
 
 #include "BLI_utildefines.h"
 #include "BLI_ghash.h"
+#include "BLI_string.h"
 
 #include "BKE_icons.h"
 #include "BKE_global.h" /* only for G.background test */
@@ -125,7 +126,7 @@ void BKE_icons_free(void)
 	}
 
 	if (gFilePreviews) {
-		BLI_ghash_free(gFilePreviews, NULL, BKE_previewimg_freefunc);
+		BLI_ghash_free(gFilePreviews, MEM_freeN, BKE_previewimg_freefunc);
 		gFilePreviews = NULL;
 	}
 }
@@ -144,72 +145,6 @@ PreviewImage *BKE_previewimg_create(void)
 	return prv_img;
 }
 
-/**
- * Generate a PreviewImage from given file path, using thumbnails management.
- */
-PreviewImage *BKE_previewimg_thumbnail_create(const char *path, const int source, bool force_update)
-{
-	PreviewImage *prv = NULL;
-	void **prv_v;
-	int icon_w, icon_h;
-
-	prv_v = BLI_ghash_lookup_p(gFilePreviews, path);
-
-	if (prv_v) {
-		prv = *prv_v;
-		BLI_assert(prv);
-	}
-
-	if (prv && force_update) {
-		BKE_previewimg_clear(prv, ICON_SIZE_ICON);
-		BKE_previewimg_clear(prv, ICON_SIZE_PREVIEW);
-	}
-	else if (!prv) {
-		prv = BKE_previewimg_create();
-		force_update = true;
-	}
-
-	if (force_update) {
-		ImBuf *thumb = IMB_thumb_manage(path, THB_NORMAL, source);
-
-		if (thumb) {
-			prv->w[ICON_SIZE_PREVIEW] = thumb->x;
-			prv->h[ICON_SIZE_PREVIEW] = thumb->y;
-			prv->rect[ICON_SIZE_PREVIEW] = MEM_dupallocN(thumb->rect);
-			prv->flag[ICON_SIZE_PREVIEW] &= ~(CHANGED | USER_EDITED);
-
-			if (thumb->x > thumb->y) {
-				icon_w = ICON_RENDER_DEFAULT_HEIGHT;
-				icon_h = (thumb->y * icon_w) / thumb->x + 1;
-			}
-			else if (thumb->x < thumb->y) {
-				icon_h = ICON_RENDER_DEFAULT_HEIGHT;
-				icon_w = (thumb->x * icon_h) / thumb->y + 1;
-			}
-			else {
-				icon_w = icon_h = ICON_RENDER_DEFAULT_HEIGHT;
-			}
-
-			IMB_scaleImBuf(thumb, icon_w, icon_h);
-			prv->w[ICON_SIZE_ICON] = icon_w;
-			prv->h[ICON_SIZE_ICON] = icon_h;
-			prv->rect[ICON_SIZE_ICON] = MEM_dupallocN(thumb->rect);
-			prv->flag[ICON_SIZE_ICON] &= ~(CHANGED | USER_EDITED);
-
-			IMB_freeImBuf(thumb);
-		}
-
-		if (prv_v) {
-			*prv_v = prv;
-		}
-		else {
-			BLI_ghash_insert(gFilePreviews, (void *)path, prv);
-		}
-	}
-
-	return prv;
-}
-
 void BKE_previewimg_freefunc(void *link)
 {
 	PreviewImage *prv = (PreviewImage *)link;
@@ -299,7 +234,114 @@ void BKE_previewimg_free_id(ID *id)
 	}
 }
 
-PreviewImage *BKE_previewimg_get(ID *id)
+/**
+ * Generate an empty PreviewImage, if not yet existing.
+ */
+PreviewImage *BKE_previewimg_name_get(const char *name)
+{
+	PreviewImage *prv = NULL;
+	void **prv_v;
+
+	prv_v = BLI_ghash_lookup_p(gFilePreviews, name);
+
+	if (prv_v) {
+		prv = *prv_v;
+		BLI_assert(prv);
+	}
+
+	if (!prv) {
+		prv = BKE_previewimg_create();
+	}
+
+	if (prv_v) {
+		*prv_v = prv;
+	}
+	else {
+		BLI_ghash_insert(gFilePreviews, (void *)BLI_strdup(name), prv);
+	}
+
+	return prv;
+}
+
+/**
+ * Generate a PreviewImage from given file path, using thumbnails management, if not yet existing.
+ */
+PreviewImage *BKE_previewimg_thumbnail_get(const char *name, const char *path, const int source, bool force_update)
+{
+	PreviewImage *prv = NULL;
+	void **prv_v;
+	int icon_w, icon_h;
+
+	prv_v = BLI_ghash_lookup_p(gFilePreviews, name);
+
+	if (prv_v) {
+		prv = *prv_v;
+		BLI_assert(prv);
+	}
+
+	if (prv && force_update) {
+		BKE_previewimg_clear(prv, ICON_SIZE_ICON);
+		BKE_previewimg_clear(prv, ICON_SIZE_PREVIEW);
+	}
+	else if (!prv) {
+		prv = BKE_previewimg_create();
+		force_update = true;
+	}
+
+	if (force_update) {
+		ImBuf *thumb = IMB_thumb_manage(path, THB_NORMAL, source);
+
+		if (thumb) {
+			prv->w[ICON_SIZE_PREVIEW] = thumb->x;
+			prv->h[ICON_SIZE_PREVIEW] = thumb->y;
+			prv->rect[ICON_SIZE_PREVIEW] = MEM_dupallocN(thumb->rect);
+			prv->flag[ICON_SIZE_PREVIEW] &= ~(CHANGED | USER_EDITED);
+
+			if (thumb->x > thumb->y) {
+				icon_w = ICON_RENDER_DEFAULT_HEIGHT;
+				icon_h = (thumb->y * icon_w) / thumb->x + 1;
+			}
+			else if (thumb->x < thumb->y) {
+				icon_h = ICON_RENDER_DEFAULT_HEIGHT;
+				icon_w = (thumb->x * icon_h) / thumb->y + 1;
+			}
+			else {
+				icon_w = icon_h = ICON_RENDER_DEFAULT_HEIGHT;
+			}
+
+			IMB_scaleImBuf(thumb, icon_w, icon_h);
+			prv->w[ICON_SIZE_ICON] = icon_w;
+			prv->h[ICON_SIZE_ICON] = icon_h;
+			prv->rect[ICON_SIZE_ICON] = MEM_dupallocN(thumb->rect);
+			prv->flag[ICON_SIZE_ICON] &= ~(CHANGED | USER_EDITED);
+
+			IMB_freeImBuf(thumb);
+		}
+
+		if (prv_v) {
+			*prv_v = prv;
+		}
+		else {
+			BLI_ghash_insert(gFilePreviews, (void *)BLI_strdup(name), prv);
+		}
+	}
+
+	return prv;
+}
+
+void BKE_previewimg_name_release(const char *name)
+{
+	PreviewImage *prv = BLI_ghash_popkey(gFilePreviews, (void *)name, MEM_freeN);
+
+	if (prv) {
+		if (prv->icon_id) {
+			BKE_icon_delete(prv->icon_id);
+		}
+		BKE_previewimg_freefunc(prv);
+	}
+}
+
+PreviewImage *BKE_previewimg_id_get(ID *id)
 {
 	PreviewImage *prv_img = NULL;
 
@@ -346,7 +388,7 @@ void BKE_icon_changed(int id)
 	icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(id));
 	
 	if (icon) {
-		PreviewImage *prv = BKE_previewimg_get((ID *)icon->obj);
+		PreviewImage *prv = BKE_previewimg_id_get((ID *)icon->obj);
 
 		/* all previews changed */
 		if (prv) {
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index fb5960f..979cad1 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1156,7 +1156,7 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al
 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 	}
 	else if (di->type == ICON_TYPE_PREVIEW) {
-		PreviewImage *pi = icon->type ? BKE_previewimg_get((ID *)icon->obj) : icon->obj;
+		PreviewImage *pi = icon->type ? BKE_previewimg_id_get((ID *)icon->obj) : icon->obj;
 
 		if (pi) {
 			/* no create icon on this level in code */
@@ -1183,7 +1183,7 @@ static void u

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list