[Bf-blender-cvs] [bc11cb3daa6] blender2.8: UI: Support for runtime geometry icons

Campbell Barton noreply at git.blender.org
Fri Apr 20 15:35:28 CEST 2018


Commit: bc11cb3daa60c28e41bc400df29d7f8085993888
Author: Campbell Barton
Date:   Fri Apr 20 15:15:10 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBbc11cb3daa60c28e41bc400df29d7f8085993888

UI: Support for runtime geometry icons

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

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/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_widgets.c
M	source/blender/gpu/CMakeLists.txt
M	source/blender/gpu/GPU_shader.h
M	source/blender/gpu/intern/gpu_shader.c
A	source/blender/gpu/shaders/gpu_shader_2D_smooth_color_uniform_alpha_vert.glsl

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

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;
 	}
 }
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index a33dcfc5ab6..6bcdc2f9266 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -35,6 +35,7 @@
 
 #include "GPU_draw.h"
 #include "GPU_matrix.h"
+#include "GPU_batch.h"
 #include "GPU_immediate.h"
 
 #include "BLI_blenlib.h"
@@ -98,6 +99,7 @@ typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
 #define ICON_TYPE_TEXTURE   1
 #define ICON_TYPE_BUFFER    2
 #define ICON_TYPE_VECTOR    3
+#define ICON_TYPE_GEOM      4
 
 typedef struct DrawInfo {
 	int type;
@@ -107,6 +109,9 @@ typedef struct DrawInfo {
 		struct {
 			VectorDrawFunc func;
 		} vector;
+		struct {
+			Gwn_Batch *batch;
+		} geom;
 		struct {
 			IconImage *image;
 		} buffer;
@@ -742,18 +747,61 @@ void UI_icons_free_drawinfo(void *drawinfo)
 				MEM_freeN(di->data.buffer.image);
 			}
 		}
+		else if (di->type == ICON_TYPE_GEOM) {
+			if (di->data.geom.batch) {
+				GWN_BATCH_DISCARD_SAFE(di->data.geom.batch);
+			}
+		}
 
 		MEM_freeN(di);
 	}
 }
 
-static DrawInfo *icon_create_drawinfo(void)
+/**
+ * #Icon.data_type and #Icon.obj
+ */
+static DrawInfo *icon_create_drawinfo(int icon_data_type, void *icon_obj)
 {
 	DrawInfo *di = NULL;
 
 	di = MEM_callocN(sizeof(DrawInfo), "di_icon");
-	di->type = ICON_TYPE_PREVIEW;
 
+	if (ELEM(icon_data_type, ICON_DATA_ID, ICON_DATA_PREVIEW)) {
+		di->type = ICON_TYPE_PREVIEW;
+	}
+	else if (icon_data_type == ICON_DATA_GEOM) {
+		di->type = ICON_TYPE_GEOM;
+
+		struct Icon_Geom *geom = icon_obj;
+		static Gwn_VertFormat format = {0};
+		static struct { uint pos, color; } attr_id;
+		if (format.attrib_ct == 0) {
+			attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_U8, 2, GWN_FETCH_INT_TO_FLOAT_UNIT);
+			attr_id.color = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+		}
+		Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+		GWN_vertbuf_data_alloc(vbo, geom->coords_len * 3);
+		GWN_vertbuf_attr_fill(vbo, attr_id.pos, geom->coords);
+		GWN_vertbuf_attr_fill(vbo, attr_id.color, geom->colors);
+
+		Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+		di->data.geom.batch = batch;
+	}
+	else {
+		BLI_assert(0);
+	}
+
+	return di;
+}
+
+static DrawInfo *icon_ensure_drawinfo(Icon *icon)
+{
+	if (icon->drawinfo) {
+		return icon->drawinfo;
+	}
+	DrawInfo *di = icon_create_drawinfo(icon->obj_type, icon->obj);
+	icon->drawinfo = di;
+	icon->drawinfo_free = UI_icons_free_drawinfo;
 	return di;
 }
 
@@ -771,40 +819,27 @@ int UI_icon_get_width(int icon_id)
 		return 0;
 	}
 	
-	di = (DrawInfo *)icon->drawinfo;
-	if (!di) {
-		di = icon_create_drawinfo();
-		icon->drawinfo = di;
-	}
-
-	if (di)
+	di = icon_ensure_drawinfo(icon);
+	if (di) {
 		return ICON_DEFAULT_WIDTH;
+	}
 
 	return 0;
 }
 
 int UI_icon_get_height(int icon_id)
 {
-	Icon *icon = NULL;
-	DrawInfo *di = 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list