UltimateZoneBuilder/Source/Core/ZDoom/VoxeldefParser.cs
MaxED deb43343bb Visual mode: "Fit Textures" action can now fit textures across multiple selected surfaces. A number of times to repeat a texture can now be specified.
Visual mode: removed "Fit Texture's Width" and "Fit Texture's Height" actions.
Visual mode: "Auto-align texture offsets" actions were incorrectly aligning double-sided middle walls in some cases.
Visual mode: "Auto-align texture offsets" actions now align non-wrapped double-sided middle walls to vertical offset closest to their initial vertical offset.
Visual mode: middle parts of double-sided walls were ignored when Shift-selecting walls.
Nodebuilders/Game configurations: GL nodes definitions were missing from game configurations.
Nodebuilders/Game configurations: "~MAP" wildcard can now be a part of a lump name. 
Nodebuilders: GL nodes were not properly handled by the editor.
Main Window: the window is now moved into the view when stored position is ouside of screen bounds. 
Classic and Visual modes: changing thing pitch was ignored in some cases.
Visual mode: raising and lowering a thing with "+SPAWNCEILING" flag now works the same way as when raising/lowering a regular thing.
Visual mode: using "Raise/Lower Floor/Ceiling to adjacent sector" actions on a thing with "+SPAWNCEILING" flag now works the same way as when using them on a regular thing.  
Rendering: even more fixes to MODELDEF and UDMF properties-related model rendering logic.
Internal, ResourceListEditor: rewritten resource validation check in a more OOP-ish way.
Configurations: fixed an infinite loop crash when a file was trying to include() itself.
UDMF thing flags: added Skill 6-8 to the flags list (because there are thing filters for these).
ZDoom_ACS.cfg: added definitions for SetTeleFog and SwapTeleFog.
ZDoom_DECORATE.cfg: added definitions for A_SetTeleFog and A_SwapTeleFog.
Updated ZDoom ACC.
Updated documentation.
2014-12-22 21:36:49 +00:00

161 lines
4.6 KiB
C#

#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.IO;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.GZBuilder.Data;
using SlimDX;
#endregion
namespace CodeImp.DoomBuilder.ZDoom
{
public sealed class VoxeldefParser : ZDTextParser
{
private Dictionary<string, ModelData> entries; //sprite name, entry
internal Dictionary<string, ModelData> Entries { get { return entries; } }
public override bool Parse(Stream stream, string sourcefilename)
{
base.Parse(stream, sourcefilename);
entries = new Dictionary<string, ModelData>(StringComparer.Ordinal);
string prevToken = string.Empty;
List<string> spriteNames = new List<string>();
string modelName = string.Empty;
// Continue until at the end of the stream
while(SkipWhitespace(true))
{
string token = ReadToken();
if(token != null)
{
token = StripTokenQuotes(token).ToLowerInvariant();
if(token == ",") //previous token was a sprite name
{
if(!string.IsNullOrEmpty(prevToken))
{
if(!spriteNames.Contains(prevToken)) spriteNames.Add(prevToken);
}
prevToken = token.ToUpperInvariant();
}
else if(token == "=") //next token should be a voxel model name
{
if(!string.IsNullOrEmpty(prevToken))
{
if(!spriteNames.Contains(prevToken)) spriteNames.Add(prevToken);
}
SkipWhitespace(true);
token = ReadToken();
if(string.IsNullOrEmpty(token))
{
General.ErrorLogger.Add(ErrorType.Error, "Unable to get voxel model name from '" + sourcefilename + "', line " + GetCurrentLineNumber());
spriteNames.Clear();
continue;
}
modelName = StripTokenQuotes(token).ToLowerInvariant();
}
else if(token == "{") //read the settings
{
ModelData mde = new ModelData();
mde.IsVoxel = true;
float scale = 1.0f;
float angleoffset = 0;
while(SkipWhitespace(true))
{
token = ReadToken();
if(!string.IsNullOrEmpty(token))
{
token = StripTokenQuotes(token).ToLowerInvariant();
if(token == "}") //store data
{
if(!string.IsNullOrEmpty(modelName) && spriteNames.Count > 0)
{
mde.ModelNames.Add(modelName);
mde.SetTransform(Matrix.RotationZ(Angle2D.DegToRad(angleoffset)), Matrix.Identity, new Vector3(scale));
foreach(string s in spriteNames)
{
if(entries.ContainsKey(s)) //TODO: is this a proper behaviour?
{
entries[s] = mde;
}
else
{
entries.Add(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")
{
SkipWhitespace(true);
token = StripTokenQuotes(ReadToken());
if(token != "=")
{
General.ErrorLogger.Add(ErrorType.Error, "Error in " + sourcefilename + " at line " + GetCurrentLineNumber() + ": expected '=', but got '" + token + "'");
break;
}
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 + "'");
}
}
else if(token == "scale")
{
SkipWhitespace(true);
token = StripTokenQuotes(ReadToken());
if(token != "=")
{
General.ErrorLogger.Add(ErrorType.Error, "Error in " + sourcefilename + " at line " + GetCurrentLineNumber() + ": expected '=', but got '" + token + "'");
break;
}
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 + "'");
}
}
prevToken = token.ToUpperInvariant();
}
}
}
else
{
prevToken = token.ToUpperInvariant();
}
}
}
return entries.Count > 0;
}
}
}