diff options
Diffstat (limited to 'source/blender/blenkernel')
22 files changed, 722 insertions, 77 deletions
diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h index ac8f861fa56..ffbdc6972f4 100644 --- a/source/blender/blenkernel/BKE_appdir.h +++ b/source/blender/blenkernel/BKE_appdir.h @@ -82,6 +82,7 @@ enum { #define BLENDER_STARTUP_FILE "startup.blend" #define BLENDER_USERPREF_FILE "userpref.blend" +#define BLENDER_WORKSPACES_FILE "workspaces.blend" #define BLENDER_QUIT_FILE "quit.blend" #define BLENDER_BOOKMARK_FILE "bookmarks.txt" #define BLENDER_HISTORY_FILE "recent-files.txt" diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index bc3db11f34b..ae87f1097d1 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -28,7 +28,7 @@ * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 280 -#define BLENDER_SUBVERSION 0 +#define BLENDER_SUBVERSION 1 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 6 diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h index ac58451e412..d9fff5343b0 100644 --- a/source/blender/blenkernel/BKE_blendfile.h +++ b/source/blender/blenkernel/BKE_blendfile.h @@ -60,6 +60,10 @@ struct UserDef *BKE_blendfile_userdef_read_from_memory( int BKE_blendfile_userdef_write(const char *filepath, struct ReportList *reports); +struct WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath, struct ReportList *reports); +bool BKE_blendfile_workspace_config_write(struct Main *bmain, const char *filepath, struct ReportList *reports); +void BKE_blendfile_workspace_config_data_free(struct WorkspaceConfigFileData *workspace_config); + /* partial blend file writing */ void BKE_blendfile_write_partial_tag_ID(struct ID *id, bool set); diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index c911d9ec952..b71f5a4aa8e 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -145,6 +145,7 @@ void CTX_py_dict_set(bContext *C, void *value); struct wmWindowManager *CTX_wm_manager(const bContext *C); struct wmWindow *CTX_wm_window(const bContext *C); +struct WorkSpace *CTX_wm_workspace(const bContext *C); struct bScreen *CTX_wm_screen(const bContext *C); struct ScrArea *CTX_wm_area(const bContext *C); struct SpaceLink *CTX_wm_space_data(const bContext *C); diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index c6ec7e9df25..17ab0bf0d2b 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -60,6 +60,7 @@ struct SceneLayer; void BKE_layer_exit(void); struct SceneLayer *BKE_scene_layer_render_active(const struct Scene *scene); +struct SceneLayer *BKE_scene_layer_context_active_ex(const struct Main *bmain, const struct Scene *scene); struct SceneLayer *BKE_scene_layer_context_active(const struct Scene *scene); struct SceneLayer *BKE_scene_layer_add(struct Scene *scene, const char *name); diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 6649cfbb585..dcc15c66c3e 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -95,7 +95,7 @@ void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, const bool id_in_ma struct ListBase *which_libbase(struct Main *mainlib, short type); -#define MAX_LIBARRAY 35 +#define MAX_LIBARRAY 36 int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]); /* Main API */ diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 387045878f3..a616429fa95 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -123,6 +123,7 @@ typedef struct Main { ListBase mask; ListBase linestyle; ListBase cachefiles; + ListBase workspaces; char id_tag_update[MAX_LIBARRAY]; diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 454fba0126e..cd59ef98903 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -52,11 +52,13 @@ struct SceneLayer; struct UnitSettings; struct Main; -#define SCE_COPY_NEW 0 -#define SCE_COPY_EMPTY 1 -#define SCE_COPY_LINK_OB 2 -#define SCE_COPY_LINK_DATA 3 -#define SCE_COPY_FULL 4 +typedef enum eSceneCopyMethod { + SCE_COPY_NEW = 0, + SCE_COPY_EMPTY = 1, + SCE_COPY_LINK_OB = 2, + SCE_COPY_LINK_DATA = 3, + SCE_COPY_FULL = 4, +} eSceneCopyMethod; /* Use as the contents of a 'for' loop: for (SETLOOPER(...)) { ... */ #define SETLOOPER(_sce_basis, _sce_iter, _base) \ diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 7def41d0540..645a99d592f 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -308,11 +308,12 @@ unsigned int BKE_screen_view3d_layer_active( unsigned int BKE_screen_view3d_layer_all(const struct bScreen *sc) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); void BKE_screen_view3d_sync(struct View3D *v3d, struct Scene *scene); -void BKE_screen_view3d_scene_sync(struct bScreen *sc); -void BKE_screen_view3d_main_sync(ListBase *screen_lb, struct Scene *scene); +void BKE_screen_view3d_scene_sync(struct bScreen *sc, struct Scene *scene); void BKE_screen_view3d_twmode_remove(struct View3D *v3d, const int i); void BKE_screen_view3d_main_twmode_remove(ListBase *screen_lb, struct Scene *scene, const int i); void BKE_screen_gpu_fx_validate(struct GPUFXSettings *fx_settings); +bool BKE_screen_is_fullscreen_area(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BKE_screen_is_used(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); /* zoom factor conversion */ float BKE_screen_view3d_zoom_to_fac(float camzoom); diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h new file mode 100644 index 00000000000..e7eaf72dd15 --- /dev/null +++ b/source/blender/blenkernel/BKE_workspace.h @@ -0,0 +1,116 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file BKE_workspace.h + * \ingroup bke + */ + +#ifndef __BKE_WORKSPACE_H__ +#define __BKE_WORKSPACE_H__ + +#include "BLI_compiler_attrs.h" + +struct bScreen; + +typedef struct WorkSpace WorkSpace; +typedef struct WorkSpaceInstanceHook WorkSpaceInstanceHook; +typedef struct WorkSpaceLayout WorkSpaceLayout; + +/** + * Plan is to store the object-mode per workspace, not per object anymore. + * However, there's quite some work to be done for that, so for now, there is just a basic + * implementation of an object <-> workspace object-mode syncing for testing, with some known + * problems. Main problem being that the modes can get out of sync when changing object selection. + * Would require a pile of temporary changes to always sync modes when changing selection. So just + * leaving this here for some testing until object-mode is really a workspace level setting. + */ +#define USE_WORKSPACE_MODE + + +/* -------------------------------------------------------------------- */ +/* Create, delete, init */ + +WorkSpace *BKE_workspace_add(struct Main *bmain, const char *name); +void BKE_workspace_free(WorkSpace *workspace); +void BKE_workspace_remove(struct Main *bmain, WorkSpace *workspace); + +WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const struct Main *bmain); +void BKE_workspace_instance_hook_free(const struct Main *bmain, WorkSpaceInstanceHook *hook); + +struct WorkSpaceLayout *BKE_workspace_layout_add( + WorkSpace *workspace, + struct bScreen *screen, + const char *name) ATTR_NONNULL(); +void BKE_workspace_layout_remove( + struct Main *bmain, + WorkSpace *workspace, WorkSpaceLayout *layout) ATTR_NONNULL(); + + +/* -------------------------------------------------------------------- */ +/* General Utils */ + +WorkSpaceLayout *BKE_workspace_layout_find( + const WorkSpace *workspace, const struct bScreen *screen) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; +WorkSpaceLayout *BKE_workspace_layout_find_global( + const struct Main *bmain, const struct bScreen *screen, + WorkSpace **r_workspace) ATTR_NONNULL(1, 2) ATTR_WARN_UNUSED_RESULT; + +WorkSpaceLayout *BKE_workspace_layout_iter_circular( + const WorkSpace *workspace, WorkSpaceLayout *start, + bool (*callback)(const WorkSpaceLayout *layout, void *arg), + void *arg, const bool iter_backward); + + +/* -------------------------------------------------------------------- */ +/* Getters/Setters */ + +#define GETTER_ATTRS ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT +#define SETTER_ATTRS ATTR_NONNULL(1) + +WorkSpace *BKE_workspace_active_get(WorkSpaceInstanceHook *hook) GETTER_ATTRS; +void BKE_workspace_active_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace) SETTER_ATTRS; +WorkSpaceLayout *BKE_workspace_active_layout_get(const WorkSpaceInstanceHook *hook) GETTER_ATTRS; +void BKE_workspace_active_layout_set(WorkSpaceInstanceHook *hook, WorkSpaceLayout *layout) SETTER_ATTRS; +struct bScreen *BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook) GETTER_ATTRS; +void BKE_workspace_active_screen_set( + WorkSpaceInstanceHook *hook, struct WorkSpace *workspace, struct bScreen *screen) SETTER_ATTRS; +enum ObjectMode BKE_workspace_object_mode_get(const WorkSpace *workspace) GETTER_ATTRS; +#ifdef USE_WORKSPACE_MODE +void BKE_workspace_object_mode_set(WorkSpace *workspace, const enum ObjectMode mode) SETTER_ATTRS; +#endif +struct SceneLayer *BKE_workspace_render_layer_get(const WorkSpace *workspace) GETTER_ATTRS; +void BKE_workspace_render_layer_set(WorkSpace *workspace, struct SceneLayer *layer) SETTER_ATTRS; +struct ListBase *BKE_workspace_layouts_get(WorkSpace *workspace) GETTER_ATTRS; + +const char *BKE_workspace_layout_name_get(const WorkSpaceLayout *layout) GETTER_ATTRS; +void BKE_workspace_layout_name_set( + WorkSpace *workspace, WorkSpaceLayout *layout, const char *new_name) ATTR_NONNULL(); +struct bScreen *BKE_workspace_layout_screen_get(const WorkSpaceLayout *layout) GETTER_ATTRS; +void BKE_workspace_layout_screen_set(WorkSpaceLayout *layout, struct bScreen *screen) SETTER_ATTRS; + +WorkSpaceLayout *BKE_workspace_hook_layout_for_workspace_get( + const WorkSpaceInstanceHook *hook, const WorkSpace *workspace) GETTER_ATTRS; +void BKE_workspace_hook_layout_for_workspace_set( + WorkSpaceInstanceHook *hook, WorkSpace *workspace, WorkSpaceLayout *layout) ATTR_NONNULL(); + +#undef GETTER_ATTRS +#undef SETTER_ATTRS + +#endif /* __BKE_WORKSPACE_H__ */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 1ddc6fce818..71aeb393c97 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -190,6 +190,7 @@ set(SRC intern/tracking_stabilize.c intern/tracking_util.c intern/unit.c + intern/workspace.c intern/world.c intern/writeavi.c intern/writeframeserver.c @@ -302,6 +303,7 @@ set(SRC BKE_tracking.h BKE_unit.h BKE_utildefines.h + BKE_workspace.h BKE_world.h BKE_writeavi.h BKE_writeframeserver.h diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index a521d671ea4..9e244246e16 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -32,6 +32,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "DNA_workspace_types.h" #include "BLI_listbase.h" #include "BLI_string.h" @@ -48,11 +49,13 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_ipo.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_workspace.h" #include "BLO_readfile.h" #include "BLO_writefile.h" @@ -93,7 +96,7 @@ static bool wm_scene_is_visible(wmWindowManager *wm, Scene *scene) { wmWindow *win; for (win = wm->windows.first; win; win = win->next) { - if (win->screen->scene == scene) { + if (win->scene == scene) { return true; } } @@ -162,17 +165,22 @@ static void setup_app_data( * (otherwise we'd be undoing on an off-screen scene which isn't acceptable). * see: T43424 */ + wmWindow *win; bScreen *curscreen = NULL; + SceneLayer *cur_render_layer; bool track_undo_scene; /* comes from readfile.c */ SWAP(ListBase, G.main->wm, bfd->main->wm); + SWAP(ListBase, G.main->workspaces, bfd->main->workspaces); SWAP(ListBase, G.main->screen, bfd->main->screen); - /* we re-use current screen */ + /* we re-use current window and screen */ + win = CTX_wm_window(C); curscreen = CTX_wm_screen(C); - /* but use new Scene pointer */ + /* but use Scene pointer from new file */ curscene = bfd->curscene; + cur_render_layer = bfd->cur_render_layer; track_undo_scene = (mode == LOAD_UNDO && curscreen && curscene && bfd->main->wm.first); @@ -183,32 +191,31 @@ static void setup_app_data( if (curscene == NULL) { curscene = BKE_scene_add(bfd->main, "Empty"); } + if (cur_render_layer == NULL) { + /* fallback to scene layer */ + cur_render_layer = BKE_scene_layer_render_active(curscene); + } if (track_undo_scene) { /* keep the old (free'd) scene, let 'blo_lib_link_screen_restore' * replace it with 'curscene' if its needed */ } - else { - /* and we enforce curscene to be in current screen */ - if (curscreen) { - /* can run in bgmode */ - curscreen->scene = curscene; - } + /* and we enforce curscene to be in current screen */ + else if (win) { /* can run in bgmode */ + win->scene = curscene; } /* BKE_blender_globals_clear will free G.main, here we can still restore pointers */ - blo_lib_link_screen_restore(bfd->main, curscreen, curscene); - /* curscreen might not be set when loading without ui (see T44217) so only re-assign if available */ - if (curscreen) { - curscene = curscreen->scene; + blo_lib_link_restore(bfd->main, CTX_wm_manager(C), curscene, cur_render_layer); + if (win) { + curscene = win->scene; } if (track_undo_scene) { wmWindowManager *wm = bfd->main->wm.first; if (wm_scene_is_visible(wm, bfd->curscene) == false) { curscene = bfd->curscene; - curscreen->scene = curscene; - BKE_screen_view3d_scene_sync(curscreen); + BKE_screen_view3d_scene_sync(curscreen, curscene); } } } @@ -262,12 +269,14 @@ static void setup_app_data( /* this can happen when active scene was lib-linked, and doesn't exist anymore */ if (CTX_data_scene(C) == NULL) { + wmWindow *win = CTX_wm_window(C); + /* in case we don't even have a local scene, add one */ if (!G.main->scene.first) BKE_scene_add(G.main, "Empty"); CTX_data_scene_set(C, G.main->scene.first); - CTX_wm_screen(C)->scene = CTX_data_scene(C); + win->scene = CTX_data_scene(C); curscene = CTX_data_scene(C); } @@ -316,12 +325,10 @@ static void setup_app_data( wmWindowManager *wm = G.main->wm.first; if (wm) { - wmWindow *win; - - for (win = wm->windows.first; win; win = win->next) { - if (win->screen && win->screen->scene) /* zealous check... */ - if (win->screen->scene != curscene) - BKE_scene_set_background(G.main, win->screen->scene); + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (win->scene && win->scene != curscene) { + BKE_scene_set_background(G.main, win->scene); + } } } } @@ -509,6 +516,49 @@ int BKE_blendfile_userdef_write(const char *filepath, ReportList *reports) return retval; } +WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath, ReportList *reports) +{ + BlendFileData *bfd; + WorkspaceConfigFileData *workspace_config = NULL; + + bfd = BLO_read_from_file(filepath, reports, BLO_READ_SKIP_USERDEF); + if (bfd) { + workspace_config = MEM_mallocN(sizeof(*workspace_config), __func__); + workspace_config->main = bfd->main; + workspace_config->workspaces = bfd->main->workspaces; + + MEM_freeN(bfd); + } + + return workspace_config; +} + +bool BKE_blendfile_workspace_config_write(Main *bmain, const char *filepath, ReportList *reports) +{ + int fileflags = G.fileflags & ~(G_FILE_NO_UI | G_FILE_AUTOPLAY | G_FILE_HISTORY); + bool retval = false; + + BKE_blendfile_write_partial_begin(bmain); + + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + BKE_blendfile_write_partial_tag_ID(&workspace->id, true); + } + + if (BKE_blendfile_write_partial(bmain, filepath, fileflags, reports)) { + retval = true; + } + + BKE_blendfile_write_partial_end(bmain); + + return retval; +} + +void BKE_blendfile_workspace_config_data_free(WorkspaceConfigFileData *workspace_config) +{ + BKE_main_free(workspace_config->main); + MEM_freeN(workspace_config); +} + /** \} */ diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index ec0e14d814f..7f24f1c2e5e 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -53,6 +53,7 @@ #include "BKE_main.h" #include "BKE_screen.h" #include "BKE_sound.h" +#include "BKE_workspace.h" #include "RNA_access.h" @@ -69,6 +70,7 @@ struct bContext { struct { struct wmWindowManager *manager; struct wmWindow *window; + struct WorkSpace *workspace; struct bScreen *screen; struct ScrArea *area; struct ARegion *region; @@ -630,6 +632,11 @@ wmWindow *CTX_wm_window(const bContext *C) return ctx_wm_python_context_get(C, "window", &RNA_Window, C->wm.window); } +WorkSpace *CTX_wm_workspace(const bContext *C) +{ + return ctx_wm_python_context_get(C, "workspace", &RNA_WorkSpace, C->wm.workspace); +} + bScreen *CTX_wm_screen(const bContext *C) { return ctx_wm_python_context_get(C, "screen", &RNA_Screen, C->wm.screen); @@ -829,9 +836,11 @@ void CTX_wm_manager_set(bContext *C, wmWindowManager *wm) void CTX_wm_window_set(bContext *C, wmWindow *win) { C->wm.window = win; - C->wm.screen = (win) ? win->screen : NULL; - if (C->wm.screen) - C->data.scene = C->wm.screen->scene; + if (win) { + C->data.scene = win->scene; + } + C->wm.workspace = (win) ? BKE_workspace_active_get(win->workspace_hook) : NULL; + C->wm.screen = (win) ? BKE_workspace_active_screen_get(win->workspace_hook) : NULL; C->wm.area = NULL; C->wm.region = NULL; } @@ -839,9 +848,6 @@ void CTX_wm_window_set(bContext *C, wmWindow *win) void CTX_wm_screen_set(bContext *C, bScreen *screen) { C->wm.screen = screen; - if (C->wm.screen) { - CTX_data_scene_set(C, C->wm.screen->scene); - } C->wm.area = NULL; C->wm.region = NULL; } diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index 70d037d85f3..e905eaeed76 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -82,7 +82,7 @@ static IDType idtypes[] = { { ID_PAL, "Palettes", "palettes", BLT_I18NCONTEXT_ID_PALETTE, IDTYPE_FLAGS_ISLINKABLE }, { ID_PC, "PaintCurve", "paint_curves", BLT_I18NCONTEXT_ID_PAINTCURVE, IDTYPE_FLAGS_ISLINKABLE }, { ID_SCE, "Scene", "scenes", BLT_I18NCONTEXT_ID_SCENE, IDTYPE_FLAGS_ISLINKABLE }, - { ID_SCR, "Screen", "screens", BLT_I18NCONTEXT_ID_SCREEN, 0 }, + { ID_SCR, "Screen", "screens", BLT_I18NCONTEXT_ID_SCREEN, IDTYPE_FLAGS_ISLINKABLE }, { ID_SEQ, "Sequence", "sequences", BLT_I18NCONTEXT_ID_SEQUENCE, 0 }, /* not actually ID data */ { ID_SPK, "Speaker", "speakers", BLT_I18NCONTEXT_ID_SPEAKER, IDTYPE_FLAGS_ISLINKABLE }, { ID_SO, "Sound", "sounds", BLT_I18NCONTEXT_ID_SOUND, IDTYPE_FLAGS_ISLINKABLE }, @@ -91,6 +91,7 @@ static IDType idtypes[] = { { ID_VF, "VFont", "fonts", BLT_I18NCONTEXT_ID_VFONT, IDTYPE_FLAGS_ISLINKABLE }, { ID_WO, "World", "worlds", BLT_I18NCONTEXT_ID_WORLD, IDTYPE_FLAGS_ISLINKABLE }, { ID_WM, "WindowManager", "window_managers", BLT_I18NCONTEXT_ID_WINDOWMANAGER, 0 }, + { ID_WS, "WorkSpace", "workspaces", BLT_I18NCONTEXT_ID_WORKSPACE, IDTYPE_FLAGS_ISLINKABLE }, /** Keep last, not an ID exactly, only include for completeness */ { ID_ID, "ID", "ids", BLT_I18NCONTEXT_ID_ID, 0 }, /* plural is fake */ @@ -210,6 +211,7 @@ int BKE_idcode_to_idfilter(const short idcode) CASE_IDFILTER(TXT); CASE_IDFILTER(VF); CASE_IDFILTER(WO); + CASE_IDFILTER(WS); default: return 0; } @@ -303,6 +305,7 @@ int BKE_idcode_to_index(const short idcode) CASE_IDINDEX(VF); CASE_IDINDEX(WM); CASE_IDINDEX(WO); + CASE_IDINDEX(WS); } BLI_assert(0); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 9b28d9732e5..7ee4afd052d 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -81,6 +81,7 @@ #include "BKE_scene.h" #include "BKE_node.h" #include "BKE_sequencer.h" /* seq_foreground_frame_get() */ +#include "BKE_workspace.h" #include "BLF_api.h" @@ -2544,8 +2545,9 @@ void BKE_image_walk_all_users(const Main *mainp, void *customdata, /* image window, compo node users */ for (wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */ for (win = wm->windows.first; win; win = win->next) { - ScrArea *sa; - for (sa = win->screen->areabase.first; sa; sa = sa->next) { + const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); + + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { if (sa->spacetype == SPACE_VIEW3D) { View3D *v3d = sa->spacedata.first; BGpic *bgpic; diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index d2fa09fa9e9..b088c7b4745 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -38,12 +38,14 @@ #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_workspace.h" #include "DNA_ID.h" #include "DNA_layer_types.h" #include "DNA_object_types.h" #include "DNA_node_types.h" #include "DNA_scene_types.h" +#include "DNA_windowmanager_types.h" #include "DRW_engine.h" @@ -76,14 +78,25 @@ SceneLayer *BKE_scene_layer_render_active(const Scene *scene) } /** - * Returns the SceneLayer to be used for drawing, outliner, and - * other context related areas. + * Returns the SceneLayer to be used for drawing, outliner, and other context related areas. */ +SceneLayer *BKE_scene_layer_context_active_ex(const Main *bmain, const Scene *UNUSED(scene)) +{ + /* XXX We should really pass the workspace as argument, but would require + * some bigger changes since it's often not available where we call this. + * Just working around this by getting active window from WM for now */ + for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { + /* Called on startup, so 'winactive' may not be set, in that case fall back to first window. */ + wmWindow *win = wm->winactive ? wm->winactive : wm->windows.first; + const WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook); + return BKE_workspace_render_layer_get(workspace); + } + + return NULL; +} SceneLayer *BKE_scene_layer_context_active(const Scene *scene) { - /* waiting for workspace to get the layer from context*/ - TODO_LAYER_CONTEXT; - return BKE_scene_layer_render_active(scene); + return BKE_scene_layer_context_active_ex(G.main, scene); } /** diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 4da2108b9d0..b81465a1b1d 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -70,6 +70,7 @@ #include "DNA_vfont_types.h" #include "DNA_windowmanager_types.h" #include "DNA_world_types.h" +#include "DNA_workspace_types.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" @@ -471,7 +472,11 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local) case ID_CF: if (!test) BKE_cachefile_make_local(bmain, (CacheFile *)id, lib_local); return true; + case ID_WS: case ID_SCR: + /* A bit special: can be appended but not linked. Return false + * since supporting make-local doesn't make much sense. */ + return false; case ID_LI: case ID_KE: case ID_WM: @@ -578,6 +583,7 @@ bool id_copy(Main *bmain, ID *id, ID **newid, bool test) case ID_CF: if (!test) *newid = (ID *)BKE_cachefile_copy(bmain, (CacheFile *)id); return true; + case ID_WS: case ID_SCE: case ID_LI: case ID_SCR: @@ -693,6 +699,8 @@ ListBase *which_libbase(Main *mainlib, short type) return &(mainlib->paintcurves); case ID_CF: return &(mainlib->cachefiles); + case ID_WS: + return &(mainlib->workspaces); } return NULL; } @@ -838,6 +846,7 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[INDEX_ID_OB] = &(main->object); lb[INDEX_ID_LS] = &(main->linestyle); /* referenced by scenes */ lb[INDEX_ID_SCE] = &(main->scene); + lb[INDEX_ID_WS] = &(main->workspaces); /* before wm, so it's freed after it! */ lb[INDEX_ID_WM] = &(main->wm); lb[INDEX_ID_MSK] = &(main->mask); @@ -967,6 +976,9 @@ void *BKE_libblock_alloc_notest(short type) case ID_CF: id = MEM_callocN(sizeof(CacheFile), "Cache File"); break; + case ID_WS: + id = MEM_callocN(sizeof(WorkSpace), "Workspace"); + break; } return id; } diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index 0c89a5bea42..d2ee11cc397 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -61,6 +61,8 @@ #include "DNA_sound_types.h" #include "DNA_text_types.h" #include "DNA_vfont_types.h" +#include "DNA_windowmanager_types.h" +#include "DNA_workspace_types.h" #include "DNA_world_types.h" #include "BLI_utildefines.h" @@ -83,6 +85,7 @@ #include "BKE_sca.h" #include "BKE_sequencer.h" #include "BKE_tracking.h" +#include "BKE_workspace.h" #define FOREACH_FINALIZE _finalize @@ -746,13 +749,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call break; } - case ID_SCR: - { - bScreen *screen = (bScreen *) id; - CALLBACK_INVOKE(screen->scene, IDWALK_CB_USER_ONE); - break; - } - case ID_WO: { World *world = (World *) id; @@ -963,6 +959,38 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call } break; } + + case ID_WM: + { + wmWindowManager *wm = (wmWindowManager *)id; + + for (wmWindow *win = wm->windows.first; win; win = win->next) { + ID *workspace = (ID *)BKE_workspace_active_get(win->workspace_hook); + + CALLBACK_INVOKE(win->scene, IDWALK_CB_USER_ONE); + + CALLBACK_INVOKE_ID(workspace, IDWALK_CB_NOP); + /* allow callback to set a different workspace */ + BKE_workspace_active_set(win->workspace_hook, (WorkSpace *)workspace); + } + break; + } + + case ID_WS: + { + WorkSpace *workspace = (WorkSpace *)id; + ListBase *layouts = BKE_workspace_layouts_get(workspace); + + for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) { + bScreen *screen = BKE_workspace_layout_screen_get(layout); + + CALLBACK_INVOKE(screen, IDWALK_CB_NOP); + /* allow callback to set a different screen */ + BKE_workspace_layout_screen_set(layout, screen); + } + + break; + } case ID_GD: { bGPdata *gpencil = (bGPdata *) id; @@ -974,11 +1002,11 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call } /* Nothing needed for those... */ + case ID_SCR: case ID_IM: case ID_VF: case ID_TXT: case ID_SO: - case ID_WM: case ID_PAL: case ID_PC: case ID_CF: @@ -1106,6 +1134,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) return ELEM(id_type_used, ID_MC); /* WARNING! mask->parent.id, not typed. */ case ID_LS: return (ELEM(id_type_used, ID_TE, ID_OB)); + case ID_WS: case ID_IM: case ID_VF: case ID_TXT: diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index 02128ae9c3a..235b10dd1da 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -106,6 +106,7 @@ #include "BKE_scene.h" #include "BKE_text.h" #include "BKE_texture.h" +#include "BKE_workspace.h" #include "BKE_world.h" #include "DEG_depsgraph.h" @@ -883,6 +884,9 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const b case ID_CF: BKE_cachefile_free((CacheFile *)id); break; + case ID_WS: + BKE_workspace_free((WorkSpace *)id); + break; } /* avoid notifying on removed data */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 9de3ab5a93b..92f5dade0a5 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -93,6 +93,7 @@ #include "BKE_sequencer.h" #include "BKE_sound.h" #include "BKE_unit.h" +#include "BKE_workspace.h" #include "BKE_world.h" #include "DEG_depsgraph.h" @@ -1004,7 +1005,7 @@ BaseLegacy *BKE_scene_base_find(Scene *scene, Object *ob) /** * Sets the active scene, mainly used when running in background mode (``--scene`` command line argument). * This is also called to set the scene directly, bypassing windowing code. - * Otherwise #ED_screen_set_scene is used when changing scenes by the user. + * Otherwise #WM_window_change_active_scene is used when changing scenes by the user. */ void BKE_scene_set_background(Main *bmain, Scene *scene) { @@ -1442,8 +1443,8 @@ static bool check_rendered_viewport_visible(Main *bmain) wmWindowManager *wm = bmain->wm.first; wmWindow *window; for (window = wm->windows.first; window != NULL; window = window->next) { - bScreen *screen = window->screen; - Scene *scene = screen->scene; + const bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook); + Scene *scene = window->scene; ScrArea *area; RenderEngineType *type = RE_engines_find(scene->r.engine); if ((type->draw_engine != NULL) || (type->render_to_view == NULL)) { @@ -1755,6 +1756,9 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base) /* for the first loop we should get the layer from context */ SceneLayer *sl = BKE_scene_layer_context_active((*sce_iter)); + /* TODO For first scene (non-background set), we should pass the render layer as argument. + * In some cases we want it to be the workspace one, in other the scene one. */ + TODO_LAYER; if (sl->object_bases.first) { return (Base *)sl->object_bases.first; diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index c5d00d63b6d..b1f8f574b7e 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -596,7 +596,7 @@ void BKE_screen_view3d_sync(View3D *v3d, struct Scene *scene) } } -void BKE_screen_view3d_scene_sync(bScreen *sc) +void BKE_screen_view3d_scene_sync(bScreen *sc, Scene *scene) { /* are there cameras in the views that are not in the scene? */ ScrArea *sa; @@ -605,41 +605,25 @@ void BKE_screen_view3d_scene_sync(bScreen *sc) for (sl = sa->spacedata.first; sl; sl = sl->next) { if (sl->spacetype == SPACE_VIEW3D) { View3D *v3d = (View3D *) sl; - BKE_screen_view3d_sync(v3d, sc->scene); + BKE_screen_view3d_sync(v3d, scene); } } } } -void BKE_screen_view3d_main_sync(ListBase *screen_lb, Scene *scene) -{ - bScreen *sc; - ScrArea *sa; - SpaceLink *sl; - - /* from scene copy to the other views */ - for (sc = screen_lb->first; sc; sc = sc->id.next) { - if (sc->scene != scene) - continue; - - for (sa = sc->areabase.first; sa; sa = sa->next) - for (sl = sa->spacedata.first; sl; sl = sl->next) - if (sl->spacetype == SPACE_VIEW3D) - BKE_screen_view3d_sync((View3D *)sl, scene); - } -} - +/* XXX apply D2687 */ void BKE_screen_view3d_twmode_remove(View3D *v3d, const int i) { const int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM); if (selected_index == i) { - v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */ + v3d->twmode = V3D_MANIP_GLOBAL; } else if (selected_index > i) { v3d->twmode--; } } +/* XXX apply D2687 */ void BKE_screen_view3d_main_twmode_remove(ListBase *screen_lb, Scene *scene, const int i) { bScreen *sc; @@ -700,3 +684,13 @@ void BKE_screen_gpu_fx_validate(GPUFXSettings *fx_settings) GPU_fx_compositor_init_ssao_settings(fx_ssao); } } + +bool BKE_screen_is_fullscreen_area(const bScreen *screen) +{ + return ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL); +} + +bool BKE_screen_is_used(const bScreen *screen) +{ + return (screen->winid != 0); +} diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c new file mode 100644 index 00000000000..8afad317dce --- /dev/null +++ b/source/blender/blenkernel/intern/workspace.c @@ -0,0 +1,399 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/workspace.c + * \ingroup bke + */ + +/* allow accessing private members of DNA_workspace_types.h */ +#define DNA_PRIVATE_WORKSPACE_ALLOW + +#include <stdlib.h> + +#include "BLI_utildefines.h" +#include "BLI_string.h" +#include "BLI_string_utils.h" +#include "BLI_listbase.h" + +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_workspace.h" + +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_workspace_types.h" + +#include "MEM_guardedalloc.h" + + +/* -------------------------------------------------------------------- */ +/* Internal utils */ + +static void workspace_layout_name_set( + WorkSpace *workspace, WorkSpaceLayout *layout, const char *new_name) +{ + BLI_strncpy(layout->name, new_name, sizeof(layout->name)); + BLI_uniquename(&workspace->layouts, layout, "Layout", '.', offsetof(WorkSpaceLayout, name), sizeof(layout->name)); +} + +/** + * This should only be used directly when it is to be expected that there isn't + * a layout within \a workspace that wraps \a screen. Usually - especially outside + * of BKE_workspace - #BKE_workspace_layout_find should be used! + */ +static WorkSpaceLayout *workspace_layout_find_exec( + const WorkSpace *workspace, const bScreen *screen) +{ + return BLI_findptr(&workspace->layouts, screen, offsetof(WorkSpaceLayout, screen)); +} + +static void workspace_relation_add( + ListBase *relation_list, void *parent, void *data) +{ + WorkSpaceDataRelation *relation = MEM_callocN(sizeof(*relation), __func__); + relation->parent = parent; + relation->value = data; + /* add to head, if we switch back to it soon we find it faster. */ + BLI_addhead(relation_list, relation); +} +static void workspace_relation_remove( + ListBase *relation_list, WorkSpaceDataRelation *relation) +{ + BLI_remlink(relation_list, relation); + MEM_freeN(relation); +} + +static void workspace_relation_ensure_updated( + ListBase *relation_list, void *parent, void *data) +{ + WorkSpaceDataRelation *relation = BLI_findptr(relation_list, parent, offsetof(WorkSpaceDataRelation, parent)); + if (relation != NULL) { + relation->value = data; + /* reinsert at the head of the list, so that more commonly used relations are found faster. */ + BLI_remlink(relation_list, relation); + BLI_addhead(relation_list, relation); + } + else { + /* no matching relation found, add new one */ + workspace_relation_add(relation_list, parent, data); + } +} + +static void *workspace_relation_get_data_matching_parent( + const ListBase *relation_list, const void *parent) +{ + WorkSpaceDataRelation *relation = BLI_findptr(relation_list, parent, offsetof(WorkSpaceDataRelation, parent)); + if (relation != NULL) { + return relation->value; + } + else { + return NULL; + } +} + +/** + * Checks if \a screen is already used within any workspace. A screen should never be assigned to multiple + * WorkSpaceLayouts, but that should be ensured outside of the BKE_workspace module and without such checks. + * Hence, this should only be used as assert check before assigining a screen to a workspace. + */ +#ifndef NDEBUG +static bool workspaces_is_screen_used( +#else +static bool UNUSED_FUNCTION(workspaces_is_screen_used)( +#endif + const Main *bmain, bScreen *screen) +{ + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + if (workspace_layout_find_exec(workspace, screen)) { + return true; + } + } + + return false; +} + +/* -------------------------------------------------------------------- */ +/* Create, delete, init */ + +WorkSpace *BKE_workspace_add(Main *bmain, const char *name) +{ + WorkSpace *new_workspace = BKE_libblock_alloc(bmain, ID_WS, name); + return new_workspace; +} + +void BKE_workspace_free(WorkSpace *workspace) +{ + for (WorkSpaceDataRelation *relation = workspace->hook_layout_relations.first, *relation_next; + relation; + relation = relation_next) + { + relation_next = relation->next; + workspace_relation_remove(&workspace->hook_layout_relations, relation); + } + BLI_freelistN(&workspace->layouts); +} + +void BKE_workspace_remove(Main *bmain, WorkSpace *workspace) +{ + for (WorkSpaceLayout *layout = workspace->layouts.first, *layout_next; layout; layout = layout_next) { + layout_next = layout->next; + BKE_workspace_layout_remove(bmain, workspace, layout); + } + + BKE_libblock_free(bmain, workspace); +} + +WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const Main *bmain) +{ + WorkSpaceInstanceHook *hook = MEM_callocN(sizeof(WorkSpaceInstanceHook), __func__); + + /* set an active screen-layout for each possible window/workspace combination */ + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + BKE_workspace_hook_layout_for_workspace_set(hook, workspace, workspace->layouts.first); + } + + return hook; +} +void BKE_workspace_instance_hook_free(const Main *bmain, WorkSpaceInstanceHook *hook) +{ + /* workspaces should never be freed before wm (during which we call this function) */ + BLI_assert(!BLI_listbase_is_empty(&bmain->workspaces)); + + /* Free relations for this hook */ + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + for (WorkSpaceDataRelation *relation = workspace->hook_layout_relations.first, *relation_next; + relation; + relation = relation_next) + { + relation_next = relation->next; + if (relation->parent == hook) { + workspace_relation_remove(&workspace->hook_layout_relations, relation); + } + } + } + + MEM_freeN(hook); +} + +/** + * Add a new layout to \a workspace for \a screen. + */ +WorkSpaceLayout *BKE_workspace_layout_add( + WorkSpace *workspace, + bScreen *screen, + const char *name) +{ + WorkSpaceLayout *layout = MEM_callocN(sizeof(*layout), __func__); + + BLI_assert(!workspaces_is_screen_used(G.main, screen)); + layout->screen = screen; + workspace_layout_name_set(workspace, layout, name); + BLI_addtail(&workspace->layouts, layout); + + return layout; +} + +void BKE_workspace_layout_remove( + Main *bmain, + WorkSpace *workspace, WorkSpaceLayout *layout) +{ + BKE_libblock_free(bmain, BKE_workspace_layout_screen_get(layout)); + BLI_freelinkN(&workspace->layouts, layout); +} + +/* -------------------------------------------------------------------- */ +/* General Utils */ + +WorkSpaceLayout *BKE_workspace_layout_find( + const WorkSpace *workspace, const bScreen *screen) +{ + WorkSpaceLayout *layout = workspace_layout_find_exec(workspace, screen); + if (layout) { + return layout; + } + + printf("%s: Couldn't find layout in this workspace: '%s' screen: '%s'. " + "This should not happen!\n", + __func__, workspace->id.name + 2, screen->id.name + 2); + + return NULL; +} + +/** + * Find the layout for \a screen without knowing which workspace to look in. + * + * \param r_workspace: Optionally return the workspace that contains the looked up layout (if found). + */ +WorkSpaceLayout *BKE_workspace_layout_find_global( + const Main *bmain, const bScreen *screen, + WorkSpace **r_workspace) +{ + WorkSpaceLayout *layout; + + if (r_workspace) { + *r_workspace = NULL; + } + + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + if ((layout = workspace_layout_find_exec(workspace, screen))) { + if (r_workspace) { + *r_workspace = workspace; + } + + return layout; + } + } + + return NULL; +} + +/** + * Circular workspace layout iterator. + * + * \param callback: Custom function which gets executed for each layout. Can return false to stop iterating. + * \param arg: Custom data passed to each \a callback call. + * + * \return the layout at which \a callback returned false. + */ +WorkSpaceLayout *BKE_workspace_layout_iter_circular( + const WorkSpace *workspace, WorkSpaceLayout *start, + bool (*callback)(const WorkSpaceLayout *layout, void *arg), + void *arg, const bool iter_backward) +{ + WorkSpaceLayout *iter_layout; + + if (iter_backward) { + BLI_LISTBASE_CIRCULAR_BACKWARD_BEGIN(&workspace->layouts, iter_layout, start) + { + if (!callback(iter_layout, arg)) { + return iter_layout; + } + } + BLI_LISTBASE_CIRCULAR_BACKWARD_END(&workspace->layouts, iter_layout, start); + } + else { + BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN(&workspace->layouts, iter_layout, start) + { + if (!callback(iter_layout, arg)) { + return iter_layout; + } + } + BLI_LISTBASE_CIRCULAR_FORWARD_END(&workspace->layouts, iter_layout, start) + } + + return NULL; +} + + +/* -------------------------------------------------------------------- */ +/* Getters/Setters */ + +WorkSpace *BKE_workspace_active_get(WorkSpaceInstanceHook *hook) +{ + return hook->active; +} +void BKE_workspace_active_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace) +{ + hook->active = workspace; + if (workspace) { + WorkSpaceLayout *layout = workspace_relation_get_data_matching_parent(&workspace->hook_layout_relations, hook); + if (layout) { + hook->act_layout = layout; + } + } +} + +WorkSpaceLayout *BKE_workspace_active_layout_get(const WorkSpaceInstanceHook *hook) +{ + return hook->act_layout; +} +void BKE_workspace_active_layout_set(WorkSpaceInstanceHook *hook, WorkSpaceLayout *layout) +{ + hook->act_layout = layout; +} + +bScreen *BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook) +{ + return hook->act_layout->screen; +} +void BKE_workspace_active_screen_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace, bScreen *screen) +{ + /* we need to find the WorkspaceLayout that wraps this screen */ + WorkSpaceLayout *layout = BKE_workspace_layout_find(hook->active, screen); + BKE_workspace_hook_layout_for_workspace_set(hook, workspace, layout); +} + +#ifdef USE_WORKSPACE_MODE +ObjectMode BKE_workspace_object_mode_get(const WorkSpace *workspace) +{ + return workspace->object_mode; +} +void BKE_workspace_object_mode_set(WorkSpace *workspace, const ObjectMode mode) +{ + workspace->object_mode = mode; +} +#endif + +SceneLayer *BKE_workspace_render_layer_get(const WorkSpace *workspace) +{ + return workspace->render_layer; +} +void BKE_workspace_render_layer_set(WorkSpace *workspace, SceneLayer *layer) +{ + workspace->render_layer = layer; +} + +ListBase *BKE_workspace_layouts_get(WorkSpace *workspace) +{ + return &workspace->layouts; +} + + +const char *BKE_workspace_layout_name_get(const WorkSpaceLayout *layout) +{ + return layout->name; +} +void BKE_workspace_layout_name_set(WorkSpace *workspace, WorkSpaceLayout *layout, const char *new_name) +{ + workspace_layout_name_set(workspace, layout, new_name); +} + +bScreen *BKE_workspace_layout_screen_get(const WorkSpaceLayout *layout) +{ + return layout->screen; +} +void BKE_workspace_layout_screen_set(WorkSpaceLayout *layout, bScreen *screen) +{ + layout->screen = screen; +} + +WorkSpaceLayout *BKE_workspace_hook_layout_for_workspace_get( + const WorkSpaceInstanceHook *hook, const WorkSpace *workspace) +{ + return workspace_relation_get_data_matching_parent(&workspace->hook_layout_relations, hook); +} +void BKE_workspace_hook_layout_for_workspace_set( + WorkSpaceInstanceHook *hook, WorkSpace *workspace, WorkSpaceLayout *layout) +{ + hook->act_layout = layout; + workspace_relation_ensure_updated(&workspace->hook_layout_relations, hook, layout); +} |