Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/properties_workspace.py2
-rw-r--r--source/blender/blenkernel/intern/workspace.c11
-rw-r--r--source/blender/blenloader/intern/readfile.c3
-rw-r--r--source/blender/editors/screen/workspace_edit.c77
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h3
-rw-r--r--source/blender/makesdna/DNA_workspace_types.h5
-rw-r--r--source/blender/makesrna/intern/rna_workspace.c7
-rw-r--r--source/blender/windowmanager/intern/wm.c8
8 files changed, 114 insertions, 2 deletions
diff --git a/release/scripts/startup/bl_ui/properties_workspace.py b/release/scripts/startup/bl_ui/properties_workspace.py
index 542d770c062..1a245b33cd2 100644
--- a/release/scripts/startup/bl_ui/properties_workspace.py
+++ b/release/scripts/startup/bl_ui/properties_workspace.py
@@ -28,6 +28,8 @@ class WORKSPACE_PT_main(WorkSpaceButtonsPanel, Panel):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
+
+ layout.prop(workspace, "use_pin_scene")
layout.prop(workspace, "object_mode", text="Mode")
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index ef0a3069815..0265dd037b1 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -67,6 +67,8 @@ static void workspace_foreach_id(ID *id, LibraryForeachIDData *data)
{
WorkSpace *workspace = (WorkSpace *)id;
+ BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, workspace->pin_scene, IDWALK_CB_NOP);
+
LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, layout->screen, IDWALK_CB_USER);
}
@@ -120,6 +122,15 @@ static void workspace_blend_read_lib(BlendLibReader *reader, ID *id)
WorkSpace *workspace = (WorkSpace *)id;
Main *bmain = BLO_read_lib_get_main(reader);
+ /* Do not keep the scene reference when appending a workspace. Setting a scene for a workspace is
+ * a convenience feature, but the workspace should never truly depend on scene data. */
+ if (ID_IS_LINKED(id)) {
+ workspace->pin_scene = NULL;
+ }
+ else {
+ BLO_read_id_address(reader, NULL, &workspace->pin_scene);
+ }
+
/* Restore proper 'parent' pointers to relevant data, and clean up unused/invalid entries. */
LISTBASE_FOREACH_MUTABLE (WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) {
relation->parent = NULL;
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 973965ada50..f0d390677bb 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2732,6 +2732,8 @@ void blo_lib_link_restore(Main *oldmain,
LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
lib_link_workspace_layout_restore(id_map, newmain, layout);
}
+ workspace->pin_scene = restore_pointer_by_name(
+ id_map, (ID *)workspace->pin_scene, USER_IGNORE);
}
LISTBASE_FOREACH (wmWindow *, win, &curwm->windows) {
@@ -2745,6 +2747,7 @@ void blo_lib_link_restore(Main *oldmain,
if (win->scene == NULL) {
win->scene = curscene;
}
+ win->unpinned_scene = restore_pointer_by_name(id_map, (ID *)win->unpinned_scene, USER_IGNORE);
if (BKE_view_layer_find(win->scene, win->view_layer_name) == NULL) {
STRNCPY(win->view_layer_name, cur_view_layer->name);
}
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index 01417650b3d..0535a270176 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);
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index f7aaa1186db..5e741508603 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -239,6 +239,9 @@ typedef struct wmWindow {
struct Scene *new_scene;
/** Active view layer displayed in this window. */
char view_layer_name[64];
+ /** The workspace may temporarily override the window's scene with scene pinning. This is the
+ * "overriden" or "default" scene to restore when entering a workspace with no scene pinned. */
+ struct Scene *unpinned_scene;
struct WorkSpaceInstanceHook *workspace_hook;
diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h
index b8ed39bfd5d..a72689badb1 100644
--- a/source/blender/makesdna/DNA_workspace_types.h
+++ b/source/blender/makesdna/DNA_workspace_types.h
@@ -123,6 +123,10 @@ typedef struct WorkSpace {
/** List of #bToolRef */
ListBase tools;
+ /** Optional, scene to switch to when enabling this workspace (NULL to disable). Cleared on
+ * link/append. */
+ struct Scene *pin_scene;
+
char _pad[4];
int object_mode;
@@ -195,6 +199,7 @@ typedef struct WorkSpaceInstanceHook {
typedef enum eWorkSpaceFlags {
WORKSPACE_USE_FILTER_BY_ORIGIN = (1 << 1),
+ WORKSPACE_USE_PIN_SCENE = (1 << 2),
} eWorkSpaceFlags;
#ifdef __cplusplus
diff --git a/source/blender/makesrna/intern/rna_workspace.c b/source/blender/makesrna/intern/rna_workspace.c
index 0b6c3934985..4873831abce 100644
--- a/source/blender/makesrna/intern/rna_workspace.c
+++ b/source/blender/makesrna/intern/rna_workspace.c
@@ -413,6 +413,13 @@ static void rna_def_workspace(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Object Mode", "Switch to this object mode when activating the workspace");
+ prop = RNA_def_property(srna, "use_pin_scene", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", WORKSPACE_USE_PIN_SCENE);
+ RNA_def_property_ui_text(prop,
+ "Pin Scene",
+ "Remember the last used scene for the workspace and switch to it "
+ "whenever this workspace is activated again");
+
/* Flags */
prop = RNA_def_property(srna, "use_filter_by_owner", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 40d9b0b9a35..32cec8f779c 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -81,6 +81,8 @@ static void window_manager_foreach_id(ID *id, LibraryForeachIDData *data)
if (BKE_lib_query_foreachid_iter_stop(data)) {
return;
}
+
+ BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, win->unpinned_scene, IDWALK_CB_NOP);
}
if (BKE_lib_query_foreachid_process_flags_get(data) & IDWALK_INCLUDE_UI) {
@@ -224,6 +226,7 @@ static void lib_link_workspace_instance_hook(BlendLibReader *reader,
{
WorkSpace *workspace = BKE_workspace_active_get(hook);
BLO_read_id_address(reader, id->lib, &workspace);
+
BKE_workspace_active_set(hook, workspace);
}
@@ -239,6 +242,11 @@ static void window_manager_blend_read_lib(BlendLibReader *reader, ID *id)
/* deprecated, but needed for versioning (will be NULL'ed then) */
BLO_read_id_address(reader, NULL, &win->screen);
+ /* The unpinned scene is a UI->Scene-data pointer, and should be NULL'ed on linking (like
+ * WorkSpace.pin_scene). But the WindowManager ID (owning the window) is never linked. */
+ BLI_assert(!ID_IS_LINKED(id));
+ BLO_read_id_address(reader, id->lib, &win->unpinned_scene);
+
LISTBASE_FOREACH (ScrArea *, area, &win->global_areas.areabase) {
BKE_screen_area_blend_read_lib(reader, &wm->id, area);
}