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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/CMakeLists.txt3
-rw-r--r--source/blender/editors/animation/anim_markers.c4
-rw-r--r--source/blender/editors/include/ED_scene.h40
-rw-r--r--source/blender/editors/include/ED_screen.h47
-rw-r--r--source/blender/editors/include/ED_view3d.h7
-rw-r--r--source/blender/editors/interface/interface.c11
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c19
-rw-r--r--source/blender/editors/interface/interface_regions.c7
-rw-r--r--source/blender/editors/interface/interface_templates.c4
-rw-r--r--source/blender/editors/interface/interface_utils.c3
-rw-r--r--source/blender/editors/interface/resources.c17
-rw-r--r--source/blender/editors/object/object_add.c4
-rw-r--r--source/blender/editors/object/object_edit.c20
-rw-r--r--source/blender/editors/object/object_select.c8
-rw-r--r--source/blender/editors/render/render_internal.c10
-rw-r--r--source/blender/editors/render/render_update.c4
-rw-r--r--source/blender/editors/render/render_view.c15
-rw-r--r--source/blender/editors/scene/CMakeLists.txt43
-rw-r--r--source/blender/editors/scene/scene_edit.c202
-rw-r--r--source/blender/editors/screen/CMakeLists.txt3
-rw-r--r--source/blender/editors/screen/area.c11
-rw-r--r--source/blender/editors/screen/screen_context.c8
-rw-r--r--source/blender/editors/screen/screen_draw.c9
-rw-r--r--source/blender/editors/screen/screen_edit.c427
-rw-r--r--source/blender/editors/screen/screen_intern.h11
-rw-r--r--source/blender/editors/screen/screen_ops.c229
-rw-r--r--source/blender/editors/screen/workspace_edit.c426
-rw-r--r--source/blender/editors/screen/workspace_layout_edit.c198
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c16
-rw-r--r--source/blender/editors/space_action/space_action.c6
-rw-r--r--source/blender/editors/space_api/spacetypes.c3
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c15
-rw-r--r--source/blender/editors/space_clip/clip_editor.c11
-rw-r--r--source/blender/editors/space_file/file_utils.c1
-rw-r--r--source/blender/editors/space_file/filesel.c2
-rw-r--r--source/blender/editors/space_graph/space_graph.c5
-rw-r--r--source/blender/editors/space_image/space_image.c7
-rw-r--r--source/blender/editors/space_info/space_info.c3
-rw-r--r--source/blender/editors/space_nla/space_nla.c5
-rw-r--r--source/blender/editors/space_node/node_edit.c2
-rw-r--r--source/blender/editors/space_node/space_node.c3
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h2
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c6
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c12
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c5
-rw-r--r--source/blender/editors/space_time/space_time.c5
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c30
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c41
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c10
-rw-r--r--source/blender/editors/transform/transform_ops.c4
-rw-r--r--source/blender/editors/transform/transform_orientations.c4
-rw-r--r--source/blender/editors/util/CMakeLists.txt1
53 files changed, 1398 insertions, 598 deletions
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt
index 1559512d713..f62db3c1ddb 100644
--- a/source/blender/editors/CMakeLists.txt
+++ b/source/blender/editors/CMakeLists.txt
@@ -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)
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 7ec19d12fb6..ef67411a48d 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -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);
diff --git a/source/blender/editors/include/ED_scene.h b/source/blender/editors/include/ED_scene.h
new file mode 100644
index 00000000000..2f67f7befae
--- /dev/null
+++ b/source/blender/editors/include/ED_scene.h
@@ -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__ */
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 1208b1f31b6..dec8bf7d615 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -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);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 02243738d6c..667ca099305 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -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);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 562a2f6e32c..be37ba46f7f 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -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)
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index bad47512d12..858c21dfdda 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -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;
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index ed8c3a50875..fd6d056f7d4 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -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);
}
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 266d8aacae3..dbef5b68a03 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -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) {
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index f383719a747..fd1569ae42e 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -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;
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index e8eda567a4a..09ec08fe265 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -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;
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 177168aa3c3..068caee4e1a 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -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;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index abdbf3afd5a..fe232e37886 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -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
}
}
}
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 4bdd524f110..60c8fa6f28d 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -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);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index d4e9956b189..bdfbac3dba7 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -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;
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index e019bc9f697..ce52b9af4b2 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -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;
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index c4a9af79ec2..e4bae9d78ea 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -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);
diff --git a/source/blender/editors/scene/CMakeLists.txt b/source/blender/editors/scene/CMakeLists.txt
new file mode 100644
index 00000000000..72199ca5c1f
--- /dev/null
+++ b/source/blender/editors/scene/CMakeLists.txt
@@ -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}")
diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c
new file mode 100644
index 00000000000..6956793435c
--- /dev/null
+++ b/source/blender/editors/scene/scene_edit.c
@@ -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);
+}
diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt
index 43e044b613a..02584a4611b 100644
--- a/source/blender/editors/screen/CMakeLists.txt
+++ b/source/blender/editors/screen/CMakeLists.txt
@@ -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
)
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 3b933b0182a..9d3dde06925 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -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;
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index 0448fba78e6..d4e9609904e 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -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;
diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c
index 4e43a7f96e7..52c13871925 100644
--- a/source/blender/editors/screen/screen_draw.c
+++ b/source/blender/editors/screen/screen_draw.c
@@ -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;
}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index d59109a5baa..65b783463a9 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -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;
}
+
+/* -------------------------------------------------------------------- */
+/* 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;
+ }
+ }
+
+ return screen;
+}
+
/**
- * operator call, WM + Window + screen already existed before
- *
- * \warning Do NOT call in area/region queues!
- * \returns success.
+ * \return the screen to activate.
+ * \warning The returned screen may not always equal \a screen_new!
*/
-bool ED_screen_set(bContext *C, bScreen *sc)
+bScreen *screen_change_prepare(bScreen *screen_old, bScreen *screen_new, Main *bmain, bContext *C, wmWindow *win)
{
- 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 (BLI_findindex(&bmain->screen, screen_new) == -1) {
+ return NULL;
}
- 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;
- }
- }
+ if (ELEM(screen_new->state, SCREENMAXIMIZED, SCREENFULL)) {
+ screen_new = screen_fullscreen_find_associated_normal_screen(bmain, screen_new);
}
/* check for valid winid */
- if (sc->winid != 0 && sc->winid != win->winid) {
- return false;
+ if (!(screen_new->winid == 0 || screen_new->winid == win->winid)) {
+ return NULL;
}
-
- if (oldscreen != sc) {
- wmTimer *wt = oldscreen->animtimer;
- ScrArea *sa;
- Scene *oldscene = oldscreen->scene;
+
+ 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);
- return false;
+ 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);
}
-/* only call outside of area/region loops */
-bool ED_screen_delete(bContext *C, bScreen *sc)
+
+/**
+ * \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);
- 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;
- }
+ bScreen *screen_old = CTX_wm_screen(C);
+ bScreen *screen_new = screen_change_prepare(screen_old, sc, bmain, C, win);
- /* 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 */
+ 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);
- 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;
- }
+
+ 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;
+}
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index 49c0869fcfb..4eb68d01df7 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -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__ */
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 69d13beee48..5cd68f5121c 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -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);
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
new file mode 100644
index 00000000000..3782d583003
--- /dev/null
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -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 */
diff --git a/source/blender/editors/screen/workspace_layout_edit.c b/source/blender/editors/screen/workspace_layout_edit.c
new file mode 100644
index 00000000000..e4dd841f833
--- /dev/null
+++ b/source/blender/editors/screen/workspace_layout_edit.c
@@ -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;
+}
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 1b18dd4e41c..64bd866c0db 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -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);
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index e76d83715a2..fca54b282f8 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -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);
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 4d601a31251..3a431eb82df 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -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();
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 47297e84242..299ab7171d6 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -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);
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 59dd755173f..942bc2661c3 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -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;
diff --git a/source/blender/editors/space_file/file_utils.c b/source/blender/editors/space_file/file_utils.c
index c1caf5ae8ac..fc870399696 100644
--- a/source/blender/editors/space_file/file_utils.c
+++ b/source/blender/editors/space_file/file_utils.c
@@ -26,6 +26,7 @@
#include "BLI_rect.h"
#include "BLI_fileops.h"
+#include "BLI_listbase.h"
#include "BLO_readfile.h"
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index c2700233cf5..c03be5782be 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -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;
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 980ee5aeffe..c17b60badae 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -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);
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index baa1dcdffd9..56afdce7bb1 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -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;
}
}
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index ab08b288470..4f042364c63 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -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)
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index a71f2f20a3f..ab7a913ce62 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -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);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 3cb5fd94ea9..8568b0a676d 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -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) {
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 4eeb4d02d8c..665808c500f 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -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;
}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 06b37377535..722bec1fa46 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -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 {
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 931af08c717..400a01a2908 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -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) {
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 0591a8674d3..159a00ae0ed 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -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);
}
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index b632db48caa..346e567dd8d 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -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;
}
}
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index 9a3ae2dcd70..283cd6c0e24 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -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;
}
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 9c55e99b151..1dc9b169714 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -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);
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index bc74475e8cc..a27c5df9128 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -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;
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 6d1393a2905..31677e08207 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -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);
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 93554c374d9..53f343ed071 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -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;
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 2a97384cf7d..a2a5307c707 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -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;
}
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index c9e40865164..2ba640500c7 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -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)
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index c0b30f93939..766f70d025c 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -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