diff options
Diffstat (limited to 'source/blender/editors/screen/workspace_edit.c')
-rw-r--r-- | source/blender/editors/screen/workspace_edit.c | 107 |
1 files changed, 105 insertions, 2 deletions
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index 01417650b3d..cb29f15420c 100644 --- a/source/blender/editors/screen/workspace_edit.c +++ b/source/blender/editors/screen/workspace_edit.c @@ -54,17 +54,87 @@ WorkSpace *ED_workspace_add(Main *bmain, const char *name) return BKE_workspace_add(bmain, name); } +static void workspace_exit(WorkSpace *workspace, wmWindow *win) +{ + /* Scene pinning: Store whatever scene was active when leaving the workspace. It's reactivated + * when the workspace gets reactivated as well. */ + if (workspace->flags & WORKSPACE_USE_PIN_SCENE) { + workspace->pin_scene = WM_window_get_active_scene(win); + } + else { + /* The active scene may have been changed. So also always update the unpinned scene to the + * latest when leaving a workspace that has no scene pinning. */ + win->unpinned_scene = WM_window_get_active_scene(win); + } +} + +/** + * State changes (old workspace to new workspace): + * 1) unpinned -> pinned + * * Store current scene as the unpinned one (done in #workspace_exit()). + * * Change the current scene to the pinned one. + * 2) pinned -> pinned + * * Change the current scene to the new pinned one. + * 3) pinned -> unpinned + * * Change current scene back to the unpinned one + * 4) unpinned -> unpinned + * * Make sure the unpinned scene is active. + * + * Note that the pin scene must also be updated when leaving a workspace with a pinned scene. + * That's done separately via workspace_exit() above. + */ +static void workspace_scene_pinning_update(WorkSpace *workspace_new, + const WorkSpace *workspace_old, + bContext *C) +{ + wmWindow *win = CTX_wm_window(C); + Main *bmain = CTX_data_main(C); + Scene *active_scene = WM_window_get_active_scene(win); + + const bool is_new_pinned = (workspace_new->flags & WORKSPACE_USE_PIN_SCENE); + const bool is_old_pinned = (workspace_old->flags & WORKSPACE_USE_PIN_SCENE); + + /* State changes 1 and 2. */ + if (is_new_pinned) { + if (workspace_new->pin_scene && (workspace_new->pin_scene != active_scene)) { + WM_window_set_active_scene(bmain, C, win, workspace_new->pin_scene); + workspace_new->pin_scene = NULL; + } + } + /* State change 3 - Changing from workspace with pinned scene to unpinned scene. */ + else if (is_old_pinned) { + if (win->unpinned_scene) { + WM_window_set_active_scene(bmain, C, win, win->unpinned_scene); + } + else { + /* When leaving a workspace where the pinning was just enabled, the unpinned scene wasn't set + * yet. */ + win->unpinned_scene = active_scene; + } + } + else { + /* When leaving a workspace where the pinning was just disabled, we still want to restore the + * unpinned scene. */ + if (win->unpinned_scene) { + WM_window_set_active_scene(bmain, C, win, win->unpinned_scene); + } + } + + BLI_assert(WM_window_get_active_scene(win)); +} + /** * Changes the object mode (if needed) to the one set in \a workspace_new. * Object mode is still stored on object level. In future it should all be workspace level instead. */ static void workspace_change_update(WorkSpace *workspace_new, - const WorkSpace *workspace_old, + WorkSpace *workspace_old, bContext *C, wmWindowManager *wm) { + workspace_scene_pinning_update(workspace_new, workspace_old, C); /* needs to be done before changing mode! (to ensure right context) */ - UNUSED_VARS(workspace_old, workspace_new, C, wm); + UNUSED_VARS(wm); #if 0 Object *ob_act = CTX_data_active_object(C) eObjectMode mode_old = workspace_old->object_mode; eObjectMode mode_new = workspace_new->object_mode; @@ -113,6 +183,8 @@ bool ED_workspace_change(WorkSpace *workspace_new, bContext *C, wmWindowManager return false; } + workspace_exit(workspace_old, win); + screen_change_prepare(screen_old, screen_new, bmain, C, win); if (screen_new == NULL) { @@ -143,6 +215,7 @@ WorkSpace *ED_workspace_duplicate(WorkSpace *workspace_old, Main *bmain, wmWindo WorkSpace *workspace_new = ED_workspace_add(bmain, workspace_old->id.name + 2); workspace_new->flags = workspace_old->flags; + workspace_new->pin_scene = workspace_old->pin_scene; workspace_new->object_mode = workspace_old->object_mode; workspace_new->order = workspace_old->order; BLI_duplicatelist(&workspace_new->owner_ids, &workspace_old->owner_ids); @@ -512,6 +585,35 @@ static void WORKSPACE_OT_reorder_to_front(wmOperatorType *ot) ot->exec = workspace_reorder_to_front_exec; } +static int workspace_scene_pin_toggle(bContext *C, wmOperator *UNUSED(op)) +{ + WorkSpace *workspace = workspace_context_get(C); + + /* Trivial. The operator is only needed to display a superimposed extra icon, which + * requires an operator. */ + workspace->flags ^= WORKSPACE_USE_PIN_SCENE; + + WM_event_add_notifier(C, NC_WORKSPACE, NULL); + + return OPERATOR_FINISHED; +} + +static void WORKSPACE_OT_scene_pin_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Pin Scene to Workspace"; + ot->description = + "Remember the last used scene for the current workspace and switch to it whenever this " + "workspace is activated again"; + ot->idname = "WORKSPACE_OT_scene_pin_toggle"; + + /* api callbacks */ + ot->poll = workspace_context_poll; + ot->exec = workspace_scene_pin_toggle; + + ot->flag = OPTYPE_INTERNAL; +} + void ED_operatortypes_workspace(void) { WM_operatortype_append(WORKSPACE_OT_duplicate); @@ -520,6 +622,7 @@ void ED_operatortypes_workspace(void) WM_operatortype_append(WORKSPACE_OT_append_activate); WM_operatortype_append(WORKSPACE_OT_reorder_to_back); WM_operatortype_append(WORKSPACE_OT_reorder_to_front); + WM_operatortype_append(WORKSPACE_OT_scene_pin_toggle); } /** \} Workspace Operators */ |