From adc2a4af789c366327fad4e19848a13b0aac35e8 Mon Sep 17 00:00:00 2001
From: MaxED <j.maxed@gmail.com>
Date: Mon, 29 Sep 2014 14:05:38 +0000
Subject: [PATCH] Map Analysis: "Check texture alignment" check now works in
 UDMF map format. Fixed incorrect syntax in ZDoom_DECORATE.cfg.

---
 Build/Scripting/ZDoom_DECORATE.cfg            |   2 +-
 .../ErrorChecks/CheckTextureAlignment.cs      | 291 +++++++++++-------
 .../Interface/ErrorCheckForm.Designer.cs      |   4 +-
 .../Interface/ErrorCheckForm.resx             |   3 -
 4 files changed, 184 insertions(+), 116 deletions(-)

diff --git a/Build/Scripting/ZDoom_DECORATE.cfg b/Build/Scripting/ZDoom_DECORATE.cfg
index 6ac6821ca..10564a44f 100644
--- a/Build/Scripting/ZDoom_DECORATE.cfg
+++ b/Build/Scripting/ZDoom_DECORATE.cfg
@@ -291,7 +291,7 @@ keywords
 	A_SkelWhoosh = "A_SkelWhoosh";
 	A_StartFire = "A_StartFire";
 	A_FireCrackle = "A_FireCrackle";
-	A_BFGSpray = "A_BFGSpray[(string flashtype = "BFGExtra"[, int numrays = 40[, int damage = 15[, float angle = 90[, float distance = 1024[, float vrange = 32[, int explicit_damage = 0]]]]]])] ";
+	A_BFGSpray = "A_BFGSpray[(string flashtype = 'BFGExtra'[, int numrays = 40[, int damage = 15[, float angle = 90[, float distance = 1024[, float vrange = 32[, int explicit_damage = 0]]]]]])]";
 	A_BarrelDestroy = "A_BarrelDestroy";
 //State keywords
 	Light = "Light(string lightname)";
diff --git a/Source/Plugins/BuilderModes/ErrorChecks/CheckTextureAlignment.cs b/Source/Plugins/BuilderModes/ErrorChecks/CheckTextureAlignment.cs
index e22500bdb..ebc674adb 100644
--- a/Source/Plugins/BuilderModes/ErrorChecks/CheckTextureAlignment.cs
+++ b/Source/Plugins/BuilderModes/ErrorChecks/CheckTextureAlignment.cs
@@ -5,6 +5,7 @@ using System.Collections.Generic;
 using System.Drawing;
 using System.Threading;
 using CodeImp.DoomBuilder.Data;
+using CodeImp.DoomBuilder.GZBuilder.Tools;
 using CodeImp.DoomBuilder.Geometry;
 using CodeImp.DoomBuilder.Map;
 using CodeImp.DoomBuilder.VisualModes;
@@ -22,6 +23,12 @@ namespace CodeImp.DoomBuilder.BuilderModes.ErrorChecks
 
 		#endregion
 
+		#region ================== Variables
+
+		private Dictionary<VisualGeometryType, Dictionary<int, Dictionary<int, bool>>> donesides;
+
+		#endregion
+
 		#region ================== Constructor / Destructor
 
 		// Constructor
@@ -38,35 +45,50 @@ namespace CodeImp.DoomBuilder.BuilderModes.ErrorChecks
 		// This runs the check
 		public override void Run()
 		{
-			Dictionary<int, Dictionary<int, bool>> donesides = new Dictionary<int, Dictionary<int, bool>>();
+			donesides = new Dictionary<VisualGeometryType, Dictionary<int, Dictionary<int, bool>>>(3);
+			donesides.Add(VisualGeometryType.WALL_UPPER, new Dictionary<int, Dictionary<int, bool>>());
+			donesides.Add(VisualGeometryType.WALL_MIDDLE, new Dictionary<int, Dictionary<int, bool>>());
+			donesides.Add(VisualGeometryType.WALL_LOWER, new Dictionary<int, Dictionary<int, bool>>());
+			
 			int progress = 0;
 			int stepprogress = 0;
-			bool udmf = General.Map.UDMF;
 
 			// Go for all the liendefs
 			foreach(Linedef l in General.Map.Map.Linedefs) 
 			{
-				// Check if not already done
-				if (donesides.ContainsKey(l.Index)) continue;
-
 				// Check if we need to align any part of the front sidedef
-				if (l.Front != null) 
+				if(l.Front != null) 
 				{
-					CheckTopAlignment(l.Front, donesides, udmf);
-					CheckMiddleAlignment(l.Front, donesides, udmf);
-					CheckBottomAlignment(l.Front, donesides, udmf);
+					if(!donesides[VisualGeometryType.WALL_UPPER].ContainsKey(l.Front.Index))
+						CheckTopAlignment(l.Front);
+					if(!donesides[VisualGeometryType.WALL_MIDDLE].ContainsKey(l.Front.Index))
+						CheckMiddleAlignment(l.Front);
+					if(!donesides[VisualGeometryType.WALL_LOWER].ContainsKey(l.Front.Index))
+						CheckBottomAlignment(l.Front);
 				}
 
 				// Check if we need to align any part of the back sidedef
-				if (l.Back != null) 
+				if(l.Back != null) 
 				{
-					CheckTopAlignment(l.Back, donesides, udmf);
-					CheckMiddleAlignment(l.Back, donesides, udmf);
-					CheckBottomAlignment(l.Back, donesides, udmf);
+					if(!donesides[VisualGeometryType.WALL_UPPER].ContainsKey(l.Back.Index))
+						CheckTopAlignment(l.Back);
+					if(!donesides[VisualGeometryType.WALL_MIDDLE].ContainsKey(l.Back.Index))
+						CheckMiddleAlignment(l.Back);
+					if(!donesides[VisualGeometryType.WALL_LOWER].ContainsKey(l.Back.Index))
+						CheckBottomAlignment(l.Back);
 				}
 
 				// Handle thread interruption
-				try { Thread.Sleep(0); } catch(ThreadInterruptedException) { return; }
+				try
+				{
+					Thread.Sleep(0);
+				}
+				catch (ThreadInterruptedException)
+				{
+					// Clear collection
+					donesides.Clear();
+					return;
+				}
 
 				// We are making progress!
 				if ((++progress / PROGRESS_STEP) > stepprogress) 
@@ -75,93 +97,72 @@ namespace CodeImp.DoomBuilder.BuilderModes.ErrorChecks
 					AddProgress(1);
 				}
 			}
+
+			// Clear collection
+			donesides.Clear();
 		}
 
 		#endregion
 
-		#region ================== UDMF alignment checks
+		#region ================== Alignment checks
 
-		private void CheckTopAlignment(Sidedef sidedef, Dictionary<int, Dictionary<int, bool>> donesides, bool udmf) 
+		private void CheckTopAlignment(Sidedef sidedef) 
 		{
 			if (!sidedef.HighRequired() || sidedef.LongHighTexture == MapSet.EmptyLongName) return;
-			if (!udmf)
-			{
-				CheckClassicTopAlignment(sidedef, donesides);
-				return;
-			}
+			
+			float scaleX = sidedef.Fields.GetValue("scalex_top", 1.0f);
+			float scaleY = sidedef.Fields.GetValue("scaley_top", 1.0f);
+			int localY = (int)Math.Round(sidedef.Fields.GetValue("offsety_top", 0.0f));
 
+			int x = sidedef.OffsetX + (int)Math.Round(sidedef.Fields.GetValue("offsetx_top", 0.0f));
+			int y = (int)Tools.GetSidedefTopOffsetY(sidedef, sidedef.OffsetY + localY, scaleY, false);
+			CheckAlignment(sidedef, x, y, scaleX, scaleY, VisualGeometryType.WALL_UPPER, sidedef.HighTexture);
 		}
 
-		private void CheckMiddleAlignment(Sidedef sidedef, Dictionary<int, Dictionary<int, bool>> donesides, bool udmf) 
+		private void CheckMiddleAlignment(Sidedef sidedef) 
 		{
 			if (!sidedef.MiddleRequired() || sidedef.LongMiddleTexture == MapSet.EmptyLongName) return;
-			if (!udmf)
-			{
-				CheckClassicMiddleAlignment(sidedef, donesides);
-				return;
-			}
+			
+			float scaleX = sidedef.Fields.GetValue("scalex_mid", 1.0f);
+			float scaleY = sidedef.Fields.GetValue("scaley_mid", 1.0f);
+			int localY = (int)Math.Round(sidedef.Fields.GetValue("offsety_mid", 0.0f));
 
+			int x = sidedef.OffsetX + (int)Math.Round(sidedef.Fields.GetValue("offsetx_mid", 0.0f));
+			int y = (int)Tools.GetSidedefMiddleOffsetY(sidedef, sidedef.OffsetY + localY, scaleY, false);
+			CheckAlignment(sidedef, x, y, scaleX, scaleY, VisualGeometryType.WALL_MIDDLE, sidedef.MiddleTexture);
 		}
 
-		private void CheckBottomAlignment(Sidedef sidedef, Dictionary<int, Dictionary<int, bool>> donesides, bool udmf) 
+		private void CheckBottomAlignment(Sidedef sidedef) 
 		{
-			if (!sidedef.LowRequired() || sidedef.LongLowTexture == MapSet.EmptyLongName) return;
-			if (!udmf) 
-			{
-				CheckClassicBottomAlignment(sidedef, donesides);
-				return;
-			}
+			if(!sidedef.LowRequired() || sidedef.LongLowTexture == MapSet.EmptyLongName) return;
 
-		}
+			float scaleX = sidedef.Fields.GetValue("scalex_bottom", 1.0f);
+			float scaleY = sidedef.Fields.GetValue("scaley_bottom", 1.0f);
+			int localY = (int)Math.Round(sidedef.Fields.GetValue("offsety_bottom", 0.0f));
 
-		private void AddProcessedSides(Sidedef s1, Sidedef s2, Dictionary<int, Dictionary<int, bool>> donesides)
-		{
-			// Add them both ways
-			if (!donesides.ContainsKey(s1.Index)) donesides.Add(s1.Index, new Dictionary<int, bool>());
-			donesides[s1.Index].Add(s2.Index, false);
-
-			if (!donesides.ContainsKey(s2.Index)) donesides.Add(s2.Index, new Dictionary<int, bool>());
-			donesides[s2.Index].Add(s1.Index, false);
+			int x = sidedef.OffsetX + (int)Math.Round(sidedef.Fields.GetValue("offsetx_bottom", 0.0f));
+			int y = (int)Tools.GetSidedefBottomOffsetY(sidedef, sidedef.OffsetY + localY, scaleY, false);
+			CheckAlignment(sidedef, x, y, scaleX, scaleY, VisualGeometryType.WALL_LOWER, sidedef.LowTexture);
 		}
 
 		#endregion
 
-		#region ==================  Classic alignment checks
-
-		private void CheckClassicTopAlignment(Sidedef sidedef, Dictionary<int, Dictionary<int, bool>> donesides) 
-		{
-			int x = sidedef.OffsetX;
-			int y = (int)Tools.GetSidedefTopOffsetY(sidedef, sidedef.OffsetY, 1.0f, false);
-			CheckClassicAlignment(sidedef, x, y, BuilderModesTools.GetSidedefPartSize(sidedef, VisualGeometryType.WALL_UPPER), sidedef.HighTexture, donesides);
-		}
-
-		private void CheckClassicMiddleAlignment(Sidedef sidedef, Dictionary<int, Dictionary<int, bool>> donesides)
-		{
-			int x = sidedef.OffsetX;
-			int y = (int)Tools.GetSidedefMiddleOffsetY(sidedef, sidedef.OffsetY, 1.0f, false);
-			CheckClassicAlignment(sidedef, x, y, BuilderModesTools.GetSidedefPartSize(sidedef, VisualGeometryType.WALL_MIDDLE), sidedef.MiddleTexture, donesides);
-		}
-
-		private void CheckClassicBottomAlignment(Sidedef sidedef, Dictionary<int, Dictionary<int, bool>> donesides) 
-		{
-			int x = sidedef.OffsetX;
-			int y = (int)Tools.GetSidedefBottomOffsetY(sidedef, sidedef.OffsetY, 1.0f, false);
-			CheckClassicAlignment(sidedef, x, y, BuilderModesTools.GetSidedefPartSize(sidedef, VisualGeometryType.WALL_LOWER), sidedef.LowTexture, donesides);
-		}
+		#region ================== Methods
 
-		private void CheckClassicAlignment(Sidedef sidedef, int offsetx, int offsety, Rectangle partsize, string texturename, Dictionary<int, Dictionary<int, bool>> donesides) 
+		private void CheckAlignment(Sidedef sidedef, int offsetx, int offsety, float linescalex, float linescaley, VisualGeometryType parttype, string texturename) 
 		{
 			ImageData texture = General.Map.Data.GetTextureImage(texturename);
-			if (!texture.IsImageLoaded) return;
+			if(!texture.IsImageLoaded) return;
+			Rectangle partsize = BuilderModesTools.GetSidedefPartSize(sidedef, parttype);
 
-			float scalex = (General.Map.Config.ScaledTextureOffsets && !texture.WorldPanning) ? texture.Scale.x : 1.0f;
-			float scaley = (General.Map.Config.ScaledTextureOffsets && !texture.WorldPanning) ? texture.Scale.y : 1.0f;
+			float scalex = ((General.Map.Config.ScaledTextureOffsets && !texture.WorldPanning) ? texture.Scale.x : 1.0f);
+			float scaley = ((General.Map.Config.ScaledTextureOffsets && !texture.WorldPanning) ? texture.Scale.y : 1.0f);
 
 			// Move offsets to proper range
 			offsetx %= texture.Width;
-			if (offsetx < 0) offsetx += texture.Width;
+			if(offsetx < 0) offsetx += texture.Width;
 			offsety %= texture.Height;
-			if (offsety < 0) offsety += texture.Height;
+			if(offsety < 0) offsety += texture.Height;
 
 			// Check if current line is aligned to other sides
 			ICollection<Linedef> lines = (sidedef.IsFront ? sidedef.Line.Start.Linedefs : sidedef.Line.End.Linedefs);
@@ -169,32 +170,48 @@ namespace CodeImp.DoomBuilder.BuilderModes.ErrorChecks
 
 			foreach(Linedef line in lines) 
 			{
-				if (line.Index == sidedef.Line.Index) continue;
+				if(line.Index == sidedef.Line.Index) continue;
 
 				Sidedef target = null;
-				if (line.Front != null && line.End == v) target = line.Front;
-				else if (line.Back != null && line.Start == v) target = line.Back;
+				if(line.Front != null && line.End == v) target = line.Front;
+				else if(line.Back != null && line.Start == v) target = line.Back;
 
 				// No target or laready processed?
-				if (target == null || (donesides.ContainsKey(sidedef.Index) && donesides[sidedef.Index].ContainsKey(target.Index)))
+				if(target == null || (donesides[parttype].ContainsKey(sidedef.Index) && donesides[parttype][sidedef.Index].ContainsKey(target.Index)))
 					continue;
 
 				// Get expected texture offsets
-				int alignedY = GetExpectedOffsetY(sidedef, target, texturename, texture.Height, scaley, partsize);
-				if (alignedY == int.MinValue) continue; // alignedY == int.MinValue means no textures on target and current source part match 
-				
+				VisualGeometryType targetparttype = VisualGeometryType.UNKNOWN;
+				int alignedY = GetExpectedOffsetY(sidedef, target, texturename, texture.Height, scaley, linescaley, partsize, ref targetparttype);
+				if(targetparttype == VisualGeometryType.UNKNOWN) continue;
+
+				// Not aligned if scaley is not equal
+				float targetscaley = GetSidedefValue(target, targetparttype, "scaley", 1.0f);
+				if(targetscaley != linescaley) {
+#if DEBUG //TODO: remove this
+					string msg = "Case 1: '" + texturename + "' source " + sidedef.Line.Index + " (" + (sidedef.IsFront ? "front" : "back")
+						+ "), target " + target.Line.Index + " (" + (target.IsFront ? "front" : "back")
+						+ "): scale mismatch: target: " + targetscaley
+						+ "; source: " + linescaley;
+					SubmitResult(new ResultTexturesMisaligned(sidedef, target, texturename, msg));
+#else
+					SubmitResult(new ResultTexturesMisaligned(sidedef, target, texturename));
+#endif
+				}
+				float targetscalex = GetSidedefValue(target, targetparttype, "scalex", 1.0f);
+
 				alignedY %= texture.Height;
-				if (alignedY < 0) alignedY += texture.Height;
+				if(alignedY < 0) alignedY += texture.Height;
 
-				int alignedX = (target.OffsetX + (int)Math.Round(target.Line.Length / scalex)) % texture.Width;
-				if (alignedX < 0) alignedX += texture.Width;
+				int alignedX = (target.OffsetX + (int)GetSidedefValue(target, targetparttype, "offsetx", 0f) + (int)Math.Round(target.Line.Length / scalex * targetscalex)) % texture.Width;
+				if(alignedX < 0) alignedX += texture.Width;
 
 				// Submit result if target offsets don't match expected ones
-				if (offsetx != alignedX || offsety != alignedY)
+				if(offsetx != alignedX || offsety != alignedY) 
 				{
 #if DEBUG //TODO: remove this
-					string msg = "Case 1: '"+texturename+"' source " + sidedef.Line.Index + " (" + (sidedef.IsFront ? "front" : "back") 
-						+ "), target " + target.Line.Index + " (" + (target.IsFront ? "front" : "back") 
+					string msg = "Case 1: '" + texturename + "' source " + sidedef.Line.Index + " (" + (sidedef.IsFront ? "front" : "back")
+						+ "), target " + target.Line.Index + " (" + (target.IsFront ? "front" : "back")
 						+ "): expected: " + alignedX + ", " + alignedY
 						+ "; actual [source]: " + offsetx + ", " + offsety;
 
@@ -202,8 +219,10 @@ namespace CodeImp.DoomBuilder.BuilderModes.ErrorChecks
 #else
 					SubmitResult(new ResultTexturesMisaligned(sidedef, target, texturename));
 #endif
-					AddProcessedSides(sidedef, target, donesides);
 				}
+
+				// Add to collection
+				AddProcessedSides(sidedef, parttype, target, targetparttype);
 			}
 
 			// Check if other sides are aligned to current side
@@ -212,28 +231,44 @@ namespace CodeImp.DoomBuilder.BuilderModes.ErrorChecks
 
 			foreach(Linedef line in lines) 
 			{
-				if (line.Index == sidedef.Line.Index) continue;
+				if(line.Index == sidedef.Line.Index) continue;
 
 				Sidedef target = null;
-				if (line.Front != null && line.Start == v) target = line.Front;
-				else if (line.Back != null && line.End == v) target = line.Back;
+				if(line.Front != null && line.Start == v) target = line.Front;
+				else if(line.Back != null && line.End == v) target = line.Back;
 
 				// No target or laready processed?
-				if (target == null || (donesides.ContainsKey(sidedef.Index) && donesides[sidedef.Index].ContainsKey(target.Index)))
+				if(target == null || (donesides[parttype].ContainsKey(sidedef.Index) && donesides[parttype][sidedef.Index].ContainsKey(target.Index)))
 					continue;
 
 				// Get expected texture offsets
-				int alignedY = GetExpectedOffsetY(sidedef, target, texturename, texture.Height, scaley, partsize);
-				if (alignedY == int.MinValue) continue; // alignedY == int.MinValue means no textures on target and current source part match 
-				
+				VisualGeometryType targetparttype = VisualGeometryType.UNKNOWN;
+				int alignedY = GetExpectedOffsetY(sidedef, target, texturename, texture.Height, scaley, linescaley, partsize, ref targetparttype);
+				if(targetparttype == VisualGeometryType.UNKNOWN) continue;
+
+				// Not aligned if scaley is not equal
+				float targetscaley = GetSidedefValue(target, targetparttype, "scaley", 1.0f);
+				if (targetscaley != linescaley)
+				{
+#if DEBUG //TODO: remove this
+					string msg = "Case 2: '" + texturename + "' source " + sidedef.Line.Index + " (" + (sidedef.IsFront ? "front" : "back")
+						+ "), target " + target.Line.Index + " (" + (target.IsFront ? "front" : "back")
+						+ "): scale mismatch: target: " + targetscaley
+						+ "; source: " + linescaley;
+					SubmitResult(new ResultTexturesMisaligned(sidedef, target, texturename, msg));
+#else
+					SubmitResult(new ResultTexturesMisaligned(sidedef, target, texturename));
+#endif
+				}
+
 				alignedY %= texture.Height;
-				if (alignedY < 0) alignedY += texture.Height;
+				if(alignedY < 0) alignedY += texture.Height;
 
-				int alignedX = (target.OffsetX - (int)Math.Round(sidedef.Line.Length / scalex)) % texture.Width;
-				if (alignedX < 0) alignedX += texture.Width;
+				int alignedX = (target.OffsetX + (int)GetSidedefValue(target, targetparttype, "offsetx", 0f) - (int)Math.Round(sidedef.Line.Length / scalex * linescalex)) % texture.Width;
+				if(alignedX < 0) alignedX += texture.Width;
 
 				// Submit result if target offsets don't match expected ones
-				if (offsetx != alignedX || offsety != alignedY) 
+				if(offsetx != alignedX || offsety != alignedY) 
 				{
 #if DEBUG //TODO: remove this
 					string msg = "Case 2: '" + texturename + "' source " + sidedef.Line.Index + " (" + (sidedef.IsFront ? "front" : "back")
@@ -241,35 +276,71 @@ namespace CodeImp.DoomBuilder.BuilderModes.ErrorChecks
 						+ "): expected: " + alignedX + ", " + alignedY
 						+ "; actual [source]: " + offsetx + ", " + offsety;
 					
-					SubmitResult(new ResultTexturesMisaligned(target, sidedef, texturename, msg));
+					SubmitResult(new ResultTexturesMisaligned(sidedef, target, texturename, msg));
 #else
-					SubmitResult(new ResultTexturesMisaligned(target, sidedef, texturename));
+					SubmitResult(new ResultTexturesMisaligned(sidedef, target, texturename));
 #endif
-					AddProcessedSides(sidedef, target, donesides);
 				}
+
+				// Add to collection
+				AddProcessedSides(sidedef, parttype, target, targetparttype);
 			}
 		}
 
-		private int GetExpectedOffsetY(Sidedef source, Sidedef target, string texturename, int textureheight, float scaleY, Rectangle partsize) 
+		private float GetSidedefValue(Sidedef target, VisualGeometryType targetparttype, string key, float defaultvalue) 
+		{
+			switch (targetparttype)
+			{
+				case VisualGeometryType.WALL_UPPER:
+					return (float)Math.Round(UDMFTools.GetFloat(target.Fields, key + "_top", defaultvalue), 3);
+
+				case VisualGeometryType.WALL_MIDDLE:
+					return (float)Math.Round(UDMFTools.GetFloat(target.Fields, key + "_mid", defaultvalue), 3);
+
+				case VisualGeometryType.WALL_LOWER:
+					return (float)Math.Round(UDMFTools.GetFloat(target.Fields, key + "_bottom", defaultvalue), 3);
+			}
+
+			return 0;
+		}
+
+		private void AddProcessedSides(Sidedef s1, VisualGeometryType type1, Sidedef s2, VisualGeometryType type2)
 		{
-			if (target.MiddleTexture == texturename
-					&& partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_MIDDLE))) 
+			// Add them both ways
+			if(!donesides[type1].ContainsKey(s1.Index)) donesides[type1].Add(s1.Index, new Dictionary<int, bool>());
+			donesides[type1][s1.Index].Add(s2.Index, false);
+
+			if(!donesides[type2].ContainsKey(s2.Index)) donesides[type2].Add(s2.Index, new Dictionary<int, bool>());
+			donesides[type2][s2.Index].Add(s1.Index, false);
+		}
+
+		private int GetExpectedOffsetY(Sidedef source, Sidedef target, string texturename, int textureheight, float texturescaley, float linescaley, Rectangle partsize, ref VisualGeometryType matchingparttype) 
+		{
+			if(target.MiddleTexture == texturename
+					&& partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_MIDDLE)))
 			{
-				return ((int)Tools.GetSidedefMiddleOffsetY(target, target.OffsetY, 1.0f, false) + (int)Math.Round((target.Sector.CeilHeight - source.Sector.CeilHeight) / scaleY)) % textureheight;
-			} 
+				matchingparttype = VisualGeometryType.WALL_MIDDLE;
+				int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
+				return ((int)Tools.GetSidedefMiddleOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight;
+			}
 			
-			if (target.HighTexture == texturename
+			if(target.HighTexture == texturename
 					&& partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_UPPER))) 
 			{
-				return ((int)Tools.GetSidedefTopOffsetY(target, target.OffsetY, 1.0f, false) + (int)Math.Round((target.Sector.CeilHeight - source.Sector.CeilHeight) / scaleY)) % textureheight;
-			} 
-			
-			if (target.LowTexture == texturename
+				matchingparttype = VisualGeometryType.WALL_UPPER;
+				int partheight = (int) Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
+				return ((int)Tools.GetSidedefTopOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight;
+			}
+
+			if(target.LowTexture == texturename
 				  && partsize.IntersectsWith(BuilderModesTools.GetSidedefPartSize(target, VisualGeometryType.WALL_LOWER))) 
 			{
-				return ((int)Tools.GetSidedefBottomOffsetY(target, target.OffsetY, 1.0f, false) + (int)Math.Round((target.Sector.CeilHeight - source.Sector.CeilHeight) / scaleY)) % textureheight;
+				matchingparttype = VisualGeometryType.WALL_LOWER;
+				int partheight = (int)Math.Round(((target.Sector.CeilHeight - source.Sector.CeilHeight) / texturescaley) * linescaley);
+				return ((int)Tools.GetSidedefBottomOffsetY(target, target.OffsetY + GetSidedefValue(target, matchingparttype, "offsety", 0f), linescaley, false) + partheight) % textureheight;
 			}
 
+			matchingparttype = VisualGeometryType.UNKNOWN;
 			return int.MinValue;
 		}
 
diff --git a/Source/Plugins/BuilderModes/Interface/ErrorCheckForm.Designer.cs b/Source/Plugins/BuilderModes/Interface/ErrorCheckForm.Designer.cs
index 1b843fb06..0417860f9 100644
--- a/Source/Plugins/BuilderModes/Interface/ErrorCheckForm.Designer.cs
+++ b/Source/Plugins/BuilderModes/Interface/ErrorCheckForm.Designer.cs
@@ -312,9 +312,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			this.toggleall.CheckState = System.Windows.Forms.CheckState.Checked;
 			this.toggleall.Location = new System.Drawing.Point(10, 12);
 			this.toggleall.Name = "toggleall";
-			this.toggleall.Size = new System.Drawing.Size(71, 18);
+			this.toggleall.Size = new System.Drawing.Size(70, 18);
 			this.toggleall.TabIndex = 5;
-			this.toggleall.Text = "Toggle All";
+			this.toggleall.Text = "Toggle all";
 			this.toggleall.UseVisualStyleBackColor = true;
 			this.toggleall.CheckedChanged += new System.EventHandler(this.toggleall_CheckedChanged);
 			// 
diff --git a/Source/Plugins/BuilderModes/Interface/ErrorCheckForm.resx b/Source/Plugins/BuilderModes/Interface/ErrorCheckForm.resx
index e86ef2190..4b7dd4c27 100644
--- a/Source/Plugins/BuilderModes/Interface/ErrorCheckForm.resx
+++ b/Source/Plugins/BuilderModes/Interface/ErrorCheckForm.resx
@@ -123,9 +123,6 @@
   <metadata name="progress.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="progress.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-    <value>True</value>
-  </metadata>
   <metadata name="closebutton.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-- 
GitLab