- 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:
codeimp 2009-06-11 21:21:20 +00:00
parent f66980b60f
commit 55e640b6e1
32 changed files with 1561 additions and 586 deletions

View file

@ -3,7 +3,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}</ProjectGuid>
<OutputType>WinExe</OutputType>

View file

@ -48,13 +48,14 @@ namespace CodeImp.DoomBuilder.Config
private Configuration cfg;
// Cached variables
private int undolevels;
//private int undolevels;
private bool blackbrowsers;
private int visualfov;
private float visualmousesensx;
private float visualmousesensy;
private int imagebrightness;
private float doublesidedalpha;
private byte doublesidedalphabyte;
private float backgroundalpha;
private bool qualitydisplay;
private bool squarethings;
@ -92,11 +93,12 @@ namespace CodeImp.DoomBuilder.Config
#region ================== Properties
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 int VisualFOV { get { return visualfov; } internal set { visualfov = 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 VisualMouseSensX { get { return visualmousesensx; } internal set { visualmousesensx = value; } }
public float VisualMouseSensY { get { return visualmousesensy; } internal set { visualmousesensy = value; } }
@ -153,12 +155,13 @@ namespace CodeImp.DoomBuilder.Config
{
// Read the cache variables
blackbrowsers = cfg.ReadSetting("blackbrowsers", false);
undolevels = cfg.ReadSetting("undolevels", 20);
//undolevels = cfg.ReadSetting("undolevels", 20);
visualfov = cfg.ReadSetting("visualfov", 80);
visualmousesensx = cfg.ReadSetting("visualmousesensx", 40f);
visualmousesensy = cfg.ReadSetting("visualmousesensy", 40f);
imagebrightness = cfg.ReadSetting("imagebrightness", 3);
doublesidedalpha = cfg.ReadSetting("doublesidedalpha", 0.4f);
doublesidedalphabyte = (byte)(doublesidedalpha * 255f);
backgroundalpha = cfg.ReadSetting("backgroundalpha", 1.0f);
qualitydisplay = cfg.ReadSetting("qualitydisplay", true);
squarethings = cfg.ReadSetting("squarethings", false);
@ -197,7 +200,7 @@ namespace CodeImp.DoomBuilder.Config
// Write the cache variables
cfg.WriteSetting("blackbrowsers", blackbrowsers);
cfg.WriteSetting("undolevels", undolevels);
//cfg.WriteSetting("undolevels", undolevels);
cfg.WriteSetting("visualfov", visualfov);
cfg.WriteSetting("visualmousesensx", visualmousesensx);
cfg.WriteSetting("visualmousesensy", visualmousesensy);
@ -363,7 +366,7 @@ namespace CodeImp.DoomBuilder.Config
{
t.Type = defaultthingtype;
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

View file

@ -199,6 +199,8 @@ namespace CodeImp.DoomBuilder.Controls
// This applies the current fields to a UniFields object
public void Apply(UniFields tofields)
{
tofields.BeforeFieldsChange();
// Go for all the fields
UniFields tempfields = new UniFields(tofields);
foreach(KeyValuePair<string, UniValue> f in tempfields)

File diff suppressed because it is too large Load diff

View file

@ -40,7 +40,7 @@ namespace CodeImp.DoomBuilder.Editing
{
#region ================== Variables
private MemoryStream mapdata;
private MemoryStream recstream;
private string filename;
private string description;
private int ticketid; // For safe withdrawing
@ -62,22 +62,22 @@ namespace CodeImp.DoomBuilder.Editing
#region ================== Constructor / Disposer
// 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.description = description;
this.mapdata = mapdata;
this.recstream = recstream;
this.filename = null;
}
// 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.description = info.description;
this.mapdata = mapdata;
this.recstream = recstream;
this.filename = null;
}
@ -87,8 +87,8 @@ namespace CodeImp.DoomBuilder.Editing
lock(this)
{
isdisposed = true;
if(mapdata != null) mapdata.Dispose();
mapdata = null;
if(recstream != null) recstream.Dispose();
recstream = null;
if(isondisk) File.Delete(filename);
isondisk = false;
}
@ -99,15 +99,15 @@ namespace CodeImp.DoomBuilder.Editing
#region ================== Methods
// This returns the map data
internal MemoryStream GetMapData()
internal MemoryStream GetStream()
{
lock(this)
{
// Restore into memory if needed
if(isondisk) RestoreFromFile();
// Return a copy of the buffer
return new MemoryStream(mapdata.ToArray());
// Return the buffer
return recstream;
}
}
@ -121,9 +121,9 @@ namespace CodeImp.DoomBuilder.Editing
isondisk = true;
// Compress data
mapdata.Seek(0, SeekOrigin.Begin);
MemoryStream outstream = new MemoryStream((int)mapdata.Length);
BZip2.Compress(mapdata, outstream, 300000);
recstream.Seek(0, SeekOrigin.Begin);
MemoryStream outstream = new MemoryStream((int)recstream.Length);
BZip2.Compress(recstream, outstream, 300000);
// Make temporary file
filename = General.MakeTempFilename(General.Map.TempPath, "snapshot");
@ -132,8 +132,8 @@ namespace CodeImp.DoomBuilder.Editing
File.WriteAllBytes(filename, outstream.ToArray());
// Remove data from memory
mapdata.Dispose();
mapdata = null;
recstream.Dispose();
recstream = null;
outstream.Dispose();
}
}
@ -154,7 +154,7 @@ namespace CodeImp.DoomBuilder.Editing
MemoryStream outstream = new MemoryStream((int)instream.Length * 4);
instream.Seek(0, SeekOrigin.Begin);
BZip2.Decompress(instream, outstream);
mapdata = new MemoryStream(outstream.ToArray());
recstream = new MemoryStream(outstream.ToArray());
// Clean up
instream.Dispose();

View file

@ -348,13 +348,17 @@ namespace CodeImp.DoomBuilder
General.WriteLogLine("Initializing map format interface " + config.FormatInterface + "...");
io = MapSetIO.Create(config.FormatInterface, tempwad, this);
General.WriteLogLine("Reading map data structures from file...");
try { map = io.Read(map, TEMP_MAP_HEADER); }
catch(Exception e)
{
General.ErrorLogger.Add(ErrorType.Error, "Unable to read the map data structures with the specified configuration. " + e.GetType().Name + ": " + e.Message);
General.ShowErrorMessage("Unable to read the map data structures with the specified configuration.", MessageBoxButtons.OK);
return false;
}
#if DEBUG
map = io.Read(map, TEMP_MAP_HEADER);
#else
try { map = io.Read(map, TEMP_MAP_HEADER); }
catch(Exception e)
{
General.ErrorLogger.Add(ErrorType.Error, "Unable to read the map data structures with the specified configuration. " + e.GetType().Name + ": " + e.Message);
General.ShowErrorMessage("Unable to read the map data structures with the specified configuration.", MessageBoxButtons.OK);
return false;
}
#endif
map.EndAddRemove();
// Load data manager
@ -446,6 +450,8 @@ namespace CodeImp.DoomBuilder
{
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);
foreach(string k in flagkeys) t.Flags[k] = false;
}

View file

@ -566,14 +566,14 @@ namespace CodeImp.DoomBuilder.Geometry
{
// 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.Sector != newsector) ls.Line.Front.ChangeSector(newsector);
if(ls.Line.Front.Sector != newsector) ls.Line.Front.SetSector(newsector);
ApplyDefaultsToSidedef(ls.Line.Front, sourceside);
}
else
{
// 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.Sector != newsector) ls.Line.Back.ChangeSector(newsector);
if(ls.Line.Back.Sector != newsector) ls.Line.Back.SetSector(newsector);
ApplyDefaultsToSidedef(ls.Line.Back, sourceside);
}
@ -622,7 +622,7 @@ namespace CodeImp.DoomBuilder.Geometry
else
{
// Link to the new sector
ls.Line.Front.ChangeSector(original.Sector);
ls.Line.Front.SetSector(original.Sector);
}
}
else
@ -641,7 +641,7 @@ namespace CodeImp.DoomBuilder.Geometry
else
{
// Link to the new sector
ls.Line.Back.ChangeSector(original.Sector);
ls.Line.Back.SetSector(original.Sector);
}
}
}

View file

@ -101,6 +101,9 @@ namespace CodeImp.DoomBuilder.Geometry
// Constructor
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

View file

@ -42,6 +42,7 @@ namespace CodeImp.DoomBuilder.IO
private Stream stream;
private BinaryReader reader;
private string[] stringstable;
private int stringtablepos;
#endregion
@ -49,6 +50,8 @@ namespace CodeImp.DoomBuilder.IO
public bool IsWriting { get { return false; } }
public int EndPosition { get { return stringtablepos; } }
#endregion
#region ================== Constructor / Destructor
@ -69,8 +72,8 @@ namespace CodeImp.DoomBuilder.IO
public void Begin()
{
// First 4 bytes are reserved for the offset of the strings table
int offset = reader.ReadInt32();
stream.Seek(offset, SeekOrigin.Begin);
stringtablepos = reader.ReadInt32();
stream.Seek(stringtablepos, SeekOrigin.Begin);
// Read the strings
List<string> strings = new List<string>();

View file

@ -375,6 +375,8 @@ namespace CodeImp.DoomBuilder.IO
// This reads custom fields from a collection and adds them to a map element
private void ReadCustomFields(UniversalCollection collection, MapElement element, string elementname)
{
element.Fields.BeforeFieldsChange();
// Go for all the elements in the collection
foreach(UniversalEntry e in collection)
{

View file

@ -67,6 +67,8 @@ namespace CodeImp.DoomBuilder.Map
private float lengthinv;
private float angle;
private RectangleF rect;
private bool blocksoundflag;
private bool impassableflag;
// Properties
private Dictionary<string, bool> flags;
@ -89,10 +91,10 @@ namespace CodeImp.DoomBuilder.Map
public Sidedef Front { get { return front; } }
public Sidedef Back { get { return back; } }
public Line2D Line { get { return new Line2D(start.Position, end.Position); } }
public Dictionary<string, bool> Flags { get { return flags; } }
public int Action { get { return action; } set { action = value; } }
public int Activate { get { return activate; } set { 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"); } }
internal Dictionary<string, bool> Flags { get { return flags; } }
public int Action { get { return action; } set { BeforePropsChange(); action = value; } }
public int Activate { get { return activate; } set { BeforePropsChange(); activate = value; } }
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 Length { get { return length; } }
public float LengthInv { get { return lengthinv; } }
@ -102,7 +104,9 @@ namespace CodeImp.DoomBuilder.Map
public int[] Args { get { return args; } }
internal int SerializedIndex { get { return serializedindex; } set { serializedindex = value; } }
internal bool FrontInterior { get { return frontinterior; } set { frontinterior = value; } }
internal bool ImpassableFlag { get { return impassableflag; } }
internal bool BlockSoundFlag { get { return blocksoundflag; } }
#endregion
#region ================== Constructor / Disposer
@ -113,41 +117,23 @@ namespace CodeImp.DoomBuilder.Map
// Initialize
this.map = map;
this.listindex = listindex;
this.start = start;
this.end = end;
this.updateneeded = true;
this.args = new int[NUM_ARGS];
this.flags = new Dictionary<string, bool>();
// 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.startvertexlistitem = start.AttachLinedefP(this);
this.end = end;
this.updateneeded = true;
this.args = new int[NUM_ARGS];
// Attach to vertices
startvertexlistitem = start.AttachLinedef(this);
endvertexlistitem = end.AttachLinedef(this);
ReadWrite(stream);
this.endvertexlistitem = end.AttachLinedefP(this);
if(map == General.Map.Map)
General.Map.UndoRedo.RecAddLinedef(this);
// We have no destructor
GC.SuppressFinalize(this);
}
// Disposer
public override void Dispose()
{
@ -157,18 +143,23 @@ namespace CodeImp.DoomBuilder.Map
// Already set isdisposed so that changes can be prohibited
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
map.RemoveLinedef(listindex);
// Detach from vertices
start.DetachLinedef(startvertexlistitem);
end.DetachLinedef(endvertexlistitem);
startvertexlistitem = null;
endvertexlistitem = null;
// Dispose sidedefs
if((front != null) && map.AutoRemove) front.Dispose();
if((back != null) && map.AutoRemove) back.Dispose();
// Detach from vertices
if(startvertexlistitem != null) start.DetachLinedefP(startvertexlistitem);
startvertexlistitem = null;
start = null;
if(endvertexlistitem != null) end.DetachLinedefP(endvertexlistitem);
endvertexlistitem = null;
end = null;
// Clean up
start = null;
@ -185,10 +176,19 @@ namespace CodeImp.DoomBuilder.Map
#endregion
#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)
{
if(!s.IsWriting) BeforePropsChange();
base.ReadWrite(s);
if(s.IsWriting)
@ -223,32 +223,46 @@ namespace CodeImp.DoomBuilder.Map
// This sets new start vertex
public void SetStartVertex(Vertex v)
{
if(map == General.Map.Map)
General.Map.UndoRedo.RecRefLinedefStart(this);
// Change start
if(startvertexlistitem != null) start.DetachLinedef(startvertexlistitem);
if(startvertexlistitem != null) start.DetachLinedefP(startvertexlistitem);
startvertexlistitem = null;
start = v;
if(start != null) startvertexlistitem = start.AttachLinedef(this);
if(start != null) startvertexlistitem = start.AttachLinedefP(this);
this.updateneeded = true;
}
// This sets new end vertex
public void SetEndVertex(Vertex v)
{
if(map == General.Map.Map)
General.Map.UndoRedo.RecRefLinedefEnd(this);
// Change end
if(endvertexlistitem != null) end.DetachLinedef(endvertexlistitem);
if(endvertexlistitem != null) end.DetachLinedefP(endvertexlistitem);
endvertexlistitem = null;
end = v;
if(end != null) endvertexlistitem = end.AttachLinedef(this);
if(end != null) endvertexlistitem = end.AttachLinedefP(this);
this.updateneeded = true;
}
// This detaches a vertex
internal void DetachVertex(Vertex v)
internal void DetachVertexP(Vertex v)
{
if(v == start)
SetStartVertex(null);
{
if(startvertexlistitem != null) start.DetachLinedefP(startvertexlistitem);
startvertexlistitem = null;
start = null;
}
else if(v == end)
SetEndVertex(null);
{
if(endvertexlistitem != null) end.DetachLinedefP(endvertexlistitem);
endvertexlistitem = null;
end = null;
}
else
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
new public void CopyPropertiesTo(Linedef l)
{
l.BeforePropsChange();
// Copy properties
l.action = action;
l.args = (int[])args.Clone();
@ -263,42 +279,57 @@ namespace CodeImp.DoomBuilder.Map
l.tag = tag;
l.updateneeded = true;
l.activate = activate;
l.impassableflag = impassableflag;
l.blocksoundflag = blocksoundflag;
base.CopyPropertiesTo(l);
}
// This attaches a sidedef on the front
public void AttachFront(Sidedef s)
internal void AttachFront(Sidedef s)
{
// No sidedef here yet?
if(front == null)
{
// Attach and recalculate
front = s;
updateneeded = true;
}
else throw new Exception("Linedef already has a front Sidedef.");
if(map == General.Map.Map)
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
front = s;
if(front != null) front.SetLinedefP(this);
updateneeded = true;
}
// This attaches a sidedef on the back
public void AttachBack(Sidedef s)
internal void AttachBack(Sidedef s)
{
// No sidedef here yet?
if(back == null)
{
// Attach and recalculate
back = s;
updateneeded = true;
}
else throw new Exception("Linedef already has a back Sidedef.");
if(map == General.Map.Map)
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
back = s;
if(back != null) back.SetLinedefP(this);
updateneeded = true;
}
// This detaches a sidedef from the front
public void DetachSidedef(Sidedef s)
internal void DetachSidedefP(Sidedef s)
{
// Sidedef is on the front?
if(front == s)
{
// Remove sidedef reference
if(front != null) front.SetLinedefP(null);
front = null;
updateneeded = true;
}
@ -306,10 +337,11 @@ namespace CodeImp.DoomBuilder.Map
else if(back == s)
{
// Remove sidedef reference
if(back != null) back.SetLinedefP(null);
back = null;
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
@ -333,6 +365,10 @@ namespace CodeImp.DoomBuilder.Map
float b = Math.Max(start.Position.y, end.Position.y);
rect = new RectangleF(l, t, r - l, b - t);
// Cached flags
blocksoundflag = IsFlagSet(General.Map.Config.SoundLinedefFlag);
impassableflag = IsFlagSet(General.Map.Config.ImpassableFlag);
// Updated
updateneeded = false;
}
@ -478,20 +514,45 @@ namespace CodeImp.DoomBuilder.Map
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;
// 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
public void FlipVertices()
{
// Flip vertices
Vertex v = start;
start = end;
end = v;
// Flip tickets accordingly
LinkedListNode<Linedef> vn = startvertexlistitem;
startvertexlistitem = endvertexlistitem;
endvertexlistitem = vn;
Vertex oldstart = start;
Vertex oldend = end;
SetStartVertex(oldend);
SetEndVertex(oldstart);
// For drawing, the interior now lies on the other side
frontinterior = !frontinterior;
@ -504,9 +565,10 @@ namespace CodeImp.DoomBuilder.Map
public void FlipSidedefs()
{
// Flip sidedefs
Sidedef sd = front;
front = back;
back = sd;
Sidedef oldfront = front;
Sidedef oldback = back;
AttachFront(oldback);
AttachBack(oldfront);
General.Map.IsChanged = true;
}
@ -544,14 +606,14 @@ namespace CodeImp.DoomBuilder.Map
if((front != null) && (back != null))
{
// Apply or remove flags for doublesided line
flags[General.Map.Config.SingleSidedFlag] = false;
flags[General.Map.Config.DoubleSidedFlag] = true;
SetFlag(General.Map.Config.SingleSidedFlag, false);
SetFlag(General.Map.Config.DoubleSidedFlag, true);
}
else
{
// Apply or remove flags for singlesided line
flags[General.Map.Config.SingleSidedFlag] = true;
flags[General.Map.Config.DoubleSidedFlag] = false;
SetFlag(General.Map.Config.SingleSidedFlag, true);
SetFlag(General.Map.Config.DoubleSidedFlag, false);
}
General.Map.IsChanged = true;
@ -952,6 +1014,8 @@ namespace CodeImp.DoomBuilder.Map
// This updates all properties
public void Update(Dictionary<string, bool> flags, int activate, int tag, int action, int[] args)
{
BeforePropsChange();
// Apply changes
this.flags = new Dictionary<string, bool>(flags);
this.tag = tag;

View file

@ -68,13 +68,14 @@ namespace CodeImp.DoomBuilder.Map
internal MapElement()
{
// Initialize
fields = new UniFields();
fields = new UniFields(this);
}
// Disposer
public virtual void Dispose()
{
// Clean up
fields.Owner = null;
fields = null;
// Done
@ -101,7 +102,7 @@ namespace CodeImp.DoomBuilder.Map
}
else
{
fields = new UniFields(c);
fields = new UniFields(this, c);
for(int i = 0; i < c; i++)
{
string t; s.rString(out t);
@ -114,7 +115,16 @@ namespace CodeImp.DoomBuilder.Map
// This copies properties to any other 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

View file

@ -204,7 +204,6 @@ namespace CodeImp.DoomBuilder.Map
{
// Already set isdisposed so that changes can be prohibited
isdisposed = true;
autoremove = false;
BeginAddRemove();
// Dispose all things
@ -435,6 +434,7 @@ namespace CodeImp.DoomBuilder.Map
{
virtualsector = newset.CreateSector();
l.Front.Sector.CopyPropertiesTo(virtualsector);
virtualsector.Fields.BeforeFieldsChange();
virtualsector.Fields[VIRTUAL_SECTOR_FIELD] = new UniValue(virtualsectorvalue);
}
@ -463,6 +463,7 @@ namespace CodeImp.DoomBuilder.Map
{
virtualsector = newset.CreateSector();
l.Back.Sector.CopyPropertiesTo(virtualsector);
virtualsector.Fields.BeforeFieldsChange();
virtualsector.Fields[VIRTUAL_SECTOR_FIELD] = new UniValue(virtualsectorvalue);
}
@ -509,24 +510,6 @@ namespace CodeImp.DoomBuilder.Map
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>
public Linedef CreateLinedef(Vertex start, Vertex end)
{
@ -545,24 +528,6 @@ namespace CodeImp.DoomBuilder.Map
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>
public Sidedef CreateSidedef(Linedef l, bool front, Sector s)
{
@ -581,24 +546,6 @@ namespace CodeImp.DoomBuilder.Map
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>
public Sector CreateSector()
{
@ -637,15 +584,6 @@ namespace CodeImp.DoomBuilder.Map
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>
public Thing CreateThing()
{
@ -919,7 +857,8 @@ namespace CodeImp.DoomBuilder.Map
// Go for all vertices
for(int i = 0; i < c; i++)
{
array[i] = CreateVertex(stream);
array[i] = CreateVertex(new Vector2D());
array[i].ReadWrite(stream);
}
return array;
@ -941,7 +880,8 @@ namespace CodeImp.DoomBuilder.Map
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;
@ -964,7 +904,8 @@ namespace CodeImp.DoomBuilder.Map
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
for(int i = 0; i < c; i++)
{
array[i] = CreateSector(stream);
array[i] = CreateSector();
array[i].ReadWrite(stream);
}
return array;
@ -2677,14 +2619,14 @@ namespace CodeImp.DoomBuilder.Map
{
// Replace with stored sidedef
bool isfront = snsd.IsFront;
snsd.Line.DetachSidedef(snsd);
snsd.Line.DetachSidedefP(snsd);
if(isfront)
snsd.Line.AttachFront(stored);
else
snsd.Line.AttachBack(stored);
// Remove the sidedef
snsd.ChangeSector(null);
snsd.SetSector(null);
RemoveSidedef(sn);
}
else

View file

@ -86,15 +86,15 @@ namespace CodeImp.DoomBuilder.Map
/// An unique index that does not change when other sectors are removed.
/// </summary>
public int FixedIndex { get { return fixedindex; } }
public int FloorHeight { get { return floorheight; } set { floorheight = value; } }
public int CeilHeight { get { return ceilheight; } set { ceilheight = value; } }
public int FloorHeight { get { return floorheight; } set { BeforePropsChange(); floorheight = value; } }
public int CeilHeight { get { return ceilheight; } set { BeforePropsChange(); ceilheight = value; } }
public string FloorTexture { get { return floortexname; } }
public string CeilTexture { get { return ceiltexname; } }
public long LongFloorTexture { get { return longfloortexname; } }
public long LongCeilTexture { get { return longceiltexname; } }
public int Effect { get { return effect; } set { 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 Brightness { get { return brightness; } set { brightness = value; updateneeded = true; } }
public int Effect { get { return effect; } set { BeforePropsChange(); effect = value; } }
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 { BeforePropsChange(); brightness = value; updateneeded = true; } }
public bool UpdateNeeded { get { return updateneeded; } set { updateneeded |= value; triangulationneeded |= value; } }
public RectangleF BBox { get { return bbox; } }
internal Sector Clone { get { return clone; } set { clone = value; } }
@ -122,21 +122,8 @@ namespace CodeImp.DoomBuilder.Map
this.triangulationneeded = true;
this.surfaceentry = new SurfaceEntry(-1, -1, -1);
// We have no destructor
GC.SuppressFinalize(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);
if(map == General.Map.Map)
General.Map.UndoRedo.RecAddSector(this);
// We have no destructor
GC.SuppressFinalize(this);
@ -150,10 +137,13 @@ namespace CodeImp.DoomBuilder.Map
{
// Already set isdisposed so that changes can be prohibited
isdisposed = true;
if(map == General.Map.Map)
General.Map.UndoRedo.RecRemSector(this);
// Remove from main list
map.RemoveSector(listindex);
// Register the index as free
map.AddSectorIndexHole(fixedindex);
@ -161,14 +151,16 @@ namespace CodeImp.DoomBuilder.Map
// because a sidedef cannot exist without reference to its sector.
if(map.AutoRemove)
foreach(Sidedef sd in sidedefs) sd.Dispose();
else
foreach(Sidedef sd in sidedefs) sd.SetSectorP(null);
// Free surface entry
General.Map.CRenderer2D.Surfaces.FreeSurfaces(surfaceentry);
// Clean up
sidedefs = null;
map = null;
// Dispose base
base.Dispose();
}
@ -178,49 +170,30 @@ namespace CodeImp.DoomBuilder.Map
#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)
{
base.ReadWrite(s);
if(!s.IsWriting) BeforePropsChange();
base.ReadWrite(s);
s.rwInt(ref fixedindex);
s.rwInt(ref floorheight);
s.rwInt(ref ceilheight);
s.rwString(ref floortexname);
s.rwString(ref ceiltexname);
//s.rwLong(ref longfloortexname);
//s.rwLong(ref longceiltexname);
s.rwLong(ref longfloortexname);
s.rwLong(ref longceiltexname);
s.rwInt(ref effect);
s.rwInt(ref tag);
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
@ -237,6 +210,8 @@ namespace CodeImp.DoomBuilder.Map
// This copies all properties to another sector
public void CopyPropertiesTo(Sector s)
{
s.BeforePropsChange();
// Copy properties
s.ceilheight = ceilheight;
s.ceiltexname = ceiltexname;
@ -252,7 +227,7 @@ namespace CodeImp.DoomBuilder.Map
}
// This attaches a sidedef and returns the listitem
public LinkedListNode<Sidedef> AttachSidedef(Sidedef sd)
internal LinkedListNode<Sidedef> AttachSidedefP(Sidedef sd)
{
updateneeded = true;
triangulationneeded = true;
@ -260,7 +235,7 @@ namespace CodeImp.DoomBuilder.Map
}
// This detaches a sidedef
public void DetachSidedef(LinkedListNode<Sidedef> l)
internal void DetachSidedefP(LinkedListNode<Sidedef> l)
{
// Not disposing?
if(!isdisposed)
@ -357,6 +332,8 @@ namespace CodeImp.DoomBuilder.Map
// This updates the floor surface
public void UpdateFloorSurface()
{
if(flatvertices == null) return;
// Create floor vertices
FlatVertex[] floorvertices = new FlatVertex[flatvertices.Length];
flatvertices.CopyTo(floorvertices, 0);
@ -372,6 +349,8 @@ namespace CodeImp.DoomBuilder.Map
// This updates the ceiling surface
public void UpdateCeilingSurface()
{
if(flatvertices == null) return;
// Create ceiling vertices
FlatVertex[] ceilvertices = new FlatVertex[flatvertices.Length];
flatvertices.CopyTo(ceilvertices, 0);
@ -484,7 +463,7 @@ namespace CodeImp.DoomBuilder.Map
// Change secter reference on my sidedefs
// This automatically disposes this sector
while(sidedefs != null)
sidedefs.First.Value.ChangeSector(other);
sidedefs.First.Value.SetSector(other);
}
else
{
@ -509,6 +488,8 @@ namespace CodeImp.DoomBuilder.Map
// This updates all properties
public void Update(int hfloor, int hceil, string tfloor, string tceil, int effect, int tag, int brightness)
{
BeforePropsChange();
// Apply changes
this.floorheight = hfloor;
this.ceilheight = hceil;
@ -523,6 +504,8 @@ namespace CodeImp.DoomBuilder.Map
// This sets texture
public void SetFloorTexture(string name)
{
BeforePropsChange();
floortexname = name;
longfloortexname = Lump.MakeLongName(name);
updateneeded = true;
@ -532,6 +515,8 @@ namespace CodeImp.DoomBuilder.Map
// This sets texture
public void SetCeilTexture(string name)
{
BeforePropsChange();
ceiltexname = name;
longceiltexname = Lump.MakeLongName(name);
updateneeded = true;

View file

@ -67,13 +67,13 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Properties
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 Sidedef Other { get { if(this == linedef.Front) return linedef.Back; else return linedef.Front; } }
public Sector Sector { get { return sector; } }
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 OffsetY { get { return offsety; } set { offsety = value; } }
public int OffsetX { get { return offsetx; } set { BeforePropsChange(); offsetx = value; } }
public int OffsetY { get { return offsety; } set { BeforePropsChange(); offsety = value; } }
public string HighTexture { get { return texnamehigh; } }
public string MiddleTexture { get { return texnamemid; } }
public string LowTexture { get { return texnamelow; } }
@ -92,8 +92,6 @@ namespace CodeImp.DoomBuilder.Map
// Initialize
this.map = map;
this.listindex = listindex;
this.linedef = l;
this.sector = s;
this.texnamehigh = "-";
this.texnamemid = "-";
this.texnamelow = "-";
@ -101,33 +99,22 @@ namespace CodeImp.DoomBuilder.Map
this.longtexnamemid = MapSet.EmptyLongName;
this.longtexnamelow = MapSet.EmptyLongName;
// Attach to the linedef
if(front) l.AttachFront(this); else l.AttachBack(this);
// Attach to sector
sectorlistitem = s.AttachSidedef(this);
// We have no destructor
GC.SuppressFinalize(this);
}
// Constructor
internal Sidedef(MapSet map, int listindex, Linedef l, bool front, Sector s, IReadWriteStream stream)
{
// Initialize
this.map = map;
this.listindex = listindex;
// Attach linedef
this.linedef = l;
this.sector = s;
// Attach to the linedef
if(front) l.AttachFront(this); else l.AttachBack(this);
// Attach to sector
sectorlistitem = s.AttachSidedef(this);
ReadWrite(stream);
if(l != null)
{
if(front)
l.AttachFrontP(this);
else
l.AttachBackP(this);
}
// Attach sector
SetSectorP(s);
if(map == General.Map.Map)
General.Map.UndoRedo.RecAddSidedef(this);
// We have no destructor
GC.SuppressFinalize(this);
}
@ -141,15 +128,18 @@ namespace CodeImp.DoomBuilder.Map
// Already set isdisposed so that changes can be prohibited
isdisposed = true;
if(map == General.Map.Map)
General.Map.UndoRedo.RecRemSidedef(this);
// Remove from main list
map.RemoveSidedef(listindex);
// Detach from linedef
linedef.DetachSidedef(this);
if(linedef != null) linedef.DetachSidedefP(this);
// Detach from sector
sector.DetachSidedef(sectorlistitem);
SetSectorP(null);
// Clean up
sectorlistitem = null;
linedef = null;
@ -164,31 +154,36 @@ namespace CodeImp.DoomBuilder.Map
#endregion
#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)
{
base.ReadWrite(s);
if(!s.IsWriting) BeforePropsChange();
base.ReadWrite(s);
s.rwInt(ref offsetx);
s.rwInt(ref offsety);
s.rwString(ref texnamehigh);
s.rwString(ref texnamemid);
s.rwString(ref texnamelow);
//s.rwLong(ref longtexnamehigh);
//s.rwLong(ref longtexnamemid);
//s.rwLong(ref longtexnamelow);
if(!s.IsWriting)
{
longtexnamehigh = Lump.MakeLongName(texnamehigh);
longtexnamemid = Lump.MakeLongName(texnamemid);
longtexnamelow = Lump.MakeLongName(texnamelow);
}
s.rwLong(ref longtexnamehigh);
s.rwLong(ref longtexnamemid);
s.rwLong(ref longtexnamelow);
}
// This copies all properties to another sidedef
public void CopyPropertiesTo(Sidedef s)
{
s.BeforePropsChange();
// Copy properties
s.offsetx = offsetx;
s.offsety = offsety;
@ -201,72 +196,50 @@ namespace CodeImp.DoomBuilder.Map
base.CopyPropertiesTo(s);
}
// This creates a checksum from the sidedef properties
// Used for faster sidedefs compression
public uint GetChecksum()
// This changes sector
public void SetSector(Sector newsector)
{
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;
if(map == General.Map.Map)
General.Map.UndoRedo.RecRefSidedefSector(this);
// Upper texture set?
if((texnamehigh.Length > 0) && (texnamehigh[0] != '-'))
{
// Copy upper texture
s.texnamehigh = texnamehigh;
s.longtexnamehigh = longtexnamehigh;
// Change sector
SetSectorP(newsector);
}
// Counts as a half coice for copying offsets
copyoffsets += 1;
}
internal void SetSectorP(Sector newsector)
{
// Detach from sector
if(sector != null) sector.DetachSidedefP(sectorlistitem);
// Middle texture set?
if((texnamemid.Length > 0) && (texnamemid[0] != '-'))
{
// Copy middle texture
s.texnamemid = texnamemid;
s.longtexnamemid = longtexnamemid;
// Change sector
sector = newsector;
// 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;
}
// Attach to sector
if(sector != null)
sectorlistitem = sector.AttachSidedefP(this);
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
@ -281,6 +254,8 @@ namespace CodeImp.DoomBuilder.Map
// This removes textures that are not required
public void RemoveUnneededTextures(bool removemiddle, bool force)
{
BeforePropsChange();
// The middle texture can be removed regardless of any sector tag or linedef action
if(!MiddleRequired() && removemiddle)
{
@ -347,6 +322,75 @@ namespace CodeImp.DoomBuilder.Map
return false;
}
}
// 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
@ -355,6 +399,8 @@ namespace CodeImp.DoomBuilder.Map
// This updates all properties
public void Update(int offsetx, int offsety, string thigh, string tmid, string tlow)
{
BeforePropsChange();
// Apply changes
this.offsetx = offsetx;
this.offsety = offsety;
@ -366,6 +412,8 @@ namespace CodeImp.DoomBuilder.Map
// This sets texture
public void SetTextureHigh(string name)
{
BeforePropsChange();
texnamehigh = name;
longtexnamehigh = Lump.MakeLongName(name);
General.Map.IsChanged = true;
@ -374,6 +422,8 @@ namespace CodeImp.DoomBuilder.Map
// This sets texture
public void SetTextureMid(string name)
{
BeforePropsChange();
texnamemid = name;
longtexnamemid = Lump.MakeLongName(name);
General.Map.IsChanged = true;
@ -382,26 +432,12 @@ namespace CodeImp.DoomBuilder.Map
// This sets texture
public void SetTextureLow(string name)
{
BeforePropsChange();
texnamelow = name;
longtexnamelow = Lump.MakeLongName(name);
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
}

View file

@ -71,18 +71,18 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Properties
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 float Angle { get { return angle; } }
public int AngleDeg { get { return (int)Angle2D.RadToDeg(angle); } }
public Dictionary<string, bool> Flags { get { return flags; } }
public int Action { get { return action; } set { action = value; } }
internal Dictionary<string, bool> Flags { get { return flags; } }
public int Action { get { return action; } set { BeforePropsChange(); action = value; } }
public int[] Args { get { return args; } }
public float Size { get { return size; } }
public float IconOffset { get { return iconoffset; } }
public PixelColor Color { get { return color; } }
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; } }
#endregion
@ -98,6 +98,9 @@ namespace CodeImp.DoomBuilder.Map
this.flags = new Dictionary<string, bool>();
this.args = new int[NUM_ARGS];
if(map == General.Map.Map)
General.Map.UndoRedo.RecAddThing(this);
// We have no destructor
GC.SuppressFinalize(this);
}
@ -111,6 +114,9 @@ namespace CodeImp.DoomBuilder.Map
// Already set isdisposed so that changes can be prohibited
isdisposed = true;
if(map == General.Map.Map)
General.Map.UndoRedo.RecRemThing(this);
// Remove from main list
map.RemoveThing(listindex);
@ -129,10 +135,19 @@ namespace CodeImp.DoomBuilder.Map
#endregion
#region ================== Management
// Call this before changing properties
protected override void BeforePropsChange()
{
if(map == General.Map.Map)
General.Map.UndoRedo.RecPrpThing(this);
}
// Serialize / deserialize
internal void ReadWrite(IReadWriteStream s)
{
if(!s.IsWriting) BeforePropsChange();
base.ReadWrite(s);
if(s.IsWriting)
@ -169,6 +184,8 @@ namespace CodeImp.DoomBuilder.Map
// This copies all properties to another thing
public void CopyPropertiesTo(Thing t)
{
t.BeforePropsChange();
// Copy properties
t.type = type;
t.angle = angle;
@ -325,6 +342,8 @@ namespace CodeImp.DoomBuilder.Map
// NOTE: This does not update sector! (call DetermineSector)
public void Move(Vector3D newpos)
{
BeforePropsChange();
// Change position
this.pos = newpos;
General.Map.IsChanged = true;
@ -334,6 +353,8 @@ namespace CodeImp.DoomBuilder.Map
// NOTE: This does not update sector! (call DetermineSector)
public void Move(Vector2D newpos)
{
BeforePropsChange();
// Change position
this.pos = new Vector3D(newpos.x, newpos.y, pos.z);
General.Map.IsChanged = true;
@ -343,6 +364,8 @@ namespace CodeImp.DoomBuilder.Map
// NOTE: This does not update sector! (call DetermineSector)
public void Move(float x, float y, float zoffset)
{
BeforePropsChange();
// Change position
this.pos = new Vector3D(x, y, zoffset);
General.Map.IsChanged = true;
@ -351,6 +374,8 @@ namespace CodeImp.DoomBuilder.Map
// This rotates the thing
public void Rotate(float newangle)
{
BeforePropsChange();
// Change angle
this.angle = newangle;
General.Map.IsChanged = true;
@ -403,7 +428,41 @@ namespace CodeImp.DoomBuilder.Map
#endregion
#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
public void SnapToGrid()
{

View file

@ -15,6 +15,10 @@ namespace CodeImp.DoomBuilder.Map
/// </summary>
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
///<summary></summary>
public UniFields() : base(2)
@ -32,5 +36,33 @@ namespace CodeImp.DoomBuilder.Map
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();
}
}
}

View file

@ -81,20 +81,9 @@ namespace CodeImp.DoomBuilder.Map
this.listindex = listindex;
this.pos = pos;
// We have no destructor
GC.SuppressFinalize(this);
}
// Constructor
internal Vertex(MapSet map, int listindex, IReadWriteStream stream)
{
// Initialize
this.map = map;
this.linedefs = new LinkedList<Linedef>();
this.listindex = listindex;
ReadWrite(stream);
if(map == General.Map.Map)
General.Map.UndoRedo.RecAddVertex(this);
// We have no destructor
GC.SuppressFinalize(this);
}
@ -107,6 +96,9 @@ namespace CodeImp.DoomBuilder.Map
{
// Already set isdisposed so that changes can be prohibited
isdisposed = true;
if(map == General.Map.Map)
General.Map.UndoRedo.RecRemVertex(this);
// Remove from main list
map.RemoveVertex(listindex);
@ -120,7 +112,7 @@ namespace CodeImp.DoomBuilder.Map
else
{
// Detach from linedefs
foreach(Linedef ld in linedefs) ld.DetachVertex(this);
foreach(Linedef ld in linedefs) ld.DetachVertexP(this);
}
// Clean up
@ -136,11 +128,21 @@ namespace CodeImp.DoomBuilder.Map
#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
public LinkedListNode<Linedef> AttachLinedef(Linedef l) { return linedefs.AddLast(l); }
internal LinkedListNode<Linedef> AttachLinedefP(Linedef l)
{
return linedefs.AddLast(l);
}
// This detaches a linedef
public void DetachLinedef(LinkedListNode<Linedef> l)
internal void DetachLinedefP(LinkedListNode<Linedef> l)
{
// Not disposing?
if(!isdisposed)
@ -160,9 +162,17 @@ namespace CodeImp.DoomBuilder.Map
// Serialize / deserialize
internal void ReadWrite(IReadWriteStream s)
{
if(!s.IsWriting) BeforePropsChange();
base.ReadWrite(s);
s.rwVector2D(ref pos);
if(s.IsWriting)
{
// Let all lines know they need an update
foreach(Linedef l in linedefs) l.NeedUpdate();
}
}
// Selected
@ -187,6 +197,8 @@ namespace CodeImp.DoomBuilder.Map
// This copies all properties to another thing
public void CopyPropertiesTo(Vertex v)
{
v.BeforePropsChange();
// Copy properties
v.pos = pos;
base.CopyPropertiesTo(v);
@ -213,6 +225,8 @@ namespace CodeImp.DoomBuilder.Map
// Do we actually move?
if(newpos != pos)
{
BeforePropsChange();
// Change position
pos = newpos;

View file

@ -575,22 +575,20 @@ namespace CodeImp.DoomBuilder.Rendering
// This returns the color for a linedef
public PixelColor DetermineLinedefColor(Linedef l)
{
// Impassable lines
if(l.IsFlagSet(General.Map.Config.ImpassableFlag))
if(l.Selected)
return General.Colors.Selection;
else if(l.ImpassableFlag)
{
// Determine color
if(l.Selected) return General.Colors.Selection;
else if(l.Action != 0) return General.Colors.Actions;
// Impassable lines
if(l.Action != 0) return General.Colors.Actions;
else return General.Colors.Linedefs;
}
else
{
// Determine color
byte a = (byte)(General.Settings.DoubleSidedAlpha * 255.0f);
if(l.Selected) return General.Colors.Selection;
else if(l.Action != 0) return General.Colors.Actions.WithAlpha(a);
else if(l.IsFlagSet(General.Map.Config.SoundLinedefFlag)) return General.Colors.Sounds.WithAlpha(a);
else return General.Colors.Linedefs.WithAlpha(a);
// Passable lines
if(l.Action != 0) return General.Colors.Actions.WithAlpha(General.Settings.DoubleSidedAlphaByte);
else if(l.BlockSoundFlag) return General.Colors.Sounds.WithAlpha(General.Settings.DoubleSidedAlphaByte);
else return General.Colors.Linedefs.WithAlpha(General.Settings.DoubleSidedAlphaByte);
}
}

View file

@ -191,8 +191,7 @@ namespace CodeImp.DoomBuilder.VisualModes
public override void OnUndoEnd()
{
base.OnUndoEnd();
ResourcesReloaded();
General.Map.Data.UpdateUsedTextures();
ResourcesReloadedPartial();
renderer.SetCrosshairBusy(false);
}
@ -206,8 +205,7 @@ namespace CodeImp.DoomBuilder.VisualModes
public override void OnRedoEnd()
{
base.OnRedoEnd();
ResourcesReloaded();
General.Map.Data.UpdateUsedTextures();
ResourcesReloadedPartial();
renderer.SetCrosshairBusy(false);
}
@ -616,8 +614,7 @@ namespace CodeImp.DoomBuilder.VisualModes
#region ================== Processing
/// <summary>
/// This disposes all resources and rebuilds the ones needed.
/// This usually happens when geometry is changed by undo, redo, cut or paste actions.
/// This disposes all resources. Needed geometry will be rebuild automatically.
/// </summary>
protected virtual void ResourcesReloaded()
{
@ -647,7 +644,92 @@ namespace CodeImp.DoomBuilder.VisualModes
// Visibility culling (this re-creates the needed resources)
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>
/// Implement this to create an instance of your VisualSector implementation.
/// </summary>

View file

@ -362,8 +362,8 @@ namespace CodeImp.DoomBuilder.Windows
// Apply all flags
foreach(CheckBox c in flags.Checkboxes)
{
if(c.CheckState == CheckState.Checked) l.Flags[c.Tag.ToString()] = true;
else if(c.CheckState == CheckState.Unchecked) l.Flags[c.Tag.ToString()] = false;
if(c.CheckState == CheckState.Checked) l.SetFlag(c.Tag.ToString(), true);
else if(c.CheckState == CheckState.Unchecked) l.SetFlag(c.Tag.ToString(), false);
}
// Apply chosen activation flag
@ -374,8 +374,8 @@ namespace CodeImp.DoomBuilder.Windows
foreach(CheckBox c in udmfactivates.Checkboxes)
{
LinedefActivateInfo ai = (c.Tag as LinedefActivateInfo);
if(c.CheckState == CheckState.Checked) l.Flags[ai.Key] = true;
else if(c.CheckState == CheckState.Unchecked) l.Flags[ai.Key] = false;
if(c.CheckState == CheckState.Checked) l.SetFlag(ai.Key, true);
else if(c.CheckState == CheckState.Unchecked) l.SetFlag(ai.Key, false);
}
// Action/tags
@ -415,7 +415,7 @@ namespace CodeImp.DoomBuilder.Windows
if(l.Front == null) General.Map.Map.CreateSidedef(l, true, s);
// Change sector?
if(l.Front.Sector != s) l.Front.ChangeSector(s);
if(l.Front.Sector != s) l.Front.SetSector(s);
// Apply settings
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);
// Change sector?
if(l.Back.Sector != s) l.Back.ChangeSector(s);
if(l.Back.Sector != s) l.Back.SetSector(s);
// Apply settings
l.Back.OffsetX = General.Clamp(backoffsetx.GetResult(l.Back.OffsetX), General.Map.FormatInterface.MinTextureOffset, General.Map.FormatInterface.MaxTextureOffset);

View file

@ -291,8 +291,8 @@ namespace CodeImp.DoomBuilder.Windows
// Apply all flags
foreach(CheckBox c in flags.Checkboxes)
{
if(c.CheckState == CheckState.Checked) t.Flags[c.Tag.ToString()] = true;
else if(c.CheckState == CheckState.Unchecked) t.Flags[c.Tag.ToString()] = false;
if(c.CheckState == CheckState.Checked) t.SetFlag(c.Tag.ToString(), true);
else if(c.CheckState == CheckState.Unchecked) t.SetFlag(c.Tag.ToString(), false);
}
// Action/tags

View file

@ -115,6 +115,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.dragstartmappos = dragstartmappos;
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
selectedverts = General.Map.Map.GetMarkedVertices(true);
@ -272,6 +276,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
// Move geometry back to original position
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(selectedverts.Count == 1) General.Map.Map.ClearSelectedVertices();
@ -308,6 +315,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Move geometry back to original position
MoveGeometryRelative(new Vector2D(0f, 0f), false, false);
// Resume normal undo/redo recording
General.Map.UndoRedo.IgnorePropChanges = false;
// Make undo for the dragging
General.Map.UndoRedo.CreateUndo("Drag geometry");
@ -364,10 +374,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
General.Map.Map.Update(true, false);
// 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
protected override void OnEditEnd()
{

View file

@ -136,6 +136,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
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
if(renderer.StartPlotter(true))
{
@ -148,21 +166,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This is important to know, because this item is used
// for snapping to the grid and snapping to nearest items
renderer.PlotVertex(dragitem, ColorCollection.HIGHLIGHT);
// Done
renderer.Finish();
}
if(viewchanged)
{
// Start rendering things
if(renderer.StartThings(true))
{
renderer.RenderThingSet(General.Map.Map.Things, 1.0f);
renderer.Finish();
}
}
// Redraw overlay
if(renderer.StartOverlay(true))
{
@ -172,8 +180,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
renderer.Finish();
}
renderer.Present();
}
#endregion

View file

@ -141,6 +141,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
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
if(renderer.StartPlotter(true))
{
@ -159,16 +177,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
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
if(renderer.StartOverlay(true))
{
@ -178,8 +186,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
renderer.Finish();
}
renderer.Present();
}
#endregion

View file

@ -232,6 +232,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
}
// Render things
UpdateRedraw();
renderer.Present();
}
// This redraws only changed things
private void UpdateRedraw()
{
// Render things
if(renderer.StartThings(true))
{
@ -248,8 +257,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Done
renderer.Finish();
}
renderer.Present();
}
// Cancelled
@ -346,7 +353,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
General.Map.Map.Update();
// Redraw
General.Interface.RedrawDisplay();
UpdateRedraw();
renderer.Present();
//General.Interface.RedrawDisplay();
}
}

View file

@ -123,6 +123,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
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
if(renderer.StartPlotter(true))
{
@ -140,16 +158,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
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
if(renderer.StartOverlay(true))
{
@ -159,8 +167,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
renderer.Finish();
}
renderer.Present();
}
#endregion

View file

@ -613,7 +613,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Add toolbar buttons
General.Interface.AddButton(BuilderPlug.Me.MenusForm.FlipSelectionH);
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
General.Map.Map.ClearAllMarks(false);
General.Map.Map.MarkSelectedVertices(true, true);
@ -751,6 +755,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Paste operation?
if(pasting)
{
// Resume normal undo/redo recording
General.Map.UndoRedo.IgnorePropChanges = false;
// Remove the geometry
int index = 0;
foreach(Vertex v in selectedvertices)
@ -773,6 +780,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
t.Rotate(thingangle[index]);
t.Move(thingpos[index++]);
}
// Resume normal undo/redo recording
General.Map.UndoRedo.IgnorePropChanges = false;
}
General.Map.Map.Update(true, true);
@ -810,7 +820,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Make undo
General.Map.UndoRedo.CreateUndo("Edit selection");
}
// Resume normal undo/redo recording
General.Map.UndoRedo.IgnorePropChanges = false;
// Mark selected geometry
General.Map.Map.ClearAllMarks(false);
General.Map.Map.MarkAllSelectedGeometry(true, true, true, true, false);
@ -863,7 +876,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(joinsidedef != null)
{
// Join!
s.ChangeSector(joinsidedef.Sector);
s.SetSector(joinsidedef.Sector);
s.Marked = false;
joined = true;

View file

@ -912,8 +912,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
sd.SetTextureLow("-");
// Set upper/lower unpegged flags
sd.Line.Flags[General.Map.Config.UpperUnpeggedFlag] = false;
sd.Line.Flags[General.Map.Config.LowerUnpeggedFlag] = true;
sd.Line.SetFlag(General.Map.Config.UpperUnpeggedFlag, false);
sd.Line.SetFlag(General.Map.Config.LowerUnpeggedFlag, true);
}
else
{
@ -923,8 +923,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(doortex.Length > 0) sd.Other.SetTextureHigh(doortex);
// Set upper/lower unpegged flags
sd.Line.Flags[General.Map.Config.UpperUnpeggedFlag] = false;
sd.Line.Flags[General.Map.Config.LowerUnpeggedFlag] = false;
sd.Line.SetFlag(General.Map.Config.UpperUnpeggedFlag, false);
sd.Line.SetFlag(General.Map.Config.LowerUnpeggedFlag, false);
// Get door linedef type from config
sd.Line.Action = General.Map.Config.MakeDoorAction;

View file

@ -113,9 +113,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
type = t.Type;
angle = t.Angle;
flags = new Dictionary<string, bool>(t.Flags);
flags = t.GetFlags();
tag = t.Tag;
action = t.Action;
action = t.Action;
args = (int[])(t.Args.Clone());
}
@ -123,9 +123,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
t.Type = type;
t.Rotate(angle);
t.Flags.Clear();
t.ClearFlags();
foreach(KeyValuePair<string, bool> f in flags)
t.Flags.Add(f.Key, f.Value);
t.SetFlag(f.Key, f.Value);
t.Tag = tag;
t.Action = action;
for(int i = 0; i < t.Args.Length; i++)

View file

@ -220,8 +220,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Toggle upper-unpegged
public virtual void OnToggleUpperUnpegged()
{
if(this.Sidedef.Line.Flags.ContainsKey(General.Map.Config.UpperUnpeggedFlag) &&
this.Sidedef.Line.Flags[General.Map.Config.UpperUnpeggedFlag])
if(this.Sidedef.Line.IsFlagSet(General.Map.Config.UpperUnpeggedFlag))
{
// Remove flag
mode.ApplyUpperUnpegged(false);
@ -236,8 +235,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Toggle lower-unpegged
public virtual void OnToggleLowerUnpegged()
{
if(this.Sidedef.Line.Flags.ContainsKey(General.Map.Config.LowerUnpeggedFlag) &&
this.Sidedef.Line.Flags[General.Map.Config.LowerUnpeggedFlag])
if(this.Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
{
// Remove flag
mode.ApplyLowerUnpegged(false);
@ -258,14 +256,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Remove flag
mode.CreateUndo("Remove 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
{
// Add flag
mode.CreateUndo("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
@ -290,14 +288,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Remove flag
mode.CreateUndo("Remove 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
{
// Add flag
mode.CreateUndo("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

View file

@ -512,6 +512,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
PickTarget();
}
// After resources were partially reloaded
protected override void ResourcesReloadedPartial()
{
base.ResourcesReloadedPartial();
PickTarget();
}
// Mouse moves
public override void OnMouseMove(MouseEventArgs e)
{