mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-18 14:31:50 +00:00
Fixed, text parsers: in some cases include directives were processed differently from ZDoom.
Fixed, ACS parser: absolute and relative include paths handling was broken in R2448.
This commit is contained in:
parent
3621ff78c1
commit
f3fbf241d9
16 changed files with 417 additions and 319 deletions
|
@ -79,7 +79,7 @@ namespace CodeImp.DoomBuilder.Compilers
|
|||
foreach(string include in includes)
|
||||
{
|
||||
// Grab the script text from the resources
|
||||
MemoryStream s = General.Map.Data.LoadFile(include);
|
||||
Stream s = General.Map.Data.LoadFile(include);
|
||||
|
||||
if(s != null)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using CodeImp.DoomBuilder.IO;
|
||||
|
@ -38,7 +39,7 @@ namespace CodeImp.DoomBuilder.Config
|
|||
private readonly string programfile;
|
||||
private readonly string programinterface;
|
||||
private readonly string path;
|
||||
private readonly List<string> files;
|
||||
private readonly HashSet<string> files;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -49,7 +50,7 @@ namespace CodeImp.DoomBuilder.Config
|
|||
public string Path { get { return path; } }
|
||||
public string ProgramFile { get { return programfile; } }
|
||||
public string ProgramInterface { get { return programinterface; } }
|
||||
public List<string> Files { get { return files; } }
|
||||
public HashSet<string> Files { get { return files; } }
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -64,7 +65,7 @@ namespace CodeImp.DoomBuilder.Config
|
|||
this.filename = filename;
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
this.files = new List<string>();
|
||||
this.files = new HashSet<string>(StringComparer.OrdinalIgnoreCase); //mxd. List -> HashSet
|
||||
|
||||
// Read program file and interface
|
||||
this.programfile = cfg.ReadSetting("compilers." + name + ".program", "");
|
||||
|
@ -75,7 +76,14 @@ namespace CodeImp.DoomBuilder.Config
|
|||
foreach(DictionaryEntry de in cfgfiles)
|
||||
{
|
||||
if(de.Key.ToString() != "interface" && de.Key.ToString() != "program")
|
||||
files.Add(de.Value.ToString());
|
||||
{
|
||||
//mxd
|
||||
string include = de.Value.ToString().Replace(System.IO.Path.AltDirectorySeparatorChar, System.IO.Path.DirectorySeparatorChar);
|
||||
if(files.Contains(include))
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Include file '" + de.Value + "' is double-defined in '" + name + "' compiler configuration");
|
||||
else
|
||||
files.Add(include);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -366,7 +366,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
LoadReverbs();
|
||||
LoadSndSeq();
|
||||
LoadVoxels();
|
||||
Dictionary<string, List<int>> actorsbyclass = CreateActorsByClassList();
|
||||
Dictionary<string, int> actorsbyclass = CreateActorsByClassList();
|
||||
LoadModeldefs(actorsbyclass);
|
||||
foreach(Thing t in General.Map.Map.Things) t.UpdateCache();
|
||||
General.MainWindow.DisplayReady();
|
||||
|
@ -1719,9 +1719,9 @@ namespace CodeImp.DoomBuilder.Data
|
|||
#region ================== mxd. Modeldef, Voxeldef, Gldefs, Mapinfo
|
||||
|
||||
//mxd. This creates <Actor Class, Thing.Type> dictionary. Should be called after all DECORATE actors are parsed
|
||||
private Dictionary<string, List<int>> CreateActorsByClassList()
|
||||
private Dictionary<string, int> CreateActorsByClassList()
|
||||
{
|
||||
Dictionary<string, List<int>> actors = new Dictionary<string, List<int>>(StringComparer.Ordinal);
|
||||
Dictionary<string, int> actors = new Dictionary<string, int>(StringComparer.Ordinal);
|
||||
if(string.IsNullOrEmpty(General.Map.Config.DecorateGames)) return actors;
|
||||
|
||||
//read our new shiny ClassNames for default game things
|
||||
|
@ -1730,13 +1730,15 @@ namespace CodeImp.DoomBuilder.Data
|
|||
if(!string.IsNullOrEmpty(ti.Value.ClassName))
|
||||
{
|
||||
string classname = ti.Value.ClassName.ToLowerInvariant();
|
||||
if(!actors.ContainsKey(classname)) actors.Add(classname, new List<int>());
|
||||
actors[classname].Add(ti.Key);
|
||||
|
||||
if(actors.ContainsKey(classname) && actors[classname] != ti.Key)
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "actor '" + ti.Value.ClassName + "' has several editor numbers! Only the last one (" + ti.Key + ") will be used.");
|
||||
actors[classname] = ti.Key;
|
||||
}
|
||||
}
|
||||
|
||||
if(actors.Count == 0)
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Warning: unable to find any DECORATE actor definitions!");
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "unable to find any DECORATE actor definitions!");
|
||||
|
||||
return actors;
|
||||
}
|
||||
|
@ -1799,13 +1801,13 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd. This parses modeldefs. Should be called after all DECORATE actors are parsed and actorsByClass dictionary created
|
||||
private void LoadModeldefs(Dictionary<string, List<int>> actorsByClass)
|
||||
private void LoadModeldefs(Dictionary<string, int> actorsbyclass)
|
||||
{
|
||||
//if no actors defined in DECORATE or game config...
|
||||
if(actorsByClass.Count == 0) return;
|
||||
if(actorsbyclass.Count == 0) return;
|
||||
|
||||
Dictionary<string, ModelData> modelDefEntriesByName = new Dictionary<string, ModelData>(StringComparer.Ordinal);
|
||||
ModeldefParser parser = new ModeldefParser();
|
||||
Dictionary<string, ModelData> modeldefentriesbyname = new Dictionary<string, ModelData>(StringComparer.Ordinal);
|
||||
ModeldefParser parser = new ModeldefParser(actorsbyclass);
|
||||
|
||||
foreach(DataReader dr in containers)
|
||||
{
|
||||
|
@ -1819,15 +1821,10 @@ namespace CodeImp.DoomBuilder.Data
|
|||
{
|
||||
foreach(KeyValuePair<string, ModelData> g in parser.Entries)
|
||||
{
|
||||
if(modelDefEntriesByName.ContainsKey(g.Key))
|
||||
{
|
||||
if(modeldefentriesbyname.ContainsKey(g.Key))
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Model definition for actor '" + g.Key + "' is double-defined in '" + group.Key + "'");
|
||||
modelDefEntriesByName[g.Key] = g.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
modelDefEntriesByName.Add(g.Key, g.Value);
|
||||
}
|
||||
|
||||
modeldefentriesbyname[g.Key] = g.Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1838,16 +1835,12 @@ namespace CodeImp.DoomBuilder.Data
|
|||
|
||||
currentreader = null;
|
||||
|
||||
foreach(KeyValuePair<string, ModelData> e in modelDefEntriesByName)
|
||||
foreach(KeyValuePair<string, ModelData> e in modeldefentriesbyname)
|
||||
{
|
||||
if(actorsByClass.ContainsKey(e.Key))
|
||||
{
|
||||
foreach(int i in actorsByClass[e.Key]) modeldefentries[i] = modelDefEntriesByName[e.Key];
|
||||
}
|
||||
if(actorsbyclass.ContainsKey(e.Key))
|
||||
modeldefentries[actorsbyclass[e.Key]] = modeldefentriesbyname[e.Key];
|
||||
else if(!decorate.ActorsByClass.ContainsKey(e.Key))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Got MODELDEF override for class '" + e.Key + "', but haven't found such class in Decorate");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1947,11 +1940,11 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
}
|
||||
|
||||
//mxd. This parses gldefs. Should be called after all DECORATE actors are parsed and actorsByClass dictionary created
|
||||
private void LoadGldefs(Dictionary<string, List<int>> actorsByClass)
|
||||
//mxd. This parses gldefs. Should be called after all DECORATE actors are parsed
|
||||
private void LoadGldefs(Dictionary<string, int> actorsbyclass)
|
||||
{
|
||||
//if no actors defined in DECORATE or game config...
|
||||
if(actorsByClass.Count == 0) return;
|
||||
if(actorsbyclass.Count == 0) return;
|
||||
|
||||
GldefsParser parser = new GldefsParser { OnInclude = ParseFromLocation };
|
||||
|
||||
|
@ -1975,19 +1968,14 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
}
|
||||
|
||||
//create gldefsEntries dictionary
|
||||
foreach(KeyValuePair<string, string> e in parser.Objects) //ClassName, Light name
|
||||
//create Gldefs Entries dictionary
|
||||
foreach(KeyValuePair<string, string> e in parser.Objects) //<ClassName, Light name>
|
||||
{
|
||||
//if we have decorate actor and light definition for given ClassName...
|
||||
if(actorsByClass.ContainsKey(e.Key) && parser.LightsByName.ContainsKey(e.Value))
|
||||
{
|
||||
foreach(int i in actorsByClass[e.Key])
|
||||
gldefsentries[i] = parser.LightsByName[e.Value];
|
||||
}
|
||||
if(actorsbyclass.ContainsKey(e.Key) && parser.LightsByName.ContainsKey(e.Value))
|
||||
gldefsentries[actorsbyclass[e.Key]] = parser.LightsByName[e.Value];
|
||||
else if(!decorate.AllActorsByClass.ContainsKey(e.Key))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Got GLDEFS light for class '" + e.Key + "', but haven't found such class in DECORATE");
|
||||
}
|
||||
}
|
||||
|
||||
// Grab them glowy flats!
|
||||
|
@ -2162,13 +2150,15 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
//mxd
|
||||
internal MemoryStream LoadFile(string name)
|
||||
internal Stream LoadFile(string name)
|
||||
{
|
||||
// Relative path?
|
||||
if(name.StartsWith("..\\")) name = name.Replace("..\\", "");
|
||||
|
||||
// Filesystem path?
|
||||
if(Path.IsPathRooted(name))
|
||||
return (File.Exists(name) ? File.OpenRead(name) : null);
|
||||
|
||||
foreach(DataReader dr in containers)
|
||||
if(dr.FileExists(name)) return dr.LoadFile(name);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.IO;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using CodeImp.DoomBuilder.ZDoom;
|
||||
|
@ -14,7 +15,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
|
||||
private readonly HashSet<string> parsedlumps;
|
||||
private readonly HashSet<string> includes;
|
||||
private List<string> includestoskip;
|
||||
private HashSet<string> includestoskip;
|
||||
private string libraryname;
|
||||
|
||||
private readonly List<ScriptItem> namedscripts;
|
||||
|
@ -36,15 +37,15 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
namedscripts = new List<ScriptItem>();
|
||||
numberedscripts = new List<ScriptItem>();
|
||||
functions = new List<ScriptItem>();
|
||||
parsedlumps = new HashSet<string>();
|
||||
includes = new HashSet<string>();
|
||||
includestoskip = new List<string>();
|
||||
parsedlumps = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
includes = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
includestoskip = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
specialtokens += "(,)";
|
||||
}
|
||||
|
||||
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
|
||||
{
|
||||
return Parse(stream, sourcefilename, new List<string>(), false, false, clearerrors);
|
||||
return Parse(stream, sourcefilename, new HashSet<string>(), false, false, clearerrors);
|
||||
}
|
||||
|
||||
public bool Parse(Stream stream, string sourcefilename, bool processincludes, bool isinclude, bool clearerrors)
|
||||
|
@ -52,19 +53,20 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
return Parse(stream, sourcefilename, includestoskip, processincludes, isinclude, clearerrors);
|
||||
}
|
||||
|
||||
public bool Parse(Stream stream, string sourcefilename, List<string> configincludes, bool processincludes, bool isinclude, bool clearerrors)
|
||||
public bool Parse(Stream stream, string sourcefilename, HashSet<string> configincludes, bool processincludes, bool isinclude, bool clearerrors)
|
||||
{
|
||||
parsedlumps.Add(sourcefilename);
|
||||
if(isinclude && !includes.Contains(sourcefilename)) includes.Add(sourcefilename);
|
||||
includestoskip = configincludes;
|
||||
int bracelevel = 0;
|
||||
string source = sourcefilename.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||
|
||||
// Integrity check
|
||||
if(stream == null || stream.Length == 0)
|
||||
// Duplicate checks
|
||||
if(parsedlumps.Contains(source))
|
||||
{
|
||||
ReportError("Unable to load " + (isinclude ? "include" : "") + " file '" + sourcefilename + "'!");
|
||||
ReportError("Already parsed '" + source + "'. Check your #include directives");
|
||||
return false;
|
||||
}
|
||||
|
||||
parsedlumps.Add(source);
|
||||
includestoskip = configincludes;
|
||||
int bracelevel = 0;
|
||||
|
||||
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
|
||||
|
||||
|
@ -204,6 +206,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
default:
|
||||
if(processincludes && (token == "#include" || token == "#import"))
|
||||
{
|
||||
//INFO: ZDoom ACC include paths can be absolute ("d:\stuff\coollib.acs"), relative ("../coollib.acs")
|
||||
//and can use forward and backward slashes ("acs\map01/script.acs")
|
||||
//also include paths must be quoted
|
||||
//long filenames are supported
|
||||
SkipWhitespace(true);
|
||||
string includelump = ReadToken(false); // Don't skip newline
|
||||
|
||||
|
@ -213,7 +219,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
return false;
|
||||
}
|
||||
|
||||
includelump = StripTokenQuotes(includelump).ToLowerInvariant();
|
||||
includelump = StripTokenQuotes(includelump);
|
||||
|
||||
if(string.IsNullOrEmpty(includelump))
|
||||
{
|
||||
|
@ -221,26 +227,39 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
return false;
|
||||
}
|
||||
|
||||
string includename = Path.GetFileName(includelump);
|
||||
includelump = includelump.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||
|
||||
// Compiler files?
|
||||
if(includestoskip.Contains(includename)) continue;
|
||||
if(includestoskip.Contains(includelump)) continue;
|
||||
|
||||
// Already parsed this?
|
||||
if(includes.Contains(includename))
|
||||
string includelumppath = GetRootedPath(source, includelump);
|
||||
|
||||
// Rooting succeeded?
|
||||
if(HasError || string.IsNullOrEmpty(includelumppath)) return false;
|
||||
|
||||
// Already parsed?
|
||||
if(includes.Contains(includelumppath))
|
||||
{
|
||||
ReportError("already parsed '" + includename + "'. Check your #include directives");
|
||||
ReportError("Already parsed '" + includelump + "'. Check your " + token + " directives");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add to collections
|
||||
includes.Add(includelumppath);
|
||||
|
||||
// Callback to parse this file
|
||||
if(OnInclude != null) OnInclude(this, includelump.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar));
|
||||
if(OnInclude != null) OnInclude(this, includelumppath);
|
||||
|
||||
// Bail out on error
|
||||
if(this.HasError) return false;
|
||||
|
||||
// Set our buffers back to continue parsing
|
||||
datastream = localstream;
|
||||
datareader = localreader;
|
||||
sourcename = localsourcename;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
private readonly Dictionary<string, DynamicLightData> lightsByName; //LightName, light definition
|
||||
private readonly Dictionary<string, string> objects; //ClassName, LightName
|
||||
private readonly Dictionary<long, GlowingFlatData> glowingflats;
|
||||
private readonly List<string> parsedlumps;
|
||||
private readonly HashSet<string> parsedlumps;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -69,7 +69,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
whitespace = "\n \t\r\u00A0";
|
||||
specialtokens = ",{}\n";
|
||||
|
||||
parsedlumps = new List<string>();
|
||||
parsedlumps = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
lightsByName = new Dictionary<string, DynamicLightData>(StringComparer.Ordinal); //LightName, Light params
|
||||
objects = new Dictionary<string, string>(StringComparer.Ordinal); //ClassName, LightName
|
||||
glowingflats = new Dictionary<long, GlowingFlatData>(); // Texture name hash, Glowing Flat Data
|
||||
|
@ -81,7 +81,6 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
|
||||
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
|
||||
{
|
||||
parsedlumps.Add(sourcefilename);
|
||||
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
|
||||
|
||||
// Keep local data
|
||||
|
@ -92,11 +91,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
// Continue until at the end of the stream
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
string token = ReadToken();
|
||||
string token = StripTokenQuotes(ReadToken()).ToLowerInvariant(); //Quotes can be anywhere! ANYWHERE!!! And GZDoom will still parse data correctly
|
||||
if(!string.IsNullOrEmpty(token))
|
||||
{
|
||||
token = StripTokenQuotes(token.ToLowerInvariant()); //Quotes can be anywhere! ANYWHERE!!! And GZDoom will still parse data correctly
|
||||
|
||||
//got light structure
|
||||
if(token == GldefsLightType.POINT || token == GldefsLightType.PULSE || token == GldefsLightType.FLICKER
|
||||
|| token == GldefsLightType.FLICKER2 || token == GldefsLightType.SECTOR)
|
||||
|
@ -131,7 +128,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Red))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected Red color value, but got '" + token + "'");
|
||||
ReportError("Expected Red color value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -141,7 +138,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Green))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected Green color value, but got '" + token + "'");
|
||||
ReportError("Expected Green color value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -151,7 +148,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Blue))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected Blue color value, but got '" + token + "'");
|
||||
ReportError("Expected Blue color value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
//size
|
||||
|
@ -166,7 +163,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.PrimaryRadius))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected Size value, but got '" + token + "'");
|
||||
ReportError("Expected Size value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
light.PrimaryRadius *= 2;
|
||||
|
@ -174,7 +171,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else
|
||||
{
|
||||
ReportError("'" + token + "' is not valid property for " + lightType + ".");
|
||||
ReportError("'" + token + "' is not valid property for " + lightType);
|
||||
return false;
|
||||
}
|
||||
//offset
|
||||
|
@ -187,7 +184,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!ReadSignedFloat(token, ref light.Offset.X))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected Offset X value, but got '" + token + "'");
|
||||
ReportError("Expected Offset X value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -197,7 +194,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!ReadSignedFloat(token, ref light.Offset.Z))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected Offset Y value, but got '" + token + "'");
|
||||
ReportError("Expected Offset Y value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -207,7 +204,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!ReadSignedFloat(token, ref light.Offset.Y))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected Offset Z value, but got '" + token + "'");
|
||||
ReportError("Expected Offset Z value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
//subtractive
|
||||
|
@ -237,7 +234,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected Dontlightself value, but got '" + token + "'");
|
||||
ReportError("Expected DontLightSelf value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -255,7 +252,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out interval))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected Interval value, but got '" + token + "'");
|
||||
ReportError("Expected Interval value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -288,7 +285,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.SecondaryRadius))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected SecondarySize value, but got '" + token + "'");
|
||||
ReportError("Expected SecondarySize value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
light.SecondaryRadius *= 2;
|
||||
|
@ -311,7 +308,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out chance))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected Chance value, but got '" + token + "'");
|
||||
ReportError("Expected Chance value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -336,13 +333,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected Scale value, but got '" + token + "'");
|
||||
ReportError("Expected Scale value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(scale > 1.0f)
|
||||
{
|
||||
ReportError("scale must be in 0.0 - 1.0 range, but is " + scale);
|
||||
ReportError("Scale must be in 0.0 - 1.0 range, but is " + scale);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -623,37 +620,59 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else if(token == "#include")
|
||||
{
|
||||
//INFO: ZDoom GLDEFS include paths can't be relative ("../glstuff.txt")
|
||||
//or absolute ("d:/project/glstuff.txt")
|
||||
//or have backward slases ("info\glstuff.txt")
|
||||
//include paths are relative to the first parsed entry, not the current one
|
||||
//also include paths may or may not be quoted
|
||||
SkipWhitespace(true);
|
||||
string includelump = ReadToken(false); // Don't skip newline
|
||||
string includelump = StripTokenQuotes(ReadToken(false)); // Don't skip newline
|
||||
|
||||
// Sanity checks
|
||||
if(!includelump.StartsWith("\"") || !includelump.EndsWith("\""))
|
||||
{
|
||||
ReportError("#include filename should be quoted");
|
||||
return false;
|
||||
}
|
||||
|
||||
includelump = StripTokenQuotes(includelump).ToLowerInvariant();
|
||||
|
||||
// More sanity checks
|
||||
if(string.IsNullOrEmpty(includelump))
|
||||
{
|
||||
ReportError("Expected file name to include");
|
||||
return false;
|
||||
}
|
||||
|
||||
includelump = includelump.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||
|
||||
// Already parsed?
|
||||
if(parsedlumps.IndexOf(includelump) != -1)
|
||||
// Absolute paths are not supported...
|
||||
if(Path.IsPathRooted(includelump))
|
||||
{
|
||||
ReportError("already parsed '" + includelump + "'. Check your #include directives");
|
||||
ReportError("Absolute include paths are not supported by ZDoom");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Relative paths are not supported
|
||||
if(includelump.StartsWith(RELATIVE_PATH_MARKER) || includelump.StartsWith(CURRENT_FOLDER_PATH_MARKER) ||
|
||||
includelump.StartsWith(ALT_RELATIVE_PATH_MARKER) || includelump.StartsWith(ALT_CURRENT_FOLDER_PATH_MARKER))
|
||||
{
|
||||
ReportError("Relative include paths are not supported by ZDoom");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Backward slases are not supported
|
||||
if(includelump.Contains(Path.DirectorySeparatorChar.ToString()))
|
||||
{
|
||||
ReportError("Only forward slases are supported by ZDoom");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Already parsed?
|
||||
if(parsedlumps.Contains(includelump))
|
||||
{
|
||||
ReportError("Already parsed '" + includelump + "'. Check your #include directives");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add to collection
|
||||
parsedlumps.Add(includelump);
|
||||
|
||||
// Callback to parse this file
|
||||
if(OnInclude != null) OnInclude(this, includelump, clearerrors);
|
||||
|
||||
// Bail out on error
|
||||
if(this.HasError) return false;
|
||||
|
||||
// Set our buffers back to continue parsing
|
||||
datastream = localstream;
|
||||
datareader = localreader;
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
mapinfo = new MapInfo();
|
||||
spawnnums = new Dictionary<int, string>();
|
||||
doomednums = new Dictionary<int, string>();
|
||||
parsedlumps = new HashSet<string>();
|
||||
parsedlumps = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -68,7 +68,6 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
public bool Parse(Stream stream, string sourcefilename, string mapname, bool clearerrors)
|
||||
{
|
||||
this.mapname = mapname.ToLowerInvariant();
|
||||
parsedlumps.Add(sourcefilename);
|
||||
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
|
||||
|
||||
while(SkipWhitespace(true))
|
||||
|
@ -166,7 +165,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!ReadSignedFloat(token, ref scrollSpeed))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected " + skyType + " scroll speed value, but got '" + token + "'");
|
||||
ReportError("Expected " + skyType + " scroll speed value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -182,7 +181,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else
|
||||
{
|
||||
ReportError("expected " + skyType + " texture name");
|
||||
ReportError("Expected " + skyType + " texture name");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +216,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else
|
||||
{
|
||||
ReportError("expected " + skyType + " texture name");
|
||||
ReportError("Expected " + skyType + " texture name");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -251,13 +250,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else //...or not
|
||||
{
|
||||
ReportError("failed to parse " + fadeType + " value from string '" + colorVal + "'");
|
||||
ReportError("Failed to parse " + fadeType + " value from string '" + colorVal + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportError("expected " + fadeType + " color value");
|
||||
ReportError("Expected " + fadeType + " color value");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -279,7 +278,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!ReadSignedInt(token, ref val))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected " + shadeType + " value, but got '" + token + "'");
|
||||
ReportError("Expected " + shadeType + " value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -306,7 +305,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected " + densityType + " value, but got '" + token + "'");
|
||||
ReportError("Expected " + densityType + " value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -352,17 +351,56 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(token == "include")
|
||||
}
|
||||
else if(token == "include") // It's "include", not "#include". Cause fuck consistency.
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
string includelump = StripTokenQuotes(ReadToken(false)).ToLowerInvariant(); // Don't skip newline
|
||||
|
||||
string includelump = StripTokenQuotes(ReadToken(false)); // Don't skip newline
|
||||
|
||||
//INFO: ZDoom MAPINFO include paths can't be relative ("../mapstuff.txt")
|
||||
//or absolute ("d:/project/mapstuff.txt")
|
||||
//or have backward slases ("info\mapstuff.txt")
|
||||
//include paths are relative to the first parsed entry, not the current one
|
||||
//also include paths may or may not be quoted
|
||||
if(!string.IsNullOrEmpty(includelump))
|
||||
{
|
||||
// Absolute paths are not supported...
|
||||
if(Path.IsPathRooted(includelump))
|
||||
{
|
||||
ReportError("Absolute include paths are not supported by ZDoom");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Relative paths are not supported
|
||||
if(includelump.StartsWith(RELATIVE_PATH_MARKER) || includelump.StartsWith(CURRENT_FOLDER_PATH_MARKER) ||
|
||||
includelump.StartsWith(ALT_RELATIVE_PATH_MARKER) || includelump.StartsWith(ALT_CURRENT_FOLDER_PATH_MARKER))
|
||||
{
|
||||
ReportError("Relative include paths are not supported by ZDoom");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Backward slases are not supported
|
||||
if(includelump.Contains(Path.DirectorySeparatorChar.ToString()))
|
||||
{
|
||||
ReportError("Only forward slases are supported by ZDoom");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Already parsed?
|
||||
if(parsedlumps.Contains(includelump))
|
||||
{
|
||||
ReportError("Already parsed '" + includelump + "'. Check your include directives");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add to collection
|
||||
parsedlumps.Add(includelump);
|
||||
|
||||
// Callback to parse this file
|
||||
if(OnInclude != null)
|
||||
OnInclude(this, includelump.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar), clearerrors);
|
||||
if(OnInclude != null) OnInclude(this, includelump, clearerrors);
|
||||
|
||||
// Bail out on error
|
||||
if(this.HasError) return false;
|
||||
|
||||
// Set our buffers back to continue parsing
|
||||
datastream = localstream;
|
||||
|
@ -371,7 +409,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else
|
||||
{
|
||||
ReportError("got include directive with missing or incorrect path: '" + includelump + "'");
|
||||
ReportError("Expected filename to include");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -384,7 +422,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
token = ReadToken();
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
ReportError("failed to find the end of GameInfo block");
|
||||
ReportError("Failed to find the end of GameInfo block");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
if(token == "}") break;
|
||||
|
@ -396,7 +434,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
string skyflatname = StripTokenQuotes(ReadToken());
|
||||
if(string.IsNullOrEmpty(skyflatname))
|
||||
{
|
||||
ReportError("unable to get SkyFlatName value");
|
||||
ReportError("Unable to get SkyFlatName value");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
|
||||
|
@ -413,7 +451,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
token = ReadToken();
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
ReportError("failed to find the end of DoomEdNums block");
|
||||
ReportError("Failed to find the end of DoomEdNums block");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
if(token == "}") break;
|
||||
|
@ -423,7 +461,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out id))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected DoomEdNums entry number, but got '" + token + "'");
|
||||
ReportError("Expected DoomEdNums entry number, but got '" + token + "'");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
|
||||
|
@ -435,7 +473,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
string classname = StripTokenQuotes(ReadToken());
|
||||
if(string.IsNullOrEmpty(classname))
|
||||
{
|
||||
ReportError("unable to get DoomEdNums entry class definition");
|
||||
ReportError("Unable to get DoomEdNums entry class definition");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
|
||||
|
@ -461,7 +499,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
token = ReadToken();
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
ReportError("failed to find the end of SpawnNums block");
|
||||
ReportError("Failed to find the end of SpawnNums block");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
if(token == "}") break;
|
||||
|
@ -471,7 +509,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out id))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected SpawnNums number, but got '" + token + "'");
|
||||
ReportError("Expected SpawnNums number, but got '" + token + "'");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
|
||||
|
@ -483,7 +521,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
token = StripTokenQuotes(ReadToken());
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
ReportError("unable to get SpawnNums entry class definition");
|
||||
ReportError("Unable to get SpawnNums entry class definition");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,14 +6,18 @@ using CodeImp.DoomBuilder.GZBuilder.Data;
|
|||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
||||
{
|
||||
internal class ModeldefParser : ZDTextParser
|
||||
internal class ModeldefParser : ZDTextParser
|
||||
{
|
||||
private readonly Dictionary<string, int> actorsbyclass;
|
||||
internal Dictionary<string, int> ActorsByClass { get { return actorsbyclass; } }
|
||||
|
||||
private Dictionary<string, ModelData> entries; //classname, entry
|
||||
internal Dictionary<string, ModelData> Entries { get { return entries; } }
|
||||
|
||||
internal ModeldefParser()
|
||||
internal ModeldefParser(Dictionary<string, int> actorsbyclass)
|
||||
{
|
||||
entries = new Dictionary<string, ModelData>(StringComparer.Ordinal);
|
||||
this.actorsbyclass = actorsbyclass;
|
||||
this.entries = new Dictionary<string, ModelData>(StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
//should be called after all decorate actors are parsed
|
||||
|
@ -60,22 +64,15 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
|
||||
// Skip untill current structure end
|
||||
if(!mds.ParsingFinished)
|
||||
{
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
token = ReadToken();
|
||||
if(string.IsNullOrEmpty(token) || token == "}") break;
|
||||
}
|
||||
}
|
||||
if(!mds.ParsingFinished) SkipStructure(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown structure!
|
||||
string token2;
|
||||
if(token != "{")
|
||||
if(token != "{")
|
||||
{
|
||||
string token2;
|
||||
do
|
||||
{
|
||||
if(!SkipWhitespace(true)) break;
|
||||
|
@ -85,16 +82,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
while(token2 != "{");
|
||||
}
|
||||
|
||||
int scopelevel = 1;
|
||||
do
|
||||
{
|
||||
if(!SkipWhitespace(true)) break;
|
||||
token2 = ReadToken();
|
||||
if(string.IsNullOrEmpty(token2)) break;
|
||||
if(token2 == "{") scopelevel++;
|
||||
if(token2 == "}") scopelevel--;
|
||||
}
|
||||
while(scopelevel > 0);
|
||||
SkipStructure(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,6 +90,20 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
return entries.Count > 0;
|
||||
}
|
||||
|
||||
// Skips untill current structure end
|
||||
private void SkipStructure(int scopelevel)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(!SkipWhitespace(true)) break;
|
||||
string token = ReadToken();
|
||||
if(string.IsNullOrEmpty(token)) break;
|
||||
if(token == "{") scopelevel++;
|
||||
if(token == "}") scopelevel--;
|
||||
}
|
||||
while(scopelevel > 0);
|
||||
}
|
||||
|
||||
protected override string GetLanguageType()
|
||||
{
|
||||
return "MODELDEF";
|
||||
|
|
|
@ -60,7 +60,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
path = parser.StripTokenQuotes(parser.ReadToken(false)).Replace("/", "\\"); // Don't skip newline
|
||||
if(string.IsNullOrEmpty(path))
|
||||
{
|
||||
parser.ReportError("expected model path, but got '" + token + "'");
|
||||
parser.ReportError("Expected model path, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -78,7 +78,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out index))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected model index, but got '" + token + "'");
|
||||
parser.ReportError("Expected model index, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
token = parser.StripTokenQuotes(parser.ReadToken(false)).ToLowerInvariant(); // Don't skip newline
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
parser.ReportError("model name required");
|
||||
parser.ReportError("Expected model name");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -102,13 +102,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
string fileExt = Path.GetExtension(token);
|
||||
if(string.IsNullOrEmpty(fileExt))
|
||||
{
|
||||
parser.ReportError("model '" + token + "' won't be loaded. Models without extension are not supported by GZDoom");
|
||||
parser.ReportError("Model '" + token + "' won't be loaded. Models without extension are not supported by GZDoom");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fileExt != ".md3" && fileExt != ".md2")
|
||||
{
|
||||
parser.ReportError("model '" + token + "' won't be loaded. Only MD2 and MD3 models are supported");
|
||||
parser.ReportError("Model '" + token + "' won't be loaded. Only MD2 and MD3 models are supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out skinIndex))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected skin index, but got '" + token + "'");
|
||||
parser.ReportError("Expected skin index, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -145,7 +145,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
token = parser.StripTokenQuotes(parser.ReadToken(false)).ToLowerInvariant(); // Don't skip newline
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
parser.ReportError("skin path required");
|
||||
parser.ReportError("Skin path required");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
string ext = Path.GetExtension(token);
|
||||
if(Array.IndexOf(ModelData.SUPPORTED_TEXTURE_EXTENSIONS, ext) == -1)
|
||||
{
|
||||
parser.ReportError("image format '" + ext + "' is not supported!");
|
||||
parser.ReportError("Image format '" + ext + "' is not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref scale.Y))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected Scale X value, but got '" + token + "'");
|
||||
parser.ReportError("Expected Scale X value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref scale.X))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected Scale Y value, but got '" + token + "'");
|
||||
parser.ReportError("Expected Scale Y value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref scale.Z))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected Scale Z value, but got '" + token + "'");
|
||||
parser.ReportError("Expected Scale Z value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -204,7 +204,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref offset.X))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected Offset X value, but got '" + token + "'");
|
||||
parser.ReportError("Expected Offset X value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -213,7 +213,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref offset.Y))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected Offset Y value, but got '" + token + "'");
|
||||
parser.ReportError("Expected Offset Y value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -222,7 +222,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref offset.Z))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected Offset Z value, but got '" + token + "'");
|
||||
parser.ReportError("Expected Offset Z value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -237,7 +237,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref offset.Z))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected ZOffset value, but got '" + token + "'");
|
||||
parser.ReportError("Expected ZOffset value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -252,7 +252,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref angleOffset))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected AngleOffset value, but got '" + token + "'");
|
||||
parser.ReportError("Expected AngleOffset value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -267,7 +267,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref pitchOffset))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected PitchOffset value, but got '" + token + "'");
|
||||
parser.ReportError("Expected PitchOffset value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -282,7 +282,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref rollOffset))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected RollOffset value, but got '" + token + "'");
|
||||
parser.ReportError("Expected RollOffset value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -376,7 +376,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out modelIndex))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected model index, but got '" + token + "'");
|
||||
parser.ReportError("Expected model index, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
|
||||
if(modelNames[modelIndex] == null)
|
||||
{
|
||||
parser.ReportError("got model index, which doesn't correspond to any defined model");
|
||||
parser.ReportError("Model index doesn't correspond to any defined model");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -404,7 +404,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedInt(token, ref frame))
|
||||
{
|
||||
// Not numeric!
|
||||
parser.ReportError("expected model frame index, but got '" + token + "'");
|
||||
parser.ReportError("Expected model frame index, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -417,7 +417,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
// Missing!
|
||||
parser.ReportError("expected model frame name");
|
||||
parser.ReportError("Expected model frame name");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -451,7 +451,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
// Bail out when got errors or no models are used
|
||||
if(Array.IndexOf(modelsUsed, true) == -1)
|
||||
{
|
||||
parser.ReportError("no models are used by '" + classname + "'");
|
||||
parser.ReportError("No models are used by '" + classname + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,14 +59,14 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
string texturename = StripTokenQuotes(ReadToken(false));
|
||||
if(string.IsNullOrEmpty(texturename))
|
||||
{
|
||||
ReportError("expected camera texture name");
|
||||
ReportError("Expected camera texture name");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Camera texture names are limited to 8 chars
|
||||
if(texturename.Length > DataManager.CLASIC_IMAGE_NAME_LENGTH)
|
||||
{
|
||||
ReportError("camera texture names must be no longer than " + DataManager.CLASIC_IMAGE_NAME_LENGTH + " chars");
|
||||
ReportError("Camera texture names must be no longer than " + DataManager.CLASIC_IMAGE_NAME_LENGTH + " chars");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
SkipWhitespace(true);
|
||||
if(!ReadSignedInt(ref width) || width < 1)
|
||||
{
|
||||
ReportError("expected camera texture width");
|
||||
ReportError("Expected camera texture width");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
SkipWhitespace(true);
|
||||
if(!ReadSignedInt(ref height) || height < 1)
|
||||
{
|
||||
ReportError("expected camera texture height");
|
||||
ReportError("Expected camera texture height");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
SkipWhitespace(true);
|
||||
if(!ReadSignedInt(ref fitwidth) || fitwidth < 1)
|
||||
{
|
||||
ReportError("expected camera texture fit width");
|
||||
ReportError("Expected camera texture fit width");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
SkipWhitespace(true);
|
||||
if(!ReadSignedInt(ref fitheight) || fitheight < 1)
|
||||
{
|
||||
ReportError("expected camera texture fit height");
|
||||
ReportError("Expected camera texture fit height");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,9 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
// These are all parsed actors, also those from other games
|
||||
private Dictionary<string, ActorStructure> archivedactors;
|
||||
|
||||
//mxd. Includes tracking
|
||||
private readonly HashSet<string> parsedlumps;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -84,6 +87,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
// Initialize
|
||||
actors = new Dictionary<string, ActorStructure>(StringComparer.Ordinal);
|
||||
archivedactors = new Dictionary<string, ActorStructure>(StringComparer.Ordinal);
|
||||
parsedlumps = new HashSet<string>(StringComparer.OrdinalIgnoreCase); //mxd
|
||||
}
|
||||
|
||||
// Disposer
|
||||
|
@ -148,35 +152,63 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
case "#include":
|
||||
{
|
||||
// Include a file
|
||||
//INFO: ZDoom DECORATE include paths can't be relative ("../actor.txt")
|
||||
//or absolute ("d:/project/actor.txt")
|
||||
//or have backward slases ("info\actor.txt")
|
||||
//include paths are relative to the first parsed entry, not the current one
|
||||
//also include paths may or may not be quoted
|
||||
SkipWhitespace(true);
|
||||
string filename = ReadToken(false); //mxd. Don't skip newline
|
||||
string filename = StripTokenQuotes(ReadToken(false)); //mxd. Don't skip newline
|
||||
|
||||
//mxd. Sanity checks
|
||||
if(!filename.StartsWith("\"") || !filename.EndsWith("\""))
|
||||
{
|
||||
ReportError("#include filename should be quoted");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Strip the quotes
|
||||
filename = filename.Replace("\"", "");
|
||||
|
||||
//mxd. More sanity checks
|
||||
if(string.IsNullOrEmpty(filename))
|
||||
{
|
||||
ReportError("Expected file name to include");
|
||||
return false;
|
||||
}
|
||||
|
||||
//mxd. Absolute paths are not supported...
|
||||
if(Path.IsPathRooted(filename))
|
||||
{
|
||||
ReportError("Absolute include paths are not supported by ZDoom");
|
||||
return false;
|
||||
}
|
||||
|
||||
//mxd. Relative paths are not supported
|
||||
if(filename.StartsWith(RELATIVE_PATH_MARKER) || filename.StartsWith(CURRENT_FOLDER_PATH_MARKER) ||
|
||||
filename.StartsWith(ALT_RELATIVE_PATH_MARKER) || filename.StartsWith(ALT_CURRENT_FOLDER_PATH_MARKER))
|
||||
{
|
||||
ReportError("Relative include paths are not supported by ZDoom");
|
||||
return false;
|
||||
}
|
||||
|
||||
//mxd. Backward slases are not supported
|
||||
if(filename.Contains(Path.DirectorySeparatorChar.ToString()))
|
||||
{
|
||||
ReportError("Only forward slases are supported by ZDoom");
|
||||
return false;
|
||||
}
|
||||
|
||||
//mxd. Already parsed?
|
||||
if(parsedlumps.Contains(filename))
|
||||
{
|
||||
ReportError("Already parsed '" + filename + "'. Check your include directives");
|
||||
return false;
|
||||
}
|
||||
|
||||
//mxd. Add to collection
|
||||
parsedlumps.Add(filename);
|
||||
|
||||
// Callback to parse this file now
|
||||
if(OnInclude != null) OnInclude(this, filename);
|
||||
|
||||
//mxd. Bail out on error
|
||||
if(this.HasError) return false;
|
||||
|
||||
// Set our buffers back to continue parsing
|
||||
datastream = localstream;
|
||||
datareader = localreader;
|
||||
sourcename = localsourcename;
|
||||
if(this.HasError) return false;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -71,8 +71,6 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
// Constructor
|
||||
internal PatchStructure(TexturesParser parser)
|
||||
{
|
||||
string tokenstr;
|
||||
|
||||
// Initialize
|
||||
alpha = 1.0f;
|
||||
renderStyle = TexturePathRenderStyle.Copy;//mxd
|
||||
|
@ -94,17 +92,11 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
name = name.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||
|
||||
// Now we should find a comma
|
||||
parser.SkipWhitespace(true);
|
||||
tokenstr = parser.ReadToken();
|
||||
if(tokenstr != ",")
|
||||
{
|
||||
parser.ReportError("Expected a comma");
|
||||
return;
|
||||
}
|
||||
if(!parser.NextTokenIs(",")) return; //mxd
|
||||
|
||||
// Next is the patch width
|
||||
parser.SkipWhitespace(true);
|
||||
tokenstr = parser.ReadToken();
|
||||
string tokenstr = parser.ReadToken();
|
||||
if(string.IsNullOrEmpty(tokenstr) || !int.TryParse(tokenstr, NumberStyles.Integer, CultureInfo.InvariantCulture, out offsetx))
|
||||
{
|
||||
parser.ReportError("Expected offset in pixels");
|
||||
|
@ -112,13 +104,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
}
|
||||
|
||||
// Now we should find a comma again
|
||||
parser.SkipWhitespace(true);
|
||||
tokenstr = parser.ReadToken();
|
||||
if(tokenstr != ",")
|
||||
{
|
||||
parser.ReportError("Expected a comma");
|
||||
return;
|
||||
}
|
||||
if(!parser.NextTokenIs(",")) return; //mxd
|
||||
|
||||
// Next is the patch height
|
||||
parser.SkipWhitespace(true);
|
||||
|
@ -129,16 +115,8 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
return;
|
||||
}
|
||||
|
||||
// Next token is the beginning of the texture scope.
|
||||
// If not, then the patch info ends here.
|
||||
parser.SkipWhitespace(true);
|
||||
tokenstr = parser.ReadToken();
|
||||
if(tokenstr != "{")
|
||||
{
|
||||
// Rewind so this structure can be read again
|
||||
parser.DataStream.Seek(-tokenstr.Length - 1, SeekOrigin.Current);
|
||||
return;
|
||||
}
|
||||
// Next token is the beginning of the texture scope. If not, then the patch info ends here.
|
||||
if(!parser.NextTokenIs("{", false)) return; //mxd
|
||||
|
||||
// Now parse the contents of texture structure
|
||||
bool done = false; //mxd
|
||||
|
@ -169,7 +147,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
if(rotation != 0 && rotation != 90 && rotation != 180 && rotation != 270)
|
||||
{
|
||||
parser.LogWarning("Got unsupported rotation (" + rotation + ") in patch '" + name + "'");
|
||||
parser.LogWarning("Unsupported rotation (" + rotation + ") in patch '" + name + "'");
|
||||
rotation = 0;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
if(string.IsNullOrEmpty(name))
|
||||
{
|
||||
ReportError("Got empty sound environment name");
|
||||
ReportError("Expected sound environment name");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
int arg1;
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out arg1))
|
||||
{
|
||||
ReportError("Failed to parse the first part of '" + name + "' sound environment ID");
|
||||
ReportError("Expected first part of '" + name + "' sound environment ID, but got '" + token + "'");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
int arg2;
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out arg2))
|
||||
{
|
||||
ReportError("Failed to parse the second part of '" + name + "' sound environment ID");
|
||||
ReportError("Expected second part of '" + name + "' sound environment ID, but got '" + token + "'");
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,17 +102,11 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
}
|
||||
|
||||
// Now we should find a comma
|
||||
parser.SkipWhitespace(true);
|
||||
string tokenstr = parser.ReadToken();
|
||||
if(tokenstr != ",")
|
||||
{
|
||||
parser.ReportError("Expected a comma");
|
||||
return;
|
||||
}
|
||||
if(!parser.NextTokenIs(",")) return; //mxd
|
||||
|
||||
// Next is the texture width
|
||||
parser.SkipWhitespace(true);
|
||||
tokenstr = parser.ReadToken();
|
||||
string tokenstr = parser.ReadToken();
|
||||
if(string.IsNullOrEmpty(tokenstr) || !int.TryParse(tokenstr, NumberStyles.Integer, CultureInfo.InvariantCulture, out width))
|
||||
{
|
||||
parser.ReportError("Expected width in pixels");
|
||||
|
@ -120,13 +114,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
}
|
||||
|
||||
// Now we should find a comma again
|
||||
parser.SkipWhitespace(true);
|
||||
tokenstr = parser.ReadToken();
|
||||
if(tokenstr != ",")
|
||||
{
|
||||
parser.ReportError("Expected a comma");
|
||||
return;
|
||||
}
|
||||
if(!parser.NextTokenIs(",")) return; //mxd
|
||||
|
||||
// Next is the texture height
|
||||
parser.SkipWhitespace(true);
|
||||
|
@ -138,9 +126,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
}
|
||||
|
||||
// Next token should be the beginning of the texture scope
|
||||
parser.SkipWhitespace(true);
|
||||
tokenstr = parser.ReadToken();
|
||||
if(tokenstr != "{")
|
||||
if(!parser.NextTokenIs("{", false)) //mxd
|
||||
{
|
||||
parser.ReportError("Expected begin of structure");
|
||||
return;
|
||||
|
@ -172,13 +158,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
if(!ReadTokenInt(parser, token, out xoffset)) return;
|
||||
|
||||
// Now we should find a comma
|
||||
parser.SkipWhitespace(true);
|
||||
tokenstr = parser.ReadToken();
|
||||
if(tokenstr != ",")
|
||||
{
|
||||
parser.ReportError("Expected a comma");
|
||||
return;
|
||||
}
|
||||
if(!parser.NextTokenIs(",")) return; //mxd
|
||||
|
||||
// Read y offset
|
||||
if(!ReadTokenInt(parser, token, out yoffset)) return;
|
||||
|
@ -223,19 +203,15 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
parser.ReportError("Expected numeric value for property '" + propertyname + "'");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Success
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't find the property value!
|
||||
parser.ReportError("Expected a value for property '" + propertyname + "'");
|
||||
value = 0.0f;
|
||||
return false;
|
||||
|
||||
// Success
|
||||
return true;
|
||||
}
|
||||
|
||||
// Can't find the property value!
|
||||
parser.ReportError("Expected a value for property '" + propertyname + "'");
|
||||
value = 0.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
// This reads the next token and sets an integral value, returns false when failed
|
||||
|
@ -252,41 +228,29 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
parser.ReportError("Expected integral value for property '" + propertyname + "'");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Success
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't find the property value!
|
||||
parser.ReportError("Expected a value for property '" + propertyname + "'");
|
||||
value = 0;
|
||||
return false;
|
||||
|
||||
// Success
|
||||
return true;
|
||||
}
|
||||
|
||||
// Can't find the property value!
|
||||
parser.ReportError("Expected a value for property '" + propertyname + "'");
|
||||
value = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// This makes a HighResImage texture for this texture
|
||||
internal HighResImage MakeImage()
|
||||
{
|
||||
float scalex, scaley;
|
||||
|
||||
// Determine default scale
|
||||
float defaultscale = General.Map.Config.DefaultTextureScale;
|
||||
|
||||
// Determine scale for texture
|
||||
if(xscale == 0.0f) scalex = defaultscale; else scalex = 1f / xscale;
|
||||
if(yscale == 0.0f) scaley = defaultscale; else scaley = 1f / yscale;
|
||||
float scalex = ((xscale == 0.0f) ? General.Map.Config.DefaultTextureScale : 1f / xscale);
|
||||
float scaley = ((yscale == 0.0f) ? General.Map.Config.DefaultTextureScale : 1f / yscale);
|
||||
|
||||
// Make texture
|
||||
HighResImage tex = new HighResImage(name, virtualpath, width, height, scalex, scaley, worldpanning, typename == "flat");
|
||||
|
||||
// Add patches
|
||||
foreach(PatchStructure p in patches)
|
||||
{
|
||||
tex.AddPatch(new TexturePatch(p));//mxd
|
||||
}
|
||||
foreach(PatchStructure p in patches) tex.AddPatch(new TexturePatch(p));//mxd
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
//mxd. Can't load image without name
|
||||
if(string.IsNullOrEmpty(tx.Name))
|
||||
{
|
||||
ReportError("Can't load an unnamed texture. Please consider giving names to your resources.");
|
||||
ReportError("Can't load an unnamed texture. Please consider giving names to your resources");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
//mxd. Can't load image without name
|
||||
if(string.IsNullOrEmpty(tx.Name))
|
||||
{
|
||||
ReportError("Can't load an unnamed sprite. Please consider giving names to your resources.");
|
||||
ReportError("Can't load an unnamed sprite. Please consider giving names to your resources");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
//mxd. Can't load image without name
|
||||
if(string.IsNullOrEmpty(tx.Name))
|
||||
{
|
||||
ReportError("Can't load an unnamed WallTexture. Please consider giving names to your resources.");
|
||||
ReportError("Can't load an unnamed WallTexture. Please consider giving names to your resources");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
//mxd. Can't load image without name
|
||||
if(string.IsNullOrEmpty(tx.Name))
|
||||
{
|
||||
ReportError("Can't load an unnamed flat. Please consider giving names to your resources.");
|
||||
ReportError("Can't load an unnamed flat. Please consider giving names to your resources");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
{
|
||||
if(!string.IsNullOrEmpty(prevToken) && !spriteNames.Contains(prevToken)) spriteNames.Add(prevToken);
|
||||
prevToken = token.ToUpperInvariant();
|
||||
|
||||
}
|
||||
else if(token == "=") //next token should be a voxel model name
|
||||
{
|
||||
|
@ -78,14 +77,8 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
foreach(string s in spriteNames)
|
||||
{
|
||||
if(entries.ContainsKey(s)) //TODO: is this a proper behaviour?
|
||||
{
|
||||
entries[s] = mde;
|
||||
}
|
||||
else
|
||||
{
|
||||
entries.Add(s, mde);
|
||||
}
|
||||
//TODO: is this the proper behaviour?
|
||||
entries[s] = mde;
|
||||
}
|
||||
|
||||
//reset local data
|
||||
|
@ -96,45 +89,31 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
break;
|
||||
}
|
||||
else if(token == "overridepalette")
|
||||
else if(token == "overridepalette")
|
||||
{
|
||||
mde.OverridePalette = true;
|
||||
}
|
||||
else if(token == "angleoffset")
|
||||
else if(token == "angleoffset")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
if(!NextTokenIs("=")) return false;
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if(token != "=")
|
||||
{
|
||||
ReportError("expected '=', but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if(!ReadSignedFloat(token, ref angleoffset))
|
||||
if(!ReadSignedFloat(token, ref angleoffset))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected AngleOffset value, but got '" + token + "'");
|
||||
ReportError("Expected AngleOffset value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(token == "scale")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if(token != "=")
|
||||
{
|
||||
ReportError("expected '=', but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
if(!NextTokenIs("=")) return false;
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if(!ReadSignedFloat(token, ref scale))
|
||||
{
|
||||
// Not numeric!
|
||||
ReportError("expected Scale value, but got '" + token + "'");
|
||||
ReportError("Expected Scale value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ using System.Globalization;
|
|||
using System.Text;
|
||||
using System.IO;
|
||||
using CodeImp.DoomBuilder.Compilers;
|
||||
using CodeImp.DoomBuilder.Data;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -29,6 +30,11 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
public abstract class ZDTextParser
|
||||
{
|
||||
#region ================== Constants
|
||||
|
||||
protected static readonly string RELATIVE_PATH_MARKER = ".." + Path.DirectorySeparatorChar;
|
||||
protected static readonly string CURRENT_FOLDER_PATH_MARKER = "." + Path.DirectorySeparatorChar;
|
||||
protected static readonly string ALT_RELATIVE_PATH_MARKER = ".." + Path.AltDirectorySeparatorChar;
|
||||
protected static readonly string ALT_CURRENT_FOLDER_PATH_MARKER = "." + Path.AltDirectorySeparatorChar;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -84,7 +90,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
//mxd. Integrity check
|
||||
if(stream == null || stream.Length == 0)
|
||||
{
|
||||
ReportError("Unable to load '" + sourcefilename + "'!");
|
||||
ReportError("Unable to load '" + sourcefilename + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -408,20 +414,20 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
}
|
||||
|
||||
//mxd
|
||||
protected bool NextTokenIs(string expectedtoken)
|
||||
internal bool NextTokenIs(string expectedtoken)
|
||||
{
|
||||
return NextTokenIs(expectedtoken, true);
|
||||
}
|
||||
|
||||
//mxd
|
||||
protected bool NextTokenIs(string expectedtoken, bool reporterror)
|
||||
internal bool NextTokenIs(string expectedtoken, bool reporterror)
|
||||
{
|
||||
if(!SkipWhitespace(true)) return false;
|
||||
string token = ReadToken();
|
||||
|
||||
if(string.Compare(token, expectedtoken, true) != 0)
|
||||
{
|
||||
if(reporterror) ReportError("expected '" + expectedtoken + "', but got '" + token + "'");
|
||||
if(reporterror) ReportError("Expected '" + expectedtoken + "', but got '" + token + "'");
|
||||
|
||||
// Rewind so this structure can be read again
|
||||
DataStream.Seek(-token.Length - 1, SeekOrigin.Current);
|
||||
|
@ -525,6 +531,69 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
return Math.Max(linenumber, 0);
|
||||
}
|
||||
|
||||
//mxd. This converts given path to be relative to "filename"
|
||||
protected string GetRootedPath(string filename, string includefilename)
|
||||
{
|
||||
// Construct root-relative path...
|
||||
filename = filename.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||
|
||||
// Filename absolute? Try to convert it to resource-rooted
|
||||
if(Path.IsPathRooted(filename))
|
||||
{
|
||||
foreach(DataReader reader in General.Map.Data.Containers)
|
||||
{
|
||||
if(reader is DirectoryReader && filename.StartsWith(reader.Location.location, true, CultureInfo.InvariantCulture))
|
||||
{
|
||||
filename = filename.Substring(reader.Location.location.Length + 1, filename.Length - reader.Location.location.Length - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string filepath = Path.GetDirectoryName(filename);
|
||||
string result = includefilename.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||
|
||||
if(result.StartsWith(RELATIVE_PATH_MARKER) && !string.IsNullOrEmpty(filepath))
|
||||
{
|
||||
string[] parts = filepath.Split(Path.DirectorySeparatorChar);
|
||||
int index = parts.Length - 1;
|
||||
int pos;
|
||||
|
||||
// Count & trim relative path markers
|
||||
while((pos = result.LastIndexOf(RELATIVE_PATH_MARKER, StringComparison.Ordinal)) != -1)
|
||||
{
|
||||
// includefilename references something above the root?
|
||||
if(index-- < 0)
|
||||
{
|
||||
ReportError("Unable to construct rooted path from '" + includefilename + "'");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
string start = result.Substring(0, pos);
|
||||
string end = result.Substring(pos + RELATIVE_PATH_MARKER.Length, result.Length - pos - RELATIVE_PATH_MARKER.Length);
|
||||
result = start + end;
|
||||
}
|
||||
|
||||
// Construct absolute path relative to current filename
|
||||
while(index > -1)
|
||||
{
|
||||
result = parts[index--] + Path.DirectorySeparatorChar + result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Trim "this folder" marker
|
||||
if(result.StartsWith(CURRENT_FOLDER_PATH_MARKER))
|
||||
result = result.TrimStart(CURRENT_FOLDER_PATH_MARKER.ToCharArray());
|
||||
|
||||
// Treat as relative path
|
||||
if(!string.IsNullOrEmpty(filepath))
|
||||
result = Path.Combine(filepath, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//mxd. Language type
|
||||
protected abstract string GetLanguageType();
|
||||
|
||||
|
|
Loading…
Reference in a new issue