mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-31 04:40:55 +00:00
- Progressive undo/redo system (much faster and up to 1000 undo/redo levels) Please note that several plugin functions and properties have changed.
- Some small optimizations in the classic 2D rendering (cached linedef flags, reduced some unneeded redrawing)
This commit is contained in:
parent
f66980b60f
commit
55e640b6e1
32 changed files with 1561 additions and 586 deletions
|
@ -3,7 +3,7 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
<ProductVersion>8.0.50727</ProductVersion>
|
<ProductVersion>9.0.30729</ProductVersion>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
<ProjectGuid>{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}</ProjectGuid>
|
<ProjectGuid>{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}</ProjectGuid>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
|
|
|
@ -48,13 +48,14 @@ namespace CodeImp.DoomBuilder.Config
|
||||||
private Configuration cfg;
|
private Configuration cfg;
|
||||||
|
|
||||||
// Cached variables
|
// Cached variables
|
||||||
private int undolevels;
|
//private int undolevels;
|
||||||
private bool blackbrowsers;
|
private bool blackbrowsers;
|
||||||
private int visualfov;
|
private int visualfov;
|
||||||
private float visualmousesensx;
|
private float visualmousesensx;
|
||||||
private float visualmousesensy;
|
private float visualmousesensy;
|
||||||
private int imagebrightness;
|
private int imagebrightness;
|
||||||
private float doublesidedalpha;
|
private float doublesidedalpha;
|
||||||
|
private byte doublesidedalphabyte;
|
||||||
private float backgroundalpha;
|
private float backgroundalpha;
|
||||||
private bool qualitydisplay;
|
private bool qualitydisplay;
|
||||||
private bool squarethings;
|
private bool squarethings;
|
||||||
|
@ -92,11 +93,12 @@ namespace CodeImp.DoomBuilder.Config
|
||||||
#region ================== Properties
|
#region ================== Properties
|
||||||
|
|
||||||
internal Configuration Config { get { return cfg; } }
|
internal Configuration Config { get { return cfg; } }
|
||||||
public int UndoLevels { get { return undolevels; } internal set { undolevels = value; } }
|
//public int UndoLevels { get { return undolevels; } internal set { undolevels = value; } }
|
||||||
public bool BlackBrowsers { get { return blackbrowsers; } internal set { blackbrowsers = value; } }
|
public bool BlackBrowsers { get { return blackbrowsers; } internal set { blackbrowsers = value; } }
|
||||||
public int VisualFOV { get { return visualfov; } internal set { visualfov = value; } }
|
public int VisualFOV { get { return visualfov; } internal set { visualfov = value; } }
|
||||||
public int ImageBrightness { get { return imagebrightness; } internal set { imagebrightness = value; } }
|
public int ImageBrightness { get { return imagebrightness; } internal set { imagebrightness = value; } }
|
||||||
public float DoubleSidedAlpha { get { return doublesidedalpha; } internal set { doublesidedalpha = value; } }
|
public float DoubleSidedAlpha { get { return doublesidedalpha; } internal set { doublesidedalpha = value; doublesidedalphabyte = (byte)(doublesidedalpha * 255f); } }
|
||||||
|
public byte DoubleSidedAlphaByte { get { return doublesidedalphabyte; } }
|
||||||
public float BackgroundAlpha { get { return backgroundalpha; } internal set { backgroundalpha = value; } }
|
public float BackgroundAlpha { get { return backgroundalpha; } internal set { backgroundalpha = value; } }
|
||||||
public float VisualMouseSensX { get { return visualmousesensx; } internal set { visualmousesensx = value; } }
|
public float VisualMouseSensX { get { return visualmousesensx; } internal set { visualmousesensx = value; } }
|
||||||
public float VisualMouseSensY { get { return visualmousesensy; } internal set { visualmousesensy = value; } }
|
public float VisualMouseSensY { get { return visualmousesensy; } internal set { visualmousesensy = value; } }
|
||||||
|
@ -153,12 +155,13 @@ namespace CodeImp.DoomBuilder.Config
|
||||||
{
|
{
|
||||||
// Read the cache variables
|
// Read the cache variables
|
||||||
blackbrowsers = cfg.ReadSetting("blackbrowsers", false);
|
blackbrowsers = cfg.ReadSetting("blackbrowsers", false);
|
||||||
undolevels = cfg.ReadSetting("undolevels", 20);
|
//undolevels = cfg.ReadSetting("undolevels", 20);
|
||||||
visualfov = cfg.ReadSetting("visualfov", 80);
|
visualfov = cfg.ReadSetting("visualfov", 80);
|
||||||
visualmousesensx = cfg.ReadSetting("visualmousesensx", 40f);
|
visualmousesensx = cfg.ReadSetting("visualmousesensx", 40f);
|
||||||
visualmousesensy = cfg.ReadSetting("visualmousesensy", 40f);
|
visualmousesensy = cfg.ReadSetting("visualmousesensy", 40f);
|
||||||
imagebrightness = cfg.ReadSetting("imagebrightness", 3);
|
imagebrightness = cfg.ReadSetting("imagebrightness", 3);
|
||||||
doublesidedalpha = cfg.ReadSetting("doublesidedalpha", 0.4f);
|
doublesidedalpha = cfg.ReadSetting("doublesidedalpha", 0.4f);
|
||||||
|
doublesidedalphabyte = (byte)(doublesidedalpha * 255f);
|
||||||
backgroundalpha = cfg.ReadSetting("backgroundalpha", 1.0f);
|
backgroundalpha = cfg.ReadSetting("backgroundalpha", 1.0f);
|
||||||
qualitydisplay = cfg.ReadSetting("qualitydisplay", true);
|
qualitydisplay = cfg.ReadSetting("qualitydisplay", true);
|
||||||
squarethings = cfg.ReadSetting("squarethings", false);
|
squarethings = cfg.ReadSetting("squarethings", false);
|
||||||
|
@ -197,7 +200,7 @@ namespace CodeImp.DoomBuilder.Config
|
||||||
|
|
||||||
// Write the cache variables
|
// Write the cache variables
|
||||||
cfg.WriteSetting("blackbrowsers", blackbrowsers);
|
cfg.WriteSetting("blackbrowsers", blackbrowsers);
|
||||||
cfg.WriteSetting("undolevels", undolevels);
|
//cfg.WriteSetting("undolevels", undolevels);
|
||||||
cfg.WriteSetting("visualfov", visualfov);
|
cfg.WriteSetting("visualfov", visualfov);
|
||||||
cfg.WriteSetting("visualmousesensx", visualmousesensx);
|
cfg.WriteSetting("visualmousesensx", visualmousesensx);
|
||||||
cfg.WriteSetting("visualmousesensy", visualmousesensy);
|
cfg.WriteSetting("visualmousesensy", visualmousesensy);
|
||||||
|
@ -363,7 +366,7 @@ namespace CodeImp.DoomBuilder.Config
|
||||||
{
|
{
|
||||||
t.Type = defaultthingtype;
|
t.Type = defaultthingtype;
|
||||||
t.Rotate(defaultthingangle);
|
t.Rotate(defaultthingangle);
|
||||||
foreach(string f in defaultthingflags) t.Flags[f] = true;
|
foreach(string f in defaultthingflags) t.SetFlag(f, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This attempts to find the default drawing settings
|
// This attempts to find the default drawing settings
|
||||||
|
|
|
@ -199,6 +199,8 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
// This applies the current fields to a UniFields object
|
// This applies the current fields to a UniFields object
|
||||||
public void Apply(UniFields tofields)
|
public void Apply(UniFields tofields)
|
||||||
{
|
{
|
||||||
|
tofields.BeforeFieldsChange();
|
||||||
|
|
||||||
// Go for all the fields
|
// Go for all the fields
|
||||||
UniFields tempfields = new UniFields(tofields);
|
UniFields tempfields = new UniFields(tofields);
|
||||||
foreach(KeyValuePair<string, UniValue> f in tempfields)
|
foreach(KeyValuePair<string, UniValue> f in tempfields)
|
||||||
|
|
|
@ -25,6 +25,7 @@ using System.Threading;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using CodeImp.DoomBuilder.Geometry;
|
||||||
using CodeImp.DoomBuilder.Plugins;
|
using CodeImp.DoomBuilder.Plugins;
|
||||||
using CodeImp.DoomBuilder.Windows;
|
using CodeImp.DoomBuilder.Windows;
|
||||||
using CodeImp.DoomBuilder.IO;
|
using CodeImp.DoomBuilder.IO;
|
||||||
|
@ -41,6 +42,39 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
{
|
{
|
||||||
#region ================== Constants
|
#region ================== Constants
|
||||||
|
|
||||||
|
// Maximum undo/redo levels
|
||||||
|
private const int MAX_UNDO_LEVELS = 1000;
|
||||||
|
|
||||||
|
// Default stream capacity
|
||||||
|
private const int STREAM_CAPACITY = 1000;
|
||||||
|
|
||||||
|
// Stream codes
|
||||||
|
// "Prp" stands for property changes (uses the ReadWrite functions)
|
||||||
|
// "Ref" stands for reference changes
|
||||||
|
private enum StreamCodes : byte
|
||||||
|
{
|
||||||
|
AddVertex,
|
||||||
|
RemVertex,
|
||||||
|
PrpVertex,
|
||||||
|
AddLinedef,
|
||||||
|
RemLinedef,
|
||||||
|
PrpLinedef,
|
||||||
|
RefLinedefStart,
|
||||||
|
RefLinedefEnd,
|
||||||
|
RefLinedefFront,
|
||||||
|
RefLinedefBack,
|
||||||
|
AddSidedef,
|
||||||
|
RemSidedef,
|
||||||
|
PrpSidedef,
|
||||||
|
RefSidedefSector,
|
||||||
|
AddSector,
|
||||||
|
RemSector,
|
||||||
|
PrpSector,
|
||||||
|
AddThing,
|
||||||
|
RemThing,
|
||||||
|
PrpThing,
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Variables
|
#region ================== Variables
|
||||||
|
@ -57,6 +91,17 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
// Unique tickets
|
// Unique tickets
|
||||||
private int ticketid;
|
private int ticketid;
|
||||||
|
|
||||||
|
// Writing stream
|
||||||
|
private UndoSnapshot snapshot;
|
||||||
|
private bool isundosnapshot;
|
||||||
|
private MemoryStream stream;
|
||||||
|
private SerializerStream ss;
|
||||||
|
private int commandswritten;
|
||||||
|
private long prevstreamlength;
|
||||||
|
private bool ignorepropchanges;
|
||||||
|
private bool isrecordingcommand;
|
||||||
|
private MapElement propsrecorded;
|
||||||
|
|
||||||
// Background thread
|
// Background thread
|
||||||
private volatile bool dobackgroundwork;
|
private volatile bool dobackgroundwork;
|
||||||
private Thread backgroundthread;
|
private Thread backgroundthread;
|
||||||
|
@ -68,10 +113,40 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
|
|
||||||
#region ================== Properties
|
#region ================== Properties
|
||||||
|
|
||||||
public UndoSnapshot NextUndo { get { if(undos.Count > 0) return undos[0]; else return null; } }
|
public UndoSnapshot NextUndo
|
||||||
public UndoSnapshot NextRedo { get { if(redos.Count > 0) return redos[0]; else return null; } }
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if(!isundosnapshot && (snapshot != null))
|
||||||
|
return snapshot;
|
||||||
|
else if(undos.Count > 0)
|
||||||
|
return undos[0];
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UndoSnapshot NextRedo
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if(isundosnapshot && (snapshot != null))
|
||||||
|
return snapshot;
|
||||||
|
else if(redos.Count > 0)
|
||||||
|
return redos[0];
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsDisposed { get { return isdisposed; } }
|
public bool IsDisposed { get { return isdisposed; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This can be used to ignore insignificant element property changes. Any property changes
|
||||||
|
/// that are made while this is set to True will not be undoable. Use with great care!
|
||||||
|
/// </summary>
|
||||||
|
public bool IgnorePropChanges { get { return ignorepropchanges; } set { ignorepropchanges = value; } }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Constructor / Disposer
|
#region ================== Constructor / Disposer
|
||||||
|
@ -81,8 +156,8 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
{
|
{
|
||||||
// Initialize
|
// Initialize
|
||||||
ticketid = 1;
|
ticketid = 1;
|
||||||
undos = new List<UndoSnapshot>(General.Settings.UndoLevels + 1);
|
undos = new List<UndoSnapshot>(MAX_UNDO_LEVELS + 1);
|
||||||
redos = new List<UndoSnapshot>(General.Settings.UndoLevels + 1);
|
redos = new List<UndoSnapshot>(MAX_UNDO_LEVELS + 1);
|
||||||
|
|
||||||
// Bind any methods
|
// Bind any methods
|
||||||
General.Actions.BindMethods(this);
|
General.Actions.BindMethods(this);
|
||||||
|
@ -154,7 +229,7 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
UndoSnapshot u;
|
UndoSnapshot u;
|
||||||
|
|
||||||
// Too many?
|
// Too many?
|
||||||
if(list.Count > General.Settings.UndoLevels)
|
if(list.Count > MAX_UNDO_LEVELS)
|
||||||
{
|
{
|
||||||
// Remove one and dispose map
|
// Remove one and dispose map
|
||||||
u = list[list.Count - 1];
|
u = list[list.Count - 1];
|
||||||
|
@ -175,23 +250,23 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
dobackgroundwork = false;
|
dobackgroundwork = false;
|
||||||
|
|
||||||
int undolevel = 0;
|
int undolevel = 0;
|
||||||
UndoSnapshot snapshot;
|
UndoSnapshot us;
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
// Get the next snapshot or leave
|
// Get the next snapshot or leave
|
||||||
lock(undos)
|
lock(undos)
|
||||||
{
|
{
|
||||||
if(undolevel < undos.Count)
|
if(undolevel < undos.Count)
|
||||||
snapshot = undos[undolevel];
|
us = undos[undolevel];
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write to file or load from file, if needed
|
// Write to file or load from file, if needed
|
||||||
if(snapshot.StoreOnDisk && !snapshot.IsOnDisk)
|
if(us.StoreOnDisk && !us.IsOnDisk)
|
||||||
snapshot.WriteToFile();
|
us.WriteToFile();
|
||||||
else if(!snapshot.StoreOnDisk && snapshot.IsOnDisk)
|
else if(!us.StoreOnDisk && us.IsOnDisk)
|
||||||
snapshot.RestoreFromFile();
|
us.RestoreFromFile();
|
||||||
|
|
||||||
// Next
|
// Next
|
||||||
undolevel++;
|
undolevel++;
|
||||||
|
@ -204,16 +279,16 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
lock(redos)
|
lock(redos)
|
||||||
{
|
{
|
||||||
if(redolevel < redos.Count)
|
if(redolevel < redos.Count)
|
||||||
snapshot = redos[redolevel];
|
us = redos[redolevel];
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write to file or load from file, if needed
|
// Write to file or load from file, if needed
|
||||||
if(snapshot.StoreOnDisk && !snapshot.IsOnDisk)
|
if(us.StoreOnDisk && !us.IsOnDisk)
|
||||||
snapshot.WriteToFile();
|
us.WriteToFile();
|
||||||
else if(!snapshot.StoreOnDisk && snapshot.IsOnDisk)
|
else if(!us.StoreOnDisk && us.IsOnDisk)
|
||||||
snapshot.RestoreFromFile();
|
us.RestoreFromFile();
|
||||||
|
|
||||||
// Next
|
// Next
|
||||||
redolevel++;
|
redolevel++;
|
||||||
|
@ -225,6 +300,122 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This starts a new recording
|
||||||
|
private void StartRecording(string description)
|
||||||
|
{
|
||||||
|
stream = new MemoryStream(STREAM_CAPACITY);
|
||||||
|
ss = new SerializerStream(stream);
|
||||||
|
ss.Begin();
|
||||||
|
commandswritten = 0;
|
||||||
|
propsrecorded = null;
|
||||||
|
snapshot = new UndoSnapshot(description, stream, ticketid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This finishes recording
|
||||||
|
private void FinishRecording()
|
||||||
|
{
|
||||||
|
// End current recording
|
||||||
|
if(stream != null)
|
||||||
|
{
|
||||||
|
propsrecorded = null;
|
||||||
|
ss.wInt(commandswritten);
|
||||||
|
ss.End();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This begins writing to the record stream
|
||||||
|
private bool BeginRecordData(StreamCodes code)
|
||||||
|
{
|
||||||
|
if(ss == null) return false;
|
||||||
|
isrecordingcommand = true;
|
||||||
|
prevstreamlength = stream.Length;
|
||||||
|
ss.wByte((byte)code);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This ends writing to the record stream
|
||||||
|
private void EndRecordData()
|
||||||
|
{
|
||||||
|
// We write the difference in bytes to the stream so that
|
||||||
|
// the stream can be read from the end backwards
|
||||||
|
int delta = (int)(stream.Length - prevstreamlength);
|
||||||
|
ss.wInt(delta);
|
||||||
|
commandswritten++;
|
||||||
|
isrecordingcommand = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This outputs record info, if desired
|
||||||
|
private void LogRecordInfo(string info)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
//General.WriteLogLine(info);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// This plays back a stream in reverse
|
||||||
|
private void PlaybackStream(MemoryStream pstream)
|
||||||
|
{
|
||||||
|
General.Map.Map.AutoRemove = false;
|
||||||
|
|
||||||
|
General.Map.Map.ClearAllMarks(false);
|
||||||
|
|
||||||
|
pstream.Seek(0, SeekOrigin.Begin);
|
||||||
|
DeserializerStream ds = new DeserializerStream(pstream);
|
||||||
|
ds.Begin();
|
||||||
|
|
||||||
|
if(pstream.Length > 4)
|
||||||
|
{
|
||||||
|
// Start at the end
|
||||||
|
pstream.Seek(ds.EndPosition - 4, SeekOrigin.Begin);
|
||||||
|
int numcmds; ds.rInt(out numcmds);
|
||||||
|
pstream.Seek(-8, SeekOrigin.Current);
|
||||||
|
while(numcmds > 0)
|
||||||
|
{
|
||||||
|
// Go back up the stream to the beginning of the prev command
|
||||||
|
int len; ds.rInt(out len);
|
||||||
|
pstream.Seek(-(len + 4), SeekOrigin.Current);
|
||||||
|
|
||||||
|
// Play back the command
|
||||||
|
long beginpos = pstream.Position;
|
||||||
|
byte cmd; ds.rByte(out cmd);
|
||||||
|
switch((StreamCodes)cmd)
|
||||||
|
{
|
||||||
|
case StreamCodes.AddVertex: PlayAddVertex(ds); break;
|
||||||
|
case StreamCodes.RemVertex: PlayRemVertex(ds); break;
|
||||||
|
case StreamCodes.PrpVertex: PlayPrpVertex(ds); break;
|
||||||
|
case StreamCodes.AddLinedef: PlayAddLinedef(ds); break;
|
||||||
|
case StreamCodes.RemLinedef: PlayRemLinedef(ds); break;
|
||||||
|
case StreamCodes.PrpLinedef: PlayPrpLinedef(ds); break;
|
||||||
|
case StreamCodes.RefLinedefStart: PlayRefLinedefStart(ds); break;
|
||||||
|
case StreamCodes.RefLinedefEnd: PlayRefLinedefEnd(ds); break;
|
||||||
|
case StreamCodes.RefLinedefFront: PlayRefLinedefFront(ds); break;
|
||||||
|
case StreamCodes.RefLinedefBack: PlayRefLinedefBack(ds); break;
|
||||||
|
case StreamCodes.AddSidedef: PlayAddSidedef(ds); break;
|
||||||
|
case StreamCodes.RemSidedef: PlayRemSidedef(ds); break;
|
||||||
|
case StreamCodes.PrpSidedef: PlayPrpSidedef(ds); break;
|
||||||
|
case StreamCodes.RefSidedefSector: PlayRefSidedefSector(ds); break;
|
||||||
|
case StreamCodes.AddSector: PlayAddSector(ds); break;
|
||||||
|
case StreamCodes.RemSector: PlayRemSector(ds); break;
|
||||||
|
case StreamCodes.PrpSector: PlayPrpSector(ds); break;
|
||||||
|
case StreamCodes.AddThing: PlayAddThing(ds); break;
|
||||||
|
case StreamCodes.RemThing: PlayRemThing(ds); break;
|
||||||
|
case StreamCodes.PrpThing: PlayPrpThing(ds); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check
|
||||||
|
if((beginpos + len) != pstream.Position)
|
||||||
|
throw new Exception("The last command did not read the same amount of data that was written for this command!");
|
||||||
|
|
||||||
|
// Go back for next command
|
||||||
|
pstream.Seek(-(len + 4), SeekOrigin.Current);
|
||||||
|
|
||||||
|
numcmds--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
General.Map.Map.AutoRemove = true;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Public Methods
|
#region ================== Public Methods
|
||||||
|
@ -272,14 +463,15 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
(groupid == 0) || (lastgroupid == 0) || (groupid != lastgroupid) ||
|
(groupid == 0) || (lastgroupid == 0) || (groupid != lastgroupid) ||
|
||||||
(grouptag != lastgrouptag))
|
(grouptag != lastgrouptag))
|
||||||
{
|
{
|
||||||
|
FinishRecording();
|
||||||
|
|
||||||
// Next ticket id
|
// Next ticket id
|
||||||
if(++ticketid == int.MaxValue) ticketid = 1;
|
if(++ticketid == int.MaxValue) ticketid = 1;
|
||||||
|
|
||||||
General.WriteLogLine("Creating undo snapshot \"" + description + "\", Source " + groupsourcename + ", Group " + groupid + ", Tag " + grouptag + ", Ticket ID " + ticketid + "...");
|
General.WriteLogLine("Creating undo snapshot \"" + description + "\", Source " + groupsourcename + ", Group " + groupid + ", Tag " + grouptag + ", Ticket ID " + ticketid + "...");
|
||||||
|
|
||||||
// Make a snapshot
|
if((snapshot != null) && !isundosnapshot)
|
||||||
u = new UndoSnapshot(description, General.Map.Map.Serialize(), ticketid);
|
{
|
||||||
|
|
||||||
lock(undos)
|
lock(undos)
|
||||||
{
|
{
|
||||||
// The current top of the stack can now be written to disk
|
// The current top of the stack can now be written to disk
|
||||||
|
@ -287,9 +479,13 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
if(undos.Count > 0) undos[0].StoreOnDisk = true;
|
if(undos.Count > 0) undos[0].StoreOnDisk = true;
|
||||||
|
|
||||||
// Put it on the stack
|
// Put it on the stack
|
||||||
undos.Insert(0, u);
|
undos.Insert(0, snapshot);
|
||||||
LimitUndoRedoLevel(undos);
|
LimitUndoRedoLevel(undos);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StartRecording(description);
|
||||||
|
isundosnapshot = false;
|
||||||
|
|
||||||
// Clear all redos
|
// Clear all redos
|
||||||
ClearRedos();
|
ClearRedos();
|
||||||
|
@ -326,15 +522,17 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
{
|
{
|
||||||
General.WriteLogLine("Withdrawing undo snapshot \"" + undos[0].Description + "\", Ticket ID " + ticket + "...");
|
General.WriteLogLine("Withdrawing undo snapshot \"" + undos[0].Description + "\", Ticket ID " + ticket + "...");
|
||||||
|
|
||||||
lock(undos)
|
if(snapshot != null)
|
||||||
{
|
{
|
||||||
// Remove the last made undo
|
// Just trash this recording
|
||||||
undos[0].Dispose();
|
// You must call CreateUndo first before making any more changes
|
||||||
undos.RemoveAt(0);
|
FinishRecording();
|
||||||
|
isundosnapshot = false;
|
||||||
// Make the current top of the stack load into memory
|
snapshot = null;
|
||||||
// because it just became the next immediate undo level
|
}
|
||||||
if(undos.Count > 0) undos[0].StoreOnDisk = false;
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("No undo is recording that can be withdrawn");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
|
@ -348,12 +546,12 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
[BeginAction("undo")]
|
[BeginAction("undo")]
|
||||||
public void PerformUndo()
|
public void PerformUndo()
|
||||||
{
|
{
|
||||||
UndoSnapshot u, r;
|
UndoSnapshot u = null;
|
||||||
Cursor oldcursor = Cursor.Current;
|
Cursor oldcursor = Cursor.Current;
|
||||||
Cursor.Current = Cursors.WaitCursor;
|
Cursor.Current = Cursors.WaitCursor;
|
||||||
|
|
||||||
// Anything to undo?
|
// Anything to undo?
|
||||||
if(undos.Count > 0)
|
if((undos.Count > 0) || ((snapshot != null) && !isundosnapshot))
|
||||||
{
|
{
|
||||||
// Let the plugins know
|
// Let the plugins know
|
||||||
if(General.Plugins.OnUndoBegin())
|
if(General.Plugins.OnUndoBegin())
|
||||||
|
@ -364,6 +562,37 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
// Cancel volatile mode, if any
|
// Cancel volatile mode, if any
|
||||||
// This returns false when mode was not volatile
|
// This returns false when mode was not volatile
|
||||||
if(!General.CancelVolatileMode())
|
if(!General.CancelVolatileMode())
|
||||||
|
{
|
||||||
|
FinishRecording();
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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)
|
lock(undos)
|
||||||
{
|
{
|
||||||
|
@ -375,44 +604,39 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
// because it just became the next immediate undo level
|
// because it just became the next immediate undo level
|
||||||
if(undos.Count > 0) undos[0].StoreOnDisk = false;
|
if(undos.Count > 0) undos[0].StoreOnDisk = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
General.WriteLogLine("Performing undo \"" + u.Description + "\", Ticket ID " + u.TicketID + "...");
|
General.WriteLogLine("Performing undo \"" + u.Description + "\", Ticket ID " + u.TicketID + "...");
|
||||||
General.Interface.DisplayStatus(StatusType.Action, u.Description + " undone.");
|
General.Interface.DisplayStatus(StatusType.Action, u.Description + " undone.");
|
||||||
|
|
||||||
// Make a snapshot for redo
|
// Make a snapshot for redo
|
||||||
r = new UndoSnapshot(u, General.Map.Map.Serialize());
|
StartRecording(u.Description);
|
||||||
|
isundosnapshot = true;
|
||||||
lock(redos)
|
|
||||||
{
|
|
||||||
// The current top of the stack can now be written to disk
|
|
||||||
// because it is no longer the next immediate undo level
|
|
||||||
if(redos.Count > 0) redos[0].StoreOnDisk = true;
|
|
||||||
|
|
||||||
// Put it on the stack
|
|
||||||
redos.Insert(0, r);
|
|
||||||
LimitUndoRedoLevel(redos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset grouping
|
// Reset grouping
|
||||||
lastgroupplugin = null;
|
lastgroupplugin = null;
|
||||||
|
|
||||||
// Change map set
|
// Play back the stream in reverse
|
||||||
MemoryStream data = u.GetMapData();
|
MemoryStream data = u.GetStream();
|
||||||
General.Map.ChangeMapSet(new MapSet(data));
|
PlaybackStream(data);
|
||||||
data.Dispose();
|
data.Dispose();
|
||||||
|
|
||||||
// Remove selection
|
// Remove selection
|
||||||
General.Map.Map.ClearAllMarks(false);
|
|
||||||
General.Map.Map.ClearAllSelected();
|
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.RedrawDisplay();
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
General.Editing.Mode.OnUndoEnd();
|
General.Editing.Mode.OnUndoEnd();
|
||||||
General.Plugins.OnUndoEnd();
|
General.Plugins.OnUndoEnd();
|
||||||
|
|
||||||
// Update
|
// Update interface
|
||||||
dobackgroundwork = true;
|
dobackgroundwork = true;
|
||||||
General.Map.Data.UpdateUsedTextures();
|
|
||||||
General.MainWindow.RedrawDisplay();
|
|
||||||
General.MainWindow.UpdateInterface();
|
General.MainWindow.UpdateInterface();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,12 +650,12 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
[BeginAction("redo")]
|
[BeginAction("redo")]
|
||||||
public void PerformRedo()
|
public void PerformRedo()
|
||||||
{
|
{
|
||||||
UndoSnapshot u, r;
|
UndoSnapshot r = null;
|
||||||
Cursor oldcursor = Cursor.Current;
|
Cursor oldcursor = Cursor.Current;
|
||||||
Cursor.Current = Cursors.WaitCursor;
|
Cursor.Current = Cursors.WaitCursor;
|
||||||
|
|
||||||
// Anything to redo?
|
// Anything to redo?
|
||||||
if(redos.Count > 0)
|
if((redos.Count > 0) || ((snapshot != null) && isundosnapshot))
|
||||||
{
|
{
|
||||||
// Let the plugins know
|
// Let the plugins know
|
||||||
if(General.Plugins.OnRedoBegin())
|
if(General.Plugins.OnRedoBegin())
|
||||||
|
@ -442,6 +666,37 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
// Cancel volatile mode, if any
|
// Cancel volatile mode, if any
|
||||||
General.CancelVolatileMode();
|
General.CancelVolatileMode();
|
||||||
|
|
||||||
|
FinishRecording();
|
||||||
|
|
||||||
|
if(isundosnapshot)
|
||||||
|
{
|
||||||
|
// This snapshot was started by PerformUndo, which means
|
||||||
|
// it can directly be used to redo to previous undo
|
||||||
|
if(snapshot != null)
|
||||||
|
r = snapshot;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(snapshot != null)
|
||||||
|
{
|
||||||
|
// This snapshot was made by a previous call to this
|
||||||
|
// function and should go on the undo list
|
||||||
|
lock(undos)
|
||||||
|
{
|
||||||
|
// The current top of the stack can now be written to disk
|
||||||
|
// because it is no longer the next immediate undo level
|
||||||
|
if(undos.Count > 0) undos[0].StoreOnDisk = true;
|
||||||
|
|
||||||
|
// Put it on the stack
|
||||||
|
undos.Insert(0, snapshot);
|
||||||
|
LimitUndoRedoLevel(undos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No immediate snapshot to redo? Then get the next one from the stack
|
||||||
|
if(r == null)
|
||||||
|
{
|
||||||
lock(redos)
|
lock(redos)
|
||||||
{
|
{
|
||||||
// Get redo snapshot
|
// Get redo snapshot
|
||||||
|
@ -452,44 +707,38 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
// because it just became the next immediate undo level
|
// because it just became the next immediate undo level
|
||||||
if(redos.Count > 0) redos[0].StoreOnDisk = false;
|
if(redos.Count > 0) redos[0].StoreOnDisk = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
General.WriteLogLine("Performing redo \"" + r.Description + "\", Ticket ID " + r.TicketID + "...");
|
General.WriteLogLine("Performing redo \"" + r.Description + "\", Ticket ID " + r.TicketID + "...");
|
||||||
General.Interface.DisplayStatus(StatusType.Action, r.Description + " redone.");
|
General.Interface.DisplayStatus(StatusType.Action, r.Description + " redone.");
|
||||||
|
|
||||||
// Make a snapshot for undo
|
StartRecording(r.Description);
|
||||||
u = new UndoSnapshot(r, General.Map.Map.Serialize());
|
isundosnapshot = false;
|
||||||
|
|
||||||
lock(undos)
|
|
||||||
{
|
|
||||||
// The current top of the stack can now be written to disk
|
|
||||||
// because it is no longer the next immediate undo level
|
|
||||||
if(undos.Count > 0) undos[0].StoreOnDisk = true;
|
|
||||||
|
|
||||||
// Put it on the stack
|
|
||||||
undos.Insert(0, u);
|
|
||||||
LimitUndoRedoLevel(undos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset grouping
|
// Reset grouping
|
||||||
lastgroupplugin = null;
|
lastgroupplugin = null;
|
||||||
|
|
||||||
// Change map set
|
// Play back the stream in reverse
|
||||||
MemoryStream data = r.GetMapData();
|
MemoryStream data = r.GetStream();
|
||||||
General.Map.ChangeMapSet(new MapSet(data));
|
PlaybackStream(data);
|
||||||
data.Dispose();
|
data.Dispose();
|
||||||
|
|
||||||
// Remove selection
|
// Remove selection
|
||||||
General.Map.Map.ClearAllMarks(false);
|
|
||||||
General.Map.Map.ClearAllSelected();
|
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.RedrawDisplay();
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
General.Editing.Mode.OnRedoEnd();
|
General.Editing.Mode.OnRedoEnd();
|
||||||
General.Plugins.OnRedoEnd();
|
General.Plugins.OnRedoEnd();
|
||||||
|
|
||||||
// Update
|
// Update interface
|
||||||
dobackgroundwork = true;
|
dobackgroundwork = true;
|
||||||
General.Map.Data.UpdateUsedTextures();
|
|
||||||
General.MainWindow.RedrawDisplay();
|
|
||||||
General.MainWindow.UpdateInterface();
|
General.MainWindow.UpdateInterface();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -499,5 +748,428 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Record and Playback
|
||||||
|
|
||||||
|
internal void RecAddVertex(Vertex v)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.AddVertex)) return;
|
||||||
|
ss.wInt(v.Index);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Adding vertex " + v.Index + " at " + v.Position);
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayAddVertex(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
LogRecordInfo("PLY: Removing vertex " + index);
|
||||||
|
Vertex v = General.Map.Map.GetVertexByIndex(index);
|
||||||
|
v.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecRemVertex(Vertex v)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.RemVertex)) return;
|
||||||
|
ss.wInt(v.Index);
|
||||||
|
ss.wVector2D(v.Position);
|
||||||
|
v.ReadWrite(ss);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Removing vertex " + v.Index + " (at " + v.Position + ")");
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayRemVertex(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
Vector2D pos; ds.rVector2D(out pos);
|
||||||
|
LogRecordInfo("PLY: Adding vertex " + index + " at " + pos);
|
||||||
|
Vertex v = General.Map.Map.CreateVertex(index, pos);
|
||||||
|
v.ReadWrite(ds);
|
||||||
|
v.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecPrpVertex(Vertex v)
|
||||||
|
{
|
||||||
|
if(!ignorepropchanges && !isrecordingcommand && !object.ReferenceEquals(v, propsrecorded))
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.PrpVertex)) return;
|
||||||
|
ss.wInt(v.Index);
|
||||||
|
v.ReadWrite(ss);
|
||||||
|
EndRecordData();
|
||||||
|
propsrecorded = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayPrpVertex(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
Vertex v = General.Map.Map.GetVertexByIndex(index);
|
||||||
|
v.ReadWrite(ds);
|
||||||
|
v.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecAddLinedef(Linedef l)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.AddLinedef)) return;
|
||||||
|
ss.wInt(l.Index);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Adding linedef " + l.Index + " from " + ((l.Start != null) ? l.Start.Index : -1) + " to " + ((l.End != null) ? l.End.Index : -1));
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayAddLinedef(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
LogRecordInfo("PLY: Removing linedef " + index);
|
||||||
|
Linedef l = General.Map.Map.GetLinedefByIndex(index);
|
||||||
|
l.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecRemLinedef(Linedef l)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.RemLinedef)) return;
|
||||||
|
ss.wInt(l.Index);
|
||||||
|
ss.wInt(l.Start.Index);
|
||||||
|
ss.wInt(l.End.Index);
|
||||||
|
l.ReadWrite(ss);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Removing linedef " + l.Index + " (from " + ((l.Start != null) ? l.Start.Index : -1) + " to " + ((l.End != null) ? l.End.Index : -1) + ")");
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayRemLinedef(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
int sindex; ds.rInt(out sindex);
|
||||||
|
int eindex; ds.rInt(out eindex);
|
||||||
|
LogRecordInfo("PLY: Adding linedef " + index + " from " + sindex + " to " + eindex);
|
||||||
|
Vertex vs = General.Map.Map.GetVertexByIndex(sindex);
|
||||||
|
Vertex ve = General.Map.Map.GetVertexByIndex(eindex);
|
||||||
|
Linedef l = General.Map.Map.CreateLinedef(index, vs, ve);
|
||||||
|
l.ReadWrite(ds);
|
||||||
|
l.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecPrpLinedef(Linedef l)
|
||||||
|
{
|
||||||
|
if(!ignorepropchanges && !isrecordingcommand && !object.ReferenceEquals(l, propsrecorded))
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.PrpLinedef)) return;
|
||||||
|
ss.wInt(l.Index);
|
||||||
|
l.ReadWrite(ss);
|
||||||
|
EndRecordData();
|
||||||
|
propsrecorded = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayPrpLinedef(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
Linedef l = General.Map.Map.GetLinedefByIndex(index);
|
||||||
|
l.ReadWrite(ds);
|
||||||
|
l.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecRefLinedefStart(Linedef l)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.RefLinedefStart)) return;
|
||||||
|
ss.wInt(l.Index);
|
||||||
|
if(l.Start != null) ss.wInt(l.Start.Index); else ss.wInt(-1);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Setting linedef " + l.Index + " start vertex " + ((l.Start != null) ? l.Start.Index : -1));
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayRefLinedefStart(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
Linedef l = General.Map.Map.GetLinedefByIndex(index);
|
||||||
|
int vindex; ds.rInt(out vindex);
|
||||||
|
LogRecordInfo("PLY: Setting linedef " + index + " start vertex " + vindex);
|
||||||
|
Vertex v = (vindex >= 0) ? General.Map.Map.GetVertexByIndex(vindex) : null;
|
||||||
|
l.SetStartVertex(v);
|
||||||
|
l.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecRefLinedefEnd(Linedef l)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.RefLinedefEnd)) return;
|
||||||
|
ss.wInt(l.Index);
|
||||||
|
if(l.End != null) ss.wInt(l.End.Index); else ss.wInt(-1);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Setting linedef " + l.Index + " end vertex " + ((l.End != null) ? l.End.Index : -1));
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayRefLinedefEnd(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
Linedef l = General.Map.Map.GetLinedefByIndex(index);
|
||||||
|
int vindex; ds.rInt(out vindex);
|
||||||
|
LogRecordInfo("PLY: Setting linedef " + index + " end vertex " + vindex);
|
||||||
|
Vertex v = (vindex >= 0) ? General.Map.Map.GetVertexByIndex(vindex) : null;
|
||||||
|
l.SetEndVertex(v);
|
||||||
|
l.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecRefLinedefFront(Linedef l)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.RefLinedefFront)) return;
|
||||||
|
ss.wInt(l.Index);
|
||||||
|
if(l.Front != null) ss.wInt(l.Front.Index); else ss.wInt(-1);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Setting linedef " + l.Index + " front sidedef " + ((l.Front != null) ? l.Front.Index : -1));
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayRefLinedefFront(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
Linedef l = General.Map.Map.GetLinedefByIndex(index);
|
||||||
|
int sindex; ds.rInt(out sindex);
|
||||||
|
LogRecordInfo("PLY: Setting linedef " + index + " front sidedef " + sindex);
|
||||||
|
Sidedef sd = (sindex >= 0) ? General.Map.Map.GetSidedefByIndex(sindex) : null;
|
||||||
|
l.AttachFront(sd);
|
||||||
|
l.Marked = true;
|
||||||
|
sd.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecRefLinedefBack(Linedef l)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.RefLinedefBack)) return;
|
||||||
|
ss.wInt(l.Index);
|
||||||
|
if(l.Back != null) ss.wInt(l.Back.Index); else ss.wInt(-1);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Setting linedef " + l.Index + " back sidedef " + ((l.Back != null) ? l.Back.Index : -1));
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayRefLinedefBack(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
Linedef l = General.Map.Map.GetLinedefByIndex(index);
|
||||||
|
int sindex; ds.rInt(out sindex);
|
||||||
|
LogRecordInfo("PLY: Setting linedef " + index + " back sidedef " + sindex);
|
||||||
|
Sidedef sd = (sindex >= 0) ? General.Map.Map.GetSidedefByIndex(sindex) : null;
|
||||||
|
l.AttachBack(sd);
|
||||||
|
l.Marked = true;
|
||||||
|
sd.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecAddSidedef(Sidedef s)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.AddSidedef)) return;
|
||||||
|
ss.wInt(s.Index);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Adding sidedef " + s.Index + " to linedef " + s.Line.Index + (s.IsFront ? " front" : " back") + " and sector " + s.Sector.Index);
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayAddSidedef(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
LogRecordInfo("PLY: Removing sidedef " + index);
|
||||||
|
Sidedef s = General.Map.Map.GetSidedefByIndex(index);
|
||||||
|
s.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecRemSidedef(Sidedef s)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.RemSidedef)) return;
|
||||||
|
ss.wInt(s.Index);
|
||||||
|
ss.wInt(s.Line.Index);
|
||||||
|
ss.wBool(s.IsFront);
|
||||||
|
ss.wInt(s.Sector.Index);
|
||||||
|
s.ReadWrite(ss);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Removing sidedef " + s.Index + " (from linedef " + s.Line.Index + (s.IsFront ? " front" : " back") + " and sector " + s.Sector.Index + ")");
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayRemSidedef(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
int dindex; ds.rInt(out dindex);
|
||||||
|
bool front; ds.rBool(out front);
|
||||||
|
int sindex; ds.rInt(out sindex);
|
||||||
|
LogRecordInfo("PLY: Adding sidedef " + index + " to linedef " + dindex + (front ? " front" : " back") + " and sector " + sindex);
|
||||||
|
Linedef l = General.Map.Map.GetLinedefByIndex(dindex);
|
||||||
|
Sector s = General.Map.Map.GetSectorByIndex(sindex);
|
||||||
|
Sidedef sd = General.Map.Map.CreateSidedef(index, l, front, s);
|
||||||
|
sd.ReadWrite(ds);
|
||||||
|
sd.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecPrpSidedef(Sidedef s)
|
||||||
|
{
|
||||||
|
if(!ignorepropchanges && !isrecordingcommand && !object.ReferenceEquals(s, propsrecorded))
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.PrpSidedef)) return;
|
||||||
|
ss.wInt(s.Index);
|
||||||
|
s.ReadWrite(ss);
|
||||||
|
EndRecordData();
|
||||||
|
propsrecorded = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayPrpSidedef(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
Sidedef s = General.Map.Map.GetSidedefByIndex(index);
|
||||||
|
s.ReadWrite(ds);
|
||||||
|
s.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecRefSidedefSector(Sidedef s)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.RefSidedefSector)) return;
|
||||||
|
ss.wInt(s.Index);
|
||||||
|
if(s.Sector != null) ss.wInt(s.Sector.Index); else ss.wInt(-1);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Setting sidedef " + s.Index + " sector " + ((s.Sector != null) ? s.Sector.Index : -1));
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayRefSidedefSector(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
Sidedef sd = General.Map.Map.GetSidedefByIndex(index);
|
||||||
|
int sindex; ds.rInt(out sindex);
|
||||||
|
LogRecordInfo("PLY: Setting sidedef " + index + " sector " + sindex);
|
||||||
|
Sector sc = (sindex >= 0) ? General.Map.Map.GetSectorByIndex(sindex) : null;
|
||||||
|
sd.SetSector(sc);
|
||||||
|
sd.Marked = true;
|
||||||
|
sc.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecAddSector(Sector s)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.AddSector)) return;
|
||||||
|
ss.wInt(s.Index);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Adding sector " + s.Index);
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayAddSector(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
LogRecordInfo("PLY: Removing sector " + index);
|
||||||
|
Sector s = General.Map.Map.GetSectorByIndex(index);
|
||||||
|
s.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecRemSector(Sector s)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.RemSector)) return;
|
||||||
|
ss.wInt(s.Index);
|
||||||
|
s.ReadWrite(ss);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Removing sector " + s.Index);
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayRemSector(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
LogRecordInfo("PLY: Adding sector " + index);
|
||||||
|
Sector s = General.Map.Map.CreateSector(index);
|
||||||
|
s.ReadWrite(ds);
|
||||||
|
s.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecPrpSector(Sector s)
|
||||||
|
{
|
||||||
|
if(!ignorepropchanges && !isrecordingcommand && !object.ReferenceEquals(s, propsrecorded))
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.PrpSector)) return;
|
||||||
|
ss.wInt(s.Index);
|
||||||
|
s.ReadWrite(ss);
|
||||||
|
EndRecordData();
|
||||||
|
propsrecorded = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayPrpSector(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
Sector s = General.Map.Map.GetSectorByIndex(index);
|
||||||
|
s.ReadWrite(ds);
|
||||||
|
s.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecAddThing(Thing t)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.AddThing)) return;
|
||||||
|
ss.wInt(t.Index);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Adding thing " + t.Index);
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayAddThing(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
LogRecordInfo("PLY: Removing thing " + index);
|
||||||
|
Thing t = General.Map.Map.GetThingByIndex(index);
|
||||||
|
t.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecRemThing(Thing t)
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.RemThing)) return;
|
||||||
|
ss.wInt(t.Index);
|
||||||
|
t.ReadWrite(ss);
|
||||||
|
EndRecordData();
|
||||||
|
|
||||||
|
LogRecordInfo("REC: Removing thing " + t.Index);
|
||||||
|
propsrecorded = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayRemThing(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
LogRecordInfo("PLY: Adding thing " + index);
|
||||||
|
Thing t = General.Map.Map.CreateThing(index);
|
||||||
|
t.ReadWrite(ds);
|
||||||
|
t.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RecPrpThing(Thing t)
|
||||||
|
{
|
||||||
|
if(!ignorepropchanges && !isrecordingcommand && !object.ReferenceEquals(t, propsrecorded))
|
||||||
|
{
|
||||||
|
if(!BeginRecordData(StreamCodes.PrpThing)) return;
|
||||||
|
ss.wInt(t.Index);
|
||||||
|
t.ReadWrite(ss);
|
||||||
|
EndRecordData();
|
||||||
|
propsrecorded = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PlayPrpThing(DeserializerStream ds)
|
||||||
|
{
|
||||||
|
int index; ds.rInt(out index);
|
||||||
|
Thing t = General.Map.Map.GetThingByIndex(index);
|
||||||
|
t.ReadWrite(ds);
|
||||||
|
t.Marked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
{
|
{
|
||||||
#region ================== Variables
|
#region ================== Variables
|
||||||
|
|
||||||
private MemoryStream mapdata;
|
private MemoryStream recstream;
|
||||||
private string filename;
|
private string filename;
|
||||||
private string description;
|
private string description;
|
||||||
private int ticketid; // For safe withdrawing
|
private int ticketid; // For safe withdrawing
|
||||||
|
@ -62,22 +62,22 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
#region ================== Constructor / Disposer
|
#region ================== Constructor / Disposer
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
internal UndoSnapshot(string description, MemoryStream mapdata, int ticketid)
|
internal UndoSnapshot(string description, MemoryStream recstream, int ticketid)
|
||||||
{
|
{
|
||||||
if(mapdata == null) General.Fail("Argument cannot be null!");
|
if(recstream == null) General.Fail("Argument cannot be null!");
|
||||||
this.ticketid = ticketid;
|
this.ticketid = ticketid;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.mapdata = mapdata;
|
this.recstream = recstream;
|
||||||
this.filename = null;
|
this.filename = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
internal UndoSnapshot(UndoSnapshot info, MemoryStream mapdata)
|
internal UndoSnapshot(UndoSnapshot info, MemoryStream recstream)
|
||||||
{
|
{
|
||||||
if(mapdata == null) General.Fail("Argument cannot be null!");
|
if(recstream == null) General.Fail("Argument cannot be null!");
|
||||||
this.ticketid = info.ticketid;
|
this.ticketid = info.ticketid;
|
||||||
this.description = info.description;
|
this.description = info.description;
|
||||||
this.mapdata = mapdata;
|
this.recstream = recstream;
|
||||||
this.filename = null;
|
this.filename = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,8 +87,8 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
lock(this)
|
lock(this)
|
||||||
{
|
{
|
||||||
isdisposed = true;
|
isdisposed = true;
|
||||||
if(mapdata != null) mapdata.Dispose();
|
if(recstream != null) recstream.Dispose();
|
||||||
mapdata = null;
|
recstream = null;
|
||||||
if(isondisk) File.Delete(filename);
|
if(isondisk) File.Delete(filename);
|
||||||
isondisk = false;
|
isondisk = false;
|
||||||
}
|
}
|
||||||
|
@ -99,15 +99,15 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
#region ================== Methods
|
#region ================== Methods
|
||||||
|
|
||||||
// This returns the map data
|
// This returns the map data
|
||||||
internal MemoryStream GetMapData()
|
internal MemoryStream GetStream()
|
||||||
{
|
{
|
||||||
lock(this)
|
lock(this)
|
||||||
{
|
{
|
||||||
// Restore into memory if needed
|
// Restore into memory if needed
|
||||||
if(isondisk) RestoreFromFile();
|
if(isondisk) RestoreFromFile();
|
||||||
|
|
||||||
// Return a copy of the buffer
|
// Return the buffer
|
||||||
return new MemoryStream(mapdata.ToArray());
|
return recstream;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,9 +121,9 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
isondisk = true;
|
isondisk = true;
|
||||||
|
|
||||||
// Compress data
|
// Compress data
|
||||||
mapdata.Seek(0, SeekOrigin.Begin);
|
recstream.Seek(0, SeekOrigin.Begin);
|
||||||
MemoryStream outstream = new MemoryStream((int)mapdata.Length);
|
MemoryStream outstream = new MemoryStream((int)recstream.Length);
|
||||||
BZip2.Compress(mapdata, outstream, 300000);
|
BZip2.Compress(recstream, outstream, 300000);
|
||||||
|
|
||||||
// Make temporary file
|
// Make temporary file
|
||||||
filename = General.MakeTempFilename(General.Map.TempPath, "snapshot");
|
filename = General.MakeTempFilename(General.Map.TempPath, "snapshot");
|
||||||
|
@ -132,8 +132,8 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
File.WriteAllBytes(filename, outstream.ToArray());
|
File.WriteAllBytes(filename, outstream.ToArray());
|
||||||
|
|
||||||
// Remove data from memory
|
// Remove data from memory
|
||||||
mapdata.Dispose();
|
recstream.Dispose();
|
||||||
mapdata = null;
|
recstream = null;
|
||||||
outstream.Dispose();
|
outstream.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ namespace CodeImp.DoomBuilder.Editing
|
||||||
MemoryStream outstream = new MemoryStream((int)instream.Length * 4);
|
MemoryStream outstream = new MemoryStream((int)instream.Length * 4);
|
||||||
instream.Seek(0, SeekOrigin.Begin);
|
instream.Seek(0, SeekOrigin.Begin);
|
||||||
BZip2.Decompress(instream, outstream);
|
BZip2.Decompress(instream, outstream);
|
||||||
mapdata = new MemoryStream(outstream.ToArray());
|
recstream = new MemoryStream(outstream.ToArray());
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
instream.Dispose();
|
instream.Dispose();
|
||||||
|
|
|
@ -348,6 +348,9 @@ namespace CodeImp.DoomBuilder
|
||||||
General.WriteLogLine("Initializing map format interface " + config.FormatInterface + "...");
|
General.WriteLogLine("Initializing map format interface " + config.FormatInterface + "...");
|
||||||
io = MapSetIO.Create(config.FormatInterface, tempwad, this);
|
io = MapSetIO.Create(config.FormatInterface, tempwad, this);
|
||||||
General.WriteLogLine("Reading map data structures from file...");
|
General.WriteLogLine("Reading map data structures from file...");
|
||||||
|
#if DEBUG
|
||||||
|
map = io.Read(map, TEMP_MAP_HEADER);
|
||||||
|
#else
|
||||||
try { map = io.Read(map, TEMP_MAP_HEADER); }
|
try { map = io.Read(map, TEMP_MAP_HEADER); }
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
|
@ -355,6 +358,7 @@ namespace CodeImp.DoomBuilder
|
||||||
General.ShowErrorMessage("Unable to read the map data structures with the specified configuration.", MessageBoxButtons.OK);
|
General.ShowErrorMessage("Unable to read the map data structures with the specified configuration.", MessageBoxButtons.OK);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
map.EndAddRemove();
|
map.EndAddRemove();
|
||||||
|
|
||||||
// Load data manager
|
// Load data manager
|
||||||
|
@ -446,6 +450,8 @@ namespace CodeImp.DoomBuilder
|
||||||
{
|
{
|
||||||
if(t.Type == config.Start3DModeThingType)
|
if(t.Type == config.Start3DModeThingType)
|
||||||
{
|
{
|
||||||
|
// We're not using SetFlag here, this doesn't have to be undone.
|
||||||
|
// Please note that this is totally exceptional!
|
||||||
List<string> flagkeys = new List<string>(t.Flags.Keys);
|
List<string> flagkeys = new List<string>(t.Flags.Keys);
|
||||||
foreach(string k in flagkeys) t.Flags[k] = false;
|
foreach(string k in flagkeys) t.Flags[k] = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -566,14 +566,14 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
{
|
{
|
||||||
// Create sidedef is needed and ensure it points to the new sector
|
// Create sidedef is needed and ensure it points to the new sector
|
||||||
if(ls.Line.Front == null) General.Map.Map.CreateSidedef(ls.Line, true, newsector);
|
if(ls.Line.Front == null) General.Map.Map.CreateSidedef(ls.Line, true, newsector);
|
||||||
if(ls.Line.Front.Sector != newsector) ls.Line.Front.ChangeSector(newsector);
|
if(ls.Line.Front.Sector != newsector) ls.Line.Front.SetSector(newsector);
|
||||||
ApplyDefaultsToSidedef(ls.Line.Front, sourceside);
|
ApplyDefaultsToSidedef(ls.Line.Front, sourceside);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create sidedef is needed and ensure it points to the new sector
|
// Create sidedef is needed and ensure it points to the new sector
|
||||||
if(ls.Line.Back == null) General.Map.Map.CreateSidedef(ls.Line, false, newsector);
|
if(ls.Line.Back == null) General.Map.Map.CreateSidedef(ls.Line, false, newsector);
|
||||||
if(ls.Line.Back.Sector != newsector) ls.Line.Back.ChangeSector(newsector);
|
if(ls.Line.Back.Sector != newsector) ls.Line.Back.SetSector(newsector);
|
||||||
ApplyDefaultsToSidedef(ls.Line.Back, sourceside);
|
ApplyDefaultsToSidedef(ls.Line.Back, sourceside);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,7 +622,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Link to the new sector
|
// Link to the new sector
|
||||||
ls.Line.Front.ChangeSector(original.Sector);
|
ls.Line.Front.SetSector(original.Sector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -641,7 +641,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Link to the new sector
|
// Link to the new sector
|
||||||
ls.Line.Back.ChangeSector(original.Sector);
|
ls.Line.Back.SetSector(original.Sector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,9 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
// Constructor
|
// Constructor
|
||||||
public Triangulation()
|
public Triangulation()
|
||||||
{
|
{
|
||||||
|
islandvertices = Array.AsReadOnly<int>(new int[0]);
|
||||||
|
vertices = Array.AsReadOnly<Vector2D>(new Vector2D[0]);
|
||||||
|
sidedefs = Array.AsReadOnly<Sidedef>(new Sidedef[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This performs the triangulation
|
// This performs the triangulation
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace CodeImp.DoomBuilder.IO
|
||||||
private Stream stream;
|
private Stream stream;
|
||||||
private BinaryReader reader;
|
private BinaryReader reader;
|
||||||
private string[] stringstable;
|
private string[] stringstable;
|
||||||
|
private int stringtablepos;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -49,6 +50,8 @@ namespace CodeImp.DoomBuilder.IO
|
||||||
|
|
||||||
public bool IsWriting { get { return false; } }
|
public bool IsWriting { get { return false; } }
|
||||||
|
|
||||||
|
public int EndPosition { get { return stringtablepos; } }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Constructor / Destructor
|
#region ================== Constructor / Destructor
|
||||||
|
@ -69,8 +72,8 @@ namespace CodeImp.DoomBuilder.IO
|
||||||
public void Begin()
|
public void Begin()
|
||||||
{
|
{
|
||||||
// First 4 bytes are reserved for the offset of the strings table
|
// First 4 bytes are reserved for the offset of the strings table
|
||||||
int offset = reader.ReadInt32();
|
stringtablepos = reader.ReadInt32();
|
||||||
stream.Seek(offset, SeekOrigin.Begin);
|
stream.Seek(stringtablepos, SeekOrigin.Begin);
|
||||||
|
|
||||||
// Read the strings
|
// Read the strings
|
||||||
List<string> strings = new List<string>();
|
List<string> strings = new List<string>();
|
||||||
|
|
|
@ -375,6 +375,8 @@ namespace CodeImp.DoomBuilder.IO
|
||||||
// This reads custom fields from a collection and adds them to a map element
|
// This reads custom fields from a collection and adds them to a map element
|
||||||
private void ReadCustomFields(UniversalCollection collection, MapElement element, string elementname)
|
private void ReadCustomFields(UniversalCollection collection, MapElement element, string elementname)
|
||||||
{
|
{
|
||||||
|
element.Fields.BeforeFieldsChange();
|
||||||
|
|
||||||
// Go for all the elements in the collection
|
// Go for all the elements in the collection
|
||||||
foreach(UniversalEntry e in collection)
|
foreach(UniversalEntry e in collection)
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,6 +67,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
private float lengthinv;
|
private float lengthinv;
|
||||||
private float angle;
|
private float angle;
|
||||||
private RectangleF rect;
|
private RectangleF rect;
|
||||||
|
private bool blocksoundflag;
|
||||||
|
private bool impassableflag;
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
private Dictionary<string, bool> flags;
|
private Dictionary<string, bool> flags;
|
||||||
|
@ -89,10 +91,10 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
public Sidedef Front { get { return front; } }
|
public Sidedef Front { get { return front; } }
|
||||||
public Sidedef Back { get { return back; } }
|
public Sidedef Back { get { return back; } }
|
||||||
public Line2D Line { get { return new Line2D(start.Position, end.Position); } }
|
public Line2D Line { get { return new Line2D(start.Position, end.Position); } }
|
||||||
public Dictionary<string, bool> Flags { get { return flags; } }
|
internal Dictionary<string, bool> Flags { get { return flags; } }
|
||||||
public int Action { get { return action; } set { action = value; } }
|
public int Action { get { return action; } set { BeforePropsChange(); action = value; } }
|
||||||
public int Activate { get { return activate; } set { activate = value; } }
|
public int Activate { get { return activate; } set { BeforePropsChange(); activate = value; } }
|
||||||
public int Tag { get { return tag; } set { tag = value; if((tag < General.Map.FormatInterface.MinTag) || (tag > General.Map.FormatInterface.MaxTag)) throw new ArgumentOutOfRangeException("Tag", "Invalid tag number"); } }
|
public int Tag { get { return tag; } set { BeforePropsChange(); tag = value; if((tag < General.Map.FormatInterface.MinTag) || (tag > General.Map.FormatInterface.MaxTag)) throw new ArgumentOutOfRangeException("Tag", "Invalid tag number"); } }
|
||||||
public float LengthSq { get { return lengthsq; } }
|
public float LengthSq { get { return lengthsq; } }
|
||||||
public float Length { get { return length; } }
|
public float Length { get { return length; } }
|
||||||
public float LengthInv { get { return lengthinv; } }
|
public float LengthInv { get { return lengthinv; } }
|
||||||
|
@ -102,6 +104,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
public int[] Args { get { return args; } }
|
public int[] Args { get { return args; } }
|
||||||
internal int SerializedIndex { get { return serializedindex; } set { serializedindex = value; } }
|
internal int SerializedIndex { get { return serializedindex; } set { serializedindex = value; } }
|
||||||
internal bool FrontInterior { get { return frontinterior; } set { frontinterior = value; } }
|
internal bool FrontInterior { get { return frontinterior; } set { frontinterior = value; } }
|
||||||
|
internal bool ImpassableFlag { get { return impassableflag; } }
|
||||||
|
internal bool BlockSoundFlag { get { return blocksoundflag; } }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -113,36 +117,18 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Initialize
|
// Initialize
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.listindex = listindex;
|
this.listindex = listindex;
|
||||||
this.start = start;
|
|
||||||
this.end = end;
|
|
||||||
this.updateneeded = true;
|
this.updateneeded = true;
|
||||||
this.args = new int[NUM_ARGS];
|
this.args = new int[NUM_ARGS];
|
||||||
this.flags = new Dictionary<string, bool>();
|
this.flags = new Dictionary<string, bool>();
|
||||||
|
|
||||||
// Attach to vertices
|
// Attach to vertices
|
||||||
startvertexlistitem = start.AttachLinedef(this);
|
|
||||||
endvertexlistitem = end.AttachLinedef(this);
|
|
||||||
|
|
||||||
// We have no destructor
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
internal Linedef(MapSet map, int listindex, Vertex start, Vertex end, IReadWriteStream stream)
|
|
||||||
{
|
|
||||||
// Initialize
|
|
||||||
this.map = map;
|
|
||||||
this.listindex = listindex;
|
|
||||||
this.start = start;
|
this.start = start;
|
||||||
|
this.startvertexlistitem = start.AttachLinedefP(this);
|
||||||
this.end = end;
|
this.end = end;
|
||||||
this.updateneeded = true;
|
this.endvertexlistitem = end.AttachLinedefP(this);
|
||||||
this.args = new int[NUM_ARGS];
|
|
||||||
|
|
||||||
// Attach to vertices
|
if(map == General.Map.Map)
|
||||||
startvertexlistitem = start.AttachLinedef(this);
|
General.Map.UndoRedo.RecAddLinedef(this);
|
||||||
endvertexlistitem = end.AttachLinedef(this);
|
|
||||||
|
|
||||||
ReadWrite(stream);
|
|
||||||
|
|
||||||
// We have no destructor
|
// We have no destructor
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
|
@ -157,18 +143,23 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Already set isdisposed so that changes can be prohibited
|
// Already set isdisposed so that changes can be prohibited
|
||||||
isdisposed = true;
|
isdisposed = true;
|
||||||
|
|
||||||
|
// Dispose sidedefs
|
||||||
|
if((front != null) && map.AutoRemove) front.Dispose(); else AttachFrontP(null);
|
||||||
|
if((back != null) && map.AutoRemove) back.Dispose(); else AttachBackP(null);
|
||||||
|
|
||||||
|
if(map == General.Map.Map)
|
||||||
|
General.Map.UndoRedo.RecRemLinedef(this);
|
||||||
|
|
||||||
// Remove from main list
|
// Remove from main list
|
||||||
map.RemoveLinedef(listindex);
|
map.RemoveLinedef(listindex);
|
||||||
|
|
||||||
// Detach from vertices
|
// Detach from vertices
|
||||||
start.DetachLinedef(startvertexlistitem);
|
if(startvertexlistitem != null) start.DetachLinedefP(startvertexlistitem);
|
||||||
end.DetachLinedef(endvertexlistitem);
|
|
||||||
startvertexlistitem = null;
|
startvertexlistitem = null;
|
||||||
|
start = null;
|
||||||
|
if(endvertexlistitem != null) end.DetachLinedefP(endvertexlistitem);
|
||||||
endvertexlistitem = null;
|
endvertexlistitem = null;
|
||||||
|
end = null;
|
||||||
// Dispose sidedefs
|
|
||||||
if((front != null) && map.AutoRemove) front.Dispose();
|
|
||||||
if((back != null) && map.AutoRemove) back.Dispose();
|
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
start = null;
|
start = null;
|
||||||
|
@ -186,9 +177,18 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
|
|
||||||
#region ================== Management
|
#region ================== Management
|
||||||
|
|
||||||
// Serialize / deserialize
|
// Call this before changing properties
|
||||||
|
protected override void BeforePropsChange()
|
||||||
|
{
|
||||||
|
if(map == General.Map.Map)
|
||||||
|
General.Map.UndoRedo.RecPrpLinedef(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize / deserialize (passive: doesn't record)
|
||||||
internal void ReadWrite(IReadWriteStream s)
|
internal void ReadWrite(IReadWriteStream s)
|
||||||
{
|
{
|
||||||
|
if(!s.IsWriting) BeforePropsChange();
|
||||||
|
|
||||||
base.ReadWrite(s);
|
base.ReadWrite(s);
|
||||||
|
|
||||||
if(s.IsWriting)
|
if(s.IsWriting)
|
||||||
|
@ -223,32 +223,46 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This sets new start vertex
|
// This sets new start vertex
|
||||||
public void SetStartVertex(Vertex v)
|
public void SetStartVertex(Vertex v)
|
||||||
{
|
{
|
||||||
|
if(map == General.Map.Map)
|
||||||
|
General.Map.UndoRedo.RecRefLinedefStart(this);
|
||||||
|
|
||||||
// Change start
|
// Change start
|
||||||
if(startvertexlistitem != null) start.DetachLinedef(startvertexlistitem);
|
if(startvertexlistitem != null) start.DetachLinedefP(startvertexlistitem);
|
||||||
startvertexlistitem = null;
|
startvertexlistitem = null;
|
||||||
start = v;
|
start = v;
|
||||||
if(start != null) startvertexlistitem = start.AttachLinedef(this);
|
if(start != null) startvertexlistitem = start.AttachLinedefP(this);
|
||||||
this.updateneeded = true;
|
this.updateneeded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This sets new end vertex
|
// This sets new end vertex
|
||||||
public void SetEndVertex(Vertex v)
|
public void SetEndVertex(Vertex v)
|
||||||
{
|
{
|
||||||
|
if(map == General.Map.Map)
|
||||||
|
General.Map.UndoRedo.RecRefLinedefEnd(this);
|
||||||
|
|
||||||
// Change end
|
// Change end
|
||||||
if(endvertexlistitem != null) end.DetachLinedef(endvertexlistitem);
|
if(endvertexlistitem != null) end.DetachLinedefP(endvertexlistitem);
|
||||||
endvertexlistitem = null;
|
endvertexlistitem = null;
|
||||||
end = v;
|
end = v;
|
||||||
if(end != null) endvertexlistitem = end.AttachLinedef(this);
|
if(end != null) endvertexlistitem = end.AttachLinedefP(this);
|
||||||
this.updateneeded = true;
|
this.updateneeded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This detaches a vertex
|
// This detaches a vertex
|
||||||
internal void DetachVertex(Vertex v)
|
internal void DetachVertexP(Vertex v)
|
||||||
{
|
{
|
||||||
if(v == start)
|
if(v == start)
|
||||||
SetStartVertex(null);
|
{
|
||||||
|
if(startvertexlistitem != null) start.DetachLinedefP(startvertexlistitem);
|
||||||
|
startvertexlistitem = null;
|
||||||
|
start = null;
|
||||||
|
}
|
||||||
else if(v == end)
|
else if(v == end)
|
||||||
SetEndVertex(null);
|
{
|
||||||
|
if(endvertexlistitem != null) end.DetachLinedefP(endvertexlistitem);
|
||||||
|
endvertexlistitem = null;
|
||||||
|
end = null;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
throw new Exception("Specified Vertex is not attached to this Linedef.");
|
throw new Exception("Specified Vertex is not attached to this Linedef.");
|
||||||
}
|
}
|
||||||
|
@ -256,6 +270,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This copies all properties to another line
|
// This copies all properties to another line
|
||||||
new public void CopyPropertiesTo(Linedef l)
|
new public void CopyPropertiesTo(Linedef l)
|
||||||
{
|
{
|
||||||
|
l.BeforePropsChange();
|
||||||
|
|
||||||
// Copy properties
|
// Copy properties
|
||||||
l.action = action;
|
l.action = action;
|
||||||
l.args = (int[])args.Clone();
|
l.args = (int[])args.Clone();
|
||||||
|
@ -263,42 +279,57 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
l.tag = tag;
|
l.tag = tag;
|
||||||
l.updateneeded = true;
|
l.updateneeded = true;
|
||||||
l.activate = activate;
|
l.activate = activate;
|
||||||
|
l.impassableflag = impassableflag;
|
||||||
|
l.blocksoundflag = blocksoundflag;
|
||||||
base.CopyPropertiesTo(l);
|
base.CopyPropertiesTo(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This attaches a sidedef on the front
|
// This attaches a sidedef on the front
|
||||||
public void AttachFront(Sidedef s)
|
internal void AttachFront(Sidedef s)
|
||||||
{
|
{
|
||||||
// No sidedef here yet?
|
if(map == General.Map.Map)
|
||||||
if(front == null)
|
General.Map.UndoRedo.RecRefLinedefFront(this);
|
||||||
|
|
||||||
|
// Attach and recalculate
|
||||||
|
AttachFrontP(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passive version, does not record the change
|
||||||
|
internal void AttachFrontP(Sidedef s)
|
||||||
{
|
{
|
||||||
// Attach and recalculate
|
// Attach and recalculate
|
||||||
front = s;
|
front = s;
|
||||||
|
if(front != null) front.SetLinedefP(this);
|
||||||
updateneeded = true;
|
updateneeded = true;
|
||||||
}
|
}
|
||||||
else throw new Exception("Linedef already has a front Sidedef.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// This attaches a sidedef on the back
|
// This attaches a sidedef on the back
|
||||||
public void AttachBack(Sidedef s)
|
internal void AttachBack(Sidedef s)
|
||||||
{
|
{
|
||||||
// No sidedef here yet?
|
if(map == General.Map.Map)
|
||||||
if(back == null)
|
General.Map.UndoRedo.RecRefLinedefBack(this);
|
||||||
|
|
||||||
|
// Attach and recalculate
|
||||||
|
AttachBackP(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passive version, does not record the change
|
||||||
|
internal void AttachBackP(Sidedef s)
|
||||||
{
|
{
|
||||||
// Attach and recalculate
|
// Attach and recalculate
|
||||||
back = s;
|
back = s;
|
||||||
|
if(back != null) back.SetLinedefP(this);
|
||||||
updateneeded = true;
|
updateneeded = true;
|
||||||
}
|
}
|
||||||
else throw new Exception("Linedef already has a back Sidedef.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// This detaches a sidedef from the front
|
// This detaches a sidedef from the front
|
||||||
public void DetachSidedef(Sidedef s)
|
internal void DetachSidedefP(Sidedef s)
|
||||||
{
|
{
|
||||||
// Sidedef is on the front?
|
// Sidedef is on the front?
|
||||||
if(front == s)
|
if(front == s)
|
||||||
{
|
{
|
||||||
// Remove sidedef reference
|
// Remove sidedef reference
|
||||||
|
if(front != null) front.SetLinedefP(null);
|
||||||
front = null;
|
front = null;
|
||||||
updateneeded = true;
|
updateneeded = true;
|
||||||
}
|
}
|
||||||
|
@ -306,10 +337,11 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
else if(back == s)
|
else if(back == s)
|
||||||
{
|
{
|
||||||
// Remove sidedef reference
|
// Remove sidedef reference
|
||||||
|
if(back != null) back.SetLinedefP(null);
|
||||||
back = null;
|
back = null;
|
||||||
updateneeded = true;
|
updateneeded = true;
|
||||||
}
|
}
|
||||||
else throw new Exception("Specified Sidedef is not attached to this Linedef.");
|
//else throw new Exception("Specified Sidedef is not attached to this Linedef.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// This updates the line when changes have been made
|
// This updates the line when changes have been made
|
||||||
|
@ -333,6 +365,10 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
float b = Math.Max(start.Position.y, end.Position.y);
|
float b = Math.Max(start.Position.y, end.Position.y);
|
||||||
rect = new RectangleF(l, t, r - l, b - t);
|
rect = new RectangleF(l, t, r - l, b - t);
|
||||||
|
|
||||||
|
// Cached flags
|
||||||
|
blocksoundflag = IsFlagSet(General.Map.Config.SoundLinedefFlag);
|
||||||
|
impassableflag = IsFlagSet(General.Map.Config.ImpassableFlag);
|
||||||
|
|
||||||
// Updated
|
// Updated
|
||||||
updateneeded = false;
|
updateneeded = false;
|
||||||
}
|
}
|
||||||
|
@ -479,18 +515,43 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This sets a flag
|
||||||
|
public void SetFlag(string flagname, bool value)
|
||||||
|
{
|
||||||
|
if(!flags.ContainsKey(flagname) || (IsFlagSet(flagname) != value))
|
||||||
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
|
flags[flagname] = value;
|
||||||
|
|
||||||
|
// Cached flags
|
||||||
|
if(flagname == General.Map.Config.SoundLinedefFlag) blocksoundflag = value;
|
||||||
|
if(flagname == General.Map.Config.ImpassableFlag) impassableflag = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This returns a copy of the flags dictionary
|
||||||
|
public Dictionary<string, bool> GetFlags()
|
||||||
|
{
|
||||||
|
return new Dictionary<string, bool>(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This clears all flags
|
||||||
|
public void ClearFlags()
|
||||||
|
{
|
||||||
|
flags.Clear();
|
||||||
|
blocksoundflag = false;
|
||||||
|
impassableflag = false;
|
||||||
|
}
|
||||||
|
|
||||||
// This flips the linedef's vertex attachments
|
// This flips the linedef's vertex attachments
|
||||||
public void FlipVertices()
|
public void FlipVertices()
|
||||||
{
|
{
|
||||||
// Flip vertices
|
// Flip vertices
|
||||||
Vertex v = start;
|
Vertex oldstart = start;
|
||||||
start = end;
|
Vertex oldend = end;
|
||||||
end = v;
|
SetStartVertex(oldend);
|
||||||
|
SetEndVertex(oldstart);
|
||||||
// Flip tickets accordingly
|
|
||||||
LinkedListNode<Linedef> vn = startvertexlistitem;
|
|
||||||
startvertexlistitem = endvertexlistitem;
|
|
||||||
endvertexlistitem = vn;
|
|
||||||
|
|
||||||
// For drawing, the interior now lies on the other side
|
// For drawing, the interior now lies on the other side
|
||||||
frontinterior = !frontinterior;
|
frontinterior = !frontinterior;
|
||||||
|
@ -504,9 +565,10 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
public void FlipSidedefs()
|
public void FlipSidedefs()
|
||||||
{
|
{
|
||||||
// Flip sidedefs
|
// Flip sidedefs
|
||||||
Sidedef sd = front;
|
Sidedef oldfront = front;
|
||||||
front = back;
|
Sidedef oldback = back;
|
||||||
back = sd;
|
AttachFront(oldback);
|
||||||
|
AttachBack(oldfront);
|
||||||
|
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
}
|
}
|
||||||
|
@ -544,14 +606,14 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
if((front != null) && (back != null))
|
if((front != null) && (back != null))
|
||||||
{
|
{
|
||||||
// Apply or remove flags for doublesided line
|
// Apply or remove flags for doublesided line
|
||||||
flags[General.Map.Config.SingleSidedFlag] = false;
|
SetFlag(General.Map.Config.SingleSidedFlag, false);
|
||||||
flags[General.Map.Config.DoubleSidedFlag] = true;
|
SetFlag(General.Map.Config.DoubleSidedFlag, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Apply or remove flags for singlesided line
|
// Apply or remove flags for singlesided line
|
||||||
flags[General.Map.Config.SingleSidedFlag] = true;
|
SetFlag(General.Map.Config.SingleSidedFlag, true);
|
||||||
flags[General.Map.Config.DoubleSidedFlag] = false;
|
SetFlag(General.Map.Config.DoubleSidedFlag, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
|
@ -952,6 +1014,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This updates all properties
|
// This updates all properties
|
||||||
public void Update(Dictionary<string, bool> flags, int activate, int tag, int action, int[] args)
|
public void Update(Dictionary<string, bool> flags, int activate, int tag, int action, int[] args)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
// Apply changes
|
// Apply changes
|
||||||
this.flags = new Dictionary<string, bool>(flags);
|
this.flags = new Dictionary<string, bool>(flags);
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
|
|
|
@ -68,13 +68,14 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
internal MapElement()
|
internal MapElement()
|
||||||
{
|
{
|
||||||
// Initialize
|
// Initialize
|
||||||
fields = new UniFields();
|
fields = new UniFields(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disposer
|
// Disposer
|
||||||
public virtual void Dispose()
|
public virtual void Dispose()
|
||||||
{
|
{
|
||||||
// Clean up
|
// Clean up
|
||||||
|
fields.Owner = null;
|
||||||
fields = null;
|
fields = null;
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
|
@ -101,7 +102,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fields = new UniFields(c);
|
fields = new UniFields(this, c);
|
||||||
for(int i = 0; i < c; i++)
|
for(int i = 0; i < c; i++)
|
||||||
{
|
{
|
||||||
string t; s.rString(out t);
|
string t; s.rString(out t);
|
||||||
|
@ -114,7 +115,16 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This copies properties to any other element
|
// This copies properties to any other element
|
||||||
public void CopyPropertiesTo(MapElement element)
|
public void CopyPropertiesTo(MapElement element)
|
||||||
{
|
{
|
||||||
element.fields = new UniFields(this.fields);
|
element.fields = new UniFields(this, this.fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This must implement the call to the undo system to record the change of properties
|
||||||
|
protected abstract void BeforePropsChange();
|
||||||
|
|
||||||
|
// This is called before the custom fields change
|
||||||
|
internal void BeforeFieldsChange()
|
||||||
|
{
|
||||||
|
BeforePropsChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -204,7 +204,6 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
{
|
{
|
||||||
// Already set isdisposed so that changes can be prohibited
|
// Already set isdisposed so that changes can be prohibited
|
||||||
isdisposed = true;
|
isdisposed = true;
|
||||||
autoremove = false;
|
|
||||||
BeginAddRemove();
|
BeginAddRemove();
|
||||||
|
|
||||||
// Dispose all things
|
// Dispose all things
|
||||||
|
@ -435,6 +434,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
{
|
{
|
||||||
virtualsector = newset.CreateSector();
|
virtualsector = newset.CreateSector();
|
||||||
l.Front.Sector.CopyPropertiesTo(virtualsector);
|
l.Front.Sector.CopyPropertiesTo(virtualsector);
|
||||||
|
virtualsector.Fields.BeforeFieldsChange();
|
||||||
virtualsector.Fields[VIRTUAL_SECTOR_FIELD] = new UniValue(virtualsectorvalue);
|
virtualsector.Fields[VIRTUAL_SECTOR_FIELD] = new UniValue(virtualsectorvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,6 +463,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
{
|
{
|
||||||
virtualsector = newset.CreateSector();
|
virtualsector = newset.CreateSector();
|
||||||
l.Back.Sector.CopyPropertiesTo(virtualsector);
|
l.Back.Sector.CopyPropertiesTo(virtualsector);
|
||||||
|
virtualsector.Fields.BeforeFieldsChange();
|
||||||
virtualsector.Fields[VIRTUAL_SECTOR_FIELD] = new UniValue(virtualsectorvalue);
|
virtualsector.Fields[VIRTUAL_SECTOR_FIELD] = new UniValue(virtualsectorvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,24 +510,6 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This creates a new vertex from a stream
|
|
||||||
private Vertex CreateVertex(IReadWriteStream stream)
|
|
||||||
{
|
|
||||||
// Make the vertex
|
|
||||||
Vertex v = new Vertex(this, numvertices, stream);
|
|
||||||
AddItem(v, ref vertices, numvertices, ref numvertices);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This creates a new vertex from a stream
|
|
||||||
private Vertex CreateVertex(int index, IReadWriteStream stream)
|
|
||||||
{
|
|
||||||
// Make the vertex
|
|
||||||
Vertex v = new Vertex(this, index, stream);
|
|
||||||
AddItem(v, ref vertices, index, ref numvertices);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>This creates a new linedef and returns it.</summary>
|
/// <summary>This creates a new linedef and returns it.</summary>
|
||||||
public Linedef CreateLinedef(Vertex start, Vertex end)
|
public Linedef CreateLinedef(Vertex start, Vertex end)
|
||||||
{
|
{
|
||||||
|
@ -545,24 +528,6 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This creates a new linedef from a stream
|
|
||||||
private Linedef CreateLinedef(Vertex start, Vertex end, IReadWriteStream stream)
|
|
||||||
{
|
|
||||||
// Make the linedef
|
|
||||||
Linedef l = new Linedef(this, numlinedefs, start, end, stream);
|
|
||||||
AddItem(l, ref linedefs, numlinedefs, ref numlinedefs);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This creates a new linedef from a stream
|
|
||||||
private Linedef CreateLinedef(int index, Vertex start, Vertex end, IReadWriteStream stream)
|
|
||||||
{
|
|
||||||
// Make the linedef
|
|
||||||
Linedef l = new Linedef(this, index, start, end, stream);
|
|
||||||
AddItem(l, ref linedefs, index, ref numlinedefs);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>This creates a new sidedef and returns it.</summary>
|
/// <summary>This creates a new sidedef and returns it.</summary>
|
||||||
public Sidedef CreateSidedef(Linedef l, bool front, Sector s)
|
public Sidedef CreateSidedef(Linedef l, bool front, Sector s)
|
||||||
{
|
{
|
||||||
|
@ -581,24 +546,6 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
return sd;
|
return sd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This creates a new sidedef from a stream
|
|
||||||
private Sidedef CreateSidedef(Linedef l, bool front, Sector s, IReadWriteStream stream)
|
|
||||||
{
|
|
||||||
// Make the sidedef
|
|
||||||
Sidedef sd = new Sidedef(this, numsidedefs, l, front, s, stream);
|
|
||||||
AddItem(sd, ref sidedefs, numsidedefs, ref numsidedefs);
|
|
||||||
return sd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This creates a new sidedef from a stream
|
|
||||||
private Sidedef CreateSidedef(int index, Linedef l, bool front, Sector s, IReadWriteStream stream)
|
|
||||||
{
|
|
||||||
// Make the sidedef
|
|
||||||
Sidedef sd = new Sidedef(this, index, l, front, s, stream);
|
|
||||||
AddItem(sd, ref sidedefs, index, ref numsidedefs);
|
|
||||||
return sd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>This creates a new sector and returns it.</summary>
|
/// <summary>This creates a new sector and returns it.</summary>
|
||||||
public Sector CreateSector()
|
public Sector CreateSector()
|
||||||
{
|
{
|
||||||
|
@ -637,15 +584,6 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This creates a new sector from a stream
|
|
||||||
private Sector CreateSector(IReadWriteStream stream)
|
|
||||||
{
|
|
||||||
// Make the sector
|
|
||||||
Sector s = new Sector(this, numsectors, stream);
|
|
||||||
AddItem(s, ref sectors, numsectors, ref numsectors);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>This creates a new thing and returns it.</summary>
|
/// <summary>This creates a new thing and returns it.</summary>
|
||||||
public Thing CreateThing()
|
public Thing CreateThing()
|
||||||
{
|
{
|
||||||
|
@ -919,7 +857,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Go for all vertices
|
// Go for all vertices
|
||||||
for(int i = 0; i < c; i++)
|
for(int i = 0; i < c; i++)
|
||||||
{
|
{
|
||||||
array[i] = CreateVertex(stream);
|
array[i] = CreateVertex(new Vector2D());
|
||||||
|
array[i].ReadWrite(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
|
@ -941,7 +880,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
|
|
||||||
stream.rInt(out end);
|
stream.rInt(out end);
|
||||||
|
|
||||||
array[i] = CreateLinedef(verticesarray[start], verticesarray[end], stream);
|
array[i] = CreateLinedef(verticesarray[start], verticesarray[end]);
|
||||||
|
array[i].ReadWrite(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
|
@ -964,7 +904,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
|
|
||||||
stream.rBool(out front);
|
stream.rBool(out front);
|
||||||
|
|
||||||
CreateSidedef(linedefsarray[lineindex], front, sectorsarray[sectorindex], stream);
|
Sidedef sd = CreateSidedef(linedefsarray[lineindex], front, sectorsarray[sectorindex]);
|
||||||
|
sd.ReadWrite(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -978,7 +919,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Go for all sectors
|
// Go for all sectors
|
||||||
for(int i = 0; i < c; i++)
|
for(int i = 0; i < c; i++)
|
||||||
{
|
{
|
||||||
array[i] = CreateSector(stream);
|
array[i] = CreateSector();
|
||||||
|
array[i].ReadWrite(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
|
@ -2677,14 +2619,14 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
{
|
{
|
||||||
// Replace with stored sidedef
|
// Replace with stored sidedef
|
||||||
bool isfront = snsd.IsFront;
|
bool isfront = snsd.IsFront;
|
||||||
snsd.Line.DetachSidedef(snsd);
|
snsd.Line.DetachSidedefP(snsd);
|
||||||
if(isfront)
|
if(isfront)
|
||||||
snsd.Line.AttachFront(stored);
|
snsd.Line.AttachFront(stored);
|
||||||
else
|
else
|
||||||
snsd.Line.AttachBack(stored);
|
snsd.Line.AttachBack(stored);
|
||||||
|
|
||||||
// Remove the sidedef
|
// Remove the sidedef
|
||||||
snsd.ChangeSector(null);
|
snsd.SetSector(null);
|
||||||
RemoveSidedef(sn);
|
RemoveSidedef(sn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -86,15 +86,15 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
/// An unique index that does not change when other sectors are removed.
|
/// An unique index that does not change when other sectors are removed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int FixedIndex { get { return fixedindex; } }
|
public int FixedIndex { get { return fixedindex; } }
|
||||||
public int FloorHeight { get { return floorheight; } set { floorheight = value; } }
|
public int FloorHeight { get { return floorheight; } set { BeforePropsChange(); floorheight = value; } }
|
||||||
public int CeilHeight { get { return ceilheight; } set { ceilheight = value; } }
|
public int CeilHeight { get { return ceilheight; } set { BeforePropsChange(); ceilheight = value; } }
|
||||||
public string FloorTexture { get { return floortexname; } }
|
public string FloorTexture { get { return floortexname; } }
|
||||||
public string CeilTexture { get { return ceiltexname; } }
|
public string CeilTexture { get { return ceiltexname; } }
|
||||||
public long LongFloorTexture { get { return longfloortexname; } }
|
public long LongFloorTexture { get { return longfloortexname; } }
|
||||||
public long LongCeilTexture { get { return longceiltexname; } }
|
public long LongCeilTexture { get { return longceiltexname; } }
|
||||||
public int Effect { get { return effect; } set { effect = value; } }
|
public int Effect { get { return effect; } set { BeforePropsChange(); effect = value; } }
|
||||||
public int Tag { get { return tag; } set { tag = value; if((tag < General.Map.FormatInterface.MinTag) || (tag > General.Map.FormatInterface.MaxTag)) throw new ArgumentOutOfRangeException("Tag", "Invalid tag number"); } }
|
public int Tag { get { return tag; } set { BeforePropsChange(); tag = value; if((tag < General.Map.FormatInterface.MinTag) || (tag > General.Map.FormatInterface.MaxTag)) throw new ArgumentOutOfRangeException("Tag", "Invalid tag number"); } }
|
||||||
public int Brightness { get { return brightness; } set { brightness = value; updateneeded = true; } }
|
public int Brightness { get { return brightness; } set { BeforePropsChange(); brightness = value; updateneeded = true; } }
|
||||||
public bool UpdateNeeded { get { return updateneeded; } set { updateneeded |= value; triangulationneeded |= value; } }
|
public bool UpdateNeeded { get { return updateneeded; } set { updateneeded |= value; triangulationneeded |= value; } }
|
||||||
public RectangleF BBox { get { return bbox; } }
|
public RectangleF BBox { get { return bbox; } }
|
||||||
internal Sector Clone { get { return clone; } set { clone = value; } }
|
internal Sector Clone { get { return clone; } set { clone = value; } }
|
||||||
|
@ -122,21 +122,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
this.triangulationneeded = true;
|
this.triangulationneeded = true;
|
||||||
this.surfaceentry = new SurfaceEntry(-1, -1, -1);
|
this.surfaceentry = new SurfaceEntry(-1, -1, -1);
|
||||||
|
|
||||||
// We have no destructor
|
if(map == General.Map.Map)
|
||||||
GC.SuppressFinalize(this);
|
General.Map.UndoRedo.RecAddSector(this);
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
internal Sector(MapSet map, int listindex, IReadWriteStream stream)
|
|
||||||
{
|
|
||||||
// Initialize
|
|
||||||
this.map = map;
|
|
||||||
this.listindex = listindex;
|
|
||||||
this.sidedefs = new LinkedList<Sidedef>();
|
|
||||||
this.triangulationneeded = true;
|
|
||||||
this.surfaceentry = new SurfaceEntry(-1, -1, -1);
|
|
||||||
|
|
||||||
ReadWrite(stream);
|
|
||||||
|
|
||||||
// We have no destructor
|
// We have no destructor
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
|
@ -151,6 +138,9 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Already set isdisposed so that changes can be prohibited
|
// Already set isdisposed so that changes can be prohibited
|
||||||
isdisposed = true;
|
isdisposed = true;
|
||||||
|
|
||||||
|
if(map == General.Map.Map)
|
||||||
|
General.Map.UndoRedo.RecRemSector(this);
|
||||||
|
|
||||||
// Remove from main list
|
// Remove from main list
|
||||||
map.RemoveSector(listindex);
|
map.RemoveSector(listindex);
|
||||||
|
|
||||||
|
@ -161,6 +151,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// because a sidedef cannot exist without reference to its sector.
|
// because a sidedef cannot exist without reference to its sector.
|
||||||
if(map.AutoRemove)
|
if(map.AutoRemove)
|
||||||
foreach(Sidedef sd in sidedefs) sd.Dispose();
|
foreach(Sidedef sd in sidedefs) sd.Dispose();
|
||||||
|
else
|
||||||
|
foreach(Sidedef sd in sidedefs) sd.SetSectorP(null);
|
||||||
|
|
||||||
// Free surface entry
|
// Free surface entry
|
||||||
General.Map.CRenderer2D.Surfaces.FreeSurfaces(surfaceentry);
|
General.Map.CRenderer2D.Surfaces.FreeSurfaces(surfaceentry);
|
||||||
|
@ -178,9 +170,18 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
|
|
||||||
#region ================== Management
|
#region ================== Management
|
||||||
|
|
||||||
// Serialize / deserialize
|
// Call this before changing properties
|
||||||
|
protected override void BeforePropsChange()
|
||||||
|
{
|
||||||
|
if(map == General.Map.Map)
|
||||||
|
General.Map.UndoRedo.RecPrpSector(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize / deserialize (passive: this doesn't record)
|
||||||
internal void ReadWrite(IReadWriteStream s)
|
internal void ReadWrite(IReadWriteStream s)
|
||||||
{
|
{
|
||||||
|
if(!s.IsWriting) BeforePropsChange();
|
||||||
|
|
||||||
base.ReadWrite(s);
|
base.ReadWrite(s);
|
||||||
|
|
||||||
s.rwInt(ref fixedindex);
|
s.rwInt(ref fixedindex);
|
||||||
|
@ -188,39 +189,11 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
s.rwInt(ref ceilheight);
|
s.rwInt(ref ceilheight);
|
||||||
s.rwString(ref floortexname);
|
s.rwString(ref floortexname);
|
||||||
s.rwString(ref ceiltexname);
|
s.rwString(ref ceiltexname);
|
||||||
//s.rwLong(ref longfloortexname);
|
s.rwLong(ref longfloortexname);
|
||||||
//s.rwLong(ref longceiltexname);
|
s.rwLong(ref longceiltexname);
|
||||||
s.rwInt(ref effect);
|
s.rwInt(ref effect);
|
||||||
s.rwInt(ref tag);
|
s.rwInt(ref tag);
|
||||||
s.rwInt(ref brightness);
|
s.rwInt(ref brightness);
|
||||||
|
|
||||||
// Use a new triangulator when reading from stream
|
|
||||||
if(!s.IsWriting && (triangles == null)) triangles = new Triangulation();
|
|
||||||
triangles.ReadWrite(s);
|
|
||||||
|
|
||||||
if(s.IsWriting)
|
|
||||||
{
|
|
||||||
s.wInt(labels.Count);
|
|
||||||
for(int i = 0; i < labels.Count; i++)
|
|
||||||
{
|
|
||||||
s.wVector2D(labels[i].position);
|
|
||||||
s.wFloat(labels[i].radius);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
longfloortexname = Lump.MakeLongName(floortexname);
|
|
||||||
longceiltexname = Lump.MakeLongName(ceiltexname);
|
|
||||||
|
|
||||||
int c; s.rInt(out c);
|
|
||||||
LabelPositionInfo[] labelsarray = new LabelPositionInfo[c];
|
|
||||||
for(int i = 0; i < c; i++)
|
|
||||||
{
|
|
||||||
s.rVector2D(out labelsarray[i].position);
|
|
||||||
s.rFloat(out labelsarray[i].radius);
|
|
||||||
}
|
|
||||||
labels = Array.AsReadOnly<LabelPositionInfo>(labelsarray);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// After deserialization
|
// After deserialization
|
||||||
|
@ -237,6 +210,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This copies all properties to another sector
|
// This copies all properties to another sector
|
||||||
public void CopyPropertiesTo(Sector s)
|
public void CopyPropertiesTo(Sector s)
|
||||||
{
|
{
|
||||||
|
s.BeforePropsChange();
|
||||||
|
|
||||||
// Copy properties
|
// Copy properties
|
||||||
s.ceilheight = ceilheight;
|
s.ceilheight = ceilheight;
|
||||||
s.ceiltexname = ceiltexname;
|
s.ceiltexname = ceiltexname;
|
||||||
|
@ -252,7 +227,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
// This attaches a sidedef and returns the listitem
|
// This attaches a sidedef and returns the listitem
|
||||||
public LinkedListNode<Sidedef> AttachSidedef(Sidedef sd)
|
internal LinkedListNode<Sidedef> AttachSidedefP(Sidedef sd)
|
||||||
{
|
{
|
||||||
updateneeded = true;
|
updateneeded = true;
|
||||||
triangulationneeded = true;
|
triangulationneeded = true;
|
||||||
|
@ -260,7 +235,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
// This detaches a sidedef
|
// This detaches a sidedef
|
||||||
public void DetachSidedef(LinkedListNode<Sidedef> l)
|
internal void DetachSidedefP(LinkedListNode<Sidedef> l)
|
||||||
{
|
{
|
||||||
// Not disposing?
|
// Not disposing?
|
||||||
if(!isdisposed)
|
if(!isdisposed)
|
||||||
|
@ -357,6 +332,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This updates the floor surface
|
// This updates the floor surface
|
||||||
public void UpdateFloorSurface()
|
public void UpdateFloorSurface()
|
||||||
{
|
{
|
||||||
|
if(flatvertices == null) return;
|
||||||
|
|
||||||
// Create floor vertices
|
// Create floor vertices
|
||||||
FlatVertex[] floorvertices = new FlatVertex[flatvertices.Length];
|
FlatVertex[] floorvertices = new FlatVertex[flatvertices.Length];
|
||||||
flatvertices.CopyTo(floorvertices, 0);
|
flatvertices.CopyTo(floorvertices, 0);
|
||||||
|
@ -372,6 +349,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This updates the ceiling surface
|
// This updates the ceiling surface
|
||||||
public void UpdateCeilingSurface()
|
public void UpdateCeilingSurface()
|
||||||
{
|
{
|
||||||
|
if(flatvertices == null) return;
|
||||||
|
|
||||||
// Create ceiling vertices
|
// Create ceiling vertices
|
||||||
FlatVertex[] ceilvertices = new FlatVertex[flatvertices.Length];
|
FlatVertex[] ceilvertices = new FlatVertex[flatvertices.Length];
|
||||||
flatvertices.CopyTo(ceilvertices, 0);
|
flatvertices.CopyTo(ceilvertices, 0);
|
||||||
|
@ -484,7 +463,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Change secter reference on my sidedefs
|
// Change secter reference on my sidedefs
|
||||||
// This automatically disposes this sector
|
// This automatically disposes this sector
|
||||||
while(sidedefs != null)
|
while(sidedefs != null)
|
||||||
sidedefs.First.Value.ChangeSector(other);
|
sidedefs.First.Value.SetSector(other);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -509,6 +488,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This updates all properties
|
// This updates all properties
|
||||||
public void Update(int hfloor, int hceil, string tfloor, string tceil, int effect, int tag, int brightness)
|
public void Update(int hfloor, int hceil, string tfloor, string tceil, int effect, int tag, int brightness)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
// Apply changes
|
// Apply changes
|
||||||
this.floorheight = hfloor;
|
this.floorheight = hfloor;
|
||||||
this.ceilheight = hceil;
|
this.ceilheight = hceil;
|
||||||
|
@ -523,6 +504,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This sets texture
|
// This sets texture
|
||||||
public void SetFloorTexture(string name)
|
public void SetFloorTexture(string name)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
floortexname = name;
|
floortexname = name;
|
||||||
longfloortexname = Lump.MakeLongName(name);
|
longfloortexname = Lump.MakeLongName(name);
|
||||||
updateneeded = true;
|
updateneeded = true;
|
||||||
|
@ -532,6 +515,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This sets texture
|
// This sets texture
|
||||||
public void SetCeilTexture(string name)
|
public void SetCeilTexture(string name)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
ceiltexname = name;
|
ceiltexname = name;
|
||||||
longceiltexname = Lump.MakeLongName(name);
|
longceiltexname = Lump.MakeLongName(name);
|
||||||
updateneeded = true;
|
updateneeded = true;
|
||||||
|
|
|
@ -67,13 +67,13 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
#region ================== Properties
|
#region ================== Properties
|
||||||
|
|
||||||
public MapSet Map { get { return map; } }
|
public MapSet Map { get { return map; } }
|
||||||
public bool IsFront { get { return (this == linedef.Front); } }
|
public bool IsFront { get { return (linedef != null) ? (this == linedef.Front) : false; } }
|
||||||
public Linedef Line { get { return linedef; } }
|
public Linedef Line { get { return linedef; } }
|
||||||
public Sidedef Other { get { if(this == linedef.Front) return linedef.Back; else return linedef.Front; } }
|
public Sidedef Other { get { if(this == linedef.Front) return linedef.Back; else return linedef.Front; } }
|
||||||
public Sector Sector { get { return sector; } }
|
public Sector Sector { get { return sector; } }
|
||||||
public float Angle { get { if(IsFront) return linedef.Angle; else return Angle2D.Normalized(linedef.Angle + Angle2D.PI); } }
|
public float Angle { get { if(IsFront) return linedef.Angle; else return Angle2D.Normalized(linedef.Angle + Angle2D.PI); } }
|
||||||
public int OffsetX { get { return offsetx; } set { offsetx = value; } }
|
public int OffsetX { get { return offsetx; } set { BeforePropsChange(); offsetx = value; } }
|
||||||
public int OffsetY { get { return offsety; } set { offsety = value; } }
|
public int OffsetY { get { return offsety; } set { BeforePropsChange(); offsety = value; } }
|
||||||
public string HighTexture { get { return texnamehigh; } }
|
public string HighTexture { get { return texnamehigh; } }
|
||||||
public string MiddleTexture { get { return texnamemid; } }
|
public string MiddleTexture { get { return texnamemid; } }
|
||||||
public string LowTexture { get { return texnamelow; } }
|
public string LowTexture { get { return texnamelow; } }
|
||||||
|
@ -92,8 +92,6 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Initialize
|
// Initialize
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.listindex = listindex;
|
this.listindex = listindex;
|
||||||
this.linedef = l;
|
|
||||||
this.sector = s;
|
|
||||||
this.texnamehigh = "-";
|
this.texnamehigh = "-";
|
||||||
this.texnamemid = "-";
|
this.texnamemid = "-";
|
||||||
this.texnamelow = "-";
|
this.texnamelow = "-";
|
||||||
|
@ -101,32 +99,21 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
this.longtexnamemid = MapSet.EmptyLongName;
|
this.longtexnamemid = MapSet.EmptyLongName;
|
||||||
this.longtexnamelow = MapSet.EmptyLongName;
|
this.longtexnamelow = MapSet.EmptyLongName;
|
||||||
|
|
||||||
// Attach to the linedef
|
// Attach linedef
|
||||||
if(front) l.AttachFront(this); else l.AttachBack(this);
|
this.linedef = l;
|
||||||
|
if(l != null)
|
||||||
// Attach to sector
|
{
|
||||||
sectorlistitem = s.AttachSidedef(this);
|
if(front)
|
||||||
|
l.AttachFrontP(this);
|
||||||
// We have no destructor
|
else
|
||||||
GC.SuppressFinalize(this);
|
l.AttachBackP(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor
|
// Attach sector
|
||||||
internal Sidedef(MapSet map, int listindex, Linedef l, bool front, Sector s, IReadWriteStream stream)
|
SetSectorP(s);
|
||||||
{
|
|
||||||
// Initialize
|
|
||||||
this.map = map;
|
|
||||||
this.listindex = listindex;
|
|
||||||
this.linedef = l;
|
|
||||||
this.sector = s;
|
|
||||||
|
|
||||||
// Attach to the linedef
|
if(map == General.Map.Map)
|
||||||
if(front) l.AttachFront(this); else l.AttachBack(this);
|
General.Map.UndoRedo.RecAddSidedef(this);
|
||||||
|
|
||||||
// Attach to sector
|
|
||||||
sectorlistitem = s.AttachSidedef(this);
|
|
||||||
|
|
||||||
ReadWrite(stream);
|
|
||||||
|
|
||||||
// We have no destructor
|
// We have no destructor
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
|
@ -141,14 +128,17 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Already set isdisposed so that changes can be prohibited
|
// Already set isdisposed so that changes can be prohibited
|
||||||
isdisposed = true;
|
isdisposed = true;
|
||||||
|
|
||||||
|
if(map == General.Map.Map)
|
||||||
|
General.Map.UndoRedo.RecRemSidedef(this);
|
||||||
|
|
||||||
// Remove from main list
|
// Remove from main list
|
||||||
map.RemoveSidedef(listindex);
|
map.RemoveSidedef(listindex);
|
||||||
|
|
||||||
// Detach from linedef
|
// Detach from linedef
|
||||||
linedef.DetachSidedef(this);
|
if(linedef != null) linedef.DetachSidedefP(this);
|
||||||
|
|
||||||
// Detach from sector
|
// Detach from sector
|
||||||
sector.DetachSidedef(sectorlistitem);
|
SetSectorP(null);
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
sectorlistitem = null;
|
sectorlistitem = null;
|
||||||
|
@ -165,9 +155,18 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
|
|
||||||
#region ================== Management
|
#region ================== Management
|
||||||
|
|
||||||
// Serialize / deserialize
|
// Call this before changing properties
|
||||||
|
protected override void BeforePropsChange()
|
||||||
|
{
|
||||||
|
if(map == General.Map.Map)
|
||||||
|
General.Map.UndoRedo.RecPrpSidedef(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize / deserialize (passive: this doesn't record)
|
||||||
internal void ReadWrite(IReadWriteStream s)
|
internal void ReadWrite(IReadWriteStream s)
|
||||||
{
|
{
|
||||||
|
if(!s.IsWriting) BeforePropsChange();
|
||||||
|
|
||||||
base.ReadWrite(s);
|
base.ReadWrite(s);
|
||||||
|
|
||||||
s.rwInt(ref offsetx);
|
s.rwInt(ref offsetx);
|
||||||
|
@ -175,20 +174,16 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
s.rwString(ref texnamehigh);
|
s.rwString(ref texnamehigh);
|
||||||
s.rwString(ref texnamemid);
|
s.rwString(ref texnamemid);
|
||||||
s.rwString(ref texnamelow);
|
s.rwString(ref texnamelow);
|
||||||
//s.rwLong(ref longtexnamehigh);
|
s.rwLong(ref longtexnamehigh);
|
||||||
//s.rwLong(ref longtexnamemid);
|
s.rwLong(ref longtexnamemid);
|
||||||
//s.rwLong(ref longtexnamelow);
|
s.rwLong(ref longtexnamelow);
|
||||||
if(!s.IsWriting)
|
|
||||||
{
|
|
||||||
longtexnamehigh = Lump.MakeLongName(texnamehigh);
|
|
||||||
longtexnamemid = Lump.MakeLongName(texnamemid);
|
|
||||||
longtexnamelow = Lump.MakeLongName(texnamelow);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This copies all properties to another sidedef
|
// This copies all properties to another sidedef
|
||||||
public void CopyPropertiesTo(Sidedef s)
|
public void CopyPropertiesTo(Sidedef s)
|
||||||
{
|
{
|
||||||
|
s.BeforePropsChange();
|
||||||
|
|
||||||
// Copy properties
|
// Copy properties
|
||||||
s.offsetx = offsetx;
|
s.offsetx = offsetx;
|
||||||
s.offsety = offsety;
|
s.offsety = offsety;
|
||||||
|
@ -201,73 +196,51 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
base.CopyPropertiesTo(s);
|
base.CopyPropertiesTo(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This creates a checksum from the sidedef properties
|
// This changes sector
|
||||||
// Used for faster sidedefs compression
|
public void SetSector(Sector newsector)
|
||||||
public uint GetChecksum()
|
|
||||||
{
|
{
|
||||||
CRC crc = new CRC();
|
if(map == General.Map.Map)
|
||||||
crc.Add(sector.FixedIndex);
|
General.Map.UndoRedo.RecRefSidedefSector(this);
|
||||||
crc.Add(offsetx);
|
|
||||||
crc.Add(offsety);
|
// Change sector
|
||||||
crc.Add(longtexnamehigh);
|
SetSectorP(newsector);
|
||||||
crc.Add(longtexnamelow);
|
|
||||||
crc.Add(longtexnamemid);
|
|
||||||
return (uint)(crc.Value & 0x00000000FFFFFFFF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This copies textures to another sidedef
|
internal void SetSectorP(Sector newsector)
|
||||||
// And possibly also the offsets
|
|
||||||
public void AddTexturesTo(Sidedef s)
|
|
||||||
{
|
{
|
||||||
int copyoffsets = 0;
|
// Detach from sector
|
||||||
|
if(sector != null) sector.DetachSidedefP(sectorlistitem);
|
||||||
|
|
||||||
// s cannot be null
|
// Change sector
|
||||||
if(s == null) return;
|
sector = newsector;
|
||||||
|
|
||||||
// Upper texture set?
|
// Attach to sector
|
||||||
if((texnamehigh.Length > 0) && (texnamehigh[0] != '-'))
|
if(sector != null)
|
||||||
{
|
sectorlistitem = sector.AttachSidedefP(this);
|
||||||
// Copy upper texture
|
|
||||||
s.texnamehigh = texnamehigh;
|
|
||||||
s.longtexnamehigh = longtexnamehigh;
|
|
||||||
|
|
||||||
// Counts as a half coice for copying offsets
|
|
||||||
copyoffsets += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Middle texture set?
|
|
||||||
if((texnamemid.Length > 0) && (texnamemid[0] != '-'))
|
|
||||||
{
|
|
||||||
// Copy middle texture
|
|
||||||
s.texnamemid = texnamemid;
|
|
||||||
s.longtexnamemid = longtexnamemid;
|
|
||||||
|
|
||||||
// Counts for copying offsets
|
|
||||||
copyoffsets += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lower texture set?
|
|
||||||
if((texnamelow.Length > 0) && (texnamelow[0] != '-'))
|
|
||||||
{
|
|
||||||
// Copy middle texture
|
|
||||||
s.texnamelow = texnamelow;
|
|
||||||
s.longtexnamelow = longtexnamelow;
|
|
||||||
|
|
||||||
// Counts as a half coice for copying offsets
|
|
||||||
copyoffsets += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy offsets also?
|
|
||||||
if(copyoffsets >= 2)
|
|
||||||
{
|
|
||||||
// Copy offsets
|
|
||||||
s.offsetx = offsetx;
|
|
||||||
s.offsety = offsety;
|
|
||||||
}
|
|
||||||
|
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This sets the linedef
|
||||||
|
public void SetLinedef(Linedef ld, bool front)
|
||||||
|
{
|
||||||
|
if(linedef != null) linedef.DetachSidedefP(this);
|
||||||
|
|
||||||
|
if(ld != null)
|
||||||
|
{
|
||||||
|
if(front)
|
||||||
|
ld.AttachFront(this);
|
||||||
|
else
|
||||||
|
ld.AttachBack(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This sets the linedef (passive: this doesn't tell the linedef and doesn't record)
|
||||||
|
internal void SetLinedefP(Linedef ld)
|
||||||
|
{
|
||||||
|
linedef = ld;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Methods
|
#region ================== Methods
|
||||||
|
@ -281,6 +254,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This removes textures that are not required
|
// This removes textures that are not required
|
||||||
public void RemoveUnneededTextures(bool removemiddle, bool force)
|
public void RemoveUnneededTextures(bool removemiddle, bool force)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
// The middle texture can be removed regardless of any sector tag or linedef action
|
// The middle texture can be removed regardless of any sector tag or linedef action
|
||||||
if(!MiddleRequired() && removemiddle)
|
if(!MiddleRequired() && removemiddle)
|
||||||
{
|
{
|
||||||
|
@ -348,6 +323,75 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This creates a checksum from the sidedef properties
|
||||||
|
// Used for faster sidedefs compression
|
||||||
|
public uint GetChecksum()
|
||||||
|
{
|
||||||
|
CRC crc = new CRC();
|
||||||
|
crc.Add(sector.FixedIndex);
|
||||||
|
crc.Add(offsetx);
|
||||||
|
crc.Add(offsety);
|
||||||
|
crc.Add(longtexnamehigh);
|
||||||
|
crc.Add(longtexnamelow);
|
||||||
|
crc.Add(longtexnamemid);
|
||||||
|
return (uint)(crc.Value & 0x00000000FFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This copies textures to another sidedef
|
||||||
|
// And possibly also the offsets
|
||||||
|
public void AddTexturesTo(Sidedef s)
|
||||||
|
{
|
||||||
|
int copyoffsets = 0;
|
||||||
|
|
||||||
|
// s cannot be null
|
||||||
|
if(s == null) return;
|
||||||
|
|
||||||
|
s.BeforePropsChange();
|
||||||
|
|
||||||
|
// Upper texture set?
|
||||||
|
if((texnamehigh.Length > 0) && (texnamehigh[0] != '-'))
|
||||||
|
{
|
||||||
|
// Copy upper texture
|
||||||
|
s.texnamehigh = texnamehigh;
|
||||||
|
s.longtexnamehigh = longtexnamehigh;
|
||||||
|
|
||||||
|
// Counts as a half coice for copying offsets
|
||||||
|
copyoffsets += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Middle texture set?
|
||||||
|
if((texnamemid.Length > 0) && (texnamemid[0] != '-'))
|
||||||
|
{
|
||||||
|
// Copy middle texture
|
||||||
|
s.texnamemid = texnamemid;
|
||||||
|
s.longtexnamemid = longtexnamemid;
|
||||||
|
|
||||||
|
// Counts for copying offsets
|
||||||
|
copyoffsets += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lower texture set?
|
||||||
|
if((texnamelow.Length > 0) && (texnamelow[0] != '-'))
|
||||||
|
{
|
||||||
|
// Copy middle texture
|
||||||
|
s.texnamelow = texnamelow;
|
||||||
|
s.longtexnamelow = longtexnamelow;
|
||||||
|
|
||||||
|
// Counts as a half coice for copying offsets
|
||||||
|
copyoffsets += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy offsets also?
|
||||||
|
if(copyoffsets >= 2)
|
||||||
|
{
|
||||||
|
// Copy offsets
|
||||||
|
s.offsetx = offsetx;
|
||||||
|
s.offsety = offsety;
|
||||||
|
}
|
||||||
|
|
||||||
|
General.Map.IsChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Changes
|
#region ================== Changes
|
||||||
|
@ -355,6 +399,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This updates all properties
|
// This updates all properties
|
||||||
public void Update(int offsetx, int offsety, string thigh, string tmid, string tlow)
|
public void Update(int offsetx, int offsety, string thigh, string tmid, string tlow)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
// Apply changes
|
// Apply changes
|
||||||
this.offsetx = offsetx;
|
this.offsetx = offsetx;
|
||||||
this.offsety = offsety;
|
this.offsety = offsety;
|
||||||
|
@ -366,6 +412,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This sets texture
|
// This sets texture
|
||||||
public void SetTextureHigh(string name)
|
public void SetTextureHigh(string name)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
texnamehigh = name;
|
texnamehigh = name;
|
||||||
longtexnamehigh = Lump.MakeLongName(name);
|
longtexnamehigh = Lump.MakeLongName(name);
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
|
@ -374,6 +422,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This sets texture
|
// This sets texture
|
||||||
public void SetTextureMid(string name)
|
public void SetTextureMid(string name)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
texnamemid = name;
|
texnamemid = name;
|
||||||
longtexnamemid = Lump.MakeLongName(name);
|
longtexnamemid = Lump.MakeLongName(name);
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
|
@ -382,27 +432,13 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This sets texture
|
// This sets texture
|
||||||
public void SetTextureLow(string name)
|
public void SetTextureLow(string name)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
texnamelow = name;
|
texnamelow = name;
|
||||||
longtexnamelow = Lump.MakeLongName(name);
|
longtexnamelow = Lump.MakeLongName(name);
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This changes sector
|
|
||||||
public void ChangeSector(Sector newsector)
|
|
||||||
{
|
|
||||||
// Detach from sector
|
|
||||||
sector.DetachSidedef(sectorlistitem);
|
|
||||||
|
|
||||||
// Change sector
|
|
||||||
sector = newsector;
|
|
||||||
|
|
||||||
// Attach to sector
|
|
||||||
if(sector != null)
|
|
||||||
sectorlistitem = sector.AttachSidedef(this);
|
|
||||||
|
|
||||||
General.Map.IsChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,18 +71,18 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
#region ================== Properties
|
#region ================== Properties
|
||||||
|
|
||||||
public MapSet Map { get { return map; } }
|
public MapSet Map { get { return map; } }
|
||||||
public int Type { get { return type; } set { type = value; } }
|
public int Type { get { return type; } set { BeforePropsChange(); type = value; } }
|
||||||
public Vector3D Position { get { return pos; } }
|
public Vector3D Position { get { return pos; } }
|
||||||
public float Angle { get { return angle; } }
|
public float Angle { get { return angle; } }
|
||||||
public int AngleDeg { get { return (int)Angle2D.RadToDeg(angle); } }
|
public int AngleDeg { get { return (int)Angle2D.RadToDeg(angle); } }
|
||||||
public Dictionary<string, bool> Flags { get { return flags; } }
|
internal Dictionary<string, bool> Flags { get { return flags; } }
|
||||||
public int Action { get { return action; } set { action = value; } }
|
public int Action { get { return action; } set { BeforePropsChange(); action = value; } }
|
||||||
public int[] Args { get { return args; } }
|
public int[] Args { get { return args; } }
|
||||||
public float Size { get { return size; } }
|
public float Size { get { return size; } }
|
||||||
public float IconOffset { get { return iconoffset; } }
|
public float IconOffset { get { return iconoffset; } }
|
||||||
public PixelColor Color { get { return color; } }
|
public PixelColor Color { get { return color; } }
|
||||||
public bool FixedSize { get { return fixedsize; } }
|
public bool FixedSize { get { return fixedsize; } }
|
||||||
public int Tag { get { return tag; } set { tag = value; if((tag < General.Map.FormatInterface.MinTag) || (tag > General.Map.FormatInterface.MaxTag)) throw new ArgumentOutOfRangeException("Tag", "Invalid tag number"); } }
|
public int Tag { get { return tag; } set { BeforePropsChange(); tag = value; if((tag < General.Map.FormatInterface.MinTag) || (tag > General.Map.FormatInterface.MaxTag)) throw new ArgumentOutOfRangeException("Tag", "Invalid tag number"); } }
|
||||||
public Sector Sector { get { return sector; } }
|
public Sector Sector { get { return sector; } }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -98,6 +98,9 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
this.flags = new Dictionary<string, bool>();
|
this.flags = new Dictionary<string, bool>();
|
||||||
this.args = new int[NUM_ARGS];
|
this.args = new int[NUM_ARGS];
|
||||||
|
|
||||||
|
if(map == General.Map.Map)
|
||||||
|
General.Map.UndoRedo.RecAddThing(this);
|
||||||
|
|
||||||
// We have no destructor
|
// We have no destructor
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
@ -111,6 +114,9 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Already set isdisposed so that changes can be prohibited
|
// Already set isdisposed so that changes can be prohibited
|
||||||
isdisposed = true;
|
isdisposed = true;
|
||||||
|
|
||||||
|
if(map == General.Map.Map)
|
||||||
|
General.Map.UndoRedo.RecRemThing(this);
|
||||||
|
|
||||||
// Remove from main list
|
// Remove from main list
|
||||||
map.RemoveThing(listindex);
|
map.RemoveThing(listindex);
|
||||||
|
|
||||||
|
@ -130,9 +136,18 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
|
|
||||||
#region ================== Management
|
#region ================== Management
|
||||||
|
|
||||||
|
// Call this before changing properties
|
||||||
|
protected override void BeforePropsChange()
|
||||||
|
{
|
||||||
|
if(map == General.Map.Map)
|
||||||
|
General.Map.UndoRedo.RecPrpThing(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Serialize / deserialize
|
// Serialize / deserialize
|
||||||
internal void ReadWrite(IReadWriteStream s)
|
internal void ReadWrite(IReadWriteStream s)
|
||||||
{
|
{
|
||||||
|
if(!s.IsWriting) BeforePropsChange();
|
||||||
|
|
||||||
base.ReadWrite(s);
|
base.ReadWrite(s);
|
||||||
|
|
||||||
if(s.IsWriting)
|
if(s.IsWriting)
|
||||||
|
@ -169,6 +184,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This copies all properties to another thing
|
// This copies all properties to another thing
|
||||||
public void CopyPropertiesTo(Thing t)
|
public void CopyPropertiesTo(Thing t)
|
||||||
{
|
{
|
||||||
|
t.BeforePropsChange();
|
||||||
|
|
||||||
// Copy properties
|
// Copy properties
|
||||||
t.type = type;
|
t.type = type;
|
||||||
t.angle = angle;
|
t.angle = angle;
|
||||||
|
@ -325,6 +342,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// NOTE: This does not update sector! (call DetermineSector)
|
// NOTE: This does not update sector! (call DetermineSector)
|
||||||
public void Move(Vector3D newpos)
|
public void Move(Vector3D newpos)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
// Change position
|
// Change position
|
||||||
this.pos = newpos;
|
this.pos = newpos;
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
|
@ -334,6 +353,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// NOTE: This does not update sector! (call DetermineSector)
|
// NOTE: This does not update sector! (call DetermineSector)
|
||||||
public void Move(Vector2D newpos)
|
public void Move(Vector2D newpos)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
// Change position
|
// Change position
|
||||||
this.pos = new Vector3D(newpos.x, newpos.y, pos.z);
|
this.pos = new Vector3D(newpos.x, newpos.y, pos.z);
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
|
@ -343,6 +364,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// NOTE: This does not update sector! (call DetermineSector)
|
// NOTE: This does not update sector! (call DetermineSector)
|
||||||
public void Move(float x, float y, float zoffset)
|
public void Move(float x, float y, float zoffset)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
// Change position
|
// Change position
|
||||||
this.pos = new Vector3D(x, y, zoffset);
|
this.pos = new Vector3D(x, y, zoffset);
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
|
@ -351,6 +374,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This rotates the thing
|
// This rotates the thing
|
||||||
public void Rotate(float newangle)
|
public void Rotate(float newangle)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
// Change angle
|
// Change angle
|
||||||
this.angle = newangle;
|
this.angle = newangle;
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
|
@ -404,6 +429,40 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
|
|
||||||
#region ================== Methods
|
#region ================== Methods
|
||||||
|
|
||||||
|
// This checks and returns a flag without creating it
|
||||||
|
public bool IsFlagSet(string flagname)
|
||||||
|
{
|
||||||
|
if(flags.ContainsKey(flagname))
|
||||||
|
return flags[flagname];
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This sets a flag
|
||||||
|
public void SetFlag(string flagname, bool value)
|
||||||
|
{
|
||||||
|
if(!flags.ContainsKey(flagname) || (IsFlagSet(flagname) != value))
|
||||||
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
|
flags[flagname] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This returns a copy of the flags dictionary
|
||||||
|
public Dictionary<string, bool> GetFlags()
|
||||||
|
{
|
||||||
|
return new Dictionary<string,bool>(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This clears all flags
|
||||||
|
public void ClearFlags()
|
||||||
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
|
flags.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
// This snaps the vertex to the grid
|
// This snaps the vertex to the grid
|
||||||
public void SnapToGrid()
|
public void SnapToGrid()
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,6 +15,10 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class UniFields : SortedList<string, UniValue>
|
public class UniFields : SortedList<string, UniValue>
|
||||||
{
|
{
|
||||||
|
// Owner of this list
|
||||||
|
protected MapElement owner;
|
||||||
|
public MapElement Owner { get { return owner; } internal set { owner = value; } }
|
||||||
|
|
||||||
// New constructor
|
// New constructor
|
||||||
///<summary></summary>
|
///<summary></summary>
|
||||||
public UniFields() : base(2)
|
public UniFields() : base(2)
|
||||||
|
@ -32,5 +36,33 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
public UniFields(UniFields copyfrom) : base(copyfrom)
|
public UniFields(UniFields copyfrom) : base(copyfrom)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New constructor
|
||||||
|
///<summary></summary>
|
||||||
|
public UniFields(MapElement owner) : base(2)
|
||||||
|
{
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New constructor
|
||||||
|
///<summary></summary>
|
||||||
|
public UniFields(MapElement owner, int capacity) : base(capacity)
|
||||||
|
{
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy constructor
|
||||||
|
///<summary></summary>
|
||||||
|
public UniFields(MapElement owner, UniFields copyfrom) : base(copyfrom)
|
||||||
|
{
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Call this before making changes to the fields, or they may not be updated correctly with undo/redo!</summary>
|
||||||
|
public void BeforeFieldsChange()
|
||||||
|
{
|
||||||
|
if(owner != null)
|
||||||
|
owner.BeforeFieldsChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,19 +81,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
this.listindex = listindex;
|
this.listindex = listindex;
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
|
|
||||||
// We have no destructor
|
if(map == General.Map.Map)
|
||||||
GC.SuppressFinalize(this);
|
General.Map.UndoRedo.RecAddVertex(this);
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
internal Vertex(MapSet map, int listindex, IReadWriteStream stream)
|
|
||||||
{
|
|
||||||
// Initialize
|
|
||||||
this.map = map;
|
|
||||||
this.linedefs = new LinkedList<Linedef>();
|
|
||||||
this.listindex = listindex;
|
|
||||||
|
|
||||||
ReadWrite(stream);
|
|
||||||
|
|
||||||
// We have no destructor
|
// We have no destructor
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
|
@ -108,6 +97,9 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Already set isdisposed so that changes can be prohibited
|
// Already set isdisposed so that changes can be prohibited
|
||||||
isdisposed = true;
|
isdisposed = true;
|
||||||
|
|
||||||
|
if(map == General.Map.Map)
|
||||||
|
General.Map.UndoRedo.RecRemVertex(this);
|
||||||
|
|
||||||
// Remove from main list
|
// Remove from main list
|
||||||
map.RemoveVertex(listindex);
|
map.RemoveVertex(listindex);
|
||||||
|
|
||||||
|
@ -120,7 +112,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Detach from linedefs
|
// Detach from linedefs
|
||||||
foreach(Linedef ld in linedefs) ld.DetachVertex(this);
|
foreach(Linedef ld in linedefs) ld.DetachVertexP(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
|
@ -136,11 +128,21 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
|
|
||||||
#region ================== Management
|
#region ================== Management
|
||||||
|
|
||||||
|
// Call this before changing properties
|
||||||
|
protected override void BeforePropsChange()
|
||||||
|
{
|
||||||
|
if(map == General.Map.Map)
|
||||||
|
General.Map.UndoRedo.RecPrpVertex(this);
|
||||||
|
}
|
||||||
|
|
||||||
// This attaches a linedef and returns the listitem
|
// This attaches a linedef and returns the listitem
|
||||||
public LinkedListNode<Linedef> AttachLinedef(Linedef l) { return linedefs.AddLast(l); }
|
internal LinkedListNode<Linedef> AttachLinedefP(Linedef l)
|
||||||
|
{
|
||||||
|
return linedefs.AddLast(l);
|
||||||
|
}
|
||||||
|
|
||||||
// This detaches a linedef
|
// This detaches a linedef
|
||||||
public void DetachLinedef(LinkedListNode<Linedef> l)
|
internal void DetachLinedefP(LinkedListNode<Linedef> l)
|
||||||
{
|
{
|
||||||
// Not disposing?
|
// Not disposing?
|
||||||
if(!isdisposed)
|
if(!isdisposed)
|
||||||
|
@ -160,9 +162,17 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Serialize / deserialize
|
// Serialize / deserialize
|
||||||
internal void ReadWrite(IReadWriteStream s)
|
internal void ReadWrite(IReadWriteStream s)
|
||||||
{
|
{
|
||||||
|
if(!s.IsWriting) BeforePropsChange();
|
||||||
|
|
||||||
base.ReadWrite(s);
|
base.ReadWrite(s);
|
||||||
|
|
||||||
s.rwVector2D(ref pos);
|
s.rwVector2D(ref pos);
|
||||||
|
|
||||||
|
if(s.IsWriting)
|
||||||
|
{
|
||||||
|
// Let all lines know they need an update
|
||||||
|
foreach(Linedef l in linedefs) l.NeedUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Selected
|
// Selected
|
||||||
|
@ -187,6 +197,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This copies all properties to another thing
|
// This copies all properties to another thing
|
||||||
public void CopyPropertiesTo(Vertex v)
|
public void CopyPropertiesTo(Vertex v)
|
||||||
{
|
{
|
||||||
|
v.BeforePropsChange();
|
||||||
|
|
||||||
// Copy properties
|
// Copy properties
|
||||||
v.pos = pos;
|
v.pos = pos;
|
||||||
base.CopyPropertiesTo(v);
|
base.CopyPropertiesTo(v);
|
||||||
|
@ -213,6 +225,8 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Do we actually move?
|
// Do we actually move?
|
||||||
if(newpos != pos)
|
if(newpos != pos)
|
||||||
{
|
{
|
||||||
|
BeforePropsChange();
|
||||||
|
|
||||||
// Change position
|
// Change position
|
||||||
pos = newpos;
|
pos = newpos;
|
||||||
|
|
||||||
|
|
|
@ -575,22 +575,20 @@ namespace CodeImp.DoomBuilder.Rendering
|
||||||
// This returns the color for a linedef
|
// This returns the color for a linedef
|
||||||
public PixelColor DetermineLinedefColor(Linedef l)
|
public PixelColor DetermineLinedefColor(Linedef l)
|
||||||
{
|
{
|
||||||
// Impassable lines
|
if(l.Selected)
|
||||||
if(l.IsFlagSet(General.Map.Config.ImpassableFlag))
|
return General.Colors.Selection;
|
||||||
|
else if(l.ImpassableFlag)
|
||||||
{
|
{
|
||||||
// Determine color
|
// Impassable lines
|
||||||
if(l.Selected) return General.Colors.Selection;
|
if(l.Action != 0) return General.Colors.Actions;
|
||||||
else if(l.Action != 0) return General.Colors.Actions;
|
|
||||||
else return General.Colors.Linedefs;
|
else return General.Colors.Linedefs;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Determine color
|
// Passable lines
|
||||||
byte a = (byte)(General.Settings.DoubleSidedAlpha * 255.0f);
|
if(l.Action != 0) return General.Colors.Actions.WithAlpha(General.Settings.DoubleSidedAlphaByte);
|
||||||
if(l.Selected) return General.Colors.Selection;
|
else if(l.BlockSoundFlag) return General.Colors.Sounds.WithAlpha(General.Settings.DoubleSidedAlphaByte);
|
||||||
else if(l.Action != 0) return General.Colors.Actions.WithAlpha(a);
|
else return General.Colors.Linedefs.WithAlpha(General.Settings.DoubleSidedAlphaByte);
|
||||||
else if(l.IsFlagSet(General.Map.Config.SoundLinedefFlag)) return General.Colors.Sounds.WithAlpha(a);
|
|
||||||
else return General.Colors.Linedefs.WithAlpha(a);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,8 +191,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
public override void OnUndoEnd()
|
public override void OnUndoEnd()
|
||||||
{
|
{
|
||||||
base.OnUndoEnd();
|
base.OnUndoEnd();
|
||||||
ResourcesReloaded();
|
ResourcesReloadedPartial();
|
||||||
General.Map.Data.UpdateUsedTextures();
|
|
||||||
renderer.SetCrosshairBusy(false);
|
renderer.SetCrosshairBusy(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,8 +205,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
public override void OnRedoEnd()
|
public override void OnRedoEnd()
|
||||||
{
|
{
|
||||||
base.OnRedoEnd();
|
base.OnRedoEnd();
|
||||||
ResourcesReloaded();
|
ResourcesReloadedPartial();
|
||||||
General.Map.Data.UpdateUsedTextures();
|
|
||||||
renderer.SetCrosshairBusy(false);
|
renderer.SetCrosshairBusy(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,8 +614,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
#region ================== Processing
|
#region ================== Processing
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This disposes all resources and rebuilds the ones needed.
|
/// This disposes all resources. Needed geometry will be rebuild automatically.
|
||||||
/// This usually happens when geometry is changed by undo, redo, cut or paste actions.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void ResourcesReloaded()
|
protected virtual void ResourcesReloaded()
|
||||||
{
|
{
|
||||||
|
@ -648,6 +645,91 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
DoCulling();
|
DoCulling();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This disposes orphaned resources and resources on changed geometry.
|
||||||
|
/// This usually happens when geometry is changed by undo, redo, cut or paste actions
|
||||||
|
/// and uses the marks to check what needs to be reloaded.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void ResourcesReloadedPartial()
|
||||||
|
{
|
||||||
|
Dictionary<Sector, VisualSector> newsectors = new Dictionary<Sector,VisualSector>(allsectors.Count);
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
// Neighbour sectors must be updated as well
|
||||||
|
foreach(Sector s in General.Map.Map.Sectors)
|
||||||
|
{
|
||||||
|
if(s.Marked)
|
||||||
|
{
|
||||||
|
foreach(Sidedef sd in s.Sidedefs)
|
||||||
|
if(sd.Other != null) sd.Other.Marked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go for all sidedefs to mark sectors that need updating
|
||||||
|
foreach(Sidedef sd in General.Map.Map.Sidedefs)
|
||||||
|
if(sd.Marked) sd.Sector.Marked = true;
|
||||||
|
|
||||||
|
// Go for all vertices to mark linedefs that need updating
|
||||||
|
foreach(Vertex v in General.Map.Map.Vertices)
|
||||||
|
{
|
||||||
|
if(v.Marked)
|
||||||
|
{
|
||||||
|
foreach(Linedef ld in v.Linedefs)
|
||||||
|
ld.Marked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go for all linedefs to mark sectors that need updating
|
||||||
|
foreach(Linedef ld in General.Map.Map.Linedefs)
|
||||||
|
{
|
||||||
|
if(ld.Marked)
|
||||||
|
{
|
||||||
|
if(ld.Front != null) ld.Front.Sector.Marked = true;
|
||||||
|
if(ld.Back != null) ld.Back.Sector.Marked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispose if source was disposed or marked
|
||||||
|
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
|
||||||
|
{
|
||||||
|
if(vs.Key.IsDisposed || vs.Key.Marked)
|
||||||
|
{
|
||||||
|
vs.Value.Dispose();
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
newsectors.Add(vs.Key, vs.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
General.WriteLogLine("VisualSectors disposed: " + counter);
|
||||||
|
|
||||||
|
// Things depend on the sector they are in and because we can't
|
||||||
|
// easily determine which ones changed, we dispose all things
|
||||||
|
foreach(KeyValuePair<Thing, VisualThing> vt in allthings)
|
||||||
|
vt.Value.Dispose();
|
||||||
|
|
||||||
|
// Apply new lists
|
||||||
|
allsectors = newsectors;
|
||||||
|
allthings = new Dictionary<Thing, VisualThing>(allthings.Count);
|
||||||
|
|
||||||
|
// Clear visibility collections
|
||||||
|
visiblesectors.Clear();
|
||||||
|
visibleblocks.Clear();
|
||||||
|
visiblegeometry.Clear();
|
||||||
|
visiblethings.Clear();
|
||||||
|
|
||||||
|
// Make new blockmap
|
||||||
|
if(blockmap != null)
|
||||||
|
{
|
||||||
|
blockmap.Dispose();
|
||||||
|
blockmap = new VisualBlockMap();
|
||||||
|
FillBlockMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visibility culling (this re-creates the needed resources)
|
||||||
|
DoCulling();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implement this to create an instance of your VisualSector implementation.
|
/// Implement this to create an instance of your VisualSector implementation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -362,8 +362,8 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
// Apply all flags
|
// Apply all flags
|
||||||
foreach(CheckBox c in flags.Checkboxes)
|
foreach(CheckBox c in flags.Checkboxes)
|
||||||
{
|
{
|
||||||
if(c.CheckState == CheckState.Checked) l.Flags[c.Tag.ToString()] = true;
|
if(c.CheckState == CheckState.Checked) l.SetFlag(c.Tag.ToString(), true);
|
||||||
else if(c.CheckState == CheckState.Unchecked) l.Flags[c.Tag.ToString()] = false;
|
else if(c.CheckState == CheckState.Unchecked) l.SetFlag(c.Tag.ToString(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply chosen activation flag
|
// Apply chosen activation flag
|
||||||
|
@ -374,8 +374,8 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
foreach(CheckBox c in udmfactivates.Checkboxes)
|
foreach(CheckBox c in udmfactivates.Checkboxes)
|
||||||
{
|
{
|
||||||
LinedefActivateInfo ai = (c.Tag as LinedefActivateInfo);
|
LinedefActivateInfo ai = (c.Tag as LinedefActivateInfo);
|
||||||
if(c.CheckState == CheckState.Checked) l.Flags[ai.Key] = true;
|
if(c.CheckState == CheckState.Checked) l.SetFlag(ai.Key, true);
|
||||||
else if(c.CheckState == CheckState.Unchecked) l.Flags[ai.Key] = false;
|
else if(c.CheckState == CheckState.Unchecked) l.SetFlag(ai.Key, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action/tags
|
// Action/tags
|
||||||
|
@ -415,7 +415,7 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
if(l.Front == null) General.Map.Map.CreateSidedef(l, true, s);
|
if(l.Front == null) General.Map.Map.CreateSidedef(l, true, s);
|
||||||
|
|
||||||
// Change sector?
|
// Change sector?
|
||||||
if(l.Front.Sector != s) l.Front.ChangeSector(s);
|
if(l.Front.Sector != s) l.Front.SetSector(s);
|
||||||
|
|
||||||
// Apply settings
|
// Apply settings
|
||||||
l.Front.OffsetX = General.Clamp(frontoffsetx.GetResult(l.Front.OffsetX), General.Map.FormatInterface.MinTextureOffset, General.Map.FormatInterface.MaxTextureOffset);
|
l.Front.OffsetX = General.Clamp(frontoffsetx.GetResult(l.Front.OffsetX), General.Map.FormatInterface.MinTextureOffset, General.Map.FormatInterface.MaxTextureOffset);
|
||||||
|
@ -442,7 +442,7 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
if(l.Back == null) General.Map.Map.CreateSidedef(l, false, s);
|
if(l.Back == null) General.Map.Map.CreateSidedef(l, false, s);
|
||||||
|
|
||||||
// Change sector?
|
// Change sector?
|
||||||
if(l.Back.Sector != s) l.Back.ChangeSector(s);
|
if(l.Back.Sector != s) l.Back.SetSector(s);
|
||||||
|
|
||||||
// Apply settings
|
// Apply settings
|
||||||
l.Back.OffsetX = General.Clamp(backoffsetx.GetResult(l.Back.OffsetX), General.Map.FormatInterface.MinTextureOffset, General.Map.FormatInterface.MaxTextureOffset);
|
l.Back.OffsetX = General.Clamp(backoffsetx.GetResult(l.Back.OffsetX), General.Map.FormatInterface.MinTextureOffset, General.Map.FormatInterface.MaxTextureOffset);
|
||||||
|
|
|
@ -291,8 +291,8 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
// Apply all flags
|
// Apply all flags
|
||||||
foreach(CheckBox c in flags.Checkboxes)
|
foreach(CheckBox c in flags.Checkboxes)
|
||||||
{
|
{
|
||||||
if(c.CheckState == CheckState.Checked) t.Flags[c.Tag.ToString()] = true;
|
if(c.CheckState == CheckState.Checked) t.SetFlag(c.Tag.ToString(), true);
|
||||||
else if(c.CheckState == CheckState.Unchecked) t.Flags[c.Tag.ToString()] = false;
|
else if(c.CheckState == CheckState.Unchecked) t.SetFlag(c.Tag.ToString(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action/tags
|
// Action/tags
|
||||||
|
|
|
@ -116,6 +116,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
|
|
||||||
Cursor.Current = Cursors.AppStarting;
|
Cursor.Current = Cursors.AppStarting;
|
||||||
|
|
||||||
|
// We don't want to record this for undoing while we move the geometry around.
|
||||||
|
// This will be set back to normal when we're done.
|
||||||
|
General.Map.UndoRedo.IgnorePropChanges = true;
|
||||||
|
|
||||||
// Make list of selected vertices
|
// Make list of selected vertices
|
||||||
selectedverts = General.Map.Map.GetMarkedVertices(true);
|
selectedverts = General.Map.Map.GetMarkedVertices(true);
|
||||||
|
|
||||||
|
@ -273,6 +277,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
// Move geometry back to original position
|
// Move geometry back to original position
|
||||||
MoveGeometryRelative(new Vector2D(0f, 0f), false, false);
|
MoveGeometryRelative(new Vector2D(0f, 0f), false, false);
|
||||||
|
|
||||||
|
// Resume normal undo/redo recording
|
||||||
|
General.Map.UndoRedo.IgnorePropChanges = false;
|
||||||
|
|
||||||
// If only a single vertex was selected, deselect it now
|
// If only a single vertex was selected, deselect it now
|
||||||
if(selectedverts.Count == 1) General.Map.Map.ClearSelectedVertices();
|
if(selectedverts.Count == 1) General.Map.Map.ClearSelectedVertices();
|
||||||
|
|
||||||
|
@ -308,6 +315,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
// Move geometry back to original position
|
// Move geometry back to original position
|
||||||
MoveGeometryRelative(new Vector2D(0f, 0f), false, false);
|
MoveGeometryRelative(new Vector2D(0f, 0f), false, false);
|
||||||
|
|
||||||
|
// Resume normal undo/redo recording
|
||||||
|
General.Map.UndoRedo.IgnorePropChanges = false;
|
||||||
|
|
||||||
// Make undo for the dragging
|
// Make undo for the dragging
|
||||||
General.Map.UndoRedo.CreateUndo("Drag geometry");
|
General.Map.UndoRedo.CreateUndo("Drag geometry");
|
||||||
|
|
||||||
|
@ -364,10 +374,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
General.Map.Map.Update(true, false);
|
General.Map.Map.Update(true, false);
|
||||||
|
|
||||||
// Redraw
|
// Redraw
|
||||||
General.Interface.RedrawDisplay();
|
UpdateRedraw();
|
||||||
|
renderer.Present();
|
||||||
|
//General.Interface.RedrawDisplay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This redraws only the required things
|
||||||
|
protected virtual void UpdateRedraw()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// When edit button is released
|
// When edit button is released
|
||||||
protected override void OnEditEnd()
|
protected override void OnEditEnd()
|
||||||
{
|
{
|
||||||
|
|
|
@ -136,6 +136,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
|
|
||||||
renderer.RedrawSurface();
|
renderer.RedrawSurface();
|
||||||
|
|
||||||
|
UpdateRedraw();
|
||||||
|
|
||||||
|
if(viewchanged)
|
||||||
|
{
|
||||||
|
// Start rendering things
|
||||||
|
if(renderer.StartThings(true))
|
||||||
|
{
|
||||||
|
renderer.RenderThingSet(General.Map.Map.Things, 1.0f);
|
||||||
|
renderer.Finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.Present();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This redraws only the required things
|
||||||
|
protected override void UpdateRedraw()
|
||||||
|
{
|
||||||
// Start rendering structure
|
// Start rendering structure
|
||||||
if(renderer.StartPlotter(true))
|
if(renderer.StartPlotter(true))
|
||||||
{
|
{
|
||||||
|
@ -153,16 +171,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
renderer.Finish();
|
renderer.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(viewchanged)
|
|
||||||
{
|
|
||||||
// Start rendering things
|
|
||||||
if(renderer.StartThings(true))
|
|
||||||
{
|
|
||||||
renderer.RenderThingSet(General.Map.Map.Things, 1.0f);
|
|
||||||
renderer.Finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redraw overlay
|
// Redraw overlay
|
||||||
if(renderer.StartOverlay(true))
|
if(renderer.StartOverlay(true))
|
||||||
{
|
{
|
||||||
|
@ -172,8 +180,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
}
|
}
|
||||||
renderer.Finish();
|
renderer.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.Present();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -141,6 +141,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
|
|
||||||
renderer.RedrawSurface();
|
renderer.RedrawSurface();
|
||||||
|
|
||||||
|
UpdateRedraw();
|
||||||
|
|
||||||
|
// Redraw things when view changed
|
||||||
|
if(viewchanged)
|
||||||
|
{
|
||||||
|
if(renderer.StartThings(true))
|
||||||
|
{
|
||||||
|
renderer.RenderThingSet(General.Map.Map.Things, 1.0f);
|
||||||
|
renderer.Finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.Present();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This redraws only the required things
|
||||||
|
protected override void UpdateRedraw()
|
||||||
|
{
|
||||||
// Start rendering
|
// Start rendering
|
||||||
if(renderer.StartPlotter(true))
|
if(renderer.StartPlotter(true))
|
||||||
{
|
{
|
||||||
|
@ -159,16 +177,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
renderer.Finish();
|
renderer.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redraw things when view changed
|
|
||||||
if(viewchanged)
|
|
||||||
{
|
|
||||||
if(renderer.StartThings(true))
|
|
||||||
{
|
|
||||||
renderer.RenderThingSet(General.Map.Map.Things, 1.0f);
|
|
||||||
renderer.Finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redraw overlay
|
// Redraw overlay
|
||||||
if(renderer.StartOverlay(true))
|
if(renderer.StartOverlay(true))
|
||||||
{
|
{
|
||||||
|
@ -178,8 +186,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
}
|
}
|
||||||
renderer.Finish();
|
renderer.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.Present();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -232,6 +232,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Render things
|
||||||
|
UpdateRedraw();
|
||||||
|
|
||||||
|
renderer.Present();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This redraws only changed things
|
||||||
|
private void UpdateRedraw()
|
||||||
|
{
|
||||||
// Render things
|
// Render things
|
||||||
if(renderer.StartThings(true))
|
if(renderer.StartThings(true))
|
||||||
{
|
{
|
||||||
|
@ -248,8 +257,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
// Done
|
// Done
|
||||||
renderer.Finish();
|
renderer.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.Present();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancelled
|
// Cancelled
|
||||||
|
@ -346,7 +353,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
General.Map.Map.Update();
|
General.Map.Map.Update();
|
||||||
|
|
||||||
// Redraw
|
// Redraw
|
||||||
General.Interface.RedrawDisplay();
|
UpdateRedraw();
|
||||||
|
renderer.Present();
|
||||||
|
//General.Interface.RedrawDisplay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
|
|
||||||
renderer.RedrawSurface();
|
renderer.RedrawSurface();
|
||||||
|
|
||||||
|
UpdateRedraw();
|
||||||
|
|
||||||
|
// Redraw things when view changed
|
||||||
|
if(viewchanged)
|
||||||
|
{
|
||||||
|
if(renderer.StartThings(true))
|
||||||
|
{
|
||||||
|
renderer.RenderThingSet(General.Map.Map.Things, 1.0f);
|
||||||
|
renderer.Finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.Present();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This redraws only the required things
|
||||||
|
protected override void UpdateRedraw()
|
||||||
|
{
|
||||||
// Start rendering
|
// Start rendering
|
||||||
if(renderer.StartPlotter(true))
|
if(renderer.StartPlotter(true))
|
||||||
{
|
{
|
||||||
|
@ -140,16 +158,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
renderer.Finish();
|
renderer.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redraw things when view changed
|
|
||||||
if(viewchanged)
|
|
||||||
{
|
|
||||||
if(renderer.StartThings(true))
|
|
||||||
{
|
|
||||||
renderer.RenderThingSet(General.Map.Map.Things, 1.0f);
|
|
||||||
renderer.Finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redraw overlay
|
// Redraw overlay
|
||||||
if(renderer.StartOverlay(true))
|
if(renderer.StartOverlay(true))
|
||||||
{
|
{
|
||||||
|
@ -159,8 +167,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
}
|
}
|
||||||
renderer.Finish();
|
renderer.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.Present();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -614,6 +614,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
General.Interface.AddButton(BuilderPlug.Me.MenusForm.FlipSelectionH);
|
General.Interface.AddButton(BuilderPlug.Me.MenusForm.FlipSelectionH);
|
||||||
General.Interface.AddButton(BuilderPlug.Me.MenusForm.FlipSelectionV);
|
General.Interface.AddButton(BuilderPlug.Me.MenusForm.FlipSelectionV);
|
||||||
|
|
||||||
|
// We don't want to record this for undoing while we move the geometry around.
|
||||||
|
// This will be set back to normal when we're done.
|
||||||
|
General.Map.UndoRedo.IgnorePropChanges = true;
|
||||||
|
|
||||||
// Convert geometry selection
|
// Convert geometry selection
|
||||||
General.Map.Map.ClearAllMarks(false);
|
General.Map.Map.ClearAllMarks(false);
|
||||||
General.Map.Map.MarkSelectedVertices(true, true);
|
General.Map.Map.MarkSelectedVertices(true, true);
|
||||||
|
@ -751,6 +755,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
// Paste operation?
|
// Paste operation?
|
||||||
if(pasting)
|
if(pasting)
|
||||||
{
|
{
|
||||||
|
// Resume normal undo/redo recording
|
||||||
|
General.Map.UndoRedo.IgnorePropChanges = false;
|
||||||
|
|
||||||
// Remove the geometry
|
// Remove the geometry
|
||||||
int index = 0;
|
int index = 0;
|
||||||
foreach(Vertex v in selectedvertices)
|
foreach(Vertex v in selectedvertices)
|
||||||
|
@ -773,6 +780,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
t.Rotate(thingangle[index]);
|
t.Rotate(thingangle[index]);
|
||||||
t.Move(thingpos[index++]);
|
t.Move(thingpos[index++]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resume normal undo/redo recording
|
||||||
|
General.Map.UndoRedo.IgnorePropChanges = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
General.Map.Map.Update(true, true);
|
General.Map.Map.Update(true, true);
|
||||||
|
@ -811,6 +821,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
General.Map.UndoRedo.CreateUndo("Edit selection");
|
General.Map.UndoRedo.CreateUndo("Edit selection");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resume normal undo/redo recording
|
||||||
|
General.Map.UndoRedo.IgnorePropChanges = false;
|
||||||
|
|
||||||
// Mark selected geometry
|
// Mark selected geometry
|
||||||
General.Map.Map.ClearAllMarks(false);
|
General.Map.Map.ClearAllMarks(false);
|
||||||
General.Map.Map.MarkAllSelectedGeometry(true, true, true, true, false);
|
General.Map.Map.MarkAllSelectedGeometry(true, true, true, true, false);
|
||||||
|
@ -863,7 +876,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
if(joinsidedef != null)
|
if(joinsidedef != null)
|
||||||
{
|
{
|
||||||
// Join!
|
// Join!
|
||||||
s.ChangeSector(joinsidedef.Sector);
|
s.SetSector(joinsidedef.Sector);
|
||||||
s.Marked = false;
|
s.Marked = false;
|
||||||
joined = true;
|
joined = true;
|
||||||
|
|
||||||
|
|
|
@ -912,8 +912,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
sd.SetTextureLow("-");
|
sd.SetTextureLow("-");
|
||||||
|
|
||||||
// Set upper/lower unpegged flags
|
// Set upper/lower unpegged flags
|
||||||
sd.Line.Flags[General.Map.Config.UpperUnpeggedFlag] = false;
|
sd.Line.SetFlag(General.Map.Config.UpperUnpeggedFlag, false);
|
||||||
sd.Line.Flags[General.Map.Config.LowerUnpeggedFlag] = true;
|
sd.Line.SetFlag(General.Map.Config.LowerUnpeggedFlag, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -923,8 +923,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
if(doortex.Length > 0) sd.Other.SetTextureHigh(doortex);
|
if(doortex.Length > 0) sd.Other.SetTextureHigh(doortex);
|
||||||
|
|
||||||
// Set upper/lower unpegged flags
|
// Set upper/lower unpegged flags
|
||||||
sd.Line.Flags[General.Map.Config.UpperUnpeggedFlag] = false;
|
sd.Line.SetFlag(General.Map.Config.UpperUnpeggedFlag, false);
|
||||||
sd.Line.Flags[General.Map.Config.LowerUnpeggedFlag] = false;
|
sd.Line.SetFlag(General.Map.Config.LowerUnpeggedFlag, false);
|
||||||
|
|
||||||
// Get door linedef type from config
|
// Get door linedef type from config
|
||||||
sd.Line.Action = General.Map.Config.MakeDoorAction;
|
sd.Line.Action = General.Map.Config.MakeDoorAction;
|
||||||
|
|
|
@ -113,7 +113,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
{
|
{
|
||||||
type = t.Type;
|
type = t.Type;
|
||||||
angle = t.Angle;
|
angle = t.Angle;
|
||||||
flags = new Dictionary<string, bool>(t.Flags);
|
flags = t.GetFlags();
|
||||||
tag = t.Tag;
|
tag = t.Tag;
|
||||||
action = t.Action;
|
action = t.Action;
|
||||||
args = (int[])(t.Args.Clone());
|
args = (int[])(t.Args.Clone());
|
||||||
|
@ -123,9 +123,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
{
|
{
|
||||||
t.Type = type;
|
t.Type = type;
|
||||||
t.Rotate(angle);
|
t.Rotate(angle);
|
||||||
t.Flags.Clear();
|
t.ClearFlags();
|
||||||
foreach(KeyValuePair<string, bool> f in flags)
|
foreach(KeyValuePair<string, bool> f in flags)
|
||||||
t.Flags.Add(f.Key, f.Value);
|
t.SetFlag(f.Key, f.Value);
|
||||||
t.Tag = tag;
|
t.Tag = tag;
|
||||||
t.Action = action;
|
t.Action = action;
|
||||||
for(int i = 0; i < t.Args.Length; i++)
|
for(int i = 0; i < t.Args.Length; i++)
|
||||||
|
|
|
@ -220,8 +220,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
// Toggle upper-unpegged
|
// Toggle upper-unpegged
|
||||||
public virtual void OnToggleUpperUnpegged()
|
public virtual void OnToggleUpperUnpegged()
|
||||||
{
|
{
|
||||||
if(this.Sidedef.Line.Flags.ContainsKey(General.Map.Config.UpperUnpeggedFlag) &&
|
if(this.Sidedef.Line.IsFlagSet(General.Map.Config.UpperUnpeggedFlag))
|
||||||
this.Sidedef.Line.Flags[General.Map.Config.UpperUnpeggedFlag])
|
|
||||||
{
|
{
|
||||||
// Remove flag
|
// Remove flag
|
||||||
mode.ApplyUpperUnpegged(false);
|
mode.ApplyUpperUnpegged(false);
|
||||||
|
@ -236,8 +235,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
// Toggle lower-unpegged
|
// Toggle lower-unpegged
|
||||||
public virtual void OnToggleLowerUnpegged()
|
public virtual void OnToggleLowerUnpegged()
|
||||||
{
|
{
|
||||||
if(this.Sidedef.Line.Flags.ContainsKey(General.Map.Config.LowerUnpeggedFlag) &&
|
if(this.Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
|
||||||
this.Sidedef.Line.Flags[General.Map.Config.LowerUnpeggedFlag])
|
|
||||||
{
|
{
|
||||||
// Remove flag
|
// Remove flag
|
||||||
mode.ApplyLowerUnpegged(false);
|
mode.ApplyLowerUnpegged(false);
|
||||||
|
@ -258,14 +256,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
// Remove flag
|
// Remove flag
|
||||||
mode.CreateUndo("Remove upper-unpegged setting");
|
mode.CreateUndo("Remove upper-unpegged setting");
|
||||||
mode.SetActionResult("Removed upper-unpegged setting.");
|
mode.SetActionResult("Removed upper-unpegged setting.");
|
||||||
this.Sidedef.Line.Flags[General.Map.Config.UpperUnpeggedFlag] = false;
|
this.Sidedef.Line.SetFlag(General.Map.Config.UpperUnpeggedFlag, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Add flag
|
// Add flag
|
||||||
mode.CreateUndo("Set upper-unpegged setting");
|
mode.CreateUndo("Set upper-unpegged setting");
|
||||||
mode.SetActionResult("Set upper-unpegged setting.");
|
mode.SetActionResult("Set upper-unpegged setting.");
|
||||||
this.Sidedef.Line.Flags[General.Map.Config.UpperUnpeggedFlag] = true;
|
this.Sidedef.Line.SetFlag(General.Map.Config.UpperUnpeggedFlag, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update sidedef geometry
|
// Update sidedef geometry
|
||||||
|
@ -290,14 +288,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
// Remove flag
|
// Remove flag
|
||||||
mode.CreateUndo("Remove lower-unpegged setting");
|
mode.CreateUndo("Remove lower-unpegged setting");
|
||||||
mode.SetActionResult("Removed lower-unpegged setting.");
|
mode.SetActionResult("Removed lower-unpegged setting.");
|
||||||
this.Sidedef.Line.Flags[General.Map.Config.LowerUnpeggedFlag] = false;
|
this.Sidedef.Line.SetFlag(General.Map.Config.LowerUnpeggedFlag, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Add flag
|
// Add flag
|
||||||
mode.CreateUndo("Set lower-unpegged setting");
|
mode.CreateUndo("Set lower-unpegged setting");
|
||||||
mode.SetActionResult("Set lower-unpegged setting.");
|
mode.SetActionResult("Set lower-unpegged setting.");
|
||||||
this.Sidedef.Line.Flags[General.Map.Config.LowerUnpeggedFlag] = true;
|
this.Sidedef.Line.SetFlag(General.Map.Config.LowerUnpeggedFlag, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update sidedef geometry
|
// Update sidedef geometry
|
||||||
|
|
|
@ -512,6 +512,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
PickTarget();
|
PickTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// After resources were partially reloaded
|
||||||
|
protected override void ResourcesReloadedPartial()
|
||||||
|
{
|
||||||
|
base.ResourcesReloadedPartial();
|
||||||
|
PickTarget();
|
||||||
|
}
|
||||||
|
|
||||||
// Mouse moves
|
// Mouse moves
|
||||||
public override void OnMouseMove(MouseEventArgs e)
|
public override void OnMouseMove(MouseEventArgs e)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue