forked from bartvdbraak/blender
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.
This commit is contained in:
parent
2fe9e3c1f0
commit
31e26bb83b
@ -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,15 +239,36 @@ 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);
|
||||
|
||||
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");
|
||||
@ -246,6 +278,15 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
|
||||
|
||||
/* 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 */
|
||||
|
@ -909,16 +909,39 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
|
||||
write_node_socket_interface(wd, ntree, sock);
|
||||
}
|
||||
|
||||
static void current_screen_compat(Main *mainvar, bScreen **screen)
|
||||
/**
|
||||
* Take care using 'use_active_win', since we wont want the currently active window
|
||||
* to change which scene renders (currently only used for undo).
|
||||
*/
|
||||
static void current_screen_compat(Main *mainvar, bScreen **r_screen, bool use_active_win)
|
||||
{
|
||||
wmWindowManager *wm;
|
||||
wmWindow *window;
|
||||
wmWindow *window = NULL;
|
||||
|
||||
/* find a global current screen in the first open window, to have
|
||||
* a reasonable default for reading in older versions */
|
||||
wm = mainvar->wm.first;
|
||||
window = (wm) ? wm->windows.first : NULL;
|
||||
*screen = (window) ? window->screen : NULL;
|
||||
|
||||
if (wm) {
|
||||
if (use_active_win) {
|
||||
/* write the active window into the file, needed for multi-window undo T43424 */
|
||||
for (window = wm->windows.first; window; window = window->next) {
|
||||
if (window->active) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* fallback */
|
||||
if (window == NULL) {
|
||||
window = wm->windows.first;
|
||||
}
|
||||
}
|
||||
else {
|
||||
window = wm->windows.first;
|
||||
}
|
||||
}
|
||||
|
||||
*r_screen = (window) ? window->screen : NULL;
|
||||
}
|
||||
|
||||
typedef struct RenderInfo {
|
||||
@ -937,7 +960,7 @@ static void write_renderinfo(WriteData *wd, Main *mainvar)
|
||||
RenderInfo data;
|
||||
|
||||
/* XXX in future, handle multiple windows with multiple screens? */
|
||||
current_screen_compat(mainvar, &curscreen);
|
||||
current_screen_compat(mainvar, &curscreen, false);
|
||||
if (curscreen) curscene = curscreen->scene;
|
||||
|
||||
for (sce= mainvar->scene.first; sce; sce= sce->id.next) {
|
||||
@ -3437,6 +3460,7 @@ static void write_linestyles(WriteData *wd, ListBase *idbase)
|
||||
* - for undofile, curscene needs to be saved */
|
||||
static void write_global(WriteData *wd, int fileflags, Main *mainvar)
|
||||
{
|
||||
const bool is_undo = (wd->current != NULL);
|
||||
FileGlobal fg;
|
||||
bScreen *screen;
|
||||
char subvstr[8];
|
||||
@ -3446,7 +3470,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
|
||||
memset(fg.filename, 0, sizeof(fg.filename));
|
||||
memset(fg.build_hash, 0, sizeof(fg.build_hash));
|
||||
|
||||
current_screen_compat(mainvar, &screen);
|
||||
current_screen_compat(mainvar, &screen, is_undo);
|
||||
|
||||
/* XXX still remap G */
|
||||
fg.curscreen= screen;
|
||||
|
Loading…
Reference in New Issue
Block a user