mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-18 22:41:46 +00:00
Merged master into duplicate-3d-floors branch
Added some error handling to duplicating 3D floors
This commit is contained in:
commit
57b184a9e6
5 changed files with 153 additions and 118 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,19 @@ using CodeImp.DoomBuilder.Map;
|
|||
|
||||
namespace CodeImp.DoomBuilder.ThreeDFloorMode
|
||||
{
|
||||
[Serializable]
|
||||
public class NoSpaceInCSAException : Exception
|
||||
{
|
||||
public NoSpaceInCSAException()
|
||||
{ }
|
||||
|
||||
public NoSpaceInCSAException(string message) : base(message)
|
||||
{ }
|
||||
|
||||
public NoSpaceInCSAException(string message, Exception innerException) : base(message, innerException)
|
||||
{ }
|
||||
}
|
||||
|
||||
public class ControlSectorArea
|
||||
{
|
||||
|
||||
|
@ -318,7 +331,7 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode
|
|||
}
|
||||
}
|
||||
|
||||
throw new Exception("Not enough space for control sector relocation");
|
||||
throw new NoSpaceInCSAException("Not enough space for control sector relocation");
|
||||
}
|
||||
|
||||
public List<DrawnVertex> GetNewControlSectorVertices()
|
||||
|
@ -354,7 +367,7 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode
|
|||
}
|
||||
}
|
||||
|
||||
throw new Exception("No space left for control sectors");
|
||||
throw new NoSpaceInCSAException("No space left for control sectors");
|
||||
}
|
||||
|
||||
public bool Inside(float x, float y)
|
||||
|
|
|
@ -61,10 +61,12 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode
|
|||
{
|
||||
#region ================== Constants
|
||||
|
||||
private const string duplicateundodescription = "Duplicate 3D floor control sectors before pasting";
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Variables
|
||||
|
||||
|
||||
// Highlighted item
|
||||
protected Sector highlighted;
|
||||
protected ThreeDFloor highlighted3dfloor;
|
||||
|
@ -87,6 +89,7 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode
|
|||
|
||||
ControlSectorArea.Highlight csahighlight = ControlSectorArea.Highlight.None;
|
||||
bool dragging = false;
|
||||
bool withdrawduplicateundo;
|
||||
|
||||
bool paintselectpressed;
|
||||
|
||||
|
@ -108,10 +111,19 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode
|
|||
{
|
||||
threedfloors = BuilderPlug.GetThreeDFloors(General.Map.Map.Sectors.ToList());
|
||||
|
||||
if(General.Editing.Mode is EditSelectionMode && ((EditSelectionMode)General.Editing.Mode).Cancelled)
|
||||
{
|
||||
withdrawduplicateundo = false;
|
||||
|
||||
// If we're coming from EditSelectionMode, and that modes was cancelled check if the last undo was to create
|
||||
// duplicated 3D floors. If that's the case we want to withdraw that undo, too. Don't do it here, though, as the other
|
||||
// mode is still active, do it in OnEngage instead
|
||||
if (General.Editing.Mode is EditSelectionMode &&
|
||||
((EditSelectionMode)General.Editing.Mode).Cancelled &&
|
||||
General.Map.UndoRedo.NextUndo != null &&
|
||||
General.Map.UndoRedo.NextUndo.Description == duplicateundodescription)
|
||||
{
|
||||
withdrawduplicateundo = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Disposer
|
||||
|
@ -674,6 +686,10 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode
|
|||
UpdateLabels();
|
||||
updateOverlaySurfaces();
|
||||
UpdateOverlay();
|
||||
|
||||
// Withdraw the undo that was created when
|
||||
if (withdrawduplicateundo)
|
||||
General.Map.UndoRedo.WithdrawUndo();
|
||||
}
|
||||
|
||||
void ViewSelectionNumbers_Click(object sender, EventArgs e)
|
||||
|
@ -1516,9 +1532,12 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode
|
|||
tagblacklist.Add(tag);
|
||||
|
||||
if (duplicatethreedfloors.Count == 0)
|
||||
{
|
||||
General.Interface.DisplayStatus(StatusType.Warning, "Selected geometry doesn't contain 3D floors");
|
||||
return;
|
||||
}
|
||||
|
||||
General.Map.UndoRedo.CreateUndo("Duplicate 3D floor control sectors before pasting");
|
||||
General.Map.UndoRedo.CreateUndo(duplicateundodescription);
|
||||
|
||||
// Create a new control sector for each 3D floor that needs to be duplicated. Force it to generate
|
||||
// a new tag, and store the old (current) and new tag
|
||||
|
@ -1527,13 +1546,14 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode
|
|||
int newtag;
|
||||
int oldtag = tdf.UDMFTag;
|
||||
|
||||
if(tdf.CreateGeometry(new List<int>(), true, out newtag))
|
||||
try
|
||||
{
|
||||
tdf.CreateGeometry(new List<int>(), true, out newtag);
|
||||
tagreplacements[oldtag] = newtag;
|
||||
}
|
||||
else
|
||||
catch(NoSpaceInCSAException e)
|
||||
{
|
||||
General.Interface.DisplayStatus(StatusType.Warning, "Could not create 3D floor control sector geometry");
|
||||
General.Interface.DisplayStatus(StatusType.Warning, string.Format("Could not create 3D floor control sector geometry: {0}", e.Message));
|
||||
General.Map.UndoRedo.WithdrawUndo();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1444,7 +1444,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
// Cancel mode
|
||||
public override void OnCancel()
|
||||
{
|
||||
// Make sure the following code is only run once
|
||||
// Only allow the following code to be run once
|
||||
if (cancelled)
|
||||
return;
|
||||
|
||||
|
|
Loading…
Reference in a new issue