Fix T71812: Outliner walk navigation not activating

Walk navigation used a separate flag to select the element. This is
because activation and mode toggling were connected until rB702e00f91088
cleaned up the selection logic.

Now walk navigation can activate objects and other elements without
changing modes. This also addresses renaming in the outliner which
did renaming from the active element, not the walk element.
This commit is contained in:
Nathan Craddock 2020-06-20 16:02:54 -06:00
parent 2d9ab46e0b
commit 8ce1a60262
Notes: blender-bot 2023-02-14 00:10:08 +01:00
Referenced by issue #71812, Outliner: Active selection not in sync when navigating with arrow keys
4 changed files with 34 additions and 75 deletions

View File

@ -288,8 +288,6 @@ void outliner_object_mode_toggle(struct bContext *C,
ViewLayer *view_layer,
Base *base);
void outliner_set_walk_element(struct SpaceOutliner *soops, struct TreeStoreElem *tselem);
bool outliner_item_is_co_over_name_icons(const TreeElement *te, float view_co_x);
bool outliner_item_is_co_within_close_toggle(const TreeElement *te, float view_co_x);

View File

@ -1143,13 +1143,6 @@ eOLDrawState tree_element_type_active(bContext *C,
/* ================================================ */
/* Set the walk navigation start element */
void outliner_set_walk_element(SpaceOutliner *soops, TreeStoreElem *tselem)
{
outliner_flag_set(&soops->tree, TSE_ACTIVE_WALK, false);
tselem->flag |= TSE_ACTIVE_WALK;
}
/**
* Action when clicking to activate an item (typically under the mouse cursor),
* but don't do any cursor intersection checks.
@ -1192,8 +1185,6 @@ static void do_outliner_item_activate_tree_element(bContext *C,
recursive && tselem->type == 0);
}
outliner_set_walk_element(soops, tselem);
if (tselem->type == 0) { // the lib blocks
if (do_activate_data == false) {
/* Only select in outliner. */
@ -1656,80 +1647,60 @@ static TreeElement *outliner_find_next_element(SpaceOutliner *soops, TreeElement
}
static TreeElement *do_outliner_select_walk(SpaceOutliner *soops,
TreeElement *walk_element,
TreeElement *te,
const int direction,
const bool extend,
const bool toggle_all)
{
TreeStoreElem *tselem = TREESTORE(walk_element);
if (!extend) {
outliner_flag_set(&soops->tree, TSE_SELECTED, false);
}
tselem->flag &= ~TSE_ACTIVE_WALK;
TreeStoreElem *tselem = TREESTORE(te);
switch (direction) {
case UI_SELECT_WALK_UP:
walk_element = outliner_find_previous_element(soops, walk_element);
te = outliner_find_previous_element(soops, te);
break;
case UI_SELECT_WALK_DOWN:
walk_element = outliner_find_next_element(soops, walk_element);
te = outliner_find_next_element(soops, te);
break;
case UI_SELECT_WALK_LEFT:
outliner_item_openclose(walk_element, false, toggle_all);
outliner_item_openclose(te, false, toggle_all);
break;
case UI_SELECT_WALK_RIGHT:
outliner_item_openclose(walk_element, true, toggle_all);
outliner_item_openclose(te, true, toggle_all);
break;
}
TreeStoreElem *tselem_new = TREESTORE(walk_element);
/* If new element is already selected, deselect the previous element */
TreeStoreElem *tselem_new = TREESTORE(te);
if (extend) {
tselem->flag = (tselem_new->flag & TSE_SELECTED) ? (tselem->flag & ~TSE_SELECTED) :
(tselem->flag | TSE_SELECTED);
}
tselem_new->flag |= TSE_SELECTED | TSE_ACTIVE_WALK;
return walk_element;
return te;
}
/* 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 */
/* Find the active element to walk from, or set one if none exists.
* Changed is set to true if the active elmenet is found, or false if it was set */
static TreeElement *find_walk_select_start_element(SpaceOutliner *soops, bool *changed)
{
TreeElement *walk_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE_WALK);
TreeElement *active_te = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE);
*changed = false;
/* If no walk element exists, start from active */
if (!walk_element) {
TreeElement *active_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE);
/* 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;
}
/* If no active element exists, use the first element in the tree */
if (!active_te) {
active_te = soops->tree.first;
*changed = true;
}
/* If walk element is not visible, set that element's first visible parent as walk element */
if (!outliner_is_element_visible(walk_element)) {
TREESTORE(walk_element)->flag &= ~TSE_ACTIVE_WALK;
while (!outliner_is_element_visible(walk_element)) {
walk_element = walk_element->parent;
/* If the active element is not visible, activate the first visible parent element */
if (!outliner_is_element_visible(active_te)) {
while (!outliner_is_element_visible(active_te)) {
active_te = active_te->parent;
}
*changed = true;
}
return walk_element;
return active_te;
}
/* Scroll the outliner when the walk element reaches the top or bottom boundary */
@ -1758,18 +1729,18 @@ static int outliner_walk_select_invoke(bContext *C, wmOperator *op, const wmEven
const bool toggle_all = RNA_boolean_get(op->ptr, "toggle_all");
bool changed;
TreeElement *walk_element = find_walk_select_start_element(soops, &changed);
TreeElement *active_te = find_walk_select_start_element(soops, &changed);
/* If finding the starting walk select element did not move the element, proceed to walk */
/* If finding the active element did not modify the selection, proceed to walk */
if (!changed) {
walk_element = do_outliner_select_walk(soops, walk_element, direction, extend, toggle_all);
}
else {
TREESTORE(walk_element)->flag |= TSE_SELECTED | TSE_ACTIVE_WALK;
active_te = do_outliner_select_walk(soops, active_te, direction, extend, toggle_all);
}
outliner_item_select(
C, soops, active_te, OL_ITEM_SELECT | OL_ITEM_ACTIVATE | (extend ? OL_ITEM_EXTEND : 0));
/* Scroll outliner to focus on walk element */
outliner_walk_scroll(region, walk_element);
outliner_walk_scroll(region, active_te);
ED_outliner_select_sync_from_outliner(C, soops);
ED_region_tag_redraw(region);

View File

@ -392,7 +392,6 @@ void ED_outliner_select_sync_from_outliner(bContext *C, SpaceOutliner *soops)
}
static void outliner_select_sync_from_object(ViewLayer *view_layer,
SpaceOutliner *soops,
Object *obact,
TreeElement *te,
TreeStoreElem *tselem)
@ -404,7 +403,6 @@ static void outliner_select_sync_from_object(ViewLayer *view_layer,
if (base && (ob == obact)) {
tselem->flag |= TSE_ACTIVE;
outliner_set_walk_element(soops, tselem);
}
else {
tselem->flag &= ~TSE_ACTIVE;
@ -418,8 +416,7 @@ static void outliner_select_sync_from_object(ViewLayer *view_layer,
}
}
static void outliner_select_sync_from_edit_bone(SpaceOutliner *soops,
EditBone *ebone_active,
static void outliner_select_sync_from_edit_bone(EditBone *ebone_active,
TreeElement *te,
TreeStoreElem *tselem)
{
@ -427,7 +424,6 @@ static void outliner_select_sync_from_edit_bone(SpaceOutliner *soops,
if (ebone == ebone_active) {
tselem->flag |= TSE_ACTIVE;
outliner_set_walk_element(soops, tselem);
}
else {
tselem->flag &= ~TSE_ACTIVE;
@ -441,8 +437,7 @@ static void outliner_select_sync_from_edit_bone(SpaceOutliner *soops,
}
}
static void outliner_select_sync_from_pose_bone(SpaceOutliner *soops,
bPoseChannel *pchan_active,
static void outliner_select_sync_from_pose_bone(bPoseChannel *pchan_active,
TreeElement *te,
TreeStoreElem *tselem)
{
@ -451,7 +446,6 @@ static void outliner_select_sync_from_pose_bone(SpaceOutliner *soops,
if (pchan == pchan_active) {
tselem->flag |= TSE_ACTIVE;
outliner_set_walk_element(soops, tselem);
}
else {
tselem->flag &= ~TSE_ACTIVE;
@ -465,15 +459,12 @@ static void outliner_select_sync_from_pose_bone(SpaceOutliner *soops,
}
}
static void outliner_select_sync_from_sequence(SpaceOutliner *soops,
Sequence *sequence_active,
TreeStoreElem *tselem)
static void outliner_select_sync_from_sequence(Sequence *sequence_active, TreeStoreElem *tselem)
{
Sequence *seq = (Sequence *)tselem->id;
if (seq == sequence_active) {
tselem->flag |= TSE_ACTIVE;
outliner_set_walk_element(soops, tselem);
}
else {
tselem->flag &= ~TSE_ACTIVE;
@ -510,22 +501,22 @@ static void outliner_sync_selection_to_outliner(ViewLayer *view_layer,
if (tselem->type == 0 && te->idcode == ID_OB) {
if (sync_types->object) {
outliner_select_sync_from_object(view_layer, soops, active_data->object, te, tselem);
outliner_select_sync_from_object(view_layer, active_data->object, te, tselem);
}
}
else if (tselem->type == TSE_EBONE) {
if (sync_types->edit_bone) {
outliner_select_sync_from_edit_bone(soops, active_data->edit_bone, te, tselem);
outliner_select_sync_from_edit_bone(active_data->edit_bone, te, tselem);
}
}
else if (tselem->type == TSE_POSE_CHANNEL) {
if (sync_types->pose_bone) {
outliner_select_sync_from_pose_bone(soops, active_data->pose_channel, te, tselem);
outliner_select_sync_from_pose_bone(active_data->pose_channel, te, tselem);
}
}
else if (tselem->type == TSE_SEQUENCE) {
if (sync_types->sequence) {
outliner_select_sync_from_sequence(soops, active_data->sequence, tselem);
outliner_select_sync_from_sequence(active_data->sequence, tselem);
}
}
else {

View File

@ -62,8 +62,7 @@ enum {
TSE_DRAG_AFTER = (1 << 8),
/* Needed because outliner-only elements can be active */
TSE_ACTIVE = (1 << 9),
/* Needed because walk selection should not activate */
TSE_ACTIVE_WALK = (1 << 10),
/* TSE_ACTIVE_WALK = (1 << 10), */ /* Unused */
TSE_DRAG_ANY = (TSE_DRAG_INTO | TSE_DRAG_BEFORE | TSE_DRAG_AFTER),
};