diff options
author | Campbell Barton <ideasman42@gmail.com> | 2015-02-09 21:45:57 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2015-02-09 21:51:05 +0300 |
commit | 31e26bb83bd0a538c76fd8bb6ebce65027dde94c (patch) | |
tree | 7a58e52c4ab98149eab81e6fb9db67d9458a2f7e /source/blender/blenkernel/intern/blender.c | |
parent | 2fe9e3c1f0fd968bb214e13763b58a35f637caa9 (diff) |
Fix T43424: undo changes the active scene
Using different scenes with 2+ windows broke entirely using undo.
Now keep track of the current windows scene in each undo-file,
and ensure the undo-scene is on a visible window when undo is executed,
switching the scene only when its not in a visible window.
Diffstat (limited to 'source/blender/blenkernel/intern/blender.c')
-rw-r--r-- | source/blender/blenkernel/intern/blender.c | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index fb02af1be20..dda790ea700 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -185,6 +185,17 @@ static void clean_paths(Main *main) } } +static bool wm_scene_is_visible(wmWindowManager *wm, Scene *scene) +{ + wmWindow *win; + for (win = wm->windows.first; win; win = win->next) { + if (win->screen->scene == scene) { + return true; + } + } + return false; +} + /* context matching */ /* handle no-ui case */ @@ -228,24 +239,54 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath /* no load screens? */ if (mode != LOAD_UI) { + /* Logic for 'track_undo_scene' is to keep using the scene which the active screen has, + * as long as the scene associated with the undo operation is visible in one of the open windows. + * + * - 'curscreen->scene' - scene the user is currently looking at. + * - 'bfd->curscene' - scene undo-step was created in. + * + * This means users can have 2+ windows open and undo in both without screens switching. + * But if they close one of the screens, + * undo will ensure that the scene being operated on will be activated + * (otherwise we'd be undoing on an off-screen scene which isn't acceptable). + * see: T43424 + */ + bool track_undo_scene; + /* comes from readfile.c */ SWAP(ListBase, G.main->wm, bfd->main->wm); SWAP(ListBase, G.main->screen, bfd->main->screen); SWAP(ListBase, G.main->script, bfd->main->script); - /* we re-use current screen */ curscreen = CTX_wm_screen(C); - /* but use new Scene pointer */ - curscene = bfd->curscene; + + track_undo_scene = (mode == LOAD_UNDO && curscreen && bfd->main->wm.first); + if (track_undo_scene) { + curscene = curscreen->scene; + } + else { + /* but use new Scene pointer */ + curscene = bfd->curscene; + } + if (curscene == NULL) curscene = bfd->main->scene.first; /* empty file, we add a scene to make Blender work */ if (curscene == NULL) curscene = BKE_scene_add(bfd->main, "Empty"); - + /* and we enforce curscene to be in current screen */ if (curscreen) curscreen->scene = curscene; /* can run in bgmode */ /* clear_global will free G.main, here we can still restore pointers */ blo_lib_link_screen_restore(bfd->main, curscreen, curscene); + curscene = curscreen->scene; + + if (track_undo_scene) { + wmWindowManager *wm = bfd->main->wm.first; + if (wm_scene_is_visible(wm, bfd->curscene) == false) { + curscene = bfd->curscene; + curscreen->scene = curscene; + } + } } /* free G.main Main database */ |