mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-18 14:31:50 +00:00
TEXTURES support: both patch Blend syntaxes are now supported (previously only "Blend <string color>[,<float alpha>]" was supported).
Added X11R6RGB parser. Rewritten parts of unhandled exceptions handling to reduce the chance of additional exceptions happening after the first one.
This commit is contained in:
parent
1703af1c82
commit
adadca9d99
20 changed files with 605 additions and 390 deletions
|
@ -3372,7 +3372,7 @@ zdoom
|
|||
{
|
||||
1 = "Disable light effects";
|
||||
2 = "Restrict light inside";
|
||||
4 = "Fog effect (GZDoom) / Fade effect (ZDoom)";
|
||||
4 = "Fog effect (GZDoom only)";
|
||||
8 = "Ignore bottom height";
|
||||
16 = "Use upper texture";
|
||||
32 = "Use lower texture";
|
||||
|
|
|
@ -1021,6 +1021,7 @@
|
|||
<Compile Include="ZDoom\TexturesParser.cs" />
|
||||
<Compile Include="ZDoom\TextureStructure.cs" />
|
||||
<Compile Include="ZDoom\VoxeldefParser.cs" />
|
||||
<Compile Include="ZDoom\X11R6RGBParser.cs" />
|
||||
<Compile Include="ZDoom\ZDTextParser.cs" />
|
||||
<Compile Include="ZDoom\DecorateParser.cs" />
|
||||
<Compile Include="ZDoom\StateStructure.cs" />
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace CodeImp.DoomBuilder.Config
|
|||
ANIMDEFS = 9,
|
||||
REVERBS = 10,
|
||||
TERRAIN = 11,
|
||||
X11R6RGB = 12,
|
||||
}
|
||||
|
||||
internal class ScriptConfiguration : IComparable<ScriptConfiguration>
|
||||
|
|
|
@ -97,6 +97,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
private string[] soundsequences;
|
||||
private string[] terrainnames;
|
||||
private string[] damagetypes;
|
||||
private Dictionary<string, PixelColor> knowncolors; // Colors parsed from X11R6RGB lump. Color names are lowercase without spaces
|
||||
|
||||
//mxd. Text resources
|
||||
private Dictionary<ScriptType, HashSet<TextResource>> textresources;
|
||||
|
@ -156,6 +157,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
public string[] SoundSequences { get { return soundsequences; } }
|
||||
public string[] TerrainNames { get { return terrainnames; } }
|
||||
public string[] DamageTypes { get { return damagetypes; } }
|
||||
public Dictionary<string, PixelColor> KnownColors { get { return knowncolors; } }
|
||||
internal Dictionary<ScriptType, HashSet<TextResource>> TextResources { get { return textresources; } }
|
||||
|
||||
//mxd
|
||||
|
@ -326,6 +328,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
terrainnames = new string[0];
|
||||
textresources = new Dictionary<ScriptType, HashSet<TextResource>>();
|
||||
damagetypes = new string[0];
|
||||
knowncolors = new Dictionary<string, PixelColor>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// Load texture sets
|
||||
foreach(DefinedTextureSet ts in General.Map.ConfigSettings.TextureSets)
|
||||
|
@ -386,6 +389,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
// Load stuff
|
||||
LoadX11R6RGB(); //mxd
|
||||
LoadPalette();
|
||||
Dictionary<string, TexturesParser> cachedparsers = new Dictionary<string, TexturesParser>(); //mxd
|
||||
int texcount = LoadTextures(texturesonly, texturenamesshorttofull, cachedparsers);
|
||||
|
@ -588,6 +592,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
terrainnames = null; //mxd
|
||||
textresources = null; //mxd
|
||||
damagetypes = null; //mxd
|
||||
knowncolors = null; //mxd
|
||||
texturenames = null;
|
||||
flatnames = null;
|
||||
imageque = null;
|
||||
|
@ -801,10 +806,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
while(true);
|
||||
}
|
||||
catch(ThreadInterruptedException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch(ThreadInterruptedException) { }
|
||||
}
|
||||
|
||||
// This adds an image for background loading or unloading
|
||||
|
@ -2460,6 +2462,34 @@ namespace CodeImp.DoomBuilder.Data
|
|||
terrainnames = names.ToArray();
|
||||
}
|
||||
|
||||
//mxd. This loads X11R6RGB
|
||||
private void LoadX11R6RGB()
|
||||
{
|
||||
X11R6RGBParser parser = new X11R6RGBParser();
|
||||
|
||||
foreach(DataReader dr in containers)
|
||||
{
|
||||
currentreader = dr;
|
||||
IEnumerable<TextResourceData> streams = dr.GetX11R6RGBData();
|
||||
|
||||
// Parse the data
|
||||
foreach(TextResourceData data in streams)
|
||||
{
|
||||
parser.Parse(data, true);
|
||||
|
||||
// Report errors?
|
||||
if(parser.HasError) parser.LogError();
|
||||
}
|
||||
}
|
||||
|
||||
// Add to text resources collection
|
||||
textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values);
|
||||
currentreader = null;
|
||||
|
||||
// Set as collection
|
||||
knowncolors = parser.KnownColors;
|
||||
}
|
||||
|
||||
//mxd
|
||||
internal TextResourceData GetTextResourceData(string name)
|
||||
{
|
||||
|
|
|
@ -240,6 +240,9 @@ namespace CodeImp.DoomBuilder.Data
|
|||
//mxd. When implemented, this returns the TERRAIN lump
|
||||
public abstract IEnumerable<TextResourceData> GetTerrainData();
|
||||
|
||||
//mxd. When implemented, this returns the X11R6RGB lump
|
||||
public abstract IEnumerable<TextResourceData> GetX11R6RGBData();
|
||||
|
||||
//mxd. When implemented, this returns the list of voxel model names
|
||||
public abstract IEnumerable<string> GetVoxelNames();
|
||||
|
||||
|
|
|
@ -701,7 +701,6 @@ namespace CodeImp.DoomBuilder.Data
|
|||
|
||||
#region ================== TERRAIN (mxd)
|
||||
|
||||
//mxd
|
||||
public override IEnumerable<TextResourceData> GetTerrainData()
|
||||
{
|
||||
// Error when suspended
|
||||
|
@ -722,6 +721,28 @@ namespace CodeImp.DoomBuilder.Data
|
|||
|
||||
#endregion
|
||||
|
||||
#region ================== XBRSBSBB11 (mxd)
|
||||
|
||||
public override IEnumerable<TextResourceData> GetX11R6RGBData()
|
||||
{
|
||||
// Error when suspended
|
||||
if(issuspended) throw new Exception("Data reader is suspended");
|
||||
|
||||
List<TextResourceData> result = new List<TextResourceData>();
|
||||
string[] files = GetAllFilesWithTitle("", "X11R6RGB", false);
|
||||
|
||||
// Add to collection
|
||||
foreach(string s in files)
|
||||
result.Add(new TextResourceData(this, LoadFile(s), s, true));
|
||||
|
||||
// Find in any of the wad files
|
||||
foreach(WADReader wr in wads) result.AddRange(wr.GetTerrainData());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
||||
// This loads the images in this directory
|
||||
|
|
|
@ -98,7 +98,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
{
|
||||
// Add it
|
||||
patches.Add(patch);
|
||||
if(patch.lumpname == Name) hasPatchWithSameName = true; //mxd
|
||||
if(patch.LumpName == Name) hasPatchWithSameName = true; //mxd
|
||||
}
|
||||
|
||||
// This loads the image
|
||||
|
@ -143,11 +143,11 @@ namespace CodeImp.DoomBuilder.Data
|
|||
foreach(TexturePatch p in patches)
|
||||
{
|
||||
//mxd. Some patches (like "TNT1A0") should be skipped
|
||||
if(p.skip) continue;
|
||||
if(p.Skip) continue;
|
||||
|
||||
// Get the patch data stream
|
||||
string patchlocation = string.Empty; //mxd
|
||||
Stream patchdata = General.Map.Data.GetPatchData(p.lumpname, p.haslongname, ref patchlocation);
|
||||
Stream patchdata = General.Map.Data.GetPatchData(p.LumpName, p.HasLongName, ref patchlocation);
|
||||
if(patchdata != null)
|
||||
{
|
||||
// Copy patch data to memory
|
||||
|
@ -170,7 +170,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
if(reader is UnknownImageReader)
|
||||
{
|
||||
// Data is in an unknown format!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Patch lump \"" + Path.Combine(patchlocation, p.lumpname) + "\" data format could not be read, while loading texture \"" + this.Name + "\"");
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Patch lump \"" + Path.Combine(patchlocation, p.LumpName) + "\" data format could not be read, while loading texture \"" + this.Name + "\"");
|
||||
missingpatches++; //mxd
|
||||
}
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
catch(InvalidDataException)
|
||||
{
|
||||
// Data cannot be read!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Patch lump \"" + p.lumpname + "\" data format could not be read, while loading texture \"" + this.Name + "\"");
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Patch lump \"" + p.LumpName + "\" data format could not be read, while loading texture \"" + this.Name + "\"");
|
||||
missingpatches++; //mxd
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
patchbmp = TransformPatch(p, patchbmp);
|
||||
|
||||
// Draw the patch on the texture image
|
||||
Rectangle tgtrect = new Rectangle(p.x, p.y, patchbmp.Size.Width, patchbmp.Size.Height);
|
||||
Rectangle tgtrect = new Rectangle(p.X, p.Y, patchbmp.Size.Width, patchbmp.Size.Height);
|
||||
g.DrawImageUnscaledAndClipped(patchbmp, tgtrect);
|
||||
patchbmp.Dispose();
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
//mxd. ZDoom can use any known graphic as patch
|
||||
if(General.Map.Config.MixTexturesFlats)
|
||||
{
|
||||
ImageData img = General.Map.Data.GetTextureImage(p.lumpname);
|
||||
ImageData img = General.Map.Data.GetTextureImage(p.LumpName);
|
||||
if(!(img is UnknownImage) && img != this)
|
||||
{
|
||||
if(!img.IsImageLoaded) img.LoadImage();
|
||||
|
@ -217,7 +217,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
Bitmap patchbmp = TransformPatch(p, new Bitmap(img.GetBitmap()));
|
||||
|
||||
// Draw the patch on the texture image
|
||||
Rectangle tgtrect = new Rectangle(p.x, p.y, patchbmp.Size.Width, patchbmp.Size.Height);
|
||||
Rectangle tgtrect = new Rectangle(p.X, p.Y, patchbmp.Size.Width, patchbmp.Size.Height);
|
||||
g.DrawImageUnscaledAndClipped(patchbmp, tgtrect);
|
||||
patchbmp.Dispose();
|
||||
|
||||
|
@ -226,7 +226,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
// Missing a patch lump!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Missing patch lump \"" + p.lumpname + "\" while loading texture \"" + this.Name + "\"");
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Missing patch lump \"" + p.LumpName + "\" while loading texture \"" + this.Name + "\"");
|
||||
missingpatches++; //mxd
|
||||
}
|
||||
}
|
||||
|
@ -249,20 +249,20 @@ namespace CodeImp.DoomBuilder.Data
|
|||
private Bitmap TransformPatch(TexturePatch p, Bitmap patchbmp)
|
||||
{
|
||||
//mxd. Flip
|
||||
if(p.flipx || p.flipy)
|
||||
if(p.FlipX || p.FlipY)
|
||||
{
|
||||
RotateFlipType flip;
|
||||
if(p.flipx && !p.flipy) flip = RotateFlipType.RotateNoneFlipX;
|
||||
else if(!p.flipx && p.flipy) flip = RotateFlipType.RotateNoneFlipY;
|
||||
if(p.FlipX && !p.FlipY) flip = RotateFlipType.RotateNoneFlipX;
|
||||
else if(!p.FlipX && p.FlipY) flip = RotateFlipType.RotateNoneFlipY;
|
||||
else flip = RotateFlipType.RotateNoneFlipXY;
|
||||
patchbmp.RotateFlip(flip);
|
||||
}
|
||||
|
||||
//mxd. Then rotate. I do it this way because RotateFlip function rotates THEN flips, and GZDoom does it the other way around.
|
||||
if(p.rotate != 0)
|
||||
if(p.Rotate != 0)
|
||||
{
|
||||
RotateFlipType rotate;
|
||||
switch(p.rotate)
|
||||
switch(p.Rotate)
|
||||
{
|
||||
case 90: rotate = RotateFlipType.Rotate90FlipNone; break;
|
||||
case 180: rotate = RotateFlipType.Rotate180FlipNone; break;
|
||||
|
@ -272,7 +272,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
// Adjust patch alpha, apply tint or blend
|
||||
if(p.blendstyle != TexturePathBlendStyle.None || p.style != TexturePathRenderStyle.Copy)
|
||||
if(p.BlendStyle != TexturePathBlendStyle.NONE || p.RenderStyle != TexturePathRenderStyle.COPY)
|
||||
{
|
||||
BitmapData bmpdata = null;
|
||||
|
||||
|
@ -282,61 +282,61 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Cannot lock image \"" + p.lumpname + "\" for alpha adjustment. " + e.GetType().Name + ": " + e.Message);
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Cannot lock image \"" + p.LumpName + "\" for alpha adjustment. " + e.GetType().Name + ": " + e.Message);
|
||||
}
|
||||
|
||||
if(bmpdata != null)
|
||||
{
|
||||
PixelColor* pixels = (PixelColor*)(bmpdata.Scan0.ToPointer());
|
||||
int numpixels = bmpdata.Width * bmpdata.Height;
|
||||
int patchalpha = (int)Math.Round(General.Clamp(p.alpha, 0f, 1f) * 255); //convert alpha to [0-255] range
|
||||
int patchalpha = (int)Math.Round(General.Clamp(p.Alpha, 0f, 1f) * 255); //convert alpha to [0-255] range
|
||||
|
||||
//mxd. Blend/Tint support
|
||||
if(p.blendstyle == TexturePathBlendStyle.Blend)
|
||||
if(p.BlendStyle == TexturePathBlendStyle.BLEND)
|
||||
{
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
{
|
||||
cp->r = (byte)((cp->r * p.blend.r) * PixelColor.BYTE_TO_FLOAT);
|
||||
cp->g = (byte)((cp->g * p.blend.g) * PixelColor.BYTE_TO_FLOAT);
|
||||
cp->b = (byte)((cp->b * p.blend.b) * PixelColor.BYTE_TO_FLOAT);
|
||||
cp->r = (byte)((cp->r * p.BlendColor.r) * PixelColor.BYTE_TO_FLOAT);
|
||||
cp->g = (byte)((cp->g * p.BlendColor.g) * PixelColor.BYTE_TO_FLOAT);
|
||||
cp->b = (byte)((cp->b * p.BlendColor.b) * PixelColor.BYTE_TO_FLOAT);
|
||||
}
|
||||
}
|
||||
else if(p.blendstyle == TexturePathBlendStyle.Tint)
|
||||
else if(p.BlendStyle == TexturePathBlendStyle.TINT)
|
||||
{
|
||||
float tintammount = p.tintammount - 0.1f;
|
||||
float tintammount = p.BlendColor.a * PixelColor.BYTE_TO_FLOAT;// -0.1f;
|
||||
|
||||
if(tintammount > 0)
|
||||
{
|
||||
float br = p.blend.r * PixelColor.BYTE_TO_FLOAT * tintammount;
|
||||
float bg = p.blend.g * PixelColor.BYTE_TO_FLOAT * tintammount;
|
||||
float bb = p.blend.b * PixelColor.BYTE_TO_FLOAT * tintammount;
|
||||
float invTint = 1.0f - tintammount;
|
||||
float br = p.BlendColor.r * PixelColor.BYTE_TO_FLOAT * tintammount;
|
||||
float bg = p.BlendColor.g * PixelColor.BYTE_TO_FLOAT * tintammount;
|
||||
float bb = p.BlendColor.b * PixelColor.BYTE_TO_FLOAT * tintammount;
|
||||
float invtintammount = 1.0f - tintammount;
|
||||
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
{
|
||||
cp->r = (byte)(((cp->r * PixelColor.BYTE_TO_FLOAT) * invTint + br) * 255.0f);
|
||||
cp->g = (byte)(((cp->g * PixelColor.BYTE_TO_FLOAT) * invTint + bg) * 255.0f);
|
||||
cp->b = (byte)(((cp->b * PixelColor.BYTE_TO_FLOAT) * invTint + bb) * 255.0f);
|
||||
cp->r = (byte)(((cp->r * PixelColor.BYTE_TO_FLOAT) * invtintammount + br) * 255.0f);
|
||||
cp->g = (byte)(((cp->g * PixelColor.BYTE_TO_FLOAT) * invtintammount + bg) * 255.0f);
|
||||
cp->b = (byte)(((cp->b * PixelColor.BYTE_TO_FLOAT) * invtintammount + bb) * 255.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//mxd. Apply RenderStyle
|
||||
if(p.style == TexturePathRenderStyle.Blend)
|
||||
if(p.RenderStyle == TexturePathRenderStyle.BLEND)
|
||||
{
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
cp->a = (byte)((cp->a * patchalpha) * PixelColor.BYTE_TO_FLOAT);
|
||||
}
|
||||
//mxd. We need a copy of underlying part of texture for these styles
|
||||
else if(p.style != TexturePathRenderStyle.Copy)
|
||||
else if(p.RenderStyle != TexturePathRenderStyle.COPY)
|
||||
{
|
||||
// Copy portion of texture
|
||||
int lockWidth = (p.x + patchbmp.Size.Width > bitmap.Width) ? bitmap.Width - p.x : patchbmp.Size.Width;
|
||||
int lockHeight = (p.y + patchbmp.Size.Height > bitmap.Height) ? bitmap.Height - p.y : patchbmp.Size.Height;
|
||||
int lockWidth = (p.X + patchbmp.Size.Width > bitmap.Width) ? bitmap.Width - p.X : patchbmp.Size.Width;
|
||||
int lockHeight = (p.Y + patchbmp.Size.Height > bitmap.Height) ? bitmap.Height - p.Y : patchbmp.Size.Height;
|
||||
|
||||
Bitmap source = new Bitmap(patchbmp.Size.Width, patchbmp.Size.Height);
|
||||
using(Graphics sg = Graphics.FromImage(source))
|
||||
sg.DrawImageUnscaled(bitmap, new Rectangle(-p.x, -p.y, lockWidth, lockHeight));
|
||||
sg.DrawImageUnscaled(bitmap, new Rectangle(-p.X, -p.Y, lockWidth, lockHeight));
|
||||
|
||||
// Lock texture
|
||||
BitmapData texturebmpdata = null;
|
||||
|
@ -355,9 +355,9 @@ namespace CodeImp.DoomBuilder.Data
|
|||
PixelColor* texturepixels = (PixelColor*)(texturebmpdata.Scan0.ToPointer());
|
||||
PixelColor* tcp = texturepixels + numpixels - 1;
|
||||
|
||||
switch(p.style)
|
||||
switch(p.RenderStyle)
|
||||
{
|
||||
case TexturePathRenderStyle.Add:
|
||||
case TexturePathRenderStyle.ADD:
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
{
|
||||
cp->r = (byte)Math.Min(255, cp->r + tcp->r);
|
||||
|
@ -368,7 +368,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
break;
|
||||
|
||||
case TexturePathRenderStyle.Subtract:
|
||||
case TexturePathRenderStyle.SUBTRACT:
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
{
|
||||
cp->r = (byte)Math.Max(0, tcp->r - cp->r);
|
||||
|
@ -379,7 +379,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
break;
|
||||
|
||||
case TexturePathRenderStyle.ReverseSubtract:
|
||||
case TexturePathRenderStyle.REVERSE_SUBTRACT:
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
{
|
||||
cp->r = (byte)Math.Max(0, cp->r - tcp->r);
|
||||
|
@ -390,7 +390,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
break;
|
||||
|
||||
case TexturePathRenderStyle.Modulate:
|
||||
case TexturePathRenderStyle.MODULATE:
|
||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||
{
|
||||
cp->r = (byte)((cp->r * tcp->r) * PixelColor.BYTE_TO_FLOAT);
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Add it
|
||||
patches.Add(patch);
|
||||
|
||||
if(patch.lumpname == Name) hasPatchWithSameName = true; //mxd
|
||||
if(patch.LumpName == Name) hasPatchWithSameName = true; //mxd
|
||||
}
|
||||
|
||||
// This loads the image
|
||||
|
@ -103,7 +103,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
{
|
||||
// Get the patch data stream
|
||||
string patchlocation = string.Empty; //mxd
|
||||
Stream patchdata = General.Map.Data.GetPatchData(p.lumpname, p.haslongname, ref patchlocation);
|
||||
Stream patchdata = General.Map.Data.GetPatchData(p.LumpName, p.HasLongName, ref patchlocation);
|
||||
if(patchdata != null)
|
||||
{
|
||||
// Copy patch data to memory
|
||||
|
@ -125,7 +125,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
if(reader is UnknownImageReader)
|
||||
{
|
||||
// Data is in an unknown format!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Patch lump \"" + Path.Combine(patchlocation, p.lumpname) + "\" data format could not be read, while loading texture \"" + this.Name + "\". Does this lump contain valid picture data at all?");
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Patch lump \"" + Path.Combine(patchlocation, p.LumpName) + "\" data format could not be read, while loading texture \"" + this.Name + "\". Does this lump contain valid picture data at all?");
|
||||
loadfailed = true;
|
||||
missingpatches++; //mxd
|
||||
}
|
||||
|
@ -135,11 +135,11 @@ namespace CodeImp.DoomBuilder.Data
|
|||
{
|
||||
// Draw the patch
|
||||
mem.Seek(0, SeekOrigin.Begin);
|
||||
try { reader.DrawToPixelData(mem, pixels, width, height, p.x, p.y); }
|
||||
try { reader.DrawToPixelData(mem, pixels, width, height, p.X, p.Y); }
|
||||
catch(InvalidDataException)
|
||||
{
|
||||
// Data cannot be read!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Patch lump \"" + p.lumpname + "\" data format could not be read, while loading texture \"" + this.Name + "\". Does this lump contain valid picture data at all?");
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Patch lump \"" + p.LumpName + "\" data format could not be read, while loading texture \"" + this.Name + "\". Does this lump contain valid picture data at all?");
|
||||
loadfailed = true;
|
||||
missingpatches++; //mxd
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
else
|
||||
{
|
||||
// Missing a patch lump!
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Missing patch lump \"" + p.lumpname + "\" while loading texture \"" + this.Name + "\". Did you forget to include required resources?");
|
||||
General.ErrorLogger.Add(ErrorType.Error, "Missing patch lump \"" + p.LumpName + "\" while loading texture \"" + this.Name + "\". Did you forget to include required resources?");
|
||||
loadfailed = true;
|
||||
missingpatches++; //mxd
|
||||
}
|
||||
|
|
|
@ -26,93 +26,90 @@ namespace CodeImp.DoomBuilder.Data
|
|||
{
|
||||
public enum TexturePathRenderStyle
|
||||
{
|
||||
Copy,
|
||||
Blend,
|
||||
Add,
|
||||
Subtract,
|
||||
ReverseSubtract,
|
||||
Modulate,
|
||||
CopyAlpha,
|
||||
CopyNewAlpha, //mxd
|
||||
Overlay, //mxd
|
||||
COPY,
|
||||
BLEND,
|
||||
ADD,
|
||||
SUBTRACT,
|
||||
REVERSE_SUBTRACT,
|
||||
MODULATE,
|
||||
COPY_ALPHA,
|
||||
COPY_NEW_ALPHA, //mxd
|
||||
OVERLAY, //mxd
|
||||
}
|
||||
|
||||
public enum TexturePathBlendStyle //mxd
|
||||
{
|
||||
None,
|
||||
Blend,
|
||||
Tint
|
||||
NONE,
|
||||
BLEND,
|
||||
TINT
|
||||
}
|
||||
|
||||
internal struct TexturePatch
|
||||
{
|
||||
public readonly string lumpname;
|
||||
public readonly int x;
|
||||
public readonly int y;
|
||||
public readonly bool flipx;
|
||||
public readonly bool flipy;
|
||||
public readonly bool haslongname; //mxd
|
||||
public readonly int rotate;
|
||||
public PixelColor blend;
|
||||
public readonly float alpha;
|
||||
public readonly TexturePathRenderStyle style;
|
||||
public readonly TexturePathBlendStyle blendstyle; //mxd
|
||||
public readonly float tintammount;//mxd
|
||||
public readonly bool skip; //mxd
|
||||
public readonly string LumpName;
|
||||
public readonly int X;
|
||||
public readonly int Y;
|
||||
public readonly bool FlipX;
|
||||
public readonly bool FlipY;
|
||||
public readonly bool HasLongName; //mxd
|
||||
public readonly int Rotate;
|
||||
public PixelColor BlendColor;
|
||||
public readonly float Alpha;
|
||||
public readonly TexturePathRenderStyle RenderStyle;
|
||||
public readonly TexturePathBlendStyle BlendStyle; //mxd
|
||||
public readonly bool Skip; //mxd
|
||||
|
||||
// Constructor for simple patches
|
||||
public TexturePatch(string lumpname, int x, int y)
|
||||
{
|
||||
// Initialize
|
||||
this.lumpname = lumpname;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.flipx = false;
|
||||
this.flipy = false;
|
||||
this.rotate = 0;
|
||||
this.blend = new PixelColor(0, 0, 0, 0);
|
||||
this.alpha = 1.0f;
|
||||
this.style = TexturePathRenderStyle.Copy;
|
||||
this.blendstyle = TexturePathBlendStyle.None;//mxd
|
||||
this.tintammount = 0; //mxd
|
||||
this.haslongname = false; //mxd
|
||||
this.skip = false; //mxd
|
||||
this.LumpName = lumpname;
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
this.FlipX = false;
|
||||
this.FlipY = false;
|
||||
this.Rotate = 0;
|
||||
this.BlendColor = new PixelColor(0, 0, 0, 0);
|
||||
this.Alpha = 1.0f;
|
||||
this.RenderStyle = TexturePathRenderStyle.COPY;
|
||||
this.BlendStyle = TexturePathBlendStyle.NONE;//mxd
|
||||
this.HasLongName = false; //mxd
|
||||
this.Skip = false; //mxd
|
||||
}
|
||||
|
||||
//mxd. Constructor for hires patches
|
||||
public TexturePatch(PatchStructure patch)
|
||||
{
|
||||
// Initialize
|
||||
this.lumpname = patch.Name.ToUpperInvariant();
|
||||
this.x = patch.OffsetX;
|
||||
this.y = patch.OffsetY;
|
||||
this.flipx = patch.FlipX;
|
||||
this.flipy = patch.FlipY;
|
||||
this.rotate = patch.Rotation;
|
||||
this.blend = patch.BlendColor;
|
||||
this.alpha = patch.Alpha;
|
||||
this.style = patch.RenderStyle;
|
||||
this.blendstyle = patch.BlendStyle;
|
||||
this.tintammount = patch.TintAmmount;
|
||||
this.haslongname = (Path.GetFileNameWithoutExtension(this.lumpname) != this.lumpname);
|
||||
this.skip = patch.Skip;
|
||||
this.LumpName = patch.Name.ToUpperInvariant();
|
||||
this.X = patch.OffsetX;
|
||||
this.Y = patch.OffsetY;
|
||||
this.FlipX = patch.FlipX;
|
||||
this.FlipY = patch.FlipY;
|
||||
this.Rotate = patch.Rotation;
|
||||
this.BlendColor = patch.BlendColor;
|
||||
this.Alpha = patch.Alpha;
|
||||
this.RenderStyle = patch.RenderStyle;
|
||||
this.BlendStyle = patch.BlendStyle;
|
||||
this.HasLongName = (Path.GetFileNameWithoutExtension(this.LumpName) != this.LumpName);
|
||||
this.Skip = patch.Skip;
|
||||
|
||||
//mxd. Check data so we don't perform unneeded operations later on
|
||||
if(this.alpha == 1.0f)
|
||||
if(this.Alpha == 1.0f)
|
||||
{
|
||||
switch(this.style)
|
||||
switch(this.RenderStyle)
|
||||
{
|
||||
case TexturePathRenderStyle.Blend:
|
||||
case TexturePathRenderStyle.CopyAlpha:
|
||||
case TexturePathRenderStyle.CopyNewAlpha:
|
||||
case TexturePathRenderStyle.Overlay:
|
||||
this.style = TexturePathRenderStyle.Copy;
|
||||
case TexturePathRenderStyle.BLEND:
|
||||
case TexturePathRenderStyle.COPY_ALPHA:
|
||||
case TexturePathRenderStyle.COPY_NEW_ALPHA:
|
||||
case TexturePathRenderStyle.OVERLAY:
|
||||
this.RenderStyle = TexturePathRenderStyle.COPY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//mxd. and get rid of render styles we don't support
|
||||
if(this.style == TexturePathRenderStyle.Overlay) this.style = TexturePathRenderStyle.Copy;
|
||||
if(this.RenderStyle == TexturePathRenderStyle.OVERLAY) this.RenderStyle = TexturePathRenderStyle.COPY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1015,6 +1015,13 @@ namespace CodeImp.DoomBuilder.Data
|
|||
return GetAllLumps("TERRAIN");
|
||||
}
|
||||
|
||||
//mxd
|
||||
public override IEnumerable<TextResourceData> GetX11R6RGBData()
|
||||
{
|
||||
if(issuspended) throw new Exception("Data reader is suspended");
|
||||
return GetAllLumps("X11R6RGB");
|
||||
}
|
||||
|
||||
//mxd
|
||||
private IEnumerable<TextResourceData> GetFirstLump(string name)
|
||||
{
|
||||
|
|
|
@ -2,12 +2,11 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using CodeImp.DoomBuilder.Config;
|
||||
using CodeImp.DoomBuilder.Data;
|
||||
using SlimDX;
|
||||
using CodeImp.DoomBuilder.Rendering;
|
||||
using CodeImp.DoomBuilder.ZDoom;
|
||||
using CodeImp.DoomBuilder.GZBuilder.Data;
|
||||
|
||||
|
@ -607,16 +606,15 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
ReportError("Expected " + fadetype + " color value");
|
||||
return false;
|
||||
}
|
||||
|
||||
Color4 color = new Color4();
|
||||
|
||||
// Try to get the color...
|
||||
if(GetColor(colorval, ref color))
|
||||
PixelColor color = new PixelColor();
|
||||
if(GetColorFromString(colorval, ref color))
|
||||
{
|
||||
if(fadetype == "fade")
|
||||
mapinfo.FadeColor = color;
|
||||
mapinfo.FadeColor = color.ToColorValue();
|
||||
else
|
||||
mapinfo.OutsideFogColor = color;
|
||||
mapinfo.OutsideFogColor = color.ToColorValue();
|
||||
}
|
||||
else //...or not
|
||||
{
|
||||
|
@ -687,30 +685,5 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
|||
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
||||
private static bool GetColor(string name, ref Color4 color)
|
||||
{
|
||||
if(name == "black") return true;
|
||||
|
||||
//probably it's a hex color (like FFCC11)?
|
||||
int ci;
|
||||
if(int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ci))
|
||||
{
|
||||
color = new Color4(ci) {Alpha = 1.0f};
|
||||
return true;
|
||||
}
|
||||
|
||||
//probably it's a color name?
|
||||
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;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,34 +12,34 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
{
|
||||
public partial class ExceptionDialog : Form
|
||||
{
|
||||
private readonly bool cannotContinue;
|
||||
private readonly string logPath;
|
||||
private readonly bool isterminating;
|
||||
private readonly string logpath;
|
||||
|
||||
public ExceptionDialog(UnhandledExceptionEventArgs e)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
logPath = Path.Combine(General.SettingsPath, @"GZCrash.txt");
|
||||
logpath = Path.Combine(General.SettingsPath, @"GZCrash.txt");
|
||||
Exception ex = (Exception)e.ExceptionObject;
|
||||
errorDescription.Text = "Error in " + ex.Source + ":";
|
||||
string sysinfo = GetSystemInfo();
|
||||
using(StreamWriter sw = File.CreateText(logPath))
|
||||
using(StreamWriter sw = File.CreateText(logpath))
|
||||
{
|
||||
sw.Write(sysinfo + GetExceptionDescription(ex));
|
||||
}
|
||||
|
||||
errorMessage.Text = ex.Message + Environment.NewLine + ex.StackTrace;
|
||||
cannotContinue = true; //cannot recover from this...
|
||||
isterminating = e.IsTerminating; // Recoverable?
|
||||
}
|
||||
|
||||
public ExceptionDialog(ThreadExceptionEventArgs e)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
logPath = Path.Combine(General.SettingsPath, @"GZCrash.txt");
|
||||
logpath = Path.Combine(General.SettingsPath, @"GZCrash.txt");
|
||||
errorDescription.Text = "Error in " + e.Exception.Source + ":";
|
||||
string sysinfo = GetSystemInfo();
|
||||
using(StreamWriter sw = File.CreateText(logPath))
|
||||
using(StreamWriter sw = File.CreateText(logpath))
|
||||
{
|
||||
sw.Write(sysinfo + GetExceptionDescription(e.Exception));
|
||||
}
|
||||
|
@ -50,78 +50,92 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
|
||||
public void Setup()
|
||||
{
|
||||
bContinue.Enabled = !cannotContinue;
|
||||
string[] titles =
|
||||
{
|
||||
"0x000000 at 0xFFFFFF. That's probaby bad",
|
||||
"Here we go again...",
|
||||
"Uh oh, you're screwed",
|
||||
"All is lost!",
|
||||
"Achievement unlocked: CRASH TIME!",
|
||||
"OH NOES! TEH ERROR!",
|
||||
"0001000001111011000000000011001101011120110111",
|
||||
"Nuclear launch detected!",
|
||||
"Don't send this to Microsoft",
|
||||
"You. Shall. Not. Pass!!!",
|
||||
"Yep, we have bugs",
|
||||
"It's dangerous to go alone. Take this!",
|
||||
"The operation completed successfully",
|
||||
"Security Alert – Moving cursor is not as safe as you thought",
|
||||
"Random error appears from north",
|
||||
"ERROR: NO_ERROR",
|
||||
"Epic fail",
|
||||
"At least it's not BSoD...",
|
||||
"User Error. Please Replace User",
|
||||
"Brought to you by MaxED!",
|
||||
"GZDoom Builder proudly presents:",
|
||||
"You aren't expected to understand this",
|
||||
"Back to the drawing board...",
|
||||
"I'm sorry... :(",
|
||||
"This is a horrbble day for you, and of course, the world",
|
||||
"Abort, Retry, Fail?",
|
||||
"You are making progress. I'm afraid that's something I can't allow to happen",
|
||||
"You are making progress. That's not OK",
|
||||
"No errors found, restarting computer",
|
||||
"Does Not Compute!",
|
||||
"I’m sorry, Dave, I’m afraid I can’t do that",
|
||||
"What's that? Chicken?",
|
||||
"It can only be attributable to human error",
|
||||
"It's now safe to turn off your computer",
|
||||
"I've got a bad feeling about this",
|
||||
"YOU CAN’T DO THAT!",
|
||||
"Man the Lifeboats! Women and children first!",
|
||||
"IMPOSSIBURU!!!",
|
||||
"Now deleting all files. Goodbye",
|
||||
"General Failure",
|
||||
"Invalid Error",
|
||||
"Beam me up Scotty, there’s no life out here",
|
||||
"Well, you ran into something and the game is over",
|
||||
"I'm good at writing bad code",
|
||||
"$FUNNY_ERROR_CAPTION",
|
||||
"In Soviet Russia, exception throws YOU!",
|
||||
"...and then GZDB was the demons!",
|
||||
"B U S T E D",
|
||||
"Freeze mode enabled",
|
||||
"You feel strange...",
|
||||
"That doesn't seem to work",
|
||||
"This function is only available in the retail version of GZDoom Builder",
|
||||
"You picked up the Random Exception.",
|
||||
"Pinky says that you're the new hope. Bear that in mind.",
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
||||
"Deal with it",
|
||||
"Error 47",
|
||||
"YOU DIED",
|
||||
"Thanks, Obama",
|
||||
"The God Of Exceptions Demands MORE Exceptions!",
|
||||
"Good. It's boring here anyway.",
|
||||
"Shameful display!",
|
||||
"It's CRASHENING!",
|
||||
"W-W-W-WIPEOUT!",
|
||||
"EVERYTHING IS LOST!",
|
||||
"Your empty is full!",
|
||||
"Let's see how far this infinite loop goes...",
|
||||
"Windows 10 is here! RUN!",
|
||||
"You really screwed up this time!",
|
||||
"[WFDS]",
|
||||
"[No]",
|
||||
"An error has occurred while creating an error",
|
||||
"Catastrophic failure",
|
||||
"This time, it’s the human’s fault",
|
||||
"No error occurred",
|
||||
"Hey! It looks like you're having an error!",
|
||||
"What, what, what, what, what, what, what, what, what, what?",
|
||||
"WARNING: PROGRAMMING BUG IN GZDB!",
|
||||
"Something happened",
|
||||
"The Device is Error",
|
||||
};
|
||||
|
||||
string[] titles = {
|
||||
"0x000000 at 0xFFFFFF. That's probaby bad",
|
||||
"Here we go again...",
|
||||
"Uh oh, you're screwed",
|
||||
"All is lost!",
|
||||
"Achievement unlocked: CRASH TIME!",
|
||||
"OH NOES! TEH ERROR!",
|
||||
"0001000001111011000000000011001101011110110111",
|
||||
"Nuclear launch detected!",
|
||||
"Don't send this to Microsoft",
|
||||
"You. Shall. Not. Pass!!!",
|
||||
"Yep, we have bugs",
|
||||
"It's dangerous to go alone. Take this!",
|
||||
"The operation completed successfully",
|
||||
"Security Alert – Moving cursor is not as safe as you thought",
|
||||
"Random error appears from north",
|
||||
"ERROR: NO_ERROR",
|
||||
"Epic fail",
|
||||
"At least it's not BSoD...",
|
||||
"User Error. Please Replace User",
|
||||
"Brought to you by MaxED!",
|
||||
"GZDoom Builder proudly presents:",
|
||||
"You aren't expected to understand this",
|
||||
"Back to the drawing board...",
|
||||
"I'm sorry... :(",
|
||||
"This is a horrbble day for you, and of course, the world",
|
||||
"Abort, Retry, Fail?",
|
||||
"You are making progress. I'm afraid that's something I can't allow to happen",
|
||||
"You are making progress. That's not OK",
|
||||
"No errors found, restarting computer",
|
||||
"Does Not Compute!",
|
||||
"I’m sorry, Dave, I’m afraid I can’t do that",
|
||||
"What's that? Chicken?",
|
||||
"It can only be attributable to human error",
|
||||
"It's now safe to turn off your computer",
|
||||
"I've got a bad feeling about this",
|
||||
"YOU CAN’T DO THAT!",
|
||||
"Man the Lifeboats! Women and children first!",
|
||||
"IMPOSSIBURU!!!",
|
||||
"Now deleting all files. Goodbye",
|
||||
"General Failure",
|
||||
"Invalid Error",
|
||||
"Beam me up Scotty, there’s no life out here",
|
||||
"Well, you ran into something and the game is over",
|
||||
"I'm good at writing bad code",
|
||||
"$FUNNY_ERROR_CAPTION",
|
||||
"In Soviet Russia, exception throws YOU!",
|
||||
"...and then GZDB was the demons!",
|
||||
"B U S T E D",
|
||||
"Freeze mode enabled",
|
||||
"You feel strange...",
|
||||
"That doesn't seem to work",
|
||||
"This function is only available in the retail version of GZDoom Builder",
|
||||
"You picked up the Random Exception.",
|
||||
"Pinky says that you're the new hope. Bear that in mind.",
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
||||
"Deal with it",
|
||||
"Error 47",
|
||||
"YOU DIED",
|
||||
"Thanks, Obama",
|
||||
"The God Of Exceptions Demands MORE Exceptions!",
|
||||
"Good. It's boring here anyway.",
|
||||
"Shameful display!",
|
||||
"It's CRASHENING!",
|
||||
"W-W-W-WIPEOUT!",
|
||||
"EVERYTHING IS LOST!",
|
||||
"Your empty is full!",
|
||||
"Let's see how far this infinite loop goes...",
|
||||
};
|
||||
this.Text = titles[new Random().Next(0, titles.Length - 1)];
|
||||
bContinue.Enabled = !isterminating;
|
||||
}
|
||||
|
||||
private static string GetSystemInfo()
|
||||
|
@ -181,8 +195,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
|||
|
||||
private void reportLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
if(!File.Exists(logPath)) return;
|
||||
System.Diagnostics.Process.Start("explorer.exe", @"/select, " + logPath);
|
||||
if(!File.Exists(logpath)) return;
|
||||
System.Diagnostics.Process.Start("explorer.exe", @"/select, " + logpath);
|
||||
reportLink.LinkVisited = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -2080,70 +2080,64 @@ namespace CodeImp.DoomBuilder
|
|||
|
||||
#region ================== mxd. Uncaught exceptions handling
|
||||
|
||||
// In some cases the program can remain operational after these
|
||||
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try handling it in user-friendy way...
|
||||
GZBuilder.Windows.ExceptionDialog dlg = new GZBuilder.Windows.ExceptionDialog(e);
|
||||
dlg.Setup();
|
||||
if(dlg.ShowDialog() == DialogResult.Cancel) Application.Exit();
|
||||
if(dlg.ShowDialog() == DialogResult.Cancel) Terminate(false);
|
||||
}
|
||||
catch
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
MessageBox.Show("Fatal Windows Forms Error", "Fatal Windows Forms Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Application.Exit();
|
||||
}
|
||||
string exceptionmsg;
|
||||
|
||||
// Try getting exception details...
|
||||
try { exceptionmsg = "Fatal Windows Forms error occurred: " + e.Exception.Message + "\n\nStack Trace:\n" + e.Exception.StackTrace; }
|
||||
catch(Exception exc) { exceptionmsg = "Failed to get initial excepton details: " + exc.Message + "\n\nStack Trace:\n" + exc.StackTrace; }
|
||||
|
||||
// Try logging it...
|
||||
try { WriteLogLine(exceptionmsg); } catch { }
|
||||
|
||||
// Try displaying it to the user...
|
||||
try { MessageBox.Show("Fatal Windows Forms Error", exceptionmsg, MessageBoxButtons.OK, MessageBoxIcon.Stop); }
|
||||
finally { Process.GetCurrentProcess().Kill(); }
|
||||
}
|
||||
}
|
||||
|
||||
// These are usually unrecoverable
|
||||
private static void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
string exceptionmsg = string.Empty;
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
Exception ex = (Exception)e.ExceptionObject;
|
||||
exceptionmsg = "An application error occurred: " + ex.Message + "\n\nStack Trace:\n" + ex.StackTrace;
|
||||
|
||||
// Since we can't prevent the app from terminating, log this to the event log.
|
||||
try
|
||||
{
|
||||
if(!EventLog.SourceExists("ThreadException"))
|
||||
EventLog.CreateEventSource("ThreadException", "Application");
|
||||
|
||||
// Create an EventLog instance and assign its source.
|
||||
using(EventLog myLog = new EventLog())
|
||||
{
|
||||
myLog.Source = "ThreadException";
|
||||
myLog.WriteEntry(exceptionmsg);
|
||||
}
|
||||
}
|
||||
catch(Exception exc)
|
||||
{
|
||||
MessageBox.Show("Could not write the error to the event log.\nReason: "
|
||||
+ exc.Message + "\n\nInitial exception:\n" + exceptionmsg, "Fatal Non-UI Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
|
||||
}
|
||||
|
||||
// Try handling it in user-friendy way...
|
||||
GZBuilder.Windows.ExceptionDialog dlg = new GZBuilder.Windows.ExceptionDialog(e);
|
||||
dlg.Setup();
|
||||
dlg.ShowDialog();
|
||||
}
|
||||
catch(Exception exc)
|
||||
if(dlg.ShowDialog() == DialogResult.Cancel) Terminate(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
string exceptionmsg;
|
||||
|
||||
// Try getting exception details...
|
||||
try
|
||||
{
|
||||
MessageBox.Show("Failed to write the error to the event log or to show the Exception Dialog.\n\nReason: "
|
||||
+ exc.Message + "\n\nInitial exception:\n" + exceptionmsg, "Fatal Non-UI Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Application.Exit();
|
||||
Exception ex = (Exception) e.ExceptionObject;
|
||||
exceptionmsg = "Fatal Non-UI error occurred: " + ex.Message + "\n\nStack Trace:\n" + ex.StackTrace;
|
||||
}
|
||||
catch(Exception exc)
|
||||
{
|
||||
exceptionmsg = "Failed to get initial excepton details: " + exc.Message + "\n\nStack Trace:\n" + exc.StackTrace;
|
||||
}
|
||||
|
||||
// Try logging it...
|
||||
try { WriteLogLine(exceptionmsg); } catch {}
|
||||
|
||||
// Try displaying it to the user...
|
||||
try { MessageBox.Show("Fatal Windows Forms Error", exceptionmsg, MessageBoxButtons.OK, MessageBoxIcon.Stop); }
|
||||
finally { Process.GetCurrentProcess().Kill(); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -724,21 +724,22 @@ namespace CodeImp.DoomBuilder
|
|||
string settingsfile;
|
||||
WAD targetwad = null;
|
||||
bool includenodes;
|
||||
bool fileexists = File.Exists(newfilepathname); //mxd
|
||||
|
||||
General.WriteLogLine("Saving map to file: " + newfilepathname);
|
||||
|
||||
//mxd. Official IWAD check...
|
||||
WAD hashtest = new WAD(newfilepathname, true);
|
||||
if(hashtest.IsOfficialIWAD)
|
||||
{
|
||||
General.WriteLogLine("Map saving aborted: attempt to modify official IWAD");
|
||||
General.ShowErrorMessage("Official IWADs should not be modified.\nConsider making a PWAD instead", MessageBoxButtons.OK);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if(fileexists)
|
||||
{
|
||||
WAD hashtest = new WAD(newfilepathname, true);
|
||||
if(hashtest.IsOfficialIWAD)
|
||||
{
|
||||
General.WriteLogLine("Map saving aborted: attempt to modify an official IWAD");
|
||||
General.ShowErrorMessage("Official IWADs should not be modified.\nConsider making a PWAD instead", MessageBoxButtons.OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
hashtest.Dispose();
|
||||
hashtest = null;
|
||||
}
|
||||
|
||||
// Scripts changed?
|
||||
|
@ -786,79 +787,85 @@ namespace CodeImp.DoomBuilder
|
|||
}
|
||||
|
||||
//mxd. Target file is read-only?
|
||||
FileInfo info = new FileInfo(newfilepathname);
|
||||
if(info.Exists && info.IsReadOnly)
|
||||
if(fileexists)
|
||||
{
|
||||
if(General.ShowWarningMessage("Unable to save the map: target file is read-only.\nRemove read-only flag and save the map anyway?", MessageBoxButtons.YesNo) == DialogResult.Yes)
|
||||
FileInfo info = new FileInfo(newfilepathname);
|
||||
if(info.IsReadOnly)
|
||||
{
|
||||
General.WriteLogLine("Removing read-only flag from the map file...");
|
||||
try
|
||||
if(General.ShowWarningMessage("Unable to save the map: target file is read-only.\nRemove read-only flag and save the map anyway?", MessageBoxButtons.YesNo) == DialogResult.Yes)
|
||||
{
|
||||
info.IsReadOnly = false;
|
||||
General.WriteLogLine("Removing read-only flag from the map file...");
|
||||
try
|
||||
{
|
||||
info.IsReadOnly = false;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
General.ShowErrorMessage("Failed to remove read-only flag from \"" + filepathname + "\":" + Environment.NewLine + Environment.NewLine + e.Message, MessageBoxButtons.OK);
|
||||
General.WriteLogLine("Failed to remove read-only flag from \"" + filepathname + "\":" + e.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
else
|
||||
{
|
||||
General.ShowErrorMessage("Failed to remove read-only flag from \"" + filepathname + "\":" + Environment.NewLine + Environment.NewLine + e.Message, MessageBoxButtons.OK);
|
||||
General.WriteLogLine("Failed to remove read-only flag from \"" + filepathname + "\":" + e.Message);
|
||||
General.WriteLogLine("Map saving cancelled...");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
General.WriteLogLine("Map saving cancelled...");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Suspend data resources
|
||||
data.Suspend();
|
||||
|
||||
//mxd. Check if the target file is locked
|
||||
FileLockChecker.FileLockCheckResult checkresult = FileLockChecker.CheckFile(newfilepathname);
|
||||
if(!string.IsNullOrEmpty(checkresult.Error))
|
||||
if(fileexists)
|
||||
{
|
||||
if(checkresult.Processes.Count > 0)
|
||||
FileLockChecker.FileLockCheckResult checkresult = FileLockChecker.CheckFile(newfilepathname);
|
||||
if(!string.IsNullOrEmpty(checkresult.Error))
|
||||
{
|
||||
string rest = "Press 'Retry' to close " + (checkresult.Processes.Count > 1 ? "all processes" : "the process")
|
||||
+ " and retry." + Environment.NewLine + "Press 'Cancel' to cancel saving.";
|
||||
|
||||
if(General.ShowErrorMessage(checkresult.Error + rest, MessageBoxButtons.RetryCancel) == DialogResult.Retry)
|
||||
if(checkresult.Processes.Count > 0)
|
||||
{
|
||||
// Close all processes
|
||||
foreach(Process process in checkresult.Processes)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(!process.HasExited) process.Kill();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
General.ShowErrorMessage("Failed to close " + Path.GetFileName(process.MainModule.FileName) + ":" + Environment.NewLine + Environment.NewLine + e.Message, MessageBoxButtons.OK);
|
||||
data.Resume();
|
||||
General.WriteLogLine("Map saving failed: failed to close " + Path.GetFileName(process.MainModule.FileName));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
string rest = "Press 'Retry' to close " + (checkresult.Processes.Count > 1 ? "all processes" : "the process")
|
||||
+ " and retry." + Environment.NewLine + "Press 'Cancel' to cancel saving.";
|
||||
|
||||
// Retry
|
||||
data.Resume();
|
||||
General.WriteLogLine("Map saving restarted...");
|
||||
return SaveMap(newfilepathname, purpose);
|
||||
if(General.ShowErrorMessage(checkresult.Error + rest, MessageBoxButtons.RetryCancel) == DialogResult.Retry)
|
||||
{
|
||||
// Close all processes
|
||||
foreach(Process process in checkresult.Processes)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(!process.HasExited) process.Kill();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
General.ShowErrorMessage("Failed to close " + Path.GetFileName(process.MainModule.FileName) + ":" + Environment.NewLine + Environment.NewLine + e.Message, MessageBoxButtons.OK);
|
||||
data.Resume();
|
||||
General.WriteLogLine("Map saving failed: failed to close " + Path.GetFileName(process.MainModule.FileName));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Retry
|
||||
data.Resume();
|
||||
General.WriteLogLine("Map saving restarted...");
|
||||
return SaveMap(newfilepathname, purpose);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.Resume();
|
||||
General.WriteLogLine("Map saving cancelled...");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ShowErrorMessage(checkresult.Error, MessageBoxButtons.OK);
|
||||
data.Resume();
|
||||
General.WriteLogLine("Map saving cancelled...");
|
||||
General.WriteLogLine("Map saving failed: " + checkresult.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
General.ShowErrorMessage(checkresult.Error, MessageBoxButtons.OK);
|
||||
data.Resume();
|
||||
General.WriteLogLine("Map saving failed: " + checkresult.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine original map name
|
||||
|
@ -867,7 +874,7 @@ namespace CodeImp.DoomBuilder
|
|||
|
||||
try
|
||||
{
|
||||
if(File.Exists(newfilepathname))
|
||||
if(fileexists)
|
||||
{
|
||||
// mxd. Check if target wad already has a map with the same name
|
||||
if(purpose == SavePurpose.IntoFile)
|
||||
|
|
2
Source/Core/Windows/MainForm.Designer.cs
generated
2
Source/Core/Windows/MainForm.Designer.cs
generated
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using System.Windows.Forms;
|
||||
using CodeImp.DoomBuilder.Controls;
|
||||
|
||||
|
@ -407,6 +408,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.menufile.Name = "menufile";
|
||||
this.menufile.Size = new System.Drawing.Size(37, 20);
|
||||
this.menufile.Text = "&File";
|
||||
this.menufile.DropDownOpening += menufile_DropDownOpening;
|
||||
//
|
||||
// itemnewmap
|
||||
//
|
||||
|
|
|
@ -2603,13 +2603,9 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
internal void AddRecentFile(string filename)
|
||||
{
|
||||
//mxd. Recreate recent files list
|
||||
if(recentitems.Length != General.Settings.MaxRecentFiles)
|
||||
if(recentitems.Length != General.Settings.MaxRecentFiles)
|
||||
{
|
||||
foreach(ToolStripMenuItem item in recentitems)
|
||||
menufile.DropDownItems.Remove(item);
|
||||
|
||||
SaveRecentFiles();
|
||||
CreateRecentFiles();
|
||||
UpdateRecentItems();
|
||||
}
|
||||
|
||||
int movedownto = General.Settings.MaxRecentFiles - 1;
|
||||
|
@ -2645,6 +2641,16 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
itemnorecent.Visible = false;
|
||||
}
|
||||
|
||||
//mxd
|
||||
private void UpdateRecentItems()
|
||||
{
|
||||
foreach(ToolStripMenuItem item in recentitems)
|
||||
menufile.DropDownItems.Remove(item);
|
||||
|
||||
SaveRecentFiles();
|
||||
CreateRecentFiles();
|
||||
}
|
||||
|
||||
// This returns the trimmed file/path string
|
||||
private string GetDisplayFilename(string filename)
|
||||
{
|
||||
|
@ -2689,6 +2695,12 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
// Open this file
|
||||
General.OpenMapFile(item.Tag.ToString(), null);
|
||||
}
|
||||
|
||||
//mxd
|
||||
private void menufile_DropDownOpening(object sender, EventArgs e)
|
||||
{
|
||||
UpdateRecentItems();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#region ================== Namespaces
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using CodeImp.DoomBuilder.Config;
|
||||
using CodeImp.DoomBuilder.Data;
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using CodeImp.DoomBuilder.Data;
|
||||
using System.IO;
|
||||
using CodeImp.DoomBuilder.Data;
|
||||
using CodeImp.DoomBuilder.Rendering;
|
||||
|
||||
#endregion
|
||||
|
@ -45,10 +45,9 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
private readonly bool flipy;
|
||||
private readonly float alpha;
|
||||
private readonly int rotation; //mxd
|
||||
private readonly TexturePathRenderStyle renderStyle; //mxd
|
||||
private readonly PixelColor blendColor; //mxd
|
||||
private readonly TexturePathBlendStyle blendStyle; //mxd
|
||||
private readonly float tintAmmount; //mxd
|
||||
private readonly TexturePathRenderStyle renderstyle; //mxd
|
||||
private readonly PixelColor blendcolor; //mxd
|
||||
private readonly TexturePathBlendStyle blendstyle; //mxd
|
||||
private static readonly string[] renderStyles = { "copy", "translucent", "add", "subtract", "reversesubtract", "modulate", "copyalpha", "copynewalpha", "overlay" }; //mxd
|
||||
private readonly bool skip; //mxd
|
||||
|
||||
|
@ -63,10 +62,9 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
public bool FlipY { get { return flipy; } }
|
||||
public float Alpha { get { return alpha; } }
|
||||
public int Rotation { get { return rotation; } } //mxd
|
||||
public TexturePathRenderStyle RenderStyle { get { return renderStyle; } } //mxd
|
||||
public TexturePathBlendStyle BlendStyle { get { return blendStyle; } }
|
||||
public float TintAmmount { get { return tintAmmount; } }
|
||||
public PixelColor BlendColor { get { return blendColor; } }//mxd
|
||||
public TexturePathRenderStyle RenderStyle { get { return renderstyle; } } //mxd
|
||||
public TexturePathBlendStyle BlendStyle { get { return blendstyle; } }
|
||||
public PixelColor BlendColor { get { return blendcolor; } }//mxd
|
||||
public bool Skip { get { return skip; } } //mxd
|
||||
|
||||
#endregion
|
||||
|
@ -78,8 +76,8 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
{
|
||||
// Initialize
|
||||
alpha = 1.0f;
|
||||
renderStyle = TexturePathRenderStyle.Copy;//mxd
|
||||
blendStyle = TexturePathBlendStyle.None; //mxd
|
||||
renderstyle = TexturePathRenderStyle.COPY;//mxd
|
||||
blendstyle = TexturePathBlendStyle.NONE; //mxd
|
||||
|
||||
// There should be 3 tokens separated by 2 commas now:
|
||||
// Name, Width, Height
|
||||
|
@ -164,30 +162,69 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
string s;
|
||||
if(!ReadTokenString(parser, token, out s)) return;
|
||||
int index = Array.IndexOf(renderStyles, s.ToLowerInvariant());
|
||||
renderStyle = index == -1 ? TexturePathRenderStyle.Copy : (TexturePathRenderStyle) index;
|
||||
renderstyle = index == -1 ? TexturePathRenderStyle.COPY : (TexturePathRenderStyle) index;
|
||||
break;
|
||||
|
||||
case "blend": //mxd
|
||||
int val;
|
||||
if(!ReadTokenColor(parser, token, out val)) return;
|
||||
blendColor = PixelColor.FromInt(val);
|
||||
|
||||
parser.SkipWhitespace(false);
|
||||
token = parser.ReadToken();
|
||||
PixelColor color = new PixelColor();
|
||||
|
||||
if(token == ",") //read tint ammount
|
||||
{
|
||||
parser.SkipWhitespace(false);
|
||||
if(!ReadTokenFloat(parser, token, out tintAmmount)) return;
|
||||
tintAmmount = General.Clamp(tintAmmount, 0.0f, 1.0f);
|
||||
blendStyle = TexturePathBlendStyle.Tint;
|
||||
}
|
||||
else
|
||||
// Blend <string color>[,<float alpha>] block?
|
||||
token = parser.ReadToken(false);
|
||||
if(!parser.ReadByte(token, ref color.r))
|
||||
{
|
||||
blendStyle = TexturePathBlendStyle.Blend;
|
||||
// Rewind so this structure can be read again
|
||||
parser.DataStream.Seek(-token.Length, SeekOrigin.Current);
|
||||
if(!ZDTextParser.GetColorFromString(token, ref color))
|
||||
{
|
||||
parser.ReportError("Unsupported patch blend definition");
|
||||
return;
|
||||
}
|
||||
}
|
||||
// That's Blend <int r>,<int g>,<int b>[,<float alpha>] block
|
||||
else
|
||||
{
|
||||
if(!parser.SkipWhitespace(false) ||
|
||||
!parser.NextTokenIs(",", false) || !parser.SkipWhitespace(false) || !parser.ReadByte(ref color.g) ||
|
||||
!parser.NextTokenIs(",", false) || !parser.SkipWhitespace(false) || !parser.ReadByte(ref color.b))
|
||||
{
|
||||
parser.ReportError("Unsupported patch blend definition");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Alpha block?
|
||||
float blendalpha = -1f;
|
||||
parser.SkipWhitespace(false);
|
||||
if(parser.NextTokenIs(",", false))
|
||||
{
|
||||
parser.SkipWhitespace(false);
|
||||
if(!ReadTokenFloat(parser, token, out blendalpha))
|
||||
{
|
||||
parser.ReportError("Unsupported patch blend alpha value");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Blend may never be 0 when using the Tint effect
|
||||
if(blendalpha > 0.0f)
|
||||
{
|
||||
color.a = (byte)General.Clamp((int)(blendalpha * 255), 1, 254);
|
||||
blendstyle = TexturePathBlendStyle.TINT;
|
||||
|
||||
}
|
||||
else if(blendalpha < 0.0f)
|
||||
{
|
||||
color.a = 255;
|
||||
blendstyle = TexturePathBlendStyle.BLEND;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ignore Blend when alpha == 0
|
||||
parser.LogWarning("Blend with zero alpha will be ignored by ZDoom");
|
||||
break;
|
||||
}
|
||||
|
||||
// Store the color
|
||||
blendcolor = color;
|
||||
break;
|
||||
|
||||
case "}":
|
||||
|
@ -268,36 +305,6 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
return true;
|
||||
}
|
||||
|
||||
//mxd. This reads the next token and sets a PixelColor value, returns false when failed
|
||||
private static bool ReadTokenColor(TexturesParser parser, string propertyname, out int value)
|
||||
{
|
||||
parser.SkipWhitespace(true);
|
||||
string strvalue = parser.StripTokenQuotes(parser.ReadToken());
|
||||
value = 0;
|
||||
|
||||
if(string.IsNullOrEmpty(strvalue))
|
||||
{
|
||||
// Can't find the property value!
|
||||
parser.ReportError("Expected a value for property \"" + propertyname + "\"");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strvalue[0] != '#')
|
||||
{
|
||||
parser.ReportError("Expected color value for property \"" + propertyname + "\"");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try parsing as value
|
||||
if(!int.TryParse(strvalue.Remove(0, 1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out value))
|
||||
{
|
||||
parser.ReportError("Expected color value for property \"" + propertyname + "\"");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
87
Source/Core/ZDoom/X11R6RGBParser.cs
Normal file
87
Source/Core/ZDoom/X11R6RGBParser.cs
Normal file
|
@ -0,0 +1,87 @@
|
|||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using CodeImp.DoomBuilder.Config;
|
||||
using CodeImp.DoomBuilder.Data;
|
||||
using CodeImp.DoomBuilder.Rendering;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.ZDoom
|
||||
{
|
||||
internal sealed class X11R6RGBParser : ZDTextParser
|
||||
{
|
||||
#region ================== Variables
|
||||
|
||||
private readonly Dictionary<string, PixelColor> knowncolors;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
internal override ScriptType ScriptType { get { return ScriptType.X11R6RGB; } }
|
||||
|
||||
public Dictionary<string, PixelColor> KnownColors { get { return knowncolors; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor
|
||||
|
||||
internal X11R6RGBParser()
|
||||
{
|
||||
knowncolors = new Dictionary<string, PixelColor>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Parsing
|
||||
|
||||
public override bool Parse(TextResourceData data, bool clearerrors)
|
||||
{
|
||||
// Already parsed?
|
||||
if(!base.AddTextResource(data))
|
||||
{
|
||||
if(clearerrors) ClearError();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Cannot process?
|
||||
if(!base.Parse(data, clearerrors)) return false;
|
||||
|
||||
// Continue until at the end of the stream
|
||||
char[] space = {' ', '\t'};
|
||||
while(SkipWhitespace(true))
|
||||
{
|
||||
string line = ReadLine();
|
||||
if(string.IsNullOrEmpty(line) || line.StartsWith("!")) continue; // Skip comments
|
||||
|
||||
// "R G B Name with spaces"
|
||||
string[] parts = line.Split(space, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if(parts.Length < 4)
|
||||
{
|
||||
ReportError("Incorrect X11R6RGB color assignment");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse colors
|
||||
byte r = 0, g = 0, b = 0;
|
||||
if(!ReadByte(parts[0], ref r)) { ReportError("Expected red color value in [0 .. 255] range"); return false; }
|
||||
if(!ReadByte(parts[1], ref g)) { ReportError("Expected green color value in [0 .. 255] range"); return false; }
|
||||
if(!ReadByte(parts[2], ref b)) { ReportError("Expected blue color value in [0 .. 255] range"); return false; }
|
||||
|
||||
// Assemble name
|
||||
string colorname = string.Join("", parts, 3, parts.Length - 3);
|
||||
|
||||
// Add to collection
|
||||
knowncolors[colorname] = new PixelColor(255, r, g, b);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ using System.IO;
|
|||
using CodeImp.DoomBuilder.Compilers;
|
||||
using CodeImp.DoomBuilder.Config;
|
||||
using CodeImp.DoomBuilder.Data;
|
||||
using CodeImp.DoomBuilder.Rendering;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -557,6 +558,65 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
return success;
|
||||
}
|
||||
|
||||
//mxd
|
||||
protected internal bool ReadByte(ref byte value) { return ReadByte(StripTokenQuotes(ReadToken(false)), ref value); }
|
||||
protected internal bool ReadByte(string token, ref byte value)
|
||||
{
|
||||
if(token == "-") return false;
|
||||
|
||||
int result;
|
||||
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out result) || result < 0 || result > 255)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
value = (byte)result;
|
||||
return true;
|
||||
}
|
||||
|
||||
//mxd. This replicates ZDoom's V_GetColorFromString method
|
||||
public static bool GetColorFromString(string name, ref PixelColor color)
|
||||
{
|
||||
name = StripQuotes(name.Replace(" ", ""));
|
||||
|
||||
// Check for HTML-style #RRGGBB or #RGB color string
|
||||
bool ishtmlcolor = false;
|
||||
if(name.StartsWith("#"))
|
||||
{
|
||||
ishtmlcolor = true;
|
||||
name = name.Remove(0, 1);
|
||||
|
||||
// Expand RGB to RRGGBB
|
||||
if(name.Length == 3)
|
||||
{
|
||||
name = name[0].ToString() + name[0] + name[1] + name[1] + name[2] + name[2];
|
||||
}
|
||||
else if(name.Length != 6)
|
||||
{
|
||||
// Bad HTML-style; pretend it's black.
|
||||
color = new PixelColor();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Probably it's a hex color (like FFCC11)?
|
||||
int ci;
|
||||
if(int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ci))
|
||||
{
|
||||
color = PixelColor.FromInt(ci).WithAlpha(255);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Probably it's a color name?
|
||||
if(!ishtmlcolor && General.Map.Data.KnownColors.ContainsKey(name))
|
||||
{
|
||||
color = General.Map.Data.KnownColors[name];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//mxd
|
||||
protected void SkipStructure() { SkipStructure(new HashSet<string>()); }
|
||||
protected void SkipStructure(HashSet<string> breakat)
|
||||
|
|
Loading…
Reference in a new issue