- Better handling of missing UDMF TEXTMAP fields (Error now includes the element and index at which the field is missing and will not abort loading. Instead it will use a default value.)

- UDMF TEXTMAP now contains the indices of elements as comment next to the structure header.
- Thing cages in Visual Mode now also get the selection and highlight color so that a selection and highlight on things without sprite can also be seen.
This commit is contained in:
codeimp 2009-06-15 21:58:34 +00:00
parent 4f52e3f5e8
commit f5b661216b
5 changed files with 106 additions and 64 deletions

View file

@ -30,6 +30,12 @@ namespace CodeImp.DoomBuilder.IO
{ {
public sealed class UniversalCollection : List<UniversalEntry> public sealed class UniversalCollection : List<UniversalEntry>
{ {
// Variables
private string comment;
// Properties
public string Comment { get { return comment; } set { comment = value; } }
// Overload // Overload
public void Add(string key, object value) public void Add(string key, object value)
{ {

View file

@ -674,7 +674,13 @@ namespace CodeImp.DoomBuilder.IO
{ {
// Output recursive structure // Output recursive structure
if(whitespace) { db.Append(leveltabs); db.Append(newline); } if(whitespace) { db.Append(leveltabs); db.Append(newline); }
db.Append(leveltabs); db.Append(de.Current.Key); db.Append(newline); db.Append(leveltabs); db.Append(de.Current.Key);
if(!string.IsNullOrEmpty(((UniversalCollection)de.Current.Value).Comment))
{
if(whitespace) db.Append("\t");
db.Append("// " + ((UniversalCollection)de.Current.Value).Comment);
}
db.Append(newline);
db.Append(leveltabs); db.Append("{"); db.Append(newline); db.Append(leveltabs); db.Append("{"); db.Append(newline);
db.Append(OutputStructure((UniversalCollection)de.Current.Value, level + 1, newline, whitespace)); db.Append(OutputStructure((UniversalCollection)de.Current.Value, level + 1, newline, whitespace));
db.Append(leveltabs); db.Append("}"); db.Append(newline); db.Append(leveltabs); db.Append("}"); db.Append(newline);

View file

@ -115,7 +115,7 @@ namespace CodeImp.DoomBuilder.IO
UniversalParser textmap = new UniversalParser(); UniversalParser textmap = new UniversalParser();
textmap.StrictChecking = strictchecking; textmap.StrictChecking = strictchecking;
//try try
{ {
// Read UDMF from stream // Read UDMF from stream
textmap.InputConfiguration(reader.ReadToEnd()); textmap.InputConfiguration(reader.ReadToEnd());
@ -135,9 +135,9 @@ namespace CodeImp.DoomBuilder.IO
ReadThings(map, textmap); ReadThings(map, textmap);
} }
} }
//catch(Exception e) catch(Exception e)
{ {
//General.ShowErrorMessage("Unexpected error reading UDMF map data. " + e.GetType().Name + ": " + e.Message, MessageBoxButtons.OK); General.ShowErrorMessage("Unexpected error reading UDMF map data. " + e.GetType().Name + ": " + e.Message, MessageBoxButtons.OK);
} }
return map; return map;
@ -156,27 +156,28 @@ namespace CodeImp.DoomBuilder.IO
// Read fields // Read fields
UniversalCollection c = collections[i]; UniversalCollection c = collections[i];
int[] args = new int[Linedef.NUM_ARGS]; int[] args = new int[Linedef.NUM_ARGS];
float x = GetCollectionEntry<float>(c, "x", true, 0.0f); string where = "thing " + i;
float y = GetCollectionEntry<float>(c, "y", true, 0.0f); float x = GetCollectionEntry<float>(c, "x", true, 0.0f, where);
float height = GetCollectionEntry<float>(c, "height", false, 0.0f); float y = GetCollectionEntry<float>(c, "y", true, 0.0f, where);
int tag = GetCollectionEntry<int>(c, "id", false, 0); float height = GetCollectionEntry<float>(c, "height", false, 0.0f, where);
int angledeg = GetCollectionEntry<int>(c, "angle", false, 0); int tag = GetCollectionEntry<int>(c, "id", false, 0, where);
int type = GetCollectionEntry<int>(c, "type", true, 0); int angledeg = GetCollectionEntry<int>(c, "angle", false, 0, where);
int special = GetCollectionEntry<int>(c, "special", false, 0); int type = GetCollectionEntry<int>(c, "type", true, 0, where);
args[0] = GetCollectionEntry<int>(c, "arg0", false, 0); int special = GetCollectionEntry<int>(c, "special", false, 0, where);
args[1] = GetCollectionEntry<int>(c, "arg1", false, 0); args[0] = GetCollectionEntry<int>(c, "arg0", false, 0, where);
args[2] = GetCollectionEntry<int>(c, "arg2", false, 0); args[1] = GetCollectionEntry<int>(c, "arg1", false, 0, where);
args[3] = GetCollectionEntry<int>(c, "arg3", false, 0); args[2] = GetCollectionEntry<int>(c, "arg2", false, 0, where);
args[4] = GetCollectionEntry<int>(c, "arg4", false, 0); args[3] = GetCollectionEntry<int>(c, "arg3", false, 0, where);
args[4] = GetCollectionEntry<int>(c, "arg4", false, 0, where);
// Flags // Flags
Dictionary<string, bool> stringflags = new Dictionary<string, bool>(); Dictionary<string, bool> stringflags = new Dictionary<string, bool>();
foreach(KeyValuePair<string, string> flag in General.Map.Config.ThingFlags) foreach(KeyValuePair<string, string> flag in General.Map.Config.ThingFlags)
stringflags[flag.Key] = GetCollectionEntry<bool>(c, flag.Key, false, false); stringflags[flag.Key] = GetCollectionEntry<bool>(c, flag.Key, false, false, where);
foreach(FlagTranslation ft in General.Map.Config.ThingFlagsTranslation) foreach(FlagTranslation ft in General.Map.Config.ThingFlagsTranslation)
{ {
foreach(string field in ft.Fields) foreach(string field in ft.Fields)
stringflags[field] = GetCollectionEntry<bool>(c, field, false, false); stringflags[field] = GetCollectionEntry<bool>(c, field, false, false, where);
} }
// Create new item // Create new item
@ -203,31 +204,32 @@ namespace CodeImp.DoomBuilder.IO
// Read fields // Read fields
UniversalCollection lc = linescolls[i]; UniversalCollection lc = linescolls[i];
int[] args = new int[Linedef.NUM_ARGS]; int[] args = new int[Linedef.NUM_ARGS];
int tag = GetCollectionEntry<int>(lc, "id", false, 0); string where = "linedef " + i;
int v1 = GetCollectionEntry<int>(lc, "v1", true, 0); int tag = GetCollectionEntry<int>(lc, "id", false, 0, where);
int v2 = GetCollectionEntry<int>(lc, "v2", true, 0); int v1 = GetCollectionEntry<int>(lc, "v1", true, 0, where);
int special = GetCollectionEntry<int>(lc, "special", false, 0); int v2 = GetCollectionEntry<int>(lc, "v2", true, 0, where);
args[0] = GetCollectionEntry<int>(lc, "arg0", false, 0); int special = GetCollectionEntry<int>(lc, "special", false, 0, where);
args[1] = GetCollectionEntry<int>(lc, "arg1", false, 0); args[0] = GetCollectionEntry<int>(lc, "arg0", false, 0, where);
args[2] = GetCollectionEntry<int>(lc, "arg2", false, 0); args[1] = GetCollectionEntry<int>(lc, "arg1", false, 0, where);
args[3] = GetCollectionEntry<int>(lc, "arg3", false, 0); args[2] = GetCollectionEntry<int>(lc, "arg2", false, 0, where);
args[4] = GetCollectionEntry<int>(lc, "arg4", false, 0); args[3] = GetCollectionEntry<int>(lc, "arg3", false, 0, where);
int s1 = GetCollectionEntry<int>(lc, "sidefront", true, -1); args[4] = GetCollectionEntry<int>(lc, "arg4", false, 0, where);
int s2 = GetCollectionEntry<int>(lc, "sideback", false, -1); int s1 = GetCollectionEntry<int>(lc, "sidefront", true, -1, where);
int s2 = GetCollectionEntry<int>(lc, "sideback", false, -1, where);
// Flags // Flags
Dictionary<string, bool> stringflags = new Dictionary<string, bool>(); Dictionary<string, bool> stringflags = new Dictionary<string, bool>();
foreach(KeyValuePair<string, string> flag in General.Map.Config.LinedefFlags) foreach(KeyValuePair<string, string> flag in General.Map.Config.LinedefFlags)
stringflags[flag.Key] = GetCollectionEntry<bool>(lc, flag.Key, false, false); stringflags[flag.Key] = GetCollectionEntry<bool>(lc, flag.Key, false, false, where);
foreach(FlagTranslation ft in General.Map.Config.LinedefFlagsTranslation) foreach(FlagTranslation ft in General.Map.Config.LinedefFlagsTranslation)
{ {
foreach(string field in ft.Fields) foreach(string field in ft.Fields)
stringflags[field] = GetCollectionEntry<bool>(lc, field, false, false); stringflags[field] = GetCollectionEntry<bool>(lc, field, false, false, where);
} }
// Activations // Activations
foreach(LinedefActivateInfo activate in General.Map.Config.LinedefActivates) foreach(LinedefActivateInfo activate in General.Map.Config.LinedefActivates)
stringflags[activate.Key] = GetCollectionEntry<bool>(lc, activate.Key, false, false); stringflags[activate.Key] = GetCollectionEntry<bool>(lc, activate.Key, false, false, where);
// Create new linedef // Create new linedef
if(vertexlink.ContainsKey(v1) && vertexlink.ContainsKey(v2)) if(vertexlink.ContainsKey(v1) && vertexlink.ContainsKey(v2))
@ -246,7 +248,7 @@ namespace CodeImp.DoomBuilder.IO
if(s1 > -1) if(s1 > -1)
{ {
if(s1 < sidescolls.Count) if(s1 < sidescolls.Count)
ReadSidedef(map, sidescolls[s1], l, true, sectorlink); ReadSidedef(map, sidescolls[s1], l, true, sectorlink, s1);
else else
General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid front sidedef " + s1 + ". Sidedef has been removed."); General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid front sidedef " + s1 + ". Sidedef has been removed.");
} }
@ -254,7 +256,7 @@ namespace CodeImp.DoomBuilder.IO
if(s2 > -1) if(s2 > -1)
{ {
if(s2 < sidescolls.Count) if(s2 < sidescolls.Count)
ReadSidedef(map, sidescolls[s2], l, false, sectorlink); ReadSidedef(map, sidescolls[s2], l, false, sectorlink, s2);
else else
General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid back sidedef " + s1 + ". Sidedef has been removed."); General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid back sidedef " + s1 + ". Sidedef has been removed.");
} }
@ -273,15 +275,16 @@ namespace CodeImp.DoomBuilder.IO
// This reads a single sidedef and connects it to the given linedef // This reads a single sidedef and connects it to the given linedef
private void ReadSidedef(MapSet map, UniversalCollection sc, Linedef ld, private void ReadSidedef(MapSet map, UniversalCollection sc, Linedef ld,
bool front, Dictionary<int, Sector> sectorlink) bool front, Dictionary<int, Sector> sectorlink, int index)
{ {
// Read fields // Read fields
int offsetx = GetCollectionEntry<int>(sc, "offsetx", false, 0); string where = "linedef " + ld.Index + (front ? " front sidedef " : " back sidedef ") + index;
int offsety = GetCollectionEntry<int>(sc, "offsety", false, 0); int offsetx = GetCollectionEntry<int>(sc, "offsetx", false, 0, where);
string thigh = GetCollectionEntry<string>(sc, "texturetop", false, "-"); int offsety = GetCollectionEntry<int>(sc, "offsety", false, 0, where);
string tlow = GetCollectionEntry<string>(sc, "texturebottom", false, "-"); string thigh = GetCollectionEntry<string>(sc, "texturetop", false, "-", where);
string tmid = GetCollectionEntry<string>(sc, "texturemiddle", false, "-"); string tlow = GetCollectionEntry<string>(sc, "texturebottom", false, "-", where);
int sector = GetCollectionEntry<int>(sc, "sector", true, 0); string tmid = GetCollectionEntry<string>(sc, "texturemiddle", false, "-", where);
int sector = GetCollectionEntry<int>(sc, "sector", true, 0, where);
// Create sidedef // Create sidedef
if(sectorlink.ContainsKey(sector)) if(sectorlink.ContainsKey(sector))
@ -315,13 +318,14 @@ namespace CodeImp.DoomBuilder.IO
{ {
// Read fields // Read fields
UniversalCollection c = collections[i]; UniversalCollection c = collections[i];
int hfloor = GetCollectionEntry<int>(c, "heightfloor", false, 0); string where = "sector " + i;
int hceil = GetCollectionEntry<int>(c, "heightceiling", false, 0); int hfloor = GetCollectionEntry<int>(c, "heightfloor", false, 0, where);
string tfloor = GetCollectionEntry<string>(c, "texturefloor", true, "-"); int hceil = GetCollectionEntry<int>(c, "heightceiling", false, 0, where);
string tceil = GetCollectionEntry<string>(c, "textureceiling", true, "-"); string tfloor = GetCollectionEntry<string>(c, "texturefloor", true, "-", where);
int bright = GetCollectionEntry<int>(c, "lightlevel", false, 160); string tceil = GetCollectionEntry<string>(c, "textureceiling", true, "-", where);
int special = GetCollectionEntry<int>(c, "special", false, 0); int bright = GetCollectionEntry<int>(c, "lightlevel", false, 160, where);
int tag = GetCollectionEntry<int>(c, "id", false, 0); int special = GetCollectionEntry<int>(c, "special", false, 0, where);
int tag = GetCollectionEntry<int>(c, "id", false, 0, where);
// Create new item // Create new item
Sector s = map.CreateSector(); Sector s = map.CreateSector();
@ -355,8 +359,9 @@ namespace CodeImp.DoomBuilder.IO
{ {
// Read fields // Read fields
UniversalCollection c = collections[i]; UniversalCollection c = collections[i];
float x = GetCollectionEntry<float>(c, "x", true, 0.0f); string where = "vertex " + i;
float y = GetCollectionEntry<float>(c, "y", true, 0.0f); float x = GetCollectionEntry<float>(c, "x", true, 0.0f, where);
float y = GetCollectionEntry<float>(c, "y", true, 0.0f, where);
// Create new item // Create new item
Vertex v = map.CreateVertex(new Vector2D(x, y)); Vertex v = map.CreateVertex(new Vector2D(x, y));
@ -402,7 +407,7 @@ namespace CodeImp.DoomBuilder.IO
} }
// This validates and returns an entry // This validates and returns an entry
private T GetCollectionEntry<T>(UniversalCollection c, string entryname, bool required, T defaultvalue) private T GetCollectionEntry<T>(UniversalCollection c, string entryname, bool required, T defaultvalue, string where)
{ {
T result = default(T); T result = default(T);
bool found = false; bool found = false;
@ -438,17 +443,12 @@ namespace CodeImp.DoomBuilder.IO
// Not found? // Not found?
if(!found) if(!found)
{ {
// Entry is required? // Report error when entry is required!
if(required) if(required)
{ General.ErrorLogger.Add(ErrorType.Error, "Error while reading UDMF map data: Missing required field '" + entryname + "' at " + where + ".");
// Error, cannot find required entry!
throw new Exception("Error while reading UDMF map data: Missing required field '" + entryname + "'."); // Make default entry
} result = defaultvalue;
else
{
// Make default entry
result = defaultvalue;
}
} }
// Return result // Return result

View file

@ -163,6 +163,7 @@ namespace CodeImp.DoomBuilder.IO
UniversalCollection coll = new UniversalCollection(); UniversalCollection coll = new UniversalCollection();
coll.Add("x", v.Position.x); coll.Add("x", v.Position.x);
coll.Add("y", v.Position.y); coll.Add("y", v.Position.y);
coll.Comment = v.Index.ToString();
// Add custom fields // Add custom fields
AddCustomFields(v, "vertex", coll); AddCustomFields(v, "vertex", coll);
@ -183,6 +184,7 @@ namespace CodeImp.DoomBuilder.IO
if(l.Tag != 0) coll.Add("id", l.Tag); if(l.Tag != 0) coll.Add("id", l.Tag);
coll.Add("v1", vertexids[l.Start]); coll.Add("v1", vertexids[l.Start]);
coll.Add("v2", vertexids[l.End]); coll.Add("v2", vertexids[l.End]);
coll.Comment = l.Index.ToString();
// Sidedef references // Sidedef references
if((l.Front != null) && sidedefids.ContainsKey(l.Front)) if((l.Front != null) && sidedefids.ContainsKey(l.Front))
@ -231,6 +233,7 @@ namespace CodeImp.DoomBuilder.IO
if(s.LongLowTexture != MapSet.EmptyLongName) coll.Add("texturebottom", s.LowTexture); if(s.LongLowTexture != MapSet.EmptyLongName) coll.Add("texturebottom", s.LowTexture);
if(s.LongMiddleTexture != MapSet.EmptyLongName) coll.Add("texturemiddle", s.MiddleTexture); if(s.LongMiddleTexture != MapSet.EmptyLongName) coll.Add("texturemiddle", s.MiddleTexture);
coll.Add("sector", sectorids[s.Sector]); coll.Add("sector", sectorids[s.Sector]);
coll.Comment = s.Index.ToString();
// Add custom fields // Add custom fields
AddCustomFields(s, "sidedef", coll); AddCustomFields(s, "sidedef", coll);
@ -255,6 +258,7 @@ namespace CodeImp.DoomBuilder.IO
coll.Add("lightlevel", s.Brightness); coll.Add("lightlevel", s.Brightness);
if(s.Effect != 0) coll.Add("special", s.Effect); if(s.Effect != 0) coll.Add("special", s.Effect);
if(s.Tag != 0) coll.Add("id", s.Tag); if(s.Tag != 0) coll.Add("id", s.Tag);
coll.Comment = s.Index.ToString();
// Add custom fields // Add custom fields
AddCustomFields(s, "sector", coll); AddCustomFields(s, "sector", coll);
@ -284,6 +288,7 @@ namespace CodeImp.DoomBuilder.IO
if(t.Args[2] != 0) coll.Add("arg2", t.Args[2]); 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[3] != 0) coll.Add("arg3", t.Args[3]);
if(t.Args[4] != 0) coll.Add("arg4", t.Args[4]); if(t.Args[4] != 0) coll.Add("arg4", t.Args[4]);
coll.Comment = t.Index.ToString();
// Flags // Flags
foreach(KeyValuePair<string, bool> flag in t.Flags) foreach(KeyValuePair<string, bool> flag in t.Flags)

View file

@ -516,6 +516,9 @@ namespace CodeImp.DoomBuilder.Rendering
// This renders all thing cages // This renders all thing cages
private void RenderThingCages() private void RenderThingCages()
{ {
int currentshaderpass = shaderpass;
int highshaderpass = shaderpass + 2;
// Set renderstates // Set renderstates
graphics.Device.SetRenderState(RenderState.AlphaBlendEnable, true); graphics.Device.SetRenderState(RenderState.AlphaBlendEnable, true);
graphics.Device.SetRenderState(RenderState.AlphaTestEnable, false); graphics.Device.SetRenderState(RenderState.AlphaTestEnable, false);
@ -529,13 +532,35 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.Shaders.World3D.BeginPass(shaderpass); graphics.Shaders.World3D.BeginPass(shaderpass);
foreach(VisualThing t in thingsbydistance) foreach(VisualThing t in thingsbydistance)
{ {
// Determine the shader pass we want to use for this object
int wantedshaderpass = ((t == highlighted) || t.Selected) ? highshaderpass : shaderpass;
// Switch shader pass?
if(currentshaderpass != wantedshaderpass)
{
graphics.Shaders.World3D.EndPass();
graphics.Shaders.World3D.BeginPass(wantedshaderpass);
currentshaderpass = wantedshaderpass;
}
// Setup matrix // Setup matrix
world = Matrix.Multiply(t.CageScales, t.Position); world = Matrix.Multiply(t.CageScales, t.Position);
ApplyMatrices3D(); ApplyMatrices3D();
// Setup color // Setup color
graphics.Shaders.World3D.SetModulateColor(t.CageColor); if(currentshaderpass == highshaderpass)
graphics.Device.SetRenderState(RenderState.TextureFactor, t.CageColor); {
Color4 highcolor = CalculateHighlightColor((t == highlighted), t.Selected);
graphics.Shaders.World3D.SetHighlightColor(highcolor.ToArgb());
highcolor.Alpha = 1.0f;
graphics.Shaders.World3D.SetModulateColor(highcolor.ToArgb());
graphics.Device.SetRenderState(RenderState.TextureFactor, highcolor.ToArgb());
}
else
{
graphics.Shaders.World3D.SetModulateColor(t.CageColor);
graphics.Device.SetRenderState(RenderState.TextureFactor, t.CageColor);
}
// Render! // Render!
graphics.Shaders.World3D.ApplySettings(); graphics.Shaders.World3D.ApplySettings();