- splitten up UDMF reading/writing in seperate classes where they write to/read from a stream. the UniversalMapSetIO now simply makes use of the reader and writer.

- EmptyLongName in MapSet is now a static field
This commit is contained in:
codeimp 2008-09-17 19:21:45 +00:00
parent d9f509fb76
commit b717794aed
12 changed files with 461 additions and 772 deletions

View file

@ -126,10 +126,11 @@
<Compile Include="Data\DataLocationList.cs" />
<Compile Include="Data\DataManager.cs" />
<Compile Include="Data\WADReader.cs" />
<Compile Include="IO\PrefabMapSetIO.cs" />
<Compile Include="IO\UniversalCollection.cs" />
<Compile Include="IO\UniversalEntry.cs" />
<Compile Include="IO\UniversalParser.cs" />
<Compile Include="IO\UniversalStreamReader.cs" />
<Compile Include="IO\UniversalStreamWriter.cs" />
<Compile Include="Map\MapElement.cs" />
<Compile Include="Map\UniFields.cs" />
<Compile Include="Map\UniValue.cs" />

View file

@ -39,6 +39,8 @@ namespace CodeImp.DoomBuilder.Editing
{
#region ================== Constants
private const string CLIPBOARD_DATA_FORMAT = "UDMF_GEOMETRTY";
#endregion
#region ================== Variables
@ -86,6 +88,59 @@ namespace CodeImp.DoomBuilder.Editing
#region ================== Private Methods
// This performs the copy. Returns false when copy was cancelled.
private bool DoCopySelection()
{
// Ask the editing mode to prepare selection for copying.
// The edit mode should mark all vertices, lines and sectors
// that need to be copied.
if(General.Map.Mode.OnCopyBegin())
{
MapSet copyset = new MapSet();
// TODO: Do the copy
// Create temp wadfile
string tempfile = General.MakeTempFilename(General.TempPath);
General.WriteLogLine("Creating temporary file: " + tempfile);
WAD tempwad = new WAD(tempfile);
// Create writer interface
//MapSetIO io = new PrefabMapSetIO(tempwad, General.Map);
// Write to temporary file
General.WriteLogLine("Writing map data structures to file...");
int index = tempwad.FindLumpIndex(MapManager.TEMP_MAP_HEADER);
if(index == -1) index = 0;
//io.Write(copyset, MapManager.TEMP_MAP_HEADER, index);
//Clipboard.SetData(CLIPBOARD_DATA_FORMAT, io.
return true;
}
else
{
General.MessageBeep(MessageBeepType.Warning);
return false;
}
}
// This performs the paste. Returns false when paste was cancelled.
private bool DoPasteSelection()
{
// Ask the editing mode to prepare selection for pasting.
if(General.Map.Mode.OnPasteBegin())
{
// TODO: Do the paste
return true;
}
else
{
General.MessageBeep(MessageBeepType.Warning);
return false;
}
}
#endregion
#region ================== Public Methods
@ -94,7 +149,7 @@ namespace CodeImp.DoomBuilder.Editing
[BeginAction("copyselection")]
public void CopySelection()
{
DoCopySelection();
}
// This cuts the current selection
@ -102,20 +157,21 @@ namespace CodeImp.DoomBuilder.Editing
public void CutSelection()
{
// Copy selected geometry
CopySelection();
// Get the delete action and check if it's bound
Action deleteitem = General.Actions["builder_deleteitem"];
if(deleteitem.BeginBound)
if(DoCopySelection())
{
// Perform delete action
deleteitem.Begin();
deleteitem.End();
}
else
{
// Action not bound
General.Interface.DisplayWarning("Cannot remove that in this mode.");
// Get the delete action and check if it's bound
Action deleteitem = General.Actions["builder_deleteitem"];
if(deleteitem.BeginBound)
{
// Perform delete action
deleteitem.Begin();
deleteitem.End();
}
else
{
// Action not bound
General.Interface.DisplayWarning("Cannot remove that in this mode.");
}
}
}
@ -123,7 +179,7 @@ namespace CodeImp.DoomBuilder.Editing
[BeginAction("pasteselection")]
public void PasteSelection()
{
DoPasteSelection();
}
#endregion

View file

@ -162,8 +162,15 @@ namespace CodeImp.DoomBuilder.Editing
// This forces the mode to cancel and return to the "parent" mode
public virtual void OnCancel() { }
public virtual void OnAccept() { }
// Called before copying. Return false when copying should be cancelled.
// The edit mode should mark all vertices, lines and sectors
// that need to be copied.
public virtual bool OnCopyBegin() { return false; }
// Called before pasting. Return false when paste should be cancelled.
public virtual bool OnPasteBegin() { return false; }
// Interface events
public virtual void OnMouseClick(MouseEventArgs e) { }

View file

@ -509,6 +509,9 @@ namespace CodeImp.DoomBuilder
// Bind static methods to actions
General.Actions.BindMethods(typeof(General));
// Initialize static classes
MapSet.Initialize();
// Create main window
General.WriteLogLine("Loading main interface window...");
mainwindow = new MainForm();

View file

@ -44,8 +44,8 @@ namespace CodeImp.DoomBuilder
#region ================== Constants
// Map header name in temporary file
private const string TEMP_MAP_HEADER = "TEMPMAP";
private const string BUILD_MAP_HEADER = "MAP01";
internal const string TEMP_MAP_HEADER = "TEMPMAP";
internal const string BUILD_MAP_HEADER = "MAP01";
public const string CONFIG_MAP_HEADER = "~MAP";
// Save modes

View file

@ -540,11 +540,11 @@ namespace CodeImp.DoomBuilder.Geometry
// This takes sidedef settings if not taken yet
private static void TakeSidedefSettings(ref SidedefSettings settings, Sidedef side)
{
if((side.LongHighTexture != General.Map.Map.EmptyLongName) && (settings.newtexhigh == null))
if((side.LongHighTexture != MapSet.EmptyLongName) && (settings.newtexhigh == null))
settings.newtexhigh = side.HighTexture;
if((side.LongMiddleTexture != General.Map.Map.EmptyLongName) && (settings.newtexmid == null))
if((side.LongMiddleTexture != MapSet.EmptyLongName) && (settings.newtexmid == null))
settings.newtexmid = side.MiddleTexture;
if((side.LongLowTexture != General.Map.Map.EmptyLongName) && (settings.newtexlow == null))
if((side.LongLowTexture != MapSet.EmptyLongName) && (settings.newtexlow == null))
settings.newtexlow = side.LowTexture;
}

View file

@ -108,10 +108,7 @@ namespace CodeImp.DoomBuilder.IO
// This reads a map from the file and returns a MapSet
public override MapSet Read(MapSet map, string mapname)
{
UniversalParser textmap = new UniversalParser();
StreamReader lumpreader = null;
Dictionary<int, Vertex> vertexlink;
Dictionary<int, Sector> sectorlink;
UniversalStreamReader udmfreader = new UniversalStreamReader();
// Find the index where first map lump begins
int firstindex = wad.FindLumpIndex(mapname) + 1;
@ -120,313 +117,14 @@ namespace CodeImp.DoomBuilder.IO
Lump lump = wad.FindLump("TEXTMAP", firstindex);
if(lump == null) throw new Exception("Could not find required lump TEXTMAP!");
try
{
// Parse the UDMF data
lumpreader = new StreamReader(lump.Stream, Encoding.ASCII);
lump.Stream.Seek(0, SeekOrigin.Begin);
textmap.InputConfiguration(lumpreader.ReadToEnd());
// Check for errors
if(textmap.ErrorResult != 0)
{
// Show parse error
General.ShowErrorMessage("Error while parsing UDMF map data:\n" + textmap.ErrorDescription, MessageBoxButtons.OK);
}
else
{
// Read the map
vertexlink = ReadVertices(map, textmap);
sectorlink = ReadSectors(map, textmap);
ReadLinedefs(map, textmap, vertexlink, sectorlink);
ReadThings(map, textmap);
}
}
catch(Exception e)
{
General.ShowErrorMessage("Unexpected error reading UDMF map data. " + e.GetType().Name + ": " + e.Message, MessageBoxButtons.OK);
}
finally
{
if(lumpreader != null) lumpreader.Dispose();
}
// Read the UDMF data
lump.Stream.Seek(0, SeekOrigin.Begin);
udmfreader.SetKnownCustomTypes = true;
udmfreader.Read(map, lump.Stream);
// Return result
return map;
}
// This reads the things
private void ReadThings(MapSet map, UniversalParser textmap)
{
// Get list of entries
List<UniversalCollection> collections = GetNamedCollections(textmap.Root, "thing");
// Go for all collections
for(int i = 0; i < collections.Count; i++)
{
// Read fields
UniversalCollection c = collections[i];
int[] args = new int[Linedef.NUM_ARGS];
float x = GetCollectionEntry<float>(c, "x", true, 0.0f);
float y = GetCollectionEntry<float>(c, "y", true, 0.0f);
float height = GetCollectionEntry<float>(c, "height", false, 0.0f);
int tag = GetCollectionEntry<int>(c, "id", false, 0);
int angledeg = GetCollectionEntry<int>(c, "angle", false, 0);
int type = GetCollectionEntry<int>(c, "type", true, 0);
int special = GetCollectionEntry<int>(c, "special", false, 0);
args[0] = GetCollectionEntry<int>(c, "arg0", false, 0);
args[1] = GetCollectionEntry<int>(c, "arg1", false, 0);
args[2] = GetCollectionEntry<int>(c, "arg2", false, 0);
args[3] = GetCollectionEntry<int>(c, "arg3", false, 0);
args[4] = GetCollectionEntry<int>(c, "arg4", false, 0);
// Flags
Dictionary<string, bool> stringflags = new Dictionary<string, bool>();
foreach(KeyValuePair<string, string> flag in General.Map.Config.ThingFlags)
stringflags[flag.Key] = GetCollectionEntry<bool>(c, flag.Key, false, false);
// Create new item
Thing t = map.CreateThing();
t.Update(type, x, y, height, Angle2D.DegToRad(angledeg), stringflags, tag, special, args);
//t.DetermineSector();
t.UpdateConfiguration();
// Custom fields
ReadCustomFields(c, t, "thing");
}
}
// This reads the linedefs and sidedefs
private void ReadLinedefs(MapSet map, UniversalParser textmap,
Dictionary<int, Vertex> vertexlink, Dictionary<int, Sector> sectorlink)
{
// Get list of entries
List<UniversalCollection> linescolls = GetNamedCollections(textmap.Root, "linedef");
List<UniversalCollection> sidescolls = GetNamedCollections(textmap.Root, "sidedef");
// Go for all lines
for(int i = 0; i < linescolls.Count; i++)
{
// Read fields
UniversalCollection lc = linescolls[i];
int[] args = new int[Linedef.NUM_ARGS];
int tag = GetCollectionEntry<int>(lc, "id", false, 0);
int v1 = GetCollectionEntry<int>(lc, "v1", true, 0);
int v2 = GetCollectionEntry<int>(lc, "v2", true, 0);
int special = GetCollectionEntry<int>(lc, "special", false, 0);
args[0] = GetCollectionEntry<int>(lc, "arg0", false, 0);
args[1] = GetCollectionEntry<int>(lc, "arg1", false, 0);
args[2] = GetCollectionEntry<int>(lc, "arg2", false, 0);
args[3] = GetCollectionEntry<int>(lc, "arg3", false, 0);
args[4] = GetCollectionEntry<int>(lc, "arg4", false, 0);
int s1 = GetCollectionEntry<int>(lc, "sidefront", true, -1);
int s2 = GetCollectionEntry<int>(lc, "sideback", false, -1);
// Flags
Dictionary<string, bool> stringflags = new Dictionary<string, bool>();
foreach(KeyValuePair<string, string> flag in General.Map.Config.LinedefFlags)
stringflags[flag.Key] = GetCollectionEntry<bool>(lc, flag.Key, false, false);
// Activations
foreach(LinedefActivateInfo activate in General.Map.Config.LinedefActivates)
stringflags[activate.Key] = GetCollectionEntry<bool>(lc, activate.Key, false, false);
// Create new item
Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
l.Update(stringflags, 0, tag, special, args);
l.UpdateCache();
// Custom fields
ReadCustomFields(lc, l, "linedef");
// Read sidedefs and connect them to the line
if(s1 > -1) ReadSidedef(map, sidescolls[s1], l, true, sectorlink);
if(s2 > -1) ReadSidedef(map, sidescolls[s2], l, false, sectorlink);
}
}
// This reads a single sidedef and connects it to the given linedef
private void ReadSidedef(MapSet map, UniversalCollection sc, Linedef ld,
bool front, Dictionary<int, Sector> sectorlink)
{
// Read fields
int offsetx = GetCollectionEntry<int>(sc, "offsetx", false, 0);
int offsety = GetCollectionEntry<int>(sc, "offsety", false, 0);
string thigh = GetCollectionEntry<string>(sc, "texturetop", false, "-");
string tlow = GetCollectionEntry<string>(sc, "texturebottom", false, "-");
string tmid = GetCollectionEntry<string>(sc, "texturemiddle", false, "-");
int sector = GetCollectionEntry<int>(sc, "sector", true, 0);
// Create sidedef
Sidedef s = map.CreateSidedef(ld, front, sectorlink[sector]);
s.Update(offsetx, offsety, thigh, tmid, tlow);
// Custom fields
ReadCustomFields(sc, s, "sidedef");
}
// This reads the sectors
private Dictionary<int, Sector> ReadSectors(MapSet map, UniversalParser textmap)
{
Dictionary<int, Sector> link;
// Get list of entries
List<UniversalCollection> collections = GetNamedCollections(textmap.Root, "sector");
// Create lookup table
link = new Dictionary<int, Sector>(collections.Count);
// Go for all collections
for(int i = 0; i < collections.Count; i++)
{
// Read fields
UniversalCollection c = collections[i];
int hfloor = GetCollectionEntry<int>(c, "heightfloor", false, 0);
int hceil = GetCollectionEntry<int>(c, "heightceiling", false, 0);
string tfloor = GetCollectionEntry<string>(c, "texturefloor", true, "-");
string tceil = GetCollectionEntry<string>(c, "textureceiling", true, "-");
int bright = GetCollectionEntry<int>(c, "lightlevel", false, 160);
int special = GetCollectionEntry<int>(c, "special", false, 0);
int tag = GetCollectionEntry<int>(c, "id", false, 0);
// Create new item
Sector s = map.CreateSector();
s.Update(hfloor, hceil, tfloor, tceil, special, tag, bright);
// Custom fields
ReadCustomFields(c, s, "sector");
// Add it to the lookup table
link.Add(i, s);
}
// Return lookup table
return link;
}
// This reads the vertices
private Dictionary<int, Vertex> ReadVertices(MapSet map, UniversalParser textmap)
{
Dictionary<int, Vertex> link;
// Get list of entries
List<UniversalCollection> collections = GetNamedCollections(textmap.Root, "vertex");
// Create lookup table
link = new Dictionary<int, Vertex>(collections.Count);
// Go for all collections
for(int i = 0; i < collections.Count; i++)
{
// Read fields
UniversalCollection c = collections[i];
float x = GetCollectionEntry<float>(c, "x", true, 0.0f);
float y = GetCollectionEntry<float>(c, "y", true, 0.0f);
// Create new item
Vertex v = map.CreateVertex(new Vector2D(x, y));
// Custom fields
ReadCustomFields(c, v, "vertex");
// Add it to the lookup table
link.Add(i, v);
}
// Return lookup table
return link;
}
// This reads custom fields from a collection and adds them to a map element
private void ReadCustomFields(UniversalCollection collection, MapElement element, string elementname)
{
// Go for all the elements in the collection
foreach(UniversalEntry e in collection)
{
// Check if not a managed field
if(!config.SettingExists("managedfields." + elementname + "." + e.Key))
{
int type = (int)UniversalType.Integer;
// Determine default type
if(e.Value.GetType() == typeof(int)) type = (int)UniversalType.Integer;
else if(e.Value.GetType() == typeof(float)) type = (int)UniversalType.Float;
else if(e.Value.GetType() == typeof(bool)) type = (int)UniversalType.Boolean;
else if(e.Value.GetType() == typeof(string)) type = (int)UniversalType.String;
// Try to find the type from configuration
type = manager.Options.GetUniversalFieldType(elementname, e.Key, type);
// Make custom field
element.Fields.Add(e.Key, new UniValue(type, e.Value));
}
}
}
// This validates and returns an entry
private T GetCollectionEntry<T>(UniversalCollection c, string entryname, bool required, T defaultvalue)
{
T result = default(T);
bool found = false;
// Find the entry
foreach(UniversalEntry e in c)
{
// Check if matches
if(e.Key == entryname)
{
// Let's be kind and cast any int to a float if needed
if((typeof(T) == typeof(float)) &&
(e.Value.GetType() == typeof(int)))
{
// Make it a float
result = (T)e.Value;
}
else
{
// Verify type
e.ValidateType(typeof(T));
// Found it!
result = (T)e.Value;
}
// Done
found = true;
}
}
// Not found?
if(!found)
{
// Entry is required?
if(required)
{
// Error, cannot find required entry!
throw new Exception("Error while reading UDMF map data: Missing required field '" + entryname + "'.");
}
else
{
// Make default entry
result = defaultvalue;
}
}
// Return result
return result;
}
// This makes a list of all collections with the given name
private List<UniversalCollection> GetNamedCollections(UniversalCollection collection, string entryname)
{
List<UniversalCollection> list = new List<UniversalCollection>();
// Make list
foreach(UniversalEntry e in collection)
if((e.Value is UniversalCollection) && (e.Key == entryname)) list.Add(e.Value as UniversalCollection);
return list;
}
#endregion
@ -435,194 +133,26 @@ namespace CodeImp.DoomBuilder.IO
// This writes a MapSet to the file
public override void Write(MapSet map, string mapname, int position)
{
UniversalParser textmap = new UniversalParser();
// Begin with fields that must be at the top
textmap.Root.Add("namespace", manager.Config.EngineName);
Dictionary<Vertex, int> vertexids = new Dictionary<Vertex, int>();
Dictionary<Sidedef, int> sidedefids = new Dictionary<Sidedef, int>();
Dictionary<Sector, int> sectorids = new Dictionary<Sector, int>();
// Index the elements in the data structures
foreach(Vertex v in map.Vertices) vertexids.Add(v, vertexids.Count);
foreach(Sidedef sd in map.Sidedefs) sidedefids.Add(sd, sidedefids.Count);
foreach(Sector s in map.Sectors) sectorids.Add(s, sectorids.Count);
// We will write the custom field types again, so forget
// all previous field types (this gets rid of unused field types)
manager.Options.ForgetUniversalFieldTypes();
// Write the data structures to textmap
WriteVertices(map, textmap);
WriteLinedefs(map, textmap, sidedefids, vertexids);
WriteSidedefs(map, textmap, sectorids);
WriteSectors(map, textmap);
WriteThings(map, textmap);
// Get the textmap as string
string textmapstr = textmap.OutputConfiguration();
UniversalStreamWriter udmfwriter = new UniversalStreamWriter();
// Write map to memory stream
MemoryStream memstream = new MemoryStream();
memstream.Seek(0, SeekOrigin.Begin);
udmfwriter.RememberCustomTypes = true;
udmfwriter.Write(map, memstream, manager.Config.EngineName);
// Find insert position and remove old lump
int insertpos = MapManager.RemoveSpecificLump(wad, "TEXTMAP", position, "", manager.Config.MapLumpNames);
if(insertpos == -1) insertpos = position + 1;
if(insertpos > wad.Lumps.Count) insertpos = wad.Lumps.Count;
// Create the lump from memory
Lump lump = wad.Insert("TEXTMAP", insertpos, textmapstr.Length);
StreamWriter lumpwriter = new StreamWriter(lump.Stream);
Lump lump = wad.Insert("TEXTMAP", insertpos, (int)memstream.Length);
lump.Stream.Seek(0, SeekOrigin.Begin);
lumpwriter.Write(textmapstr);
lumpwriter.Flush();
}
memstream.WriteTo(lump.Stream);
// This writes the vertices
private void WriteVertices(MapSet map, UniversalParser textmap)
{
// Go for all vertices
foreach(Vertex v in map.Vertices)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
coll.Add("x", v.Position.x);
coll.Add("y", v.Position.y);
// Add custom fields
AddCustomFields(v, "vertex", coll);
// Store
textmap.Root.Add("vertex", coll);
}
}
// This writes the linedefs
private void WriteLinedefs(MapSet map, UniversalParser textmap, IDictionary<Sidedef, int> sidedefids, IDictionary<Vertex, int> vertexids)
{
// Go for all linedefs
foreach(Linedef l in map.Linedefs)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
if(l.Tag != 0) coll.Add("id", l.Tag);
coll.Add("v1", vertexids[l.Start]);
coll.Add("v2", vertexids[l.End]);
if(l.Front != null) coll.Add("sidefront", sidedefids[l.Front]); else coll.Add("sidefront", -1);
if(l.Back != null) coll.Add("sideback", sidedefids[l.Back]); else coll.Add("sideback", -1);
if(l.Action != 0) coll.Add("special", l.Action);
if(l.Args[0] != 0) coll.Add("arg0", l.Args[0]);
if(l.Args[1] != 0) coll.Add("arg1", l.Args[1]);
if(l.Args[2] != 0) coll.Add("arg2", l.Args[2]);
if(l.Args[3] != 0) coll.Add("arg3", l.Args[3]);
if(l.Args[4] != 0) coll.Add("arg4", l.Args[4]);
// Flags
foreach(KeyValuePair<string, bool> flag in l.Flags)
if(flag.Value) coll.Add(flag.Key, flag.Value);
// Add custom fields
AddCustomFields(l, "linedef", coll);
// Store
textmap.Root.Add("linedef", coll);
}
}
// This writes the sidedefs
private void WriteSidedefs(MapSet map, UniversalParser textmap, IDictionary<Sector, int> sectorids)
{
// Go for all sidedefs
foreach(Sidedef s in map.Sidedefs)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
if(s.OffsetX != 0) coll.Add("offsetx", s.OffsetX);
if(s.OffsetY != 0) coll.Add("offsety", s.OffsetY);
if(s.LongHighTexture != map.EmptyLongName) coll.Add("texturetop", s.HighTexture);
if(s.LongLowTexture != map.EmptyLongName) coll.Add("texturebottom", s.LowTexture);
if(s.LongMiddleTexture != map.EmptyLongName) coll.Add("texturemiddle", s.MiddleTexture);
coll.Add("sector", sectorids[s.Sector]);
// Add custom fields
AddCustomFields(s, "sidedef", coll);
// Store
textmap.Root.Add("sidedef", coll);
}
}
// This writes the sectors
private void WriteSectors(MapSet map, UniversalParser textmap)
{
// Go for all sectors
foreach(Sector s in map.Sectors)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
coll.Add("heightfloor", s.FloorHeight);
coll.Add("heightceiling", s.CeilHeight);
coll.Add("texturefloor", s.FloorTexture);
coll.Add("textureceiling", s.CeilTexture);
coll.Add("lightlevel", s.Brightness);
if(s.Effect != 0) coll.Add("special", s.Effect);
if(s.Tag != 0) coll.Add("id", s.Tag);
// Add custom fields
AddCustomFields(s, "sector", coll);
// Store
textmap.Root.Add("sector", coll);
}
}
// This writes the things
private void WriteThings(MapSet map, UniversalParser textmap)
{
// Go for all things
foreach(Thing t in map.Things)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
if(t.Tag != 0) coll.Add("id", t.Tag);
coll.Add("x", t.Position.x);
coll.Add("y", t.Position.y);
if(t.Position.z != 0.0f) coll.Add("height", (float)t.Position.z);
coll.Add("angle", t.AngleDeg);
coll.Add("type", t.Type);
if(t.Action != 0) coll.Add("special", t.Action);
if(t.Args[0] != 0) coll.Add("arg0", t.Args[0]);
if(t.Args[1] != 0) coll.Add("arg1", t.Args[1]);
if(t.Args[2] != 0) coll.Add("arg2", t.Args[2]);
if(t.Args[3] != 0) coll.Add("arg3", t.Args[3]);
if(t.Args[4] != 0) coll.Add("arg4", t.Args[4]);
// Flags
foreach(KeyValuePair<string, bool> flag in t.Flags)
if(flag.Value) coll.Add(flag.Key, flag.Value);
// Add custom fields
AddCustomFields(t, "thing", coll);
// Store
textmap.Root.Add("thing", coll);
}
}
// This adds custom fields from a map element to a collection
private void AddCustomFields(MapElement element, string elementname, UniversalCollection collection)
{
// Add custom fields
foreach(KeyValuePair<string, UniValue> f in element.Fields)
{
// Not a managed field?
if(!config.SettingExists("managedfields." + elementname + "." + f.Key))
{
// Add type information to DBS file for map
manager.Options.SetUniversalFieldType(elementname, f.Key, f.Value.Type);
// Store field
collection.Add(f.Key, f.Value.Value);
}
}
// Done
memstream.Dispose();
}
#endregion

View file

@ -32,29 +32,36 @@ using CodeImp.DoomBuilder.Types;
namespace CodeImp.DoomBuilder.IO
{
internal class PrefabMapSetIO : MapSetIO
internal class UniversalStreamReader
{
#region ================== Constants
// Name of the UDMF configuration file
private const string UDMF_CONFIG_NAME = "UDMF.cfg";
#endregion
#region ================== Variables
private Configuration config;
private bool setknowncustomtypes;
#endregion
#region ================== Properties
public bool SetKnownCustomTypes { get { return setknowncustomtypes; } set { setknowncustomtypes = value; } }
#endregion
#region ================== Constructor / Disposer
// Constructor
public PrefabMapSetIO(WAD wad, MapManager manager) : base(wad, manager)
public UniversalStreamReader()
{
// Make configuration
config = new Configuration();
// Find a resource named UDMF.cfg
string[] resnames = General.ThisAssembly.GetManifestResourceNames();
foreach(string rn in resnames)
@ -65,7 +72,7 @@ namespace CodeImp.DoomBuilder.IO
// Get a stream from the resource
Stream udmfcfg = General.ThisAssembly.GetManifestResourceStream(rn);
StreamReader udmfcfgreader = new StreamReader(udmfcfg, Encoding.ASCII);
// Load configuration from stream
config.InputConfiguration(udmfcfgreader.ReadToEnd());
@ -84,7 +91,7 @@ namespace CodeImp.DoomBuilder.IO
// Add thing flags
foreach(KeyValuePair<string, string> flag in General.Map.Config.ThingFlags)
config.WriteSetting("managedfields.thing." + flag.Key, true);
// Done
udmfcfgreader.Dispose();
udmfcfg.Dispose();
@ -95,37 +102,20 @@ namespace CodeImp.DoomBuilder.IO
#endregion
#region ================== Properties
public override int MaxSidedefs { get { return int.MaxValue; } }
public override int VertexDecimals { get { return 8; } }
public override string DecimalsFormat { get { return "0.000"; } }
#endregion
#region ================== Reading
// This reads a map from the file and returns a MapSet
public override MapSet Read(MapSet map, string mapname)
// This reads from a stream
public MapSet Read(MapSet map, Stream stream)
{
UniversalParser textmap = new UniversalParser();
StreamReader lumpreader = null;
StreamReader reader = new StreamReader(stream, Encoding.ASCII);
Dictionary<int, Vertex> vertexlink;
Dictionary<int, Sector> sectorlink;
// Find the index where first map lump begins
int firstindex = wad.FindLumpIndex(mapname) + 1;
// Get the TEXTMAP lump from wad file
Lump lump = wad.FindLump("TEXTMAP", firstindex);
if(lump == null) throw new Exception("Could not find required lump TEXTMAP!");
UniversalParser textmap = new UniversalParser();
try
{
// Parse the UDMF data
lumpreader = new StreamReader(lump.Stream, Encoding.ASCII);
lump.Stream.Seek(0, SeekOrigin.Begin);
textmap.InputConfiguration(lumpreader.ReadToEnd());
// Read UDMF from stream
textmap.InputConfiguration(reader.ReadToEnd());
// Check for errors
if(textmap.ErrorResult != 0)
@ -146,12 +136,7 @@ namespace CodeImp.DoomBuilder.IO
{
General.ShowErrorMessage("Unexpected error reading UDMF map data. " + e.GetType().Name + ": " + e.Message, MessageBoxButtons.OK);
}
finally
{
if(lumpreader != null) lumpreader.Dispose();
}
// Return result
return map;
}
@ -160,7 +145,7 @@ namespace CodeImp.DoomBuilder.IO
{
// Get list of entries
List<UniversalCollection> collections = GetNamedCollections(textmap.Root, "thing");
// Go for all collections
for(int i = 0; i < collections.Count; i++)
{
@ -184,13 +169,13 @@ namespace CodeImp.DoomBuilder.IO
Dictionary<string, bool> stringflags = new Dictionary<string, bool>();
foreach(KeyValuePair<string, string> flag in General.Map.Config.ThingFlags)
stringflags[flag.Key] = GetCollectionEntry<bool>(c, flag.Key, false, false);
// Create new item
Thing t = map.CreateThing();
t.Update(type, x, y, height, Angle2D.DegToRad(angledeg), stringflags, tag, special, args);
//t.DetermineSector();
t.UpdateConfiguration();
// Custom fields
ReadCustomFields(c, t, "thing");
}
@ -221,7 +206,7 @@ namespace CodeImp.DoomBuilder.IO
args[4] = GetCollectionEntry<int>(lc, "arg4", false, 0);
int s1 = GetCollectionEntry<int>(lc, "sidefront", true, -1);
int s2 = GetCollectionEntry<int>(lc, "sideback", false, -1);
// Flags
Dictionary<string, bool> stringflags = new Dictionary<string, bool>();
foreach(KeyValuePair<string, string> flag in General.Map.Config.LinedefFlags)
@ -230,7 +215,7 @@ namespace CodeImp.DoomBuilder.IO
// Activations
foreach(LinedefActivateInfo activate in General.Map.Config.LinedefActivates)
stringflags[activate.Key] = GetCollectionEntry<bool>(lc, activate.Key, false, false);
// Create new item
Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
l.Update(stringflags, 0, tag, special, args);
@ -238,7 +223,7 @@ namespace CodeImp.DoomBuilder.IO
// Custom fields
ReadCustomFields(lc, l, "linedef");
// Read sidedefs and connect them to the line
if(s1 > -1) ReadSidedef(map, sidescolls[s1], l, true, sectorlink);
if(s2 > -1) ReadSidedef(map, sidescolls[s2], l, false, sectorlink);
@ -288,7 +273,7 @@ namespace CodeImp.DoomBuilder.IO
int bright = GetCollectionEntry<int>(c, "lightlevel", false, 160);
int special = GetCollectionEntry<int>(c, "special", false, 0);
int tag = GetCollectionEntry<int>(c, "id", false, 0);
// Create new item
Sector s = map.CreateSector();
s.Update(hfloor, hceil, tfloor, tceil, special, tag, bright);
@ -308,13 +293,13 @@ namespace CodeImp.DoomBuilder.IO
private Dictionary<int, Vertex> ReadVertices(MapSet map, UniversalParser textmap)
{
Dictionary<int, Vertex> link;
// Get list of entries
List<UniversalCollection> collections = GetNamedCollections(textmap.Root, "vertex");
// Create lookup table
link = new Dictionary<int, Vertex>(collections.Count);
// Go for all collections
for(int i = 0; i < collections.Count; i++)
{
@ -328,7 +313,7 @@ namespace CodeImp.DoomBuilder.IO
// Custom fields
ReadCustomFields(c, v, "vertex");
// Add it to the lookup table
link.Add(i, v);
}
@ -347,7 +332,7 @@ namespace CodeImp.DoomBuilder.IO
if(!config.SettingExists("managedfields." + elementname + "." + e.Key))
{
int type = (int)UniversalType.Integer;
// Determine default type
if(e.Value.GetType() == typeof(int)) type = (int)UniversalType.Integer;
else if(e.Value.GetType() == typeof(float)) type = (int)UniversalType.Float;
@ -355,20 +340,21 @@ namespace CodeImp.DoomBuilder.IO
else if(e.Value.GetType() == typeof(string)) type = (int)UniversalType.String;
// Try to find the type from configuration
type = manager.Options.GetUniversalFieldType(elementname, e.Key, type);
if(setknowncustomtypes)
type = General.Map.Options.GetUniversalFieldType(elementname, e.Key, type);
// Make custom field
element.Fields.Add(e.Key, new UniValue(type, e.Value));
}
}
}
// This validates and returns an entry
private T GetCollectionEntry<T>(UniversalCollection c, string entryname, bool required, T defaultvalue)
{
T result = default(T);
bool found = false;
// Find the entry
foreach(UniversalEntry e in c)
{
@ -390,12 +376,12 @@ namespace CodeImp.DoomBuilder.IO
// Found it!
result = (T)e.Value;
}
// Done
found = true;
}
}
// Not found?
if(!found)
{
@ -415,7 +401,7 @@ namespace CodeImp.DoomBuilder.IO
// Return result
return result;
}
// This makes a list of all collections with the given name
private List<UniversalCollection> GetNamedCollections(UniversalCollection collection, string entryname)
{
@ -424,207 +410,10 @@ namespace CodeImp.DoomBuilder.IO
// Make list
foreach(UniversalEntry e in collection)
if((e.Value is UniversalCollection) && (e.Key == entryname)) list.Add(e.Value as UniversalCollection);
return list;
}
#endregion
#region ================== Writing
// This writes a MapSet to the file
public override void Write(MapSet map, string mapname, int position)
{
UniversalParser textmap = new UniversalParser();
// Begin with fields that must be at the top
textmap.Root.Add("namespace", manager.Config.EngineName);
Dictionary<Vertex, int> vertexids = new Dictionary<Vertex, int>();
Dictionary<Sidedef, int> sidedefids = new Dictionary<Sidedef, int>();
Dictionary<Sector, int> sectorids = new Dictionary<Sector, int>();
// Index the elements in the data structures
foreach(Vertex v in map.Vertices) vertexids.Add(v, vertexids.Count);
foreach(Sidedef sd in map.Sidedefs) sidedefids.Add(sd, sidedefids.Count);
foreach(Sector s in map.Sectors) sectorids.Add(s, sectorids.Count);
// We will write the custom field types again, so forget
// all previous field types (this gets rid of unused field types)
manager.Options.ForgetUniversalFieldTypes();
// Write the data structures to textmap
WriteVertices(map, textmap);
WriteLinedefs(map, textmap, sidedefids, vertexids);
WriteSidedefs(map, textmap, sectorids);
WriteSectors(map, textmap);
WriteThings(map, textmap);
// Get the textmap as string
string textmapstr = textmap.OutputConfiguration();
// Find insert position and remove old lump
int insertpos = MapManager.RemoveSpecificLump(wad, "TEXTMAP", position, "", manager.Config.MapLumpNames);
if(insertpos == -1) insertpos = position + 1;
if(insertpos > wad.Lumps.Count) insertpos = wad.Lumps.Count;
// Create the lump from memory
Lump lump = wad.Insert("TEXTMAP", insertpos, textmapstr.Length);
StreamWriter lumpwriter = new StreamWriter(lump.Stream);
lump.Stream.Seek(0, SeekOrigin.Begin);
lumpwriter.Write(textmapstr);
lumpwriter.Flush();
}
// This writes the vertices
private void WriteVertices(MapSet map, UniversalParser textmap)
{
// Go for all vertices
foreach(Vertex v in map.Vertices)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
coll.Add("x", v.Position.x);
coll.Add("y", v.Position.y);
// Add custom fields
AddCustomFields(v, "vertex", coll);
// Store
textmap.Root.Add("vertex", coll);
}
}
// This writes the linedefs
private void WriteLinedefs(MapSet map, UniversalParser textmap, IDictionary<Sidedef, int> sidedefids, IDictionary<Vertex, int> vertexids)
{
// Go for all linedefs
foreach(Linedef l in map.Linedefs)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
if(l.Tag != 0) coll.Add("id", l.Tag);
coll.Add("v1", vertexids[l.Start]);
coll.Add("v2", vertexids[l.End]);
if(l.Front != null) coll.Add("sidefront", sidedefids[l.Front]); else coll.Add("sidefront", -1);
if(l.Back != null) coll.Add("sideback", sidedefids[l.Back]); else coll.Add("sideback", -1);
if(l.Action != 0) coll.Add("special", l.Action);
if(l.Args[0] != 0) coll.Add("arg0", l.Args[0]);
if(l.Args[1] != 0) coll.Add("arg1", l.Args[1]);
if(l.Args[2] != 0) coll.Add("arg2", l.Args[2]);
if(l.Args[3] != 0) coll.Add("arg3", l.Args[3]);
if(l.Args[4] != 0) coll.Add("arg4", l.Args[4]);
// Flags
foreach(KeyValuePair<string, bool> flag in l.Flags)
if(flag.Value) coll.Add(flag.Key, flag.Value);
// Add custom fields
AddCustomFields(l, "linedef", coll);
// Store
textmap.Root.Add("linedef", coll);
}
}
// This writes the sidedefs
private void WriteSidedefs(MapSet map, UniversalParser textmap, IDictionary<Sector, int> sectorids)
{
// Go for all sidedefs
foreach(Sidedef s in map.Sidedefs)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
if(s.OffsetX != 0) coll.Add("offsetx", s.OffsetX);
if(s.OffsetY != 0) coll.Add("offsety", s.OffsetY);
if(s.LongHighTexture != map.EmptyLongName) coll.Add("texturetop", s.HighTexture);
if(s.LongLowTexture != map.EmptyLongName) coll.Add("texturebottom", s.LowTexture);
if(s.LongMiddleTexture != map.EmptyLongName) coll.Add("texturemiddle", s.MiddleTexture);
coll.Add("sector", sectorids[s.Sector]);
// Add custom fields
AddCustomFields(s, "sidedef", coll);
// Store
textmap.Root.Add("sidedef", coll);
}
}
// This writes the sectors
private void WriteSectors(MapSet map, UniversalParser textmap)
{
// Go for all sectors
foreach(Sector s in map.Sectors)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
coll.Add("heightfloor", s.FloorHeight);
coll.Add("heightceiling", s.CeilHeight);
coll.Add("texturefloor", s.FloorTexture);
coll.Add("textureceiling", s.CeilTexture);
coll.Add("lightlevel", s.Brightness);
if(s.Effect != 0) coll.Add("special", s.Effect);
if(s.Tag != 0) coll.Add("id", s.Tag);
// Add custom fields
AddCustomFields(s, "sector", coll);
// Store
textmap.Root.Add("sector", coll);
}
}
// This writes the things
private void WriteThings(MapSet map, UniversalParser textmap)
{
// Go for all things
foreach(Thing t in map.Things)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
if(t.Tag != 0) coll.Add("id", t.Tag);
coll.Add("x", t.Position.x);
coll.Add("y", t.Position.y);
if(t.Position.z != 0.0f) coll.Add("height", (float)t.Position.z);
coll.Add("angle", t.AngleDeg);
coll.Add("type", t.Type);
if(t.Action != 0) coll.Add("special", t.Action);
if(t.Args[0] != 0) coll.Add("arg0", t.Args[0]);
if(t.Args[1] != 0) coll.Add("arg1", t.Args[1]);
if(t.Args[2] != 0) coll.Add("arg2", t.Args[2]);
if(t.Args[3] != 0) coll.Add("arg3", t.Args[3]);
if(t.Args[4] != 0) coll.Add("arg4", t.Args[4]);
// Flags
foreach(KeyValuePair<string, bool> flag in t.Flags)
if(flag.Value) coll.Add(flag.Key, flag.Value);
// Add custom fields
AddCustomFields(t, "thing", coll);
// Store
textmap.Root.Add("thing", coll);
}
}
// This adds custom fields from a map element to a collection
private void AddCustomFields(MapElement element, string elementname, UniversalCollection collection)
{
// Add custom fields
foreach(KeyValuePair<string, UniValue> f in element.Fields)
{
// Not a managed field?
if(!config.SettingExists("managedfields." + elementname + "." + f.Key))
{
// Add type information to DBS file for map
manager.Options.SetUniversalFieldType(elementname, f.Key, f.Value.Type);
// Store field
collection.Add(f.Key, f.Value.Value);
}
}
}
#endregion
}
}

View file

@ -0,0 +1,298 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.IO;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Types;
#endregion
namespace CodeImp.DoomBuilder.IO
{
internal class UniversalStreamWriter
{
#region ================== Constants
// Name of the UDMF configuration file
private const string UDMF_CONFIG_NAME = "UDMF.cfg";
#endregion
#region ================== Variables
private Configuration config;
private bool remembercustomtypes;
#endregion
#region ================== Properties
public bool RememberCustomTypes { get { return remembercustomtypes; } set { remembercustomtypes = value; } }
#endregion
#region ================== Constructor / Disposer
// Constructor
public UniversalStreamWriter()
{
// Make configurations
config = new Configuration();
// Find a resource named UDMF.cfg
string[] resnames = General.ThisAssembly.GetManifestResourceNames();
foreach(string rn in resnames)
{
// Found it?
if(rn.EndsWith(UDMF_CONFIG_NAME, StringComparison.InvariantCultureIgnoreCase))
{
// Get a stream from the resource
Stream udmfcfg = General.ThisAssembly.GetManifestResourceStream(rn);
StreamReader udmfcfgreader = new StreamReader(udmfcfg, Encoding.ASCII);
// Load configuration from stream
config.InputConfiguration(udmfcfgreader.ReadToEnd());
// Now we add the linedef flags, activations and thing flags
// to this list, so that these don't show up in the custom
// fields list either. We use true as dummy value (it has no meaning)
// Add linedef flags
foreach(KeyValuePair<string, string> flag in General.Map.Config.LinedefFlags)
config.WriteSetting("managedfields.linedef." + flag.Key, true);
// Add linedef activations
foreach(LinedefActivateInfo activate in General.Map.Config.LinedefActivates)
config.WriteSetting("managedfields.linedef." + activate.Key, true);
// Add thing flags
foreach(KeyValuePair<string, string> flag in General.Map.Config.ThingFlags)
config.WriteSetting("managedfields.thing." + flag.Key, true);
// Done
udmfcfgreader.Dispose();
udmfcfg.Dispose();
break;
}
}
}
#endregion
#region ================== Writing
// This writes the structures to a stream
// writenamespace may be null to omit writing the namespace to the stream
public void Write(MapSet map, Stream stream, string writenamespace)
{
UniversalParser textmap = new UniversalParser();
// Begin with fields that must be at the top
if(writenamespace != null) textmap.Root.Add("namespace", writenamespace);
Dictionary<Vertex, int> vertexids = new Dictionary<Vertex, int>();
Dictionary<Sidedef, int> sidedefids = new Dictionary<Sidedef, int>();
Dictionary<Sector, int> sectorids = new Dictionary<Sector, int>();
// Index the elements in the data structures
foreach(Vertex v in map.Vertices) vertexids.Add(v, vertexids.Count);
foreach(Sidedef sd in map.Sidedefs) sidedefids.Add(sd, sidedefids.Count);
foreach(Sector s in map.Sectors) sectorids.Add(s, sectorids.Count);
// If we write the custom field types again, then forget
// all previous field types (this gets rid of unused field types)
if(remembercustomtypes) General.Map.Options.ForgetUniversalFieldTypes();
// Write the data structures to textmap
WriteVertices(map.Vertices, textmap);
WriteLinedefs(map.Linedefs, textmap, sidedefids, vertexids);
WriteSidedefs(map.Sidedefs, textmap, sectorids);
WriteSectors(map.Sectors, textmap);
WriteThings(map.Things, textmap);
// Get the textmap as string
string textmapstr = textmap.OutputConfiguration();
// Write to stream
StreamWriter writer = new StreamWriter(stream, Encoding.ASCII);
writer.Write(textmapstr);
writer.Flush();
}
// This adds vertices
private void WriteVertices(ICollection<Vertex> vertices, UniversalParser textmap)
{
// Go for all vertices
foreach(Vertex v in vertices)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
coll.Add("x", v.Position.x);
coll.Add("y", v.Position.y);
// Add custom fields
AddCustomFields(v, "vertex", coll);
// Store
textmap.Root.Add("vertex", coll);
}
}
// This adds linedefs
private void WriteLinedefs(ICollection<Linedef> linedefs, UniversalParser textmap, IDictionary<Sidedef, int> sidedefids, IDictionary<Vertex, int> vertexids)
{
// Go for all linedefs
foreach(Linedef l in linedefs)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
if(l.Tag != 0) coll.Add("id", l.Tag);
coll.Add("v1", vertexids[l.Start]);
coll.Add("v2", vertexids[l.End]);
if(l.Front != null) coll.Add("sidefront", sidedefids[l.Front]); else coll.Add("sidefront", -1);
if(l.Back != null) coll.Add("sideback", sidedefids[l.Back]); else coll.Add("sideback", -1);
if(l.Action != 0) coll.Add("special", l.Action);
if(l.Args[0] != 0) coll.Add("arg0", l.Args[0]);
if(l.Args[1] != 0) coll.Add("arg1", l.Args[1]);
if(l.Args[2] != 0) coll.Add("arg2", l.Args[2]);
if(l.Args[3] != 0) coll.Add("arg3", l.Args[3]);
if(l.Args[4] != 0) coll.Add("arg4", l.Args[4]);
// Flags
foreach(KeyValuePair<string, bool> flag in l.Flags)
if(flag.Value) coll.Add(flag.Key, flag.Value);
// Add custom fields
AddCustomFields(l, "linedef", coll);
// Store
textmap.Root.Add("linedef", coll);
}
}
// This adds sidedefs
private void WriteSidedefs(ICollection<Sidedef> sidedefs, UniversalParser textmap, IDictionary<Sector, int> sectorids)
{
// Go for all sidedefs
foreach(Sidedef s in sidedefs)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
if(s.OffsetX != 0) coll.Add("offsetx", s.OffsetX);
if(s.OffsetY != 0) coll.Add("offsety", s.OffsetY);
if(s.LongHighTexture != MapSet.EmptyLongName) coll.Add("texturetop", s.HighTexture);
if(s.LongLowTexture != MapSet.EmptyLongName) coll.Add("texturebottom", s.LowTexture);
if(s.LongMiddleTexture != MapSet.EmptyLongName) coll.Add("texturemiddle", s.MiddleTexture);
coll.Add("sector", sectorids[s.Sector]);
// Add custom fields
AddCustomFields(s, "sidedef", coll);
// Store
textmap.Root.Add("sidedef", coll);
}
}
// This adds sectors
private void WriteSectors(ICollection<Sector> sectors, UniversalParser textmap)
{
// Go for all sectors
foreach(Sector s in sectors)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
coll.Add("heightfloor", s.FloorHeight);
coll.Add("heightceiling", s.CeilHeight);
coll.Add("texturefloor", s.FloorTexture);
coll.Add("textureceiling", s.CeilTexture);
coll.Add("lightlevel", s.Brightness);
if(s.Effect != 0) coll.Add("special", s.Effect);
if(s.Tag != 0) coll.Add("id", s.Tag);
// Add custom fields
AddCustomFields(s, "sector", coll);
// Store
textmap.Root.Add("sector", coll);
}
}
// This adds things
private void WriteThings(ICollection<Thing> things, UniversalParser textmap)
{
// Go for all things
foreach(Thing t in things)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
if(t.Tag != 0) coll.Add("id", t.Tag);
coll.Add("x", t.Position.x);
coll.Add("y", t.Position.y);
if(t.Position.z != 0.0f) coll.Add("height", (float)t.Position.z);
coll.Add("angle", t.AngleDeg);
coll.Add("type", t.Type);
if(t.Action != 0) coll.Add("special", t.Action);
if(t.Args[0] != 0) coll.Add("arg0", t.Args[0]);
if(t.Args[1] != 0) coll.Add("arg1", t.Args[1]);
if(t.Args[2] != 0) coll.Add("arg2", t.Args[2]);
if(t.Args[3] != 0) coll.Add("arg3", t.Args[3]);
if(t.Args[4] != 0) coll.Add("arg4", t.Args[4]);
// Flags
foreach(KeyValuePair<string, bool> flag in t.Flags)
if(flag.Value) coll.Add(flag.Key, flag.Value);
// Add custom fields
AddCustomFields(t, "thing", coll);
// Store
textmap.Root.Add("thing", coll);
}
}
// This adds custom fields from a map element to a collection
private void AddCustomFields(MapElement element, string elementname, UniversalCollection collection)
{
// Add custom fields
foreach(KeyValuePair<string, UniValue> f in element.Fields)
{
// Not a managed field?
if(!config.SettingExists("managedfields." + elementname + "." + f.Key))
{
// Add type information to DBS file for map
if(remembercustomtypes)
General.Map.Options.SetUniversalFieldType(elementname, f.Key, f.Value.Type);
// Store field
collection.Add(f.Key, f.Value.Value);
}
}
}
#endregion
}
}

View file

@ -59,7 +59,7 @@ namespace CodeImp.DoomBuilder.Map
private LinkedList<Thing> things;
// Optimization
private long emptylongname;
private static long emptylongname;
// Disposing
private bool isdisposed = false;
@ -74,7 +74,7 @@ namespace CodeImp.DoomBuilder.Map
public ICollection<Sector> Sectors { get { return sectors; } }
public ICollection<Thing> Things { get { return things; } }
public bool IsDisposed { get { return isdisposed; } }
public long EmptyLongName { get { return emptylongname; } }
public static long EmptyLongName { get { return emptylongname; } }
#endregion
@ -91,7 +91,6 @@ namespace CodeImp.DoomBuilder.Map
things = new LinkedList<Thing>();
indexholes = new List<int>();
lastsectorindex = 0;
emptylongname = Lump.MakeLongName("-");
// We have no destructor
GC.SuppressFinalize(this);
@ -141,6 +140,12 @@ namespace CodeImp.DoomBuilder.Map
}
}
// Static initializer
internal static void Initialize()
{
emptylongname = Lump.MakeLongName("-");
}
#endregion
#region ================== Management

View file

@ -113,8 +113,8 @@ namespace CodeImp.DoomBuilder.Map
this.index = index;
this.floortexname = "-";
this.ceiltexname = "-";
this.longfloortexname = map.EmptyLongName;
this.longceiltexname = map.EmptyLongName;
this.longfloortexname = MapSet.EmptyLongName;
this.longceiltexname = MapSet.EmptyLongName;
this.triangulationneeded = true;
// We have no destructor

View file

@ -97,9 +97,9 @@ namespace CodeImp.DoomBuilder.Map
this.texnamehigh = "-";
this.texnamemid = "-";
this.texnamelow = "-";
this.longtexnamehigh = map.EmptyLongName;
this.longtexnamemid = map.EmptyLongName;
this.longtexnamelow = map.EmptyLongName;
this.longtexnamehigh = MapSet.EmptyLongName;
this.longtexnamemid = MapSet.EmptyLongName;
this.longtexnamelow = MapSet.EmptyLongName;
// Attach to the linedef
if(front) l.AttachFront(this); else l.AttachBack(this);
@ -221,19 +221,19 @@ namespace CodeImp.DoomBuilder.Map
if(!HighRequired())
{
this.texnamehigh = "-";
this.longtexnamehigh = map.EmptyLongName;
this.longtexnamehigh = MapSet.EmptyLongName;
}
if(!MiddleRequired() && removemiddle)
{
this.texnamemid = "-";
this.longtexnamemid = map.EmptyLongName;
this.longtexnamemid = MapSet.EmptyLongName;
}
if(!LowRequired())
{
this.texnamelow = "-";
this.longtexnamelow = map.EmptyLongName;
this.longtexnamelow = MapSet.EmptyLongName;
}
}