Changed how performing undo interacts with volatile modes (it will now actually perform the undo instead of just canceling the volatile mode)

This commit is contained in:
biwa 2020-06-13 15:56:16 +02:00 committed by spherallic
parent 7d180e5cae
commit 4b0dce43ed
2 changed files with 121 additions and 115 deletions

View file

@ -608,132 +608,134 @@ namespace CodeImp.DoomBuilder.Editing
// Call UndoBegin event // Call UndoBegin event
if(General.Editing.Mode.OnUndoBegin()) if(General.Editing.Mode.OnUndoBegin())
{ {
// Cancel volatile mode, if any // biwa. Previously being in a volatile mode simply switch back the the previous
// This returns false when mode was not volatile // stable mode without actually performing the undo. This causes problems when the
if(!General.Editing.CancelVolatileMode()) // 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; FinishRecording();
populationchanged = false;
General.Map.Map.ClearAllMarks(false);
General.Map.Map.BeginAddRemove();
// Go for all levels to undo if(isundosnapshot)
for(int lvl = 0; lvl < levels; lvl++)
{ {
FinishRecording(); if(snapshot != null)
if(isundosnapshot)
{ {
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 // The current top of the stack can now be written to disk
// function and should go on the redo list // because it is no longer the next immediate redo level
lock(redos) 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 // Put it on the stack
redos.Insert(0, snapshot); redos.Insert(0, snapshot);
LimitUndoRedoLevel(redos); LimitUndoRedoLevel(redos);
}
} }
} }
else }
{ else
// The snapshot can be undone immediately and it will {
// be recorded for the redo list // The snapshot can be undone immediately and it will
if(snapshot != null) // be recorded for the redo list
u = snapshot; 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(); // No immediate snapshot to undo? Then get the next one from the stack
if(u == null)
if((levels > 1) && showmessage)
General.Interface.DisplayStatus(StatusType.Action, "Undone " + levelsundone + " changes.");
// (Re)set hacky flat alignment
if (General.Map.SRB2)
{ {
foreach (Sector s in General.Map.Map.Sectors) lock(undos)
if (s.Marked || linedeftags.Contains(s.Tag)) {
if(undos.Count > 0)
{ {
s.UpdateFloorSurface(); // Get undo snapshot
s.UpdateCeilingSurface(); 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;
}
}
} }
// Remove selection General.WriteLogLine("Performing undo \"" + u.Description + "\", Ticket ID " + u.TicketID + "...");
General.Map.Map.ClearAllSelected();
// Update map if((levels == 1) && showmessage)
General.Map.Map.Update(); General.Interface.DisplayStatus(StatusType.Action, u.Description + " undone.");
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! // Make a snapshot for redo
General.Map.IsChanged = true; StartRecording(u.Description);
isundosnapshot = true;
// Done // Reset grouping
General.Editing.Mode.OnUndoEnd(); lastgroupplugin = null;
General.Plugins.OnUndoEnd();
// Update interface // Play back the stream in reverse
General.Editing.Mode.UpdateSelectionInfo(); //mxd MemoryStream data = u.GetStream();
General.MainWindow.RedrawDisplay(); //mxd PlaybackStream(data);
dobackgroundwork = true; data.Dispose();
General.MainWindow.UpdateInterface();
// Done with this snapshot
u = null;
levelsundone++;
} }
General.Map.Map.EndAddRemove();
if((levels > 1) && showmessage)
General.Interface.DisplayStatus(StatusType.Action, "Undone " + levelsundone + " changes.");
// (Re)set hacky flat alignment
if (General.Map.SRB2)
{
foreach (Sector s in General.Map.Map.Sectors)
if (s.Marked || linedeftags.Contains(s.Tag))
{
s.UpdateFloorSurface();
s.UpdateCeilingSurface();
}
}
// 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();
} }
} }
} }

View file

@ -1401,6 +1401,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Cancel mode // Cancel mode
public override void OnCancel() public override void OnCancel()
{ {
// Only allow the following code to be run once
if (cancelled)
return;
base.OnCancel(); base.OnCancel();
// Paste operation? // Paste operation?