2014-12-03 23:15:26 +00:00
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
2014-02-26 14:11:06 +00:00
using System.Collections.Generic ;
2014-01-03 10:33:45 +00:00
using System.IO ;
using CodeImp.DoomBuilder.Geometry ;
using CodeImp.DoomBuilder.GZBuilder.Data ;
using SlimDX ;
2014-12-03 23:15:26 +00:00
#endregion
2014-01-03 10:33:45 +00:00
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 ; } }
2014-12-03 23:15:26 +00:00
public override bool Parse ( Stream stream , string sourcefilename )
{
2014-01-03 10:33:45 +00:00
base . Parse ( stream , sourcefilename ) ;
2014-02-26 14:11:06 +00:00
entries = new Dictionary < string , ModelData > ( StringComparer . Ordinal ) ;
2014-01-03 10:33:45 +00:00
string prevToken = string . Empty ;
List < string > spriteNames = new List < string > ( ) ;
string modelName = string . Empty ;
// Continue until at the end of the stream
2014-12-03 23:15:26 +00:00
while ( SkipWhitespace ( true ) )
{
2014-01-03 10:33:45 +00:00
string token = ReadToken ( ) ;
2015-06-18 19:45:39 +00:00
if ( ! string . IsNullOrEmpty ( token ) )
2014-12-03 23:15:26 +00:00
{
2014-01-03 10:33:45 +00:00
token = StripTokenQuotes ( token ) . ToLowerInvariant ( ) ;
2014-12-03 23:15:26 +00:00
if ( token = = "," ) //previous token was a sprite name
{
2015-03-21 19:41:54 +00:00
if ( ! string . IsNullOrEmpty ( prevToken ) & & ! spriteNames . Contains ( prevToken ) ) spriteNames . Add ( prevToken ) ;
2014-01-03 10:33:45 +00:00
prevToken = token . ToUpperInvariant ( ) ;
2014-12-03 23:15:26 +00:00
}
else if ( token = = "=" ) //next token should be a voxel model name
{
2015-03-21 19:41:54 +00:00
if ( ! string . IsNullOrEmpty ( prevToken ) & & ! spriteNames . Contains ( prevToken ) ) spriteNames . Add ( prevToken ) ;
2014-01-03 10:33:45 +00:00
SkipWhitespace ( true ) ;
token = ReadToken ( ) ;
2014-12-03 23:15:26 +00:00
if ( string . IsNullOrEmpty ( token ) )
{
2014-01-03 10:33:45 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Unable to get voxel model name from '" + sourcefilename + "', line " + GetCurrentLineNumber ( ) ) ;
spriteNames . Clear ( ) ;
continue ;
}
modelName = StripTokenQuotes ( token ) . ToLowerInvariant ( ) ;
2014-12-03 23:15:26 +00:00
}
else if ( token = = "{" ) //read the settings
{
2014-12-22 21:36:49 +00:00
ModelData mde = new ModelData ( ) ;
mde . IsVoxel = true ;
float scale = 1.0f ;
float angleoffset = 0 ;
2014-01-03 10:33:45 +00:00
2014-12-03 23:15:26 +00:00
while ( SkipWhitespace ( true ) )
{
2014-01-03 10:33:45 +00:00
token = ReadToken ( ) ;
2014-12-03 23:15:26 +00:00
if ( ! string . IsNullOrEmpty ( token ) )
{
2014-01-03 10:33:45 +00:00
token = StripTokenQuotes ( token ) . ToLowerInvariant ( ) ;
2014-12-03 23:15:26 +00:00
if ( token = = "}" ) //store data
{
if ( ! string . IsNullOrEmpty ( modelName ) & & spriteNames . Count > 0 )
{
2014-12-22 21:36:49 +00:00
mde . ModelNames . Add ( modelName ) ;
mde . SetTransform ( Matrix . RotationZ ( Angle2D . DegToRad ( angleoffset ) ) , Matrix . Identity , new Vector3 ( scale ) ) ;
2014-01-03 10:33:45 +00:00
2014-12-03 23:15:26 +00:00
foreach ( string s in spriteNames )
{
if ( entries . ContainsKey ( s ) ) //TODO: is this a proper behaviour?
{
2014-12-22 21:36:49 +00:00
entries [ s ] = mde ;
2014-12-03 23:15:26 +00:00
}
else
{
2014-12-22 21:36:49 +00:00
entries . Add ( s , mde ) ;
2014-01-03 10:33:45 +00:00
}
}
//reset local data
modelName = string . Empty ;
prevToken = string . Empty ;
spriteNames . Clear ( ) ;
}
break ;
2014-12-03 23:15:26 +00:00
}
else if ( token = = "overridepalette" )
{
2014-12-22 21:36:49 +00:00
mde . OverridePalette = true ;
2014-12-03 23:15:26 +00:00
}
else if ( token = = "angleoffset" )
{
2014-01-03 10:33:45 +00:00
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
2014-12-03 23:15:26 +00:00
if ( token ! = "=" )
{
2014-01-03 10:33:45 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in " + sourcefilename + " at line " + GetCurrentLineNumber ( ) + ": expected '=', but got '" + token + "'" ) ;
break ;
}
token = StripTokenQuotes ( ReadToken ( ) ) ;
2014-12-22 21:36:49 +00:00
if ( ! ReadSignedFloat ( token , ref angleoffset ) )
2014-12-03 23:15:26 +00:00
{
2014-01-03 10:33:45 +00:00
// Not numeric!
General . ErrorLogger . Add ( ErrorType . Error , "Error in " + sourcefilename + " at line " + GetCurrentLineNumber ( ) + ": expected AngleOffset value, but got '" + token + "'" ) ;
}
2014-12-03 23:15:26 +00:00
}
else if ( token = = "scale" )
{
2014-01-03 10:33:45 +00:00
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
2014-12-03 23:15:26 +00:00
if ( token ! = "=" )
{
2014-01-03 10:33:45 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in " + sourcefilename + " at line " + GetCurrentLineNumber ( ) + ": expected '=', but got '" + token + "'" ) ;
break ;
}
token = StripTokenQuotes ( ReadToken ( ) ) ;
2014-12-03 23:15:26 +00:00
if ( ! ReadSignedFloat ( token , ref scale ) )
{
2014-01-03 10:33:45 +00:00
// Not numeric!
General . ErrorLogger . Add ( ErrorType . Error , "Error in " + sourcefilename + " at line " + GetCurrentLineNumber ( ) + ": expected Scale value, but got '" + token + "'" ) ;
}
}
prevToken = token . ToUpperInvariant ( ) ;
}
}
2014-12-03 23:15:26 +00:00
}
else
{
2014-01-03 10:33:45 +00:00
prevToken = token . ToUpperInvariant ( ) ;
}
}
}
return entries . Count > 0 ;
}
}
}