[Bf-blender-cvs] [a284ca9d391] soc-2019-outliner: Outliner: Rewrite walk select
Nathan Craddock
noreply at git.blender.org
Wed Jul 10 22:30:49 CEST 2019
Commit: a284ca9d391f8df91537e8797521576dc2684c58
Author: Nathan Craddock
Date: Wed Jul 10 14:30:02 2019 -0600
Branches: soc-2019-outliner
https://developer.blender.org/rBa284ca9d391f8df91537e8797521576dc2684c58
Outliner: Rewrite walk select
Rather than basing walk select on active flags, use a new TSE_WALK
flag to navigate. Also cleaned up and simplified code.
===================================================================
M source/blender/editors/space_outliner/outliner_select.c
M source/blender/makesdna/DNA_outliner_types.h
===================================================================
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 9419bebfe46..9202b8f87a7 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -1587,6 +1587,7 @@ void OUTLINER_OT_select_box(wmOperatorType *ot)
/* **************** Walk Select Tool ****************** */
+/* Given a tree element return the rightmost child that is visible in the outliner */
static TreeElement *outliner_find_rightmost_visible_child(SpaceOutliner *soops, TreeElement *te)
{
while (te->subtree.last) {
@@ -1600,6 +1601,21 @@ static TreeElement *outliner_find_rightmost_visible_child(SpaceOutliner *soops,
return te;
}
+/* Find previous visible element in the tree */
+static TreeElement *outliner_find_previous_element(SpaceOutliner *soops, TreeElement *walk_element)
+{
+ if (walk_element->prev) {
+ walk_element = outliner_find_rightmost_visible_child(soops, walk_element->prev);
+ }
+ else if (walk_element->parent) {
+ /* Use parent if at beginning of list */
+ walk_element = walk_element->parent;
+ }
+
+ return walk_element;
+}
+
+/* Recursively search up the tree until a successor to a given element is found */
static TreeElement *outliner_element_find_successor_in_parents(TreeElement *te)
{
TreeElement *successor = te;
@@ -1616,125 +1632,121 @@ static TreeElement *outliner_element_find_successor_in_parents(TreeElement *te)
return te;
}
-static TreeElement *do_outliner_select_walk_up(SpaceOutliner *soops, TreeElement *active)
+/* Find next visible element in the tree */
+static TreeElement *outliner_find_next_element(SpaceOutliner *soops, TreeElement *walk_element)
{
- if (active->prev) {
- active = outliner_find_rightmost_visible_child(soops, active->prev);
- }
- else if (active->parent) {
- active = active->parent;
- }
-
- return active;
-}
-
-static TreeElement *do_outliner_select_walk_down(SpaceOutliner *soops, TreeElement *active)
-{
- TreeStoreElem *tselem = TREESTORE(active);
+ TreeStoreElem *tselem = TREESTORE(walk_element);
- if (TSELEM_OPEN(tselem, soops) && active->subtree.first) {
- active = active->subtree.first;
+ if (TSELEM_OPEN(tselem, soops) && walk_element->subtree.first) {
+ walk_element = walk_element->subtree.first;
}
- else if (active->next) {
- active = active->next;
+ else if (walk_element->next) {
+ walk_element = walk_element->next;
}
else {
- active = outliner_element_find_successor_in_parents(active);
+ walk_element = outliner_element_find_successor_in_parents(walk_element);
}
- return active;
+ return walk_element;
}
-static void do_outliner_select_walk(
- bContext *C, SpaceOutliner *soops, TreeElement *active, const int direction, const bool extend)
+static void do_outliner_select_walk(SpaceOutliner *soops,
+ TreeElement *walk_element,
+ const int direction,
+ const bool extend)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- TreeStoreElem *tselem = TREESTORE(active);
+ TreeStoreElem *tselem = TREESTORE(walk_element);
if (!extend) {
outliner_flag_set(&soops->tree, TSE_SELECTED, false);
}
- tselem->flag &= ~TSE_ACTIVE;
+ tselem->flag &= ~TSE_WALK;
switch (direction) {
case OUTLINER_SELECT_WALK_UP:
- active = do_outliner_select_walk_up(soops, active);
+ walk_element = outliner_find_previous_element(soops, walk_element);
break;
case OUTLINER_SELECT_WALK_DOWN:
- active = do_outliner_select_walk_down(soops, active);
+ walk_element = outliner_find_next_element(soops, walk_element);
break;
case OUTLINER_SELECT_WALK_LEFT:
/* Close open element or jummp active to parent */
if (TSELEM_OPEN(tselem, soops)) {
tselem->flag |= TSE_CLOSED;
}
- else if (active->parent) {
- active = active->parent;
+ else if (walk_element->parent) {
+ walk_element = walk_element->parent;
}
break;
case OUTLINER_SELECT_WALK_RIGHT:
- if (!TSELEM_OPEN(tselem, soops) && active->subtree.first) {
+ if (!TSELEM_OPEN(tselem, soops) && walk_element->subtree.first) {
tselem->flag &= ~TSE_CLOSED;
}
break;
}
- TreeStoreElem *tselem_new = TREESTORE(active);
+ TreeStoreElem *tselem_new = TREESTORE(walk_element);
+
+ /* If new element is already selected, deselect the previous element */
if (extend) {
- const short new_flag = (extend && (tselem_new->flag & TSE_SELECTED)) ? 0 : TSE_SELECTED;
- tselem->flag &= ~(TSE_ACTIVE | TSE_SELECTED);
- tselem->flag |= new_flag;
+ tselem->flag = (tselem_new->flag & TSE_SELECTED) ? (tselem->flag & ~TSE_SELECTED) :
+ (tselem->flag | TSE_SELECTED);
}
- /* Activate rather than just setting flags to support mode switching */
- outliner_item_select(soops, active, extend, false);
- do_outliner_item_activate_tree_element(
- C, scene, view_layer, soops, active, tselem_new, extend, false);
+ tselem_new->flag |= TSE_SELECTED | TSE_WALK;
}
-static int outliner_walk_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+/* Find walk select element, or set it if it does not exist.
+ * Changed is set to true if walk element is found, false if it was set */
+static TreeElement *find_walk_select_start_element(SpaceOutliner *soops, bool *changed)
{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- ARegion *ar = CTX_wm_region(C);
- const int direction = RNA_enum_get(op->ptr, "direction");
- const bool extend = RNA_boolean_get(op->ptr, "extend");
+ TreeElement *walk_element = outliner_find_element_with_flag(&soops->tree, TSE_WALK);
- TreeElement *active = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE);
+ *changed = false;
- Object *obact = OBACT(view_layer);
- Base *base = BKE_view_layer_base_find(view_layer, obact);
+ /* If no walk element exists, start from active */
+ if (!walk_element) {
+ TreeElement *active_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE);
- if (obact->mode != OB_MODE_OBJECT) {
- do_outliner_activate_obdata(C, scene, view_layer, base, false);
- }
+ /* If no active element exists, use the first element in the tree */
+ if (!active_element) {
+ walk_element = soops->tree.first;
+ }
+ else {
+ walk_element = active_element;
+ }
- /* Set first element to active if no active exists */
- if (!active) {
- active = soops->tree.first;
- TREESTORE(active)->flag |= TSE_SELECTED | TSE_ACTIVE;
+ *changed = true;
}
- else if (!outliner_is_element_visible(active)) {
- /* If active is not visible, set its first visble parent to active */
- while (!outliner_is_element_visible(active)) {
- active = active->parent;
+
+ /* If walk element is not visible, set that element's first visible parent as walk element */
+ if (!outliner_is_element_visible(walk_element)) {
+ while (!outliner_is_element_visible(walk_element)) {
+ walk_element = walk_element->parent;
}
+ *changed = true;
+ }
+
+ return walk_element;
+}
- outliner_flag_set(&soops->tree, TSE_SELECTED | TSE_ACTIVE, false);
- TREESTORE(active)->flag |= TSE_SELECTED | TSE_ACTIVE;
+static int outliner_walk_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ const int direction = RNA_enum_get(op->ptr, "direction");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ bool changed;
+ TreeElement *walk_element = find_walk_select_start_element(soops, &changed);
+
+ /* If finding the starting walk select element did not move the element, proceed to walk */
+ if (!changed) {
+ do_outliner_select_walk(soops, walk_element, direction, extend);
}
else {
- TreeStoreElem *tselem = TREESTORE(active);
-
- /* If active is not selected, just select it */
- if ((tselem->flag & TSE_SELECTED) == 0) {
- tselem->flag |= TSE_SELECTED;
- }
- else {
- do_outliner_select_walk(C, soops, active, direction, extend);
- }
+ TREESTORE(walk_element)->flag |= TSE_SELECTED | TSE_WALK;
}
if (soops->flag & SO_SYNC_SELECTION) {
@@ -1758,7 +1770,7 @@ void OUTLINER_OT_select_walk(wmOperatorType *ot)
/* identifiers */
ot->name = "Walk Select";
ot->idname = "OUTLINER_OT_select_walk";
- ot->description = "Use walk selection to select tree elements";
+ ot->description = "Use walk navigation to select tree elements";
/* api callbacks */
ot->invoke = outliner_walk_select_invoke;
@@ -1771,7 +1783,7 @@ void OUTLINER_OT_select_walk(wmOperatorType *ot)
direction_items,
0,
"Walk Direction",
- "Select file in this direction");
+ "Select element in this direction");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection on walk");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h
index 5adeb5cd641..561a8876ace 100644
--- a/source/blender/makesdna/DNA_outliner_types.h
+++ b/source/blender/makesdna/DNA_outliner_types.h
@@ -61,6 +61,7 @@ enum {
TSE_DRAG_BEFORE = (1 << 7),
TSE_DRAG_AFTER = (1 << 8),
TSE_ACTIVE = (1 << 9),
+ TSE_WALK = (1 << 10),
TSE_DRAG_ANY = (TSE_DRAG_INTO | TSE_DRAG_BEFORE | TSE_DRAG_AFTER),
};
More information about the Bf-blender-cvs
mailing list