From b717794aed2e8599e9b52123f05b363902929d92 Mon Sep 17 00:00:00 2001 From: codeimp Date: Wed, 17 Sep 2008 19:21:45 +0000 Subject: [PATCH] - 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 --- Source/Builder.csproj | 3 +- Source/Editing/CopyPasteManager.cs | 86 ++- Source/Editing/EditMode.cs | 9 +- Source/General/General.cs | 3 + Source/General/MapManager.cs | 4 +- Source/Geometry/SectorTools.cs | 6 +- Source/IO/UniversalMapSetIO.cs | 504 +----------------- ...abMapSetIO.cs => UniversalStreamReader.cs} | 293 ++-------- Source/IO/UniversalStreamWriter.cs | 298 +++++++++++ Source/Map/MapSet.cs | 11 +- Source/Map/Sector.cs | 4 +- Source/Map/Sidedef.cs | 12 +- 12 files changed, 461 insertions(+), 772 deletions(-) rename Source/IO/{PrefabMapSetIO.cs => UniversalStreamReader.cs} (60%) create mode 100644 Source/IO/UniversalStreamWriter.cs diff --git a/Source/Builder.csproj b/Source/Builder.csproj index f503e1c5..36109654 100644 --- a/Source/Builder.csproj +++ b/Source/Builder.csproj @@ -126,10 +126,11 @@ - + + diff --git a/Source/Editing/CopyPasteManager.cs b/Source/Editing/CopyPasteManager.cs index 0068cabf..60f56332 100644 --- a/Source/Editing/CopyPasteManager.cs +++ b/Source/Editing/CopyPasteManager.cs @@ -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 diff --git a/Source/Editing/EditMode.cs b/Source/Editing/EditMode.cs index b289f6d4..17c41e76 100644 --- a/Source/Editing/EditMode.cs +++ b/Source/Editing/EditMode.cs @@ -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) { } diff --git a/Source/General/General.cs b/Source/General/General.cs index 8ab8d1af..d6a7751c 100644 --- a/Source/General/General.cs +++ b/Source/General/General.cs @@ -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(); diff --git a/Source/General/MapManager.cs b/Source/General/MapManager.cs index d395127a..1069f7da 100644 --- a/Source/General/MapManager.cs +++ b/Source/General/MapManager.cs @@ -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 diff --git a/Source/Geometry/SectorTools.cs b/Source/Geometry/SectorTools.cs index 45356cfc..62ea853e 100644 --- a/Source/Geometry/SectorTools.cs +++ b/Source/Geometry/SectorTools.cs @@ -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; } diff --git a/Source/IO/UniversalMapSetIO.cs b/Source/IO/UniversalMapSetIO.cs index 864d79ca..653dd4d9 100644 --- a/Source/IO/UniversalMapSetIO.cs +++ b/Source/IO/UniversalMapSetIO.cs @@ -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 vertexlink; - Dictionary 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 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(c, "x", true, 0.0f); - float y = GetCollectionEntry(c, "y", true, 0.0f); - float height = GetCollectionEntry(c, "height", false, 0.0f); - int tag = GetCollectionEntry(c, "id", false, 0); - int angledeg = GetCollectionEntry(c, "angle", false, 0); - int type = GetCollectionEntry(c, "type", true, 0); - int special = GetCollectionEntry(c, "special", false, 0); - args[0] = GetCollectionEntry(c, "arg0", false, 0); - args[1] = GetCollectionEntry(c, "arg1", false, 0); - args[2] = GetCollectionEntry(c, "arg2", false, 0); - args[3] = GetCollectionEntry(c, "arg3", false, 0); - args[4] = GetCollectionEntry(c, "arg4", false, 0); - - // Flags - Dictionary stringflags = new Dictionary(); - foreach(KeyValuePair flag in General.Map.Config.ThingFlags) - stringflags[flag.Key] = GetCollectionEntry(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 vertexlink, Dictionary sectorlink) - { - // Get list of entries - List linescolls = GetNamedCollections(textmap.Root, "linedef"); - List 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(lc, "id", false, 0); - int v1 = GetCollectionEntry(lc, "v1", true, 0); - int v2 = GetCollectionEntry(lc, "v2", true, 0); - int special = GetCollectionEntry(lc, "special", false, 0); - args[0] = GetCollectionEntry(lc, "arg0", false, 0); - args[1] = GetCollectionEntry(lc, "arg1", false, 0); - args[2] = GetCollectionEntry(lc, "arg2", false, 0); - args[3] = GetCollectionEntry(lc, "arg3", false, 0); - args[4] = GetCollectionEntry(lc, "arg4", false, 0); - int s1 = GetCollectionEntry(lc, "sidefront", true, -1); - int s2 = GetCollectionEntry(lc, "sideback", false, -1); - - // Flags - Dictionary stringflags = new Dictionary(); - foreach(KeyValuePair flag in General.Map.Config.LinedefFlags) - stringflags[flag.Key] = GetCollectionEntry(lc, flag.Key, false, false); - - // Activations - foreach(LinedefActivateInfo activate in General.Map.Config.LinedefActivates) - stringflags[activate.Key] = GetCollectionEntry(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 sectorlink) - { - // Read fields - int offsetx = GetCollectionEntry(sc, "offsetx", false, 0); - int offsety = GetCollectionEntry(sc, "offsety", false, 0); - string thigh = GetCollectionEntry(sc, "texturetop", false, "-"); - string tlow = GetCollectionEntry(sc, "texturebottom", false, "-"); - string tmid = GetCollectionEntry(sc, "texturemiddle", false, "-"); - int sector = GetCollectionEntry(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 ReadSectors(MapSet map, UniversalParser textmap) - { - Dictionary link; - - // Get list of entries - List collections = GetNamedCollections(textmap.Root, "sector"); - - // Create lookup table - link = new Dictionary(collections.Count); - - // Go for all collections - for(int i = 0; i < collections.Count; i++) - { - // Read fields - UniversalCollection c = collections[i]; - int hfloor = GetCollectionEntry(c, "heightfloor", false, 0); - int hceil = GetCollectionEntry(c, "heightceiling", false, 0); - string tfloor = GetCollectionEntry(c, "texturefloor", true, "-"); - string tceil = GetCollectionEntry(c, "textureceiling", true, "-"); - int bright = GetCollectionEntry(c, "lightlevel", false, 160); - int special = GetCollectionEntry(c, "special", false, 0); - int tag = GetCollectionEntry(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 ReadVertices(MapSet map, UniversalParser textmap) - { - Dictionary link; - - // Get list of entries - List collections = GetNamedCollections(textmap.Root, "vertex"); - - // Create lookup table - link = new Dictionary(collections.Count); - - // Go for all collections - for(int i = 0; i < collections.Count; i++) - { - // Read fields - UniversalCollection c = collections[i]; - float x = GetCollectionEntry(c, "x", true, 0.0f); - float y = GetCollectionEntry(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(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 GetNamedCollections(UniversalCollection collection, string entryname) - { - List list = new List(); - - // 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 vertexids = new Dictionary(); - Dictionary sidedefids = new Dictionary(); - Dictionary sectorids = new Dictionary(); - - // 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 sidedefids, IDictionary 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 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 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 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 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 diff --git a/Source/IO/PrefabMapSetIO.cs b/Source/IO/UniversalStreamReader.cs similarity index 60% rename from Source/IO/PrefabMapSetIO.cs rename to Source/IO/UniversalStreamReader.cs index 2e73a124..40d9e63a 100644 --- a/Source/IO/PrefabMapSetIO.cs +++ b/Source/IO/UniversalStreamReader.cs @@ -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 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 vertexlink; Dictionary 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 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 stringflags = new Dictionary(); foreach(KeyValuePair flag in General.Map.Config.ThingFlags) stringflags[flag.Key] = GetCollectionEntry(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(lc, "arg4", false, 0); int s1 = GetCollectionEntry(lc, "sidefront", true, -1); int s2 = GetCollectionEntry(lc, "sideback", false, -1); - + // Flags Dictionary stringflags = new Dictionary(); foreach(KeyValuePair 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(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(c, "lightlevel", false, 160); int special = GetCollectionEntry(c, "special", false, 0); int tag = GetCollectionEntry(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 ReadVertices(MapSet map, UniversalParser textmap) { Dictionary link; - + // Get list of entries List collections = GetNamedCollections(textmap.Root, "vertex"); - + // Create lookup table link = new Dictionary(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(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 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 vertexids = new Dictionary(); - Dictionary sidedefids = new Dictionary(); - Dictionary sectorids = new Dictionary(); - - // 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 sidedefids, IDictionary 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 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 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 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 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 } } diff --git a/Source/IO/UniversalStreamWriter.cs b/Source/IO/UniversalStreamWriter.cs new file mode 100644 index 00000000..c25b09cd --- /dev/null +++ b/Source/IO/UniversalStreamWriter.cs @@ -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 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 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 vertexids = new Dictionary(); + Dictionary sidedefids = new Dictionary(); + Dictionary sectorids = new Dictionary(); + + // 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 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 linedefs, UniversalParser textmap, IDictionary sidedefids, IDictionary 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 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 sidedefs, UniversalParser textmap, IDictionary 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 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 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 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 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 + } +} + diff --git a/Source/Map/MapSet.cs b/Source/Map/MapSet.cs index f394aaea..0959a87a 100644 --- a/Source/Map/MapSet.cs +++ b/Source/Map/MapSet.cs @@ -59,7 +59,7 @@ namespace CodeImp.DoomBuilder.Map private LinkedList things; // Optimization - private long emptylongname; + private static long emptylongname; // Disposing private bool isdisposed = false; @@ -74,7 +74,7 @@ namespace CodeImp.DoomBuilder.Map public ICollection Sectors { get { return sectors; } } public ICollection 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(); indexholes = new List(); 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 diff --git a/Source/Map/Sector.cs b/Source/Map/Sector.cs index 77d3ee57..55bfccbe 100644 --- a/Source/Map/Sector.cs +++ b/Source/Map/Sector.cs @@ -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 diff --git a/Source/Map/Sidedef.cs b/Source/Map/Sidedef.cs index 2b1cf773..39175b45 100644 --- a/Source/Map/Sidedef.cs +++ b/Source/Map/Sidedef.cs @@ -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; } }