mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-05-31 09:01:22 +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";
|
1 = "Disable light effects";
|
||||||
2 = "Restrict light inside";
|
2 = "Restrict light inside";
|
||||||
4 = "Fog effect (GZDoom) / Fade effect (ZDoom)";
|
4 = "Fog effect (GZDoom only)";
|
||||||
8 = "Ignore bottom height";
|
8 = "Ignore bottom height";
|
||||||
16 = "Use upper texture";
|
16 = "Use upper texture";
|
||||||
32 = "Use lower texture";
|
32 = "Use lower texture";
|
||||||
|
|
|
@ -1021,6 +1021,7 @@
|
||||||
<Compile Include="ZDoom\TexturesParser.cs" />
|
<Compile Include="ZDoom\TexturesParser.cs" />
|
||||||
<Compile Include="ZDoom\TextureStructure.cs" />
|
<Compile Include="ZDoom\TextureStructure.cs" />
|
||||||
<Compile Include="ZDoom\VoxeldefParser.cs" />
|
<Compile Include="ZDoom\VoxeldefParser.cs" />
|
||||||
|
<Compile Include="ZDoom\X11R6RGBParser.cs" />
|
||||||
<Compile Include="ZDoom\ZDTextParser.cs" />
|
<Compile Include="ZDoom\ZDTextParser.cs" />
|
||||||
<Compile Include="ZDoom\DecorateParser.cs" />
|
<Compile Include="ZDoom\DecorateParser.cs" />
|
||||||
<Compile Include="ZDoom\StateStructure.cs" />
|
<Compile Include="ZDoom\StateStructure.cs" />
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace CodeImp.DoomBuilder.Config
|
||||||
ANIMDEFS = 9,
|
ANIMDEFS = 9,
|
||||||
REVERBS = 10,
|
REVERBS = 10,
|
||||||
TERRAIN = 11,
|
TERRAIN = 11,
|
||||||
|
X11R6RGB = 12,
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ScriptConfiguration : IComparable<ScriptConfiguration>
|
internal class ScriptConfiguration : IComparable<ScriptConfiguration>
|
||||||
|
|
|
@ -97,6 +97,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
private string[] soundsequences;
|
private string[] soundsequences;
|
||||||
private string[] terrainnames;
|
private string[] terrainnames;
|
||||||
private string[] damagetypes;
|
private string[] damagetypes;
|
||||||
|
private Dictionary<string, PixelColor> knowncolors; // Colors parsed from X11R6RGB lump. Color names are lowercase without spaces
|
||||||
|
|
||||||
//mxd. Text resources
|
//mxd. Text resources
|
||||||
private Dictionary<ScriptType, HashSet<TextResource>> textresources;
|
private Dictionary<ScriptType, HashSet<TextResource>> textresources;
|
||||||
|
@ -156,6 +157,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
public string[] SoundSequences { get { return soundsequences; } }
|
public string[] SoundSequences { get { return soundsequences; } }
|
||||||
public string[] TerrainNames { get { return terrainnames; } }
|
public string[] TerrainNames { get { return terrainnames; } }
|
||||||
public string[] DamageTypes { get { return damagetypes; } }
|
public string[] DamageTypes { get { return damagetypes; } }
|
||||||
|
public Dictionary<string, PixelColor> KnownColors { get { return knowncolors; } }
|
||||||
internal Dictionary<ScriptType, HashSet<TextResource>> TextResources { get { return textresources; } }
|
internal Dictionary<ScriptType, HashSet<TextResource>> TextResources { get { return textresources; } }
|
||||||
|
|
||||||
//mxd
|
//mxd
|
||||||
|
@ -326,6 +328,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
terrainnames = new string[0];
|
terrainnames = new string[0];
|
||||||
textresources = new Dictionary<ScriptType, HashSet<TextResource>>();
|
textresources = new Dictionary<ScriptType, HashSet<TextResource>>();
|
||||||
damagetypes = new string[0];
|
damagetypes = new string[0];
|
||||||
|
knowncolors = new Dictionary<string, PixelColor>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
// Load texture sets
|
// Load texture sets
|
||||||
foreach(DefinedTextureSet ts in General.Map.ConfigSettings.TextureSets)
|
foreach(DefinedTextureSet ts in General.Map.ConfigSettings.TextureSets)
|
||||||
|
@ -386,6 +389,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load stuff
|
// Load stuff
|
||||||
|
LoadX11R6RGB(); //mxd
|
||||||
LoadPalette();
|
LoadPalette();
|
||||||
Dictionary<string, TexturesParser> cachedparsers = new Dictionary<string, TexturesParser>(); //mxd
|
Dictionary<string, TexturesParser> cachedparsers = new Dictionary<string, TexturesParser>(); //mxd
|
||||||
int texcount = LoadTextures(texturesonly, texturenamesshorttofull, cachedparsers);
|
int texcount = LoadTextures(texturesonly, texturenamesshorttofull, cachedparsers);
|
||||||
|
@ -588,6 +592,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
terrainnames = null; //mxd
|
terrainnames = null; //mxd
|
||||||
textresources = null; //mxd
|
textresources = null; //mxd
|
||||||
damagetypes = null; //mxd
|
damagetypes = null; //mxd
|
||||||
|
knowncolors = null; //mxd
|
||||||
texturenames = null;
|
texturenames = null;
|
||||||
flatnames = null;
|
flatnames = null;
|
||||||
imageque = null;
|
imageque = null;
|
||||||
|
@ -801,10 +806,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
while(true);
|
while(true);
|
||||||
}
|
}
|
||||||
catch(ThreadInterruptedException)
|
catch(ThreadInterruptedException) { }
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This adds an image for background loading or unloading
|
// This adds an image for background loading or unloading
|
||||||
|
@ -2460,6 +2462,34 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
terrainnames = names.ToArray();
|
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
|
//mxd
|
||||||
internal TextResourceData GetTextResourceData(string name)
|
internal TextResourceData GetTextResourceData(string name)
|
||||||
{
|
{
|
||||||
|
|
|
@ -240,6 +240,9 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
//mxd. When implemented, this returns the TERRAIN lump
|
//mxd. When implemented, this returns the TERRAIN lump
|
||||||
public abstract IEnumerable<TextResourceData> GetTerrainData();
|
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
|
//mxd. When implemented, this returns the list of voxel model names
|
||||||
public abstract IEnumerable<string> GetVoxelNames();
|
public abstract IEnumerable<string> GetVoxelNames();
|
||||||
|
|
||||||
|
|
|
@ -701,7 +701,6 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
|
|
||||||
#region ================== TERRAIN (mxd)
|
#region ================== TERRAIN (mxd)
|
||||||
|
|
||||||
//mxd
|
|
||||||
public override IEnumerable<TextResourceData> GetTerrainData()
|
public override IEnumerable<TextResourceData> GetTerrainData()
|
||||||
{
|
{
|
||||||
// Error when suspended
|
// Error when suspended
|
||||||
|
@ -722,6 +721,28 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
|
|
||||||
#endregion
|
#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
|
#region ================== Methods
|
||||||
|
|
||||||
// This loads the images in this directory
|
// This loads the images in this directory
|
||||||
|
|
|
@ -98,7 +98,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
{
|
{
|
||||||
// Add it
|
// Add it
|
||||||
patches.Add(patch);
|
patches.Add(patch);
|
||||||
if(patch.lumpname == Name) hasPatchWithSameName = true; //mxd
|
if(patch.LumpName == Name) hasPatchWithSameName = true; //mxd
|
||||||
}
|
}
|
||||||
|
|
||||||
// This loads the image
|
// This loads the image
|
||||||
|
@ -143,11 +143,11 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
foreach(TexturePatch p in patches)
|
foreach(TexturePatch p in patches)
|
||||||
{
|
{
|
||||||
//mxd. Some patches (like "TNT1A0") should be skipped
|
//mxd. Some patches (like "TNT1A0") should be skipped
|
||||||
if(p.skip) continue;
|
if(p.Skip) continue;
|
||||||
|
|
||||||
// Get the patch data stream
|
// Get the patch data stream
|
||||||
string patchlocation = string.Empty; //mxd
|
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)
|
if(patchdata != null)
|
||||||
{
|
{
|
||||||
// Copy patch data to memory
|
// Copy patch data to memory
|
||||||
|
@ -170,7 +170,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
if(reader is UnknownImageReader)
|
if(reader is UnknownImageReader)
|
||||||
{
|
{
|
||||||
// Data is in an unknown format!
|
// 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
|
missingpatches++; //mxd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,7 +184,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
catch(InvalidDataException)
|
catch(InvalidDataException)
|
||||||
{
|
{
|
||||||
// Data cannot be read!
|
// 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
|
missingpatches++; //mxd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
patchbmp = TransformPatch(p, patchbmp);
|
patchbmp = TransformPatch(p, patchbmp);
|
||||||
|
|
||||||
// Draw the patch on the texture image
|
// 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);
|
g.DrawImageUnscaledAndClipped(patchbmp, tgtrect);
|
||||||
patchbmp.Dispose();
|
patchbmp.Dispose();
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
//mxd. ZDoom can use any known graphic as patch
|
//mxd. ZDoom can use any known graphic as patch
|
||||||
if(General.Map.Config.MixTexturesFlats)
|
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 is UnknownImage) && img != this)
|
||||||
{
|
{
|
||||||
if(!img.IsImageLoaded) img.LoadImage();
|
if(!img.IsImageLoaded) img.LoadImage();
|
||||||
|
@ -217,7 +217,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
Bitmap patchbmp = TransformPatch(p, new Bitmap(img.GetBitmap()));
|
Bitmap patchbmp = TransformPatch(p, new Bitmap(img.GetBitmap()));
|
||||||
|
|
||||||
// Draw the patch on the texture image
|
// 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);
|
g.DrawImageUnscaledAndClipped(patchbmp, tgtrect);
|
||||||
patchbmp.Dispose();
|
patchbmp.Dispose();
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
// Missing a patch lump!
|
// 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
|
missingpatches++; //mxd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,20 +249,20 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
private Bitmap TransformPatch(TexturePatch p, Bitmap patchbmp)
|
private Bitmap TransformPatch(TexturePatch p, Bitmap patchbmp)
|
||||||
{
|
{
|
||||||
//mxd. Flip
|
//mxd. Flip
|
||||||
if(p.flipx || p.flipy)
|
if(p.FlipX || p.FlipY)
|
||||||
{
|
{
|
||||||
RotateFlipType flip;
|
RotateFlipType flip;
|
||||||
if(p.flipx && !p.flipy) flip = RotateFlipType.RotateNoneFlipX;
|
if(p.FlipX && !p.FlipY) flip = RotateFlipType.RotateNoneFlipX;
|
||||||
else if(!p.flipx && p.flipy) flip = RotateFlipType.RotateNoneFlipY;
|
else if(!p.FlipX && p.FlipY) flip = RotateFlipType.RotateNoneFlipY;
|
||||||
else flip = RotateFlipType.RotateNoneFlipXY;
|
else flip = RotateFlipType.RotateNoneFlipXY;
|
||||||
patchbmp.RotateFlip(flip);
|
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.
|
//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;
|
RotateFlipType rotate;
|
||||||
switch(p.rotate)
|
switch(p.Rotate)
|
||||||
{
|
{
|
||||||
case 90: rotate = RotateFlipType.Rotate90FlipNone; break;
|
case 90: rotate = RotateFlipType.Rotate90FlipNone; break;
|
||||||
case 180: rotate = RotateFlipType.Rotate180FlipNone; break;
|
case 180: rotate = RotateFlipType.Rotate180FlipNone; break;
|
||||||
|
@ -272,7 +272,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust patch alpha, apply tint or blend
|
// 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;
|
BitmapData bmpdata = null;
|
||||||
|
|
||||||
|
@ -282,61 +282,61 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
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)
|
if(bmpdata != null)
|
||||||
{
|
{
|
||||||
PixelColor* pixels = (PixelColor*)(bmpdata.Scan0.ToPointer());
|
PixelColor* pixels = (PixelColor*)(bmpdata.Scan0.ToPointer());
|
||||||
int numpixels = bmpdata.Width * bmpdata.Height;
|
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
|
//mxd. Blend/Tint support
|
||||||
if(p.blendstyle == TexturePathBlendStyle.Blend)
|
if(p.BlendStyle == TexturePathBlendStyle.BLEND)
|
||||||
{
|
{
|
||||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||||
{
|
{
|
||||||
cp->r = (byte)((cp->r * p.blend.r) * PixelColor.BYTE_TO_FLOAT);
|
cp->r = (byte)((cp->r * p.BlendColor.r) * PixelColor.BYTE_TO_FLOAT);
|
||||||
cp->g = (byte)((cp->g * p.blend.g) * PixelColor.BYTE_TO_FLOAT);
|
cp->g = (byte)((cp->g * p.BlendColor.g) * PixelColor.BYTE_TO_FLOAT);
|
||||||
cp->b = (byte)((cp->b * p.blend.b) * 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)
|
if(tintammount > 0)
|
||||||
{
|
{
|
||||||
float br = p.blend.r * PixelColor.BYTE_TO_FLOAT * tintammount;
|
float br = p.BlendColor.r * PixelColor.BYTE_TO_FLOAT * tintammount;
|
||||||
float bg = p.blend.g * PixelColor.BYTE_TO_FLOAT * tintammount;
|
float bg = p.BlendColor.g * PixelColor.BYTE_TO_FLOAT * tintammount;
|
||||||
float bb = p.blend.b * PixelColor.BYTE_TO_FLOAT * tintammount;
|
float bb = p.BlendColor.b * PixelColor.BYTE_TO_FLOAT * tintammount;
|
||||||
float invTint = 1.0f - tintammount;
|
float invtintammount = 1.0f - tintammount;
|
||||||
|
|
||||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||||
{
|
{
|
||||||
cp->r = (byte)(((cp->r * PixelColor.BYTE_TO_FLOAT) * invTint + br) * 255.0f);
|
cp->r = (byte)(((cp->r * PixelColor.BYTE_TO_FLOAT) * invtintammount + br) * 255.0f);
|
||||||
cp->g = (byte)(((cp->g * PixelColor.BYTE_TO_FLOAT) * invTint + bg) * 255.0f);
|
cp->g = (byte)(((cp->g * PixelColor.BYTE_TO_FLOAT) * invtintammount + bg) * 255.0f);
|
||||||
cp->b = (byte)(((cp->b * PixelColor.BYTE_TO_FLOAT) * invTint + bb) * 255.0f);
|
cp->b = (byte)(((cp->b * PixelColor.BYTE_TO_FLOAT) * invtintammount + bb) * 255.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//mxd. Apply RenderStyle
|
//mxd. Apply RenderStyle
|
||||||
if(p.style == TexturePathRenderStyle.Blend)
|
if(p.RenderStyle == TexturePathRenderStyle.BLEND)
|
||||||
{
|
{
|
||||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||||
cp->a = (byte)((cp->a * patchalpha) * PixelColor.BYTE_TO_FLOAT);
|
cp->a = (byte)((cp->a * patchalpha) * PixelColor.BYTE_TO_FLOAT);
|
||||||
}
|
}
|
||||||
//mxd. We need a copy of underlying part of texture for these styles
|
//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
|
// Copy portion of texture
|
||||||
int lockWidth = (p.x + patchbmp.Size.Width > bitmap.Width) ? bitmap.Width - p.x : patchbmp.Size.Width;
|
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 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);
|
Bitmap source = new Bitmap(patchbmp.Size.Width, patchbmp.Size.Height);
|
||||||
using(Graphics sg = Graphics.FromImage(source))
|
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
|
// Lock texture
|
||||||
BitmapData texturebmpdata = null;
|
BitmapData texturebmpdata = null;
|
||||||
|
@ -355,9 +355,9 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
PixelColor* texturepixels = (PixelColor*)(texturebmpdata.Scan0.ToPointer());
|
PixelColor* texturepixels = (PixelColor*)(texturebmpdata.Scan0.ToPointer());
|
||||||
PixelColor* tcp = texturepixels + numpixels - 1;
|
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--)
|
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||||
{
|
{
|
||||||
cp->r = (byte)Math.Min(255, cp->r + tcp->r);
|
cp->r = (byte)Math.Min(255, cp->r + tcp->r);
|
||||||
|
@ -368,7 +368,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TexturePathRenderStyle.Subtract:
|
case TexturePathRenderStyle.SUBTRACT:
|
||||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||||
{
|
{
|
||||||
cp->r = (byte)Math.Max(0, tcp->r - cp->r);
|
cp->r = (byte)Math.Max(0, tcp->r - cp->r);
|
||||||
|
@ -379,7 +379,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TexturePathRenderStyle.ReverseSubtract:
|
case TexturePathRenderStyle.REVERSE_SUBTRACT:
|
||||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||||
{
|
{
|
||||||
cp->r = (byte)Math.Max(0, cp->r - tcp->r);
|
cp->r = (byte)Math.Max(0, cp->r - tcp->r);
|
||||||
|
@ -390,7 +390,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TexturePathRenderStyle.Modulate:
|
case TexturePathRenderStyle.MODULATE:
|
||||||
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
for(PixelColor* cp = pixels + numpixels - 1; cp >= pixels; cp--)
|
||||||
{
|
{
|
||||||
cp->r = (byte)((cp->r * tcp->r) * PixelColor.BYTE_TO_FLOAT);
|
cp->r = (byte)((cp->r * tcp->r) * PixelColor.BYTE_TO_FLOAT);
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
// Add it
|
// Add it
|
||||||
patches.Add(patch);
|
patches.Add(patch);
|
||||||
|
|
||||||
if(patch.lumpname == Name) hasPatchWithSameName = true; //mxd
|
if(patch.LumpName == Name) hasPatchWithSameName = true; //mxd
|
||||||
}
|
}
|
||||||
|
|
||||||
// This loads the image
|
// This loads the image
|
||||||
|
@ -103,7 +103,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
{
|
{
|
||||||
// Get the patch data stream
|
// Get the patch data stream
|
||||||
string patchlocation = string.Empty; //mxd
|
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)
|
if(patchdata != null)
|
||||||
{
|
{
|
||||||
// Copy patch data to memory
|
// Copy patch data to memory
|
||||||
|
@ -125,7 +125,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
if(reader is UnknownImageReader)
|
if(reader is UnknownImageReader)
|
||||||
{
|
{
|
||||||
// Data is in an unknown format!
|
// 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;
|
loadfailed = true;
|
||||||
missingpatches++; //mxd
|
missingpatches++; //mxd
|
||||||
}
|
}
|
||||||
|
@ -135,11 +135,11 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
{
|
{
|
||||||
// Draw the patch
|
// Draw the patch
|
||||||
mem.Seek(0, SeekOrigin.Begin);
|
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)
|
catch(InvalidDataException)
|
||||||
{
|
{
|
||||||
// Data cannot be read!
|
// 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;
|
loadfailed = true;
|
||||||
missingpatches++; //mxd
|
missingpatches++; //mxd
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Missing a patch lump!
|
// 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;
|
loadfailed = true;
|
||||||
missingpatches++; //mxd
|
missingpatches++; //mxd
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,93 +26,90 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
{
|
{
|
||||||
public enum TexturePathRenderStyle
|
public enum TexturePathRenderStyle
|
||||||
{
|
{
|
||||||
Copy,
|
COPY,
|
||||||
Blend,
|
BLEND,
|
||||||
Add,
|
ADD,
|
||||||
Subtract,
|
SUBTRACT,
|
||||||
ReverseSubtract,
|
REVERSE_SUBTRACT,
|
||||||
Modulate,
|
MODULATE,
|
||||||
CopyAlpha,
|
COPY_ALPHA,
|
||||||
CopyNewAlpha, //mxd
|
COPY_NEW_ALPHA, //mxd
|
||||||
Overlay, //mxd
|
OVERLAY, //mxd
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum TexturePathBlendStyle //mxd
|
public enum TexturePathBlendStyle //mxd
|
||||||
{
|
{
|
||||||
None,
|
NONE,
|
||||||
Blend,
|
BLEND,
|
||||||
Tint
|
TINT
|
||||||
}
|
}
|
||||||
|
|
||||||
internal struct TexturePatch
|
internal struct TexturePatch
|
||||||
{
|
{
|
||||||
public readonly string lumpname;
|
public readonly string LumpName;
|
||||||
public readonly int x;
|
public readonly int X;
|
||||||
public readonly int y;
|
public readonly int Y;
|
||||||
public readonly bool flipx;
|
public readonly bool FlipX;
|
||||||
public readonly bool flipy;
|
public readonly bool FlipY;
|
||||||
public readonly bool haslongname; //mxd
|
public readonly bool HasLongName; //mxd
|
||||||
public readonly int rotate;
|
public readonly int Rotate;
|
||||||
public PixelColor blend;
|
public PixelColor BlendColor;
|
||||||
public readonly float alpha;
|
public readonly float Alpha;
|
||||||
public readonly TexturePathRenderStyle style;
|
public readonly TexturePathRenderStyle RenderStyle;
|
||||||
public readonly TexturePathBlendStyle blendstyle; //mxd
|
public readonly TexturePathBlendStyle BlendStyle; //mxd
|
||||||
public readonly float tintammount;//mxd
|
public readonly bool Skip; //mxd
|
||||||
public readonly bool skip; //mxd
|
|
||||||
|
|
||||||
// Constructor for simple patches
|
// Constructor for simple patches
|
||||||
public TexturePatch(string lumpname, int x, int y)
|
public TexturePatch(string lumpname, int x, int y)
|
||||||
{
|
{
|
||||||
// Initialize
|
// Initialize
|
||||||
this.lumpname = lumpname;
|
this.LumpName = lumpname;
|
||||||
this.x = x;
|
this.X = x;
|
||||||
this.y = y;
|
this.Y = y;
|
||||||
this.flipx = false;
|
this.FlipX = false;
|
||||||
this.flipy = false;
|
this.FlipY = false;
|
||||||
this.rotate = 0;
|
this.Rotate = 0;
|
||||||
this.blend = new PixelColor(0, 0, 0, 0);
|
this.BlendColor = new PixelColor(0, 0, 0, 0);
|
||||||
this.alpha = 1.0f;
|
this.Alpha = 1.0f;
|
||||||
this.style = TexturePathRenderStyle.Copy;
|
this.RenderStyle = TexturePathRenderStyle.COPY;
|
||||||
this.blendstyle = TexturePathBlendStyle.None;//mxd
|
this.BlendStyle = TexturePathBlendStyle.NONE;//mxd
|
||||||
this.tintammount = 0; //mxd
|
this.HasLongName = false; //mxd
|
||||||
this.haslongname = false; //mxd
|
this.Skip = false; //mxd
|
||||||
this.skip = false; //mxd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//mxd. Constructor for hires patches
|
//mxd. Constructor for hires patches
|
||||||
public TexturePatch(PatchStructure patch)
|
public TexturePatch(PatchStructure patch)
|
||||||
{
|
{
|
||||||
// Initialize
|
// Initialize
|
||||||
this.lumpname = patch.Name.ToUpperInvariant();
|
this.LumpName = patch.Name.ToUpperInvariant();
|
||||||
this.x = patch.OffsetX;
|
this.X = patch.OffsetX;
|
||||||
this.y = patch.OffsetY;
|
this.Y = patch.OffsetY;
|
||||||
this.flipx = patch.FlipX;
|
this.FlipX = patch.FlipX;
|
||||||
this.flipy = patch.FlipY;
|
this.FlipY = patch.FlipY;
|
||||||
this.rotate = patch.Rotation;
|
this.Rotate = patch.Rotation;
|
||||||
this.blend = patch.BlendColor;
|
this.BlendColor = patch.BlendColor;
|
||||||
this.alpha = patch.Alpha;
|
this.Alpha = patch.Alpha;
|
||||||
this.style = patch.RenderStyle;
|
this.RenderStyle = patch.RenderStyle;
|
||||||
this.blendstyle = patch.BlendStyle;
|
this.BlendStyle = patch.BlendStyle;
|
||||||
this.tintammount = patch.TintAmmount;
|
this.HasLongName = (Path.GetFileNameWithoutExtension(this.LumpName) != this.LumpName);
|
||||||
this.haslongname = (Path.GetFileNameWithoutExtension(this.lumpname) != this.lumpname);
|
this.Skip = patch.Skip;
|
||||||
this.skip = patch.Skip;
|
|
||||||
|
|
||||||
//mxd. Check data so we don't perform unneeded operations later on
|
//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.BLEND:
|
||||||
case TexturePathRenderStyle.CopyAlpha:
|
case TexturePathRenderStyle.COPY_ALPHA:
|
||||||
case TexturePathRenderStyle.CopyNewAlpha:
|
case TexturePathRenderStyle.COPY_NEW_ALPHA:
|
||||||
case TexturePathRenderStyle.Overlay:
|
case TexturePathRenderStyle.OVERLAY:
|
||||||
this.style = TexturePathRenderStyle.Copy;
|
this.RenderStyle = TexturePathRenderStyle.COPY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//mxd. and get rid of render styles we don't support
|
//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");
|
return GetAllLumps("TERRAIN");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//mxd
|
||||||
|
public override IEnumerable<TextResourceData> GetX11R6RGBData()
|
||||||
|
{
|
||||||
|
if(issuspended) throw new Exception("Data reader is suspended");
|
||||||
|
return GetAllLumps("X11R6RGB");
|
||||||
|
}
|
||||||
|
|
||||||
//mxd
|
//mxd
|
||||||
private IEnumerable<TextResourceData> GetFirstLump(string name)
|
private IEnumerable<TextResourceData> GetFirstLump(string name)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,12 +2,11 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using CodeImp.DoomBuilder.Config;
|
using CodeImp.DoomBuilder.Config;
|
||||||
using CodeImp.DoomBuilder.Data;
|
using CodeImp.DoomBuilder.Data;
|
||||||
using SlimDX;
|
using CodeImp.DoomBuilder.Rendering;
|
||||||
using CodeImp.DoomBuilder.ZDoom;
|
using CodeImp.DoomBuilder.ZDoom;
|
||||||
using CodeImp.DoomBuilder.GZBuilder.Data;
|
using CodeImp.DoomBuilder.GZBuilder.Data;
|
||||||
|
|
||||||
|
@ -607,16 +606,15 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
||||||
ReportError("Expected " + fadetype + " color value");
|
ReportError("Expected " + fadetype + " color value");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color4 color = new Color4();
|
|
||||||
|
|
||||||
// Try to get the color...
|
// Try to get the color...
|
||||||
if(GetColor(colorval, ref color))
|
PixelColor color = new PixelColor();
|
||||||
|
if(GetColorFromString(colorval, ref color))
|
||||||
{
|
{
|
||||||
if(fadetype == "fade")
|
if(fadetype == "fade")
|
||||||
mapinfo.FadeColor = color;
|
mapinfo.FadeColor = color.ToColorValue();
|
||||||
else
|
else
|
||||||
mapinfo.OutsideFogColor = color;
|
mapinfo.OutsideFogColor = color.ToColorValue();
|
||||||
}
|
}
|
||||||
else //...or not
|
else //...or not
|
||||||
{
|
{
|
||||||
|
@ -687,30 +685,5 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
|
||||||
|
|
||||||
#endregion
|
#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
|
public partial class ExceptionDialog : Form
|
||||||
{
|
{
|
||||||
private readonly bool cannotContinue;
|
private readonly bool isterminating;
|
||||||
private readonly string logPath;
|
private readonly string logpath;
|
||||||
|
|
||||||
public ExceptionDialog(UnhandledExceptionEventArgs e)
|
public ExceptionDialog(UnhandledExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
logPath = Path.Combine(General.SettingsPath, @"GZCrash.txt");
|
logpath = Path.Combine(General.SettingsPath, @"GZCrash.txt");
|
||||||
Exception ex = (Exception)e.ExceptionObject;
|
Exception ex = (Exception)e.ExceptionObject;
|
||||||
errorDescription.Text = "Error in " + ex.Source + ":";
|
errorDescription.Text = "Error in " + ex.Source + ":";
|
||||||
string sysinfo = GetSystemInfo();
|
string sysinfo = GetSystemInfo();
|
||||||
using(StreamWriter sw = File.CreateText(logPath))
|
using(StreamWriter sw = File.CreateText(logpath))
|
||||||
{
|
{
|
||||||
sw.Write(sysinfo + GetExceptionDescription(ex));
|
sw.Write(sysinfo + GetExceptionDescription(ex));
|
||||||
}
|
}
|
||||||
|
|
||||||
errorMessage.Text = ex.Message + Environment.NewLine + ex.StackTrace;
|
errorMessage.Text = ex.Message + Environment.NewLine + ex.StackTrace;
|
||||||
cannotContinue = true; //cannot recover from this...
|
isterminating = e.IsTerminating; // Recoverable?
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExceptionDialog(ThreadExceptionEventArgs e)
|
public ExceptionDialog(ThreadExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
logPath = Path.Combine(General.SettingsPath, @"GZCrash.txt");
|
logpath = Path.Combine(General.SettingsPath, @"GZCrash.txt");
|
||||||
errorDescription.Text = "Error in " + e.Exception.Source + ":";
|
errorDescription.Text = "Error in " + e.Exception.Source + ":";
|
||||||
string sysinfo = GetSystemInfo();
|
string sysinfo = GetSystemInfo();
|
||||||
using(StreamWriter sw = File.CreateText(logPath))
|
using(StreamWriter sw = File.CreateText(logpath))
|
||||||
{
|
{
|
||||||
sw.Write(sysinfo + GetExceptionDescription(e.Exception));
|
sw.Write(sysinfo + GetExceptionDescription(e.Exception));
|
||||||
}
|
}
|
||||||
|
@ -50,78 +50,92 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
||||||
|
|
||||||
public void Setup()
|
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)];
|
this.Text = titles[new Random().Next(0, titles.Length - 1)];
|
||||||
|
bContinue.Enabled = !isterminating;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetSystemInfo()
|
private static string GetSystemInfo()
|
||||||
|
@ -181,8 +195,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows
|
||||||
|
|
||||||
private void reportLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
private void reportLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||||
{
|
{
|
||||||
if(!File.Exists(logPath)) return;
|
if(!File.Exists(logpath)) return;
|
||||||
System.Diagnostics.Process.Start("explorer.exe", @"/select, " + logPath);
|
System.Diagnostics.Process.Start("explorer.exe", @"/select, " + logpath);
|
||||||
reportLink.LinkVisited = true;
|
reportLink.LinkVisited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2080,70 +2080,64 @@ namespace CodeImp.DoomBuilder
|
||||||
|
|
||||||
#region ================== mxd. Uncaught exceptions handling
|
#region ================== mxd. Uncaught exceptions handling
|
||||||
|
|
||||||
|
// In some cases the program can remain operational after these
|
||||||
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
|
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// Try handling it in user-friendy way...
|
||||||
GZBuilder.Windows.ExceptionDialog dlg = new GZBuilder.Windows.ExceptionDialog(e);
|
GZBuilder.Windows.ExceptionDialog dlg = new GZBuilder.Windows.ExceptionDialog(e);
|
||||||
dlg.Setup();
|
dlg.Setup();
|
||||||
if(dlg.ShowDialog() == DialogResult.Cancel) Application.Exit();
|
if(dlg.ShowDialog() == DialogResult.Cancel) Terminate(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
try
|
string exceptionmsg;
|
||||||
{
|
|
||||||
MessageBox.Show("Fatal Windows Forms Error", "Fatal Windows Forms Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
|
// Try getting exception details...
|
||||||
}
|
try { exceptionmsg = "Fatal Windows Forms error occurred: " + e.Exception.Message + "\n\nStack Trace:\n" + e.Exception.StackTrace; }
|
||||||
finally
|
catch(Exception exc) { exceptionmsg = "Failed to get initial excepton details: " + exc.Message + "\n\nStack Trace:\n" + exc.StackTrace; }
|
||||||
{
|
|
||||||
Application.Exit();
|
// 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)
|
private static void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
string exceptionmsg = string.Empty;
|
try
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
Exception ex = (Exception)e.ExceptionObject;
|
// Try handling it in user-friendy way...
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
GZBuilder.Windows.ExceptionDialog dlg = new GZBuilder.Windows.ExceptionDialog(e);
|
GZBuilder.Windows.ExceptionDialog dlg = new GZBuilder.Windows.ExceptionDialog(e);
|
||||||
dlg.Setup();
|
dlg.Setup();
|
||||||
dlg.ShowDialog();
|
if(dlg.ShowDialog() == DialogResult.Cancel) Terminate(false);
|
||||||
}
|
}
|
||||||
catch(Exception exc)
|
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: "
|
Exception ex = (Exception) e.ExceptionObject;
|
||||||
+ exc.Message + "\n\nInitial exception:\n" + exceptionmsg, "Fatal Non-UI Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
|
exceptionmsg = "Fatal Non-UI error occurred: " + ex.Message + "\n\nStack Trace:\n" + ex.StackTrace;
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Application.Exit();
|
|
||||||
}
|
}
|
||||||
|
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;
|
string settingsfile;
|
||||||
WAD targetwad = null;
|
WAD targetwad = null;
|
||||||
bool includenodes;
|
bool includenodes;
|
||||||
|
bool fileexists = File.Exists(newfilepathname); //mxd
|
||||||
|
|
||||||
General.WriteLogLine("Saving map to file: " + newfilepathname);
|
General.WriteLogLine("Saving map to file: " + newfilepathname);
|
||||||
|
|
||||||
//mxd. Official IWAD check...
|
//mxd. Official IWAD check...
|
||||||
WAD hashtest = new WAD(newfilepathname, true);
|
if(fileexists)
|
||||||
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
|
|
||||||
{
|
{
|
||||||
|
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.Dispose();
|
||||||
hashtest = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scripts changed?
|
// Scripts changed?
|
||||||
|
@ -786,79 +787,85 @@ namespace CodeImp.DoomBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
//mxd. Target file is read-only?
|
//mxd. Target file is read-only?
|
||||||
FileInfo info = new FileInfo(newfilepathname);
|
if(fileexists)
|
||||||
if(info.Exists && info.IsReadOnly)
|
|
||||||
{
|
{
|
||||||
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...");
|
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)
|
||||||
try
|
|
||||||
{
|
{
|
||||||
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("Map saving cancelled...");
|
||||||
General.WriteLogLine("Failed to remove read-only flag from \"" + filepathname + "\":" + e.Message);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
General.WriteLogLine("Map saving cancelled...");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Suspend data resources
|
// Suspend data resources
|
||||||
data.Suspend();
|
data.Suspend();
|
||||||
|
|
||||||
//mxd. Check if the target file is locked
|
//mxd. Check if the target file is locked
|
||||||
FileLockChecker.FileLockCheckResult checkresult = FileLockChecker.CheckFile(newfilepathname);
|
if(fileexists)
|
||||||
if(!string.IsNullOrEmpty(checkresult.Error))
|
|
||||||
{
|
{
|
||||||
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")
|
if(checkresult.Processes.Count > 0)
|
||||||
+ " and retry." + Environment.NewLine + "Press 'Cancel' to cancel saving.";
|
|
||||||
|
|
||||||
if(General.ShowErrorMessage(checkresult.Error + rest, MessageBoxButtons.RetryCancel) == DialogResult.Retry)
|
|
||||||
{
|
{
|
||||||
// Close all processes
|
string rest = "Press 'Retry' to close " + (checkresult.Processes.Count > 1 ? "all processes" : "the process")
|
||||||
foreach(Process process in checkresult.Processes)
|
+ " and retry." + Environment.NewLine + "Press 'Cancel' to cancel saving.";
|
||||||
{
|
|
||||||
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
|
if(General.ShowErrorMessage(checkresult.Error + rest, MessageBoxButtons.RetryCancel) == DialogResult.Retry)
|
||||||
data.Resume();
|
{
|
||||||
General.WriteLogLine("Map saving restarted...");
|
// Close all processes
|
||||||
return SaveMap(newfilepathname, purpose);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
General.ShowErrorMessage(checkresult.Error, MessageBoxButtons.OK);
|
||||||
data.Resume();
|
data.Resume();
|
||||||
General.WriteLogLine("Map saving cancelled...");
|
General.WriteLogLine("Map saving failed: " + checkresult.Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
General.ShowErrorMessage(checkresult.Error, MessageBoxButtons.OK);
|
|
||||||
data.Resume();
|
|
||||||
General.WriteLogLine("Map saving failed: " + checkresult.Error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine original map name
|
// Determine original map name
|
||||||
|
@ -867,7 +874,7 @@ namespace CodeImp.DoomBuilder
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(File.Exists(newfilepathname))
|
if(fileexists)
|
||||||
{
|
{
|
||||||
// mxd. Check if target wad already has a map with the same name
|
// mxd. Check if target wad already has a map with the same name
|
||||||
if(purpose == SavePurpose.IntoFile)
|
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 System.Windows.Forms;
|
||||||
using CodeImp.DoomBuilder.Controls;
|
using CodeImp.DoomBuilder.Controls;
|
||||||
|
|
||||||
|
@ -407,6 +408,7 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
this.menufile.Name = "menufile";
|
this.menufile.Name = "menufile";
|
||||||
this.menufile.Size = new System.Drawing.Size(37, 20);
|
this.menufile.Size = new System.Drawing.Size(37, 20);
|
||||||
this.menufile.Text = "&File";
|
this.menufile.Text = "&File";
|
||||||
|
this.menufile.DropDownOpening += menufile_DropDownOpening;
|
||||||
//
|
//
|
||||||
// itemnewmap
|
// itemnewmap
|
||||||
//
|
//
|
||||||
|
|
|
@ -2603,13 +2603,9 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
internal void AddRecentFile(string filename)
|
internal void AddRecentFile(string filename)
|
||||||
{
|
{
|
||||||
//mxd. Recreate recent files list
|
//mxd. Recreate recent files list
|
||||||
if(recentitems.Length != General.Settings.MaxRecentFiles)
|
if(recentitems.Length != General.Settings.MaxRecentFiles)
|
||||||
{
|
{
|
||||||
foreach(ToolStripMenuItem item in recentitems)
|
UpdateRecentItems();
|
||||||
menufile.DropDownItems.Remove(item);
|
|
||||||
|
|
||||||
SaveRecentFiles();
|
|
||||||
CreateRecentFiles();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int movedownto = General.Settings.MaxRecentFiles - 1;
|
int movedownto = General.Settings.MaxRecentFiles - 1;
|
||||||
|
@ -2645,6 +2641,16 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
itemnorecent.Visible = false;
|
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
|
// This returns the trimmed file/path string
|
||||||
private string GetDisplayFilename(string filename)
|
private string GetDisplayFilename(string filename)
|
||||||
{
|
{
|
||||||
|
@ -2689,6 +2695,12 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
// Open this file
|
// Open this file
|
||||||
General.OpenMapFile(item.Tag.ToString(), null);
|
General.OpenMapFile(item.Tag.ToString(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//mxd
|
||||||
|
private void menufile_DropDownOpening(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
UpdateRecentItems();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#region ================== Namespaces
|
#region ================== Namespaces
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using CodeImp.DoomBuilder.Config;
|
using CodeImp.DoomBuilder.Config;
|
||||||
using CodeImp.DoomBuilder.Data;
|
using CodeImp.DoomBuilder.Data;
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using CodeImp.DoomBuilder.Data;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using CodeImp.DoomBuilder.Data;
|
||||||
using CodeImp.DoomBuilder.Rendering;
|
using CodeImp.DoomBuilder.Rendering;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -45,10 +45,9 @@ namespace CodeImp.DoomBuilder.ZDoom
|
||||||
private readonly bool flipy;
|
private readonly bool flipy;
|
||||||
private readonly float alpha;
|
private readonly float alpha;
|
||||||
private readonly int rotation; //mxd
|
private readonly int rotation; //mxd
|
||||||
private readonly TexturePathRenderStyle renderStyle; //mxd
|
private readonly TexturePathRenderStyle renderstyle; //mxd
|
||||||
private readonly PixelColor blendColor; //mxd
|
private readonly PixelColor blendcolor; //mxd
|
||||||
private readonly TexturePathBlendStyle blendStyle; //mxd
|
private readonly TexturePathBlendStyle blendstyle; //mxd
|
||||||
private readonly float tintAmmount; //mxd
|
|
||||||
private static readonly string[] renderStyles = { "copy", "translucent", "add", "subtract", "reversesubtract", "modulate", "copyalpha", "copynewalpha", "overlay" }; //mxd
|
private static readonly string[] renderStyles = { "copy", "translucent", "add", "subtract", "reversesubtract", "modulate", "copyalpha", "copynewalpha", "overlay" }; //mxd
|
||||||
private readonly bool skip; //mxd
|
private readonly bool skip; //mxd
|
||||||
|
|
||||||
|
@ -63,10 +62,9 @@ namespace CodeImp.DoomBuilder.ZDoom
|
||||||
public bool FlipY { get { return flipy; } }
|
public bool FlipY { get { return flipy; } }
|
||||||
public float Alpha { get { return alpha; } }
|
public float Alpha { get { return alpha; } }
|
||||||
public int Rotation { get { return rotation; } } //mxd
|
public int Rotation { get { return rotation; } } //mxd
|
||||||
public TexturePathRenderStyle RenderStyle { get { return renderStyle; } } //mxd
|
public TexturePathRenderStyle RenderStyle { get { return renderstyle; } } //mxd
|
||||||
public TexturePathBlendStyle BlendStyle { get { return blendStyle; } }
|
public TexturePathBlendStyle BlendStyle { get { return blendstyle; } }
|
||||||
public float TintAmmount { get { return tintAmmount; } }
|
public PixelColor BlendColor { get { return blendcolor; } }//mxd
|
||||||
public PixelColor BlendColor { get { return blendColor; } }//mxd
|
|
||||||
public bool Skip { get { return skip; } } //mxd
|
public bool Skip { get { return skip; } } //mxd
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -78,8 +76,8 @@ namespace CodeImp.DoomBuilder.ZDoom
|
||||||
{
|
{
|
||||||
// Initialize
|
// Initialize
|
||||||
alpha = 1.0f;
|
alpha = 1.0f;
|
||||||
renderStyle = TexturePathRenderStyle.Copy;//mxd
|
renderstyle = TexturePathRenderStyle.COPY;//mxd
|
||||||
blendStyle = TexturePathBlendStyle.None; //mxd
|
blendstyle = TexturePathBlendStyle.NONE; //mxd
|
||||||
|
|
||||||
// There should be 3 tokens separated by 2 commas now:
|
// There should be 3 tokens separated by 2 commas now:
|
||||||
// Name, Width, Height
|
// Name, Width, Height
|
||||||
|
@ -164,30 +162,69 @@ namespace CodeImp.DoomBuilder.ZDoom
|
||||||
string s;
|
string s;
|
||||||
if(!ReadTokenString(parser, token, out s)) return;
|
if(!ReadTokenString(parser, token, out s)) return;
|
||||||
int index = Array.IndexOf(renderStyles, s.ToLowerInvariant());
|
int index = Array.IndexOf(renderStyles, s.ToLowerInvariant());
|
||||||
renderStyle = index == -1 ? TexturePathRenderStyle.Copy : (TexturePathRenderStyle) index;
|
renderstyle = index == -1 ? TexturePathRenderStyle.COPY : (TexturePathRenderStyle) index;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "blend": //mxd
|
case "blend": //mxd
|
||||||
int val;
|
|
||||||
if(!ReadTokenColor(parser, token, out val)) return;
|
|
||||||
blendColor = PixelColor.FromInt(val);
|
|
||||||
|
|
||||||
parser.SkipWhitespace(false);
|
parser.SkipWhitespace(false);
|
||||||
token = parser.ReadToken();
|
PixelColor color = new PixelColor();
|
||||||
|
|
||||||
if(token == ",") //read tint ammount
|
// Blend <string color>[,<float alpha>] block?
|
||||||
{
|
token = parser.ReadToken(false);
|
||||||
parser.SkipWhitespace(false);
|
if(!parser.ReadByte(token, ref color.r))
|
||||||
if(!ReadTokenFloat(parser, token, out tintAmmount)) return;
|
|
||||||
tintAmmount = General.Clamp(tintAmmount, 0.0f, 1.0f);
|
|
||||||
blendStyle = TexturePathBlendStyle.Tint;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
blendStyle = TexturePathBlendStyle.Blend;
|
if(!ZDTextParser.GetColorFromString(token, ref color))
|
||||||
// Rewind so this structure can be read again
|
{
|
||||||
parser.DataStream.Seek(-token.Length, SeekOrigin.Current);
|
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;
|
break;
|
||||||
|
|
||||||
case "}":
|
case "}":
|
||||||
|
@ -268,36 +305,6 @@ namespace CodeImp.DoomBuilder.ZDoom
|
||||||
return true;
|
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
|
#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.Compilers;
|
||||||
using CodeImp.DoomBuilder.Config;
|
using CodeImp.DoomBuilder.Config;
|
||||||
using CodeImp.DoomBuilder.Data;
|
using CodeImp.DoomBuilder.Data;
|
||||||
|
using CodeImp.DoomBuilder.Rendering;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -557,6 +558,65 @@ namespace CodeImp.DoomBuilder.ZDoom
|
||||||
return success;
|
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
|
//mxd
|
||||||
protected void SkipStructure() { SkipStructure(new HashSet<string>()); }
|
protected void SkipStructure() { SkipStructure(new HashSet<string>()); }
|
||||||
protected void SkipStructure(HashSet<string> breakat)
|
protected void SkipStructure(HashSet<string> breakat)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue