UltimateZoneBuilder/Source/Core/ZDoom/VoxeldefParser.cs
MaxED ec9c3a71f9 Added: preview sprites are now generated from voxels. Those are used as previews and when model rendering is disabled.
Fixed: voxel support logic was outdated, which in some cases resulted in voxels not being loaded and in some weird behaviour when trying to change pitch/roll of associated things.
Updated sprites lookup logic. Now it correctly handles sprites named like NNNNA0B0.
Fixed: in some cases DECORATE parser was unable to correctly detect sprite name & frame(s) block.
Updated ZDoom_ACS.cfg.
Updated ZDoom_DECORATE.cfg.
2016-07-11 22:13:43 +00:00

138 lines
3.7 KiB
C#

#region ================== Namespaces
using System;
using System.Collections.Generic;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.GZBuilder.Data;
using SlimDX;
#endregion
namespace CodeImp.DoomBuilder.ZDoom
{
public sealed class VoxeldefParser : ZDTextParser
{
internal override ScriptType ScriptType { get { return ScriptType.VOXELDEF; } }
private Dictionary<string, ModelData> entries; //sprite name, entry
internal Dictionary<string, ModelData> Entries { get { return entries; } }
public override bool Parse(TextResourceData data, bool clearerrors)
{
entries = new Dictionary<string, ModelData>(StringComparer.Ordinal);
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
List<string> spriteNames = new List<string>();
string modelName = string.Empty;
string prevToken = string.Empty;
// Continue until at the end of the stream
while(SkipWhitespace(true))
{
string token = ReadToken().ToLowerInvariant();
if(string.IsNullOrEmpty(token)) continue;
if(token == ",") //previous token was a sprite name
{
if(!string.IsNullOrEmpty(prevToken) && !spriteNames.Contains(prevToken)) spriteNames.Add(prevToken);
prevToken = StripQuotes(token).ToUpperInvariant();
}
else if(token == "=") //next token should be a voxel model name
{
if(!string.IsNullOrEmpty(prevToken) && !spriteNames.Contains(prevToken)) spriteNames.Add(prevToken);
SkipWhitespace(true);
token = ReadToken();
if(string.IsNullOrEmpty(token))
{
ReportError("Expected voxel name");
return false;
}
modelName = StripQuotes(token).ToUpperInvariant();
}
else if(token == "{") //read the settings
{
ModelData mde = new ModelData { IsVoxel = true };
float scale = 1.0f;
while(SkipWhitespace(true))
{
token = ReadToken().ToLowerInvariant();
if(string.IsNullOrEmpty(token)) continue;
if(token == "}") //store data
{
if(!string.IsNullOrEmpty(modelName) && spriteNames.Count > 0)
{
mde.ModelNames.Add(modelName);
mde.SetTransform(Matrix.RotationZ(Angle2D.DegToRad(mde.AngleOffset)), Matrix.Identity, new Vector3(scale));
foreach(string s in spriteNames)
{
//TODO: is this the proper behaviour?
entries[s] = mde;
}
//reset local data
modelName = string.Empty;
prevToken = string.Empty;
spriteNames.Clear();
}
break;
}
else if(token == "overridepalette")
{
mde.OverridePalette = true;
}
else if(token == "angleoffset")
{
if(!NextTokenIs("=")) return false;
token = ReadToken();
if(!ReadSignedFloat(token, ref mde.AngleOffset))
{
// Not numeric!
ReportError("Expected AngleOffset value, but got \"" + token + "\"");
return false;
}
}
else if(token == "scale")
{
if(!NextTokenIs("=")) return false;
token = ReadToken();
if(!ReadSignedFloat(token, ref scale))
{
// Not numeric!
ReportError("Expected Scale value, but got \"" + token + "\"");
return false;
}
}
prevToken = StripQuotes(token).ToUpperInvariant();
}
}
else
{
prevToken = StripQuotes(token).ToUpperInvariant();
}
}
return entries.Count > 0;
}
}
}