mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-12-19 08:31:01 +00:00
16b97e1c83
Dynamic lights defined in GLDEFS are now rendered in Visual modes (currently only one light per Thing is supported). Several values from (Z)MAPINFO are now used in Visual modes. Added "Reload GLDEFS", "Reload (Z)MAPINFO" and "Reload MODELDEF" menu options (in "Tools" section). MODELDEF parser now checks which model(s) is/are used in first frame. Dynamic lights are now created with more meaningful default parameters. Added errors and warnings indicator to main window.
348 lines
20 KiB
C#
348 lines
20 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
using SlimDX;
|
|
using SlimDX.Direct3D9;
|
|
|
|
using CodeImp.DoomBuilder.ZDoom;
|
|
using CodeImp.DoomBuilder.GZBuilder.Data;
|
|
|
|
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
|
|
public 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 (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scrollSpeed)) {
|
|
// Not numeric!
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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 (!ReadSignedFloat(token, ref scrollSpeed)) {
|
|
// Not numeric!
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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 (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scrollSpeed)) {
|
|
// Not numeric!
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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 (!ReadSignedFloat(token, ref scrollSpeed)) {
|
|
// Not numeric!
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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) {
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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)) {
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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)) {
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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)) {
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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 {
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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!
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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!
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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 {
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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!
|
|
GZBuilder.GZGeneral.LogAndTraceWarning("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;
|
|
}
|
|
}
|
|
}
|