[Bf-blender-cvs] [f4f6e5b6652] blender2.8: Outliner: Aggregate ID types and object types together with numbers

Dalai Felinto noreply at git.blender.org
Fri Jun 22 13:57:38 CEST 2018


Commit: f4f6e5b6652ea7df47b000ae2c8682eac29abfa3
Author: Dalai Felinto
Date:   Thu Jun 21 19:40:14 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBf4f6e5b6652ea7df47b000ae2c8682eac29abfa3

Outliner: Aggregate ID types and object types together with numbers

We draw small numbers over the icon of multiple objects of the same type.
Also, we make all inlined elements to be non-clickabled.

For modifiers we still do it the old way. In this case it is more important
to see the order then the ammount.

Reviewers: brecht, campbellbarton
Subscribers: billreynish, venomgfx

Design task and mockup: T54707
Differential Revision: https://developer.blender.org/D3497

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

M	source/blender/editors/space_outliner/outliner_draw.c
M	source/blender/makesdna/DNA_ID.h
M	source/blender/makesdna/DNA_object_types.h

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

diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 75d9b256b91..4368b74f8a7 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -51,6 +51,7 @@
 #include "BKE_deform.h"
 #include "BKE_fcurve.h"
 #include "BKE_global.h"
+#include "BKE_idcode.h"
 #include "BKE_layer.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
@@ -905,7 +906,7 @@ static void UNUSED_FUNCTION(tselem_draw_gp_icon_uibut)(struct DrawIconArg *arg,
 
 static void tselem_draw_icon(
         uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te,
-        float alpha)
+        float alpha, const bool is_clickable)
 {
 	struct DrawIconArg arg;
 	float aspect;
@@ -926,6 +927,7 @@ static void tselem_draw_icon(
 	arg.y = y;
 
 #define ICON_DRAW(_icon) UI_icon_draw_alpha(x, y, _icon, alpha)
+#define ICON_CLICK_DRAW(_icon) if (!is_clickable) ICON_DRAW(_icon); else tselem_draw_icon_uibut(&arg, _icon)
 
 	if (tselem->type) {
 		switch (tselem->type) {
@@ -1197,33 +1199,33 @@ static void tselem_draw_icon(
 			Object *ob = (Object *)tselem->id;
 			switch (ob->type) {
 				case OB_LAMP:
-					tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break;
+					ICON_CLICK_DRAW(ICON_OUTLINER_OB_LAMP); break;
 				case OB_MESH:
-					tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break;
+					ICON_CLICK_DRAW(ICON_OUTLINER_OB_MESH); break;
 				case OB_CAMERA:
-					tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break;
+					ICON_CLICK_DRAW(ICON_OUTLINER_OB_CAMERA); break;
 				case OB_CURVE:
-					tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break;
+					ICON_CLICK_DRAW(ICON_OUTLINER_OB_CURVE); break;
 				case OB_MBALL:
-					tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break;
+					ICON_CLICK_DRAW(ICON_OUTLINER_OB_META); break;
 				case OB_LATTICE:
-					tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break;
+					ICON_CLICK_DRAW(ICON_OUTLINER_OB_LATTICE); break;
 				case OB_ARMATURE:
-					tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break;
+					ICON_CLICK_DRAW(ICON_OUTLINER_OB_ARMATURE); break;
 				case OB_FONT:
-					tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break;
+					ICON_CLICK_DRAW(ICON_OUTLINER_OB_FONT); break;
 				case OB_SURF:
-					tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break;
+					ICON_CLICK_DRAW(ICON_OUTLINER_OB_SURFACE); break;
 				case OB_SPEAKER:
-					tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SPEAKER); break;
+					ICON_CLICK_DRAW(ICON_OUTLINER_OB_SPEAKER); break;
 				case OB_LIGHTPROBE:
-					tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LIGHTPROBE); break;
+					ICON_CLICK_DRAW(ICON_OUTLINER_OB_LIGHTPROBE); break;
 				case OB_EMPTY:
 					if (ob->dup_group) {
-						tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_GROUP_INSTANCE);
+						ICON_CLICK_DRAW(ICON_OUTLINER_OB_GROUP_INSTANCE);
 					}
 					else {
-						tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY);
+						ICON_CLICK_DRAW(ICON_OUTLINER_OB_EMPTY);
 					}
 					break;
 			}
@@ -1331,13 +1333,137 @@ static void tselem_draw_icon(
 #undef ICON_DRAW
 }
 
+/**
+ * For icon-only children of a collapsed tree,
+ * Draw small number over the icon to show how many items of this type are displayed.
+ */
+static void outliner_draw_iconrow_number(
+        const uiFontStyle *fstyle,
+        int offsx, int ys,
+        const eOLDrawState active,
+        const int num_elements)
+{
+	float color[4] = {0.4f, 0.4f, 0.4f, 0.9f};
+	copy_v3_fl(color, 0.2f);
+	if (active != OL_DRAWSEL_NONE) {
+		copy_v3_fl(color, 0.65f);
+		color[3] = 1.0f;
+	}
+
+	float ufac = 0.25f * UI_UNIT_X;
+	float offset_x = (float) offsx + UI_UNIT_X * 0.35f;
+
+	UI_draw_roundbox_corner_set(UI_CNR_ALL);
+	UI_draw_roundbox_aa(true,
+	                    offset_x + ufac,
+	                    (float)ys - UI_UNIT_Y * 0.2f + ufac,
+	                    offset_x + UI_UNIT_X - ufac,
+	                    (float)ys - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac,
+	                    (float)UI_UNIT_Y / 2.0f - ufac,
+	                    color);
+
+	/* Now the numbers. */
+	unsigned char text_col[4];
+
+	UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
+	text_col[3] = 255;
+
+	uiFontStyle fstyle_small = *fstyle;
+	fstyle_small.points *= 0.8f;
+
+	/* We treat +99 as 4 digits to make sure the (eyeballed) alignment looks nice. */
+	int num_digits = 4;
+	char number_text[4] = "+99\0";
+	if (num_elements < 100) {
+		BLI_snprintf(number_text, sizeof(number_text), "%d", num_elements);
+		num_digits = num_elements < 10 ? 1 : 2;
+	}
+	UI_fontstyle_draw_simple(&fstyle_small,
+	                         (offset_x + ufac + UI_UNIT_X * (2 - num_digits) * 0.12f),
+	                         (float)ys - UI_UNIT_Y * 0.095f + ufac,
+	                         number_text, text_col);
+	UI_fontstyle_set(fstyle);
+	glEnable(GL_BLEND); /* Roundbox and text drawing disables. */
+}
+
+static void outliner_draw_iconrow_doit(
+        uiBlock *block, TreeElement *te,
+        const uiFontStyle *fstyle,
+        int xmax, int *offsx, int ys, float alpha_fac,
+        const eOLDrawState active,
+        const int num_elements)
+{
+	TreeStoreElem *tselem = TREESTORE(te);
+
+	if (active != OL_DRAWSEL_NONE) {
+		float ufac = UI_UNIT_X / 20.0f;
+		float color[4] = {1.0f, 1.0f, 1.0f, 0.4f};
+
+		UI_draw_roundbox_corner_set(UI_CNR_ALL);
+		color[3] *= alpha_fac;
+
+		UI_draw_roundbox_aa(true,
+		                    (float) *offsx + 1.0f * ufac,
+		                    (float)ys + 1.0f * ufac,
+		                    (float)*offsx + UI_UNIT_X - 1.0f * ufac,
+		                    (float)ys + UI_UNIT_Y - ufac,
+		                    (float)UI_UNIT_Y / 2.0f - ufac,
+		                    color);
+		glEnable(GL_BLEND); /* Roundbox disables. */
+	}
+
+	/* No inlined icon should be clickable. */
+	tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f * alpha_fac, false);
+	te->xs = *offsx;
+	te->ys = ys;
+	te->xend = (short)*offsx + UI_UNIT_X;
+
+	if (num_elements > 1) {
+		outliner_draw_iconrow_number(fstyle, *offsx, ys, active, num_elements);
+	}
+	(*offsx) += UI_UNIT_X;
+}
+
+/**
+ * Return the index to use based on the TreeElement ID and object type
+ *
+ * We use a continuum of indeces until we get to the object datablocks
+ * and we then make room for the object types.
+ */
+static int tree_element_id_type_to_index(TreeElement *te)
+{
+	TreeStoreElem *tselem = TREESTORE(te);
+
+	const int id_index = tselem->type == 0 ? BKE_idcode_to_index(te->idcode) : INDEX_ID_GR;
+	if (id_index < INDEX_ID_OB) {
+		return id_index;
+	}
+	else if (id_index == INDEX_ID_OB) {
+		const Object *ob = (Object *)tselem->id;
+		return INDEX_ID_OB + ob->type;
+	}
+	else {
+		return id_index + OB_TYPE_MAX;
+	}
+}
+
 static void outliner_draw_iconrow(
-        bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
+        bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
         ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac)
 {
 	eOLDrawState active;
 	const Object *obact = OBACT(view_layer);
 
+	struct {
+		eOLDrawState active[INDEX_ID_MAX + OB_TYPE_MAX];
+		int num_elements[INDEX_ID_MAX + OB_TYPE_MAX];
+		TreeElement *tree_element[INDEX_ID_MAX + OB_TYPE_MAX];
+	} data = {
+		.active = {0},
+		.num_elements = {0},
+		.tree_element = {NULL},
+	};
+
 	for (TreeElement *te = lb->first; te; te = te->next) {
 		/* exit drawing early */
 		if ((*offsx) - UI_UNIT_X > xmax)
@@ -1363,41 +1489,48 @@ static void outliner_draw_iconrow(
 				active = tree_element_type_active(C, scene, view_layer, soops, te, tselem, OL_SETSEL_NONE, false);
 			}
 
-			if (active != OL_DRAWSEL_NONE) {
-				float ufac = UI_UNIT_X / 20.0f;
-				float color[4] = {1.0f, 1.0f, 1.0f, 0.4f};
-
-				UI_draw_roundbox_corner_set(UI_CNR_ALL);
-				color[3] *= alpha_fac;
-
-				UI_draw_roundbox_aa(
-				        true,
-				        (float) *offsx + 1.0f * ufac,
-				        (float)ys + 1.0f * ufac,
-				        (float)*offsx + UI_UNIT_X - 1.0f * ufac,
-				        (float)ys + UI_UNIT_Y - ufac,
-				        (float)UI_UNIT_Y / 2.0f - ufac,
-				        color);
-				glEnable(GL_BLEND); /* roundbox disables */
+			if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
+				outliner_draw_iconrow_doit(block, te, fstyle, xmax, offsx, ys, alpha_fac, active, 1);
+			}
+			else {
+				const int index = tree_element_id_type_to_index(te);
+				data.num_elements[index]++;
+				if ((data.tree_element[index] == NULL) ||
+				    (active > data.active[index]))
+				{
+					data.tree_element[index] = te;
+				}
+				data.active[index] = MAX2(active, data.active[index]);
 			}
-
-			tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f * alpha_fac);
-			te->xs = *offsx;
-			te->ys = ys;
-			te->xend = (short)*offsx + UI_UNIT_X;
-			te->flag |= TE_ICONROW; // for click
-
-			(*offsx) += UI_UNIT_X;
 		}
 
 		/* this tree element always has same amount of branches, so don't draw */
 		if (tselem->type != TSE_R_LAYER) {
 			outliner_draw_iconrow(
-			        C, block, scene, view_layer, soops,
+			        C, block, fstyle, scene, view_layer, soops,
 			        &te->subtree, level + 1, xmax, offsx, ys, alpha_fac);
 		}
 	}
 
+	for (int i = 0; i < INDEX_ID_MAX; i++) {
+		const int num_subtypes = (i == INDEX_ID_OB) ? OB_TYPE_MAX : 1;
+		/* See tree_element_id_type_to_index for the index logic. */
+		int index_base = i;
+		if (i > INDEX_ID_OB){
+			index_base += OB_TYPE_MAX;
+		}
+		for (int j = 0; j < num_subtypes; j++) {
+			const int index = index_base + j;
+			if (data.num_elements[index] != 0) {
+				outliner_draw_iconrow_doit(block,
+				                           data.tree_element[index],
+				                           fstyle,
+				                           xmax, offsx, ys, alpha_fac,
+				                           data.active[index],
+				                           data.num_elements[index]);
+			}
+		}
+	}
 }
 
 /* closed tree element */
@@ -1538,7 +1671,7 @@ static void outliner_draw_tree_element(
 		/* datatype icon */
 
 		if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_EL

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list