diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-10-30 12:24:06 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-10-30 12:48:10 +0300 |
commit | 3624c0600747d9ebde1d55f1811f810ba08c6d17 (patch) | |
tree | 7d82bc607f37b019e2fabe83dbb55b3f838b93d5 | |
parent | 9e85812acc88fa469aecccb1d5ed3e28e362278a (diff) |
Fix outliner mode toggling with multi-object pose/edit mode
For edit/pose modes clicking in the mode-column would include other
selected objects (besides the active object), causing other objects to
remain in the mode even though Control wasn't held.
Also replace `ED_object_mode_generic_exit(...)` on all objects with a
single call to `ED_object_mode_set(...)` so switching modes will only
exit the current mode, leaving objects in other modes unchanged.
-rw-r--r-- | source/blender/editors/space_outliner/outliner_select.c | 93 |
1 files changed, 63 insertions, 30 deletions
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 8034996f5c3..01aaa3c04e0 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -75,63 +75,96 @@ #include "outliner_intern.h" +/** + * \note changes to selection are by convention and not essential. + */ static void do_outliner_item_editmode_toggle(bContext *C, Scene *scene, Base *base) { Main *bmain = CTX_data_main(C); Object *ob = base->object; + bool changed = false; if (BKE_object_is_in_editmode(ob)) { - ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA); - WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); + changed = ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA); + if (changed) { + ED_object_base_select(base, BA_DESELECT); + WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); + } } else { - ED_object_editmode_enter_ex(CTX_data_main(C), scene, ob, EM_NO_CONTEXT); - WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL); + changed = ED_object_editmode_enter_ex(CTX_data_main(C), scene, ob, EM_NO_CONTEXT); + if (changed) { + ED_object_base_select(base, BA_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL); + } + } + + if (changed) { + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + ED_outliner_select_sync_from_object_tag(C); } } -static void do_outliner_item_posemode_toggle(bContext *C, Base *base) +/** + * \note changes to selection are by convention and not essential. + */ +static void do_outliner_item_posemode_toggle(bContext *C, Scene *scene, Base *base) { Main *bmain = CTX_data_main(C); Object *ob = base->object; if (ID_IS_LINKED(ob)) { BKE_report(CTX_wm_reports(C), RPT_WARNING, "Cannot pose libdata"); + return; } - else if (ob->mode & OB_MODE_POSE) { - ED_object_posemode_exit_ex(bmain, ob); - WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); + + bool changed = false; + if (ob->mode & OB_MODE_POSE) { + changed = ED_object_posemode_exit_ex(bmain, ob); + if (changed) { + ED_object_base_select(base, BA_DESELECT); + WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); + } } else { - ED_object_posemode_enter_ex(bmain, ob); - WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL); + changed = ED_object_posemode_enter_ex(bmain, ob); + if (changed) { + ED_object_base_select(base, BA_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL); + } + } + + if (changed) { + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + ED_outliner_select_sync_from_object_tag(C); } } -/* Swap the current active object from the interaction mode with the given base. */ +/** + * Swap the current active object from the interaction mode with the given base. + * + * \note Changes to selection _are_ needed in this case, + * since entering the object mode uses the selection. + * + * If we didn't want to touch selection we could add an option to the operators + * not to do multi-object editing. + */ static void do_outliner_item_mode_toggle_generic(bContext *C, TreeViewContext *tvc, Base *base) { - Main *bmain = CTX_data_main(C); - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); const int active_mode = tvc->obact->mode; - /* Return all objects to object mode. */ - FOREACH_OBJECT_BEGIN (tvc->view_layer, ob_iter) { - ED_object_mode_generic_exit(bmain, depsgraph, tvc->scene, ob_iter); - } - FOREACH_OBJECT_END; - WM_toolsystem_update_from_context_view3d(C); - - Base *base_active = BKE_view_layer_base_find(tvc->view_layer, tvc->obact); - if (base_active != base) { - ED_object_base_select(base_active, BA_DESELECT); - ED_object_base_activate(C, base); - ED_object_base_select(base, BA_SELECT); + if (ED_object_mode_set(C, OB_MODE_OBJECT)) { + Base *base_active = BKE_view_layer_base_find(tvc->view_layer, tvc->obact); + if (base_active != base) { + BKE_view_layer_base_deselect_all(tvc->view_layer); + BKE_view_layer_base_select_and_set_active(tvc->view_layer, base); + DEG_id_tag_update(&tvc->scene->id, ID_RECALC_SELECT); - /* XXX: Must add undo step between activation and setting mode to prevent an assert. */ - ED_undo_push(C, "outliner mode toggle"); - ED_object_mode_set(C, active_mode); - ED_outliner_select_sync_from_object_tag(C); + /* XXX: Must add undo step between activation and setting mode to prevent an assert. */ + ED_undo_push(C, "outliner mode toggle"); + ED_object_mode_set(C, active_mode); + ED_outliner_select_sync_from_object_tag(C); + } } } @@ -159,7 +192,7 @@ void outliner_item_mode_toggle(bContext *C, do_outliner_item_editmode_toggle(C, tvc->scene, base); } else if (tvc->ob_pose && ob->type == OB_ARMATURE) { - do_outliner_item_posemode_toggle(C, base); + do_outliner_item_posemode_toggle(C, tvc->scene, base); } } } |