[Bf-blender-cvs] [31e26bb] master: Fix T43424: undo changes the active scene

Campbell Barton noreply at git.blender.org
Mon Feb 9 19:52:24 CET 2015


Commit: 31e26bb83bd0a538c76fd8bb6ebce65027dde94c
Author: Campbell Barton
Date:   Tue Feb 10 05:45:57 2015 +1100
Branches: master
https://developer.blender.org/rB31e26bb83bd0a538c76fd8bb6ebce65027dde94c

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.

===================================================================

M	source/blender/blenkernel/intern/blender.c
M	source/blender/blenloader/intern/writefile.c

===================================================================

diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index fb02af1..dda790e 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 */
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 3eeb30a..e671e10 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -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;




More information about the Bf-blender-cvs mailing list