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. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to