diff options
Diffstat (limited to 'source/blender/editors/screen/workspace_edit.c')
-rw-r--r-- | source/blender/editors/screen/workspace_edit.c | 130 |
1 files changed, 123 insertions, 7 deletions
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index 01417650b3d..9a6bdc98d76 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,11 +215,12 @@ 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); - /* TODO(campbell): tools */ + /* TODO(@campbellbarton): tools */ LISTBASE_FOREACH (WorkSpaceLayout *, layout_old, &workspace_old->layouts) { WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate( @@ -286,6 +359,12 @@ static int workspace_append_activate_exec(bContext *C, wmOperator *op) BLO_LIBLINK_APPEND_RECURSIVE); if (appended_workspace) { + if (BLT_translate_new_dataname()) { + /* Translate workspace name */ + BKE_libblock_rename( + bmain, &appended_workspace->id, CTX_DATA_(BLT_I18NCONTEXT_ID_WORKSPACE, idname)); + } + /* Set defaults. */ BLO_update_defaults_workspace(appended_workspace, NULL); @@ -368,8 +447,14 @@ static void workspace_append_button(uiLayout *layout, BLI_assert(STREQ(ot_append->idname, "WORKSPACE_OT_append_activate")); PointerRNA opptr; - uiItemFullO_ptr( - layout, ot_append, workspace->id.name + 2, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); + uiItemFullO_ptr(layout, + ot_append, + CTX_DATA_(BLT_I18NCONTEXT_ID_WORKSPACE, workspace->id.name + 2), + ICON_NONE, + NULL, + WM_OP_EXEC_DEFAULT, + 0, + &opptr); RNA_string_set(&opptr, "idname", id->name + 2); RNA_string_set(&opptr, "filepath", filepath); } @@ -422,7 +507,8 @@ static void workspace_add_menu(bContext *UNUSED(C), uiLayout *layout, void *temp static int workspace_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - uiPopupMenu *pup = UI_popup_menu_begin(C, op->type->name, ICON_ADD); + uiPopupMenu *pup = UI_popup_menu_begin( + C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, op->type->name), ICON_ADD); uiLayout *layout = UI_popup_menu_layout(pup); uiItemMenuF(layout, IFACE_("General"), ICON_NONE, workspace_add_menu, NULL); @@ -434,7 +520,7 @@ static int workspace_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS char *template = link->data; char display_name[FILE_MAX]; - BLI_path_to_display_name(display_name, sizeof(display_name), template); + BLI_path_to_display_name(display_name, sizeof(display_name), IFACE_(template)); /* Steals ownership of link data string. */ uiItemMenuFN(layout, display_name, ICON_NONE, workspace_add_menu, template); @@ -512,6 +598,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 +635,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 */ |