2015-04-14 11:33:57 +00:00
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
using System.Drawing ;
2014-02-26 14:11:06 +00:00
using System.IO ;
2012-05-22 22:56:42 +00:00
using System.Collections.Generic ;
using System.Globalization ;
using CodeImp.DoomBuilder.ZDoom ;
2012-06-01 10:17:47 +00:00
using CodeImp.DoomBuilder.GZBuilder.Data ;
2015-04-14 11:33:57 +00:00
using CodeImp.DoomBuilder.Rendering ;
using CodeImp.DoomBuilder.IO ;
2012-05-22 22:56:42 +00:00
2015-04-14 11:33:57 +00:00
#endregion
2012-05-22 22:56:42 +00:00
2015-01-20 12:20:35 +00:00
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
{
2015-04-14 11:33:57 +00:00
internal sealed class GldefsParser : ZDTextParser
2015-01-20 12:20:35 +00:00
{
2015-04-14 11:33:57 +00:00
#region = = = = = = = = = = = = = = = = = = Structs
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
private const int DEFAULT_GLOW_HEIGHT = 64 ;
#endregion
#region = = = = = = = = = = = = = = = = = = Structs
2015-04-14 11:33:57 +00:00
private struct GldefsLightType
{
public const string POINT = "pointlight" ;
public const string PULSE = "pulselight" ;
public const string FLICKER = "flickerlight" ;
public const string FLICKER2 = "flickerlight2" ;
public const string SECTOR = "sectorlight" ;
public static readonly Dictionary < string , DynamicLightType > GLDEFS_TO_GZDOOM_LIGHT_TYPE = new Dictionary < string , DynamicLightType > ( StringComparer . Ordinal ) { { POINT , DynamicLightType . NORMAL } , { PULSE , DynamicLightType . PULSE } , { FLICKER , DynamicLightType . FLICKER } , { FLICKER2 , DynamicLightType . RANDOM } , { SECTOR , DynamicLightType . SECTOR } } ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Delegates
2012-06-01 10:17:47 +00:00
2013-09-11 09:47:53 +00:00
public delegate void IncludeDelegate ( GldefsParser parser , string includefile ) ;
public IncludeDelegate OnInclude ;
2012-06-01 10:17:47 +00:00
2015-04-14 11:33:57 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
2015-03-21 19:41:54 +00:00
private readonly Dictionary < string , DynamicLightData > lightsByName ; //LightName, light definition
private readonly Dictionary < string , string > objects ; //ClassName, LightName
2015-04-14 11:33:57 +00:00
private readonly Dictionary < long , GlowingFlatData > glowingflats ;
private readonly List < string > parsedlumps ;
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
2012-06-01 10:17:47 +00:00
2013-09-11 09:47:53 +00:00
public Dictionary < string , DynamicLightData > LightsByName { get { return lightsByName ; } }
public Dictionary < string , string > Objects { get { return objects ; } }
2015-04-14 11:33:57 +00:00
internal Dictionary < long , GlowingFlatData > GlowingFlats { get { return glowingflats ; } }
2012-06-01 10:17:47 +00:00
2015-04-14 11:33:57 +00:00
#endregion
2012-06-01 10:17:47 +00:00
2015-04-14 11:33:57 +00:00
#region = = = = = = = = = = = = = = = = = = Constructor
2013-09-11 09:47:53 +00:00
2014-12-03 23:15:26 +00:00
public GldefsParser ( )
{
2015-04-14 11:33:57 +00:00
// Syntax
whitespace = "\n \t\r\u00A0" ;
specialtokens = ",{}\n" ;
parsedlumps = new List < string > ( ) ;
2014-02-26 14:11:06 +00:00
lightsByName = new Dictionary < string , DynamicLightData > ( StringComparer . Ordinal ) ; //LightName, Light params
objects = new Dictionary < string , string > ( StringComparer . Ordinal ) ; //ClassName, LightName
2015-04-14 11:33:57 +00:00
glowingflats = new Dictionary < long , GlowingFlatData > ( ) ; // Texture name hash, Glowing Flat Data
2013-09-11 09:47:53 +00:00
}
2015-04-14 11:33:57 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Parsing
2014-12-03 23:15:26 +00:00
public override bool Parse ( Stream stream , string sourcefilename )
{
2013-09-11 09:47:53 +00:00
base . Parse ( stream , sourcefilename ) ;
2015-04-14 11:33:57 +00:00
if ( parsedlumps . IndexOf ( sourcefilename ) ! = - 1 )
2014-12-03 23:15:26 +00:00
{
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "already parsed '" + sourcefilename + "'. Check your #include directives!" ) ;
2013-09-11 09:47:53 +00:00
return false ;
}
2015-04-14 11:33:57 +00:00
parsedlumps . Add ( sourcefilename ) ;
2013-09-11 09:47:53 +00:00
// Keep local data
Stream localstream = datastream ;
string localsourcename = sourcename ;
BinaryReader localreader = datareader ;
// Continue until at the end of the stream
2014-12-03 23:15:26 +00:00
while ( SkipWhitespace ( true ) )
{
2013-09-11 09:47:53 +00:00
string token = ReadToken ( ) ;
2014-12-03 23:15:26 +00:00
if ( ! string . IsNullOrEmpty ( token ) )
{
2013-09-11 09:47:53 +00:00
token = StripTokenQuotes ( token . ToLowerInvariant ( ) ) ; //Quotes can be anywhere! ANYWHERE!!! And GZDoom will still parse data correctly
//got light structure
2014-12-03 23:15:26 +00:00
if ( token = = GldefsLightType . POINT | | token = = GldefsLightType . PULSE | | token = = GldefsLightType . FLICKER
| | token = = GldefsLightType . FLICKER2 | | token = = GldefsLightType . SECTOR )
{
2013-09-11 09:47:53 +00:00
bool gotErrors = false ;
string lightType = token ;
DynamicLightData light = new DynamicLightData ( ) ;
light . Type = GldefsLightType . GLDEFS_TO_GZDOOM_LIGHT_TYPE [ lightType ] ;
//find classname
SkipWhitespace ( true ) ;
string lightName = StripTokenQuotes ( ReadToken ( ) ) . ToLowerInvariant ( ) ;
2014-12-03 23:15:26 +00:00
if ( ! string . IsNullOrEmpty ( lightName ) )
{
2013-09-11 09:47:53 +00:00
//now find opening brace
2015-04-14 11:33:57 +00:00
if ( ! NextTokenIs ( "{" ) ) continue ;
2013-09-11 09:47:53 +00:00
//read gldefs light structure
2014-12-03 23:15:26 +00:00
while ( SkipWhitespace ( true ) )
{
2013-09-11 09:47:53 +00:00
token = ReadToken ( ) ;
2014-12-03 23:15:26 +00:00
if ( ! string . IsNullOrEmpty ( token ) )
{
2013-09-11 09:47:53 +00:00
token = token . ToLowerInvariant ( ) ;
2012-06-01 10:17:47 +00:00
//color
2014-12-03 23:15:26 +00:00
if ( token = = "color" )
{
2013-09-11 09:47:53 +00:00
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
2014-12-03 23:15:26 +00:00
if ( ! float . TryParse ( token , NumberStyles . Float , CultureInfo . InvariantCulture , out light . Color . Red ) )
{
2013-09-11 09:47:53 +00:00
// Not numeric!
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected Red Color value, but got '" + token + "'." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
2014-12-03 23:15:26 +00:00
if ( ! float . TryParse ( token , NumberStyles . Float , CultureInfo . InvariantCulture , out light . Color . Green ) )
{
2013-09-11 09:47:53 +00:00
// Not numeric!
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected Green Color value, but got '" + token + "'." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
2014-12-03 23:15:26 +00:00
if ( ! float . TryParse ( token , NumberStyles . Float , CultureInfo . InvariantCulture , out light . Color . Blue ) )
{
2013-09-11 09:47:53 +00:00
// Not numeric!
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected Blue Color value, but got '" + token + "'." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
2012-06-01 10:17:47 +00:00
//size
2014-12-03 23:15:26 +00:00
}
else if ( token = = "size" )
{
if ( lightType ! = GldefsLightType . SECTOR )
{
2013-09-11 09:47:53 +00:00
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
2014-12-03 23:15:26 +00:00
if ( ! int . TryParse ( token , NumberStyles . Integer , CultureInfo . InvariantCulture , out light . PrimaryRadius ) )
{
2013-09-11 09:47:53 +00:00
// Not numeric!
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected Size value, but got '" + token + "'." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
light . PrimaryRadius * = 2 ;
2014-12-03 23:15:26 +00:00
}
else
{
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": '" + token + "' is not valid property for " + lightType + "." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
2012-06-01 10:17:47 +00:00
//offset
2014-12-03 23:15:26 +00:00
}
else if ( token = = "offset" )
{
2013-09-11 09:47:53 +00:00
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
2014-12-03 23:15:26 +00:00
if ( ! ReadSignedFloat ( token , ref light . Offset . X ) )
{
2013-09-11 09:47:53 +00:00
// Not numeric!
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected Offset X value, but got '" + token + "'." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
2014-12-03 23:15:26 +00:00
if ( ! ReadSignedFloat ( token , ref light . Offset . Z ) )
{
2013-09-11 09:47:53 +00:00
// Not numeric!
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected Offset Y value, but got '" + token + "'" ) ;
gotErrors = true ;
break ;
}
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
2014-12-03 23:15:26 +00:00
if ( ! ReadSignedFloat ( token , ref light . Offset . Y ) )
{
2013-09-11 09:47:53 +00:00
// Not numeric!
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected Offset Z value, but got '" + token + "'." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
2012-06-01 10:17:47 +00:00
//subtractive
2014-12-03 23:15:26 +00:00
}
else if ( token = = "subtractive" )
{
2013-09-11 09:47:53 +00:00
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
int i ;
2014-12-03 23:15:26 +00:00
if ( ! int . TryParse ( token , NumberStyles . Integer , CultureInfo . InvariantCulture , out i ) )
{
2013-09-11 09:47:53 +00:00
// Not numeric!
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected Subtractive value, but got '" + token + "'." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
light . Subtractive = i = = 1 ;
2012-06-01 10:17:47 +00:00
//dontlightself
2014-12-03 23:15:26 +00:00
}
else if ( token = = "dontlightself" )
{
2013-09-11 09:47:53 +00:00
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
int i ;
2014-12-03 23:15:26 +00:00
if ( ! int . TryParse ( token , NumberStyles . Integer , CultureInfo . InvariantCulture , out i ) )
{
2013-09-11 09:47:53 +00:00
// Not numeric!
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected Dontlightself value, but got '" + token + "'." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
light . DontLightSelf = ( i = = 1 ) ;
2012-06-01 10:17:47 +00:00
//interval
2014-12-03 23:15:26 +00:00
}
else if ( token = = "interval" )
{
if ( lightType = = GldefsLightType . PULSE | | lightType = = GldefsLightType . FLICKER2 )
{
2013-09-11 09:47:53 +00:00
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
float interval ;
2014-12-03 23:15:26 +00:00
if ( ! float . TryParse ( token , NumberStyles . Float , CultureInfo . InvariantCulture , out interval ) )
{
2013-09-11 09:47:53 +00:00
// Not numeric!
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected Interval value, but got '" + token + "'." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
2014-12-03 23:15:26 +00:00
if ( interval = = 0 )
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Warning , "Warning in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": Interval value should be greater than zero." ) ;
2014-03-11 09:44:39 +00:00
2013-09-11 09:47:53 +00:00
//I wrote logic for dynamic lights animation first, so here I modify gldefs settings to fit in existing logic
2014-12-03 23:15:26 +00:00
if ( lightType = = GldefsLightType . PULSE )
{
2013-09-11 09:47:53 +00:00
light . Interval = ( int ) ( interval * 35 ) ; //measured in tics (35 per second) in PointLightPulse, measured in seconds in gldefs' PulseLight
2014-12-03 23:15:26 +00:00
}
else //FLICKER2. Seems like PointLightFlickerRandom to me
{
2013-09-11 09:47:53 +00:00
light . Interval = ( int ) ( interval * 350 ) ; //0.1 is one second for FlickerLight2
}
2014-12-03 23:15:26 +00:00
}
else
{
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": '" + token + "' is not valid property for " + lightType + "." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
2012-06-01 10:17:47 +00:00
//secondarysize
2014-12-03 23:15:26 +00:00
}
else if ( token = = "secondarysize" )
{
if ( lightType = = GldefsLightType . PULSE | | lightType = = GldefsLightType . FLICKER | | lightType = = GldefsLightType . FLICKER2 )
{
2013-09-11 09:47:53 +00:00
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
2014-12-03 23:15:26 +00:00
if ( ! int . TryParse ( token , NumberStyles . Integer , CultureInfo . InvariantCulture , out light . SecondaryRadius ) )
{
2013-09-11 09:47:53 +00:00
// Not numeric!
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected SecondarySize value, but got '" + token + "'." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
light . SecondaryRadius * = 2 ;
2014-12-03 23:15:26 +00:00
}
else
{
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": '" + token + "' is not valid property for " + lightType + "." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
2012-06-01 10:17:47 +00:00
//chance
2014-12-03 23:15:26 +00:00
}
else if ( token = = "chance" )
{
if ( lightType = = GldefsLightType . FLICKER )
{
2013-09-11 09:47:53 +00:00
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
float chance ;
2014-12-03 23:15:26 +00:00
if ( ! float . TryParse ( token , NumberStyles . Float , CultureInfo . InvariantCulture , out chance ) )
{
2013-09-11 09:47:53 +00:00
// Not numeric!
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected Chance value, but got '" + token + "'." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
//transforming from 0.0 .. 1.0 to 0 .. 359 to fit in existing logic
light . Interval = ( int ) ( chance * 359.0f ) ;
2014-12-03 23:15:26 +00:00
}
else
{
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": '" + token + "' is not valid property for " + lightType + "." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
2012-06-01 10:17:47 +00:00
//scale
2014-12-03 23:15:26 +00:00
}
else if ( token = = "scale" )
{
if ( lightType = = GldefsLightType . SECTOR )
{
2013-09-11 09:47:53 +00:00
SkipWhitespace ( true ) ;
token = StripTokenQuotes ( ReadToken ( ) ) ;
float scale ;
2014-12-03 23:15:26 +00:00
if ( ! float . TryParse ( token , NumberStyles . Float , CultureInfo . InvariantCulture , out scale ) )
{
2013-09-11 09:47:53 +00:00
// Not numeric!
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected Scale value, but got '" + token + "'." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
2014-12-03 23:15:26 +00:00
if ( scale > 1.0f )
{
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": scale must be in 0.0 - 1.0 range, but is " + scale + "." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
//sector light doesn't have animation, so we will store it's size in Interval
//transforming from 0.0 .. 1.0 to 0 .. 10 to preserve value.
light . Interval = ( int ) ( scale * 10.0f ) ;
2014-12-03 23:15:26 +00:00
}
else
{
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": '" + token + "' is not valid property for " + lightType + "." ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
break ;
}
2014-12-03 23:15:26 +00:00
}
//end of structure
else if ( token = = "}" )
{
if ( ! gotErrors )
{
2013-09-11 09:47:53 +00:00
//general checks
2014-12-03 23:15:26 +00:00
if ( light . Color . Red = = 0.0f & & light . Color . Green = = 0.0f & & light . Color . Blue = = 0.0f )
{
2013-12-20 09:24:43 +00:00
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!" ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
}
//light-type specific checks
2014-12-03 23:15:26 +00:00
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 ;
2013-09-11 09:47:53 +00:00
}
2014-12-03 23:15:26 +00:00
if ( light . Type = = DynamicLightType . FLICKER | | light . Type = = DynamicLightType . PULSE | | light . Type = = DynamicLightType . RANDOM )
{
if ( light . PrimaryRadius = = 0 & & light . SecondaryRadius = = 0 )
{
2013-12-20 09:24:43 +00:00
General . ErrorLogger . Add ( ErrorType . Warning , "'" + sourcefilename + "', line " + GetCurrentLineNumber ( ) + ": 'Size' and 'SecondarySize' are 0. This light won't be shown in GZDoom!" ) ;
2013-09-11 09:47:53 +00:00
gotErrors = true ;
}
}
//offset it slightly to avoid shading glitches
2014-12-03 23:15:26 +00:00
if ( light . Offset . Z = = 0.0f ) light . Offset . Z = 0.1f ;
2013-09-11 09:47:53 +00:00
2014-12-03 23:15:26 +00:00
if ( ! gotErrors )
{
if ( lightsByName . ContainsKey ( lightName ) )
2013-09-11 09:47:53 +00:00
lightsByName [ lightName ] = light ;
2014-12-03 23:15:26 +00:00
else
2013-09-11 09:47:53 +00:00
lightsByName . Add ( lightName , light ) ;
}
}
break ; //break out of this parsing loop
}
}
}
}
2014-12-03 23:15:26 +00:00
}
else if ( token = = "object" )
{
2013-09-11 09:47:53 +00:00
SkipWhitespace ( true ) ;
//read object class
string objectClass = StripTokenQuotes ( ReadToken ( ) ) . ToLowerInvariant ( ) ;
2014-12-03 23:15:26 +00:00
if ( ! string . IsNullOrEmpty ( objectClass ) )
{
2013-09-11 09:47:53 +00:00
//now find opening brace
2015-04-14 11:33:57 +00:00
if ( ! NextTokenIs ( "{" ) ) continue ;
2013-09-11 09:47:53 +00:00
int bracesCount = 1 ;
bool foundLight = false ;
2014-03-11 12:35:26 +00:00
bool foundFrame = false ;
2013-09-11 09:47:53 +00:00
//read frames structure
2014-12-03 23:15:26 +00:00
while ( SkipWhitespace ( true ) )
{
2013-09-11 09:47:53 +00:00
token = ReadToken ( ) ;
2014-12-03 23:15:26 +00:00
if ( ! string . IsNullOrEmpty ( token ) )
{
2013-09-11 09:47:53 +00:00
token = StripTokenQuotes ( token ) . ToLowerInvariant ( ) ;
2014-12-03 23:15:26 +00:00
if ( ! foundLight & & ! foundFrame & & token = = "frame" )
{
2014-03-11 12:35:26 +00:00
SkipWhitespace ( true ) ;
token = ReadToken ( ) . ToLowerInvariant ( ) ; //should be frame name
//use this frame if it's 4 characters long or it's the first frame
foundFrame = ( token . Length = = 4 | | ( token . Length > 4 & & token [ 4 ] = = 'a' ) ) ;
2014-12-03 23:15:26 +00:00
}
else if ( ! foundLight & & foundFrame & & token = = "light" ) //just use first light and be done with it
{
2013-09-11 09:47:53 +00:00
SkipWhitespace ( true ) ;
token = ReadToken ( ) . ToLowerInvariant ( ) ; //should be light name
2014-12-03 23:15:26 +00:00
if ( ! string . IsNullOrEmpty ( token ) )
{
if ( lightsByName . ContainsKey ( token ) )
{
2013-09-11 09:47:53 +00:00
if ( objects . ContainsKey ( objectClass ) )
objects [ objectClass ] = token ;
else
objects . Add ( objectClass , token ) ;
foundLight = true ;
2014-12-03 23:15:26 +00:00
}
else
{
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Warning , "Light declaration not found for light '" + token + "' ('" + sourcefilename + "', line " + GetCurrentLineNumber ( ) + ")." ) ;
2013-09-11 09:47:53 +00:00
}
}
2014-12-03 23:15:26 +00:00
}
else if ( token = = "{" ) //continue in this loop until object structure ends
{
2013-09-11 09:47:53 +00:00
bracesCount + + ;
2014-12-03 23:15:26 +00:00
}
else if ( token = = "}" )
{
if ( - - bracesCount < 1 ) break ; //This was Cave Johnson. And we are done here.
2013-09-11 09:47:53 +00:00
}
}
}
}
2015-04-14 11:33:57 +00:00
}
//Glowing flats block start
else if ( token = = "glow" )
{
// Next sould be opening brace
if ( ! NextTokenIs ( "{" ) ) continue ;
// Parse inner blocks
while ( SkipWhitespace ( true ) )
{
token = ReadToken ( ) . ToLowerInvariant ( ) ;
if ( token = = "flats" | | token = = "walls" )
{
// Next sould be opening brace
if ( ! NextTokenIs ( "{" ) ) break ;
// Read flat names
while ( SkipWhitespace ( true ) )
{
token = ReadToken ( ) ;
if ( token = = "}" ) break ;
// Add glow data
glowingflats [ General . Map . Data . GetFullLongFlatName ( Lump . MakeLongName ( token , General . Map . Options . UseLongTextureNames ) ) ] = new GlowingFlatData {
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
Height = DEFAULT_GLOW_HEIGHT * 2 ,
2015-04-14 11:33:57 +00:00
Fullbright = true ,
Color = new PixelColor ( 255 , 255 , 255 , 255 ) ,
CalculateTextureColor = true
} ;
}
}
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
// GLOOME subtractive flats
else if ( token = = "subflats" | | token = = "subwalls" )
{
// Next sould be opening brace
if ( ! NextTokenIs ( "{" ) ) break ;
// Read flat names
while ( SkipWhitespace ( true ) )
{
token = ReadToken ( ) ;
if ( token = = "}" ) break ;
// Add glow data
glowingflats [ General . Map . Data . GetFullLongFlatName ( Lump . MakeLongName ( token , General . Map . Options . UseLongTextureNames ) ) ] = new GlowingFlatData {
Height = DEFAULT_GLOW_HEIGHT * 2 ,
Fullblack = true ,
Subtractive = true ,
Color = new PixelColor ( 255 , 0 , 0 , 0 ) ,
CalculateTextureColor = false
} ;
}
}
else if ( token = = "texture" | | token = = "subtexture" )
2015-04-14 11:33:57 +00:00
{
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
int color ;
int glowheight = DEFAULT_GLOW_HEIGHT ;
bool subtractivetexture = ( token = = "subtexture" ) ;
2015-04-14 11:33:57 +00:00
string texturename = StripTokenQuotes ( ReadToken ( ) ) ;
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
2015-04-14 11:33:57 +00:00
if ( string . IsNullOrEmpty ( texturename ) )
{
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected a texture name." ) ;
break ;
}
// Now we should find a comma
if ( ! NextTokenIs ( "," ) ) break ;
// Next is color
SkipWhitespace ( true ) ;
token = ReadToken ( ) ;
if ( ! int . TryParse ( token , NumberStyles . HexNumber , CultureInfo . InvariantCulture , out color ) )
{
//probably it's a color name?
Color c = Color . FromName ( token ) ; //should be similar to C++ color name detection, I suppose
if ( c . IsKnownColor )
{
color = PixelColor . FromColor ( c ) . ToInt ( ) ;
}
else
{
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": expected glow color value, but got '" + token + "'." ) ;
break ;
}
}
// The glow data is valid at thispoint. Let's get texture hash
long texturehash = General . Map . Data . GetFullLongFlatName ( Lump . MakeLongName ( texturename , General . Map . Options . UseLongTextureNames ) ) ;
// Now we can find a comma
if ( ! NextTokenIs ( "," , false ) )
{
// Add glow data
glowingflats [ texturehash ] = new GlowingFlatData {
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
Height = glowheight * 2 ,
Subtractive = subtractivetexture ,
2015-04-14 11:33:57 +00:00
Color = PixelColor . FromInt ( color ) . WithAlpha ( 255 ) ,
CalculateTextureColor = false
} ;
continue ;
}
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
// Can be glow height
SkipWhitespace ( true ) ;
token = ReadToken ( ) ;
2015-04-14 11:33:57 +00:00
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
int h ;
if ( int . TryParse ( token , NumberStyles . Integer , CultureInfo . InvariantCulture , out h ) )
2015-04-14 11:33:57 +00:00
{
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
// Can't pass glowheight directly cause TryParse will unconditionally set it to 0
glowheight = h ;
// Now we can find a comma
if ( ! NextTokenIs ( "," , false ) )
{
// Add glow data
glowingflats [ texturehash ] = new GlowingFlatData {
Height = glowheight * 2 ,
Subtractive = subtractivetexture ,
Color = PixelColor . FromInt ( color ) . WithAlpha ( 255 ) ,
CalculateTextureColor = false
} ;
continue ;
}
2015-04-14 11:33:57 +00:00
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
// Read the flag
SkipWhitespace ( true ) ;
token = ReadToken ( ) . ToLowerInvariant ( ) ;
2015-04-14 11:33:57 +00:00
}
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
// Next is "fullbright" or "fullblack" flag
bool fullbright = ( token = = "fullbright" ) ;
bool fullblack = ( ! subtractivetexture & & token = = "fullblack" ) ;
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 ;
}
2015-04-14 11:33:57 +00:00
// Add glow data
glowingflats [ texturehash ] = new GlowingFlatData {
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
Height = glowheight * 2 ,
2015-04-14 11:33:57 +00:00
Fullbright = fullbright ,
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
Fullblack = fullblack ,
Subtractive = subtractivetexture ,
2015-04-14 11:33:57 +00:00
Color = PixelColor . FromInt ( color ) . WithAlpha ( 255 ) ,
CalculateTextureColor = false
} ;
}
}
// Now find closing brace
while ( SkipWhitespace ( true ) )
{
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
token = ReadToken ( ) ;
if ( string . IsNullOrEmpty ( token ) | | token = = "}" ) break ;
2015-04-14 11:33:57 +00:00
}
}
2014-12-03 23:15:26 +00:00
else if ( token = = "#include" )
{
2013-09-11 09:47:53 +00:00
SkipWhitespace ( true ) ;
string includeLump = StripTokenQuotes ( ReadToken ( ) ) . ToLowerInvariant ( ) ;
2014-12-03 23:15:26 +00:00
if ( ! string . IsNullOrEmpty ( includeLump ) )
{
2013-09-11 09:47:53 +00:00
// 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 ;
2014-12-03 23:15:26 +00:00
}
else
{
2015-04-14 11:33:57 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber ( ) + ": got #include directive with missing or incorrect path: '" + includeLump + "'." ) ;
2013-09-11 09:47:53 +00:00
}
2014-12-03 23:15:26 +00:00
}
2015-03-04 20:05:54 +00:00
else if ( token = = "$gzdb_skip" ) //mxd
{
break ;
}
2014-12-03 23:15:26 +00:00
else
{
2013-09-11 09:47:53 +00:00
// Unknown structure!
string token2 ;
2014-12-03 23:15:26 +00:00
do
{
2013-09-11 09:47:53 +00:00
if ( ! SkipWhitespace ( true ) ) break ;
token2 = ReadToken ( ) ;
2015-06-18 19:45:39 +00:00
if ( string . IsNullOrEmpty ( token2 ) ) break ;
2013-09-11 09:47:53 +00:00
}
while ( token2 ! = "{" ) ;
int scopelevel = 1 ;
2014-12-03 23:15:26 +00:00
do
{
2013-09-11 09:47:53 +00:00
if ( ! SkipWhitespace ( true ) ) break ;
token2 = ReadToken ( ) ;
2015-06-18 19:45:39 +00:00
if ( string . IsNullOrEmpty ( token2 ) ) break ;
2013-09-11 09:47:53 +00:00
if ( token2 = = "{" ) scopelevel + + ;
if ( token2 = = "}" ) scopelevel - - ;
}
while ( scopelevel > 0 ) ;
}
}
}
2013-12-20 09:24:43 +00:00
return objects . Count > 0 ;
2013-09-11 09:47:53 +00:00
}
2015-01-20 12:20:35 +00:00
2015-04-14 11:33:57 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Methods
2015-01-20 12:20:35 +00:00
internal void ClearIncludesList ( )
{
2015-04-14 11:33:57 +00:00
parsedlumps . Clear ( ) ;
2015-01-20 12:20:35 +00:00
}
2015-04-14 11:33:57 +00:00
#endregion
2013-09-11 09:47:53 +00:00
}
2012-06-01 10:17:47 +00:00
}