Main Workspace Integration

This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup)

Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know!
(Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.)

== Main Changes/Features
* Introduces the new Workspaces as data-blocks.
* Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces.
* Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces).
* Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead.
* Store screen-layouts (`bScreen`) per workspace.
* Store an active screen-layout per workspace. Changing the workspace will enable this layout.
* Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.)
* Store an active render layer per workspace.
* Moved mode switch from 3D View header to Info Editor header.
* Store active scene in window (not directly workspace related, but overlaps quite a bit).
* Removed 'Use Global Scene' User Preference option.
* Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well.
* Default .blend only contains one workspace ("General").
* Support appending workspaces.

Opening files without UI and commandline rendering should work fine.

Note that the UI is temporary! We plan to introduce a new global topbar
that contains the workspace options and tabs for switching workspaces.

== Technical Notes
* Workspaces are data-blocks.
* Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now.
* A workspace can be active in multiple windows at the same time.
* The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned).
* The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that).
* Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs.
* `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those.
* Added scene operators `SCENE_OT_`. Was previously done through screen operators.

== BPY API Changes
* Removed `Screen.scene`, added `Window.scene`
* Removed `UserPreferencesView.use_global_scene`
* Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces`
* Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer`
* Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name)

== What's left?
* There are a few open design questions (T50521). We should find the needed answers and implement them.
* Allow adding and removing individual workspaces from workspace configuration (needs UI design).
* Get the override system ready and support overrides per workspace.
* Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc).
* Allow enabling add-ons per workspace.
* Support custom workspace keymaps.
* Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later.
* Get the topbar done.
* Workspaces need a proper icon, current one is just a placeholder :)

Reviewed By: campbellbarton, mont29

Tags: #user_interface, #bf_blender_2.8

Maniphest Tasks: T50521

Differential Revision: https://developer.blender.org/D2451
This commit is contained in:
Julian Eisel
2017-06-01 19:56:58 +02:00
parent 0af93cf1ac
commit 7f564d74f9
131 changed files with 3653 additions and 1082 deletions

View File

@@ -585,6 +585,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
bf_editor_armature
bf_editor_physics
bf_editor_render
bf_editor_scene
bf_editor_screen
bf_editor_sculpt_paint
bf_editor_sound

View File

@@ -223,6 +223,10 @@
* \ingroup editors
*/
/** \defgroup edscene scene
* \ingroup editors
*/
/** \defgroup edsculpt sculpt and paint
* \ingroup editors
*/

Binary file not shown.

View File

@@ -28,7 +28,10 @@ class INFO_HT_header(Header):
layout = self.layout
window = context.window
workspace = context.workspace
screen = context.screen
scene = context.scene
layer = context.render_layer
rd = scene.render
row = layout.row(align=True)
@@ -36,15 +39,27 @@ class INFO_HT_header(Header):
INFO_MT_editor_menus.draw_collapsible(context, layout)
if window.screen.show_fullscreen:
layout.separator()
if screen.show_fullscreen:
layout.operator("screen.back_to_previous", icon='SCREEN_BACK', text="Back to Previous")
layout.separator()
else:
layout.template_ID_preview(context.window, "screen", new="screen.new", unlink="screen.delete", rows=2, cols=6)
layout.template_ID(context.screen, "scene", new="scene.new", unlink="scene.delete")
layout.template_ID(window, "workspace", new="workspace.workspace_add_menu", unlink="workspace.workspace_delete")
layout.template_search_preview(window, "screen", workspace, "screens", new="screen.new", unlink="screen.delete", rows=2, cols=6)
if hasattr(workspace, 'object_mode'):
act_mode_item = bpy.types.Object.bl_rna.properties['mode'].enum_items[workspace.object_mode]
else:
act_mode_item = bpy.types.Object.bl_rna.properties['mode'].enum_items[layer.objects.active.mode]
layout.operator_menu_enum("object.mode_set", "mode", text=act_mode_item.name, icon=act_mode_item.icon)
layout.template_search(workspace, "render_layer", scene, "render_layers")
layout.separator()
layout.template_ID(window, "scene", new="scene.new", unlink="scene.delete")
if rd.has_multiple_engines:
layout.prop(rd, "engine", text="")

View File

@@ -57,7 +57,9 @@ class USERPREF_HT_header(Header):
layout.operator_context = 'INVOKE_DEFAULT'
if userpref.active_section == 'INPUT':
if userpref.active_section == 'INTERFACE':
layout.operator("wm.save_workspace_file")
elif userpref.active_section == 'INPUT':
layout.operator("wm.keyconfig_import")
layout.operator("wm.keyconfig_export")
elif userpref.active_section == 'ADDONS':
@@ -224,7 +226,6 @@ class USERPREF_PT_interface(Panel):
col.prop(view, "show_large_cursors")
col.prop(view, "show_view_name", text="View Name")
col.prop(view, "show_playback_fps", text="Playback FPS")
col.prop(view, "use_global_scene")
col.prop(view, "object_origin_size")
col.separator()

View File

@@ -90,6 +90,7 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_view2d_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_view3d_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_windowmanager_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_workspace_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_world_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_movieclip_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_tracking_types.h

View File

@@ -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"

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 */

View File

@@ -123,6 +123,7 @@ typedef struct Main {
ListBase mask;
ListBase linestyle;
ListBase cachefiles;
ListBase workspaces;
char id_tag_update[MAX_LIBARRAY];

View File

@@ -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) \

View File

@@ -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);

View File

@@ -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__ */

View File

@@ -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

View File

@@ -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);
}
/** \} */

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}
/**

View File

@@ -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;
}

View File

@@ -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:

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -39,6 +39,7 @@ extern "C" {
struct BlendThumbnail;
struct bScreen;
struct LinkNode;
struct ListBase;
struct Main;
struct MemFile;
struct ReportList;
@@ -49,6 +50,7 @@ struct View3D;
struct bContext;
struct BHead;
struct FileData;
struct wmWindowManager;
typedef struct BlendHandle BlendHandle;
@@ -65,13 +67,20 @@ typedef struct BlendFileData {
int fileflags;
int globalf;
char filename[1024]; /* 1024 = FILE_MAX */
struct bScreen *curscreen;
struct bScreen *curscreen; /* TODO think this isn't needed anymore? */
struct Scene *curscene;
struct SceneLayer *cur_render_layer; /* layer to activate in workspaces when reading without UI */
BlenFileType type;
} BlendFileData;
typedef struct WorkspaceConfigFileData {
struct Main *main; /* has to be freed when done reading file data */
struct ListBase workspaces;
} WorkspaceConfigFileData;
/* skip reading some data-block types (may want to skip screen data too). */
typedef enum eBLOReadSkip {
@@ -100,6 +109,7 @@ BlendHandle *BLO_blendhandle_from_memory(const void *mem, int memsize);
struct LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, int *tot_names);
struct LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *tot_prev);
struct LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh);
struct LinkNode *BLO_blendhandle_get_appendable_groups(BlendHandle *bh);
void BLO_blendhandle_close(BlendHandle *bh);
@@ -126,7 +136,9 @@ void *BLO_library_read_struct(struct FileData *fd, struct BHead *bh, const char
BlendFileData *blo_read_blendafterruntime(int file, const char *name, int actualsize, struct ReportList *reports);
/* internal function but we need to expose it */
void blo_lib_link_screen_restore(struct Main *newmain, struct bScreen *curscreen, struct Scene *curscene);
void blo_lib_link_restore(
struct Main *newmain, struct wmWindowManager *curwm,
struct Scene *curscene, struct SceneLayer *cur_render_layer);
typedef void (*BLOExpandDoitCallback) (void *fdhandle, struct Main *mainvar, void *idv);

View File

@@ -53,6 +53,10 @@
/* allow readfile to use deprecated functionality */
#define DNA_DEPRECATED_ALLOW
/* Allow using DNA struct members that are marked as private for read/write.
* Note: Each header that uses this needs to define its own way of handling
* it. There's no generic implementation, direct use does nothing. */
#define DNA_PRIVATE_READ_WRITE_ALLOW
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -99,10 +103,13 @@
#include "DNA_sound_types.h"
#include "DNA_space_types.h"
#include "DNA_vfont_types.h"
#include "DNA_workspace_types.h"
#include "DNA_world_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
#include "RNA_access.h"
#include "MEM_guardedalloc.h"
#include "BLI_endian_switch.h"
@@ -149,6 +156,7 @@
#include "BKE_outliner_treehash.h"
#include "BKE_sound.h"
#include "BKE_colortools.h"
#include "BKE_workspace.h"
#include "DEG_depsgraph.h"
@@ -2774,6 +2782,78 @@ static void direct_link_cachefile(FileData *fd, CacheFile *cache_file)
direct_link_animdata(fd, cache_file->adt);
}
/* ************ READ WORKSPACES *************** */
static void lib_link_workspaces(FileData *fd, Main *bmain)
{
for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
ListBase *layouts = BKE_workspace_layouts_get(workspace);
ID *id = (ID *)workspace;
if ((id->tag & LIB_TAG_NEED_LINK) == 0) {
continue;
}
IDP_LibLinkProperty(id->properties, fd);
id_us_ensure_real(id);
for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) {
bScreen *screen = newlibadr(fd, id->lib, BKE_workspace_layout_screen_get(layout));
if (screen) {
BKE_workspace_layout_screen_set(layout, screen);
if (ID_IS_LINKED_DATABLOCK(id)) {
screen->winid = 0;
if (screen->temp) {
/* delete temp layouts when appending */
BKE_workspace_layout_remove(bmain, workspace, layout);
}
}
}
}
id->tag &= ~LIB_TAG_NEED_LINK;
}
}
static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main *main)
{
link_list(fd, BKE_workspace_layouts_get(workspace));
link_list(fd, &workspace->hook_layout_relations);
for (WorkSpaceDataRelation *relation = workspace->hook_layout_relations.first;
relation;
relation = relation->next)
{
relation->parent = newglobadr(fd, relation->parent); /* data from window - need to access through global oldnew-map */
relation->value = newdataadr(fd, relation->value);
}
if (ID_IS_LINKED_DATABLOCK(&workspace->id)) {
/* Appending workspace so render layer is likely from a different scene. Unset
* now, when activating workspace later we set a valid one from current scene. */
BKE_workspace_render_layer_set(workspace, NULL);
}
/* Same issue/fix as in direct_link_scene_update_screen_data: Can't read workspace data
* when reading windows, so have to update windows after/when reading workspaces. */
for (wmWindowManager *wm = main->wm.first; wm; wm = wm->id.next) {
for (wmWindow *win = wm->windows.first; win; win = win->next) {
WorkSpaceLayout *act_layout = newdataadr(fd, BKE_workspace_active_layout_get(win->workspace_hook));
if (act_layout) {
BKE_workspace_active_layout_set(win->workspace_hook, act_layout);
}
}
}
}
static void lib_link_workspace_instance_hook(FileData *fd, WorkSpaceInstanceHook *hook, ID *id)
{
WorkSpace *workspace = BKE_workspace_active_get(hook);
BKE_workspace_active_set(hook, newlibadr(fd, id->lib, workspace));
}
/* ************ READ MOTION PATHS *************** */
/* direct data for cache */
@@ -5977,7 +6057,19 @@ static void direct_link_layer_collections(FileData *fd, ListBase *lb)
}
}
static void direct_link_scene(FileData *fd, Scene *sce)
static void direct_link_scene_update_screen_data(
FileData *fd, const Scene *scene, const ListBase *workspaces)
{
for (WorkSpace *workspace = workspaces->first; workspace; workspace = workspace->id.next) {
SceneLayer *layer = newdataadr(fd, BKE_workspace_render_layer_get(workspace));
/* only set when layer is from the scene we read */
if (layer && (BLI_findindex(&scene->render_layers, layer) != -1)) {
BKE_workspace_render_layer_set(workspace, layer);
}
}
}
static void direct_link_scene(FileData *fd, Scene *sce, Main *bmain)
{
Editing *ed;
Sequence *seq;
@@ -6250,7 +6342,8 @@ static void direct_link_scene(FileData *fd, Scene *sce)
direct_link_scene_collection(fd, sce->collection);
}
link_list(fd, &sce->render_layers);
/* insert into global old-new map for reading without UI (link_global accesses it again) */
link_glob_list(fd, &sce->render_layers);
for (sl = sce->render_layers.first; sl; sl = sl->next) {
sl->stats = NULL;
link_list(fd, &sl->object_bases);
@@ -6277,6 +6370,8 @@ static void direct_link_scene(FileData *fd, Scene *sce)
BKE_layer_collection_engine_settings_validate_scene(sce);
BKE_scene_layer_engine_settings_validate_scene(sce);
direct_link_scene_update_screen_data(fd, sce, &bmain->workspaces);
}
/* ************ READ WM ***************** */
@@ -6289,6 +6384,12 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
link_list(fd, &wm->windows);
for (win = wm->windows.first; win; win = win->next) {
WorkSpaceInstanceHook *hook = win->workspace_hook;
win->workspace_hook = newdataadr(fd, hook);
/* we need to restore a pointer to this later when reading workspaces, so store in global oldnew-map */
oldnewmap_insert(fd->globmap, hook, win->workspace_hook, 0);
win->ghostwin = NULL;
win->eventstate = NULL;
win->curswin = NULL;
@@ -6353,6 +6454,11 @@ static void lib_link_windowmanager(FileData *fd, Main *main)
if (wm->id.tag & LIB_TAG_NEED_LINK) {
/* Note: WM IDProperties are never written to file, hence no need to read/link them here. */
for (win = wm->windows.first; win; win = win->next) {
if (win->workspace_hook) { /* NULL for old files */
lib_link_workspace_instance_hook(fd, win->workspace_hook, &wm->id);
}
win->scene = newlibadr(fd, wm->id.lib, win->scene);
/* deprecated, but needed for versioning (will be NULL'ed then) */
win->screen = newlibadr(fd, NULL, win->screen);
}
@@ -6438,13 +6544,9 @@ static void lib_link_screen(FileData *fd, Main *main)
IDP_LibLinkProperty(sc->id.properties, fd);
id_us_ensure_real(&sc->id);
/* deprecated, but needed for versioning (will be NULL'ed then) */
sc->scene = newlibadr(fd, sc->id.lib, sc->scene);
/* this should not happen, but apparently it does somehow. Until we figure out the cause,
* just assign first available scene */
if (!sc->scene)
sc->scene = main->scene.first;
sc->animtimer = NULL; /* saved in rare cases */
sc->scrubbing = false;
@@ -6752,56 +6854,59 @@ static void lib_link_clipboard_restore(struct IDNameLib_Map *id_map)
BKE_sequencer_base_recursive_apply(&seqbase_clipboard, lib_link_seq_clipboard_cb, id_map);
}
/* called from kernel/blender.c */
/* used to link a file (without UI) to the current UI */
/* note that it assumes the old pointers in UI are still valid, so old Main is not freed */
void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene)
static void lib_link_workspace_scene_data_restore(wmWindow *win, Scene *scene)
{
wmWindow *win;
wmWindowManager *wm;
bScreen *sc;
ScrArea *sa;
bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
struct IDNameLib_Map *id_map = BKE_main_idmap_create(newmain);
for (ScrArea *area = screen->areabase.first; area; area = area->next) {
for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
/* first windowmanager */
for (wm = newmain->wm.first; wm; wm = wm->id.next) {
for (win= wm->windows.first; win; win= win->next) {
win->screen = restore_pointer_by_name(id_map, (ID *)win->screen, USER_REAL);
if (win->screen == NULL)
win->screen = curscreen;
win->screen->winid = win->winid;
if (v3d->camera == NULL || v3d->scenelock) {
v3d->camera = scene->camera;
}
if (v3d->localvd) {
/*Base *base;*/
v3d->localvd->camera = scene->camera;
/* localview can become invalid during undo/redo steps, so we exit it when no could be found */
#if 0 /* XXX regionlocalview ? */
for (base= sc->scene->base.first; base; base= base->next) {
if (base->lay & v3d->lay) break;
}
if (base==NULL) {
v3d->lay= v3d->localvd->lay;
v3d->layact= v3d->localvd->layact;
MEM_freeN(v3d->localvd);
v3d->localvd= NULL;
}
#endif
}
else if (v3d->scenelock) {
v3d->lay = scene->lay;
}
}
}
}
for (sc = newmain->screen.first; sc; sc = sc->id.next) {
Scene *oldscene = sc->scene;
sc->scene= restore_pointer_by_name(id_map, (ID *)sc->scene, USER_REAL);
if (sc->scene == NULL)
sc->scene = curscene;
/* keep cursor location through undo */
copy_v3_v3(sc->scene->cursor, oldscene->cursor);
for (sa = sc->areabase.first; sa; sa = sa->next) {
SpaceLink *sl;
for (sl = sa->spacedata.first; sl; sl = sl->next) {
}
static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map, Main *newmain, WorkSpaceLayout *layout)
{
bScreen *screen = BKE_workspace_layout_screen_get(layout);
/* avoid conflicts with 2.8x branch */
{
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
BGpic *bgpic;
ARegion *ar;
if (v3d->scenelock)
v3d->camera = NULL; /* always get from scene */
else
v3d->camera = restore_pointer_by_name(id_map, (ID *)v3d->camera, USER_REAL);
if (v3d->camera == NULL)
v3d->camera = sc->scene->camera;
v3d->camera = restore_pointer_by_name(id_map, (ID *)v3d->camera, USER_REAL);
v3d->ob_centre = restore_pointer_by_name(id_map, (ID *)v3d->ob_centre, USER_REAL);
for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next) {
@@ -6812,27 +6917,6 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
id_us_plus((ID *)bgpic->clip);
}
}
if (v3d->localvd) {
/*Base *base;*/
v3d->localvd->camera = sc->scene->camera;
/* localview can become invalid during undo/redo steps, so we exit it when no could be found */
#if 0 /* XXX regionlocalview ? */
for (base= sc->scene->base.first; base; base= base->next) {
if (base->lay & v3d->lay) break;
}
if (base==NULL) {
v3d->lay= v3d->localvd->lay;
v3d->layact= v3d->localvd->layact;
MEM_freeN(v3d->localvd);
v3d->localvd= NULL;
}
#endif
}
else if (v3d->scenelock) {
v3d->lay = sc->scene->lay;
}
/* not very nice, but could help */
if ((v3d->layact & v3d->lay) == 0) v3d->layact = v3d->lay;
@@ -7035,6 +7119,44 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
}
}
}
}
/**
* Used to link a file (without UI) to the current UI.
* Note that it assumes the old pointers in UI are still valid, so old Main is not freed.
*/
void blo_lib_link_restore(Main *newmain, wmWindowManager *curwm, Scene *curscene, SceneLayer *cur_render_layer)
{
struct IDNameLib_Map *id_map = BKE_main_idmap_create(newmain);
for (WorkSpace *workspace = newmain->workspaces.first; workspace; workspace = workspace->id.next) {
ListBase *layouts = BKE_workspace_layouts_get(workspace);
for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) {
lib_link_workspace_layout_restore(id_map, newmain, layout);
}
BKE_workspace_render_layer_set(workspace, cur_render_layer);
}
for (wmWindow *win = curwm->windows.first; win; win = win->next) {
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
ID *workspace_id = (ID *)workspace;
Scene *oldscene = win->scene;
workspace = restore_pointer_by_name(id_map, workspace_id, USER_REAL);
BKE_workspace_active_set(win->workspace_hook, workspace);
win->scene = restore_pointer_by_name(id_map, (ID *)win->scene, USER_REAL);
if (win->scene == NULL) {
win->scene = curscene;
}
BKE_workspace_active_set(win->workspace_hook, workspace);
/* keep cursor location through undo */
copy_v3_v3(win->scene->cursor, oldscene->cursor);
lib_link_workspace_scene_data_restore(win, win->scene);
BLI_assert(win->screen == NULL);
}
/* update IDs stored in all possible clipboards */
lib_link_clipboard_restore(id_map);
@@ -8146,6 +8268,7 @@ static const char *dataname(short id_code)
case ID_MSK: return "Data from MSK";
case ID_LS: return "Data from LS";
case ID_CF: return "Data from CF";
case ID_WS: return "Data from WS";
}
return "Data from Lib Block";
@@ -8309,7 +8432,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short
wrong_id = direct_link_screen(fd, (bScreen *)id);
break;
case ID_SCE:
direct_link_scene(fd, (Scene *)id);
direct_link_scene(fd, (Scene *)id, main);
break;
case ID_OB:
direct_link_object(fd, (Object *)id);
@@ -8404,6 +8527,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short
case ID_CF:
direct_link_cachefile(fd, (CacheFile *)id);
break;
case ID_WS:
direct_link_workspace(fd, (WorkSpace *)id, main);
break;
}
oldnewmap_free_unused(fd->datamap);
@@ -8449,7 +8575,8 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
bfd->curscreen = fg->curscreen;
bfd->curscene = fg->curscene;
bfd->cur_render_layer = fg->cur_render_layer;
MEM_freeN(fg);
fd->globalf = bfd->globalf;
@@ -8461,6 +8588,7 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
/* note, this has to be kept for reading older files... */
static void link_global(FileData *fd, BlendFileData *bfd)
{
bfd->cur_render_layer = newglobadr(fd, bfd->cur_render_layer);
bfd->curscreen = newlibadr(fd, NULL, bfd->curscreen);
bfd->curscene = newlibadr(fd, NULL, bfd->curscene);
// this happens in files older than 2.35
@@ -8580,6 +8708,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_linestyle(fd, main);
lib_link_gpencil(fd, main);
lib_link_cachefiles(fd, main);
lib_link_workspaces(fd, main);
lib_link_library(fd, main); /* only init users */
}
@@ -8966,6 +9095,11 @@ static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
}
}
else {
/* in 2.50+ file identifier for screens is patched, forward compatibility */
if (bhead->code == ID_SCRN) {
bhead->code = ID_SCR;
}
id = is_yet_read(fd, mainvar, bhead);
if (id == NULL) {
read_libblock(fd, mainvar, bhead, LIB_TAG_TESTIND, NULL);
@@ -9817,6 +9951,15 @@ static void expand_gpencil(FileData *fd, Main *mainvar, bGPdata *gpd)
expand_animdata(fd, mainvar, gpd->adt);
}
static void expand_workspace(FileData *fd, Main *mainvar, WorkSpace *workspace)
{
ListBase *layouts = BKE_workspace_layouts_get(workspace);
for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) {
expand_doit(fd, mainvar, BKE_workspace_layout_screen_get(layout));
}
}
/**
* Set the callback func used over all ID data found by \a BLO_expand_main func.
*
@@ -9931,6 +10074,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
case ID_CF:
expand_cachefile(fd, mainvar, (CacheFile *)id);
break;
case ID_WS:
expand_workspace(fd, mainvar, (WorkSpace *)id);
break;
}
do_it = true;

View File

@@ -45,6 +45,7 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_scene.h"
#include "BKE_workspace.h"
#include "BLI_listbase.h"
#include "BLI_mempool.h"
@@ -55,6 +56,83 @@
#include "MEM_guardedalloc.h"
static bScreen *screen_parent_find(const bScreen *screen)
{
/* can avoid lookup if screen state isn't maximized/full (parent and child store the same state) */
if (ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL)) {
for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
if (sa->full && sa->full != screen) {
BLI_assert(sa->full->state == screen->state);
return sa->full;
}
}
}
return NULL;
}
static void do_version_workspaces_create_from_screens(Main *bmain)
{
for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
const bScreen *screen_parent = screen_parent_find(screen);
WorkSpace *workspace;
if (screen_parent) {
/* fullscreen with "Back to Previous" option, don't create
* a new workspace, add layout workspace containing parent */
workspace = BLI_findstring(
&bmain->workspaces, screen_parent->id.name + 2, offsetof(ID, name) + 2);
}
else {
workspace = BKE_workspace_add(bmain, screen->id.name + 2);
}
BKE_workspace_layout_add(workspace, screen, screen->id.name + 2);
BKE_workspace_render_layer_set(workspace, screen->scene->render_layers.first);
}
}
/**
* \brief After lib-link versioning for new workspace design.
*
* * Adds a workspace for (almost) each screen of the old file
* and adds the needed workspace-layout to wrap the screen.
* * Active screen isn't stored directly in window anymore, but in the active workspace.
* * Active scene isn't stored in screen anymore, but in window.
* * Create workspace instance hook for each window.
*
* \note Some of the created workspaces might be deleted again in case of reading the default startup.blend.
*/
static void do_version_workspaces_after_lib_link(Main *bmain)
{
BLI_assert(BLI_listbase_is_empty(&bmain->workspaces));
do_version_workspaces_create_from_screens(bmain);
for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
for (wmWindow *win = wm->windows.first; win; win = win->next) {
bScreen *screen_parent = screen_parent_find(win->screen);
bScreen *screen = screen_parent ? screen_parent : win->screen;
WorkSpace *workspace = BLI_findstring(&bmain->workspaces, screen->id.name + 2, offsetof(ID, name) + 2);
ListBase *layouts = BKE_workspace_layouts_get(workspace);
win->workspace_hook = BKE_workspace_instance_hook_create(bmain);
BKE_workspace_active_set(win->workspace_hook, workspace);
BKE_workspace_active_layout_set(win->workspace_hook, layouts->first);
win->scene = screen->scene;
/* Deprecated from now on! */
win->screen = NULL;
}
}
for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
/* Deprecated from now on! */
screen->scene = NULL;
}
}
void do_versions_after_linking_280(Main *main)
{
if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
@@ -183,13 +261,18 @@ void do_versions_after_linking_280(Main *main)
scene->basact = NULL;
}
}
}
if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
for (bScreen *screen = main->screen.first; screen; screen = screen->id.next) {
/* same render-layer as do_version_workspaces_after_lib_link will activate,
* so same layer as BKE_scene_layer_context_active would return */
SceneLayer *layer = screen->scene->render_layers.first;
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_OUTLINER) {
SpaceOops *soutliner = (SpaceOops *)sl;
SceneLayer *layer = BKE_scene_layer_context_active(screen->scene);
soutliner->outlinevis = SO_ACT_LAYER;
@@ -213,6 +296,11 @@ void do_versions_after_linking_280(Main *main)
}
}
}
/* New workspace design */
if (!MAIN_VERSION_ATLEAST(main, 280, 1)) {
do_version_workspaces_after_lib_link(main);
}
}
static void do_version_layer_collections_idproperties(ListBase *lb)
@@ -254,34 +342,35 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
}
if (!DNA_struct_elem_find(fd->filesdna, "GPUDOFSettings", "float", "ratio")) {
for (Camera *ca = main->camera.first; ca; ca = ca->id.next) {
ca->gpu_dof.ratio = 1.0f;
}
}
if (!DNA_struct_elem_find(fd->filesdna, "SceneLayer", "IDProperty", "*properties")) {
for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
IDPropertyTemplate val = {0};
sl->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
BKE_scene_layer_engine_settings_create(sl->properties);
if (!MAIN_VERSION_ATLEAST(main, 280, 1)) {
if (!DNA_struct_elem_find(fd->filesdna, "GPUDOFSettings", "float", "ratio")) {
for (Camera *ca = main->camera.first; ca; ca = ca->id.next) {
ca->gpu_dof.ratio = 1.0f;
}
}
}
/* MTexPoly now removed. */
if (DNA_struct_find(fd->filesdna, "MTexPoly")) {
const int cd_mtexpoly = 15; /* CD_MTEXPOLY, deprecated */
for (Mesh *me = main->mesh.first; me; me = me->id.next) {
/* If we have UV's, so this file will have MTexPoly layers too! */
if (me->mloopuv != NULL) {
CustomData_update_typemap(&me->pdata);
CustomData_free_layers(&me->pdata, cd_mtexpoly, me->totpoly);
BKE_mesh_update_customdata_pointers(me, false);
if (!DNA_struct_elem_find(fd->filesdna, "SceneLayer", "IDProperty", "*properties")) {
for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
IDPropertyTemplate val = {0};
sl->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
BKE_scene_layer_engine_settings_create(sl->properties);
}
}
}
/* MTexPoly now removed. */
if (DNA_struct_find(fd->filesdna, "MTexPoly")) {
const int cd_mtexpoly = 15; /* CD_MTEXPOLY, deprecated */
for (Mesh *me = main->mesh.first; me; me = me->id.next) {
/* If we have UV's, so this file will have MTexPoly layers too! */
if (me->mloopuv != NULL) {
CustomData_update_typemap(&me->pdata);
CustomData_free_layers(&me->pdata, cd_mtexpoly, me->totpoly);
BKE_mesh_update_customdata_pointers(me, false);
}
}
}
}

View File

@@ -40,10 +40,12 @@
#include "DNA_mesh_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_workspace_types.h"
#include "BKE_brush.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_workspace.h"
#include "BLO_readfile.h"
@@ -83,6 +85,32 @@ void BLO_update_defaults_userpref_blend(void)
#endif
}
/**
* New workspace design: Remove all screens/workspaces except of "Default" one and rename the workspace to "General".
* For compatibility, a new workspace has been created for each screen of old files,
* we only want one workspace and one screen in the default startup file however.
*/
static void update_defaults_startup_workspaces(Main *bmain)
{
WorkSpace *workspace_default = NULL;
for (WorkSpace *workspace = bmain->workspaces.first, *workspace_next; workspace; workspace = workspace_next) {
workspace_next = workspace->id.next;
if (STREQ(workspace->id.name + 2, "Default")) {
/* don't rename within iterator, renaming causes listbase to be re-sorted */
workspace_default = workspace;
}
else {
BKE_workspace_remove(bmain, workspace);
}
}
/* rename "Default" workspace to "General" */
BKE_libblock_rename(bmain, (ID *)workspace_default, "General");
BLI_assert(BLI_listbase_count(BKE_workspace_layouts_get(workspace_default)) == 1);
}
/**
* Update defaults in startup.blend, without having to save and embed the file.
* This function can be emptied each time the startup.blend is updated. */
@@ -181,20 +209,18 @@ void BLO_update_defaults_startup_blend(Main *bmain)
linestyle->chain_count = 10;
}
for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
ScrArea *area;
for (area = screen->areabase.first; area; area = area->next) {
SpaceLink *space_link;
ARegion *ar;
update_defaults_startup_workspaces(bmain);
for (space_link = area->spacedata.first; space_link; space_link = space_link->next) {
for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
for (ScrArea *area = screen->areabase.first; area; area = area->next) {
for (SpaceLink *space_link = area->spacedata.first; space_link; space_link = space_link->next) {
if (space_link->spacetype == SPACE_CLIP) {
SpaceClip *space_clip = (SpaceClip *) space_link;
space_clip->flag &= ~SC_MANUAL_CALIBRATION;
}
}
for (ar = area->regionbase.first; ar; ar = ar->next) {
for (ARegion *ar = area->regionbase.first; ar; ar = ar->next) {
/* Remove all stored panels, we want to use defaults (order, open/closed) as defined by UI code here! */
BLI_freelistN(&ar->panels);

View File

@@ -102,6 +102,10 @@
/* allow writefile to use deprecated functionality (for forward compatibility code) */
#define DNA_DEPRECATED_ALLOW
/* Allow using DNA struct members that are marked as private for read/write.
* Note: Each header that uses this needs to define its own way of handling
* it. There's no generic implementation, direct use does nothing. */
#define DNA_PRIVATE_READ_WRITE_ALLOW
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -147,6 +151,7 @@
#include "DNA_vfont_types.h"
#include "DNA_world_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_workspace_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
@@ -173,6 +178,7 @@
#include "BKE_fcurve.h"
#include "BKE_pointcache.h"
#include "BKE_mesh.h"
#include "BKE_workspace.h"
#ifdef USE_NODE_COMPAT_CUSTOMNODES
#include "NOD_socket.h" /* for sock->default_value data */
@@ -1077,10 +1083,13 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
* Take care using 'use_active_win', since we wont want the currently active window
* to change which scene renders (currently only used for undo).
*/
static void current_screen_compat(Main *mainvar, bScreen **r_screen, bool use_active_win)
static void current_screen_compat(
Main *mainvar, bool use_active_win,
bScreen **r_screen, Scene **r_scene, SceneLayer **r_render_layer)
{
wmWindowManager *wm;
wmWindow *window = NULL;
WorkSpace *workspace;
/* find a global current screen in the first open window, to have
* a reasonable default for reading in older versions */
@@ -1104,8 +1113,11 @@ static void current_screen_compat(Main *mainvar, bScreen **r_screen, bool use_ac
window = wm->windows.first;
}
}
workspace = (window) ? BKE_workspace_active_get(window->workspace_hook) : NULL;
*r_screen = (window) ? window->screen : NULL;
*r_screen = (window) ? BKE_workspace_active_screen_get(window->workspace_hook) : NULL;
*r_scene = (window) ? window->scene : NULL;
*r_render_layer = (window) ? BKE_workspace_render_layer_get(workspace) : NULL;
}
typedef struct RenderInfo {
@@ -1121,13 +1133,11 @@ static void write_renderinfo(WriteData *wd, Main *mainvar)
{
bScreen *curscreen;
Scene *sce, *curscene = NULL;
SceneLayer *render_layer;
RenderInfo data;
/* XXX in future, handle multiple windows with multiple screens? */
current_screen_compat(mainvar, &curscreen, false);
if (curscreen) {
curscene = curscreen->scene;
}
current_screen_compat(mainvar, false, &curscreen, &curscene, &render_layer);
for (sce = mainvar->scene.first; sce; sce = sce->id.next) {
if (sce->id.lib == NULL && (sce == curscene || (sce->r.scemode & R_BG_RENDER))) {
@@ -2842,8 +2852,19 @@ static void write_windowmanager(WriteData *wd, wmWindowManager *wm)
write_iddata(wd, &wm->id);
for (wmWindow *win = wm->windows.first; win; win = win->next) {
/* update deprecated screen member (for so loading in 2.7x uses the correct screen) */
win->screen = BKE_workspace_active_screen_get(win->workspace_hook);
if (win->screen) {
BLI_strncpy(win->screenname, win->screen->id.name + 2, sizeof(win->screenname));
}
writestruct(wd, DATA, wmWindow, 1, win);
writestruct(wd, DATA, WorkSpaceInstanceHook, 1, win->workspace_hook);
writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format);
/* data is written, clear deprecated data again */
win->screen = NULL;
}
}
@@ -2984,6 +3005,7 @@ static void write_screen(WriteData *wd, bScreen *sc)
View3D *v3d = (View3D *)sl;
BGpic *bgpic;
writestruct(wd, DATA, View3D, 1, v3d);
for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
writestruct(wd, DATA, BGpic, 1, bgpic);
}
@@ -3729,6 +3751,15 @@ static void write_cachefile(WriteData *wd, CacheFile *cache_file)
}
}
static void write_workspace(WriteData *wd, WorkSpace *workspace)
{
ListBase *layouts = BKE_workspace_layouts_get(workspace);
writestruct(wd, ID_WS, WorkSpace, 1, workspace);
writelist(wd, DATA, WorkSpaceLayout, layouts);
writelist(wd, DATA, WorkSpaceDataRelation, &workspace->hook_layout_relations);
}
/* Keep it last of write_foodata functions. */
static void write_libraries(WriteData *wd, Main *main)
{
@@ -3798,6 +3829,8 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
const bool is_undo = (wd->current != NULL);
FileGlobal fg;
bScreen *screen;
Scene *scene;
SceneLayer *render_layer;
char subvstr[8];
/* prevent mem checkers from complaining */
@@ -3805,11 +3838,12 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
memset(fg.filename, 0, sizeof(fg.filename));
memset(fg.build_hash, 0, sizeof(fg.build_hash));
current_screen_compat(mainvar, &screen, is_undo);
current_screen_compat(mainvar, is_undo, &screen, &scene, &render_layer);
/* XXX still remap G */
fg.curscreen = screen;
fg.curscene = screen ? screen->scene : NULL;
fg.curscene = scene;
fg.cur_render_layer = render_layer;
/* prevent to save this, is not good convention, and feature with concerns... */
fg.fileflags = (fileflags & ~G_FILE_FLAGS_RUNTIME);
@@ -3905,6 +3939,9 @@ static bool write_file_handle(
case ID_WM:
write_windowmanager(wd, (wmWindowManager *)id);
break;
case ID_WS:
write_workspace(wd, (WorkSpace *)id);
break;
case ID_SCR:
write_screen(wd, (bScreen *)id);
break;

View File

@@ -149,6 +149,7 @@ bool BLT_lang_is_ime_supported(void);
#define BLT_I18NCONTEXT_ID_TEXT "Text"
#define BLT_I18NCONTEXT_ID_VFONT "VFont"
#define BLT_I18NCONTEXT_ID_WORLD "World"
#define BLT_I18NCONTEXT_ID_WORKSPACE "WorkSpace"
#define BLT_I18NCONTEXT_ID_WINDOWMANAGER "WindowManager"
#define BLT_I18NCONTEXT_ID_MOVIECLIP "MovieClip"
#define BLT_I18NCONTEXT_ID_MASK "Mask"
@@ -203,6 +204,7 @@ typedef struct {
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_TEXT, "id_text"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_VFONT, "id_vfont"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_WORLD, "id_world"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_WORKSPACE, "id_workspace"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "id_windowmanager"), \
{NULL, NULL, NULL} \
}

View File

@@ -49,6 +49,7 @@ extern "C" {
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_workspace.h"
#define new new_
#include "BKE_screen.h"

View File

@@ -35,7 +35,7 @@ if(WITH_BLENDER)
add_subdirectory(object)
add_subdirectory(physics)
add_subdirectory(render)
add_subdirectory(screen)
add_subdirectory(scene)
add_subdirectory(sculpt_paint)
add_subdirectory(sound)
add_subdirectory(space_action)
@@ -60,6 +60,7 @@ if(WITH_BLENDER)
add_subdirectory(transform)
add_subdirectory(util)
add_subdirectory(uvedit)
add_subdirectory(screen)
endif()
add_subdirectory(datafiles)

View File

@@ -859,7 +859,7 @@ static void ed_marker_move_apply(bContext *C, wmOperator *op)
BKE_scene_camera_switch_update(scene);
if (camera != scene->camera) {
BKE_screen_view3d_scene_sync(sc);
BKE_screen_view3d_scene_sync(sc, scene);
WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
}
#endif
@@ -1550,7 +1550,7 @@ static int ed_marker_camera_bind_exec(bContext *C, wmOperator *UNUSED(op))
/* camera may have changes */
BKE_scene_camera_switch_update(scene);
BKE_screen_view3d_scene_sync(sc);
BKE_screen_view3d_scene_sync(sc, scene);
WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);

View File

@@ -0,0 +1,40 @@
/*
* ***** 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 ED_scene.h
* \ingroup editors
*/
#ifndef __ED_SCENE_H__
#define __ED_SCENE_H__
#include "BLI_compiler_attrs.h"
enum eSceneCopyMethod;
struct Scene *ED_scene_add(struct Main *bmain, bContext *C, struct wmWindow *win, enum eSceneCopyMethod method) ATTR_NONNULL();
bool ED_scene_delete(bContext *C, struct Main *bmain, struct wmWindow *win, struct Scene *scene) ATTR_NONNULL();
void ED_scene_exit(bContext *C) ATTR_NONNULL();
void ED_scene_changed_update(struct Main *bmain, bContext *C, struct Scene *scene_new,
const struct bScreen *active_screen) ATTR_NONNULL();
void ED_operatortypes_scene(void);
#endif /* __ED_SCENE_H__ */

View File

@@ -43,6 +43,8 @@ struct wmWindow;
struct wmNotifier;
struct wmEvent;
struct wmKeyConfig;
struct WorkSpace;
struct WorkSpaceInstanceHook;
struct bContext;
struct Scene;
struct bScreen;
@@ -107,12 +109,8 @@ void ED_screens_initialize(struct wmWindowManager *wm);
void ED_screen_draw(struct wmWindow *win);
void ED_screen_refresh(struct wmWindowManager *wm, struct wmWindow *win);
void ED_screen_do_listen(struct bContext *C, struct wmNotifier *note);
bScreen *ED_screen_duplicate(struct wmWindow *win, struct bScreen *sc);
bScreen *ED_screen_add(struct wmWindow *win, struct Scene *scene, const char *name);
bool ED_screen_set(struct bContext *C, struct bScreen *sc);
bool ED_screen_delete(struct bContext *C, struct bScreen *sc);
void ED_screen_set_scene(struct bContext *C, struct bScreen *screen, struct Scene *scene);
bool ED_screen_delete_scene(struct bContext *C, struct Scene *scene);
bool ED_screen_change(struct bContext *C, struct bScreen *sc);
void ED_screen_update_after_scene_change(const struct bScreen *screen, struct Scene *scene_new);
void ED_screen_set_subwinactive(struct bContext *C, struct wmEvent *event);
void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen);
void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable);
@@ -123,9 +121,42 @@ void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa);
void ED_screen_full_restore(struct bContext *C, ScrArea *sa);
struct ScrArea *ED_screen_state_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *sa, const short state);
void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
bool ED_screen_stereo3d_required(struct bScreen *screen);
bool ED_screen_stereo3d_required(const struct bScreen *screen, const struct Scene *scene);
Scene *ED_screen_scene_find(const struct bScreen *screen, const struct wmWindowManager *wm);
void ED_screen_preview_render(const struct bScreen *screen, int size_x, int size_y, unsigned int *r_rect) ATTR_NONNULL();
/* workspaces */
struct WorkSpace *ED_workspace_add(
struct Main *bmain,
const char *name,
SceneLayer *act_render_layer) ATTR_NONNULL();
bool ED_workspace_change(
struct WorkSpace *workspace_new,
struct bContext *C,
struct wmWindowManager *wm, struct wmWindow *win) ATTR_NONNULL();
struct WorkSpace *ED_workspace_duplicate(
struct WorkSpace *workspace_old,
struct Main *bmain, struct wmWindow *win);
bool ED_workspace_delete(
struct WorkSpace *workspace,
struct Main *bmain, struct bContext *C,
struct wmWindowManager *wm, struct wmWindow *win) ATTR_NONNULL();
void ED_workspace_scene_data_sync(
struct WorkSpaceInstanceHook *hook, Scene *scene) ATTR_NONNULL();
struct WorkSpaceLayout *ED_workspace_layout_add(
struct WorkSpace *workspace,
struct wmWindow *win,
const char *name) ATTR_NONNULL();
struct WorkSpaceLayout *ED_workspace_layout_duplicate(
struct WorkSpace *workspace, const struct WorkSpaceLayout *layout_old,
struct wmWindow *win) ATTR_NONNULL();
bool ED_workspace_layout_delete(
struct WorkSpace *workspace, struct WorkSpaceLayout *layout_old,
struct bContext *C) ATTR_NONNULL();
bool ED_workspace_layout_cycle(
struct WorkSpace *workspace, const short direction,
struct bContext *C) ATTR_NONNULL();
/* anim */
void ED_update_for_newframe(struct Main *bmain, struct Scene *scene, int mute);
@@ -137,6 +168,8 @@ bScreen *ED_screen_animation_no_scrub(const struct wmWindowManager *wm);
/* screen keymaps */
void ED_operatortypes_screen(void);
void ED_keymap_screen(struct wmKeyConfig *keyconf);
/* workspace keymaps */
void ED_operatortypes_workspace(void);
/* operators; context poll callbacks */
int ED_operator_screenactive(struct bContext *C);

View File

@@ -262,8 +262,9 @@ void ED_view3d_calc_camera_border_size(
const struct Scene *scene, const struct ARegion *ar,
const struct View3D *v3d, const struct RegionView3D *rv3d,
float r_size[2]);
bool ED_view3d_calc_render_border(struct Scene *scene, struct View3D *v3d,
struct ARegion *ar, struct rcti *rect);
bool ED_view3d_calc_render_border(
const struct Scene *scene, struct View3D *v3d,
struct ARegion *ar, struct rcti *rect);
void ED_view3d_clipping_calc_from_boundbox(float clip[6][4], const struct BoundBox *clipbb, const bool is_flip);
void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4],
@@ -388,7 +389,7 @@ char ED_view3d_axis_view_opposite(char view);
bool ED_view3d_lock(struct RegionView3D *rv3d);
uint64_t ED_view3d_datamask(const struct Scene *scene, const struct View3D *v3d);
uint64_t ED_view3d_screen_datamask(const struct bScreen *screen);
uint64_t ED_view3d_screen_datamask(const struct Scene *scene, const struct bScreen *screen);
bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d);

View File

@@ -2790,11 +2790,13 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh
block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]);
}
else {
const bScreen *screen = WM_window_get_active_screen(window);
/* no subwindow created yet, for menus for example, so we
* use the main window instead, since buttons are created
* there anyway */
wm_subwindow_matrix_get(window, window->screen->mainwin, block->winmat);
wm_subwindow_size_get(window, window->screen->mainwin, &getsizex, &getsizey);
wm_subwindow_matrix_get(window, screen->mainwin, block->winmat);
wm_subwindow_size_get(window, screen->mainwin, &getsizex, &getsizey);
block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]);
block->auto_open = true;
@@ -4628,7 +4630,10 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
if (ptr && prop) {
if (!item) {
int i;
/* so the context is passed to itemf functions */
WM_operator_properties_sanitize(ptr, false);
RNA_property_enum_items_gettexted(C, ptr, prop, &items, &totitems, &free_items);
for (i = 0, item = items; i < totitems; i++, item++) {
if (item->identifier[0] && item->value == value)

View File

@@ -169,8 +169,8 @@ static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, c
*/
static uiBut *eyedropper_get_property_button_under_mouse(bContext *C, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, event->x, event->y);
bScreen *screen = CTX_wm_screen(C);
ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->x, event->y);
ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_ANY, event->x, event->y);
uiBut *but = ui_but_find_mouse_over(ar, event);
@@ -262,10 +262,9 @@ static void eyedropper_exit(bContext *C, wmOperator *op)
*/
static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int mx, int my, float r_col[3])
{
/* we could use some clever */
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my);
bScreen *screen = CTX_wm_screen(C);
ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
const char *display_device = CTX_data_scene(C)->display_settings.display_device;
struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
@@ -586,8 +585,8 @@ static void datadropper_exit(bContext *C, wmOperator *op)
static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int my, ID **r_id)
{
/* we could use some clever */
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = BKE_screen_find_area_xy(win->screen, -1, mx, my);
bScreen *screen = CTX_wm_screen(C);
ScrArea *sa = BKE_screen_find_area_xy(screen, -1, mx, my);
ScrArea *area_prev = CTX_wm_area(C);
ARegion *ar_prev = CTX_wm_region(C);
@@ -887,9 +886,9 @@ static void depthdropper_exit(bContext *C, wmOperator *op)
static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth)
{
/* we could use some clever */
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my);
Scene *scene = win->screen->scene;
bScreen *screen = CTX_wm_screen(C);
ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
Scene *scene = CTX_data_scene(C);
UnitSettings *unit = &scene->unit;
const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;

View File

@@ -117,6 +117,9 @@ static ARegion *ui_region_temp_add(bScreen *sc)
static void ui_region_temp_remove(bContext *C, bScreen *sc, ARegion *ar)
{
wmWindow *win = CTX_wm_window(C);
BLI_assert(ar->regiontype == RGN_TYPE_TEMPORARY);
BLI_assert(BLI_findindex(&sc->regionbase, ar) != -1);
if (win)
wm_draw_region_clear(win, ar);
@@ -3361,11 +3364,13 @@ void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block)
/* if loading new .blend while popup is open, window will be NULL */
if (block->handle) {
if (win) {
const bScreen *screen = WM_window_get_active_screen(win);
UI_popup_handlers_remove(&win->modalhandlers, block->handle);
ui_popup_block_free(C, block->handle);
/* In the case we have nested popups, closing one may need to redraw another, see: T48874 */
for (ARegion *ar = win->screen->regionbase.first; ar; ar = ar->next) {
for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) {
ED_region_tag_refresh_ui(ar);
}
}

View File

@@ -448,6 +448,7 @@ static const char *template_id_browse_tip(const StructRNA *type)
case ID_PAL: return N_("Browse Palette Data to be linked");
case ID_PC: return N_("Browse Paint Curve Data to be linked");
case ID_CF: return N_("Browse Cache Files to be linked");
case ID_WS: return N_("Browse Workspace to be linked");
}
}
return N_("Browse ID data to be linked");
@@ -551,7 +552,7 @@ static void template_ID(
if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT);
if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) {
uiDefButR(block, UI_BTYPE_TOGGLE, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
}
}
@@ -585,6 +586,7 @@ static void template_ID(
BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
BLT_I18NCONTEXT_ID_GPENCIL,
BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
BLT_I18NCONTEXT_ID_WORKSPACE,
);
if (newop) {

View File

@@ -298,8 +298,7 @@ void ui_rna_collection_search_cb(const struct bContext *C, void *arg, const char
}
/***************************** ID Utilities *******************************/
/***************************** ID Utilities *******************************/
int UI_icon_from_id(ID *id)
{
Object *ob;

View File

@@ -2899,13 +2899,7 @@ void init_userdef_do_versions(void)
btheme->ttime.time_keyframe[3] = btheme->ttime.time_gp_keyframe[3] = 255;
}
}
/**
* Include next version bump.
*
* (keep this block even if it becomes empty).
*/
{
if (!USER_VERSION_ATLEAST(280, 1)) {
/* interface_widgets.c */
struct uiWidgetColors wcol_tab = {
{255, 255, 255, 255},
@@ -2925,6 +2919,15 @@ void init_userdef_do_versions(void)
}
}
/**
* Include next version bump.
*
* (keep this block even if it becomes empty).
*/
{
}
if (U.pixelsize == 0.0f)
U.pixelsize = 1.0f;

View File

@@ -1210,8 +1210,8 @@ static int object_delete_exec(bContext *C, wmOperator *op)
/* delete has to handle all open scenes */
BKE_main_id_tag_listbase(&bmain->scene, LIB_TAG_DOIT, true);
for (win = wm->windows.first; win; win = win->next) {
scene = win->screen->scene;
scene = WM_window_get_active_scene(win);
if (scene->id.tag & LIB_TAG_DOIT) {
scene->id.tag &= ~LIB_TAG_DOIT;

View File

@@ -83,6 +83,7 @@
#include "BKE_modifier.h"
#include "BKE_editmesh.h"
#include "BKE_report.h"
#include "BKE_workspace.h"
#include "ED_armature.h"
#include "ED_curve.h"
@@ -1499,8 +1500,15 @@ bool ED_object_mode_compat_set(bContext *C, Object *ob, int mode, ReportList *re
{
bool ok;
if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
WorkSpace *workspace = CTX_wm_workspace(C);
const char *opstring = object_mode_op_string(ob->mode);
WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
#ifdef USE_WORKSPACE_MODE
BKE_workspace_object_mode_set(workspace, ob->mode);
#else
UNUSED_VARS(workspace);
#endif
ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
if (!ok) {
wmOperatorType *ot = WM_operatortype_find(opstring, false);
@@ -1610,13 +1618,23 @@ void OBJECT_OT_mode_set(wmOperatorType *ot)
}
void ED_object_toggle_modes(bContext *C, int mode)
{
if (mode != OB_MODE_OBJECT) {
const char *opstring = object_mode_op_string(mode);
if (opstring) {
#ifdef USE_WORKSPACE_MODE
WorkSpace *workspace = CTX_wm_workspace(C);
#endif
WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
#ifdef USE_WORKSPACE_MODE
Object *ob = CTX_data_active_object(C);
if (ob) {
BKE_workspace_object_mode_set(workspace, ob->mode);
}
#endif
}
}
}

View File

@@ -59,6 +59,7 @@
#include "BKE_property.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_workspace.h"
#include "BKE_library.h"
#include "BKE_deform.h"
@@ -110,7 +111,12 @@ void ED_base_object_activate(bContext *C, BaseLegacy *base)
BASACT = base;
if (base) {
#ifdef USE_WORKSPACE_MODE
WorkSpace *workspace = CTX_wm_workspace(C);
BKE_workspace_object_mode_set(workspace, base->object->mode);
#endif
/* XXX old signals, remember to handle notifiers now! */
// select_actionchannel_by_name(base->object->action, "Object", 1);

View File

@@ -491,8 +491,9 @@ static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr,
for (wm = rj->main->wm.first; wm && matched_sa == NULL; wm = wm->id.next) { /* only 1 wm */
wmWindow *win;
for (win = wm->windows.first; win && matched_sa == NULL; win = win->next) {
ScrArea *sa;
for (sa = win->screen->areabase.first; sa; sa = sa->next) {
const bScreen *screen = WM_window_get_active_screen(win);
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
if (sa->spacetype == SPACE_IMAGE) {
SpaceImage *sima = sa->spacedata.first;
// sa->spacedata might be empty when toggling fullscreen mode.
@@ -618,8 +619,9 @@ static void render_image_restore_layer(RenderJob *rj)
for (wm = rj->main->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
wmWindow *win;
for (win = wm->windows.first; win; win = win->next) {
ScrArea *sa;
for (sa = win->screen->areabase.first; sa; sa = sa->next) {
const bScreen *screen = WM_window_get_active_screen(win);
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
if (sa == rj->sa) {
if (sa->spacetype == SPACE_IMAGE) {
SpaceImage *sima = sa->spacedata.first;

View File

@@ -66,6 +66,8 @@
#include "ED_render.h"
#include "ED_view3d.h"
#include "WM_api.h"
#include "render_intern.h" // own include
extern Material defmaterial;
@@ -104,7 +106,7 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
wm = bmain->wm.first;
for (win = wm->windows.first; win; win = win->next) {
bScreen *sc = win->screen;
bScreen *sc = WM_window_get_active_screen(win);
ScrArea *sa;
ARegion *ar;

View File

@@ -90,8 +90,10 @@ static ScrArea *find_area_showing_r_result(bContext *C, Scene *scene, wmWindow *
/* find an imagewindow showing render result */
for (*win = wm->windows.first; *win; *win = (*win)->next) {
if ((*win)->screen->scene == scene) {
for (sa = (*win)->screen->areabase.first; sa; sa = sa->next) {
if (WM_window_get_active_scene(*win) == scene) {
const bScreen *screen = WM_window_get_active_screen(*win);
for (sa = screen->areabase.first; sa; sa = sa->next) {
if (sa->spacetype == SPACE_IMAGE) {
sima = sa->spacedata.first;
if (sima->image && sima->image->type == IMA_TYPE_R_RESULT)
@@ -246,7 +248,7 @@ static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(op))
}
/* test if we have a temp screen in front */
if (win->screen->temp) {
if (WM_window_is_temp_screen(win)) {
wm_window_lower(win);
return OPERATOR_FINISHED;
}
@@ -292,7 +294,7 @@ static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *e
wmWindow *wincur = CTX_wm_window(C);
/* test if we have currently a temp screen active */
if (wincur->screen->temp) {
if (WM_window_is_temp_screen(wincur)) {
wm_window_lower(wincur);
}
else {
@@ -301,8 +303,9 @@ static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *e
/* is there another window on current scene showing result? */
for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) {
bScreen *sc = win->screen;
if ((sc->temp && ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) ||
const bScreen *sc = WM_window_get_active_screen(win);
if ((WM_window_is_temp_screen(win) && ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) ||
(win == winshow && winshow != wincur))
{
wm_window_raise(win);

View File

@@ -0,0 +1,43 @@
# ***** 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.
#
# Contributor(s): Jacques Beaurain.
#
# ***** END GPL LICENSE BLOCK *****
set(INC
../include
../../blenkernel
../../blenlib
../../blentranslation
../../makesdna
../../makesrna
../../windowmanager
)
set(INC_SYS
)
set(SRC
scene_edit.c
)
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
blender_add_lib(bf_editor_scene "${SRC}" "${INC}" "${INC_SYS}")

View File

@@ -0,0 +1,202 @@
/*
* ***** 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/editors/scene/scene_edit.c
* \ingroup edscene
*/
#include <stdio.h>
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_scene.h"
#include "BKE_workspace.h"
#include "BLI_compiler_attrs.h"
#include "BLI_listbase.h"
#include "BLT_translation.h"
#include "ED_object.h"
#include "ED_render.h"
#include "ED_scene.h"
#include "ED_screen.h"
#include "ED_util.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
Scene *ED_scene_add(Main *bmain, bContext *C, wmWindow *win, eSceneCopyMethod method)
{
Scene *scene_new;
if (method == SCE_COPY_NEW) {
scene_new = BKE_scene_add(bmain, DATA_("Scene"));
}
else { /* different kinds of copying */
Scene *scene_old = WM_window_get_active_scene(win);
scene_new = BKE_scene_copy(bmain, scene_old, method);
/* these can't be handled in blenkernel currently, so do them here */
if (method == SCE_COPY_LINK_DATA) {
ED_object_single_users(bmain, scene_new, false, true);
}
else if (method == SCE_COPY_FULL) {
ED_editors_flush_edits(C, false);
ED_object_single_users(bmain, scene_new, true, true);
}
}
WM_window_change_active_scene(bmain, C, win, scene_new);
WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, scene_new);
return scene_new;
}
/**
* \note Only call outside of area/region loops
* \return true if successful
*/
bool ED_scene_delete(bContext *C, Main *bmain, wmWindow *win, Scene *scene)
{
Scene *scene_new;
if (scene->id.prev)
scene_new = scene->id.prev;
else if (scene->id.next)
scene_new = scene->id.next;
else
return false;
WM_window_change_active_scene(bmain, C, win, scene_new);
BKE_libblock_remap(bmain, scene, scene_new, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
BKE_libblock_free(bmain, scene);
return true;
}
void ED_scene_exit(bContext *C)
{
ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO);
}
void ED_scene_changed_update(Main *bmain, bContext *C, Scene *scene_new, const bScreen *active_screen)
{
/* XXX Just using active scene render-layer for workspace when switching,
* but workspace should remember the last one set. Could store render-layer
* per window-workspace combination (using WorkSpaceDataRelation) */
SceneLayer *layer_new = BLI_findlink(&scene_new->render_layers, scene_new->active_layer);
CTX_data_scene_set(C, scene_new);
BKE_workspace_render_layer_set(CTX_wm_workspace(C), layer_new);
BKE_scene_set_background(bmain, scene_new);
DAG_on_visible_update(bmain, false);
ED_screen_update_after_scene_change(active_screen, scene_new);
ED_render_engine_changed(bmain);
ED_update_for_newframe(bmain, scene_new, 1);
/* complete redraw */
WM_event_add_notifier(C, NC_WINDOW, NULL);
}
static int scene_new_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
int type = RNA_enum_get(op->ptr, "type");
ED_scene_add(bmain, C, win, type);
return OPERATOR_FINISHED;
}
static void SCENE_OT_new(wmOperatorType *ot)
{
static EnumPropertyItem type_items[] = {
{SCE_COPY_NEW, "NEW", 0, "New", "Add new scene"},
{SCE_COPY_EMPTY, "EMPTY", 0, "Copy Settings", "Make a copy without any objects"},
{SCE_COPY_LINK_OB, "LINK_OBJECTS", 0, "Link Objects", "Link to the objects from the current scene"},
{SCE_COPY_LINK_DATA, "LINK_OBJECT_DATA", 0, "Link Object Data", "Copy objects linked to data from the current scene"},
{SCE_COPY_FULL, "FULL_COPY", 0, "Full Copy", "Make a full copy of the current scene"},
{0, NULL, 0, NULL, NULL}
};
/* identifiers */
ot->name = "New Scene";
ot->description = "Add new scene by type";
ot->idname = "SCENE_OT_new";
/* api callbacks */
ot->exec = scene_new_exec;
ot->invoke = WM_menu_invoke;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
}
static int scene_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
if (ED_scene_delete(C, CTX_data_main(C), CTX_wm_window(C), scene) == false) {
return OPERATOR_CANCELLED;
}
if (G.debug & G_DEBUG)
printf("scene delete %p\n", scene);
WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene);
return OPERATOR_FINISHED;
}
static void SCENE_OT_delete(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Delete Scene";
ot->description = "Delete active scene";
ot->idname = "SCENE_OT_delete";
/* api callbacks */
ot->exec = scene_delete_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void ED_operatortypes_scene(void)
{
WM_operatortype_append(SCENE_OT_new);
WM_operatortype_append(SCENE_OT_delete);
}

View File

@@ -23,6 +23,7 @@ set(INC
../../blenfont
../../blenkernel
../../blenlib
../../blenloader
../../blentranslation
../../bmesh
../../gpu
@@ -46,6 +47,8 @@ set(SRC
screen_edit.c
screen_ops.c
screendump.c
workspace_edit.c
workspace_layout_edit.c
screen_intern.h
)

View File

@@ -581,9 +581,11 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
UI_blocklist_free_inactive(C, &ar->uiblocks);
if (sa) {
const bScreen *screen = WM_window_get_active_screen(win);
/* disable emboss when the area is full,
* unless we need to see division between regions (quad-split for eg) */
if (((win->screen->state == SCREENFULL) && (ar->alignment == RGN_ALIGN_NONE)) == 0) {
if (((screen->state == SCREENFULL) && (ar->alignment == RGN_ALIGN_NONE)) == 0) {
region_draw_emboss(ar, &ar->winrct);
}
}
@@ -1353,7 +1355,9 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
* must be minimum '4' */
}
else {
if (ELEM(win->screen->state, SCREENNORMAL, SCREENMAXIMIZED)) {
const bScreen *screen = WM_window_get_active_screen(win);
if (ELEM(screen->state, SCREENNORMAL, SCREENMAXIMIZED)) {
region_azone_add(sa, ar, alignment, false);
}
else {
@@ -1477,6 +1481,7 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand
/* called in screen_refresh, or screens_init, also area size changes */
void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
{
const bScreen *screen = WM_window_get_active_screen(win);
ARegion *ar;
rcti rect;
@@ -1495,7 +1500,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
area_calc_totrct(sa, WM_window_pixels_x(win), WM_window_pixels_y(win));
/* clear all azones, add the area triange widgets */
area_azone_initialize(win, win->screen, sa);
area_azone_initialize(win, screen, sa);
/* region rect sizes */
rect = sa->totrct;

View File

@@ -50,6 +50,7 @@
#include "BKE_layer.h"
#include "BKE_screen.h"
#include "BKE_sequencer.h"
#include "BKE_workspace.h"
#include "RNA_access.h"
@@ -81,10 +82,13 @@ const char *screen_context_dir[] = {
int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result)
{
wmWindow *win = CTX_wm_window(C);
bScreen *sc = CTX_wm_screen(C);
ScrArea *sa = CTX_wm_area(C);
Scene *scene = sc->scene;
SceneLayer *sl = CTX_data_scene_layer(C);
Scene *scene = WM_window_get_active_scene(win);
/* can't call BKE_scene_layer_context_active here, it uses G.main->wm which might be NULL on file read. */
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
SceneLayer *sl = BKE_workspace_render_layer_get(workspace);
Object *obedit = scene->obedit;
Object *obact = sl->basact ? sl->basact->object : NULL;

View File

@@ -293,6 +293,7 @@ static void drawscredge_area(ScrArea *sa, int sizex, int sizey, unsigned int pos
*/
void ED_screen_draw(wmWindow *win)
{
bScreen *screen = WM_window_get_active_screen(win);
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
@@ -301,7 +302,7 @@ void ED_screen_draw(wmWindow *win)
ScrArea *sa2 = NULL;
ScrArea *sa3 = NULL;
wmSubWindowSet(win, win->screen->mainwin);
wmSubWindowSet(win, screen->mainwin);
unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -312,7 +313,7 @@ void ED_screen_draw(wmWindow *win)
glLineWidth((2.0f * U.pixelsize) - 1);
immUniformColor3ub(0x50, 0x50, 0x50);
for (sa = win->screen->areabase.first; sa; sa = sa->next) {
for (sa = screen->areabase.first; sa; sa = sa->next) {
drawscredge_area(sa, winsize_x, winsize_y, pos);
}
}
@@ -320,7 +321,7 @@ void ED_screen_draw(wmWindow *win)
glLineWidth(1);
immUniformColor3ub(0, 0, 0);
for (sa = win->screen->areabase.first; sa; sa = sa->next) {
for (sa = screen->areabase.first; sa; sa = sa->next) {
drawscredge_area(sa, winsize_x, winsize_y, pos);
/* gather area split/join info */
@@ -403,7 +404,7 @@ void ED_screen_draw(wmWindow *win)
immUnbindProgram();
win->screen->do_draw = false;
screen->do_draw = false;
}

View File

@@ -51,6 +51,7 @@
#include "BKE_node.h"
#include "BKE_screen.h"
#include "BKE_scene.h"
#include "BKE_workspace.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -264,7 +265,7 @@ bool scredge_is_horizontal(ScrEdge *se)
}
/* need win size to make sure not to include edges along screen edge */
ScrEdge *screen_find_active_scredge(bScreen *sc,
ScrEdge *screen_find_active_scredge(const bScreen *sc,
const int winsize_x, const int winsize_y,
const int mx, const int my)
{
@@ -455,39 +456,35 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
return newa;
}
/* empty screen, with 1 dummy area without spacedata */
/* uses window size */
bScreen *ED_screen_add(wmWindow *win, Scene *scene, const char *name)
/**
* Empty screen, with 1 dummy area without spacedata. Uses window size.
*/
bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y)
{
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
bScreen *sc;
ScrVert *sv1, *sv2, *sv3, *sv4;
sc = BKE_libblock_alloc(G.main, ID_SCR, name);
sc->scene = scene;
sc->do_refresh = true;
sc->redraws_flag = TIME_ALL_3D_WIN | TIME_ALL_ANIM_WIN;
sc->winid = win->winid;
sv1 = screen_addvert(sc, 0, 0);
sv2 = screen_addvert(sc, 0, winsize_y - 1);
sv3 = screen_addvert(sc, winsize_x - 1, winsize_y - 1);
sv4 = screen_addvert(sc, winsize_x - 1, 0);
screen_addedge(sc, sv1, sv2);
screen_addedge(sc, sv2, sv3);
screen_addedge(sc, sv3, sv4);
screen_addedge(sc, sv4, sv1);
/* dummy type, no spacedata */
screen_addarea(sc, sv1, sv2, sv3, sv4, HEADERDOWN, SPACE_EMPTY);
return sc;
}
static void screen_copy(bScreen *to, bScreen *from)
void screen_data_copy(bScreen *to, bScreen *from)
{
ScrVert *s1, *s2;
ScrEdge *se;
@@ -530,7 +527,16 @@ static void screen_copy(bScreen *to, bScreen *from)
/* put at zero (needed?) */
for (s1 = from->vertbase.first; s1; s1 = s1->next)
s1->newv = NULL;
}
/**
* Prepare a newly created screen for initializing it as active screen.
*/
void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new)
{
screen_new->winid = win->winid;
screen_new->do_refresh = true;
screen_new->do_draw = true;
}
@@ -841,24 +847,12 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
/* ****************** EXPORTED API TO OTHER MODULES *************************** */
bScreen *ED_screen_duplicate(wmWindow *win, bScreen *sc)
{
bScreen *newsc;
if (sc->state != SCREENNORMAL) return NULL; /* XXX handle this case! */
/* make new empty screen: */
newsc = ED_screen_add(win, sc->scene, sc->id.name + 2);
/* copy all data */
screen_copy(newsc, sc);
return newsc;
}
/* screen sets cursor based on swinid */
static void region_cursor_set(wmWindow *win, int swinid, int swin_changed)
{
for (ScrArea *sa = win->screen->areabase.first; sa; sa = sa->next) {
bScreen *screen = WM_window_get_active_screen(win);
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->swinid == swinid) {
if (swin_changed || (ar->type && ar->type->event_cursor)) {
@@ -876,19 +870,20 @@ static void region_cursor_set(wmWindow *win, int swinid, int swin_changed)
void ED_screen_do_listen(bContext *C, wmNotifier *note)
{
wmWindow *win = CTX_wm_window(C);
bScreen *screen = CTX_wm_screen(C);
/* generic notes */
switch (note->category) {
case NC_WM:
if (note->data == ND_FILEREAD)
win->screen->do_draw = true;
screen->do_draw = true;
break;
case NC_WINDOW:
win->screen->do_draw = true;
screen->do_draw = true;
break;
case NC_SCREEN:
if (note->action == NA_EDITED)
win->screen->do_draw = win->screen->do_refresh = true;
screen->do_draw = screen->do_refresh = true;
break;
case NC_SCENE:
if (note->data == ND_MODE)
@@ -912,7 +907,9 @@ static void screen_refresh_headersizes(void)
/* make this screen usable */
/* for file read and first use, for scaling window, area moves */
void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
{
{
bScreen *screen = WM_window_get_active_screen(win);
/* exception for bg mode, we only need the screen context */
if (!G.background) {
const int winsize_x = WM_window_pixels_x(win);
@@ -928,32 +925,34 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
/* header size depends on DPI, let's verify */
screen_refresh_headersizes();
screen_test_scale(win->screen, winsize_x, winsize_y);
screen_test_scale(screen, winsize_x, winsize_y);
if (win->screen->mainwin == 0) {
win->screen->mainwin = wm_subwindow_open(win, &winrct, false);
if (screen->mainwin == 0) {
screen->mainwin = wm_subwindow_open(win, &winrct, false);
}
else {
wm_subwindow_position(win, win->screen->mainwin, &winrct, false);
wm_subwindow_position(win, screen->mainwin, &winrct, false);
}
for (sa = win->screen->areabase.first; sa; sa = sa->next) {
for (sa = screen->areabase.first; sa; sa = sa->next) {
/* set spacetype and region callbacks, calls init() */
/* sets subwindows for regions, adds handlers */
ED_area_initialize(wm, win, sa);
}
/* wake up animtimer */
if (win->screen->animtimer)
WM_event_timer_sleep(wm, win, win->screen->animtimer, false);
if (screen->animtimer)
WM_event_timer_sleep(wm, win, screen->animtimer, false);
}
if (G.debug & G_DEBUG_EVENTS) {
printf("%s: set screen\n", __func__);
}
win->screen->do_refresh = false;
screen->do_refresh = false;
/* prevent multiwin errors */
screen->winid = win->winid;
win->screen->context = ed_screen_context;
screen->context = ed_screen_context;
}
/* file read, set all screens, ... */
@@ -962,10 +961,10 @@ void ED_screens_initialize(wmWindowManager *wm)
wmWindow *win;
for (win = wm->windows.first; win; win = win->next) {
if (win->screen == NULL)
win->screen = G.main->screen.first;
if (WM_window_get_active_workspace(win) == NULL) {
WM_window_set_active_workspace(win, G.main->workspaces.first);
}
ED_screen_refresh(wm, win);
}
}
@@ -1053,7 +1052,7 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
/* mark it available for use for other windows */
screen->winid = 0;
if (prevwin->screen->temp == 0) {
if (!WM_window_is_temp_screen(prevwin)) {
/* use previous window if possible */
CTX_wm_window_set(C, prevwin);
}
@@ -1069,13 +1068,14 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
/* case when on area-edge or in azones, or outside window */
static void screen_cursor_set(wmWindow *win, wmEvent *event)
{
const bScreen *screen = WM_window_get_active_screen(win);
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
AZone *az = NULL;
ScrArea *sa;
for (sa = win->screen->areabase.first; sa; sa = sa->next)
for (sa = screen->areabase.first; sa; sa = sa->next)
if ((az = is_in_area_actionzone(sa, &event->x)))
break;
@@ -1090,7 +1090,7 @@ static void screen_cursor_set(wmWindow *win, wmEvent *event)
}
}
else {
ScrEdge *actedge = screen_find_active_scredge(win->screen, winsize_x, winsize_y, event->x, event->y);
ScrEdge *actedge = screen_find_active_scredge(screen, winsize_x, winsize_y, event->x, event->y);
if (actedge) {
if (scredge_is_horizontal(actedge))
@@ -1109,9 +1109,9 @@ static void screen_cursor_set(wmWindow *win, wmEvent *event)
void ED_screen_set_subwinactive(bContext *C, wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
if (win->screen) {
bScreen *scr = win->screen;
bScreen *scr = WM_window_get_active_screen(win);
if (scr) {
ScrArea *sa;
ARegion *ar;
int oldswin = scr->subwinactive;
@@ -1164,7 +1164,7 @@ void ED_screen_set_subwinactive(bContext *C, wmEvent *event)
/* this used to be a notifier, but needs to be done immediate
* because it can undo setting the right button as active due
* to delayed notifier handling */
UI_screen_free_active_but(C, win->screen);
UI_screen_free_active_but(C, scr);
}
else
region_cursor_set(win, scr->subwinactive, false);
@@ -1192,177 +1192,120 @@ int ED_screen_area_active(const bContext *C)
return 0;
}
/**
* operator call, WM + Window + screen already existed before
*
* \warning Do NOT call in area/region queues!
* \returns success.
*/
bool ED_screen_set(bContext *C, bScreen *sc)
{
Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
bScreen *oldscreen = CTX_wm_screen(C);
/* validate screen, it's called with notifier reference */
if (BLI_findindex(&bmain->screen, sc) == -1) {
return true;
}
if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) {
/* find associated full */
bScreen *sc1;
for (sc1 = bmain->screen.first; sc1; sc1 = sc1->id.next) {
ScrArea *sa = sc1->areabase.first;
if (sa->full == sc) {
sc = sc1;
break;
}
/* -------------------------------------------------------------------- */
/* Screen changing */
static bScreen *screen_fullscreen_find_associated_normal_screen(const Main *bmain, bScreen *screen)
{
for (bScreen *screen_iter = bmain->screen.first; screen_iter; screen_iter = screen_iter->id.next) {
ScrArea *sa = screen_iter->areabase.first;
if (sa->full == screen) {
return screen_iter;
}
}
/* check for valid winid */
if (sc->winid != 0 && sc->winid != win->winid) {
return false;
return screen;
}
/**
* \return the screen to activate.
* \warning The returned screen may not always equal \a screen_new!
*/
bScreen *screen_change_prepare(bScreen *screen_old, bScreen *screen_new, Main *bmain, bContext *C, wmWindow *win)
{
/* validate screen, it's called with notifier reference */
if (BLI_findindex(&bmain->screen, screen_new) == -1) {
return NULL;
}
if (oldscreen != sc) {
wmTimer *wt = oldscreen->animtimer;
ScrArea *sa;
Scene *oldscene = oldscreen->scene;
if (ELEM(screen_new->state, SCREENMAXIMIZED, SCREENFULL)) {
screen_new = screen_fullscreen_find_associated_normal_screen(bmain, screen_new);
}
/* check for valid winid */
if (!(screen_new->winid == 0 || screen_new->winid == win->winid)) {
return NULL;
}
if (screen_old != screen_new) {
wmTimer *wt = screen_old->animtimer;
/* remove handlers referencing areas in old screen */
for (sa = oldscreen->areabase.first; sa; sa = sa->next) {
for (ScrArea *sa = screen_old->areabase.first; sa; sa = sa->next) {
WM_event_remove_area_handler(&win->modalhandlers, sa);
}
/* we put timer to sleep, so screen_exit has to think there's no timer */
oldscreen->animtimer = NULL;
screen_old->animtimer = NULL;
if (wt) {
WM_event_timer_sleep(wm, win, wt, true);
WM_event_timer_sleep(CTX_wm_manager(C), win, wt, true);
}
ED_screen_exit(C, win, oldscreen);
ED_screen_exit(C, win, screen_old);
/* Same scene, "transfer" playback to new screen. */
if (wt) {
if (oldscene == sc->scene) {
sc->animtimer = wt;
}
/* Else, stop playback. */
else {
oldscreen->animtimer = wt;
ED_screen_animation_play(C, 0, 0);
}
screen_new->animtimer = wt;
}
win->screen = sc;
CTX_wm_window_set(C, win); // stores C->wm.screen... hrmf
/* prevent multiwin errors */
sc->winid = win->winid;
ED_screen_refresh(CTX_wm_manager(C), CTX_wm_window(C));
WM_event_add_notifier(C, NC_WINDOW, NULL);
WM_event_add_notifier(C, NC_SCREEN | ND_SCREENSET, sc);
/* makes button hilites work */
WM_event_add_mousemove(C);
/* Needed to make sure all the derivedMeshes are
* up-to-date before viewport starts acquiring this.
*
* This is needed in cases when, for example, boolean
* modifier uses operant from invisible layer.
* Without this trick boolean wouldn't apply correct.
*
* Quite the same happens when setting screen's scene,
* so perhaps this is in fact correct thing to do.
*/
if (oldscene != sc->scene) {
BKE_scene_set_background(bmain, sc->scene);
}
/* Always do visible update since it's possible new screen will
* have different layers visible in 3D view-ports.
* This is possible because of view3d.lock_camera_and_layers option.
*/
DAG_on_visible_update(bmain, false);
return screen_new;
}
return true;
return NULL;
}
static bool ed_screen_used(wmWindowManager *wm, bScreen *sc)
void screen_changed_update(bContext *C, wmWindow *win, bScreen *sc)
{
wmWindow *win;
Scene *scene = WM_window_get_active_scene(win);
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, sc);
for (win = wm->windows.first; win; win = win->next) {
if (win->screen == sc) {
return true;
}
CTX_wm_window_set(C, win); /* stores C->wm.screen... hrmf */
if (ELEM(win->screen->state, SCREENMAXIMIZED, SCREENFULL)) {
ScrArea *sa = win->screen->areabase.first;
if (sa->full == sc) {
return true;
}
}
ED_screen_refresh(CTX_wm_manager(C), win);
BKE_screen_view3d_scene_sync(sc, scene); /* sync new screen with scene data */
WM_event_add_notifier(C, NC_WINDOW, NULL);
WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTSET, layout);
/* makes button hilites work */
WM_event_add_mousemove(C);
}
/**
* \brief Change the active screen.
*
* Operator call, WM + Window + screen already existed before
*
* \warning Do NOT call in area/region queues!
* \returns if screen changing was successful.
*/
bool ED_screen_change(bContext *C, bScreen *sc)
{
Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
bScreen *screen_old = CTX_wm_screen(C);
bScreen *screen_new = screen_change_prepare(screen_old, sc, bmain, C, win);
if (screen_new) {
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
WM_window_set_active_screen(win, workspace, sc);
screen_changed_update(C, win, screen_new);
return true;
}
return false;
}
/* only call outside of area/region loops */
bool ED_screen_delete(bContext *C, bScreen *sc)
{
Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
bScreen *newsc;
/* don't allow deleting temp fullscreens for now */
if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) {
return false;
}
/* screen can only be in use by one window at a time, so as
* long as we are able to find a screen that is unused, we
* can safely assume ours is not in use anywhere an delete it */
for (newsc = sc->id.prev; newsc; newsc = newsc->id.prev)
if (!ed_screen_used(wm, newsc) && !newsc->temp)
break;
if (!newsc) {
for (newsc = sc->id.next; newsc; newsc = newsc->id.next)
if (!ed_screen_used(wm, newsc) && !newsc->temp)
break;
}
if (!newsc) {
return false;
}
ED_screen_set(C, newsc);
if (win->screen != sc) {
BKE_libblock_free(bmain, sc);
return true;
}
else {
return false;
}
}
static void ed_screen_set_3dview_camera(Scene *scene, bScreen *sc, ScrArea *sa, View3D *v3d)
static void screen_set_3dview_camera(Scene *scene, ScrArea *sa, View3D *v3d)
{
/* fix any cameras that are used in the 3d view but not in the scene */
BKE_screen_view3d_sync(v3d, scene);
if (!v3d->camera || !BKE_scene_base_find(scene, v3d->camera)) {
v3d->camera = BKE_scene_camera_find(sc->scene);
v3d->camera = BKE_scene_camera_find(scene);
// XXX if (sc == curscreen) handle_view3d_lock();
if (!v3d->camera) {
ARegion *ar;
@@ -1386,90 +1329,16 @@ static void ed_screen_set_3dview_camera(Scene *scene, bScreen *sc, ScrArea *sa,
}
}
/* only call outside of area/region loops */
void ED_screen_set_scene(bContext *C, bScreen *screen, Scene *scene)
void ED_screen_update_after_scene_change(const bScreen *screen, Scene *scene_new)
{
Main *bmain = CTX_data_main(C);
bScreen *sc;
if (screen == NULL)
return;
if (ed_screen_used(CTX_wm_manager(C), screen))
ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO);
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
if ((U.flag & USER_SCENEGLOBAL) || sc == screen) {
if (scene != sc->scene) {
/* all areas endlocalview */
// XXX ScrArea *sa = sc->areabase.first;
// while (sa) {
// endlocalview(sa);
// sa = sa->next;
// }
sc->scene = scene;
}
}
}
// copy_view3d_lock(0); /* space.c */
/* are there cameras in the views that are not in the scene? */
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
if ((U.flag & USER_SCENEGLOBAL) || sc == screen) {
ScrArea *sa = sc->areabase.first;
while (sa) {
SpaceLink *sl = sa->spacedata.first;
while (sl) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *) sl;
ed_screen_set_3dview_camera(scene, sc, sa, v3d);
}
sl = sl->next;
}
sa = sa->next;
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
screen_set_3dview_camera(scene_new, sa, v3d);
}
}
}
CTX_data_scene_set(C, scene);
BKE_scene_set_background(bmain, scene);
DAG_on_visible_update(bmain, false);
ED_render_engine_changed(bmain);
ED_update_for_newframe(bmain, scene, 1);
/* complete redraw */
WM_event_add_notifier(C, NC_WINDOW, NULL);
}
/**
* \note Only call outside of area/region loops
* \return true if successful
*/
bool ED_screen_delete_scene(bContext *C, Scene *scene)
{
Main *bmain = CTX_data_main(C);
Scene *newscene;
if (scene->id.prev)
newscene = scene->id.prev;
else if (scene->id.next)
newscene = scene->id.next;
else
return false;
ED_screen_set_scene(C, CTX_wm_screen(C), newscene);
BKE_libblock_remap(bmain, scene, newscene, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
BKE_libblock_free(bmain, scene);
return true;
}
ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
@@ -1576,6 +1445,7 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa)
ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const short state)
{
wmWindowManager *wm = CTX_wm_manager(C);
WorkSpace *workspace = WM_window_get_active_workspace(win);
bScreen *sc, *oldscreen;
ARegion *ar;
@@ -1597,11 +1467,12 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
}
if (sa && sa->full) {
WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
/* restoring back to SCREENNORMAL */
ScrArea *old;
sc = sa->full; /* the old screen to restore */
oldscreen = win->screen; /* the one disappearing */
oldscreen = WM_window_get_active_screen(win); /* the one disappearing */
sc->state = SCREENNORMAL;
@@ -1629,10 +1500,9 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
sc->animtimer = oldscreen->animtimer;
oldscreen->animtimer = NULL;
ED_screen_set(C, sc);
ED_screen_change(C, sc);
BKE_screen_free(oldscreen);
BKE_libblock_free(CTX_data_main(C), oldscreen);
BKE_workspace_layout_remove(CTX_data_main(C), workspace, layout_old);
/* After we've restored back to SCREENNORMAL, we have to wait with
* screen handling as it uses the area coords which aren't updated yet.
@@ -1642,14 +1512,18 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
}
else {
/* change from SCREENNORMAL to new state */
WorkSpaceLayout *layout_new;
ScrArea *newa;
char newname[MAX_ID_NAME - 2];
oldscreen = win->screen;
oldscreen = WM_window_get_active_screen(win);
oldscreen->state = state;
BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal");
sc = ED_screen_add(win, oldscreen->scene, newname);
layout_new = ED_workspace_layout_add(workspace, win, newname);
sc = BKE_workspace_layout_screen_get(layout_new);
sc->state = state;
sc->redraws_flag = oldscreen->redraws_flag;
sc->temp = oldscreen->temp;
@@ -1704,7 +1578,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
BLI_assert(false);
}
ED_screen_set(C, sc);
ED_screen_change(C, sc);
}
/* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */
@@ -1850,7 +1724,7 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
scene->camera = camera;
/* are there cameras in the views that are not in the scene? */
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
BKE_screen_view3d_scene_sync(sc);
BKE_screen_view3d_scene_sync(sc, scene);
}
}
#endif
@@ -1879,11 +1753,10 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
/*
* return true if any active area requires to see in 3D
*/
bool ED_screen_stereo3d_required(bScreen *screen)
bool ED_screen_stereo3d_required(const bScreen *screen, const Scene *scene)
{
ScrArea *sa;
Scene *sce = screen->scene;
const bool is_multiview = (sce->r.scemode & R_MULTIVIEW) != 0;
const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
for (sa = screen->areabase.first; sa; sa = sa->next) {
switch (sa->spacetype) {
@@ -1958,3 +1831,19 @@ bool ED_screen_stereo3d_required(bScreen *screen)
return false;
}
/**
* Find the scene displayed in \a screen.
* \note Assumes \a screen to be visible/active!
*/
Scene *ED_screen_scene_find(const bScreen *screen, const wmWindowManager *wm)
{
for (wmWindow *win = wm->windows.first; win; win = win->next) {
if (WM_window_get_active_screen(win) == screen) {
return WM_window_get_active_scene(win);
}
}
BLI_assert(0);
return NULL;
}

View File

@@ -32,6 +32,7 @@
#define __SCREEN_INTERN_H__
struct bContextDataResult;
struct Main;
/* internal exports only */
@@ -45,6 +46,11 @@ void ED_area_data_swap(ScrArea *sa1, ScrArea *sa2);
void region_toggle_hidden(struct bContext *C, ARegion *ar, const bool do_fade);
/* screen_edit.c */
bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y);
void screen_data_copy(bScreen *to, bScreen *from);
void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new);
void screen_changed_update(struct bContext *C, wmWindow *win, bScreen *sc);
bScreen *screen_change_prepare(bScreen *screen_old, bScreen *screen_new, struct Main *bmain, struct bContext *C, wmWindow *win);
ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2);
ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge);
int screen_area_join(struct bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2);
@@ -56,7 +62,7 @@ void removedouble_scrverts(bScreen *sc);
void removedouble_scredges(bScreen *sc);
void removenotused_scredges(bScreen *sc);
bool scredge_is_horizontal(ScrEdge *se);
ScrEdge *screen_find_active_scredge(bScreen *sc,
ScrEdge *screen_find_active_scredge(const bScreen *sc,
const int winsize_x, const int winsize_y,
const int mx, const int my);
@@ -74,5 +80,8 @@ void SCREEN_OT_screencast(struct wmOperatorType *ot);
/* screen_ops.c */
void region_blend_start(struct bContext *C, struct ScrArea *sa, struct ARegion *ar);
/* workspace_layout_edit.c */
bool workspace_layout_set_poll(const struct WorkSpaceLayout *layout);
#endif /* __SCREEN_INTERN_H__ */

View File

@@ -62,6 +62,7 @@
#include "BKE_editmesh.h"
#include "BKE_sound.h"
#include "BKE_mask.h"
#include "BKE_workspace.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -978,13 +979,17 @@ static void SCREEN_OT_area_swap(wmOperatorType *ot)
/* operator callback */
static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *newwin, *win;
bScreen *newsc, *sc;
wmWindow *newwin, *win = CTX_wm_window(C);
Scene *scene;
WorkSpace *workspace = WM_window_get_active_workspace(win);
WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
WorkSpaceLayout *layout_new;
bScreen *newsc;
ScrArea *sa;
rcti rect;
win = CTX_wm_window(C);
sc = CTX_wm_screen(C);
scene = CTX_data_scene(C);
sa = CTX_wm_area(C);
/* XXX hrmf! */
@@ -1010,11 +1015,15 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
*newwin->stereo3d_format = *win->stereo3d_format;
newwin->scene = scene;
WM_window_set_active_workspace(newwin, workspace);
/* allocs new screen and adds to newly created window, using window size */
newsc = ED_screen_add(newwin, CTX_data_scene(C), sc->id.name + 2);
newwin->screen = newsc;
layout_new = ED_workspace_layout_add(workspace, newwin, BKE_workspace_layout_name_get(layout_old));
newsc = BKE_workspace_layout_screen_get(layout_new);
WM_window_set_active_layout(newwin, workspace, layout_new);
/* copy area to new screen */
ED_area_data_copy((ScrArea *)newsc->areabase.first, sa, true);
@@ -1714,7 +1723,7 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
CTX_wm_window(C)->screen->do_draw = true;
CTX_wm_screen(C)->do_draw = true;
}
@@ -2084,12 +2093,11 @@ static void areas_do_frame_follow(bContext *C, bool middle)
bScreen *scr = CTX_wm_screen(C);
Scene *scene = CTX_data_scene(C);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *window;
for (window = wm->windows.first; window; window = window->next) {
ScrArea *sa;
for (sa = window->screen->areabase.first; sa; sa = sa->next) {
ARegion *ar;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
for (wmWindow *window = wm->windows.first; window; window = window->next) {
const bScreen *screen = WM_window_get_active_screen(window);
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
/* do follow here if editor type supports it */
if ((scr->redraws_flag & TIME_FOLLOW)) {
if ((ar->regiontype == RGN_TYPE_WINDOW &&
@@ -2385,64 +2393,16 @@ static void SCREEN_OT_marker_jump(wmOperatorType *ot)
/* ************** switch screen operator ***************************** */
static bool screen_set_is_ok(bScreen *screen, bScreen *screen_prev)
{
return ((screen->winid == 0) &&
/* in typical usage these should have a nonzero winid
* (all temp screens should be used, or closed & freed). */
(screen->temp == false) &&
(screen->state == SCREENNORMAL) &&
(screen != screen_prev) &&
(screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT)));
}
/* function to be called outside UI context, or for redo */
static int screen_set_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
bScreen *screen = CTX_wm_screen(C);
bScreen *screen_prev = screen;
ScrArea *sa = CTX_wm_area(C);
int tot = BLI_listbase_count(&bmain->screen);
WorkSpace *workspace = CTX_wm_workspace(C);
int delta = RNA_int_get(op->ptr, "delta");
/* temp screens are for userpref or render display */
if (screen->temp || (sa && sa->full && sa->full->temp)) {
return OPERATOR_CANCELLED;
}
if (delta == 1) {
while (tot--) {
screen = screen->id.next;
if (screen == NULL) screen = bmain->screen.first;
if (screen_set_is_ok(screen, screen_prev)) {
break;
}
}
}
else if (delta == -1) {
while (tot--) {
screen = screen->id.prev;
if (screen == NULL) screen = bmain->screen.last;
if (screen_set_is_ok(screen, screen_prev)) {
break;
}
}
}
else {
screen = NULL;
}
if (screen && screen_prev != screen) {
/* return to previous state before switching screens */
if (sa && sa->full) {
ED_screen_full_restore(C, sa); /* may free 'screen_prev' */
}
ED_screen_set(C, screen);
if (ED_workspace_layout_cycle(workspace, delta, C)) {
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
}
@@ -3297,7 +3257,7 @@ static int header_toggle_menus_exec(bContext *C, wmOperator *UNUSED(op))
sa->flag = sa->flag ^ HEADER_NO_PULLDOWN;
ED_area_tag_redraw(sa);
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
@@ -3594,7 +3554,9 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
ED_update_for_newframe(bmain, scene, 1);
for (window = wm->windows.first; window; window = window->next) {
for (sa = window->screen->areabase.first; sa; sa = sa->next) {
const bScreen *win_screen = WM_window_get_active_screen(window);
for (sa = win_screen->areabase.first; sa; sa = sa->next) {
ARegion *ar;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
bool redraw = false;
@@ -3668,11 +3630,11 @@ static void SCREEN_OT_animation_step(wmOperatorType *ot)
/* find window that owns the animation timer */
bScreen *ED_screen_animation_playing(const wmWindowManager *wm)
{
wmWindow *win;
for (wmWindow *win = wm->windows.first; win; win = win->next) {
bScreen *screen = WM_window_get_active_screen(win);
for (win = wm->windows.first; win; win = win->next) {
if (win->screen->animtimer || win->screen->scrubbing) {
return win->screen;
if (screen->animtimer || screen->scrubbing) {
return screen;
}
}
@@ -3681,11 +3643,11 @@ bScreen *ED_screen_animation_playing(const wmWindowManager *wm)
bScreen *ED_screen_animation_no_scrub(const wmWindowManager *wm)
{
wmWindow *win;
for (wmWindow *win = wm->windows.first; win; win = win->next) {
bScreen *screen = WM_window_get_active_screen(win);
for (win = wm->windows.first; win; win = win->next) {
if (win->screen->animtimer) {
return win->screen;
if (screen->animtimer) {
return screen;
}
}
@@ -3919,11 +3881,13 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot)
static int screen_new_exec(bContext *C, wmOperator *UNUSED(op))
{
wmWindow *win = CTX_wm_window(C);
bScreen *sc = CTX_wm_screen(C);
sc = ED_screen_duplicate(win, sc);
WM_event_add_notifier(C, NC_SCREEN | ND_SCREENBROWSE, sc);
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
WorkSpaceLayout *layout_old = BKE_workspace_active_layout_get(win->workspace_hook);
WorkSpaceLayout *layout_new;
layout_new = ED_workspace_layout_duplicate(workspace, layout_old, win);
WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTBROWSE, layout_new);
return OPERATOR_FINISHED;
}
@@ -3944,9 +3908,11 @@ static void SCREEN_OT_new(wmOperatorType *ot)
static int screen_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
bScreen *sc = CTX_wm_screen(C);
WM_event_add_notifier(C, NC_SCREEN | ND_SCREENDELETE, sc);
WorkSpace *workspace = CTX_wm_workspace(C);
WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, sc);
WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTDELETE, layout);
return OPERATOR_FINISHED;
}
@@ -3961,95 +3927,6 @@ static void SCREEN_OT_delete(wmOperatorType *ot)
ot->exec = screen_delete_exec;
}
/********************* new scene operator *********************/
static int scene_new_exec(bContext *C, wmOperator *op)
{
Scene *newscene, *scene = CTX_data_scene(C);
Main *bmain = CTX_data_main(C);
int type = RNA_enum_get(op->ptr, "type");
if (type == SCE_COPY_NEW) {
newscene = BKE_scene_add(bmain, DATA_("Scene"));
}
else { /* different kinds of copying */
newscene = BKE_scene_copy(bmain, scene, type);
/* these can't be handled in blenkernel currently, so do them here */
if (type == SCE_COPY_LINK_DATA) {
ED_object_single_users(bmain, newscene, false, true);
}
else if (type == SCE_COPY_FULL) {
ED_editors_flush_edits(C, false);
ED_object_single_users(bmain, newscene, true, true);
}
}
ED_screen_set_scene(C, CTX_wm_screen(C), newscene);
WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, newscene);
return OPERATOR_FINISHED;
}
static void SCENE_OT_new(wmOperatorType *ot)
{
static EnumPropertyItem type_items[] = {
{SCE_COPY_NEW, "NEW", 0, "New", "Add new scene"},
{SCE_COPY_EMPTY, "EMPTY", 0, "Copy Settings", "Make a copy without any objects"},
{SCE_COPY_LINK_OB, "LINK_OBJECTS", 0, "Link Objects", "Link to the objects from the current scene"},
{SCE_COPY_LINK_DATA, "LINK_OBJECT_DATA", 0, "Link Object Data", "Copy objects linked to data from the current scene"},
{SCE_COPY_FULL, "FULL_COPY", 0, "Full Copy", "Make a full copy of the current scene"},
{0, NULL, 0, NULL, NULL}};
/* identifiers */
ot->name = "New Scene";
ot->description = "Add new scene by type";
ot->idname = "SCENE_OT_new";
/* api callbacks */
ot->exec = scene_new_exec;
ot->invoke = WM_menu_invoke;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
}
/********************* delete scene operator *********************/
static int scene_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
if (ED_screen_delete_scene(C, scene) == false) {
return OPERATOR_CANCELLED;
}
if (G.debug & G_DEBUG)
printf("scene delete %p\n", scene);
WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene);
return OPERATOR_FINISHED;
}
static void SCENE_OT_delete(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Delete Scene";
ot->description = "Delete active scene";
ot->idname = "SCENE_OT_delete";
/* api callbacks */
ot->exec = scene_delete_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ***************** region alpha blending ***************** */
/* implementation note: a disappearing region needs at least 1 last draw with 100% backbuffer
@@ -4321,13 +4198,11 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(SCREEN_OT_animation_step);
WM_operatortype_append(SCREEN_OT_animation_play);
WM_operatortype_append(SCREEN_OT_animation_cancel);
/* new/delete */
WM_operatortype_append(SCREEN_OT_new);
WM_operatortype_append(SCREEN_OT_delete);
WM_operatortype_append(SCENE_OT_new);
WM_operatortype_append(SCENE_OT_delete);
/* tools shared by more space types */
WM_operatortype_append(ED_OT_undo);
WM_operatortype_append(ED_OT_undo_push);

View File

@@ -0,0 +1,426 @@
/*
* ***** 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/editors/screen/workspace_edit.c
* \ingroup edscr
*/
#include <stdlib.h>
#include <string.h>
#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BKE_appdir.h"
#include "BKE_blendfile.h"
#include "BKE_context.h"
#include "BKE_idcode.h"
#include "BKE_main.h"
#include "BKE_library.h"
#include "BKE_report.h"
#include "BKE_screen.h"
#include "BKE_workspace.h"
#include "BLO_readfile.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_workspace_types.h"
#include "ED_object.h"
#include "ED_screen.h"
#include "RNA_access.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "WM_api.h"
#include "WM_types.h"
#include "screen_intern.h"
/** \name Workspace API
*
* \brief API for managing workspaces and their data.
* \{ */
WorkSpace *ED_workspace_add(
Main *bmain, const char *name, SceneLayer *act_render_layer)
{
WorkSpace *workspace = BKE_workspace_add(bmain, name);
#ifdef USE_WORKSPACE_MODE
BKE_workspace_object_mode_set(workspace, OB_MODE_OBJECT);
#endif
BKE_workspace_render_layer_set(workspace, act_render_layer);
return workspace;
}
#ifdef USE_WORKSPACE_MODE
/**
* 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_mode(
const WorkSpace *workspace_old, const WorkSpace *workspace_new,
bContext *C, Object *ob_act, ReportList *reports)
{
ObjectMode mode_old = BKE_workspace_object_mode_get(workspace_old);
ObjectMode mode_new = BKE_workspace_object_mode_get(workspace_new);
if (mode_old != mode_new) {
ED_object_mode_compat_set(C, ob_act, mode_new, reports);
ED_object_toggle_modes(C, mode_new);
}
}
#endif
static void workspace_change_update_render_layer(
WorkSpace *workspace_new, const WorkSpace *workspace_old)
{
if (!BKE_workspace_render_layer_get(workspace_new)) {
BKE_workspace_render_layer_set(workspace_new, BKE_workspace_render_layer_get(workspace_old));
}
}
static void workspace_change_update(
WorkSpace *workspace_new, const WorkSpace *workspace_old,
bContext *C, wmWindowManager *wm)
{
/* needs to be done before changing mode! (to ensure right context) */
workspace_change_update_render_layer(workspace_new, workspace_old);
#ifdef USE_WORKSPACE_MODE
workspace_change_update_mode(workspace_old, workspace_new, C, CTX_data_active_object(C), &wm->reports);
#else
UNUSED_VARS(C, wm);
#endif
}
static bool workspace_change_find_new_layout_cb(const WorkSpaceLayout *layout, void *UNUSED(arg))
{
/* return false to stop the iterator if we've found a layout that can be activated */
return workspace_layout_set_poll(layout) ? false : true;
}
static WorkSpaceLayout *workspace_change_get_new_layout(
WorkSpace *workspace_new, wmWindow *win)
{
/* ED_workspace_duplicate may have stored a layout to activate once the workspace gets activated. */
WorkSpaceLayout *layout_new;
bScreen *screen_new;
if (win->workspace_hook->temp_workspace_store) {
layout_new = win->workspace_hook->temp_layout_store;
}
else {
layout_new = BKE_workspace_hook_layout_for_workspace_get(win->workspace_hook, workspace_new);
if (!layout_new) {
layout_new = BKE_workspace_layouts_get(workspace_new)->first;
}
}
screen_new = BKE_workspace_layout_screen_get(layout_new);
if (screen_new->winid) {
/* screen is already used, try to find a free one */
WorkSpaceLayout *layout_temp = BKE_workspace_layout_iter_circular(
workspace_new, layout_new, workspace_change_find_new_layout_cb,
NULL, false);
if (!layout_temp) {
/* fallback solution: duplicate layout */
layout_temp = ED_workspace_layout_duplicate(workspace_new, layout_new, win);
}
layout_new = layout_temp;
}
return layout_new;
}
/**
* \brief Change the active workspace.
*
* Operator call, WM + Window + screen already existed before
* Pretty similar to #ED_screen_change since changing workspace also changes screen.
*
* \warning Do NOT call in area/region queues!
* \returns if workspace changing was successful.
*/
bool ED_workspace_change(
WorkSpace *workspace_new, bContext *C, wmWindowManager *wm, wmWindow *win)
{
Main *bmain = CTX_data_main(C);
WorkSpace *workspace_old = WM_window_get_active_workspace(win);
WorkSpaceLayout *layout_new = workspace_change_get_new_layout(workspace_new, win);
bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
bScreen *screen_old = BKE_workspace_active_screen_get(win->workspace_hook);
win->workspace_hook->temp_layout_store = NULL;
if (workspace_old == workspace_new) {
/* Could also return true, everything that needs to be done was done (nothing :P), but nothing changed */
return false;
}
screen_new = screen_change_prepare(screen_old, screen_new, bmain, C, win);
BLI_assert(BKE_workspace_layout_screen_get(layout_new) == screen_new);
if (screen_new) {
WM_window_set_active_layout(win, workspace_new, layout_new);
WM_window_set_active_workspace(win, workspace_new);
/* update screen *after* changing workspace - which also causes the actual screen change */
screen_changed_update(C, win, screen_new);
workspace_change_update(workspace_new, workspace_old, C, wm);
BLI_assert(BKE_workspace_render_layer_get(workspace_new) != NULL);
BLI_assert(CTX_wm_workspace(C) == workspace_new);
return true;
}
return false;
}
/**
* Duplicate a workspace including its layouts. Does not activate the workspace, but
* it stores the screen-layout to be activated (BKE_workspace_temp_layout_store)
*/
WorkSpace *ED_workspace_duplicate(
WorkSpace *workspace_old, Main *bmain, wmWindow *win)
{
WorkSpaceLayout *layout_active_old = BKE_workspace_active_layout_get(win->workspace_hook);
ListBase *layouts_old = BKE_workspace_layouts_get(workspace_old);
WorkSpace *workspace_new = ED_workspace_add(
bmain, workspace_old->id.name + 2,
BKE_workspace_render_layer_get(workspace_old));
#ifdef USE_WORKSPACE_MODE
BKE_workspace_object_mode_set(workspace_new, BKE_workspace_object_mode_get(workspace_old));
#endif
for (WorkSpaceLayout *layout_old = layouts_old->first; layout_old; layout_old = layout_old->next) {
WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(workspace_new, layout_old, win);
if (layout_active_old == layout_old) {
win->workspace_hook->temp_layout_store = layout_new;
}
}
return workspace_new;
}
/**
* \return if succeeded.
*/
bool ED_workspace_delete(
WorkSpace *workspace, Main *bmain, bContext *C, wmWindowManager *wm, wmWindow *win)
{
ID *workspace_id = (ID *)workspace;
if (BLI_listbase_is_single(&bmain->workspaces)) {
return false;
}
if (WM_window_get_active_workspace(win) == workspace) {
WorkSpace *prev = workspace_id->prev;
WorkSpace *next = workspace_id->next;
ED_workspace_change((prev != NULL) ? prev : next, C, wm, win);
}
BKE_libblock_free(bmain, workspace_id);
return true;
}
/**
* Some editor data may need to be synced with scene data (3D View camera and layers).
* This function ensures data is synced for editors in active layout of \a workspace.
*/
void ED_workspace_scene_data_sync(
WorkSpaceInstanceHook *hook, Scene *scene)
{
bScreen *screen = BKE_workspace_active_screen_get(hook);
BKE_screen_view3d_scene_sync(screen, scene);
}
/** \} Workspace API */
/** \name Workspace Operators
*
* \{ */
static int workspace_new_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
WorkSpace *workspace = ED_workspace_duplicate(WM_window_get_active_workspace(win), bmain, win);
WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, workspace);
return OPERATOR_FINISHED;
}
static void WORKSPACE_OT_workspace_duplicate(wmOperatorType *ot)
{
/* identifiers */
ot->name = "New Workspace";
ot->description = "Add a new workspace";
ot->idname = "WORKSPACE_OT_workspace_duplicate";
/* api callbacks */
ot->exec = workspace_new_exec;
ot->poll = WM_operator_winactive;
}
static int workspace_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
ED_workspace_delete(WM_window_get_active_workspace(win), bmain, C, wm, win);
return OPERATOR_FINISHED;
}
static void WORKSPACE_OT_workspace_delete(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Delete Workspace";
ot->description = "Delete the active workspace";
ot->idname = "WORKSPACE_OT_workspace_delete";
/* api callbacks */
ot->exec = workspace_delete_exec;
}
static void workspace_config_file_path_from_folder_id(
const Main *bmain, int folder_id, char *r_path)
{
const char *app_template = U.app_template[0] ? U.app_template : NULL;
const char * const cfgdir = BKE_appdir_folder_id(folder_id, app_template);
if (cfgdir) {
BLI_make_file_string(bmain->name, r_path, cfgdir, BLENDER_WORKSPACES_FILE);
}
else {
r_path[0] = '\0';
}
}
ATTR_NONNULL(1)
static WorkspaceConfigFileData *workspace_config_file_read(
const Main *bmain, ReportList *reports)
{
char workspace_config_path[FILE_MAX];
bool has_path = false;
workspace_config_file_path_from_folder_id(bmain, BLENDER_USER_CONFIG, workspace_config_path);
if (BLI_exists(workspace_config_path)) {
has_path = true;
}
else {
workspace_config_file_path_from_folder_id(bmain, BLENDER_DATAFILES, workspace_config_path);
if (BLI_exists(workspace_config_path)) {
has_path = true;
}
}
return has_path ? BKE_blendfile_workspace_config_read(workspace_config_path, reports) : NULL;
}
static void workspace_append_button(
uiLayout *layout, wmOperatorType *ot_append, const WorkSpace *workspace, const Main *from_main)
{
const ID *id = (ID *)workspace;
PointerRNA opptr;
char lib_path[FILE_MAX_LIBEXTRA];
BLI_path_join(
lib_path, sizeof(lib_path), from_main->name, BKE_idcode_to_name(GS(id->name)), NULL);
BLI_assert(STREQ(ot_append->idname, "WM_OT_append"));
opptr = uiItemFullO_ptr(
layout, ot_append, workspace->id.name + 2, ICON_NONE, NULL,
WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&opptr, "directory", lib_path);
RNA_string_set(&opptr, "filename", id->name + 2);
}
ATTR_NONNULL(1, 2)
static void workspace_config_file_append_buttons(
uiLayout *layout, const Main *bmain, ReportList *reports)
{
WorkspaceConfigFileData *workspace_config = workspace_config_file_read(bmain, reports);
if (workspace_config) {
wmOperatorType *ot_append = WM_operatortype_find("WM_OT_append", true);
for (WorkSpace *workspace = workspace_config->workspaces.first; workspace; workspace = workspace->id.next) {
workspace_append_button(layout, ot_append, workspace, workspace_config->main);
}
BKE_blendfile_workspace_config_data_free(workspace_config);
}
}
static int workspace_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
const Main *bmain = CTX_data_main(C);
uiPopupMenu *pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
uiItemO(layout, "Duplicate Current", ICON_NONE, "WORKSPACE_OT_workspace_duplicate");
uiItemS(layout);
workspace_config_file_append_buttons(layout, bmain, op->reports);
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
}
static void WORKSPACE_OT_workspace_add_menu(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Workspace";
ot->description = "Add a new workspace by duplicating the current one or appending one "
"from the user configuration";
ot->idname = "WORKSPACE_OT_workspace_add_menu";
/* api callbacks */
ot->invoke = workspace_add_invoke;
}
void ED_operatortypes_workspace(void)
{
WM_operatortype_append(WORKSPACE_OT_workspace_duplicate);
WM_operatortype_append(WORKSPACE_OT_workspace_delete);
WM_operatortype_append(WORKSPACE_OT_workspace_add_menu);
}
/** \} Workspace Operators */

View File

@@ -0,0 +1,198 @@
/*
* ***** 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/editors/screen/workspace_layout_edit.c
* \ingroup edscr
*/
#include <stdlib.h>
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_screen.h"
#include "BKE_workspace.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "DNA_screen_types.h"
#include "DNA_workspace_types.h"
#include "ED_screen.h"
#include "WM_api.h"
#include "screen_intern.h"
/**
* Empty screen, with 1 dummy area without spacedata. Uses window size.
*/
WorkSpaceLayout *ED_workspace_layout_add(
WorkSpace *workspace,
wmWindow *win,
const char *name)
{
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
bScreen *screen = screen_add(name, winsize_x, winsize_y);
WorkSpaceLayout *layout = BKE_workspace_layout_add(workspace, screen, name);
return layout;
}
WorkSpaceLayout *ED_workspace_layout_duplicate(
WorkSpace *workspace, const WorkSpaceLayout *layout_old,
wmWindow *win)
{
bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old);
const char *name = BKE_workspace_layout_name_get(layout_old);
bScreen *screen_new;
WorkSpaceLayout *layout_new;
if (BKE_screen_is_fullscreen_area(screen_old)) {
return NULL; /* XXX handle this case! */
}
layout_new = ED_workspace_layout_add(workspace, win, name);
screen_new = BKE_workspace_layout_screen_get(layout_new);
screen_data_copy(screen_new, screen_old);
return layout_new;
}
static bool workspace_layout_delete_doit(
WorkSpace *workspace, WorkSpaceLayout *layout_old, WorkSpaceLayout *layout_new,
bContext *C)
{
Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
ED_screen_change(C, screen_new);
if (BKE_workspace_active_layout_get(win->workspace_hook) != layout_old) {
BKE_workspace_layout_remove(bmain, workspace, layout_old);
return true;
}
return false;
}
bool workspace_layout_set_poll(const WorkSpaceLayout *layout)
{
const bScreen *screen = BKE_workspace_layout_screen_get(layout);
return ((BKE_screen_is_used(screen) == false) &&
/* in typical usage temp screens should have a nonzero winid
* (all temp screens should be used, or closed & freed). */
(screen->temp == false) &&
(BKE_screen_is_fullscreen_area(screen) == false) &&
(screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT)));
}
static WorkSpaceLayout *workspace_layout_delete_find_new(const WorkSpaceLayout *layout_old)
{
for (WorkSpaceLayout *layout_new = layout_old->prev; layout_new; layout_new = layout_new->next) {
if (workspace_layout_set_poll(layout_new)) {
return layout_new;
}
}
for (WorkSpaceLayout *layout_new = layout_old->next; layout_new; layout_new = layout_new->next) {
if (workspace_layout_set_poll(layout_new)) {
return layout_new;
}
}
return NULL;
}
/**
* \warning Only call outside of area/region loops!
* \return true if succeeded.
*/
bool ED_workspace_layout_delete(
WorkSpace *workspace, WorkSpaceLayout *layout_old,
bContext *C)
{
const bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old);
WorkSpaceLayout *layout_new;
BLI_assert(BLI_findindex(BKE_workspace_layouts_get(workspace), layout_old) != -1);
/* don't allow deleting temp fullscreens for now */
if (BKE_screen_is_fullscreen_area(screen_old)) {
return false;
}
/* A layout/screen can only be in use by one window at a time, so as
* long as we are able to find a layout/screen that is unused, we
* can safely assume ours is not in use anywhere an delete it. */
layout_new = workspace_layout_delete_find_new(layout_old);
if (layout_new) {
return workspace_layout_delete_doit(workspace, layout_old, layout_new, C);
}
return false;
}
static bool workspace_layout_cycle_iter_cb(const WorkSpaceLayout *layout, void *UNUSED(arg))
{
/* return false to stop iterator when we have found a layout to activate */
return !workspace_layout_set_poll(layout);
}
bool ED_workspace_layout_cycle(
WorkSpace *workspace, const short direction, bContext *C)
{
wmWindow *win = CTX_wm_window(C);
WorkSpaceLayout *old_layout = BKE_workspace_active_layout_get(win->workspace_hook);
WorkSpaceLayout *new_layout;
const bScreen *old_screen = BKE_workspace_layout_screen_get(old_layout);
ScrArea *sa = CTX_wm_area(C);
if (old_screen->temp || (sa && sa->full && sa->full->temp)) {
return false;
}
BLI_assert(ELEM(direction, 1, -1));
new_layout = BKE_workspace_layout_iter_circular(workspace, old_layout, workspace_layout_cycle_iter_cb,
NULL, (direction == -1) ? true : false);
if (new_layout && (old_layout != new_layout)) {
bScreen *new_screen = BKE_workspace_layout_screen_get(new_layout);
if (sa && sa->full) {
/* return to previous state before switching screens */
ED_screen_full_restore(C, sa); /* may free screen of old_layout */
}
ED_screen_change(C, new_screen);
return true;
}
return false;
}

View File

@@ -1056,16 +1056,20 @@ static void toggle_paint_cursor(bContext *C, int enable)
void ED_space_image_paint_update(wmWindowManager *wm, Scene *scene)
{
ToolSettings *settings = scene->toolsettings;
wmWindow *win;
ScrArea *sa;
ImagePaintSettings *imapaint = &settings->imapaint;
bool enabled = false;
for (win = wm->windows.first; win; win = win->next)
for (sa = win->screen->areabase.first; sa; sa = sa->next)
if (sa->spacetype == SPACE_IMAGE)
if (((SpaceImage *)sa->spacedata.first)->mode == SI_MODE_PAINT)
for (wmWindow *win = wm->windows.first; win; win = win->next) {
bScreen *screen = WM_window_get_active_screen(win);
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
if (sa->spacetype == SPACE_IMAGE) {
if (((SpaceImage *)sa->spacedata.first)->mode == SI_MODE_PAINT) {
enabled = true;
}
}
}
}
if (enabled) {
BKE_paint_init(scene, ePaintTexture2D, PAINT_CURSOR_TEXTURE_PAINT);

View File

@@ -395,7 +395,11 @@ static void action_main_region_listener(
if (wmn->action == NA_RENAME)
ED_region_tag_redraw(ar);
break;
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER)) {
ED_region_tag_redraw(ar);
}
break;
default:
if (wmn->data == ND_KEYS)
ED_region_tag_redraw(ar);

View File

@@ -55,6 +55,7 @@
#include "ED_paint.h"
#include "ED_physics.h"
#include "ED_render.h"
#include "ED_scene.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_space_api.h"
@@ -99,6 +100,8 @@ void ED_spacetypes_init(void)
// ...
/* register operator types for screen and all spaces */
ED_operatortypes_workspace();
ED_operatortypes_scene();
ED_operatortypes_screen();
ED_operatortypes_anim();
ED_operatortypes_animchannels();

View File

@@ -178,6 +178,20 @@ static void buttons_main_region_draw(const bContext *C, ARegion *ar)
sbuts->mainbo = sbuts->mainb;
}
static void buttons_main_region_listener(
bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn,
const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER)) {
ED_region_tag_redraw(ar);
}
break;
}
}
static void buttons_operatortypes(void)
{
WM_operatortype_append(BUTTONS_OT_toolbox);
@@ -471,6 +485,7 @@ void ED_spacetype_buttons(void)
art->regionid = RGN_TYPE_WINDOW;
art->init = buttons_main_region_init;
art->draw = buttons_main_region_draw;
art->listener = buttons_main_region_listener;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);

View File

@@ -305,15 +305,12 @@ bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r
void ED_clip_update_frame(const Main *mainp, int cfra)
{
wmWindowManager *wm;
wmWindow *win;
/* 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 (wmWindowManager *wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
for (wmWindow *win = wm->windows.first; win; win = win->next) {
bScreen *screen = WM_window_get_active_screen(win);
for (sa = win->screen->areabase.first; sa; sa = sa->next) {
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
if (sa->spacetype == SPACE_CLIP) {
SpaceClip *sc = sa->spacedata.first;

View File

@@ -26,6 +26,7 @@
#include "BLI_rect.h"
#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLO_readfile.h"

View File

@@ -215,7 +215,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS | FILTER_ID_LT | FILTER_ID_MA |
FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB |
FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO |
FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF;
FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS;
if (U.uiflag & USER_HIDE_DOT) {
params->flag |= FILE_HIDE_DOT;

View File

@@ -461,6 +461,11 @@ static void graph_region_listener(
if (wmn->action == NA_RENAME)
ED_region_tag_redraw(ar);
break;
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER)) {
ED_region_tag_redraw(ar);
}
break;
default:
if (wmn->data == ND_KEYS)
ED_region_tag_redraw(ar);

View File

@@ -443,7 +443,6 @@ static void image_refresh(const bContext *C, ScrArea *sa)
static void image_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, const Scene *scene)
{
SceneLayer *sl = BKE_scene_layer_context_active(scene);
SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
/* context changes */
@@ -536,6 +535,7 @@ static void image_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, co
case ND_TRANSFORM:
case ND_MODIFIER:
{
SceneLayer *sl = BKE_scene_layer_context_active(scene);
Object *ob = OBACT_NEW;
if (ob && (ob == wmn->reference) && (ob->mode & OB_MODE_EDIT)) {
if (sima->lock && (sima->flag & SI_DRAWSHADOW)) {
@@ -828,6 +828,11 @@ static void image_main_region_listener(
ED_region_tag_redraw(ar);
}
break;
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER)) {
ED_region_tag_redraw(ar);
}
break;
}
}

View File

@@ -260,8 +260,9 @@ static void info_header_listener(
/* context changes */
switch (wmn->category) {
case NC_SCREEN:
if (ELEM(wmn->data, ND_SCREENCAST, ND_ANIMPLAY))
if (ELEM(wmn->data, ND_LAYER, ND_SCREENCAST, ND_ANIMPLAY)) {
ED_region_tag_redraw(ar);
}
break;
case NC_WM:
if (wmn->data == ND_JOB)

View File

@@ -428,6 +428,11 @@ static void nla_main_region_listener(
if (wmn->action == NA_RENAME)
ED_region_tag_redraw(ar);
break;
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER)) {
ED_region_tag_redraw(ar);
}
break;
default:
if (wmn->data == ND_KEYS)
ED_region_tag_redraw(ar);

View File

@@ -123,7 +123,7 @@ static int compo_get_recalc_flags(const bContext *C)
int recalc_flags = 0;
for (win = wm->windows.first; win; win = win->next) {
bScreen *sc = win->screen;
const bScreen *sc = WM_window_get_active_screen(win);
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {

View File

@@ -766,12 +766,13 @@ static void node_region_listener(
}
break;
case NC_SCREEN:
if (wmn->data == ND_SCREENSET || wmn->action == NA_EDITED) {
if (wmn->data == ND_LAYOUTSET || wmn->action == NA_EDITED) {
WM_manipulatormap_tag_refresh(mmap);
}
switch (wmn->data) {
case ND_SCREENCAST:
case ND_ANIMPLAY:
case ND_LAYER:
ED_region_tag_redraw(ar);
break;
}

View File

@@ -109,7 +109,7 @@ typedef struct TreeElement {
#define TREESTORE_ID_TYPE(_id) \
(ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_NT, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \
ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS) || \
ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF, ID_PAL)) /* Only in 'blendfile' mode ... :/ */
ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF, ID_PAL, ID_WS)) /* Only in 'blendfile' mode ... :/ */
/* TreeElement->flag */
enum {

View File

@@ -160,7 +160,7 @@ static eOLDrawState tree_element_set_active_object(
sce = (Scene *)outliner_search_back(soops, te, ID_SCE);
if (sce && scene != sce) {
ED_screen_set_scene(C, CTX_wm_screen(C), sce);
WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce);
scene = sce;
}
@@ -392,7 +392,7 @@ static eOLDrawState tree_element_active_world(
if (set != OL_SETSEL_NONE) {
/* make new scene active */
if (sce && scene != sce) {
ED_screen_set_scene(C, CTX_wm_screen(C), sce);
WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce);
}
}
@@ -891,7 +891,7 @@ static void outliner_item_activate(
/* editmode? */
if (te->idcode == ID_SCE) {
if (scene != (Scene *)tselem->id) {
ED_screen_set_scene(C, CTX_wm_screen(C), (Scene *)tselem->id);
WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), (Scene *)tselem->id);
}
}
else if (te->idcode == ID_GR) {

View File

@@ -67,6 +67,7 @@
#include "ED_armature.h"
#include "ED_object.h"
#include "ED_scene.h"
#include "ED_screen.h"
#include "ED_sequencer.h"
#include "ED_util.h"
@@ -310,7 +311,7 @@ static bool scene_cb(bContext *C, eOutliner_PropSceneOps event, TreeElement *UNU
Scene *scene = (Scene *)tselem->id;
if (event == OL_SCENE_OP_DELETE) {
if (ED_screen_delete_scene(C, scene)) {
if (ED_scene_delete(C, CTX_data_main(C), CTX_wm_window(C), scene)) {
WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene);
}
else {
@@ -571,7 +572,7 @@ void outliner_do_object_operation_ex(
// when objects selected in other scenes... dunno if that should be allowed
Scene *scene_owner = (Scene *)outliner_search_back(soops, te, ID_SCE);
if (scene_owner && scene_act != scene_owner) {
ED_screen_set_scene(C, CTX_wm_screen(C), scene_owner);
WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), scene_owner);
}
/* important to use 'scene_owner' not scene_act else deleting objects can crash.
* only use 'scene_act' when 'scene_owner' is NULL, which can happen when the
@@ -994,6 +995,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
wmWindow *win = CTX_wm_window(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
int event;
const char *str = NULL;
@@ -1008,7 +1010,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
Scene *sce = scene; // to be able to delete, scenes are set...
outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_select_cb);
if (scene != sce) {
ED_screen_set_scene(C, CTX_wm_screen(C), sce);
WM_window_change_active_scene(bmain, C, win, sce);
}
str = "Select Objects";
@@ -1018,8 +1020,8 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
Scene *sce = scene; // to be able to delete, scenes are set...
outliner_do_object_operation_ex(C, op->reports, scene, soops, &soops->tree, object_select_hierarchy_cb, false);
if (scene != sce) {
ED_screen_set_scene(C, CTX_wm_screen(C), sce);
}
WM_window_change_active_scene(bmain, C, win, sce);
}
str = "Select Object Hierarchy";
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}

View File

@@ -403,6 +403,11 @@ static void outliner_main_region_listener(
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED))
ED_region_tag_redraw(ar);
break;
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER)) {
ED_region_tag_redraw(ar);
}
break;
}
}

View File

@@ -640,6 +640,11 @@ static void time_main_region_listener(
if (wmn->data == ND_DATA)
ED_region_tag_redraw(ar);
break;
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER)) {
ED_region_tag_redraw(ar);
}
break;
}
}

View File

@@ -53,6 +53,7 @@
#include "BKE_object.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_workspace.h"
#include "ED_space_api.h"
#include "ED_screen.h"
@@ -804,7 +805,6 @@ static void *view3d_main_region_duplicate(void *poin)
static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, const Scene *scene)
{
wmWindow *win = wmn->wm->winactive;
ScrArea *sa;
unsigned int lay_used = 0;
BaseLegacy *base;
@@ -820,7 +820,8 @@ static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, const Scene
base = base->next;
}
for (sa = win->screen->areabase.first; sa; sa = sa->next) {
const bScreen *screen = WM_window_get_active_screen(win);
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
if (sa->spacetype == SPACE_VIEW3D) {
if (BLI_findindex(&sa->regionbase, ar) != -1) {
View3D *v3d = sa->spacedata.first;
@@ -865,18 +866,24 @@ static void view3d_main_region_listener(
break;
case NC_SCENE:
switch (wmn->data) {
case ND_SCENEBROWSE:
case ND_LAYER_CONTENT:
if (wmn->reference)
view3d_recalc_used_layers(ar, wmn, wmn->reference);
ED_region_tag_redraw(ar);
WM_manipulatormap_tag_refresh(mmap);
break;
case ND_LAYER:
if (wmn->reference) {
BKE_screen_view3d_sync(v3d, wmn->reference);
}
ED_region_tag_redraw(ar);
break;
case ND_FRAME:
case ND_TRANSFORM:
case ND_OB_ACTIVE:
case ND_OB_SELECT:
case ND_OB_VISIBLE:
case ND_LAYER:
case ND_RENDER_OPTIONS:
case ND_MARKERS:
case ND_MODE:
@@ -1056,18 +1063,15 @@ static void view3d_main_region_listener(
case ND_SKETCH:
ED_region_tag_redraw(ar);
break;
case ND_SCREENBROWSE:
case ND_SCREENDELETE:
case ND_SCREENSET:
/* screen was changed, need to update used layers due to NC_SCENE|ND_LAYER_CONTENT */
/* updates used layers only for View3D in active screen */
if (wmn->reference) {
bScreen *sc_ref = wmn->reference;
view3d_recalc_used_layers(ar, wmn, sc_ref->scene);
}
case ND_LAYOUTBROWSE:
case ND_LAYOUTDELETE:
case ND_LAYOUTSET:
WM_manipulatormap_tag_refresh(mmap);
ED_region_tag_redraw(ar);
break;
case ND_LAYER:
ED_region_tag_redraw(ar);
break;
}
break;
@@ -1082,7 +1086,7 @@ static void view3d_main_region_listener(
/* concept is to retrieve cursor type context-less */
static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
{
Scene *scene = win->screen->scene;
const Scene *scene = WM_window_get_active_scene(win);
if (scene->obedit) {
WM_cursor_set(win, CURSOR_EDIT);

View File

@@ -1473,9 +1473,8 @@ CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d)
}
/* goes over all modes and view3d settings */
CustomDataMask ED_view3d_screen_datamask(const bScreen *screen)
CustomDataMask ED_view3d_screen_datamask(const Scene *scene, const bScreen *screen)
{
const Scene *scene = screen->scene;
CustomDataMask mask = CD_MASK_BAREMESH;
/* check if we need tfaces & mcols due to view mode */
@@ -1767,14 +1766,14 @@ void ED_scene_draw_fps(Scene *scene, const rcti *rect)
#endif
}
static bool view3d_main_region_do_render_draw(Scene *scene)
static bool view3d_main_region_do_render_draw(const Scene *scene)
{
RenderEngineType *type = RE_engines_find(scene->r.engine);
return (type && type->view_update && type->render_to_view);
}
bool ED_view3d_calc_render_border(Scene *scene, View3D *v3d, ARegion *ar, rcti *rect)
bool ED_view3d_calc_render_border(const Scene *scene, View3D *v3d, ARegion *ar, rcti *rect)
{
RegionView3D *rv3d = ar->regiondata;
bool use_border;

View File

@@ -71,11 +71,10 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event);
/* XXX quickly ported across */
static void handle_view3d_lock(bContext *C)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = CTX_wm_view3d(C);
if (v3d != NULL && sa != NULL) {
if (v3d->localvd == NULL && v3d->scenelock && sa->spacetype == SPACE_VIEW3D) {
/* copy to scene */
@@ -83,10 +82,6 @@ static void handle_view3d_lock(bContext *C)
scene->layact = v3d->layact;
scene->camera = v3d->camera;
/* not through notifier, listener don't have context
* and non-open screens or spaces need to be updated too */
BKE_screen_view3d_main_sync(&bmain->screen, scene);
/* notifiers for scene update */
WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
}
@@ -292,8 +287,8 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
bGPdata *gpd = CTX_data_gpencil_data(C);
uiBlock *block;
uiLayout *row;
bool is_paint = false;
int modeselect;
bool is_paint = ob && !(gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) &&
ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT);
RNA_pointer_create(&screen->id, &RNA_SpaceView3D, v3d, &v3dptr);
RNA_pointer_create(&scene->id, &RNA_ToolSettings, ts, &toolsptr);
@@ -304,36 +299,6 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
/* other buttons: */
UI_block_emboss_set(block, UI_EMBOSS);
/* mode */
if ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
modeselect = OB_MODE_GPENCIL;
}
else if (ob) {
modeselect = ob->mode;
is_paint = ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT);
}
else {
modeselect = OB_MODE_OBJECT;
}
row = uiLayoutRow(layout, false);
{
EnumPropertyItem *item = rna_enum_object_mode_items;
const char *name = "";
int icon = ICON_OBJECT_DATAMODE;
while (item->identifier) {
if (item->value == modeselect && item->identifier[0]) {
name = IFACE_(item->name);
icon = item->icon;
break;
}
item++;
}
uiItemMenuEnumO(row, C, "OBJECT_OT_mode_set", "mode", name, icon);
}
row = uiLayoutRow(layout, true);
uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);

View File

@@ -1358,19 +1358,21 @@ static void game_set_commmandline_options(GameData *gm)
static int game_engine_poll(bContext *C)
{
bScreen *screen;
const wmWindow *win = CTX_wm_window(C);
const Scene *scene = WM_window_get_active_scene(win);
/* we need a context and area to launch BGE
* it's a temporary solution to avoid crash at load time
* if we try to auto run the BGE. Ideally we want the
* context to be set as soon as we load the file. */
if (CTX_wm_window(C) == NULL) return 0;
if ((screen = CTX_wm_screen(C)) == NULL) return 0;
if (win == NULL) return 0;
if (CTX_wm_screen(C) == NULL) return 0;
if (CTX_data_mode_enum(C) != CTX_MODE_OBJECT)
return 0;
if (!BKE_scene_uses_blender_game(screen->scene))
if (!BKE_scene_uses_blender_game(scene))
return 0;
return 1;

View File

@@ -229,11 +229,11 @@ static int delete_orientation_poll(bContext *C)
if (ED_operator_areaactive(C) == 0)
return 0;
if (v3d) {
selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
}
return selected_index >= 0;
}

View File

@@ -381,8 +381,10 @@ void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target)
void BIF_selectTransformOrientationValue(bContext *C, int orientation)
{
View3D *v3d = CTX_wm_view3d(C);
if (v3d) /* currently using generic poll */
if (v3d) { /* currently using generic poll */
v3d->twmode = orientation;
}
}
int BIF_countTransformOrientation(const bContext *C)

View File

@@ -75,6 +75,7 @@ set(SRC
../include/ED_particle.h
../include/ED_physics.h
../include/ED_render.h
../include/ED_scene.h
../include/ED_screen.h
../include/ED_screen_types.h
../include/ED_sculpt.h

View File

@@ -32,6 +32,7 @@
#include "BLI_endian_switch.h"
#include "BLI_fileops.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h" /* Needed due to import of BLO_readfile.h */
#include "BLO_blend_defs.h"
#include "BLO_readfile.h"

View File

@@ -265,6 +265,7 @@ typedef enum ID_Type {
ID_PAL = MAKE_ID2('P', 'L'), /* Palette */
ID_PC = MAKE_ID2('P', 'C'), /* PaintCurve */
ID_CF = MAKE_ID2('C', 'F'), /* CacheFile */
ID_WS = MAKE_ID2('W', 'S'), /* WorkSpace */
} ID_Type;
/* Only used as 'placeholder' in .blend files for directly linked datablocks. */
@@ -288,7 +289,7 @@ typedef enum ID_Type {
#define ID_REAL_USERS(id) (((ID *)id)->us - ID_FAKE_USERS(id))
#define ID_EXTRA_USERS(id) (((ID *)id)->tag & LIB_TAG_EXTRAUSER ? 1 : 0)
#define ID_CHECK_UNDO(id) ((GS((id)->name) != ID_SCR) && (GS((id)->name) != ID_WM))
#define ID_CHECK_UNDO(id) ((GS((id)->name) != ID_SCR) && (GS((id)->name) != ID_WM) && (GS((id)->name) != ID_WS))
#define ID_BLEND_PATH(_bmain, _id) ((_id)->lib ? (_id)->lib->filepath : (_bmain)->name)
@@ -398,6 +399,7 @@ enum {
FILTER_ID_WO = (1 << 26),
FILTER_ID_PA = (1 << 27),
FILTER_ID_CF = (1 << 28),
FILTER_ID_WS = (1 << 29),
};
/* IMPORTANT: this enum matches the order currently use in set_lisbasepointers,
@@ -435,6 +437,7 @@ enum {
INDEX_ID_OB,
INDEX_ID_LS,
INDEX_ID_SCE,
INDEX_ID_WS,
INDEX_ID_WM,
INDEX_ID_MSK,
INDEX_ID_NULL,

View File

@@ -44,6 +44,12 @@
# endif
#endif
#ifdef __GNUC__
# define DNA_PRIVATE_ATTR __attribute__ ((deprecated))
#else
# define DNA_PRIVATE_ATTR
#endif
/* poison pragma */
#ifdef DNA_DEPRECATED_ALLOW

View File

@@ -32,9 +32,6 @@
#ifndef __DNA_FILEGLOBAL_TYPES_H__
#define __DNA_FILEGLOBAL_TYPES_H__
struct bScreen;
struct Scene;
/**
* FileGlobal stores a part of the current user-interface settings at
* the moment of saving, and the file-specific settings.
@@ -46,6 +43,9 @@ typedef struct FileGlobal {
char pad[6];
struct bScreen *curscreen;
struct Scene *curscene;
struct SceneLayer *cur_render_layer;
void *pad1;
int fileflags;
int globalf;
uint64_t build_commit_timestamp; /* commit timestamp from buildinfo */

View File

@@ -30,6 +30,7 @@
#ifndef __DNA_SCREEN_TYPES_H__
#define __DNA_SCREEN_TYPES_H__
#include "DNA_defs.h"
#include "DNA_listBase.h"
#include "DNA_view2d_types.h"
#include "DNA_vec_types.h"
@@ -52,10 +53,9 @@ typedef struct bScreen {
ListBase edgebase;
ListBase areabase;
ListBase regionbase; /* screen level regions (menus), runtime only */
struct Scene *scene;
struct Scene *newscene; /* temporary when switching */
struct Scene *scene DNA_DEPRECATED;
short winid; /* winid from WM, starts with 1 */
short redraws_flag; /* user-setting for which editors get redrawn during anim playback (used to be time->redraws) */

View File

@@ -601,7 +601,7 @@ typedef enum eUserPref_Flag {
/* USER_AUTOGRABGRID = (1 << 1), deprecated */
/* USER_AUTOROTGRID = (1 << 2), deprecated */
/* USER_AUTOSIZEGRID = (1 << 3), deprecated */
USER_SCENEGLOBAL = (1 << 4),
/* USER_SCENEGLOBAL = (1 << 4), deprecated */
USER_TRACKBALL = (1 << 5),
/* USER_DUPLILINK = (1 << 6), deprecated */
/* USER_FSCOLLUM = (1 << 7), deprecated */

View File

@@ -177,9 +177,13 @@ typedef struct wmWindow {
void *ghostwin; /* don't want to include ghost.h stuff */
struct bScreen *screen; /* active screen */
struct bScreen *newscreen; /* temporary when switching */
char screenname[64]; /* MAX_ID_NAME for matching window with active screen after file read */
struct Scene *scene; /* The scene displayed in this window. */
struct Scene *new_scene; /* temporary when switching */
struct WorkSpaceInstanceHook *workspace_hook;
struct bScreen *screen DNA_DEPRECATED;
char screenname[64]; /* MAX_ID_NAME for matching window with active screen after file read */
short posx, posy, sizex, sizey; /* window coords */
short windowstate; /* borderless, full */

View File

@@ -0,0 +1,132 @@
/*
* ***** 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 DNA_workspace_types.h
* \ingroup DNA
*
* Use API in BKE_workspace.h!
* Struct members marked with DNA_PRIVATE_WORKSPACE will throw a
* warning saying it's deprecated when used outside of workspace.c.
*/
#ifndef __DNA_WORKSPACE_TYPES_H__
#define __DNA_WORKSPACE_TYPES_H__
/* Same logic as DNA_DEPRECATED_ALLOW, but throws 'deprecated'
* warnings if DNA_PRIVATE_WORKSPACE_ALLOW is not defined */
#ifdef DNA_PRIVATE_WORKSPACE_ALLOW
/* allow use of private items */
# define DNA_PRIVATE_WORKSPACE
#else
# ifndef DNA_PRIVATE_WORKSPACE
# define DNA_PRIVATE_WORKSPACE DNA_PRIVATE_ATTR
# endif
#endif
#ifdef DNA_PRIVATE_READ_WRITE_ALLOW
# define DNA_PRIVATE_WORKSPACE_READ_WRITE
#else
# ifndef DNA_PRIVATE_WORKSPACE_READ_WRITE
# define DNA_PRIVATE_WORKSPACE_READ_WRITE DNA_PRIVATE_WORKSPACE
# endif
#endif
/**
* \brief Wrapper for bScreen.
*
* bScreens are IDs and thus stored in a main list-base. We also want to store a list-base of them within the
* workspace (so each workspace can have its own set of screen-layouts) which would mess with the next/prev pointers.
* So we use this struct to wrap a bScreen pointer with another pair of next/prev pointers.
*/
typedef struct WorkSpaceLayout {
struct WorkSpaceLayout *next, *prev;
struct bScreen *screen DNA_PRIVATE_WORKSPACE;
/* The name of this layout, we override the RNA name of the screen with this (but not ID name itself) */
char name[64] DNA_PRIVATE_WORKSPACE; /* MAX_NAME */
} WorkSpaceLayout;
typedef struct WorkSpace {
ID id;
ListBase layouts DNA_PRIVATE_WORKSPACE; /* WorkSpaceLayout */
/* Store for each hook (so for each window) which layout has
* been activated the last time this workspace was visible. */
ListBase hook_layout_relations DNA_PRIVATE_WORKSPACE_READ_WRITE; /* WorkSpaceDataRelation */
int object_mode DNA_PRIVATE_WORKSPACE; /* enum ObjectMode */
int pad;
struct SceneLayer *render_layer DNA_PRIVATE_WORKSPACE;
} WorkSpace;
/* internal struct, but exported for read/write */
#if defined(DNA_PRIVATE_READ_WRITE_ALLOW) || defined(DNA_PRIVATE_WORKSPACE_ALLOW)
/**
* Generic (and simple/primitive) struct for storing a history of assignments/relations
* of workspace data to non-workspace data in a listbase inside the workspace.
*
* Using this we can restore the old state of a workspace if the user switches back to it.
*
* Usage
* =====
* When activating a workspace, it should activate the screen-layout that was active in that
* workspace before *in this window*.
* More concretely:
* * There are two windows, win1 and win2.
* * Both show workspace ws1, but both also had workspace ws2 activated at some point before.
* * Last time ws2 was active in win1, screen-layout sl1 was activated.
* * Last time ws2 was active in win2, screen-layout sl2 was activated.
* * When changing from ws1 to ws2 in win1, screen-layout sl1 should be activated again.
* * When changing from ws1 to ws2 in win2, screen-layout sl2 should be activated again.
* So that means we have to store the active screen-layout in a per workspace, per window
* relation. This struct is used to store an active screen-layout for each window within the
* workspace.
* To find the screen-layout to activate for this window-workspace combination, simply lookup
* the WorkSpaceDataRelation with the workspace-hook of the window set as parent.
*/
typedef struct WorkSpaceDataRelation {
struct WorkSpaceDataRelation *next, *prev;
/* the data used to identify the relation (e.g. to find screen-layout (= value) from/for a hook) */
void *parent;
/* The value for this parent-data/workspace relation */
void *value;
} WorkSpaceDataRelation;
#endif /* DNA_PRIVATE_WORKSPACE_READ_WRITE */
/**
* Little wrapper to store data that is going to be per window, but comming from the workspace.
* It allows us to keep workspace and window data completely separate.
*/
typedef struct WorkSpaceInstanceHook {
WorkSpace *active DNA_PRIVATE_WORKSPACE;
struct WorkSpaceLayout *act_layout DNA_PRIVATE_WORKSPACE;
/* Needed because we can't change workspaces/layouts in running handler loop, it would break context. */
WorkSpace *temp_workspace_store;
struct WorkSpaceLayout *temp_layout_store;
} WorkSpaceInstanceHook;
#endif /* __DNA_WORKSPACE_TYPES_H__ */

View File

@@ -56,6 +56,9 @@
#include "../blenlib/BLI_sys_types.h" // for intptr_t support
/* Allow includinsg DNA files for specially guarded namespaces */
#define DNA_NAMESPACE
#define SDNA_MAX_FILENAME_LENGTH 255
@@ -132,6 +135,8 @@ static const char *includefiles[] = {
"DNA_linestyle_types.h",
"DNA_cachefile_types.h",
"DNA_layer_types.h",
"DNA_workspace_types.h",
/* see comment above before editing! */
/* empty string to indicate end of includefiles */
@@ -506,6 +511,17 @@ static int preprocess_include(char *maindata, int len)
a -= 13;
cp += 13;
}
else if (strncmp("DNA_PRIVATE_WORKSPACE", cp, 21) == 0) {
/* Check for DNA_PRIVATE_WORKSPACE_READ_WRITE */
if (strncmp("_READ_WRITE", cp + 21, 11) == 0) {
a -= 31;
cp += 31;
}
else {
a -= 20;
cp += 20;
}
}
else {
md[0] = cp[0];
md++;
@@ -1346,4 +1362,6 @@ int main(int argc, char **argv)
#include "DNA_linestyle_types.h"
#include "DNA_cachefile_types.h"
#include "DNA_layer_types.h"
#include "DNA_workspace_types.h"
/* end of list */

View File

@@ -707,6 +707,7 @@ extern StructRNA RNA_WindowManager;
extern StructRNA RNA_WipeSequence;
extern StructRNA RNA_WireframeModifier;
extern StructRNA RNA_WoodTexture;
extern StructRNA RNA_WorkSpace;
extern StructRNA RNA_World;
extern StructRNA RNA_WorldAmbientOcclusion;
extern StructRNA RNA_WorldLighting;

View File

@@ -94,6 +94,7 @@ set(DEFSRC
rna_userdef.c
rna_vfont.c
rna_wm.c
rna_workspace.c
rna_world.c
)

View File

@@ -3364,6 +3364,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_userdef.c", NULL, RNA_def_userdef},
{"rna_vfont.c", "rna_vfont_api.c", RNA_def_vfont},
{"rna_wm.c", "rna_wm_api.c", RNA_def_wm},
{"rna_workspace.c", NULL, RNA_def_workspace},
{"rna_world.c", NULL, RNA_def_world},
{"rna_movieclip.c", NULL, RNA_def_movieclip},
{"rna_tracking.c", NULL, RNA_def_tracking},

Some files were not shown because too many files have changed in this diff Show More