diff --git a/Source/Core/Data/DataManager.cs b/Source/Core/Data/DataManager.cs index 1271ab441e931c722088b609be4893d0709df557..fca6511aeda94d52b45e98dac7e73e3515ac56bb 100755 --- a/Source/Core/Data/DataManager.cs +++ b/Source/Core/Data/DataManager.cs @@ -1168,7 +1168,10 @@ namespace CodeImp.DoomBuilder.Data { // HiResImage will not give us it's actual scale Bitmap texture = img.GetBitmap(); - scale = new Vector2D((float)img.Width / texture.Width, (float)img.Height / texture.Height); + lock (texture) + { + scale = new Vector2D((float)img.Width / texture.Width, (float)img.Height / texture.Height); + } return texture; } } @@ -3273,7 +3276,12 @@ namespace CodeImp.DoomBuilder.Data { ImageData tex = LoadInternalTexture("MissingSky3D.png"); tex.CreateTexture(); - Bitmap sky = new Bitmap(tex.GetBitmap()); + Bitmap bmp = tex.GetBitmap(); + Bitmap sky; + lock (bmp) + { + sky = new Bitmap(bmp); + } sky.RotateFlip(RotateFlipType.RotateNoneFlipX); // We don't want our built-in image mirrored... skybox = MakeClassicSkyBox(sky); tex.Dispose(); diff --git a/Source/Core/Data/ImageData.cs b/Source/Core/Data/ImageData.cs index eecf23edc65648839f1872382eb9bf107bcedff7..8a4b6aef070b3726039512b50fdea74df5b0a5aa 100755 --- a/Source/Core/Data/ImageData.cs +++ b/Source/Core/Data/ImageData.cs @@ -84,6 +84,9 @@ namespace CodeImp.DoomBuilder.Data // Disposing protected bool isdisposed; + + // Dummy object used when we don't have a bitmap for locking + private object bitmapLocker = new object(); #endregion @@ -101,7 +104,7 @@ namespace CodeImp.DoomBuilder.Data public bool HasPatchWithSameName { get { return hasPatchWithSameName; } } //mxd internal bool HasLongName { get { return hasLongName; } } //mxd public bool UseColorCorrection { get { return usecolorcorrection; } set { usecolorcorrection = value; } } - public Texture Texture { get { lock(this) { return texture; } } } + public Texture Texture { get { lock (this) lock (bitmap ?? bitmapLocker) { return texture; } } } public bool IsPreviewLoaded { get { return (previewstate == ImageLoadState.Ready); } } public bool IsImageLoaded { get { return (imagestate == ImageLoadState.Ready); } } public bool LoadFailed { get { return loadfailed; } } @@ -148,7 +151,7 @@ namespace CodeImp.DoomBuilder.Data // Not already disposed? if(!isdisposed) { - lock(this) + lock (this) lock (bitmap ?? bitmapLocker) { // Clean up if(bitmap != null) bitmap.Dispose(); @@ -208,8 +211,8 @@ namespace CodeImp.DoomBuilder.Data // This unloads the image public virtual void UnloadImage() { - lock(this) - { + lock (this) lock (bitmap ?? bitmapLocker) + { if(bitmap != null) bitmap.Dispose(); bitmap = null; imagestate = ImageLoadState.None; @@ -219,8 +222,8 @@ namespace CodeImp.DoomBuilder.Data // This returns the bitmap image public Bitmap GetBitmap() { - lock(this) - { + lock (this) lock (bitmap ?? bitmapLocker) + { // Image loaded successfully? if(!loadfailed && (imagestate == ImageLoadState.Ready) && (bitmap != null)) return bitmap; @@ -244,8 +247,8 @@ namespace CodeImp.DoomBuilder.Data // This requests loading the image protected virtual void LocalLoadImage() { - lock(this) - { + lock (this) lock (bitmap ?? bitmapLocker) + { // Bitmap loaded successfully? if(bitmap != null) { @@ -443,8 +446,8 @@ namespace CodeImp.DoomBuilder.Data // This creates the Direct3D texture public virtual void CreateTexture() { - lock(this) - { + lock (this) lock (bitmap ?? bitmapLocker) + { // Only do this when texture is not created yet if(((texture == null) || (texture.Disposed)) && this.IsImageLoaded && !loadfailed) { @@ -487,9 +490,9 @@ namespace CodeImp.DoomBuilder.Data { if(!dynamictexture) throw new Exception("The image must be a dynamic image to support direct updating."); - - lock(this) - { + + lock (this) lock (bitmap ?? bitmapLocker) + { if((texture != null) && !texture.Disposed) { // Lock the bitmap and texture @@ -523,8 +526,8 @@ namespace CodeImp.DoomBuilder.Data // This destroys the Direct3D texture public void ReleaseTexture() { - lock(this) - { + lock (this) lock (bitmap ?? bitmapLocker) + { // Trash it if(texture != null) texture.Dispose(); texture = null; @@ -534,8 +537,8 @@ namespace CodeImp.DoomBuilder.Data // This draws a preview public virtual void DrawPreview(Graphics target, Point targetpos) { - lock(this) - { + lock (this) lock (bitmap ?? bitmapLocker) + { // Preview ready? if(!loadfailed && (previewstate == ImageLoadState.Ready)) { @@ -563,8 +566,8 @@ namespace CodeImp.DoomBuilder.Data // This returns a preview image public virtual Image GetPreview() { - lock(this) - { + lock (this) lock (bitmap ?? bitmapLocker) + { // Preview ready? if(previewstate == ImageLoadState.Ready) { diff --git a/Source/Core/Data/PreviewManager.cs b/Source/Core/Data/PreviewManager.cs index a281b2d298acaa9757216e1f3818ab37507db1ab..702b7ce0535c42a494c2cbb4deec7ca9b95c7379 100755 --- a/Source/Core/Data/PreviewManager.cs +++ b/Source/Core/Data/PreviewManager.cs @@ -109,61 +109,64 @@ namespace CodeImp.DoomBuilder.Data if(!img.IsImageLoaded) img.LoadImage(); int imagewidth, imageheight; Bitmap image = img.GetBitmap(); //mxd - if(!img.LoadFailed) - { - imagewidth = img.Width; - imageheight = img.Height; - } - else - { - Size size = image.Size; //mxd - imagewidth = size.Width; - imageheight = size.Height; - } - - // Determine preview size - float scalex = (img.Width > MAX_PREVIEW_SIZE) ? (MAX_PREVIEW_SIZE / (float)imagewidth) : 1.0f; - float scaley = (img.Height > MAX_PREVIEW_SIZE) ? (MAX_PREVIEW_SIZE / (float)imageheight) : 1.0f; - float scale = Math.Min(scalex, scaley); - int previewwidth = (int)(imagewidth * scale); - int previewheight = (int)(imageheight * scale); - if(previewwidth < 1) previewwidth = 1; - if(previewheight < 1) previewheight = 1; - - //mxd. Expected and actual image sizes and format match? - Bitmap preview; - if(previewwidth == imagewidth && previewheight == imageheight && image.PixelFormat == IMAGE_FORMAT) - { - preview = new Bitmap(image); - } - else - { - // Make new image - preview = new Bitmap(previewwidth, previewheight, IMAGE_FORMAT); - Graphics g = Graphics.FromImage(preview); - g.PageUnit = GraphicsUnit.Pixel; - //g.CompositingQuality = CompositingQuality.HighQuality; //mxd - g.InterpolationMode = InterpolationMode.NearestNeighbor; - //g.SmoothingMode = SmoothingMode.HighQuality; //mxd - g.PixelOffsetMode = PixelOffsetMode.None; - //g.Clear(Color.Transparent); //mxd - - // Draw image onto atlas - Rectangle atlasrect = new Rectangle(0, 0, previewwidth, previewheight); - RectangleF imgrect = General.MakeZoomedRect(new Size(imagewidth, imageheight), atlasrect); - if(imgrect.Width < 1.0f) - { - imgrect.X -= 0.5f - imgrect.Width * 0.5f; - imgrect.Width = 1.0f; - } - if(imgrect.Height < 1.0f) - { - imgrect.Y -= 0.5f - imgrect.Height * 0.5f; - imgrect.Height = 1.0f; - } - g.DrawImage(image, imgrect); - g.Dispose(); - } + Bitmap preview; + lock (image) + { + if (!img.LoadFailed) + { + imagewidth = img.Width; + imageheight = img.Height; + } + else + { + Size size = image.Size; //mxd + imagewidth = size.Width; + imageheight = size.Height; + } + + // Determine preview size + float scalex = (img.Width > MAX_PREVIEW_SIZE) ? (MAX_PREVIEW_SIZE / (float)imagewidth) : 1.0f; + float scaley = (img.Height > MAX_PREVIEW_SIZE) ? (MAX_PREVIEW_SIZE / (float)imageheight) : 1.0f; + float scale = Math.Min(scalex, scaley); + int previewwidth = (int)(imagewidth * scale); + int previewheight = (int)(imageheight * scale); + if (previewwidth < 1) previewwidth = 1; + if (previewheight < 1) previewheight = 1; + + //mxd. Expected and actual image sizes and format match? + if (previewwidth == imagewidth && previewheight == imageheight && image.PixelFormat == IMAGE_FORMAT) + { + preview = new Bitmap(image); + } + else + { + // Make new image + preview = new Bitmap(previewwidth, previewheight, IMAGE_FORMAT); + Graphics g = Graphics.FromImage(preview); + g.PageUnit = GraphicsUnit.Pixel; + //g.CompositingQuality = CompositingQuality.HighQuality; //mxd + g.InterpolationMode = InterpolationMode.NearestNeighbor; + //g.SmoothingMode = SmoothingMode.HighQuality; //mxd + g.PixelOffsetMode = PixelOffsetMode.None; + //g.Clear(Color.Transparent); //mxd + + // Draw image onto atlas + Rectangle atlasrect = new Rectangle(0, 0, previewwidth, previewheight); + RectangleF imgrect = General.MakeZoomedRect(new Size(imagewidth, imageheight), atlasrect); + if (imgrect.Width < 1.0f) + { + imgrect.X -= 0.5f - imgrect.Width * 0.5f; + imgrect.Width = 1.0f; + } + if (imgrect.Height < 1.0f) + { + imgrect.Y -= 0.5f - imgrect.Height * 0.5f; + imgrect.Height = 1.0f; + } + g.DrawImage(image, imgrect); + g.Dispose(); + } + } // Unload image if no longer needed if(!img.IsReferenced) img.UnloadImage(); diff --git a/Source/Core/Data/TEXTURESImage.cs b/Source/Core/Data/TEXTURESImage.cs index fff29db500d4f0438a1f78a2e443f21d135bbdf0..2187791407b6b6215385ad85d7144dc27e819f54 100755 --- a/Source/Core/Data/TEXTURESImage.cs +++ b/Source/Core/Data/TEXTURESImage.cs @@ -218,8 +218,13 @@ namespace CodeImp.DoomBuilder.Data { if(!img.IsImageLoaded) img.LoadImage(); - //mxd. Apply transformations from TexturePatch. We don't want to modify the original bitmap here, so make a copy - Bitmap patchbmp = TransformPatch(p, new Bitmap(img.GetBitmap())); + //mxd. Apply transformations from TexturePatch. We don't want to modify the original bitmap here, so make a copy + Bitmap bmp = img.GetBitmap(); + Bitmap patchbmp; + lock (bmp) + { + patchbmp = TransformPatch(p, new Bitmap(bmp)); + } // Draw the patch on the texture image Rectangle tgtrect = new Rectangle(p.X, p.Y, patchbmp.Size.Width, patchbmp.Size.Height); diff --git a/Source/Core/Properties/AssemblyInfo.cs b/Source/Core/Properties/AssemblyInfo.cs index e599f32d46009add4424153c93ecf011e9d2b9ea..41e70c88e877197bd7da01f7f10c702dc963af90 100755 --- a/Source/Core/Properties/AssemblyInfo.cs +++ b/Source/Core/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using CodeImp.DoomBuilder; // Build Number // Revision // -[assembly: AssemblyVersion("2.3.0.2973")] +[assembly: AssemblyVersion("2.3.0.2975")] [assembly: NeutralResourcesLanguageAttribute("en")] -[assembly: AssemblyHash("de7445b")] +[assembly: AssemblyHash("021bcf6")] diff --git a/Source/Plugins/BuilderModes/IO/WavefrontExporter.cs b/Source/Plugins/BuilderModes/IO/WavefrontExporter.cs index 6cf7b637b335dcff646dcd65daff762ec3278f15..b1cd7656f06011c271c043a2a0db188d7b0b0e3a 100755 --- a/Source/Plugins/BuilderModes/IO/WavefrontExporter.cs +++ b/Source/Plugins/BuilderModes/IO/WavefrontExporter.cs @@ -96,7 +96,10 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO if(!id.IsImageLoaded) id.LoadImage(); Bitmap bmp = id.GetBitmap(); - bmp.Save(Path.Combine(settings.ObjPath, Path.GetFileNameWithoutExtension(s) + ".PNG"), ImageFormat.Png); + lock (bmp) + { + bmp.Save(Path.Combine(settings.ObjPath, Path.GetFileNameWithoutExtension(s) + ".PNG"), ImageFormat.Png); + } } else { @@ -127,7 +130,10 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO if(settings.Textures != null && Array.IndexOf(settings.Textures, s) != -1) flatname += "_FLAT"; - bmp.Save(Path.Combine(settings.ObjPath, Path.GetFileNameWithoutExtension(flatname) + ".PNG"), ImageFormat.Png); + lock (bmp) + { + bmp.Save(Path.Combine(settings.ObjPath, Path.GetFileNameWithoutExtension(flatname) + ".PNG"), ImageFormat.Png); + } } else diff --git a/Source/Plugins/BuilderModes/Properties/AssemblyInfo.cs b/Source/Plugins/BuilderModes/Properties/AssemblyInfo.cs index 6c5fb9e6d7754b4fcdb73deaaa51cc9f9c7d468f..c189a8a1586f7d6aafbcdd68109b334b0d9f2ba8 100755 --- a/Source/Plugins/BuilderModes/Properties/AssemblyInfo.cs +++ b/Source/Plugins/BuilderModes/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Resources; // Build Number // Revision // -[assembly: AssemblyVersion("2.3.0.2973")] +[assembly: AssemblyVersion("2.3.0.2975")] [assembly: NeutralResourcesLanguageAttribute("en")] diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs b/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs index 9fde9fbc1d778f07bb6c406b9ce9ce9aa1bcbfd7..d00d0465fa5f809f97739193232ce2c2957fcdf8 100755 --- a/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs @@ -521,31 +521,34 @@ namespace CodeImp.DoomBuilder.BuilderModes // Some textures (e.g. HiResImage) may lie about their size, so use bitmap size instead Bitmap image = Texture.GetBitmap(); - - // Fetch ZDoom fields - float rotate = Angle2D.DegToRad(level.sector.Fields.GetValue("rotationceiling", 0.0f)); - Vector2D offset = new Vector2D(level.sector.Fields.GetValue("xpanningceiling", 0.0f), level.sector.Fields.GetValue("ypanningceiling", 0.0f)); - Vector2D scale = new Vector2D(level.sector.Fields.GetValue("xscaleceiling", 1.0f), level.sector.Fields.GetValue("yscaleceiling", 1.0f)); - Vector2D texscale = new Vector2D(1.0f / Texture.ScaledWidth, 1.0f / Texture.ScaledHeight); - // Texture coordinates - Vector2D o = pickintersect; - o = o.GetRotated(rotate); - o.y = -o.y; - o = (o + offset) * scale * texscale; - o.x = (o.x * image.Width) % image.Width; - o.y = (o.y * image.Height) % image.Height; - - // Make sure coordinates are inside of texture dimensions... - if(o.x < 0) o.x += image.Width; - if(o.y < 0) o.y += image.Height; - - // Make final texture coordinates... - int ox = General.Clamp((int)Math.Floor(o.x), 0, image.Width - 1); - int oy = General.Clamp((int)Math.Floor(o.y), 0, image.Height - 1); - - // Check pixel alpha - return (image.GetPixel(ox, oy).A > 0); + lock (image) + { + // Fetch ZDoom fields + float rotate = Angle2D.DegToRad(level.sector.Fields.GetValue("rotationceiling", 0.0f)); + Vector2D offset = new Vector2D(level.sector.Fields.GetValue("xpanningceiling", 0.0f), level.sector.Fields.GetValue("ypanningceiling", 0.0f)); + Vector2D scale = new Vector2D(level.sector.Fields.GetValue("xscaleceiling", 1.0f), level.sector.Fields.GetValue("yscaleceiling", 1.0f)); + Vector2D texscale = new Vector2D(1.0f / Texture.ScaledWidth, 1.0f / Texture.ScaledHeight); + + // Texture coordinates + Vector2D o = pickintersect; + o = o.GetRotated(rotate); + o.y = -o.y; + o = (o + offset) * scale * texscale; + o.x = (o.x * image.Width) % image.Width; + o.y = (o.y * image.Height) % image.Height; + + // Make sure coordinates are inside of texture dimensions... + if (o.x < 0) o.x += image.Width; + if (o.y < 0) o.y += image.Height; + + // Make final texture coordinates... + int ox = General.Clamp((int)Math.Floor(o.x), 0, image.Width - 1); + int oy = General.Clamp((int)Math.Floor(o.y), 0, image.Height - 1); + + // Check pixel alpha + return (image.GetPixel(ox, oy).A > 0); + } } return false; diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs b/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs index 504ee444dc6dda63eb07513da0253d2b65250a95..4327dd8c2d8835923c59da5f08eb5aac19ea3fd6 100755 --- a/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs @@ -454,30 +454,33 @@ namespace CodeImp.DoomBuilder.BuilderModes // Some textures (e.g. HiResImage) may lie about their size, so use bitmap size instead Bitmap image = Texture.GetBitmap(); - // Fetch ZDoom fields - float rotate = Angle2D.DegToRad(level.sector.Fields.GetValue("rotationfloor", 0.0f)); - Vector2D offset = new Vector2D(level.sector.Fields.GetValue("xpanningfloor", 0.0f), level.sector.Fields.GetValue("ypanningfloor", 0.0f)); - Vector2D scale = new Vector2D(level.sector.Fields.GetValue("xscalefloor", 1.0f), level.sector.Fields.GetValue("yscalefloor", 1.0f)); - Vector2D texscale = new Vector2D(1.0f / Texture.ScaledWidth, 1.0f / Texture.ScaledHeight); - - // Texture coordinates - Vector2D o = pickintersect; - o = o.GetRotated(rotate); - o.y = -o.y; - o = (o + offset) * scale * texscale; - o.x = (o.x * image.Width) % image.Width; - o.y = (o.y * image.Height) % image.Height; - - // Make sure coordinates are inside of texture dimensions... - if(o.x < 0) o.x += image.Width; - if(o.y < 0) o.y += image.Height; - - // Make final texture coordinates... - int ox = General.Clamp((int)Math.Floor(o.x), 0, image.Width - 1); - int oy = General.Clamp((int)Math.Floor(o.y), 0, image.Height - 1); - - // Check pixel alpha - return (image.GetPixel(ox, oy).A > 0); + lock (image) + { + // Fetch ZDoom fields + float rotate = Angle2D.DegToRad(level.sector.Fields.GetValue("rotationfloor", 0.0f)); + Vector2D offset = new Vector2D(level.sector.Fields.GetValue("xpanningfloor", 0.0f), level.sector.Fields.GetValue("ypanningfloor", 0.0f)); + Vector2D scale = new Vector2D(level.sector.Fields.GetValue("xscalefloor", 1.0f), level.sector.Fields.GetValue("yscalefloor", 1.0f)); + Vector2D texscale = new Vector2D(1.0f / Texture.ScaledWidth, 1.0f / Texture.ScaledHeight); + + // Texture coordinates + Vector2D o = pickintersect; + o = o.GetRotated(rotate); + o.y = -o.y; + o = (o + offset) * scale * texscale; + o.x = (o.x * image.Width) % image.Width; + o.y = (o.y * image.Height) % image.Height; + + // Make sure coordinates are inside of texture dimensions... + if (o.x < 0) o.x += image.Width; + if (o.y < 0) o.y += image.Height; + + // Make final texture coordinates... + int ox = General.Clamp((int)Math.Floor(o.x), 0, image.Width - 1); + int oy = General.Clamp((int)Math.Floor(o.y), 0, image.Height - 1); + + // Check pixel alpha + return (image.GetPixel(ox, oy).A > 0); + } } return false; diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs index 1ab0b07970d3d0db65bdf8057b2d44ff2bd5d777..a6a7258c5a9e50d7394b0b26d73725e116bdf35a 100755 --- a/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs @@ -341,24 +341,27 @@ namespace CodeImp.DoomBuilder.BuilderModes // Some textures (e.g. HiResImage) may lie about their size, so use bitmap size instead Bitmap image = Texture.GetBitmap(); - // Determine texture scale... - Vector2D imgscale = new Vector2D((float)Texture.Width / image.Width, (float)Texture.Height / image.Height); - Vector2D texscale = (Texture is HiResImage) ? imgscale * Texture.Scale : Texture.Scale; - - // Get correct offset to texture space... - float texoffsetx = Sidedef.OffsetX + sourceside.OffsetX + UniFields.GetFloat(Sidedef.Fields, "offsetx_mid") + UniFields.GetFloat(sourceside.Fields, "offsetx_mid"); - int ox = (int)Math.Floor((u * Sidedef.Line.Length * UniFields.GetFloat(sourceside.Fields, "scalex_mid", 1.0f) / texscale.x + (texoffsetx / imgscale.x)) % image.Width); - - float texoffsety = Sidedef.OffsetY + sourceside.OffsetY + UniFields.GetFloat(Sidedef.Fields, "offsety_mid") + UniFields.GetFloat(sourceside.Fields, "offsety_mid"); - int oy = (int)Math.Ceiling(((pickintersect.z - sourceside.Sector.CeilHeight) * UniFields.GetFloat(sourceside.Fields, "scaley_mid", 1.0f) / texscale.y - (texoffsety / imgscale.y)) % image.Height); - - // Make sure offsets are inside of texture dimensions... - if(ox < 0) ox += image.Width; - if(oy < 0) oy += image.Height; - - // Check pixel alpha - Point pixelpos = new Point(General.Clamp(ox, 0, image.Width - 1), General.Clamp(image.Height - oy, 0, image.Height - 1)); - return (image.GetPixel(pixelpos.X, pixelpos.Y).A > 0 && base.PickAccurate(@from, to, dir, ref u_ray)); + lock (image) + { + // Determine texture scale... + Vector2D imgscale = new Vector2D((float)Texture.Width / image.Width, (float)Texture.Height / image.Height); + Vector2D texscale = (Texture is HiResImage) ? imgscale * Texture.Scale : Texture.Scale; + + // Get correct offset to texture space... + float texoffsetx = Sidedef.OffsetX + sourceside.OffsetX + UniFields.GetFloat(Sidedef.Fields, "offsetx_mid") + UniFields.GetFloat(sourceside.Fields, "offsetx_mid"); + int ox = (int)Math.Floor((u * Sidedef.Line.Length * UniFields.GetFloat(sourceside.Fields, "scalex_mid", 1.0f) / texscale.x + (texoffsetx / imgscale.x)) % image.Width); + + float texoffsety = Sidedef.OffsetY + sourceside.OffsetY + UniFields.GetFloat(Sidedef.Fields, "offsety_mid") + UniFields.GetFloat(sourceside.Fields, "offsety_mid"); + int oy = (int)Math.Ceiling(((pickintersect.z - sourceside.Sector.CeilHeight) * UniFields.GetFloat(sourceside.Fields, "scaley_mid", 1.0f) / texscale.y - (texoffsety / imgscale.y)) % image.Height); + + // Make sure offsets are inside of texture dimensions... + if (ox < 0) ox += image.Width; + if (oy < 0) oy += image.Height; + + // Check pixel alpha + Point pixelpos = new Point(General.Clamp(ox, 0, image.Width - 1), General.Clamp(image.Height - oy, 0, image.Height - 1)); + return (image.GetPixel(pixelpos.X, pixelpos.Y).A > 0 && base.PickAccurate(@from, to, dir, ref u_ray)); + } } // Return texture name diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs index d36bd7603eb5905e3d2c7b6f1e55c5457d53e4ee..d8a3d84f56e9fd3e961ceebb61fd77d9d22e6f4e 100755 --- a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs @@ -287,37 +287,40 @@ namespace CodeImp.DoomBuilder.BuilderModes // Some textures (e.g. HiResImage) may lie about their size, so use bitmap size instead Bitmap image = Texture.GetBitmap(); - // Determine texture scale... - Vector2D imgscale = new Vector2D((float)Texture.Width / image.Width, (float)Texture.Height / image.Height); - Vector2D texscale = (Texture is HiResImage) ? imgscale * Texture.Scale : Texture.Scale; - - // Get correct offset to texture space... - int ox = (int)Math.Floor((u * Sidedef.Line.Length * UniFields.GetFloat(Sidedef.Fields, "scalex_mid", 1.0f) / texscale.x - + ((Sidedef.OffsetX + UniFields.GetFloat(Sidedef.Fields, "offsetx_mid")) / imgscale.x)) - % image.Width); - - int oy; - if(repeatmidtex) - { - bool pegbottom = Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag); - float zoffset = (pegbottom ? Sidedef.Sector.FloorHeight : Sidedef.Sector.CeilHeight); - oy = (int)Math.Floor(((pickintersect.z - zoffset) * UniFields.GetFloat(Sidedef.Fields, "scaley_mid", 1.0f) / texscale.y - - ((Sidedef.OffsetY - UniFields.GetFloat(Sidedef.Fields, "offsety_mid")) / imgscale.y)) - % image.Height); - } - else - { - float zoffset = bottomclipplane.GetZ(pickintersect); - oy = (int)Math.Ceiling(((pickintersect.z - zoffset) * UniFields.GetFloat(Sidedef.Fields, "scaley_mid", 1.0f) / texscale.y) % image.Height); - } + lock (image) + { + // Determine texture scale... + Vector2D imgscale = new Vector2D((float)Texture.Width / image.Width, (float)Texture.Height / image.Height); + Vector2D texscale = (Texture is HiResImage) ? imgscale * Texture.Scale : Texture.Scale; + + // Get correct offset to texture space... + int ox = (int)Math.Floor((u * Sidedef.Line.Length * UniFields.GetFloat(Sidedef.Fields, "scalex_mid", 1.0f) / texscale.x + + ((Sidedef.OffsetX + UniFields.GetFloat(Sidedef.Fields, "offsetx_mid")) / imgscale.x)) + % image.Width); + + int oy; + if (repeatmidtex) + { + bool pegbottom = Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag); + float zoffset = (pegbottom ? Sidedef.Sector.FloorHeight : Sidedef.Sector.CeilHeight); + oy = (int)Math.Floor(((pickintersect.z - zoffset) * UniFields.GetFloat(Sidedef.Fields, "scaley_mid", 1.0f) / texscale.y + - ((Sidedef.OffsetY - UniFields.GetFloat(Sidedef.Fields, "offsety_mid")) / imgscale.y)) + % image.Height); + } + else + { + float zoffset = bottomclipplane.GetZ(pickintersect); + oy = (int)Math.Ceiling(((pickintersect.z - zoffset) * UniFields.GetFloat(Sidedef.Fields, "scaley_mid", 1.0f) / texscale.y) % image.Height); + } - // Make sure offsets are inside of texture dimensions... - if(ox < 0) ox += image.Width; - if(oy < 0) oy += image.Height; + // Make sure offsets are inside of texture dimensions... + if (ox < 0) ox += image.Width; + if (oy < 0) oy += image.Height; - // Check pixel alpha - Point pixelpos = new Point(General.Clamp(ox, 0, image.Width - 1), General.Clamp(image.Height - oy, 0, image.Height - 1)); - return (image.GetPixel(pixelpos.X, pixelpos.Y).A > 0 && base.PickAccurate(from, to, dir, ref u_ray)); + // Check pixel alpha + Point pixelpos = new Point(General.Clamp(ox, 0, image.Width - 1), General.Clamp(image.Height - oy, 0, image.Height - 1)); + return (image.GetPixel(pixelpos.X, pixelpos.Y).A > 0 && base.PickAccurate(from, to, dir, ref u_ray)); + } } // Return texture name