From c43c000109fb0f3197bbe2609e0a24952ccb4eba Mon Sep 17 00:00:00 2001 From: biwa <6475593+biwa@users.noreply.github.com> Date: Sat, 13 Jun 2020 00:30:58 +0200 Subject: [PATCH 1/2] Draw Grid Mode: fixed a crash that happened when having locking slices to grid enabled --- Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs index da4a4300..8f338806 100755 --- a/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs @@ -360,12 +360,12 @@ namespace CodeImp.DoomBuilder.BuilderModes case GridLockMode.VERTICAL: slicesH = horizontalslices; - slicesV = height / General.Map.Grid.GridSize; + slicesV = Math.Abs(height / General.Map.Grid.GridSize); break; case GridLockMode.BOTH: - slicesH = width / General.Map.Grid.GridSize; - slicesV = height / General.Map.Grid.GridSize; + slicesH = Math.Abs(width / General.Map.Grid.GridSize); + slicesV = Math.Abs(height / General.Map.Grid.GridSize); break; } From 565f1f885b8a634cf1c2e131c23dffc861ad447a Mon Sep 17 00:00:00 2001 From: biwa <6475593+biwa@users.noreply.github.com> Date: Sat, 13 Jun 2020 15:56:16 +0200 Subject: [PATCH 2/2] Changed how performing undo interacts with volatile modes (it will now actually perform the undo instead of just canceling the volatile mode) --- Source/Core/Editing/UndoManager.cs | 212 +++++++++--------- .../ClassicModes/EditSelectionMode.cs | 4 + 2 files changed, 111 insertions(+), 105 deletions(-) diff --git a/Source/Core/Editing/UndoManager.cs b/Source/Core/Editing/UndoManager.cs index 583d9cb8..e2e0be09 100755 --- a/Source/Core/Editing/UndoManager.cs +++ b/Source/Core/Editing/UndoManager.cs @@ -605,121 +605,123 @@ namespace CodeImp.DoomBuilder.Editing // Call UndoBegin event if(General.Editing.Mode.OnUndoBegin()) { - // Cancel volatile mode, if any - // This returns false when mode was not volatile - if(!General.Editing.CancelVolatileMode()) + // biwa. Previously being in a volatile mode simply switch back the the previous + // stable mode without actually performing the undo. This causes problems when the + // volatile mode create undo snapshots. EditSelectionMode does this, and removing + // it's undo snapshot only works because the mode's OnCancel is called twice. + // Maybe the logic of CancelVolatileMode is just wrong. + General.Editing.CancelVolatileMode(); + + geometrychanged = false; + populationchanged = false; + General.Map.Map.ClearAllMarks(false); + General.Map.Map.BeginAddRemove(); + + // Go for all levels to undo + for(int lvl = 0; lvl < levels; lvl++) { - geometrychanged = false; - populationchanged = false; - General.Map.Map.ClearAllMarks(false); - General.Map.Map.BeginAddRemove(); - - // Go for all levels to undo - for(int lvl = 0; lvl < levels; lvl++) + FinishRecording(); + + if(isundosnapshot) { - FinishRecording(); - - if(isundosnapshot) + if(snapshot != null) { - if(snapshot != null) + // This snapshot was made by a previous call to this + // function and should go on the redo list + lock(redos) { - // This snapshot was made by a previous call to this - // function and should go on the redo list - lock(redos) - { - // The current top of the stack can now be written to disk - // because it is no longer the next immediate redo level - if(redos.Count > 0) redos[0].StoreOnDisk = true; + // The current top of the stack can now be written to disk + // because it is no longer the next immediate redo level + if(redos.Count > 0) redos[0].StoreOnDisk = true; - // Put it on the stack - redos.Insert(0, snapshot); - LimitUndoRedoLevel(redos); - } + // Put it on the stack + redos.Insert(0, snapshot); + LimitUndoRedoLevel(redos); } } - else - { - // The snapshot can be undone immediately and it will - // be recorded for the redo list - if(snapshot != null) - u = snapshot; - } - - // No immediate snapshot to undo? Then get the next one from the stack - if(u == null) - { - lock(undos) - { - if(undos.Count > 0) - { - // Get undo snapshot - u = undos[0]; - undos.RemoveAt(0); - - // Make the current top of the stack load into memory - // because it just became the next immediate undo level - if(undos.Count > 0) undos[0].StoreOnDisk = false; - } - else - { - // Nothing more to undo - u = null; - break; - } - } - } - - General.WriteLogLine("Performing undo \"" + u.Description + "\", Ticket ID " + u.TicketID + "..."); - - if((levels == 1) && showmessage) - General.Interface.DisplayStatus(StatusType.Action, u.Description + " undone."); - - // Make a snapshot for redo - StartRecording(u.Description); - isundosnapshot = true; - - // Reset grouping - lastgroupplugin = null; - - // Play back the stream in reverse - MemoryStream data = u.GetStream(); - PlaybackStream(data); - data.Dispose(); - - // Done with this snapshot - u = null; - levelsundone++; } - - General.Map.Map.EndAddRemove(); - - if((levels > 1) && showmessage) - General.Interface.DisplayStatus(StatusType.Action, "Undone " + levelsundone + " changes."); - - // Remove selection - General.Map.Map.ClearAllSelected(); - - // Update map - General.Map.Map.Update(); - foreach(Thing t in General.Map.Map.Things) if(t.Marked) t.UpdateConfiguration(); - General.Map.ThingsFilter.Update(); - General.Map.Data.UpdateUsedTextures(); - General.MainWindow.RefreshInfo(); - //General.MainWindow.RedrawDisplay(); - - // Map changed! - General.Map.IsChanged = true; - - // Done - General.Editing.Mode.OnUndoEnd(); - General.Plugins.OnUndoEnd(); + else + { + // The snapshot can be undone immediately and it will + // be recorded for the redo list + if(snapshot != null) + u = snapshot; + } + + // No immediate snapshot to undo? Then get the next one from the stack + if(u == null) + { + lock(undos) + { + if(undos.Count > 0) + { + // Get undo snapshot + u = undos[0]; + undos.RemoveAt(0); + + // Make the current top of the stack load into memory + // because it just became the next immediate undo level + if(undos.Count > 0) undos[0].StoreOnDisk = false; + } + else + { + // Nothing more to undo + u = null; + break; + } + } + } + + General.WriteLogLine("Performing undo \"" + u.Description + "\", Ticket ID " + u.TicketID + "..."); + + if((levels == 1) && showmessage) + General.Interface.DisplayStatus(StatusType.Action, u.Description + " undone."); + + // Make a snapshot for redo + StartRecording(u.Description); + isundosnapshot = true; + + // Reset grouping + lastgroupplugin = null; - // Update interface - General.Editing.Mode.UpdateSelectionInfo(); //mxd - General.MainWindow.RedrawDisplay(); //mxd - dobackgroundwork = true; - General.MainWindow.UpdateInterface(); + // Play back the stream in reverse + MemoryStream data = u.GetStream(); + PlaybackStream(data); + data.Dispose(); + + // Done with this snapshot + u = null; + levelsundone++; } + + General.Map.Map.EndAddRemove(); + + if((levels > 1) && showmessage) + General.Interface.DisplayStatus(StatusType.Action, "Undone " + levelsundone + " changes."); + + // Remove selection + General.Map.Map.ClearAllSelected(); + + // Update map + General.Map.Map.Update(); + foreach(Thing t in General.Map.Map.Things) if(t.Marked) t.UpdateConfiguration(); + General.Map.ThingsFilter.Update(); + General.Map.Data.UpdateUsedTextures(); + General.MainWindow.RefreshInfo(); + //General.MainWindow.RedrawDisplay(); + + // Map changed! + General.Map.IsChanged = true; + + // Done + General.Editing.Mode.OnUndoEnd(); + General.Plugins.OnUndoEnd(); + + // Update interface + General.Editing.Mode.UpdateSelectionInfo(); //mxd + General.MainWindow.RedrawDisplay(); //mxd + dobackgroundwork = true; + General.MainWindow.UpdateInterface(); } } } diff --git a/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs b/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs index b65bdcf2..fa03b253 100755 --- a/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs @@ -1438,6 +1438,10 @@ namespace CodeImp.DoomBuilder.BuilderModes // Cancel mode public override void OnCancel() { + // Only allow the following code to be run once + if (cancelled) + return; + base.OnCancel(); // Paste operation?