mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-23 04:12:12 +00:00
Fixed, Script Editor: file was marked as changed when changing script configurations.
Fixed, Script Editor: in some cases clicking on an error in the errors list didn't navigate to the error location. Fixed, Script Editor: in some cases incorrect error line number was shown. Fixed, Text lump parsers: fixed a crash when trying to get a filename from a quoted string with missing closing quote. Fixed, Text lump parsers: in several cases parsing errors were ignored by overlaying data structures. Fixed: in some cases Thing Filter thing flags were cleared when switching game configurations in the "Game Configurations" window. Changed, PK3 reader: loading of files with invalid path chars is now skipped instead of skipping loading of the whole resource. Also more helpful warning message is now displayed. Updated SharpCompress library to v.0.11.2.0.
This commit is contained in:
parent
a35a336527
commit
dbcc57b7a6
40 changed files with 1117 additions and 894 deletions
|
@ -9,5 +9,7 @@ compilers
|
|||
{
|
||||
interface = "AccCompiler";
|
||||
program = "bcc.exe";
|
||||
zcommon = "zcommon.acs";
|
||||
std = "std.acs";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,5 +9,9 @@ compilers
|
|||
{
|
||||
interface = "AccCompiler";
|
||||
program = "acc.exe";
|
||||
zcommon = "common.acs";
|
||||
zdefs = "defs.acs";
|
||||
zspecial = "specials.acs";
|
||||
zwvars = "wvars.acs";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,5 +9,9 @@ compilers
|
|||
{
|
||||
interface = "AccCompiler";
|
||||
program = "acc.exe";
|
||||
zcommon = "zcommon.acs";
|
||||
zdefs = "zdefs.acs";
|
||||
zspecial = "zspecial.acs";
|
||||
zwvars = "zwvars.acs";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,5 +9,9 @@ compilers
|
|||
{
|
||||
interface = "AccCompiler";
|
||||
program = "acc.exe";
|
||||
zcommon = "zcommon.acs";
|
||||
zdefs = "zdefs.acs";
|
||||
zspecial = "zspecial.acs";
|
||||
zwvars = "zwvars.acs";
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -533,7 +533,9 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="JetBrains.Profiler.Core.Api, Version=1.3.1661.20096, Culture=neutral, PublicKeyToken=1010a0d8d6380325" Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' Or '$(Configuration)|$(Platform)' == 'Release + Profiler|x86' " />
|
||||
<Reference Include="SharpCompress.3.5, Version=0.11.1.0, Culture=neutral, processorArchitecture=x86" />
|
||||
<Reference Include="SharpCompress.3.5, Version=0.11.2.0, Culture=neutral, processorArchitecture=x86">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="SlimDX, Version=2.0.13.43, Culture=neutral, PublicKeyToken=b1b0c32fd1ffe4f9, processorArchitecture=x86" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
|
@ -860,7 +862,6 @@
|
|||
<Compile Include="GZBuilder\Data\ModelLoadState.cs" />
|
||||
<Compile Include="GZBuilder\Data\ScriptItem.cs" />
|
||||
<Compile Include="GZBuilder\Data\SharpCompressHelper.cs" />
|
||||
<Compile Include="GZBuilder\Data\TextureData.cs" />
|
||||
<Compile Include="GZBuilder\Rendering\SizelessVisualThingCage.cs" />
|
||||
<Compile Include="GZBuilder\Rendering\ThingBoundingBox.cs" />
|
||||
<Compile Include="GZBuilder\Data\ThingCopyData.cs" />
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using CodeImp.DoomBuilder.Config;
|
||||
|
@ -44,7 +43,7 @@ namespace CodeImp.DoomBuilder.Compilers
|
|||
#region ================== Constructor
|
||||
|
||||
// Constructor
|
||||
public AccCompiler(CompilerInfo info) : base(info)
|
||||
public AccCompiler(CompilerInfo info) : base(info, false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace CodeImp.DoomBuilder.Compilers
|
|||
#region ================== Constructor / Disposer
|
||||
|
||||
// Constructor
|
||||
protected Compiler(CompilerInfo info)
|
||||
protected Compiler(CompilerInfo info, bool copyrequiredfiles)
|
||||
{
|
||||
// Initialize
|
||||
this.info = info;
|
||||
|
@ -83,10 +83,15 @@ namespace CodeImp.DoomBuilder.Compilers
|
|||
// Create temporary directory
|
||||
tempdir = Directory.CreateDirectory(General.MakeTempDirname());
|
||||
workingdir = tempdir.FullName;
|
||||
|
||||
// Copy required files to the temp directory
|
||||
General.WriteLogLine("Copying required files for compiler...");
|
||||
CopyRequiredFiles();
|
||||
|
||||
//mxd. ACC compiler itself is not copied to tempdir anymore, so we don't need to move it's include files
|
||||
//but we still need tempdir to compile SCRIPTS lump.
|
||||
if(copyrequiredfiles)
|
||||
{
|
||||
// Copy required files to the temp directory
|
||||
General.WriteLogLine("Copying required files for compiler...");
|
||||
CopyRequiredFiles();
|
||||
}
|
||||
}
|
||||
|
||||
// Disposer
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace CodeImp.DoomBuilder.Compilers
|
|||
#region ================== Constructor / Disposer
|
||||
|
||||
// Constructor
|
||||
public NodesCompiler(CompilerInfo info) : base(info)
|
||||
public NodesCompiler(CompilerInfo info) : base(info, true)
|
||||
{
|
||||
// Initialize
|
||||
|
||||
|
|
|
@ -454,13 +454,14 @@ namespace CodeImp.DoomBuilder.Config
|
|||
{
|
||||
// Copy the things filters from game configuration
|
||||
foreach(ThingsFilter f in gameconfig.ThingsFilters)
|
||||
{
|
||||
thingsfilters.Add(new ThingsFilter(f));
|
||||
}
|
||||
}
|
||||
|
||||
//mxd. Validate filters
|
||||
foreach(ThingsFilter f in thingsfilters) f.Validate();
|
||||
//mxd. Validate filters. Do it only for currently used ConfigInfo
|
||||
if(General.Map != null && General.Map.ConfigSettings == this)
|
||||
{
|
||||
foreach(ThingsFilter f in thingsfilters) f.Validate();
|
||||
}
|
||||
}
|
||||
|
||||
// Go for all available editing modes
|
||||
|
|
|
@ -410,6 +410,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
// Put some text in the navigator (but don't actually trigger selection event)
|
||||
navigator.Enabled = (navigator.Items.Count > 0);
|
||||
if(navigator.Items.Count > 0)
|
||||
{
|
||||
preventchanges = true;
|
||||
|
@ -421,32 +422,43 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
//mxd
|
||||
private void UpdateNavigatorDecorate(MemoryStream stream)
|
||||
{
|
||||
if (stream == null) return;
|
||||
|
||||
if(stream == null) return;
|
||||
navigator.Items.Clear();
|
||||
|
||||
DecorateParserSE parser = new DecorateParserSE();
|
||||
parser.Parse(stream, "DECORATE");
|
||||
navigator.Items.AddRange(parser.Actors.ToArray());
|
||||
if(parser.Parse(stream, "DECORATE"))
|
||||
{
|
||||
navigator.Items.AddRange(parser.Actors.ToArray());
|
||||
}
|
||||
|
||||
if(parser.HasError)
|
||||
{
|
||||
panel.ShowErrors(new List<CompilerError> { new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine) });
|
||||
}
|
||||
}
|
||||
|
||||
//mxd
|
||||
private void UpdateNavigatorModeldef(MemoryStream stream)
|
||||
{
|
||||
if (stream == null) return;
|
||||
|
||||
if(stream == null) return;
|
||||
navigator.Items.Clear();
|
||||
|
||||
ModeldefParserSE parser = new ModeldefParserSE();
|
||||
parser.Parse(stream, "MODELDEF");
|
||||
navigator.Items.AddRange(parser.Models.ToArray());
|
||||
if(parser.Parse(stream, "MODELDEF"))
|
||||
{
|
||||
navigator.Items.AddRange(parser.Models.ToArray());
|
||||
}
|
||||
|
||||
if(parser.HasError)
|
||||
{
|
||||
panel.ShowErrors(new List<CompilerError> { new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine) });
|
||||
}
|
||||
}
|
||||
|
||||
//mxd
|
||||
private void UpdateNavigatorAcs(MemoryStream stream)
|
||||
{
|
||||
if (stream == null) return;
|
||||
|
||||
if(stream == null) return;
|
||||
navigator.Items.Clear();
|
||||
|
||||
AcsParserSE parser = new AcsParserSE { AddArgumentsToScriptNames = true, IsMapScriptsLump = this is ScriptLumpDocumentTab };
|
||||
|
@ -456,17 +468,28 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
navigator.Items.AddRange(parser.NumberedScripts.ToArray());
|
||||
navigator.Items.AddRange(parser.Functions.ToArray());
|
||||
}
|
||||
|
||||
if(parser.HasError)
|
||||
{
|
||||
panel.ShowErrors(new List<CompilerError> { new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine) });
|
||||
}
|
||||
}
|
||||
|
||||
//mxd
|
||||
internal ScriptType VerifyScriptType()
|
||||
{
|
||||
ScriptTypeParserSE parser = new ScriptTypeParserSE();
|
||||
if (parser.Parse(new MemoryStream(editor.GetText()), config.Description))
|
||||
if(parser.Parse(new MemoryStream(editor.GetText()), config.Description))
|
||||
{
|
||||
if (parser.ScriptType != ScriptType.UNKNOWN && config.ScriptType != parser.ScriptType)
|
||||
if(parser.ScriptType != ScriptType.UNKNOWN && config.ScriptType != parser.ScriptType)
|
||||
return parser.ScriptType;
|
||||
}
|
||||
|
||||
if(parser.HasError)
|
||||
{
|
||||
panel.ShowErrors(new List<CompilerError> { new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine) });
|
||||
}
|
||||
|
||||
return ScriptType.UNKNOWN;
|
||||
}
|
||||
|
||||
|
|
|
@ -250,8 +250,6 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
// This sets up the script editor with a script configuration
|
||||
public void SetupStyles(ScriptConfiguration config)
|
||||
{
|
||||
Stream lexersdata;
|
||||
StreamReader lexersreader;
|
||||
Configuration lexercfg = new Configuration();
|
||||
|
||||
// Make collections
|
||||
|
@ -259,7 +257,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
SortedList<string, string> autocompletelist = new SortedList<string, string>(StringComparer.Ordinal);
|
||||
|
||||
// Keep script configuration
|
||||
if(scriptconfig != config) scriptconfig = config;
|
||||
scriptconfig = config;
|
||||
|
||||
// Find a resource named Lexers.cfg
|
||||
string[] resnames = General.ThisAssembly.GetManifestResourceNames();
|
||||
|
@ -269,8 +267,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
if(rn.EndsWith(LEXERS_RESOURCE, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
// Get a stream from the resource
|
||||
lexersdata = General.ThisAssembly.GetManifestResourceStream(rn);
|
||||
lexersreader = new StreamReader(lexersdata, Encoding.ASCII);
|
||||
Stream lexersdata = General.ThisAssembly.GetManifestResourceStream(rn);
|
||||
StreamReader lexersreader = new StreamReader(lexersdata, Encoding.ASCII);
|
||||
|
||||
// Load configuration from stream
|
||||
lexercfg.InputConfiguration(lexersreader.ReadToEnd());
|
||||
|
@ -426,8 +424,10 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
functionbar.Visible = (scriptconfig.FunctionRegEx.Length > 0);
|
||||
|
||||
// Rearrange the layout
|
||||
bool ischanged = changed; //mxd. Don't want the "changed" status to change when changing text styles
|
||||
scriptedit.ClearDocumentStyle();
|
||||
scriptedit.SetText(scriptedit.GetText(scriptedit.TextSize));
|
||||
changed = ischanged; //mxd
|
||||
this.PerformLayout();
|
||||
}
|
||||
|
||||
|
|
|
@ -175,23 +175,24 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
AcsParserSE parser = new AcsParserSE { OnInclude = (se, path) => se.Parse(General.Map.Data.LoadFile(path), path, true, true) };
|
||||
using(FileStream stream = File.OpenRead(filepathname))
|
||||
{
|
||||
if(!parser.Parse(stream, inputfile, scriptconfig.Compiler.Files, true, false))
|
||||
if(!parser.Parse(stream, filepathname, scriptconfig.Compiler.Files, true, false))
|
||||
{
|
||||
// Check for errors
|
||||
if(parser.HasError)
|
||||
{
|
||||
errors.Add(new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine));
|
||||
panel.ShowErrors(errors);
|
||||
compiler.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
compiler.Dispose();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Only works for libraries
|
||||
//mxd. Only works for libraries
|
||||
if(!parser.IsLibrary)
|
||||
{
|
||||
errors.Add(new CompilerError("External ACS files can only be compiled as libraries!", inputfile));
|
||||
errors.Add(new CompilerError("External ACS files can only be compiled as libraries!", filepathname));
|
||||
panel.ShowErrors(errors);
|
||||
compiler.Dispose();
|
||||
return;
|
||||
|
@ -349,6 +350,10 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
string ext = (config.Extensions.Length > 0 ? "." + config.Extensions[0] : "");
|
||||
SetTitle("Untitled" + ext);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateTitle(); //mxd
|
||||
}
|
||||
|
||||
//mxd
|
||||
base.ChangeScriptConfig(newconfig);
|
||||
|
|
|
@ -1404,9 +1404,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
char[] catsplitter = new[] {Path.AltDirectorySeparatorChar}; //mxd
|
||||
|
||||
// Create new parser
|
||||
decorate = new DecorateParser();
|
||||
decorate.OnInclude = LoadDecorateFromLocation;
|
||||
|
||||
decorate = new DecorateParser { OnInclude = LoadDecorateFromLocation };
|
||||
|
||||
// Only load these when the game configuration supports the use of decorate
|
||||
if(!string.IsNullOrEmpty(General.Map.Config.DecorateGames))
|
||||
{
|
||||
|
@ -1423,12 +1422,11 @@ namespace CodeImp.DoomBuilder.Data
|
|||
group.Value.Seek(0, SeekOrigin.Begin);
|
||||
decorate.Parse(group.Value, group.Key, true);
|
||||
|
||||
// Check for errors
|
||||
//mxd. DECORATE lumps are interdepandable. Can't carry on...
|
||||
if(decorate.HasError)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "DECORATE error in '" + decorate.ErrorSource
|
||||
+ (decorate.ErrorLine != CompilerError.NO_LINE_NUMBER ? "', line " + decorate.ErrorLine : "'") + ". " + decorate.ErrorDescription + ".");
|
||||
break;
|
||||
decorate.LogError(); //mxd
|
||||
return counter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1823,6 +1821,13 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Modeldefs are independable, so parsing fail in one file should not affect the others
|
||||
if(parser.HasError)
|
||||
{
|
||||
parser.LogError();
|
||||
parser.ClearError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1895,19 +1900,29 @@ namespace CodeImp.DoomBuilder.Data
|
|||
currentreader = dr;
|
||||
|
||||
KeyValuePair<string, Stream> group = dr.GetVoxeldefData();
|
||||
if(group.Value != null && parser.Parse(group.Value, group.Key))
|
||||
if(group.Value != null)
|
||||
{
|
||||
foreach(KeyValuePair<string, ModelData> entry in parser.Entries)
|
||||
if(parser.Parse(group.Value, group.Key))
|
||||
{
|
||||
foreach(KeyValuePair<string, List<int>> sc in sprites)
|
||||
foreach(KeyValuePair<string, ModelData> entry in parser.Entries)
|
||||
{
|
||||
if(sc.Key.Contains(entry.Key))
|
||||
foreach(KeyValuePair<string, List<int>> sc in sprites)
|
||||
{
|
||||
foreach(int id in sc.Value) modeldefentries[id] = entry.Value;
|
||||
processed.Add(entry.Key, false);
|
||||
if(sc.Key.Contains(entry.Key))
|
||||
{
|
||||
foreach(int id in sc.Value) modeldefentries[id] = entry.Value;
|
||||
processed.Add(entry.Key, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Report errors?
|
||||
if(parser.HasError)
|
||||
{
|
||||
parser.LogError();
|
||||
parser.ClearError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1939,7 +1954,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
|
||||
GldefsParser parser = new GldefsParser { OnInclude = ParseFromLocation };
|
||||
|
||||
//load gldefs from resources
|
||||
// Load gldefs from resources
|
||||
foreach(DataReader dr in containers)
|
||||
{
|
||||
currentreader = dr;
|
||||
|
@ -1947,7 +1962,16 @@ namespace CodeImp.DoomBuilder.Data
|
|||
Dictionary<string, Stream> streams = dr.GetGldefsData(General.Map.Config.GameType);
|
||||
|
||||
foreach(KeyValuePair<string, Stream> group in streams)
|
||||
{
|
||||
parser.Parse(group.Value, group.Key);
|
||||
|
||||
// Gldefs can be interdependable. Can't carry on
|
||||
if(parser.HasError)
|
||||
{
|
||||
parser.LogError();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//create gldefsEntries dictionary
|
||||
|
@ -1957,12 +1981,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
if(actorsByClass.ContainsKey(e.Key) && parser.LightsByName.ContainsKey(e.Value))
|
||||
{
|
||||
foreach(int i in actorsByClass[e.Key])
|
||||
{
|
||||
if(gldefsentries.ContainsKey(i))
|
||||
gldefsentries[i] = parser.LightsByName[e.Value];
|
||||
else
|
||||
gldefsentries.Add(i, parser.LightsByName[e.Value]);
|
||||
}
|
||||
gldefsentries[i] = parser.LightsByName[e.Value];
|
||||
}
|
||||
else if(!decorate.AllActorsByClass.ContainsKey(e.Key))
|
||||
{
|
||||
|
@ -1978,7 +1997,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
private void LoadMapInfo(out Dictionary<int, string> spawnnums, out Dictionary<int, string> doomednums)
|
||||
{
|
||||
MapinfoParser parser = new MapinfoParser { OnInclude = ParseFromLocation };
|
||||
|
||||
|
||||
foreach(DataReader dr in containers)
|
||||
{
|
||||
currentreader = dr;
|
||||
|
@ -1987,7 +2006,20 @@ namespace CodeImp.DoomBuilder.Data
|
|||
foreach(KeyValuePair<string, Stream> group in streams)
|
||||
{
|
||||
// Parse the data
|
||||
parser.Parse(group.Value, Path.Combine(currentreader.Location.location, group.Key), General.Map.Options.LevelName);
|
||||
parser.Parse(group.Value, Path.Combine(currentreader.Location.location, group.Key), General.Map.Options.LevelName);
|
||||
|
||||
//MAPINFO lumps are interdependable. Can't carry on...
|
||||
if(parser.HasError)
|
||||
{
|
||||
parser.LogError();
|
||||
|
||||
// No nulls allowed!
|
||||
spawnnums = new Dictionary<int, string>();
|
||||
doomednums = new Dictionary<int, string>();
|
||||
mapinfo = new MapInfo();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2024,6 +2056,13 @@ namespace CodeImp.DoomBuilder.Data
|
|||
{
|
||||
// Parse the data
|
||||
parser.Parse(group.Value, group.Key);
|
||||
|
||||
// Report errors?
|
||||
if(parser.HasError)
|
||||
{
|
||||
parser.LogError();
|
||||
parser.ClearError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2049,6 +2088,13 @@ namespace CodeImp.DoomBuilder.Data
|
|||
foreach(Stream s in streams)
|
||||
{
|
||||
if(s != null) parser.Parse(s, "SNDSEQ");
|
||||
|
||||
// Report errors?
|
||||
if(parser.HasError)
|
||||
{
|
||||
parser.LogError();
|
||||
parser.ClearError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
IReader reader = archive.ExtractAllEntries();
|
||||
while(reader.MoveToNextEntry())
|
||||
{
|
||||
if(reader.Entry.IsDirectory) continue;
|
||||
if(reader.Entry.IsDirectory || !CheckInvalidPathChars(reader.Entry.Key)) continue;
|
||||
|
||||
MemoryStream s = new MemoryStream();
|
||||
reader.WriteEntryTo(s);
|
||||
|
@ -83,8 +83,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
{
|
||||
foreach(IArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
if(entry.IsDirectory) continue;
|
||||
fileentries.Add(new DirectoryFileEntry(entry.Key));
|
||||
if(!entry.IsDirectory && CheckInvalidPathChars(entry.Key))
|
||||
fileentries.Add(new DirectoryFileEntry(entry.Key));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -415,18 +415,18 @@ namespace CodeImp.DoomBuilder.Data
|
|||
string fn = filename.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); //mxd
|
||||
|
||||
//mxd. This works waaaaaay faster with 7z archive
|
||||
if (archivetype == ArchiveType.SevenZip)
|
||||
if(archivetype == ArchiveType.SevenZip)
|
||||
{
|
||||
fn = fn.ToLowerInvariant();
|
||||
if (sevenzipentries.ContainsKey(fn)) filedata = new MemoryStream(sevenzipentries[fn]);
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (this)
|
||||
lock(this)
|
||||
{
|
||||
UpdateArchive(true);
|
||||
|
||||
foreach (var entry in archive.Entries)
|
||||
foreach(var entry in archive.Entries)
|
||||
{
|
||||
if(entry.IsDirectory) continue;
|
||||
|
||||
|
@ -444,7 +444,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
// Nothing found?
|
||||
if (filedata == null)
|
||||
if(filedata == null)
|
||||
{
|
||||
//mxd
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Cannot find the file '" + filename + "' in archive '" + location.location + "'.");
|
||||
|
@ -466,7 +466,31 @@ namespace CodeImp.DoomBuilder.Data
|
|||
filedata.Dispose();
|
||||
return tempfile;
|
||||
}
|
||||
|
||||
|
||||
//mxd. This replicates System.IO.Path.CheckInvalidPathChars() internal function
|
||||
private bool CheckInvalidPathChars(string path)
|
||||
{
|
||||
foreach(char c in path)
|
||||
{
|
||||
int num = c;
|
||||
switch(num)
|
||||
{
|
||||
case 34:
|
||||
case 60:
|
||||
case 62:
|
||||
case 124:
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in \"" + location.location + "\": unsupported character \"" + c + "\" in path \"" + path + "\". File loading was skipped.");
|
||||
return false;
|
||||
|
||||
default:
|
||||
if(num >= 32) continue;
|
||||
else goto case 34;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -408,21 +408,14 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Parse the data
|
||||
TexturesParser parser = new TexturesParser();
|
||||
parser.Parse(stream, filename);
|
||||
if(parser.HasError) parser.LogError(); //mxd
|
||||
|
||||
// Make the textures
|
||||
foreach(TextureStructure t in parser.Textures)
|
||||
{
|
||||
if(t.Name.Length > 0)
|
||||
{
|
||||
// Add the texture
|
||||
ImageData img = t.MakeImage();
|
||||
images.Add(img);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't load image without name
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Can't load an unnamed texture from \"" + filename + "\". Please consider giving names to your resources.");
|
||||
}
|
||||
// Add the texture
|
||||
ImageData img = t.MakeImage();
|
||||
images.Add(img);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -655,21 +648,14 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Parse the data
|
||||
TexturesParser parser = new TexturesParser();
|
||||
parser.Parse(stream, filename);
|
||||
if(parser.HasError) parser.LogError(); //mxd
|
||||
|
||||
// Make the textures
|
||||
foreach(TextureStructure t in parser.Flats)
|
||||
{
|
||||
if(t.Name.Length > 0)
|
||||
{
|
||||
// Add the texture
|
||||
ImageData img = t.MakeImage();
|
||||
images.Add(img);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't load image without name
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Can't load an unnamed flat from \"" + filename + "\". Please consider giving names to your resources.");
|
||||
}
|
||||
// Add the texture
|
||||
ImageData img = t.MakeImage();
|
||||
images.Add(img);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -725,21 +711,14 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Parse the data
|
||||
TexturesParser parser = new TexturesParser();
|
||||
parser.Parse(stream, filename);
|
||||
if(parser.HasError) parser.LogError(); //mxd
|
||||
|
||||
// Make the textures
|
||||
foreach(TextureStructure t in parser.Sprites)
|
||||
{
|
||||
if(t.Name.Length > 0)
|
||||
{
|
||||
// Add the sprite
|
||||
ImageData img = t.MakeImage();
|
||||
images.Add(img);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't load image without name
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Can't load an unnamed sprite from \"" + filename + "\". Please consider giving names to your resources.");
|
||||
}
|
||||
// Add the sprite
|
||||
ImageData img = t.MakeImage();
|
||||
images.Add(img);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -236,36 +236,6 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
for(int i = 0; i < Thing.NUM_ARGS; i++) thingargs[i] = -1;
|
||||
}
|
||||
if(!General.Map.FormatInterface.HasCustomFields) customfields.Clear();
|
||||
|
||||
//mxd. We don't want to keep unknown flags (like flags from different map format)
|
||||
if(General.Map.Config != null && General.Map.Config.ThingFlags != null)
|
||||
{
|
||||
List<String> unknownfields = new List<string>();
|
||||
foreach(String s in forbiddenfields)
|
||||
{
|
||||
if(!General.Map.Config.ThingFlags.ContainsKey(s))
|
||||
unknownfields.Add(s);
|
||||
}
|
||||
|
||||
if(unknownfields.Count > 0)
|
||||
{
|
||||
foreach(String s in unknownfields)
|
||||
forbiddenfields.Remove(s);
|
||||
}
|
||||
|
||||
unknownfields = new List<string>();
|
||||
foreach(String s in requiredfields)
|
||||
{
|
||||
if(!General.Map.Config.ThingFlags.ContainsKey(s))
|
||||
unknownfields.Add(s);
|
||||
}
|
||||
|
||||
if(unknownfields.Count > 0)
|
||||
{
|
||||
foreach(String s in unknownfields)
|
||||
requiredfields.Remove(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,6 +244,32 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
{
|
||||
AdjustForMapFormat();
|
||||
|
||||
//mxd. We don't want to keep unknown flags (like flags from different map format)
|
||||
if(General.Map.Config != null && General.Map.Config.ThingFlags != null)
|
||||
{
|
||||
List<String> unknownfields = new List<string>();
|
||||
foreach(String s in forbiddenfields)
|
||||
{
|
||||
if(!General.Map.Config.ThingFlags.ContainsKey(s)) unknownfields.Add(s);
|
||||
}
|
||||
|
||||
if(unknownfields.Count > 0)
|
||||
{
|
||||
foreach(String s in unknownfields) forbiddenfields.Remove(s);
|
||||
}
|
||||
|
||||
unknownfields.Clear();
|
||||
foreach(String s in requiredfields)
|
||||
{
|
||||
if(!General.Map.Config.ThingFlags.ContainsKey(s)) unknownfields.Add(s);
|
||||
}
|
||||
|
||||
if(unknownfields.Count > 0)
|
||||
{
|
||||
foreach(String s in unknownfields) requiredfields.Remove(s);
|
||||
}
|
||||
}
|
||||
|
||||
//Integrity check
|
||||
if(!IsValid())
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Things filter '" + name + "' has invalid properties. Configure the thing filter to fix this!");
|
||||
|
@ -298,8 +294,7 @@ namespace CodeImp.DoomBuilder.Editing
|
|||
/// </summary>
|
||||
public bool IsThingVisible(Thing t)
|
||||
{
|
||||
if (t.IsDisposed) return false; //mxd
|
||||
return thingsvisiblestate[t];
|
||||
return (!t.IsDisposed && thingsvisiblestate[t]);
|
||||
}
|
||||
|
||||
// This writes the filter to configuration
|
||||
|
|
|
@ -12,6 +12,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
{
|
||||
internal sealed class ModelData
|
||||
{
|
||||
#region ================== Constants
|
||||
|
||||
public static readonly string[] SUPPORTED_TEXTURE_EXTENSIONS = { ".jpg", ".tga", ".png", ".dds", ".pcx" };
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Variables
|
||||
|
||||
private ModelLoadState loadstate;
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
namespace CodeImp.DoomBuilder.GZBuilder.Data {
|
||||
public struct TextureData {
|
||||
public const string INVALID_TEXTURE = "**invalid_texture**";
|
||||
public static string[] SUPPORTED_TEXTURE_EXTENSIONS = { ".jpg", ".tga", ".png", ".dds", ".pcx" };
|
||||
}
|
||||
}
|
|
@ -63,8 +63,6 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
|
||||
base.Parse(stream, sourcefilename);
|
||||
|
||||
// Already parsed this?
|
||||
if(parsedlumps.Contains(sourcefilename)) return false;
|
||||
parsedlumps.Add(sourcefilename);
|
||||
if(isinclude && !includes.Contains(sourcefilename)) includes.Add(sourcefilename);
|
||||
includestoskip = configincludes;
|
||||
|
@ -180,46 +178,68 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
case "#library":
|
||||
if(IsMapScriptsLump)
|
||||
{
|
||||
ReportError("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": SCRIPTS lump can not be compiled as library!");
|
||||
ReportError("SCRIPTS lump can not be compiled as a library");
|
||||
return false;
|
||||
}
|
||||
|
||||
SkipWhitespace(true);
|
||||
libraryname = ReadToken();
|
||||
libraryname = ReadToken(false); // Don't skip newline
|
||||
|
||||
if(string.IsNullOrEmpty(libraryname) || !libraryname.StartsWith("\"") || !libraryname.EndsWith("\""))
|
||||
if(!libraryname.StartsWith("\"") || !libraryname.EndsWith("\""))
|
||||
{
|
||||
ReportError("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": invalid #library directive!");
|
||||
ReportError("#library name should be quoted");
|
||||
return false;
|
||||
}
|
||||
|
||||
libraryname = StripTokenQuotes(libraryname);
|
||||
|
||||
if(string.IsNullOrEmpty(libraryname))
|
||||
{
|
||||
ReportError("Expected library name");
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if(processincludes && (token == "#include" || token == "#import"))
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
string includelump = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
||||
string includelump = ReadToken(false); // Don't skip newline
|
||||
|
||||
if(!string.IsNullOrEmpty(includelump))
|
||||
if(!includelump.StartsWith("\"") || !includelump.EndsWith("\""))
|
||||
{
|
||||
string includename = Path.GetFileName(includelump);
|
||||
if(includestoskip.Contains(includename) || includes.Contains(includename)) continue;
|
||||
|
||||
// Callback to parse this file
|
||||
if(OnInclude != null) OnInclude(this, includelump.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar));
|
||||
|
||||
// Set our buffers back to continue parsing
|
||||
datastream = localstream;
|
||||
datareader = localreader;
|
||||
sourcename = localsourcename;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportError("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": got #include directive without include path!");
|
||||
ReportError(token + " filename should be quoted");
|
||||
return false;
|
||||
}
|
||||
|
||||
includelump = StripTokenQuotes(includelump).ToLowerInvariant();
|
||||
|
||||
if(string.IsNullOrEmpty(includelump))
|
||||
{
|
||||
ReportError("Expected file name to " + token);
|
||||
return false;
|
||||
}
|
||||
|
||||
string includename = Path.GetFileName(includelump);
|
||||
|
||||
// Compiler files?
|
||||
if(includestoskip.Contains(includename)) continue;
|
||||
|
||||
// Already parsed this?
|
||||
if(includes.Contains(includename))
|
||||
{
|
||||
ReportError("already parsed '" + includename + "'. Check your #include directives");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Callback to parse this file
|
||||
if(OnInclude != null) OnInclude(this, includelump.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar));
|
||||
|
||||
// Set our buffers back to continue parsing
|
||||
datastream = localstream;
|
||||
datareader = localreader;
|
||||
sourcename = localsourcename;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -276,5 +296,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
|
||||
return "(void)";
|
||||
}
|
||||
|
||||
protected override string GetLanguageType()
|
||||
{
|
||||
return "ACS";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ using CodeImp.DoomBuilder.ZDoom;
|
|||
using CodeImp.DoomBuilder.GZBuilder.Data;
|
||||
|
||||
//mxd. Decorate parser used to create ScriptItems for use in script editor's navigator
|
||||
//Should be able to parse actor definitions even from invalid DECORATE and should never fail parsing
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
||||
{
|
||||
internal sealed class DecorateParserSE : ZDTextParser
|
||||
|
@ -21,38 +22,35 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
base.Parse(stream, sourcefilename);
|
||||
|
||||
// Continue until at the end of the stream
|
||||
while (SkipWhitespace(true))
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
string token = ReadToken();
|
||||
if(string.IsNullOrEmpty(token) || token.ToUpperInvariant() != "ACTOR") continue;
|
||||
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
SkipWhitespace(true);
|
||||
int startpos = (int)stream.Position;
|
||||
|
||||
List<string> definition = new List<string>();
|
||||
|
||||
do
|
||||
{
|
||||
token = token.ToLowerInvariant();
|
||||
token = ReadToken(false); // Don't skip newline
|
||||
if(string.IsNullOrEmpty(token) || token == "{" || token == "}") break;
|
||||
definition.Add(token);
|
||||
} while(SkipWhitespace(false)); // Don't skip newline
|
||||
|
||||
if (token == "actor")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
int startPos = (int)stream.Position;
|
||||
|
||||
List<string> definition = new List<string>();
|
||||
|
||||
do
|
||||
{
|
||||
token = ReadToken();
|
||||
if(string.IsNullOrEmpty(token) || token == "{") break;
|
||||
definition.Add(token);
|
||||
} while(SkipWhitespace(true));
|
||||
|
||||
string name = "";
|
||||
foreach (string s in definition) name += s + " ";
|
||||
actors.Add(new ScriptItem(name.TrimEnd(), startPos, false));
|
||||
}
|
||||
}
|
||||
string name = string.Join(" ", definition.ToArray());
|
||||
if(!string.IsNullOrEmpty(name)) actors.Add(new ScriptItem(name, startpos, false));
|
||||
}
|
||||
|
||||
//sort nodes
|
||||
// Sort nodes
|
||||
actors.Sort(ScriptItem.SortByName);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override string GetLanguageType()
|
||||
{
|
||||
return "DECORATE";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
{
|
||||
internal sealed class GldefsParser : ZDTextParser
|
||||
{
|
||||
#region ================== Structs
|
||||
#region ================== Constants
|
||||
|
||||
private const int DEFAULT_GLOW_HEIGHT = 64;
|
||||
|
||||
|
@ -82,12 +82,6 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
public override bool Parse(Stream stream, string sourcefilename)
|
||||
{
|
||||
base.Parse(stream, sourcefilename);
|
||||
|
||||
if (parsedlumps.IndexOf(sourcefilename) != -1)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "already parsed '" + sourcefilename + "'. Check your #include directives!");
|
||||
return false;
|
||||
}
|
||||
parsedlumps.Add(sourcefilename);
|
||||
|
||||
// Keep local data
|
||||
|
@ -96,18 +90,17 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
BinaryReader localreader = datareader;
|
||||
|
||||
// Continue until at the end of the stream
|
||||
while (SkipWhitespace(true))
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
string token = ReadToken();
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
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
|
||||
if(token == GldefsLightType.POINT || token == GldefsLightType.PULSE || token == GldefsLightType.FLICKER
|
||||
|| token == GldefsLightType.FLICKER2 || token == GldefsLightType.SECTOR)
|
||||
{
|
||||
bool gotErrors = false;
|
||||
string lightType = token;
|
||||
|
||||
DynamicLightData light = new DynamicLightData();
|
||||
|
@ -117,41 +110,39 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
SkipWhitespace(true);
|
||||
string lightName = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
||||
|
||||
if (!string.IsNullOrEmpty(lightName))
|
||||
if(!string.IsNullOrEmpty(lightName))
|
||||
{
|
||||
//now find opening brace
|
||||
if(!NextTokenIs("{")) continue;
|
||||
|
||||
//read gldefs light structure
|
||||
while (SkipWhitespace(true))
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
token = ReadToken();
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
if(!string.IsNullOrEmpty(token))
|
||||
{
|
||||
token = token.ToLowerInvariant();
|
||||
//color
|
||||
if (token == "color")
|
||||
if(token == "color")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Red))
|
||||
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Red))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Red Color value, but got '" + token + "'.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("expected Red color value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Green))
|
||||
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Green))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Green Color value, but got '" + token + "'.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("expected Green color value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
SkipWhitespace(true);
|
||||
|
@ -160,128 +151,118 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Blue))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Blue Color value, but got '" + token + "'.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("expected Blue color value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
//size
|
||||
}
|
||||
else if (token == "size")
|
||||
else if(token == "size")
|
||||
{
|
||||
if (lightType != GldefsLightType.SECTOR)
|
||||
if(lightType != GldefsLightType.SECTOR)
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.PrimaryRadius))
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.PrimaryRadius))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Size value, but got '" + token + "'.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("expected Size value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
light.PrimaryRadius *= 2;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType + ".");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("'" + token + "' is not valid property for " + lightType + ".");
|
||||
return false;
|
||||
}
|
||||
//offset
|
||||
}
|
||||
else if (token == "offset")
|
||||
else if(token == "offset")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!ReadSignedFloat(token, ref light.Offset.X))
|
||||
if(!ReadSignedFloat(token, ref light.Offset.X))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset X value, but got '" + token + "'.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("expected Offset X value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!ReadSignedFloat(token, ref light.Offset.Z))
|
||||
if(!ReadSignedFloat(token, ref light.Offset.Z))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset Y value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("expected Offset Y value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!ReadSignedFloat(token, ref light.Offset.Y))
|
||||
if(!ReadSignedFloat(token, ref light.Offset.Y))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset Z value, but got '" + token + "'.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("expected Offset Z value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
//subtractive
|
||||
}
|
||||
else if (token == "subtractive")
|
||||
else if(token == "subtractive")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
int i;
|
||||
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i))
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Subtractive value, but got '" + token + "'.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("expected Subtractive value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
light.Subtractive = i == 1;
|
||||
//dontlightself
|
||||
}
|
||||
else if (token == "dontlightself")
|
||||
else if(token == "dontlightself")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
int i;
|
||||
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i))
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Dontlightself value, but got '" + token + "'.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("expected Dontlightself value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
light.DontLightSelf = (i == 1);
|
||||
//interval
|
||||
}
|
||||
else if (token == "interval")
|
||||
else if(token == "interval")
|
||||
{
|
||||
if (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER2)
|
||||
if(lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER2)
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
float interval;
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out interval))
|
||||
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out interval))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Interval value, but got '" + token + "'.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("expected Interval value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(interval == 0)
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Warning in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": Interval value should be greater than zero.");
|
||||
if(interval == 0) LogWarning("Interval value should be greater than zero");
|
||||
|
||||
//I wrote logic for dynamic lights animation first, so here I modify gldefs settings to fit in existing logic
|
||||
if (lightType == GldefsLightType.PULSE)
|
||||
if(lightType == GldefsLightType.PULSE)
|
||||
{
|
||||
light.Interval = (int)(interval * 35); //measured in tics (35 per second) in PointLightPulse, measured in seconds in gldefs' PulseLight
|
||||
}
|
||||
|
@ -292,50 +273,46 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType + ".");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("'" + token + "' is not valid property for " + lightType);
|
||||
return false;
|
||||
}
|
||||
//secondarysize
|
||||
}
|
||||
else if (token == "secondarysize")
|
||||
else if(token == "secondarysize")
|
||||
{
|
||||
if (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER || lightType == GldefsLightType.FLICKER2)
|
||||
if(lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER || lightType == GldefsLightType.FLICKER2)
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.SecondaryRadius))
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.SecondaryRadius))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected SecondarySize value, but got '" + token + "'.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("expected SecondarySize value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
light.SecondaryRadius *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType + ".");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("'" + token + "' is not valid property for " + lightType);
|
||||
return false;
|
||||
}
|
||||
//chance
|
||||
}
|
||||
else if (token == "chance")
|
||||
else if(token == "chance")
|
||||
{
|
||||
if (lightType == GldefsLightType.FLICKER)
|
||||
if(lightType == GldefsLightType.FLICKER)
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
float chance;
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out chance))
|
||||
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out chance))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Chance value, but got '" + token + "'.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("expected Chance value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
//transforming from 0.0 .. 1.0 to 0 .. 359 to fit in existing logic
|
||||
|
@ -343,33 +320,30 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType + ".");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("'" + token + "' is not valid property for " + lightType);
|
||||
return false;
|
||||
}
|
||||
//scale
|
||||
}
|
||||
else if (token == "scale")
|
||||
else if(token == "scale")
|
||||
{
|
||||
if (lightType == GldefsLightType.SECTOR)
|
||||
if(lightType == GldefsLightType.SECTOR)
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
float scale;
|
||||
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale))
|
||||
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Scale value, but got '" + token + "'.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("expected Scale value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (scale > 1.0f)
|
||||
if(scale > 1.0f)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": scale must be in 0.0 - 1.0 range, but is " + scale + ".");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("scale must be in 0.0 - 1.0 range, but is " + scale);
|
||||
return false;
|
||||
}
|
||||
|
||||
//sector light doesn't have animation, so we will store it's size in Interval
|
||||
|
@ -378,64 +352,59 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType + ".");
|
||||
gotErrors = true;
|
||||
break;
|
||||
ReportError("'" + token + "' is not valid property for " + lightType);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//end of structure
|
||||
else if (token == "}")
|
||||
else if(token == "}")
|
||||
{
|
||||
if (!gotErrors)
|
||||
bool skip = false;
|
||||
|
||||
//general checks
|
||||
if(light.Color.Red == 0.0f && light.Color.Green == 0.0f && light.Color.Blue == 0.0f)
|
||||
{
|
||||
//general checks
|
||||
if (light.Color.Red == 0.0f && light.Color.Green == 0.0f && light.Color.Blue == 0.0f)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "'" + sourcefilename + "', line " + GetCurrentLineNumber() + ": light Color is " + light.Color.Red + "," + light.Color.Green + "," + light.Color.Blue + ". It won't be shown in GZDoom!");
|
||||
gotErrors = true;
|
||||
}
|
||||
LogWarning("'" + lightName + "' light Color is " + light.Color.Red + "," + light.Color.Green + "," + light.Color.Blue + ". It won't be shown in GZDoom");
|
||||
skip = true;
|
||||
}
|
||||
|
||||
//light-type specific checks
|
||||
if (light.Type == DynamicLightType.NORMAL && light.PrimaryRadius == 0)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "'" + sourcefilename + "', line " + GetCurrentLineNumber() + ": light Size is 0. It won't be shown in GZDoom!");
|
||||
gotErrors = true;
|
||||
}
|
||||
//light-type specific checks
|
||||
if(light.Type == DynamicLightType.NORMAL && light.PrimaryRadius == 0)
|
||||
{
|
||||
LogWarning("'" + lightName + "' light Size is 0. It won't be shown in GZDoom");
|
||||
skip = true;
|
||||
}
|
||||
|
||||
if (light.Type == DynamicLightType.FLICKER || light.Type == DynamicLightType.PULSE || light.Type == DynamicLightType.RANDOM)
|
||||
if(light.Type == DynamicLightType.FLICKER || light.Type == DynamicLightType.PULSE || light.Type == DynamicLightType.RANDOM)
|
||||
{
|
||||
if(light.PrimaryRadius == 0 && light.SecondaryRadius == 0)
|
||||
{
|
||||
if (light.PrimaryRadius == 0 && light.SecondaryRadius == 0)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "'" + sourcefilename + "', line " + GetCurrentLineNumber() + ": 'Size' and 'SecondarySize' are 0. This light won't be shown in GZDoom!");
|
||||
gotErrors = true;
|
||||
}
|
||||
}
|
||||
|
||||
//offset it slightly to avoid shading glitches
|
||||
if (light.Offset.Z == 0.0f) light.Offset.Z = 0.1f;
|
||||
|
||||
if (!gotErrors)
|
||||
{
|
||||
if (lightsByName.ContainsKey(lightName))
|
||||
lightsByName[lightName] = light;
|
||||
else
|
||||
lightsByName.Add(lightName, light);
|
||||
LogWarning("'" + lightName + "' light Size and SecondarySize are 0. This light won't be shown in GZDoom");
|
||||
skip = true;
|
||||
}
|
||||
}
|
||||
break; //break out of this parsing loop
|
||||
|
||||
//offset it slightly to avoid shading glitches
|
||||
if(light.Offset.Z == 0.0f) light.Offset.Z = 0.1f;
|
||||
|
||||
// Add to the collection?
|
||||
if(!skip) lightsByName[lightName] = light;
|
||||
|
||||
//break out of this parsing loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (token == "object")
|
||||
else if(token == "object")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
//read object class
|
||||
string objectClass = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
||||
|
||||
if (!string.IsNullOrEmpty(objectClass))
|
||||
if(!string.IsNullOrEmpty(objectClass))
|
||||
{
|
||||
//now find opening brace
|
||||
if(!NextTokenIs("{")) continue;
|
||||
|
@ -445,10 +414,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
bool foundFrame = false;
|
||||
|
||||
//read frames structure
|
||||
while (SkipWhitespace(true))
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
token = ReadToken();
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
if(!string.IsNullOrEmpty(token))
|
||||
{
|
||||
token = StripTokenQuotes(token).ToLowerInvariant();
|
||||
if(!foundLight && !foundFrame && token == "frame")
|
||||
|
@ -464,29 +433,26 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
SkipWhitespace(true);
|
||||
token = ReadToken().ToLowerInvariant(); //should be light name
|
||||
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
if(!string.IsNullOrEmpty(token))
|
||||
{
|
||||
if (lightsByName.ContainsKey(token))
|
||||
if(lightsByName.ContainsKey(token))
|
||||
{
|
||||
if (objects.ContainsKey(objectClass))
|
||||
objects[objectClass] = token;
|
||||
else
|
||||
objects.Add(objectClass, token);
|
||||
objects[objectClass] = token;
|
||||
foundLight = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Light declaration not found for light '" + token + "' ('" + sourcefilename + "', line " + GetCurrentLineNumber()+").");
|
||||
LogWarning("Light declaration not found for light '" + token + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (token == "{") //continue in this loop until object structure ends
|
||||
else if(token == "{") //continue in this loop until object structure ends
|
||||
{
|
||||
bracesCount++;
|
||||
}
|
||||
else if (token == "}")
|
||||
else if(token == "}")
|
||||
{
|
||||
if (--bracesCount < 1) break; //This was Cave Johnson. And we are done here.
|
||||
if(--bracesCount < 1) break; //This was Cave Johnson. And we are done here.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -549,12 +515,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
int color;
|
||||
int glowheight = DEFAULT_GLOW_HEIGHT;
|
||||
bool subtractivetexture = (token == "subtexture");
|
||||
string texturename = StripTokenQuotes(ReadToken());
|
||||
string texturename = StripTokenQuotes(ReadToken(false));
|
||||
|
||||
if(string.IsNullOrEmpty(texturename))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected a texture name.");
|
||||
break;
|
||||
ReportError("expected " + token + " name");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now we should find a comma
|
||||
|
@ -574,8 +540,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected glow color value, but got '" + token + "'.");
|
||||
break;
|
||||
ReportError("expected glow color value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -632,8 +598,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!fullblack && !fullbright)
|
||||
{
|
||||
string expectedflags = (subtractivetexture ? "'fullbright'" : "'fullbright' or 'fullblack'");
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected " + expectedflags + " flag, but got '" + token + "'.");
|
||||
break;
|
||||
ReportError("expected " + expectedflags + " flag, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add glow data
|
||||
|
@ -655,25 +621,43 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(string.IsNullOrEmpty(token) || token == "}") break;
|
||||
}
|
||||
}
|
||||
else if (token == "#include")
|
||||
else if(token == "#include")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
string includeLump = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
||||
if (!string.IsNullOrEmpty(includeLump))
|
||||
{
|
||||
// Callback to parse this file
|
||||
if (OnInclude != null)
|
||||
OnInclude(this, includeLump.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar));
|
||||
string includelump = ReadToken(false); // Don't skip newline
|
||||
|
||||
// Set our buffers back to continue parsing
|
||||
datastream = localstream;
|
||||
datareader = localreader;
|
||||
sourcename = localsourcename;
|
||||
}
|
||||
else
|
||||
// Sanity checks
|
||||
if(!includelump.StartsWith("\"") || !includelump.EndsWith("\""))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": got #include directive with missing or incorrect path: '" + includeLump + "'.");
|
||||
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)
|
||||
{
|
||||
ReportError("already parsed '" + includelump + "'. Check your #include directives");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Callback to parse this file
|
||||
if(OnInclude != null) OnInclude(this, includelump);
|
||||
|
||||
// Set our buffers back to continue parsing
|
||||
datastream = localstream;
|
||||
datareader = localreader;
|
||||
sourcename = localsourcename;
|
||||
}
|
||||
else if(token == "$gzdb_skip") //mxd
|
||||
{
|
||||
|
@ -685,21 +669,21 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
string token2;
|
||||
do
|
||||
{
|
||||
if (!SkipWhitespace(true)) break;
|
||||
if(!SkipWhitespace(true)) break;
|
||||
token2 = ReadToken();
|
||||
if (string.IsNullOrEmpty(token2)) break;
|
||||
if(string.IsNullOrEmpty(token2)) break;
|
||||
}
|
||||
while (token2 != "{");
|
||||
int scopelevel = 1;
|
||||
do
|
||||
{
|
||||
if (!SkipWhitespace(true)) break;
|
||||
if(!SkipWhitespace(true)) break;
|
||||
token2 = ReadToken();
|
||||
if(string.IsNullOrEmpty(token2)) break;
|
||||
if (token2 == "{") scopelevel++;
|
||||
if (token2 == "}") scopelevel--;
|
||||
if(token2 == "{") scopelevel++;
|
||||
if(token2 == "}") scopelevel--;
|
||||
}
|
||||
while (scopelevel > 0);
|
||||
while(scopelevel > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -716,6 +700,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
parsedlumps.Clear();
|
||||
}
|
||||
|
||||
protected override string GetLanguageType()
|
||||
{
|
||||
return "GLDEFS";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
private string mapname;
|
||||
private readonly Dictionary<int, string> spawnnums;
|
||||
private readonly Dictionary<int, string> doomednums; // <DoomEdNum, <lowercase classname, List of default arguments>>
|
||||
private readonly HashSet<string> parsedlumps;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -50,6 +51,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
mapinfo = new MapInfo();
|
||||
spawnnums = new Dictionary<int, string>();
|
||||
doomednums = new Dictionary<int, string>();
|
||||
parsedlumps = new HashSet<string>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -67,6 +69,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
{
|
||||
base.Parse(stream, sourcefilename);
|
||||
this.mapname = mapname.ToLowerInvariant();
|
||||
parsedlumps.Add(sourcefilename);
|
||||
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
|
@ -118,30 +121,30 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
int bracelevel = 0;
|
||||
|
||||
//search for required keys
|
||||
while (SkipWhitespace(true))
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
token = ReadToken().ToLowerInvariant();
|
||||
//sky1 or sky2
|
||||
if (token == "sky1" || token == "sky2")
|
||||
if(token == "sky1" || token == "sky2")
|
||||
{
|
||||
string skyType = token;
|
||||
SkipWhitespace(true);
|
||||
token = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
||||
|
||||
//new format
|
||||
if (token == "=")
|
||||
if(token == "=")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
|
||||
//should be sky texture name
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
bool gotComma = (token.IndexOf(",") != -1);
|
||||
if (gotComma) token = token.Replace(",", "");
|
||||
if(gotComma) token = token.Replace(",", "");
|
||||
string skyTexture = StripTokenQuotes(token).ToLowerInvariant();
|
||||
|
||||
if (!string.IsNullOrEmpty(skyTexture))
|
||||
if(!string.IsNullOrEmpty(skyTexture))
|
||||
{
|
||||
if (skyType == "sky1")
|
||||
if(skyType == "sky1")
|
||||
mapinfo.Sky1 = skyTexture;
|
||||
else
|
||||
mapinfo.Sky2 = skyTexture;
|
||||
|
@ -150,25 +153,24 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
SkipWhitespace(true);
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
|
||||
if (!gotComma && token == ",")
|
||||
if(!gotComma && token == ",")
|
||||
{
|
||||
gotComma = true;
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();
|
||||
}
|
||||
|
||||
if (gotComma)
|
||||
if(gotComma)
|
||||
{
|
||||
float scrollSpeed = 0;
|
||||
if (!ReadSignedFloat(token, ref scrollSpeed))
|
||||
if(!ReadSignedFloat(token, ref scrollSpeed))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + skyType + " scroll speed value, but got '" + token + "'");
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
continue;
|
||||
ReportError("expected " + skyType + " scroll speed value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (skyType == "sky1")
|
||||
if(skyType == "sky1")
|
||||
mapinfo.Sky1ScrollSpeed = scrollSpeed;
|
||||
else
|
||||
mapinfo.Sky2ScrollSpeed = scrollSpeed;
|
||||
|
@ -180,17 +182,17 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else
|
||||
{
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + skyType + " texture name.");
|
||||
ReportError("expected " + skyType + " texture name");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//old format
|
||||
else
|
||||
{
|
||||
//token should be sky1/2 name
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
if(!string.IsNullOrEmpty(token))
|
||||
{
|
||||
if (skyType == "sky1")
|
||||
if(skyType == "sky1")
|
||||
mapinfo.Sky1 = token;
|
||||
else
|
||||
mapinfo.Sky2 = token;
|
||||
|
@ -200,14 +202,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
token = StripTokenQuotes(ReadToken());
|
||||
|
||||
float scrollSpeed = 0;
|
||||
if (!ReadSignedFloat(token, ref scrollSpeed))
|
||||
if(!ReadSignedFloat(token, ref scrollSpeed))
|
||||
{
|
||||
// Not numeric!
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skyType == "sky1")
|
||||
if(skyType == "sky1")
|
||||
mapinfo.Sky1ScrollSpeed = scrollSpeed;
|
||||
else
|
||||
mapinfo.Sky2ScrollSpeed = scrollSpeed;
|
||||
|
@ -215,20 +217,20 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else
|
||||
{
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + skyType + " texture name.");
|
||||
ReportError("expected " + skyType + " texture name");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
//fade or outsidefog
|
||||
else if (token == "fade" || token == "outsidefog")
|
||||
else if(token == "fade" || token == "outsidefog")
|
||||
{
|
||||
string fadeType = token;
|
||||
SkipWhitespace(true);
|
||||
token = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
||||
|
||||
//new format?
|
||||
if (token == "=")
|
||||
if(token == "=")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();
|
||||
|
@ -249,18 +251,18 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else //...or not
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Failed to parse " + fadeType + " value from string '" + colorVal + "' in '" + sourcename + "' at line " + GetCurrentLineNumber());
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
ReportError("failed to parse " + fadeType + " value from string '" + colorVal + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " color value.");
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
ReportError("expected " + fadeType + " color value");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//vertwallshade or horizwallshade
|
||||
else if (token == "vertwallshade" || token == "horizwallshade")
|
||||
else if(token == "vertwallshade" || token == "horizwallshade")
|
||||
{
|
||||
string shadeType = token;
|
||||
SkipWhitespace(true);
|
||||
|
@ -277,9 +279,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!ReadSignedInt(token, ref val))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + shadeType + " value, but got '" + token + "'");
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
continue;
|
||||
ReportError("expected " + shadeType + " value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(shadeType == "vertwallshade")
|
||||
|
@ -305,23 +306,22 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + densityType + " value, but got '" + token + "'");
|
||||
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
||||
continue;
|
||||
ReportError("expected " + densityType + " value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (densityType == "fogdensity")
|
||||
if(densityType == "fogdensity")
|
||||
mapinfo.FogDensity = (int)(1024 * (256.0f / val));
|
||||
else
|
||||
mapinfo.OutsideFogDensity = (int)(1024 * (256.0f / val));
|
||||
}
|
||||
//doublesky
|
||||
else if (token == "doublesky")
|
||||
else if(token == "doublesky")
|
||||
{
|
||||
mapinfo.DoubleSky = true;
|
||||
}
|
||||
//evenlighting
|
||||
else if (token == "evenlighting")
|
||||
else if(token == "evenlighting")
|
||||
{
|
||||
mapinfo.EvenLighting = true;
|
||||
}
|
||||
|
@ -331,7 +331,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
mapinfo.SmoothLighting = true;
|
||||
}
|
||||
//block end
|
||||
else if (token == "}")
|
||||
else if(token == "}")
|
||||
{
|
||||
return ParseBlock(token);
|
||||
}
|
||||
|
@ -356,12 +356,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
else if(token == "include")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
string includeLump = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
||||
if(!string.IsNullOrEmpty(includeLump))
|
||||
string includelump = StripTokenQuotes(ReadToken(false)).ToLowerInvariant(); // Don't skip newline
|
||||
|
||||
if(!string.IsNullOrEmpty(includelump))
|
||||
{
|
||||
// Callback to parse this file
|
||||
if(OnInclude != null)
|
||||
OnInclude(this, includeLump.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar));
|
||||
OnInclude(this, includelump.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar));
|
||||
|
||||
// Set our buffers back to continue parsing
|
||||
datastream = localstream;
|
||||
|
@ -370,32 +371,33 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": got #include directive with missing or incorrect path: '" + includeLump + "'.");
|
||||
ReportError("got include directive with missing or incorrect path: '" + includelump + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(token == "gameinfo")
|
||||
{
|
||||
if(!NextTokenIs("{")) return true; // Finished with this file
|
||||
if(!NextTokenIs("{")) return false; // Finished with this file
|
||||
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
token = ReadToken();
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error while parisng '" + sourcename + "' at line " + GetCurrentLineNumber() + ": failed to find the end of GameInfo block");
|
||||
return true; // Finished with this file
|
||||
ReportError("failed to find the end of GameInfo block");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
if(token == "}") break;
|
||||
|
||||
if(token == "skyflatname")
|
||||
{
|
||||
if(!NextTokenIs("=")) return true; // Finished with this file
|
||||
if(!NextTokenIs("=")) return false; // Finished with this file
|
||||
SkipWhitespace(true);
|
||||
string skyflatname = StripTokenQuotes(ReadToken());
|
||||
if(string.IsNullOrEmpty(skyflatname))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error while parisng '" + sourcename + "' at line " + GetCurrentLineNumber() + ": unable to get SkyFlatName value");
|
||||
return true; // Finished with this file
|
||||
ReportError("unable to get SkyFlatName value");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
|
||||
General.Map.Config.SkyFlatName = skyflatname.ToUpperInvariant();
|
||||
|
@ -404,15 +406,15 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else if(token == "doomednums")
|
||||
{
|
||||
if(!NextTokenIs("{")) return true; // Finished with this file
|
||||
if(!NextTokenIs("{")) return false; // Finished with this file
|
||||
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
token = ReadToken();
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error while parisng '" + sourcename + "' at line " + GetCurrentLineNumber() + ": failed to find the end of DoomEdNums block");
|
||||
return true; // Finished with this file
|
||||
ReportError("failed to find the end of DoomEdNums block");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
if(token == "}") break;
|
||||
|
||||
|
@ -421,24 +423,24 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out id))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected DoomEdNums entry number, but got '" + token + "'");
|
||||
return true; // Finished with this file
|
||||
ReportError("expected DoomEdNums entry number, but got '" + token + "'");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
|
||||
// Then "="
|
||||
if(!NextTokenIs("=")) return true; // Finished with this file
|
||||
if(!NextTokenIs("=")) return false; // Finished with this file
|
||||
|
||||
// Then actor class
|
||||
SkipWhitespace(false);
|
||||
string classname = StripTokenQuotes(ReadToken());
|
||||
if(string.IsNullOrEmpty(classname))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error while parisng '" + sourcename + "' at line " + GetCurrentLineNumber() + ": unable to get DoomEdNums entry class definition");
|
||||
return true; // Finished with this file
|
||||
ReportError("unable to get DoomEdNums entry class definition");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
|
||||
// Possible special and args. We'll skip them
|
||||
for (int i = 0; i < 6; i++)
|
||||
for(int i = 0; i < 6; i++)
|
||||
{
|
||||
if(!NextTokenIs(",", false)) break;
|
||||
|
||||
|
@ -452,15 +454,15 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
else if(token == "spawnnums")
|
||||
{
|
||||
if(!NextTokenIs("{")) return true; // Finished with this file
|
||||
if(!NextTokenIs("{")) return false; // Finished with this file
|
||||
|
||||
while (SkipWhitespace(true))
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
token = ReadToken();
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error while parisng '" + sourcename + "' at line " + GetCurrentLineNumber() + ": failed to find the end of SpawnNums block");
|
||||
return true; // Finished with this file
|
||||
ReportError("failed to find the end of SpawnNums block");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
if(token == "}") break;
|
||||
|
||||
|
@ -469,20 +471,20 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out id))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected SpawnNums number, but got '" + token + "'");
|
||||
return true; // Finished with this file
|
||||
ReportError("expected SpawnNums number, but got '" + token + "'");
|
||||
return false; // Finished with this file
|
||||
}
|
||||
|
||||
// Then "="
|
||||
if(!NextTokenIs("=")) return true; // Finished with this file
|
||||
if(!NextTokenIs("=")) return false; // Finished with this file
|
||||
|
||||
// Then actor class
|
||||
SkipWhitespace(false);
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error while parisng '" + sourcename + "' at line " + GetCurrentLineNumber() + ": unable to get SpawnNums entry class definition");
|
||||
return true;
|
||||
ReportError("unable to get SpawnNums entry class definition");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add to collection
|
||||
|
@ -503,11 +505,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
|
||||
private static bool GetColor(string name, ref Color4 color)
|
||||
{
|
||||
if (name == "black") return true;
|
||||
if(name == "black") return true;
|
||||
|
||||
//probably it's a hex color (like FFCC11)?
|
||||
int ci;
|
||||
if (int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ci))
|
||||
if(int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ci))
|
||||
{
|
||||
color = new Color4(ci) {Alpha = 1.0f};
|
||||
return true;
|
||||
|
@ -515,7 +517,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
|
||||
//probably it's a color name?
|
||||
Color c = Color.FromName(name); //should be similar to C++ color name detection, I suppose
|
||||
if (c.IsKnownColor)
|
||||
if(c.IsKnownColor)
|
||||
{
|
||||
color = new Color4(c);
|
||||
return true;
|
||||
|
@ -523,6 +525,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
return false;
|
||||
}
|
||||
|
||||
protected override string GetLanguageType()
|
||||
{
|
||||
return "MAPINFO";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
{
|
||||
private Dictionary<string, ModelData> entries; //classname, entry
|
||||
internal Dictionary<string, ModelData> Entries { get { return entries; } }
|
||||
internal string Source { get { return sourcename; } }
|
||||
|
||||
internal ModeldefParser()
|
||||
{
|
||||
|
@ -24,66 +23,88 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
entries = new Dictionary<string, ModelData>(StringComparer.Ordinal);
|
||||
|
||||
// Continue until at the end of the stream
|
||||
while (SkipWhitespace(true))
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
string token = ReadToken();
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
if(!string.IsNullOrEmpty(token))
|
||||
{
|
||||
token = StripTokenQuotes(token).ToLowerInvariant();
|
||||
if (token == "model") //model structure start
|
||||
if(token == "model") //model structure start
|
||||
{
|
||||
//find classname
|
||||
SkipWhitespace(true);
|
||||
string className = StripTokenQuotes(ReadToken(ActorStructure.ACTOR_CLASS_SPECIAL_TOKENS)).ToLowerInvariant();
|
||||
string displayclassname = StripTokenQuotes(ReadToken(ActorStructure.ACTOR_CLASS_SPECIAL_TOKENS));
|
||||
string classname = displayclassname.ToLowerInvariant();
|
||||
|
||||
if(!string.IsNullOrEmpty(className) && !entries.ContainsKey(className))
|
||||
if(!string.IsNullOrEmpty(classname) && !entries.ContainsKey(classname))
|
||||
{
|
||||
//now find opening brace
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();
|
||||
if (token != "{")
|
||||
if(token != "{")
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '"+sourcefilename+"' at line "+GetCurrentLineNumber()+": expected '{', but got '" + token + "'");
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected '{', but got '" + token + "'");
|
||||
continue; //something wrong with modeldef declaration, continue to next one
|
||||
}
|
||||
|
||||
ModeldefStructure mds = new ModeldefStructure();
|
||||
ModelData mde = mds.Parse(this);
|
||||
if (mde != null) entries.Add(className, mde);
|
||||
if(mds.Parse(this, displayclassname) && mds.ModelData != null)
|
||||
{
|
||||
entries.Add(classname, mds.ModelData);
|
||||
}
|
||||
|
||||
if(HasError)
|
||||
{
|
||||
LogError();
|
||||
ClearError();
|
||||
}
|
||||
|
||||
// Skip untill current structure end
|
||||
if(!mds.ParsingFinished)
|
||||
{
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
token = ReadToken();
|
||||
if(string.IsNullOrEmpty(token) || token == "}") break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown structure!
|
||||
string token2;
|
||||
if (token != "{")
|
||||
if(token != "{")
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!SkipWhitespace(true)) break;
|
||||
if(!SkipWhitespace(true)) break;
|
||||
token2 = ReadToken();
|
||||
if (string.IsNullOrEmpty(token2)) break;
|
||||
if(string.IsNullOrEmpty(token2)) break;
|
||||
}
|
||||
while (token2 != "{");
|
||||
while(token2 != "{");
|
||||
}
|
||||
|
||||
int scopelevel = 1;
|
||||
do
|
||||
{
|
||||
if (!SkipWhitespace(true)) break;
|
||||
if(!SkipWhitespace(true)) break;
|
||||
token2 = ReadToken();
|
||||
if (string.IsNullOrEmpty(token2)) break;
|
||||
if (token2 == "{") scopelevel++;
|
||||
if (token2 == "}") scopelevel--;
|
||||
if(string.IsNullOrEmpty(token2)) break;
|
||||
if(token2 == "{") scopelevel++;
|
||||
if(token2 == "}") scopelevel--;
|
||||
}
|
||||
while (scopelevel > 0);
|
||||
while(scopelevel > 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return entries.Count > 0;
|
||||
}
|
||||
|
||||
protected override string GetLanguageType()
|
||||
{
|
||||
return "MODELDEF";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#region ================== Namespaces
|
||||
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using CodeImp.DoomBuilder.ZDoom;
|
||||
using System.IO;
|
||||
using CodeImp.DoomBuilder.GZBuilder.Data;
|
||||
using CodeImp.DoomBuilder.ZDoom;
|
||||
|
||||
#endregion
|
||||
|
||||
//mxd. Modeldef parser used to create ScriptItems for use in script editor's navigator
|
||||
//Should be parse model definitions even from invalid MODELDEF and should never fail parsing
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
||||
{
|
||||
internal sealed class ModeldefParserSE : ZDTextParser
|
||||
|
@ -25,34 +26,39 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
base.Parse(stream, sourcefilename);
|
||||
|
||||
// Continue until at the end of the stream
|
||||
while (SkipWhitespace(true))
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
string token = ReadToken();
|
||||
if(string.IsNullOrEmpty(token) || token.ToUpperInvariant() != "MODEL") continue;
|
||||
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
SkipWhitespace(true);
|
||||
int startpos = (int)stream.Position;
|
||||
string modelname = ReadToken();
|
||||
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken(); //this should be "{"
|
||||
|
||||
if(token == "{")
|
||||
{
|
||||
token = token.ToUpperInvariant();
|
||||
ScriptItem i = new ScriptItem(modelname, startpos, false);
|
||||
models.Add(i);
|
||||
}
|
||||
|
||||
if(token == "MODEL")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
int startPos = (int)stream.Position;
|
||||
string modelName = ReadToken();
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken(); //this should be "{"
|
||||
|
||||
if (token == "{")
|
||||
{
|
||||
ScriptItem i = new ScriptItem(modelName, startPos, false);
|
||||
models.Add(i);
|
||||
}
|
||||
}
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
token = ReadToken();
|
||||
if(string.IsNullOrEmpty(token) || token == "}") break;
|
||||
}
|
||||
}
|
||||
|
||||
//sort nodes
|
||||
// Sort nodes
|
||||
models.Sort(ScriptItem.SortByName);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override string GetLanguageType()
|
||||
{
|
||||
return "MODELDEF";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
internal sealed class ModeldefStructure
|
||||
{
|
||||
private const int MAX_MODELS = 4; //maximum models per modeldef entry, zero-based
|
||||
private bool parsingfinished;
|
||||
|
||||
internal ModelData Parse(ModeldefParser parser)
|
||||
internal ModelData ModelData;
|
||||
internal bool ParsingFinished { get { return parsingfinished; } }
|
||||
|
||||
internal bool Parse(ModeldefParser parser, string classname)
|
||||
{
|
||||
|
||||
#region ================== Vars
|
||||
|
@ -35,13 +39,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
bool inheritactorroll = false;
|
||||
|
||||
string token;
|
||||
bool gotErrors = false;
|
||||
bool allParsed = false;
|
||||
|
||||
#endregion
|
||||
|
||||
//read modeldef structure contents
|
||||
while(!gotErrors && !allParsed && parser.SkipWhitespace(true))
|
||||
parsingfinished = false;
|
||||
while(!parsingfinished && parser.SkipWhitespace(true))
|
||||
{
|
||||
token = parser.ReadToken();
|
||||
if(!string.IsNullOrEmpty(token))
|
||||
|
@ -54,11 +57,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
|
||||
case "path":
|
||||
parser.SkipWhitespace(true);
|
||||
path = parser.StripTokenQuotes(parser.ReadToken()).Replace("/", "\\");
|
||||
if(string.IsNullOrEmpty(path))
|
||||
path = parser.StripTokenQuotes(parser.ReadToken(false)).Replace("/", "\\"); // Don't skip newline
|
||||
if(string.IsNullOrEmpty(path))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected path to model, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
parser.ReportError("expected model path, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -75,47 +78,42 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out index))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected model index, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
parser.ReportError("expected model index, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(index >= MAX_MODELS)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": GZDoom doesn't allow more than " + MAX_MODELS + " models per MODELDEF entry!");
|
||||
gotErrors = true;
|
||||
break;
|
||||
parser.ReportError("GZDoom doesn't allow more than " + MAX_MODELS + " models per MODELDEF entry");
|
||||
return false;
|
||||
}
|
||||
|
||||
parser.SkipWhitespace(true);
|
||||
|
||||
//model path
|
||||
token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant();
|
||||
token = parser.StripTokenQuotes(parser.ReadToken(false)).ToLowerInvariant(); // Don't skip newline
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected model name, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
parser.ReportError("model name required");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//check extension
|
||||
string fileExt = Path.GetExtension(token);
|
||||
if(string.IsNullOrEmpty(fileExt))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": model '" + token + "' won't be loaded. Models without extension are not supported by GZDoom.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
if(fileExt != ".md3" && fileExt != ".md2")
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": model '" + token + "' won't be loaded. Only MD2 and MD3 models are supported.");
|
||||
gotErrors = true;
|
||||
break;
|
||||
}
|
||||
|
||||
//GZDoom allows models with identical modelIndex, it uses the last one encountered
|
||||
modelNames[index] = Path.Combine(path, token);
|
||||
//check extension
|
||||
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");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fileExt != ".md3" && fileExt != ".md2")
|
||||
{
|
||||
parser.ReportError("model '" + token + "' won't be loaded. Only MD2 and MD3 models are supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
//GZDoom allows models with identical modelIndex, it uses the last one encountered
|
||||
modelNames[index] = Path.Combine(path, token);
|
||||
break;
|
||||
|
||||
#endregion
|
||||
|
@ -131,42 +129,36 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out skinIndex))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected skin index, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
parser.ReportError("expected skin index, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(skinIndex >= MAX_MODELS)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": GZDoom doesn't allow more than " + MAX_MODELS + " skins per MODELDEF entry!");
|
||||
gotErrors = true;
|
||||
break;
|
||||
parser.ReportError("GZDoom doesn't allow more than " + MAX_MODELS + " skins per MODELDEF entry");
|
||||
return false;
|
||||
}
|
||||
|
||||
parser.SkipWhitespace(true);
|
||||
|
||||
//skin path
|
||||
token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant();
|
||||
token = parser.StripTokenQuotes(parser.ReadToken(false)).ToLowerInvariant(); // Don't skip newline
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected skin name, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
parser.ReportError("skin path required");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
//check extension
|
||||
string ext = Path.GetExtension(token);
|
||||
if(Array.IndexOf(ModelData.SUPPORTED_TEXTURE_EXTENSIONS, ext) == -1)
|
||||
{
|
||||
//check extension
|
||||
string ext = Path.GetExtension(token);
|
||||
if(Array.IndexOf(TextureData.SUPPORTED_TEXTURE_EXTENSIONS, ext) == -1)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": image format '" + ext + "' is not supported!");
|
||||
textureNames[skinIndex] = TextureData.INVALID_TEXTURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
//GZDoom allows skins with identical modelIndex, it uses the last one encountered
|
||||
textureNames[skinIndex] = Path.Combine(path, token);
|
||||
}
|
||||
}
|
||||
parser.ReportError("image format '" + ext + "' is not supported!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//GZDoom allows skins with identical modelIndex, it uses the last one encountered
|
||||
textureNames[skinIndex] = Path.Combine(path, token);
|
||||
break;
|
||||
|
||||
#endregion
|
||||
|
@ -179,9 +171,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref scale.Y))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected Scale X value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
parser.ReportError("expected Scale X value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
parser.SkipWhitespace(true);
|
||||
|
@ -189,9 +180,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref scale.X))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected Scale Y value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
parser.ReportError("expected Scale Y value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
parser.SkipWhitespace(true);
|
||||
|
@ -199,8 +189,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref scale.Z))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected Scale Z value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
parser.ReportError("expected Scale Z value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -214,9 +204,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref offset.X))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected Offset X value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
parser.ReportError("expected Offset X value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
parser.SkipWhitespace(true);
|
||||
|
@ -224,9 +213,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref offset.Y))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected Offset Y value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
parser.ReportError("expected Offset Y value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
parser.SkipWhitespace(true);
|
||||
|
@ -234,8 +222,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref offset.Z))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected Offset Z value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
parser.ReportError("expected Offset Z value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -249,8 +237,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref offset.Z))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected ZOffset value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
parser.ReportError("expected ZOffset value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -264,8 +252,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref angleOffset))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected AngleOffset value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
parser.ReportError("expected AngleOffset value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -279,8 +267,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref pitchOffset))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected PitchOffset value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
parser.ReportError("expected PitchOffset value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -294,8 +282,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedFloat(token, ref rollOffset))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected RollOffset value, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
parser.ReportError("expected RollOffset value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -322,8 +310,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
case "frameindex":
|
||||
case "frame":
|
||||
//parsed all required fields. if got more than one model - find which one(s) should be displayed
|
||||
int len = modelNames.GetLength(0);
|
||||
if(!gotErrors && len > 1)
|
||||
if(modelNames.GetLength(0) > 1)
|
||||
{
|
||||
string spriteLump = null;
|
||||
string spriteFrame = null;
|
||||
|
@ -389,23 +376,20 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out modelIndex))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected model index, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
parser.ReportError("expected model index, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(modelIndex >= MAX_MODELS)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": GZDoom doesn't allow more than " + MAX_MODELS + " models per MODELDEF entry!");
|
||||
gotErrors = true;
|
||||
break;
|
||||
parser.ReportError("GZDoom doesn't allow more than " + MAX_MODELS + " models per MODELDEF entry");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(modelNames[modelIndex] == null)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": got model index, which doesn't correspond to any defined model!");
|
||||
gotErrors = true;
|
||||
break;
|
||||
parser.ReportError("got model index, which doesn't correspond to any defined model");
|
||||
return false;
|
||||
}
|
||||
|
||||
modelsUsed[modelIndex] = true;
|
||||
|
@ -420,9 +404,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(!parser.ReadSignedInt(token, ref frame))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected model frame index, but got '" + token + "'");
|
||||
gotErrors = true;
|
||||
break;
|
||||
parser.ReportError("expected model frame index, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip the model if frame index is -1
|
||||
|
@ -434,9 +417,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
// Missing!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected model frame name");
|
||||
gotErrors = true;
|
||||
break;
|
||||
parser.ReportError("expected model frame name");
|
||||
return false;
|
||||
}
|
||||
|
||||
frameNames[modelIndex] = token.ToLowerInvariant();
|
||||
|
@ -451,7 +433,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
}
|
||||
|
||||
allParsed = true;
|
||||
parsingfinished = true;
|
||||
break;
|
||||
|
||||
#endregion
|
||||
|
@ -467,28 +449,38 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
}
|
||||
|
||||
// Bail out when got errors or no models are used
|
||||
if(gotErrors || Array.IndexOf(modelsUsed, true) == -1) return null;
|
||||
if(Array.IndexOf(modelsUsed, true) == -1)
|
||||
{
|
||||
parser.ReportError("no models are used by '" + classname + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Classname is set in ModeldefParser
|
||||
ModelData mde = new ModelData();
|
||||
mde.InheritActorPitch = inheritactorpitch;
|
||||
mde.InheritActorRoll = inheritactorroll;
|
||||
ModelData = new ModelData();
|
||||
ModelData.InheritActorPitch = inheritactorpitch;
|
||||
ModelData.InheritActorRoll = inheritactorroll;
|
||||
Matrix moffset = Matrix.Translation(offset.Y, -offset.X, offset.Z); // Things are complicated in GZDoom...
|
||||
Matrix mrotation = Matrix.RotationY(-Angle2D.DegToRad(rollOffset)) * Matrix.RotationX(-Angle2D.DegToRad(pitchOffset)) * Matrix.RotationZ(Angle2D.DegToRad(angleOffset));
|
||||
mde.SetTransform(mrotation, moffset, scale);
|
||||
ModelData.SetTransform(mrotation, moffset, scale);
|
||||
|
||||
for(int i = 0; i < modelNames.Length; i++)
|
||||
{
|
||||
if(!string.IsNullOrEmpty(modelNames[i]) && modelsUsed[i])
|
||||
{
|
||||
mde.TextureNames.Add(string.IsNullOrEmpty(textureNames[i]) ? string.Empty : textureNames[i].ToLowerInvariant());
|
||||
mde.ModelNames.Add(modelNames[i].ToLowerInvariant());
|
||||
mde.FrameNames.Add(frameNames[i]);
|
||||
mde.FrameIndices.Add(frameIndices[i]);
|
||||
ModelData.TextureNames.Add(string.IsNullOrEmpty(textureNames[i]) ? string.Empty : textureNames[i].ToLowerInvariant());
|
||||
ModelData.ModelNames.Add(modelNames[i].ToLowerInvariant());
|
||||
ModelData.FrameNames.Add(frameNames[i]);
|
||||
ModelData.FrameIndices.Add(frameIndices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return (mde.ModelNames.Count > 0 ? mde : null);
|
||||
if(ModelData.ModelNames.Count == 0)
|
||||
{
|
||||
parser.ReportError("'" + classname + "' has no models");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,18 +28,18 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
{
|
||||
string token = ReadToken();
|
||||
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
if(!string.IsNullOrEmpty(token))
|
||||
{
|
||||
token = token.ToUpperInvariant();
|
||||
|
||||
if (token == "MODEL")
|
||||
if(token == "MODEL")
|
||||
{
|
||||
SkipWhitespace(true);
|
||||
ReadToken(); //should be model name
|
||||
SkipWhitespace(true);
|
||||
token = ReadToken();//should be opening brace
|
||||
|
||||
if (token == "{")
|
||||
if(token == "{")
|
||||
{
|
||||
scriptType = ScriptType.MODELDEF;
|
||||
return true;
|
||||
|
@ -55,7 +55,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
SkipWhitespace(true);
|
||||
token = ReadToken(); //should be opening brace
|
||||
|
||||
if (token == "{")
|
||||
if(token == "{")
|
||||
{
|
||||
scriptType = ScriptType.ACS;
|
||||
return true;
|
||||
|
@ -70,7 +70,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
SkipWhitespace(true);
|
||||
token = ReadToken();
|
||||
|
||||
if (token == ":" || token == "{" || token == "REPLACES")
|
||||
if(token == ":" || token == "{" || token == "REPLACES")
|
||||
{
|
||||
scriptType = ScriptType.DECORATE;
|
||||
return true;
|
||||
|
@ -79,7 +79,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
SkipWhitespace(true);
|
||||
token = ReadToken(); //should be actor name
|
||||
|
||||
if (token == "{")
|
||||
if(token == "{")
|
||||
{
|
||||
scriptType = ScriptType.DECORATE;
|
||||
return true;
|
||||
|
@ -90,5 +90,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override string GetLanguageType()
|
||||
{
|
||||
return "SCRIPT TYPE CHECKER";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,15 +148,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
//load texture
|
||||
List<string> errors = new List<string>();
|
||||
|
||||
//texture has unsupported extension?
|
||||
if(mde.TextureNames[i] == TextureData.INVALID_TEXTURE)
|
||||
{
|
||||
for(int c = 0; c < result.Meshes.Count; c++)
|
||||
mde.Model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture);
|
||||
|
||||
//texture not defined in MODELDEF?
|
||||
}
|
||||
else if(useSkins)
|
||||
// Texture not defined in MODELDEF?
|
||||
if(useSkins)
|
||||
{
|
||||
//try to use model's own skins
|
||||
for(int m = 0; m < result.Meshes.Count; m++)
|
||||
|
@ -171,7 +164,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
string path = result.Skins[m].Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||
ext = Path.GetExtension(path);
|
||||
|
||||
if(Array.IndexOf(TextureData.SUPPORTED_TEXTURE_EXTENSIONS, ext) == -1)
|
||||
if(Array.IndexOf(ModelData.SUPPORTED_TEXTURE_EXTENSIONS, ext) == -1)
|
||||
{
|
||||
mde.Model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture);
|
||||
errors.Add("image format '" + ext + "' is not supported!");
|
||||
|
@ -193,8 +186,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
|
||||
mde.Model.Textures.Add(t);
|
||||
}
|
||||
}
|
||||
else //try to use texture loaded from MODELDEFS
|
||||
}
|
||||
//Try to use texture loaded from MODELDEFS
|
||||
else
|
||||
{
|
||||
Texture t = LoadTexture(containers, mde.TextureNames[i], device);
|
||||
if(t == null)
|
||||
|
|
|
@ -81,29 +81,38 @@ namespace CodeImp.DoomBuilder
|
|||
|
||||
lock(this)
|
||||
{
|
||||
errors.Add(new ErrorItem(type, message));
|
||||
switch(type)
|
||||
//mxd. Don't add duplicate messages
|
||||
if(errors.Count == 0 || message != errors[errors.Count - 1].message || type != errors[errors.Count - 1].type)
|
||||
{
|
||||
case ErrorType.Error:
|
||||
erroradded = true;
|
||||
prefix = "ERROR: ";
|
||||
errors.Add(new ErrorItem(type, message));
|
||||
switch(type)
|
||||
{
|
||||
case ErrorType.Error:
|
||||
erroradded = true;
|
||||
prefix = "ERROR: ";
|
||||
#if DEBUG
|
||||
DebugConsole.WriteLine(DebugMessageType.ERROR, message);
|
||||
DebugConsole.WriteLine(DebugMessageType.ERROR, message);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ErrorType.Warning:
|
||||
warningadded = true;
|
||||
prefix = "WARNING: ";
|
||||
#if DEBUG
|
||||
DebugConsole.WriteLine(DebugMessageType.WARNING, message);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
changed = true;
|
||||
break;
|
||||
|
||||
General.WriteLogLine(prefix + message);
|
||||
General.MainWindow.SetWarningsCount(errors.Count, erroradded); //mxd
|
||||
case ErrorType.Warning:
|
||||
warningadded = true;
|
||||
prefix = "WARNING: ";
|
||||
#if DEBUG
|
||||
DebugConsole.WriteLine(DebugMessageType.WARNING, message);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
General.WriteLogLine(prefix + message);
|
||||
General.MainWindow.SetWarningsCount(errors.Count, erroradded); //mxd
|
||||
}
|
||||
//mxd. But still blink the indicator on errors
|
||||
else if(type == ErrorType.Error)
|
||||
{
|
||||
General.MainWindow.SetWarningsCount(errors.Count, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1879,10 +1879,12 @@ namespace CodeImp.DoomBuilder
|
|||
List<CompilerError> compilererrors = UpdateScriptNames();
|
||||
if(logerrors && compilererrors.Count > 0)
|
||||
{
|
||||
//INFO: CompileLump() prepends lumpname with "?" to distinguish between temporary files and files compiled in place
|
||||
//INFO: also, error.linenumber is zero-based
|
||||
foreach(CompilerError error in compilererrors)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "ACS error in '" + error.filename
|
||||
+ (error.linenumber != CompilerError.NO_LINE_NUMBER ? "', line " + error.linenumber : "'")
|
||||
General.ErrorLogger.Add(ErrorType.Error, "ACS error in '" + (error.filename.StartsWith("?") ? error.filename.Replace("?", "") : error.filename)
|
||||
+ (error.linenumber != CompilerError.NO_LINE_NUMBER ? "', line " + (error.linenumber + 1) : "'")
|
||||
+ ". " + error.description + ".");
|
||||
}
|
||||
}
|
||||
|
@ -1927,15 +1929,18 @@ namespace CodeImp.DoomBuilder
|
|||
{
|
||||
// Get script names
|
||||
AcsParserSE parser = new AcsParserSE { OnInclude = (se, path) => se.Parse(General.Map.Data.LoadFile(path), path, true, true) };
|
||||
if(parser.Parse(stream, "SCRIPTS", scriptconfig.Compiler.Files, true, false))
|
||||
|
||||
//INFO: CompileLump() prepends lumpname with "?" to distinguish between temporary files and files compiled in place
|
||||
if(parser.Parse(stream, "?SCRIPTS", scriptconfig.Compiler.Files, true, false))
|
||||
{
|
||||
// Add them to arrays
|
||||
namedscriptslist.AddRange(parser.NamedScripts);
|
||||
numberedscriptslist.AddRange(parser.NumberedScripts);
|
||||
scripincludeslist.AddRange(parser.Includes);
|
||||
}
|
||||
|
||||
// Check for errors
|
||||
else if(parser.HasError)
|
||||
if(parser.HasError)
|
||||
{
|
||||
compilererrors.Add(new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine));
|
||||
break;
|
||||
|
|
|
@ -109,7 +109,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
{
|
||||
token = token.ToLowerInvariant();
|
||||
|
||||
switch (token)
|
||||
switch(token)
|
||||
{
|
||||
case ":":
|
||||
// The next token must be the class to inherit from
|
||||
|
@ -123,9 +123,6 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
// Find the actor to inherit from
|
||||
baseclass = parser.GetArchivedActorByName(inheritclass);
|
||||
|
||||
//mxd. Does it exist? (We can carry on regardless, so add a warning)
|
||||
if(baseclass == null) parser.ReportWarning("Parent class '" + inheritclass + "' does not exist");
|
||||
break;
|
||||
|
||||
case "replaces":
|
||||
|
@ -171,7 +168,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
break;
|
||||
}
|
||||
|
||||
if (done) break; //mxd
|
||||
if(done) break; //mxd
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -188,7 +185,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
string token = parser.ReadToken();
|
||||
token = token.ToLowerInvariant();
|
||||
|
||||
switch (token)
|
||||
switch(token)
|
||||
{
|
||||
case "+":
|
||||
case "-":
|
||||
|
@ -196,7 +193,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
bool flagvalue = (token == "+");
|
||||
parser.SkipWhitespace(true);
|
||||
string flagname = parser.ReadToken();
|
||||
if (!string.IsNullOrEmpty(flagname))
|
||||
if(!string.IsNullOrEmpty(flagname))
|
||||
{
|
||||
// Add the flag with its value
|
||||
flagname = flagname.ToLowerInvariant();
|
||||
|
@ -212,10 +209,10 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
case "action":
|
||||
case "native":
|
||||
// We don't need this, ignore up to the first next ;
|
||||
while (parser.SkipWhitespace(true))
|
||||
while(parser.SkipWhitespace(true))
|
||||
{
|
||||
string t = parser.ReadToken();
|
||||
if (string.IsNullOrEmpty(t) || t == ";") break;
|
||||
if(string.IsNullOrEmpty(t) || t == ";") break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -225,31 +222,31 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
case "states":
|
||||
// Now parse actor states until we reach the end of the states structure
|
||||
while (parser.SkipWhitespace(true))
|
||||
while(parser.SkipWhitespace(true))
|
||||
{
|
||||
string statetoken = parser.ReadToken();
|
||||
if (!string.IsNullOrEmpty(statetoken))
|
||||
if(!string.IsNullOrEmpty(statetoken))
|
||||
{
|
||||
// Start of scope?
|
||||
if (statetoken == "{")
|
||||
if(statetoken == "{")
|
||||
{
|
||||
// This is fine
|
||||
}
|
||||
// End of scope?
|
||||
else if (statetoken == "}")
|
||||
else if(statetoken == "}")
|
||||
{
|
||||
// Done with the states,
|
||||
// break out of this parse loop
|
||||
break;
|
||||
}
|
||||
// State label?
|
||||
else if (statetoken == ":")
|
||||
else if(statetoken == ":")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(previoustoken))
|
||||
if(!string.IsNullOrEmpty(previoustoken))
|
||||
{
|
||||
// Parse actor state
|
||||
StateStructure st = new StateStructure(this, parser);
|
||||
if (parser.HasError) return;
|
||||
if(parser.HasError) return;
|
||||
states[previoustoken.ToLowerInvariant()] = st;
|
||||
}
|
||||
else
|
||||
|
@ -273,11 +270,11 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
break;
|
||||
|
||||
case "var": //mxd
|
||||
while (parser.SkipWhitespace(true))
|
||||
while(parser.SkipWhitespace(true))
|
||||
{
|
||||
string t = parser.ReadToken();
|
||||
if (string.IsNullOrEmpty(t) || t == ";") break;
|
||||
if (t.StartsWith("user_") && !userVars.Contains(t))
|
||||
if(string.IsNullOrEmpty(t) || t == ";") break;
|
||||
if(t.StartsWith("user_") && !userVars.Contains(t))
|
||||
userVars.Add(t);
|
||||
}
|
||||
break;
|
||||
|
@ -323,17 +320,17 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
case "game":
|
||||
// Include all tokens on the same line
|
||||
List<string> games = new List<string>();
|
||||
while (parser.SkipWhitespace(false))
|
||||
while(parser.SkipWhitespace(false))
|
||||
{
|
||||
string v = parser.ReadToken();
|
||||
if (string.IsNullOrEmpty(v))
|
||||
if(string.IsNullOrEmpty(v))
|
||||
{
|
||||
parser.ReportError("Unexpected end of structure");
|
||||
return;
|
||||
}
|
||||
if (v == "\n") break;
|
||||
if (v == "}") return; //mxd
|
||||
if (v != ",") games.Add(v.ToLowerInvariant());
|
||||
if(v == "\n") break;
|
||||
if(v == "}") return; //mxd
|
||||
if(v != ",") games.Add(v.ToLowerInvariant());
|
||||
}
|
||||
props[token] = games;
|
||||
break;
|
||||
|
@ -341,7 +338,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
// Property
|
||||
default:
|
||||
// Property begins with $? Then the whole line is a single value
|
||||
if (token.StartsWith("$"))
|
||||
if(token.StartsWith("$"))
|
||||
{
|
||||
// This is for editor-only properties such as $sprite and $category
|
||||
props[token] = new List<string> { (parser.SkipWhitespace(false) ? parser.ReadLine() : "") };
|
||||
|
@ -350,17 +347,17 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
{
|
||||
// Next tokens up until the next newline are values
|
||||
List<string> values = new List<string>();
|
||||
while (parser.SkipWhitespace(false))
|
||||
while(parser.SkipWhitespace(false))
|
||||
{
|
||||
string v = parser.ReadToken();
|
||||
if (string.IsNullOrEmpty(v))
|
||||
if(string.IsNullOrEmpty(v))
|
||||
{
|
||||
parser.ReportError("Unexpected end of structure");
|
||||
return;
|
||||
}
|
||||
if (v == "\n") break;
|
||||
if (v == "}") return; //mxd
|
||||
if (v != ",") values.Add(v);
|
||||
if(v == "\n") break;
|
||||
if(v == "}") return; //mxd
|
||||
if(v != ",") values.Add(v);
|
||||
}
|
||||
|
||||
//mxd. Translate scale to xscale and yscale
|
||||
|
@ -377,7 +374,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
break;
|
||||
}
|
||||
|
||||
if (done) break; //mxd
|
||||
if(done) break; //mxd
|
||||
|
||||
// Keep token
|
||||
previoustoken = token;
|
||||
|
@ -407,16 +404,16 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
//properties
|
||||
if(!props.ContainsKey("height"))
|
||||
props["height"] = new List<string>() { ti.Value.Height.ToString() };
|
||||
props["height"] = new List<string> { ti.Value.Height.ToString() };
|
||||
|
||||
if(!props.ContainsKey("radius"))
|
||||
props["radius"] = new List<string>() { ti.Value.Radius.ToString() };
|
||||
props["radius"] = new List<string> { ti.Value.Radius.ToString() };
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Unable to find the DECORATE class '" + inheritclass + "' to inherit from, while parsing '" + classname + ":" + doomednum + "'");
|
||||
parser.LogWarning("Unable to find '" + inheritclass + "' class to inherit from, while parsing '" + classname + ":" + doomednum + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -438,12 +435,9 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
/// </summary>
|
||||
public bool HasProperty(string propname)
|
||||
{
|
||||
if(props.ContainsKey(propname))
|
||||
return true;
|
||||
else if(!skipsuper && (baseclass != null))
|
||||
return baseclass.HasProperty(propname);
|
||||
else
|
||||
return false;
|
||||
if(props.ContainsKey(propname)) return true;
|
||||
if(!skipsuper && (baseclass != null)) return baseclass.HasProperty(propname);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -451,12 +445,9 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
/// </summary>
|
||||
public bool HasPropertyWithValue(string propname)
|
||||
{
|
||||
if(props.ContainsKey(propname) && (props[propname].Count > 0))
|
||||
return true;
|
||||
else if(!skipsuper && (baseclass != null))
|
||||
return baseclass.HasPropertyWithValue(propname);
|
||||
else
|
||||
return false;
|
||||
if(props.ContainsKey(propname) && (props[propname].Count > 0)) return true;
|
||||
if(!skipsuper && (baseclass != null)) return baseclass.HasPropertyWithValue(propname);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -466,10 +457,9 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
{
|
||||
if(props.ContainsKey(propname) && (props[propname].Count > 0))
|
||||
return string.Join(" ", props[propname].ToArray());
|
||||
else if(!skipsuper && (baseclass != null))
|
||||
if(!skipsuper && (baseclass != null))
|
||||
return baseclass.GetPropertyAllValues(propname);
|
||||
else
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -479,10 +469,9 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
{
|
||||
if(props.ContainsKey(propname) && (props[propname].Count > valueindex))
|
||||
return props[propname][valueindex];
|
||||
else if(!skipsuper && (baseclass != null))
|
||||
if(!skipsuper && (baseclass != null))
|
||||
return baseclass.GetPropertyValueString(propname, valueindex);
|
||||
else
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -524,10 +513,8 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
/// </summary>
|
||||
public bool HasFlagValue(string flag)
|
||||
{
|
||||
if(flags.ContainsKey(flag))
|
||||
return true;
|
||||
if(!skipsuper && (baseclass != null))
|
||||
return baseclass.HasFlagValue(flag);
|
||||
if(flags.ContainsKey(flag)) return true;
|
||||
if(!skipsuper && (baseclass != null)) return baseclass.HasFlagValue(flag);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -536,10 +523,8 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
/// </summary>
|
||||
public bool GetFlagValue(string flag, bool defaultvalue)
|
||||
{
|
||||
if(flags.ContainsKey(flag))
|
||||
return flags[flag];
|
||||
if(!skipsuper && (baseclass != null))
|
||||
return baseclass.GetFlagValue(flag, defaultvalue);
|
||||
if(flags.ContainsKey(flag)) return flags[flag];
|
||||
if(!skipsuper && (baseclass != null)) return baseclass.GetFlagValue(flag, defaultvalue);
|
||||
return defaultvalue;
|
||||
}
|
||||
|
||||
|
@ -548,10 +533,8 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
/// </summary>
|
||||
public bool HasState(string statename)
|
||||
{
|
||||
if(states.ContainsKey(statename))
|
||||
return true;
|
||||
if(!skipsuper && (baseclass != null))
|
||||
return baseclass.HasState(statename);
|
||||
if(states.ContainsKey(statename)) return true;
|
||||
if(!skipsuper && (baseclass != null)) return baseclass.HasState(statename);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -560,10 +543,8 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
/// </summary>
|
||||
public StateStructure GetState(string statename)
|
||||
{
|
||||
if(states.ContainsKey(statename))
|
||||
return states[statename];
|
||||
if(!skipsuper && (baseclass != null))
|
||||
return baseclass.GetState(statename);
|
||||
if(states.ContainsKey(statename)) return states[statename];
|
||||
if(!skipsuper && (baseclass != null)) return baseclass.GetState(statename);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -734,7 +715,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
if(!string.IsNullOrEmpty(result))
|
||||
{
|
||||
if (voxels.ContainsKey(result)) return result;
|
||||
if(voxels.ContainsKey(result)) return result;
|
||||
|
||||
// The sprite name may be incomplete. Find an existing sprite with direction.
|
||||
foreach(string postfix in SPRITE_POSTFIXES)
|
||||
|
|
|
@ -119,42 +119,56 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
if(!string.IsNullOrEmpty(objdeclaration))
|
||||
{
|
||||
objdeclaration = objdeclaration.ToLowerInvariant();
|
||||
if(objdeclaration == "actor")
|
||||
switch(objdeclaration)
|
||||
{
|
||||
// Read actor structure
|
||||
ActorStructure actor = new ActorStructure(this);
|
||||
if(this.HasError) break;
|
||||
|
||||
// Add the actor
|
||||
archivedactors[actor.ClassName.ToLowerInvariant()] = actor;
|
||||
if(actor.CheckActorSupported())
|
||||
actors[actor.ClassName.ToLowerInvariant()] = actor;
|
||||
|
||||
// Replace an actor?
|
||||
if(actor.ReplacesClass != null)
|
||||
case "actor":
|
||||
{
|
||||
if(GetArchivedActorByName(actor.ReplacesClass) != null)
|
||||
archivedactors[actor.ReplacesClass.ToLowerInvariant()] = actor;
|
||||
else
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Unable to find the DECORATE class '" + actor.ReplacesClass + "' to replace, while parsing '" + actor.ClassName + "'");
|
||||
|
||||
// Read actor structure
|
||||
ActorStructure actor = new ActorStructure(this);
|
||||
if(this.HasError) return false;
|
||||
|
||||
// Add the actor
|
||||
archivedactors[actor.ClassName.ToLowerInvariant()] = actor;
|
||||
if(actor.CheckActorSupported())
|
||||
actors[actor.ClassName.ToLowerInvariant()] = actor;
|
||||
|
||||
// Replace an actor?
|
||||
if(actor.ReplacesClass != null)
|
||||
{
|
||||
if(GetActorByName(actor.ReplacesClass) != null)
|
||||
if(GetArchivedActorByName(actor.ReplacesClass) != null)
|
||||
archivedactors[actor.ReplacesClass.ToLowerInvariant()] = actor;
|
||||
else
|
||||
LogWarning("Unable to find '" + actor.ReplacesClass + "' class to replace, while parsing '" + actor.ClassName + "'");
|
||||
|
||||
if(actor.CheckActorSupported() && GetActorByName(actor.ReplacesClass) != null)
|
||||
actors[actor.ReplacesClass.ToLowerInvariant()] = actor;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(objdeclaration == "#include")
|
||||
{
|
||||
// Include a file
|
||||
SkipWhitespace(true);
|
||||
string filename = ReadToken();
|
||||
if(!string.IsNullOrEmpty(filename))
|
||||
break;
|
||||
|
||||
case "#include":
|
||||
{
|
||||
// Include a file
|
||||
SkipWhitespace(true);
|
||||
string filename = 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;
|
||||
}
|
||||
|
||||
// Callback to parse this file now
|
||||
if(OnInclude != null) OnInclude(this, filename);
|
||||
|
||||
|
@ -162,50 +176,48 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
datastream = localstream;
|
||||
datareader = localreader;
|
||||
sourcename = localsourcename;
|
||||
if(HasError) break;
|
||||
if(this.HasError) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportError("Expected file name to include");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if((objdeclaration == "const") || (objdeclaration == "native") || (objdeclaration == "enum"))
|
||||
{
|
||||
// We don't need this, ignore up to the first next ;
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
string t = ReadToken();
|
||||
if(string.IsNullOrEmpty(t) || t == ";") break;
|
||||
}
|
||||
}
|
||||
else if(objdeclaration == "$gzdb_skip") //mxd
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown structure!
|
||||
// Best we can do now is just find the first { and then
|
||||
// follow the scopes until the matching } is found
|
||||
string token2;
|
||||
do
|
||||
|
||||
case "enum":
|
||||
case "native":
|
||||
case "const":
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
string t = ReadToken();
|
||||
if(string.IsNullOrEmpty(t) || t == ";") break;
|
||||
}
|
||||
break;
|
||||
|
||||
case "$gzdb_skip": break;
|
||||
|
||||
default:
|
||||
{
|
||||
if(!SkipWhitespace(true)) break;
|
||||
token2 = ReadToken();
|
||||
if(string.IsNullOrEmpty(token2)) break;
|
||||
// Unknown structure!
|
||||
// Best we can do now is just find the first { and then
|
||||
// follow the scopes until the matching } is found
|
||||
string token2;
|
||||
do
|
||||
{
|
||||
if(!SkipWhitespace(true)) break;
|
||||
token2 = ReadToken();
|
||||
if(string.IsNullOrEmpty(token2)) break;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -224,10 +236,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
public ActorStructure GetActorByName(string name)
|
||||
{
|
||||
name = name.ToLowerInvariant();
|
||||
if(actors.ContainsKey(name))
|
||||
return actors[name];
|
||||
else
|
||||
return null;
|
||||
return actors.ContainsKey(name) ? actors[name] : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -235,12 +244,8 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
/// </summary>
|
||||
public ActorStructure GetActorByDoomEdNum(int doomednum)
|
||||
{
|
||||
ICollection<ActorStructure> collection = actors.Values;
|
||||
foreach(ActorStructure a in collection)
|
||||
{
|
||||
if(a.DoomEdNum == doomednum)
|
||||
return a;
|
||||
}
|
||||
foreach(ActorStructure a in actors.Values)
|
||||
if(a.DoomEdNum == doomednum) return a;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -251,6 +256,12 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
name = name.ToLowerInvariant();
|
||||
return (archivedactors.ContainsKey(name) ? archivedactors[name] : null);
|
||||
}
|
||||
|
||||
//mxd
|
||||
protected override string GetLanguageType()
|
||||
{
|
||||
return "DECORATE";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
// First token is the class name
|
||||
parser.SkipWhitespace(true);
|
||||
name = parser.StripTokenQuotes(parser.ReadToken());
|
||||
name = parser.StripTokenQuotes(parser.ReadToken(false)); //mxd. Don't skip newline
|
||||
if(string.IsNullOrEmpty(name))
|
||||
{
|
||||
parser.ReportError("Expected patch name");
|
||||
|
@ -163,36 +163,36 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
break;
|
||||
|
||||
case "rotate":
|
||||
if (!ReadTokenInt(parser, token, out rotation)) return;
|
||||
if(!ReadTokenInt(parser, token, out rotation)) return;
|
||||
rotation = rotation % 360; //Coalesce multiples
|
||||
if (rotation < 0) rotation += 360; //Force positive
|
||||
if(rotation < 0) rotation += 360; //Force positive
|
||||
|
||||
if (rotation != 0 && rotation != 90 && rotation != 180 && rotation != 270)
|
||||
if(rotation != 0 && rotation != 90 && rotation != 180 && rotation != 270)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "Got unsupported rotation (" + rotation + ") in patch " + name);
|
||||
parser.LogWarning("Got unsupported rotation (" + rotation + ") in patch '" + name + "'");
|
||||
rotation = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case "style": //mxd
|
||||
string s;
|
||||
if (!ReadTokenString(parser, token, out s)) return;
|
||||
if(!ReadTokenString(parser, token, out s)) return;
|
||||
int index = Array.IndexOf(renderStyles, s.ToLowerInvariant());
|
||||
renderStyle = index == -1 ? TexturePathRenderStyle.Copy : (TexturePathRenderStyle) index;
|
||||
break;
|
||||
|
||||
case "blend": //mxd
|
||||
int val;
|
||||
if (!ReadTokenColor(parser, token, out val)) return;
|
||||
if(!ReadTokenColor(parser, token, out val)) return;
|
||||
blendColor = PixelColor.FromInt(val);
|
||||
|
||||
parser.SkipWhitespace(false);
|
||||
token = parser.ReadToken();
|
||||
|
||||
if (token == ",") //read tint ammount
|
||||
if(token == ",") //read tint ammount
|
||||
{
|
||||
parser.SkipWhitespace(false);
|
||||
if (!ReadTokenFloat(parser, token, out tintAmmount)) return;
|
||||
if(!ReadTokenFloat(parser, token, out tintAmmount)) return;
|
||||
tintAmmount = General.Clamp(tintAmmount, 0.0f, 1.0f);
|
||||
blendStyle = TexturePathBlendStyle.Tint;
|
||||
}
|
||||
|
@ -278,6 +278,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
parser.ReportError("Expected a value for property '" + propertyname + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -306,7 +307,8 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
{
|
||||
parser.ReportError("Expected color value for property '" + propertyname + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
if(string.IsNullOrEmpty(name))
|
||||
{
|
||||
ReportError("Got empty sound environment name!");
|
||||
ReportError("Got empty 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("Failed to parse the first part of '" + name + "' sound environment ID");
|
||||
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("Failed to parse the second part of '" + name + "' sound environment ID");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
int combinedindex = combinedargs.IndexOf(combined);
|
||||
if(combinedindex != -1)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "'" + names[combinedindex] + "' and '" + name + "' sound environments share the same ID (" + arg1 + " " + arg2 + ")!");
|
||||
LogWarning("'" + names[combinedindex] + "' and '" + name + "' sound environments share the same ID (" + arg1 + " " + arg2 + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -84,7 +84,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
// Add to collections
|
||||
if(names.Contains(name))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "'" + name + "' sound environment is double-defined in '" + sourcefilename + "'!");
|
||||
LogWarning("'" + name + "' sound environment is double-defined in '" + sourcefilename + "'");
|
||||
int index = names.IndexOf(name);
|
||||
firstargs[index] = arg1;
|
||||
secondargs[index] = arg2;
|
||||
|
@ -119,5 +119,10 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override string GetLanguageType()
|
||||
{
|
||||
return "REVERBS";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,6 +86,11 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
return result;
|
||||
}
|
||||
|
||||
protected override string GetLanguageType()
|
||||
{
|
||||
return "SNDSEQ";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -32,9 +32,9 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
#region ================== Variables
|
||||
|
||||
// All we care about is the first sprite in the sequence
|
||||
private List<string> sprites;
|
||||
private StateGoto gotostate;
|
||||
private DecorateParser parser;
|
||||
private readonly List<string> sprites;
|
||||
private readonly StateGoto gotostate;
|
||||
private readonly DecorateParser parser;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -77,20 +77,21 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
else if(token == ":")
|
||||
{
|
||||
// Rewind so that this label can be read again
|
||||
parser.DataStream.Seek(-(lasttoken.Length + 1), SeekOrigin.Current);
|
||||
if(!string.IsNullOrEmpty(lasttoken))
|
||||
parser.DataStream.Seek(-(lasttoken.Length + 1), SeekOrigin.Current);
|
||||
|
||||
// Done here
|
||||
return;
|
||||
}
|
||||
//mxd. Start of inner scope?
|
||||
else if (token == "{")
|
||||
else if(token == "{")
|
||||
{
|
||||
int bracelevel = 1;
|
||||
while(!string.IsNullOrEmpty(token) && bracelevel > 0)
|
||||
{
|
||||
parser.SkipWhitespace(false);
|
||||
token = parser.ReadToken();
|
||||
switch (token)
|
||||
switch(token)
|
||||
{
|
||||
case "{": bracelevel++; break;
|
||||
case "}": bracelevel--; break;
|
||||
|
@ -143,7 +144,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
spritename = spritename.ToUpperInvariant();
|
||||
|
||||
// Ignore some odd ZDoom things
|
||||
if (!spritename.StartsWith("TNT1") && !spritename.StartsWith("----") && !spritename.Contains("#"))
|
||||
if(!spritename.StartsWith("TNT1") && !spritename.StartsWith("----") && !spritename.Contains("#"))
|
||||
sprites.Add(spritename);
|
||||
}
|
||||
|
||||
|
@ -202,10 +203,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
private string GetSprite(int index, List<StateStructure> prevstates)
|
||||
{
|
||||
// If we have sprite of our own, see if we can return this index
|
||||
if(index < sprites.Count)
|
||||
{
|
||||
return sprites[index];
|
||||
}
|
||||
if(index < sprites.Count) return sprites[index];
|
||||
|
||||
// Otherwise, continue searching where goto tells us to go
|
||||
if(gotostate != null)
|
||||
|
|
|
@ -84,20 +84,20 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
// There should be 3 tokens separated by 2 commas now:
|
||||
// Name, Width, Height
|
||||
|
||||
// First token is the class name
|
||||
// First token is the texture name
|
||||
parser.SkipWhitespace(true);
|
||||
name = parser.StripTokenQuotes(parser.ReadToken());
|
||||
name = parser.StripTokenQuotes(parser.ReadToken(false)); //mxd. Don't skip newline
|
||||
|
||||
//mxd. It can also be "optional" keyword.
|
||||
if(name.ToLowerInvariant() == "optional")
|
||||
{
|
||||
parser.SkipWhitespace(true);
|
||||
name = parser.StripTokenQuotes(parser.ReadToken());
|
||||
name = parser.StripTokenQuotes(parser.ReadToken(false)); //mxd. Don't skip newline
|
||||
}
|
||||
|
||||
if(string.IsNullOrEmpty(name))
|
||||
{
|
||||
parser.ReportError("Expected texture or sprite name");
|
||||
parser.ReportError("Expected " + typename + " name");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -153,14 +153,14 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
string token = parser.ReadToken();
|
||||
token = token.ToLowerInvariant();
|
||||
|
||||
switch (token)
|
||||
switch(token)
|
||||
{
|
||||
case "xscale":
|
||||
if (!ReadTokenFloat(parser, token, out xscale)) return;
|
||||
if(!ReadTokenFloat(parser, token, out xscale)) return;
|
||||
break;
|
||||
|
||||
case "yscale":
|
||||
if (!ReadTokenFloat(parser, token, out yscale)) return;
|
||||
if(!ReadTokenFloat(parser, token, out yscale)) return;
|
||||
break;
|
||||
|
||||
case "worldpanning":
|
||||
|
@ -169,25 +169,25 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
case "offset":
|
||||
// Read x offset
|
||||
if (!ReadTokenInt(parser, token, out xoffset)) return;
|
||||
if(!ReadTokenInt(parser, token, out xoffset)) return;
|
||||
|
||||
// Now we should find a comma
|
||||
parser.SkipWhitespace(true);
|
||||
tokenstr = parser.ReadToken();
|
||||
if (tokenstr != ",")
|
||||
if(tokenstr != ",")
|
||||
{
|
||||
parser.ReportError("Expected a comma");
|
||||
return;
|
||||
}
|
||||
|
||||
// Read y offset
|
||||
if (!ReadTokenInt(parser, token, out yoffset)) return;
|
||||
if(!ReadTokenInt(parser, token, out yoffset)) return;
|
||||
break;
|
||||
|
||||
case "patch":
|
||||
// Read patch structure
|
||||
PatchStructure pt = new PatchStructure(parser);
|
||||
if (parser.HasError) break;
|
||||
if(parser.HasError) break;
|
||||
|
||||
//mxd. Let's ignore TNT1A0
|
||||
if(pt.Name == IGNORE_SPRITE) break;
|
||||
|
|
|
@ -46,9 +46,9 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
#region ================== Properties
|
||||
|
||||
public ICollection<TextureStructure> Textures { get { return textures.Values; } }
|
||||
public ICollection<TextureStructure> Flats { get { return flats.Values; } }
|
||||
public ICollection<TextureStructure> Sprites { get { return sprites.Values; } }
|
||||
public IEnumerable<TextureStructure> Textures { get { return textures.Values; } }
|
||||
public IEnumerable<TextureStructure> Flats { get { return flats.Values; } }
|
||||
public IEnumerable<TextureStructure> Sprites { get { return sprites.Values; } }
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -89,104 +89,139 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
if(!string.IsNullOrEmpty(objdeclaration))
|
||||
{
|
||||
objdeclaration = objdeclaration.ToLowerInvariant();
|
||||
if(objdeclaration == "texture")
|
||||
switch(objdeclaration)
|
||||
{
|
||||
// Read texture structure
|
||||
TextureStructure tx = new TextureStructure(this, "texture", virtualpath);
|
||||
if(this.HasError) break;
|
||||
case "texture":
|
||||
{
|
||||
// Read texture structure
|
||||
TextureStructure tx = new TextureStructure(this, "texture", virtualpath);
|
||||
if(this.HasError) return false;
|
||||
|
||||
// if a limit for the texture name length is set make sure that it's not exceeded
|
||||
if(tx.Name.Length > General.Map.Config.MaxTextureNameLength)
|
||||
{
|
||||
ReportError("Texture name \"" + tx.Name + "\" too long. Texture names must have a length of " + General.Map.Config.MaxTextureNameLength + " characters or less");
|
||||
return false;
|
||||
}
|
||||
|
||||
//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.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// if a limit for the texture name length is set make sure that it's not exceeded
|
||||
if(tx.Name.Length > General.Map.Config.MaxTextureNameLength)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Texture name \"" + tx.Name + "\" too long. Texture names must have a length of " + General.Map.Config.MaxTextureNameLength + " characters or less");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add the texture
|
||||
textures[tx.Name] = tx;
|
||||
if(!General.Map.Config.MixTexturesFlats) flats[tx.Name] = tx; //mxd. If MixTexturesFlats is set, textures and flats will be mixed in DataManager anyway
|
||||
}
|
||||
}
|
||||
else if(objdeclaration == "sprite")
|
||||
{
|
||||
// Read sprite structure
|
||||
TextureStructure tx = new TextureStructure(this, "sprite", virtualpath);
|
||||
if(this.HasError) break;
|
||||
break;
|
||||
|
||||
// if a limit for the sprite name length is set make sure that it's not exceeded
|
||||
if(tx.Name.Length > DataManager.CLASIC_IMAGE_NAME_LENGTH)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Sprite name \"" + tx.Name + "\" too long. Sprite names must have a length of " + DataManager.CLASIC_IMAGE_NAME_LENGTH + " characters or less");
|
||||
}
|
||||
else
|
||||
case "sprite":
|
||||
{
|
||||
// Read sprite structure
|
||||
TextureStructure tx = new TextureStructure(this, "sprite", virtualpath);
|
||||
if(this.HasError) return false;
|
||||
|
||||
// if a limit for the sprite name length is set make sure that it's not exceeded
|
||||
if(tx.Name.Length > DataManager.CLASIC_IMAGE_NAME_LENGTH)
|
||||
{
|
||||
ReportError("Sprite name \"" + tx.Name + "\" too long. Sprite names must have a length of " + DataManager.CLASIC_IMAGE_NAME_LENGTH + " characters or less");
|
||||
return false;
|
||||
}
|
||||
|
||||
//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.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the sprite
|
||||
sprites[tx.Name] = tx;
|
||||
}
|
||||
}
|
||||
else if(objdeclaration == "walltexture")
|
||||
{
|
||||
// Read walltexture structure
|
||||
TextureStructure tx = new TextureStructure(this, "walltexture", virtualpath);
|
||||
if(this.HasError) break;
|
||||
break;
|
||||
|
||||
// if a limit for the walltexture name length is set make sure that it's not exceeded
|
||||
if(tx.Name.Length > General.Map.Config.MaxTextureNameLength)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "WallTexture name \"" + tx.Name + "\" too long. WallTexture names must have a length of " + General.Map.Config.MaxTextureNameLength + " characters or less");
|
||||
}
|
||||
else
|
||||
case "walltexture":
|
||||
{
|
||||
// Read walltexture structure
|
||||
TextureStructure tx = new TextureStructure(this, "walltexture", virtualpath);
|
||||
if(this.HasError) return false;
|
||||
|
||||
// if a limit for the walltexture name length is set make sure that it's not exceeded
|
||||
if(tx.Name.Length > General.Map.Config.MaxTextureNameLength)
|
||||
{
|
||||
ReportError("WallTexture name \"" + tx.Name + "\" too long. WallTexture names must have a length of " + General.Map.Config.MaxTextureNameLength + " characters or less");
|
||||
return false;
|
||||
}
|
||||
|
||||
//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.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the walltexture
|
||||
if(!textures.ContainsKey(tx.Name) || (textures[tx.Name].TypeName != "texture"))
|
||||
textures[tx.Name] = tx;
|
||||
}
|
||||
}
|
||||
else if(objdeclaration == "flat")
|
||||
{
|
||||
// Read flat structure
|
||||
TextureStructure tx = new TextureStructure(this, "flat", virtualpath);
|
||||
if(this.HasError) break;
|
||||
break;
|
||||
|
||||
// if a limit for the flat name length is set make sure that it's not exceeded
|
||||
if(tx.Name.Length > General.Map.Config.MaxTextureNameLength)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Flat name \"" + tx.Name + "\" too long. Flat names must have a length of " + General.Map.Config.MaxTextureNameLength + " characters or less");
|
||||
}
|
||||
else
|
||||
case "flat":
|
||||
{
|
||||
// Read flat structure
|
||||
TextureStructure tx = new TextureStructure(this, "flat", virtualpath);
|
||||
if(this.HasError) return false;
|
||||
|
||||
// if a limit for the flat name length is set make sure that it's not exceeded
|
||||
if(tx.Name.Length > General.Map.Config.MaxTextureNameLength)
|
||||
{
|
||||
ReportError("Flat name \"" + tx.Name + "\" too long. Flat names must have a length of " + General.Map.Config.MaxTextureNameLength + " characters or less");
|
||||
return false;
|
||||
}
|
||||
|
||||
//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.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the flat
|
||||
if(!flats.ContainsKey(tx.Name) || (flats[tx.Name].TypeName != "texture"))
|
||||
flats[tx.Name] = tx;
|
||||
}
|
||||
}
|
||||
else if(objdeclaration == "$gzdb_skip") //mxd
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown structure!
|
||||
// Best we can do now is just find the first { and then
|
||||
// follow the scopes until the matching } is found
|
||||
string token2;
|
||||
do
|
||||
|
||||
case "$gzdb_skip": break;
|
||||
|
||||
default:
|
||||
{
|
||||
if(!SkipWhitespace(true)) break;
|
||||
token2 = ReadToken();
|
||||
if(string.IsNullOrEmpty(token2)) break;
|
||||
// Unknown structure!
|
||||
// Best we can do now is just find the first { and then
|
||||
// follow the scopes until the matching } is found
|
||||
string token2;
|
||||
do
|
||||
{
|
||||
if(!SkipWhitespace(true)) break;
|
||||
token2 = ReadToken();
|
||||
if(string.IsNullOrEmpty(token2)) break;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -194,6 +229,12 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
// Return true when no errors occurred
|
||||
return (ErrorDescription == null);
|
||||
}
|
||||
|
||||
//mxd
|
||||
protected override string GetLanguageType()
|
||||
{
|
||||
return "TEXTURES";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -49,17 +49,15 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
if(string.IsNullOrEmpty(token))
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Unable to get voxel model name from '" + sourcefilename + "', line " + GetCurrentLineNumber());
|
||||
spriteNames.Clear();
|
||||
continue;
|
||||
ReportError("Expected voxel name");
|
||||
return false;
|
||||
}
|
||||
|
||||
modelName = StripTokenQuotes(token).ToLowerInvariant();
|
||||
}
|
||||
else if(token == "{") //read the settings
|
||||
{
|
||||
ModelData mde = new ModelData();
|
||||
mde.IsVoxel = true;
|
||||
ModelData mde = new ModelData { IsVoxel = true };
|
||||
float scale = 1.0f;
|
||||
float angleoffset = 0;
|
||||
|
||||
|
@ -109,15 +107,16 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
token = StripTokenQuotes(ReadToken());
|
||||
if(token != "=")
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + sourcefilename + " at line " + GetCurrentLineNumber() + ": expected '=', but got '" + token + "'");
|
||||
break;
|
||||
ReportError("expected '=', but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if(!ReadSignedFloat(token, ref angleoffset))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + sourcefilename + " at line " + GetCurrentLineNumber() + ": expected AngleOffset value, but got '" + token + "'");
|
||||
ReportError("expected AngleOffset value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(token == "scale")
|
||||
|
@ -127,17 +126,19 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
token = StripTokenQuotes(ReadToken());
|
||||
if(token != "=")
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + sourcefilename + " at line " + GetCurrentLineNumber() + ": expected '=', but got '" + token + "'");
|
||||
break;
|
||||
ReportError("expected '=', but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
token = StripTokenQuotes(ReadToken());
|
||||
if(!ReadSignedFloat(token, ref scale))
|
||||
{
|
||||
// Not numeric!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Error in " + sourcefilename + " at line " + GetCurrentLineNumber() + ": expected Scale value, but got '" + token + "'");
|
||||
ReportError("expected Scale value, but got '" + token + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
prevToken = token.ToUpperInvariant();
|
||||
}
|
||||
}
|
||||
|
@ -151,5 +152,10 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
return entries.Count > 0;
|
||||
}
|
||||
|
||||
protected override string GetLanguageType()
|
||||
{
|
||||
return "VOXELDEF";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
private int errorline;
|
||||
private string errordesc;
|
||||
private string errorsource;
|
||||
private long prevstreamposition; //mxd. Text stream position storted before poerforming ReadToken.
|
||||
private long prevstreamposition; //mxd. Text stream position storted before performing ReadToken.
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -213,7 +213,8 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
// This reads a token (all sequential non-whitespace characters or a single character)
|
||||
// Returns null when the end of the stream has been reached
|
||||
protected internal string ReadToken()
|
||||
protected internal string ReadToken() { return ReadToken(true); } //mxd. Added "multiline" param
|
||||
protected internal string ReadToken(bool multiline)
|
||||
{
|
||||
//mxd. Return empty string when the end of the stream has been reached
|
||||
if(datastream.Position == datastream.Length) return string.Empty;
|
||||
|
@ -228,6 +229,14 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
char c = (char)datareader.ReadByte();
|
||||
while(!IsWhitespace(c) || quotedstring || IsSpecialToken(c))
|
||||
{
|
||||
//mxd. Break at newline?
|
||||
if(!multiline && c == '\r')
|
||||
{
|
||||
// Go one character back so line number is correct
|
||||
datastream.Seek(-1, SeekOrigin.Current);
|
||||
return token;
|
||||
}
|
||||
|
||||
// Special token?
|
||||
if(!quotedstring && IsSpecialToken(c))
|
||||
{
|
||||
|
@ -418,7 +427,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
|
||||
if(token != expectedtoken)
|
||||
{
|
||||
if(reporterror) General.ErrorLogger.Add(ErrorType.Error, "Error in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": 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);
|
||||
|
@ -469,20 +478,39 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
errorsource = sourcename;
|
||||
}
|
||||
|
||||
//mxd. This reports a warning
|
||||
protected internal void ReportWarning(string message)
|
||||
//mxd. This adds a warning to the ErrorLogger
|
||||
protected internal void LogWarning(string message)
|
||||
{
|
||||
// Add a warning
|
||||
General.ErrorLogger.Add(ErrorType.Warning, "DECORATE warning in '" + sourcename + "', line " + GetCurrentLineNumber() + ". " + message + ".");
|
||||
int errline = GetCurrentLineNumber();
|
||||
General.ErrorLogger.Add(ErrorType.Warning, GetLanguageType() + " warning in '" + sourcename
|
||||
+ (errline != CompilerError.NO_LINE_NUMBER ? "', line " + (errline + 1) : "'") + ". "
|
||||
+ message + ".");
|
||||
}
|
||||
|
||||
//mxd. This adds an error to the ErrorLogger
|
||||
public void LogError()
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, GetLanguageType() + " error in '" + errorsource
|
||||
+ (errorline != CompilerError.NO_LINE_NUMBER ? "', line " + (errorline + 1) : "'") + ". "
|
||||
+ errordesc + ".");
|
||||
}
|
||||
|
||||
//mxd
|
||||
internal void ClearError()
|
||||
{
|
||||
errorline = 0;
|
||||
errordesc = null;
|
||||
errorsource = null;
|
||||
}
|
||||
|
||||
//mxd
|
||||
protected internal int GetCurrentLineNumber()
|
||||
protected int GetCurrentLineNumber()
|
||||
{
|
||||
long pos = datastream.Position;
|
||||
long finishpos = Math.Min(prevstreamposition, pos);
|
||||
long readpos = 0;
|
||||
int linenumber = 0;
|
||||
int linenumber = -1;
|
||||
|
||||
// Find the line on which we found this error
|
||||
datastream.Seek(0, SeekOrigin.Begin);
|
||||
|
@ -498,9 +526,12 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
// Return to original position
|
||||
datastream.Seek(pos, SeekOrigin.Begin);
|
||||
|
||||
return linenumber;
|
||||
return Math.Max(linenumber, 0);
|
||||
}
|
||||
|
||||
|
||||
//mxd. Language type
|
||||
protected abstract string GetLanguageType();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue