mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-12-02 16:42:30 +00:00
330 lines
18 KiB
C#
330 lines
18 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using SlimDX;
|
|
using CodeImp.DoomBuilder.ZDoom;
|
|
using CodeImp.DoomBuilder.GZBuilder.Data;
|
|
|
|
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|
public sealed class MapinfoParser : ZDTextParser {
|
|
|
|
private MapInfo mapInfo;
|
|
public MapInfo MapInfo { get { return mapInfo; } }
|
|
|
|
public bool Parse(Stream stream, string sourcefilename, string mapName) {
|
|
base.Parse(stream, sourcefilename);
|
|
|
|
mapName = mapName.ToLowerInvariant();
|
|
mapInfo = new MapInfo();
|
|
|
|
while (SkipWhitespace(true)) {
|
|
string token = ReadToken();
|
|
if (token != null) {
|
|
token = token.ToLowerInvariant();
|
|
|
|
if (parseBlock(token, mapName))
|
|
break;
|
|
}
|
|
}
|
|
|
|
//check values
|
|
if (mapInfo.FadeColor != null && (mapInfo.FadeColor.Red > 0 || mapInfo.FadeColor.Green > 0 || mapInfo.FadeColor.Blue > 0))
|
|
mapInfo.HasFadeColor = true;
|
|
|
|
if (mapInfo.OutsideFogColor != null && (mapInfo.OutsideFogColor.Red > 0 || mapInfo.OutsideFogColor.Green > 0 || mapInfo.OutsideFogColor.Blue > 0))
|
|
mapInfo.HasOutsideFogColor = true;
|
|
|
|
//Cannot fail here
|
|
return true;
|
|
}
|
|
|
|
//returns true if parsing is finished
|
|
private bool parseBlock(string token, string mapName) {
|
|
string curBlockName;
|
|
mapName = mapName.ToLowerInvariant();
|
|
|
|
if (token == "map" || token == "defaultmap" || token == "adddefaultmap") {
|
|
curBlockName = token;
|
|
|
|
if (token == "map") { //check map name
|
|
//get map name
|
|
SkipWhitespace(true);
|
|
token = ReadToken().ToLowerInvariant();
|
|
|
|
if (token != mapName)
|
|
return false; //not finished, search for next "map", "defaultmap" or "adddefaultmap" block
|
|
} else if (token == "defaultmap") {
|
|
//reset MapInfo
|
|
mapInfo = new MapInfo();
|
|
}
|
|
|
|
//search for required keys
|
|
while (SkipWhitespace(true)) {
|
|
token = ReadToken().ToLowerInvariant();
|
|
|
|
//sky1 or sky2
|
|
if (token == "sky1" || token == "sky2") {
|
|
//Form1.Trace("Got sky " + token);
|
|
|
|
string skyType = token;
|
|
SkipWhitespace(true);
|
|
token = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
|
|
|
//new format
|
|
if (token == "=") {
|
|
SkipWhitespace(true);
|
|
|
|
//should be sky texture name
|
|
token = StripTokenQuotes(ReadToken());
|
|
bool gotComma = (token.IndexOf(",") != -1);
|
|
if (gotComma)
|
|
token = token.Replace(",", "");
|
|
string skyTexture = StripTokenQuotes(token).ToLowerInvariant();
|
|
|
|
if (!string.IsNullOrEmpty(skyTexture)) {
|
|
if (skyType == "sky1")
|
|
mapInfo.Sky1 = skyTexture;
|
|
else
|
|
mapInfo.Sky2 = skyTexture;
|
|
|
|
//check if we have scrollspeed
|
|
SkipWhitespace(true);
|
|
token = StripTokenQuotes(ReadToken());
|
|
|
|
if (!gotComma && token == ",") {
|
|
gotComma = true;
|
|
SkipWhitespace(true);
|
|
token = ReadToken();
|
|
}
|
|
|
|
if (gotComma) {
|
|
float scrollSpeed = 0;
|
|
|
|
if (!ReadSignedFloat(token, ref scrollSpeed)) {
|
|
// Not numeric!
|
|
General.ErrorLogger.Add(ErrorType.Error, "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;
|
|
}
|
|
|
|
if (skyType == "sky1")
|
|
mapInfo.Sky1ScrollSpeed = scrollSpeed;
|
|
else
|
|
mapInfo.Sky2ScrollSpeed = scrollSpeed;
|
|
} else {
|
|
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
|
}
|
|
} 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.");
|
|
}
|
|
//old format
|
|
} else {
|
|
//token should be sky1/2 name
|
|
if (!string.IsNullOrEmpty(token)) {
|
|
if (skyType == "sky1")
|
|
mapInfo.Sky1 = token;
|
|
else
|
|
mapInfo.Sky2 = token;
|
|
|
|
//try to read scroll speed
|
|
SkipWhitespace(true);
|
|
token = StripTokenQuotes(ReadToken());
|
|
|
|
float scrollSpeed = 0;
|
|
if (!ReadSignedFloat(token, ref scrollSpeed)) {
|
|
// Not numeric!
|
|
General.ErrorLogger.Add(ErrorType.Error, "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;
|
|
}
|
|
|
|
if (skyType == "sky1")
|
|
mapInfo.Sky1ScrollSpeed = scrollSpeed;
|
|
else
|
|
mapInfo.Sky2ScrollSpeed = scrollSpeed;
|
|
|
|
} 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.");
|
|
}
|
|
}
|
|
//fade or outsidefog
|
|
} else if (token == "fade" || token == "outsidefog") {
|
|
string fadeType = token;
|
|
SkipWhitespace(true);
|
|
token = StripTokenQuotes(ReadToken()).ToLowerInvariant();
|
|
|
|
//new format
|
|
if (token == "=") {
|
|
SkipWhitespace(true);
|
|
|
|
//red color value or color name...
|
|
token = ReadToken();
|
|
string colorVal = StripTokenQuotes(token).ToLowerInvariant();
|
|
if (!string.IsNullOrEmpty(colorVal)) {
|
|
Color4 color = new Color4();
|
|
//color.Alpha = 1.0f;
|
|
|
|
//is it color name?
|
|
if (getColorByName(colorVal, ref color)) {
|
|
if (fadeType == "fade")
|
|
mapInfo.FadeColor = color;
|
|
else
|
|
mapInfo.OutsideFogColor = color;
|
|
} else { //no, it's not
|
|
//try to get color values
|
|
int r, g, b;
|
|
string[] parts = colorVal.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
if (parts.Length != 3) {
|
|
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " color values, but got '" + token + "'");
|
|
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
|
continue;
|
|
}
|
|
|
|
if (!int.TryParse(parts[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out r)) {
|
|
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " red value, but got '" + parts[0] + "'");
|
|
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
|
continue;
|
|
}
|
|
if (!int.TryParse(parts[1], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out g)) {
|
|
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " green value, but got '" + parts[1] + "'");
|
|
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
|
continue;
|
|
}
|
|
if (!int.TryParse(parts[2], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out b)) {
|
|
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " blue value, but got '" + parts[2] + "'");
|
|
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
|
continue;
|
|
}
|
|
|
|
color.Red = (float)r / 255;
|
|
color.Green = (float)g / 255;
|
|
color.Blue = (float)b / 255;
|
|
|
|
if (fadeType == "fade")
|
|
mapInfo.FadeColor = color;
|
|
else
|
|
mapInfo.OutsideFogColor = color;
|
|
}
|
|
} 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
|
|
}
|
|
|
|
//old format
|
|
} else {
|
|
//token should contain red color value or color name...
|
|
if (!string.IsNullOrEmpty(token)) {
|
|
int r, g, b;
|
|
Color4 color = new Color4();
|
|
|
|
if (!int.TryParse(token, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out r)) {
|
|
//Not numeric! Maybe it's a color name?
|
|
if (getColorByName(token, ref color)) {
|
|
if (fadeType == "fade")
|
|
mapInfo.FadeColor = color;
|
|
else
|
|
mapInfo.OutsideFogColor = color;
|
|
} else {
|
|
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
|
}
|
|
continue;
|
|
}
|
|
|
|
SkipWhitespace(true);
|
|
token = ReadToken();
|
|
|
|
//should be color, let's continue parsing it.
|
|
if (!int.TryParse(token, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out g)) {
|
|
// Not numeric!
|
|
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " green value, but got '" + token + "'");
|
|
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
|
continue;
|
|
}
|
|
|
|
SkipWhitespace(true);
|
|
token = StripTokenQuotes(ReadToken());
|
|
|
|
if (!int.TryParse(token, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out b)) {
|
|
// Not numeric!
|
|
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " blue value, but got '" + token + "'");
|
|
datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again
|
|
continue;
|
|
}
|
|
|
|
color.Red = (float)r / 255;
|
|
color.Green = (float)g / 255;
|
|
color.Blue = (float)b / 255;
|
|
|
|
if (fadeType == "fade")
|
|
mapInfo.FadeColor = color;
|
|
else
|
|
mapInfo.OutsideFogColor = color;
|
|
|
|
} 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
|
|
}
|
|
}
|
|
//vertwallshade or horizwallshade
|
|
} else if (token == "vertwallshade" || token == "horizwallshade") {
|
|
string shadeType = token;
|
|
SkipWhitespace(true);
|
|
token = StripTokenQuotes(ReadToken());
|
|
|
|
//new format
|
|
if (token == "=") {
|
|
SkipWhitespace(true);
|
|
token = StripTokenQuotes(ReadToken());
|
|
}
|
|
|
|
int val = 0;
|
|
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;
|
|
}
|
|
|
|
if (shadeType == "vertwallshade")
|
|
mapInfo.VertWallShade = General.Clamp(val, -255, 255);
|
|
else
|
|
mapInfo.HorizWallShade = General.Clamp(val, -255, 255);
|
|
//doublesky
|
|
} else if (token == "doublesky") {
|
|
mapInfo.DoubleSky = true;
|
|
//evenlighting
|
|
} else if (token == "evenlighting") {
|
|
mapInfo.EvenLighting = true;
|
|
//smoothlighting
|
|
} else if (token == "smoothlighting") {
|
|
mapInfo.SmoothLighting = true;
|
|
//block end
|
|
} else if (token == "}") {
|
|
if (curBlockName == "map") {
|
|
return true; //we are done here
|
|
} else {
|
|
return parseBlock(token, mapName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool getColorByName(string name, ref Color4 color) {
|
|
if (name == "black")
|
|
return true;
|
|
|
|
Color c = Color.FromName(name); //should be similar to C++ color name detection, I suppose
|
|
if (c.IsKnownColor) {
|
|
color = new Color4(c);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|