[Bf-blender-cvs] [ae8e845] blender2.8: Outliner: Element mouse hover feedback

Julian Eisel noreply at git.blender.org
Sat Oct 15 01:03:37 CEST 2016


Commit: ae8e84547005dcb67ed85a6c65a1e0f031758dbf
Author: Julian Eisel
Date:   Sat Oct 15 00:40:33 2016 +0200
Branches: blender2.8
https://developer.blender.org/rBae8e84547005dcb67ed85a6c65a1e0f031758dbf

Outliner: Element mouse hover feedback

Some little UI polish to get familiar with outliner code (but also because it's a useful feature). Committing to blender2.8 branch but can also port to master (2.7) if wanted.

This basically causes the mouse hovered element to be highlighted. Contrast of the highlight should be fine, even with a non-default theme. Also did some minor cleanup.

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

M	source/blender/editors/space_outliner/outliner_draw.c
M	source/blender/editors/space_outliner/outliner_edit.c
M	source/blender/editors/space_outliner/outliner_intern.h
M	source/blender/editors/space_outliner/outliner_ops.c
M	source/blender/makesdna/DNA_outliner_types.h

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

diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 7cf40ca..7f45784 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1448,23 +1448,8 @@ static void outliner_draw_tree_element(
 		
 		glEnable(GL_BLEND);
 
-		/* start by highlighting search matches 
-		 *	we don't expand items when searching in the datablocks but we 
-		 *	still want to highlight any filter matches. 
-		 */
-		if ((SEARCHING_OUTLINER(soops) || (soops->outlinevis == SO_DATABLOCKS && soops->search_string[0] != 0)) &&
-		    (tselem->flag & TSE_SEARCHMATCH))
-		{
-			char col[4];
-			UI_GetThemeColorType4ubv(TH_MATCH, SPACE_OUTLINER, col);
-			col[3] = alpha;
-			glColor4ubv((GLubyte *)col);
-			glRecti(startx, *starty + 1, ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
-		}
-
 		/* colors for active/selected data */
 		if (tselem->type == 0) {
-			
 			if (te->idcode == ID_SCE) {
 				if (tselem->id == (ID *)scene) {
 					glColor4ub(255, 255, 255, alpha);
@@ -1650,7 +1635,7 @@ static void outliner_draw_tree_element(
 	}
 }
 
-static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx, int *starty)
+static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int startx, int *starty)
 {
 	TreeElement *te;
 	TreeStoreElem *tselem;
@@ -1670,7 +1655,7 @@ static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx,
 		*starty -= UI_UNIT_Y;
 		
 		if (TSELEM_OPEN(tselem, soops))
-			outliner_draw_hierarchy(soops, &te->subtree, startx + UI_UNIT_X, starty);
+			outliner_draw_hierarchy_lines(soops, &te->subtree, startx + UI_UNIT_X, starty);
 	}
 	
 	/* vertical line */
@@ -1706,34 +1691,71 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
 	}
 }
 
-static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty) 
+static void outliner_draw_highlights_recursive(
+        const ARegion *ar, const SpaceOops *soops, const ListBase *lb,
+        const float col_selection[4], const float col_highlight[4], const float col_searchmatch[4],
+        int start_x, int *io_start_y)
 {
-	TreeElement *te;
-	TreeStoreElem *tselem;
-	
-	for (te = lb->first; te; te = te->next) {
-		tselem = TREESTORE(te);
-		
+	const bool is_searching = SEARCHING_OUTLINER(soops) ||
+	                          (soops->outlinevis == SO_DATABLOCKS && soops->search_string[0] != 0);
+
+	for (TreeElement *te = lb->first; te; te = te->next) {
+		const TreeStoreElem *tselem = TREESTORE(te);
+		const int start_y = *io_start_y;
+
 		/* selection status */
 		if (tselem->flag & TSE_SELECTED) {
-			glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
+			glColor4fv(col_selection);
+			glRecti(0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1);
+		}
+
+		/* search match highlights
+		 *   we don't expand items when searching in the datablocks but we
+		 *   still want to highlight any filter matches. */
+		if (is_searching && (tselem->flag & TSE_SEARCHMATCH)) {
+			glColor4fv(col_searchmatch);
+			glRecti(start_x, start_y + 1, ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1);
+		}
+
+		/* mouse hover highlights */
+		if (tselem->flag & TSE_HIGHLIGHTED) {
+			glColor4fv(col_highlight);
+			glRecti(0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1);
+		}
+
+		*io_start_y -= UI_UNIT_Y;
+		if (TSELEM_OPEN(tselem, soops)) {
+			outliner_draw_highlights_recursive(
+			            ar, soops, &te->subtree, col_selection, col_highlight, col_searchmatch,
+			            start_x, io_start_y);
 		}
-		*starty -= UI_UNIT_Y;
-		if (TSELEM_OPEN(tselem, soops)) outliner_draw_selection(ar, soops, &te->subtree, starty);
 	}
 }
 
+static void outliner_draw_highlights(ARegion *ar, SpaceOops *soops, int startx, int *starty)
+{
+	const float col_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f};
+	float col_selection[4], col_searchmatch[4];
+
+	UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col_selection);
+	col_selection[3] = 1.0f; /* no alpha */
+	UI_GetThemeColor4fv(TH_MATCH, col_searchmatch);
+	col_searchmatch[3] = 0.5f;
+
+	glEnable(GL_BLEND);
+	outliner_draw_highlights_recursive(ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch,
+	                                   startx, starty);
+	glDisable(GL_BLEND);
+}
 
 static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegion *ar,
                                SpaceOops *soops, TreeElement **te_edit)
 {
 	const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
-	TreeElement *te;
 	int starty, startx;
-	float col[3];
-		
+
 	glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); // only once
-	
+
 	if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
 		/* struct marks */
 		UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
@@ -1741,23 +1763,22 @@ static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegio
 		starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
 		outliner_draw_struct_marks(ar, soops, &soops->tree, &starty);
 	}
-	
-	/* always draw selection fill before hierarchy */
-	UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col);
-	glColor3fv(col);
+
+	/* draw highlights before hierarchy */
 	starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
-	outliner_draw_selection(ar, soops, &soops->tree, &starty);
+	startx = 0;
+	outliner_draw_highlights(ar, soops, startx, &starty);
 	
 	// gray hierarchy lines
 	UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.4f);
 	starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET;
 	startx = 6;
-	outliner_draw_hierarchy(soops, &soops->tree, startx, &starty);
-	
+	outliner_draw_hierarchy_lines(soops, &soops->tree, startx, &starty);
+
 	// items themselves
 	starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
 	startx = 0;
-	for (te = soops->tree.first; te; te = te->next) {
+	for (TreeElement *te = soops->tree.first; te; te = te->next) {
 		outliner_draw_tree_element(C, block, fstyle, scene, ar, soops, te, startx, &starty, te_edit);
 	}
 }
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 8eb53d0..bfb87b6 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -151,7 +151,69 @@ TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2]
 }
 
 /* ************************************************************** */
-/* Click Activated */
+
+/* Highlight --------------------------------------------------- */
+
+/**
+ * Try to find an item under y-coordinate \a view_co_y (view-space).
+ * \note Recursive
+ */
+static TreeElement *outliner_find_item_at_y(
+        const SpaceOops *soops, const ListBase *tree, float view_co_y)
+{
+	for (TreeElement *te_iter = tree->first; te_iter; te_iter = te_iter->next) {
+		if (view_co_y < (te_iter->ys + UI_UNIT_Y)) {
+			if (view_co_y > te_iter->ys) {
+				/* co_y is inside this element */
+				return te_iter;
+			}
+			else if (TSELEM_OPEN(te_iter->store_elem, soops)) {
+				/* co_y is lower than current element, possibly inside children */
+				TreeElement *te_sub = outliner_find_item_at_y(soops, &te_iter->subtree, view_co_y);
+				if (te_sub) {
+					return te_sub;
+				}
+			}
+		}
+	}
+
+	return NULL;
+}
+
+static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+	ARegion *ar = CTX_wm_region(C);
+	SpaceOops *soops = CTX_wm_space_outliner(C);
+	const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]);
+
+	TreeElement *hovered_te = outliner_find_item_at_y(soops, &soops->tree, my);
+	bool changed;
+
+	if (!hovered_te || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED)) {
+		changed = outliner_set_flag(soops, &soops->tree, TSE_HIGHLIGHTED, false);
+		if (hovered_te) {
+			hovered_te->store_elem->flag |= TSE_HIGHLIGHTED;
+			changed = true;
+		}
+	}
+
+	if (changed) {
+		ED_region_tag_redraw(ar);
+	}
+
+	return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+}
+
+void OUTLINER_OT_highlight_update(wmOperatorType *ot)
+{
+	ot->name = "Update Highlight";
+	ot->idname = "OUTLINER_OT_highlight_update";
+	ot->description = "Update the item highlight based on the current mouse position";
+
+	ot->invoke = outliner_highlight_update;
+
+	ot->poll = ED_operator_outliner_active;
+}
 
 /* Toggle Open/Closed ------------------------------------------- */
 
@@ -742,17 +804,34 @@ int outliner_has_one_flag(SpaceOops *soops, ListBase *lb, short flag, const int
 	return 0;
 }
 
-void outliner_set_flag(SpaceOops *soops, ListBase *lb, short flag, short set)
+/**
+ * Set or unset \a flag for all outliner elements in \a lb and sub-trees.
+ * \return if any flag was modified.
+ */
+bool outliner_set_flag(SpaceOops *soops, ListBase *lb, short flag, short set)
 {
 	TreeElement *te;
 	TreeStoreElem *tselem;
-	
+	bool changed = false;
+	bool has_flag;
+
 	for (te = lb->first; te; te = te->next) {
 		tselem = TREESTORE(te);
-		if (set == 0) tselem->flag &= ~flag;
-		else tselem->flag |= flag;
-		outliner_set_flag(soops, &te->subtree, flag, set);
+		has_flag = (tselem->flag & flag);
+		if (set == 0) {
+			if (has_flag) {
+				tselem->flag &= ~flag;
+				changed = true;
+			}
+		}
+		else if (!has_flag){
+			tselem->flag |= flag;
+			changed = true;
+		}
+		changed |= outliner_set_flag(soops, &te->subtree, flag, set);
 	}
+
+	return changed;
 }
 
 /* Restriction Columns ------------------------------- */
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index e95ca32..74c59fb 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -167,7 +167,7 @@ void outliner_do_object_operation(
 int common_restrict_check(struct bContext *C, struct Object *ob);
 
 int outliner_has_one_flag(struct SpaceOops *soops, ListBase *lb, short flag, const int curlevel);
-void outliner_set_flag(struct SpaceOops *soops, ListBase *lb, short flag, short set);
+bool outliner_set_flag(struct SpaceOops *soops, ListBase *lb, short flag, short set);
 
 void object_toggle_visibilit

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list