diff --git a/Build/Configurations/Includes/Hexen_linedefs.cfg b/Build/Configurations/Includes/Hexen_linedefs.cfg
index 5fbd3fe4882bdc4c4da44529eb584df28ff3c484..3dd84d31f68a0bc811b2c0425e65a13888aaa9c5 100644
--- a/Build/Configurations/Includes/Hexen_linedefs.cfg
+++ b/Build/Configurations/Includes/Hexen_linedefs.cfg
@@ -1453,9 +1453,9 @@ teleport
 		
 		arg0
 		{
-			title = "Target MapSpot Tag";
+			title = "Target Teleport Dest. Tag";
 			type = 14;
-			targetclasses = "MapSpot,MapSpotGravity";
+			targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
 		}
 		
 		arg1
@@ -1472,9 +1472,9 @@ teleport
 		
 		arg0
 		{
-			title = "Target MapSpot Tag";
+			title = "Target Teleport Dest. Tag";
 			type = 14;
-			targetclasses = "MapSpot,MapSpotGravity";
+			targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
 		}
 		
 		arg1
diff --git a/Build/Configurations/Includes/ZDoom_linedefs.cfg b/Build/Configurations/Includes/ZDoom_linedefs.cfg
index b01071882340346ee53bab89104b3138dba57d78..60b8ac26a1e222ef8edf3850594e02591f2172f7 100644
--- a/Build/Configurations/Includes/ZDoom_linedefs.cfg
+++ b/Build/Configurations/Includes/ZDoom_linedefs.cfg
@@ -2128,9 +2128,9 @@ zdoom
 			
 			arg0
 			{
-				title = "Target MapSpot Tag";
+				title = "Target Teleport Dest. Tag";
 				type = 14;
-				targetclasses = "MapSpot,MapSpotGravity";
+				targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
 			}
 			arg1
 			{
@@ -2196,17 +2196,20 @@ zdoom
 			arg0
 			{
 				title = "Thing Tag";
+				tooltip = "The TID of the actor(s) to teleport.\nIf 0, teleports the activator only.";
 				type = 14;
 			}
 			arg1
 			{
 				title = "Source Teleport Dest. Tag";
 				type = 14;
+				targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
 			}
 			arg2
 			{
 				title = "Target Teleport Dest. Tag";
 				type = 14;
+				targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
 			}
 			arg3
 			{
@@ -2233,15 +2236,15 @@ zdoom
 			}
 			arg1
 			{
-				title = "Source MapSpot Tag";
+				title = "Source Tag";
+				tooltip = "The spot relative to which to teleport.";
 				type = 14;
-				targetclasses = "MapSpot,MapSpotGravity";
 			}
 			arg2
 			{
-				title = "Target MapSpot Tag";
+				title = "Target Teleport Dest. Tag";
 				type = 14;
-				targetclasses = "MapSpot,MapSpotGravity";
+				targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
 			}
 			arg3
 			{
@@ -2252,6 +2255,7 @@ zdoom
 			arg4
 			{
 				title = "Group Thing Tag";
+				tooltip = "The TID of the thing(s) to teleport.\nIf 0, teleports all actors in the sector";
 				type = 14;
 			}
 		}
@@ -2262,9 +2266,9 @@ zdoom
 			
 			arg0
 			{
-				title = "Target MapSpot Tag";
+				title = "Target Teleport Dest. Tag";
 				type = 14;
-				targetclasses = "MapSpot,MapSpotGravity";
+				targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
 			}
 			arg1
 			{
diff --git a/Source/Core/Controls/DebugConsole.cs b/Source/Core/Controls/DebugConsole.cs
index 832c566209bcb1f7e9f5886479f059567e6090f8..2ad24761c5517f065621ebb31ff2c48a6d882313 100644
--- a/Source/Core/Controls/DebugConsole.cs
+++ b/Source/Core/Controls/DebugConsole.cs
@@ -41,6 +41,7 @@ namespace CodeImp.DoomBuilder
 
 		private DebugMessageType filters;
 		private static long starttime = -1;
+		private static int counter;
 		private static DebugConsole me;
 
 		#endregion
@@ -159,6 +160,24 @@ namespace CodeImp.DoomBuilder
 			starttime = -1;
 		}
 
+		public static void IncrementCounter() { IncrementCounter(1); }
+		public static void IncrementCounter(int incrementby)
+		{
+			counter += incrementby;
+		}
+
+		public static void ResetCounter(string message)
+		{
+			if(message.Contains("%"))
+				message = message.Replace("%", counter.ToString());
+			else
+				message = message.TrimEnd() + ": " + counter;
+
+			WriteLine(DebugMessageType.SPECIAL, message);
+
+			counter = 0;
+		}
+
 		public static void StartProfiler()
 		{
 #if PROFILE
diff --git a/Source/Core/Data/DataManager.cs b/Source/Core/Data/DataManager.cs
index 1646ef8adc25057eceb28ffeecededcfe31e64ed..1c402e569da834384b4279ff8ec924cd53fd368d 100644
--- a/Source/Core/Data/DataManager.cs
+++ b/Source/Core/Data/DataManager.cs
@@ -590,7 +590,7 @@ namespace CodeImp.DoomBuilder.Data
 			palette = null;
 
 			//mxd. Dispose models
-			foreach(KeyValuePair<int, ModelData> i in modeldefentries) i.Value.Dispose();
+			foreach(ModelData md in modeldefentries.Values) md.Dispose();
 		
 			// Dispose containers
 			foreach(DataReader c in containers) c.Dispose();
@@ -2052,7 +2052,7 @@ namespace CodeImp.DoomBuilder.Data
 		public void ReloadModeldef() 
 		{
 			if(modeldefentries != null) 
-				foreach(KeyValuePair<int, ModelData> group in modeldefentries) group.Value.Dispose();
+				foreach(ModelData md in modeldefentries.Values) md.Dispose();
 
 			// Bail out when not supported by current game configuration
 			if(string.IsNullOrEmpty(General.Map.Config.DecorateGames)) return;
@@ -2105,16 +2105,14 @@ namespace CodeImp.DoomBuilder.Data
 			General.MainWindow.DisplayReady();
 		}
 
-		//mxd. This parses modeldefs. Should be called after all DECORATE actors are parsed and actorsByClass dictionary created
+		//mxd. This parses modeldefs. Should be called after all DECORATE actors are parsed
 		private void LoadModeldefs(Dictionary<string, int> actorsbyclass) 
 		{
-			//if no actors defined in DECORATE or game config...
+			// Abort if no classnames are defined in DECORATE or game config...
 			if(actorsbyclass.Count == 0) return;
 
-			Dictionary<string, ModelData> modeldefentriesbyname = new Dictionary<string, ModelData>(StringComparer.Ordinal);
 			ModeldefParser parser = new ModeldefParser(actorsbyclass);
-
-			foreach(DataReader dr in containers) 
+			foreach(DataReader dr in containers)
 			{
 				currentreader = dr;
 
@@ -2122,30 +2120,21 @@ namespace CodeImp.DoomBuilder.Data
 				foreach(TextResourceData data in streams) 
 				{
 					// Parse the data
-					if(parser.Parse(data, true)) 
-					{
-						foreach(KeyValuePair<string, ModelData> g in parser.Entries) 
-						{
-							if(modeldefentriesbyname.ContainsKey(g.Key))
-								General.ErrorLogger.Add(ErrorType.Warning, "Model definition for actor \"" + g.Key + "\" is double defined in \"" + Path.Combine(data.Source.Location.GetDisplayName(), data.Filename) + "\"");
-							
-							modeldefentriesbyname[g.Key] = g.Value;
-						}
-					}
+					parser.Parse(data, true);
 
 					// Modeldefs are independable, so parsing fail in one file should not affect the others
 					if(parser.HasError) parser.LogError();
 				}
 			}
 
-			//mxd. Add to text resources collection
+			// Add to text resources collection
 			textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values);
 			currentreader = null;
 
-			foreach(KeyValuePair<string, ModelData> e in modeldefentriesbyname) 
+			foreach(KeyValuePair<string, ModelData> e in parser.Entries) 
 			{
 				if(actorsbyclass.ContainsKey(e.Key))
-					modeldefentries[actorsbyclass[e.Key]] = modeldefentriesbyname[e.Key];
+					modeldefentries[actorsbyclass[e.Key]] = parser.Entries[e.Key];
 				else if(!decorate.ActorsByClass.ContainsKey(e.Key))
 					General.ErrorLogger.Add(ErrorType.Warning, "MODELDEF model \"" + e.Key + "\" doesn't match any Decorate actor class");
 			}
@@ -2228,7 +2217,7 @@ namespace CodeImp.DoomBuilder.Data
 				}
 			}
 
-			//mxd. Add to text resources collection
+			// Add to text resources collection
 			textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values);
 			currentreader = null;
 
diff --git a/Source/Core/GZBuilder/md3/ModelReader.cs b/Source/Core/GZBuilder/md3/ModelReader.cs
index 99921f33f353bdc7d690350348b5761b9c98b5b0..2ecba643472e618c472a5fe7a884a43192ca1129 100644
--- a/Source/Core/GZBuilder/md3/ModelReader.cs
+++ b/Source/Core/GZBuilder/md3/ModelReader.cs
@@ -354,9 +354,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
 			int ofsEnd = br.ReadInt32(); //Relative offset from SURFACE_START to where the Surface object ends.
 
 			// Sanity check
-			if(frame < 0 || frame > numFrames)
+			if(frame < 0 || frame >= numFrames)
 			{
-				return "invalid frame number! (frame number: " + frame + ", total frames: " + numFrames + ")";
+				return "frame " + frame + " is outside of model's frame range [0.." + (numFrames - 1) + "]";
 			}
 
 			// Polygons
@@ -453,15 +453,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
 				int num_frames = br.ReadInt32(); //Total number of frames
 
 				// Sanity checks
-				if(num_frames == 0) 
+				if(frame < 0 || frame >= num_frames)
 				{
-					result.Errors = "model has 0 frames.";
-					return result;
-				}
-
-				if(num_frames < frame || frame < 0)
-				{
-					result.Errors = "invalid target frame! (target frame: " + frame + ", total frames: " + num_frames + ")";
+					result.Errors = "frame " + frame + " is outside of model's frame range [0.." + (num_frames - 1) + "]";
 					return result;
 				}
 
diff --git a/Source/Core/Geometry/Tools.cs b/Source/Core/Geometry/Tools.cs
index fd2e41b5dcceb03989c7282d4989a57f2324df9f..269d0da28cd570ac614f514e0e2455123f3e5f84 100644
--- a/Source/Core/Geometry/Tools.cs
+++ b/Source/Core/Geometry/Tools.cs
@@ -1833,6 +1833,14 @@ namespace CodeImp.DoomBuilder.Geometry
 				   ((sd.LongMiddleTexture == texturelongname) && (sd.MiddleRequired() || sd.LongMiddleTexture != MapSet.EmptyLongName)) ;
 		}
 
+		//mxd. This checks if any of the sidedef texture match the given textures
+		public static bool SidedefTextureMatch(Sidedef sd, HashSet<long> texturelongnames)
+		{
+			return (texturelongnames.Contains(sd.LongHighTexture) && sd.HighRequired()) ||
+				   (texturelongnames.Contains(sd.LongLowTexture) && sd.LowRequired()) ||
+				   (texturelongnames.Contains(sd.LongMiddleTexture) && (sd.MiddleRequired() || sd.LongMiddleTexture != MapSet.EmptyLongName));
+		}
+
 		//mxd. This converts offsetY from/to "normalized" offset for given wall part
 		public static float GetSidedefOffsetY(Sidedef side, VisualGeometryType part, float offset, float scaleY, bool fromNormalized)
 		{
diff --git a/Source/Core/Rendering/Renderer2D.cs b/Source/Core/Rendering/Renderer2D.cs
index eb0b31efc1e91e19a292fc18d82d0d739e59b9ff..4076670c451f0e3ccfcfbd6fa5748e38cad3b3ec 100644
--- a/Source/Core/Rendering/Renderer2D.cs
+++ b/Source/Core/Rendering/Renderer2D.cs
@@ -1603,11 +1603,8 @@ namespace CodeImp.DoomBuilder.Rendering
 		public void RenderText(TextLabel label)
 		{
 			//mxd. Update the text if needed
-			RectangleF bbox = label.Update(translatex, translatey, scale, -scale);
-
-			//mxd. Have graphics / on screen?
-			if(label.VertexBuffer == null || (bbox.Right < 0.1f) || (bbox.Left > windowsize.Width) || (bbox.Bottom < 0.1f) || (bbox.Top > windowsize.Height))
-				return;
+			label.Update(translatex, translatey, scale, -scale);
+			if(label.SkipRendering) return;
 			
 			// Set renderstates for rendering
 			graphics.Device.SetRenderState(RenderState.CullMode, Cull.None);
@@ -1637,18 +1634,8 @@ namespace CodeImp.DoomBuilder.Rendering
 			foreach(TextLabel label in labels)
 			{
 				// Update the text if needed
-				RectangleF bbox = label.Update(translatex, translatey, scale, -scale);
-
-				// Have graphics / on screen?
-				if(label.VertexBuffer == null || (bbox.Right < 0.1f) || (bbox.Left > windowsize.Width) || (bbox.Bottom < 0.1f) || (bbox.Top > windowsize.Height))
-				{
-					label.SkipRendering = true;
-					skipped++;
-				}
-				else
-				{
-					label.SkipRendering = false;
-				}
+				label.Update(translatex, translatey, scale, -scale);
+				if(label.SkipRendering) skipped++;
 			}
 
 			if(labels.Count == skipped) return;
diff --git a/Source/Core/Rendering/TextLabel.cs b/Source/Core/Rendering/TextLabel.cs
index e3f50e11af203a8294b1af69ae4f59f6fa2a9528..26f35fcd2e5902506d6e4fd474515efed7f05eac 100644
--- a/Source/Core/Rendering/TextLabel.cs
+++ b/Source/Core/Rendering/TextLabel.cs
@@ -47,7 +47,6 @@ namespace CodeImp.DoomBuilder.Rendering
 		// Text settings
 		private string text;
 		private RectangleF rect;
-		private RectangleF absview; //mxd
 		private bool transformcoords;
 		private PixelColor color;
 		private PixelColor backcolor;
@@ -63,6 +62,9 @@ namespace CodeImp.DoomBuilder.Rendering
 		private float lasttranslatey;
 		private float lastscalex;
 		private float lastscaley;
+
+		//mxd. Rendering
+		private bool skiprendering;
 		
 		// Disposing
 		private bool isdisposed;
@@ -90,7 +92,7 @@ namespace CodeImp.DoomBuilder.Rendering
 		public bool DrawBackground { get { return drawbg; } set { if(drawbg != value) { drawbg = value; textureupdateneeded = true; } } } //mxd
 		internal Texture Texture { get { return texture; } } //mxd
 		internal VertexBuffer VertexBuffer { get { return textbuffer; } }
-		internal bool SkipRendering; //mxd
+		internal bool SkipRendering { get { return skiprendering; } } //mxd
 		
 		// Disposing
 		public bool IsDisposed { get { return isdisposed; } }
@@ -116,6 +118,10 @@ namespace CodeImp.DoomBuilder.Rendering
 			
 			// Register as resource
 			General.Map.Graphics.RegisterResource(this);
+
+			//mxd. Create the buffer
+			this.textbuffer = new VertexBuffer(General.Map.Graphics.Device, 4 * FlatVertex.Stride,
+										  Usage.Dynamic | Usage.WriteOnly, VertexFormat.None, Pool.Default);
 			
 			// We have no destructor
 			GC.SuppressFinalize(this);
@@ -143,7 +149,7 @@ namespace CodeImp.DoomBuilder.Rendering
 		#region ================== Methods
 		
 		// This updates the text if needed
-		internal RectangleF Update(float translatex, float translatey, float scalex, float scaley)
+		internal void Update(float translatex, float translatey, float scalex, float scaley)
 		{
 			// Check if transformation changed and needs to be updated
 			if(transformcoords && (translatex != lasttranslatex || translatey != lasttranslatey ||
@@ -156,30 +162,6 @@ namespace CodeImp.DoomBuilder.Rendering
 				updateneeded = true;
 			}
 
-			//mxd. Update texture if needed
-			if(textureupdateneeded)
-			{
-				// Get rid of old texture
-				if(texture != null)
-				{
-					texture.Dispose(); 
-					texture = null;
-				}
-
-				// Create label image
-				Bitmap img = CreateLabelImage(text, font, color, backcolor, drawbg);
-				textsize = img.Size;
-
-				// Create texture
-				MemoryStream memstream = new MemoryStream((img.Size.Width * img.Size.Height * 4) + 4096);
-				img.Save(memstream, ImageFormat.Bmp);
-				memstream.Seek(0, SeekOrigin.Begin);
-
-				texture = Texture.FromStream(General.Map.Graphics.Device, memstream, (int)memstream.Length,
-						img.Size.Width, img.Size.Height, 1, Usage.None, Format.Unknown,
-						Pool.Managed, General.Map.Graphics.PostFilter, General.Map.Graphics.MipGenerateFilter, 0);
-			}
-			
 			// Update if needed
 			if(updateneeded || textureupdateneeded)
 			{
@@ -187,6 +169,7 @@ namespace CodeImp.DoomBuilder.Rendering
 				if(text.Length > 0)
 				{
 					// Transform?
+					RectangleF absview;
 					if(transformcoords)
 					{
 						// Calculate absolute coordinates
@@ -202,6 +185,37 @@ namespace CodeImp.DoomBuilder.Rendering
 						absview = rect;
 					}
 
+					//mxd. Skip when not on screen...
+					RectangleF abssize = absview;
+					abssize.Inflate(textsize.Width / 2, textsize.Height / 2);
+					Size windowsize = General.Map.Graphics.RenderTarget.ClientSize;
+					skiprendering = (abssize.Right < 0.1f) || (abssize.Left > windowsize.Width) || (abssize.Bottom < 0.1f) || (abssize.Top > windowsize.Height);
+					if(skiprendering) return;
+
+					//mxd. Update texture if needed
+					if(textureupdateneeded)
+					{
+						// Get rid of old texture
+						if(texture != null)
+						{
+							texture.Dispose();
+							texture = null;
+						}
+
+						// Create label image
+						Bitmap img = CreateLabelImage(text, font, color, backcolor, drawbg);
+						textsize = img.Size;
+
+						// Create texture
+						MemoryStream memstream = new MemoryStream((img.Size.Width * img.Size.Height * 4) + 4096);
+						img.Save(memstream, ImageFormat.Bmp);
+						memstream.Seek(0, SeekOrigin.Begin);
+
+						texture = Texture.FromStream(General.Map.Graphics.Device, memstream, (int)memstream.Length,
+								img.Size.Width, img.Size.Height, 1, Usage.None, Format.Unknown,
+								Pool.Managed, General.Map.Graphics.PostFilter, General.Map.Graphics.MipGenerateFilter, 0);
+					}
+
 					// Align the text horizontally
 					float beginx = 0;
 					switch(alignx)
@@ -220,14 +234,6 @@ namespace CodeImp.DoomBuilder.Rendering
 						case TextAlignmentY.Bottom: beginy = absview.Y + absview.Height - textsize.Height; break;
 					}
 
-					// Do we have to make a new buffer?
-					if(textbuffer == null)
-					{
-						// Create the buffer
-						textbuffer = new VertexBuffer(General.Map.Graphics.Device, 4 * FlatVertex.Stride,
-													  Usage.Dynamic | Usage.WriteOnly, VertexFormat.None, Pool.Default);
-					}
-
 					//mxd. Lock the buffer
 					using(DataStream stream = textbuffer.Lock(0, 4 * FlatVertex.Stride, LockFlags.Discard | LockFlags.NoSystemLock))
 					{
@@ -241,16 +247,14 @@ namespace CodeImp.DoomBuilder.Rendering
 				else
 				{
 					// No faces in polygon
-					if(textbuffer != null) textbuffer.Dispose(); //mxd
 					textsize = new SizeF();
+					skiprendering = true; //mxd
 				}
 
 				// Text updated
 				updateneeded = false;
 				textureupdateneeded = false; //mxd
 			}
-
-			return absview; //mxd
 		}
 
 		//mxd
diff --git a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs
index e7bb2214b5da4dc449efef284504ed5ff97e3ab0..8a653f9e693a646590897d4d9b58126e2a1595b7 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs
@@ -606,7 +606,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 							if(requiredsize > group.Key.Labels[i].radius)
 							{
 								requiredsize = (General.Interface.MeasureString(group.Value[1], l.Font).Width / 2) / renderer.Scale;
-								l.Text = (requiredsize > group.Key.Labels[i].radius ? "+" : group.Value[1]);
+								if(requiredsize > group.Key.Labels[i].radius)
+									l.Text = (requiredsize > group.Key.Labels[i].radius * 4 ? string.Empty : "+");
+								else
+									l.Text = group.Value[1];
 							}
 							else
 							{
diff --git a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs
index 22762e57ede03f25ee6484fd772be92bac1609f5..6ddd127772165613eb244ef417e08e0411763155 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs
@@ -197,6 +197,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 					List<TextLabel> torender = new List<TextLabel>(orderedselection.Count);
 					foreach(Sector s in orderedselection) 
 					{
+						//mxd. Self-referencing (and probably some other) sectors don't have labels...
+						if(labels[s].Length == 0) continue;
+						
 						// Render labels
 						TextLabel[] labelarray = labels[s];
 						float requiredsize = (labelarray[0].TextSize.Height / 2) / renderer.Scale;
@@ -238,7 +241,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 					if(requiredsize > group.Key.Labels[i].radius) 
 					{
 						requiredsize = (General.Interface.MeasureString(group.Value[1], l.Font).Width / 2) / renderer.Scale;
-						l.Text = (requiredsize > group.Key.Labels[i].radius ? "+" : group.Value[1]);
+						if(requiredsize > group.Key.Labels[i].radius)
+							l.Text = (requiredsize > group.Key.Labels[i].radius * 4 ? string.Empty : "+");
+						else
+							l.Text = group.Value[1];
 					} 
 					else 
 					{
diff --git a/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs
index 5db17cb70e5a116c609cb85a631b440eedcc3c82..29252531456a0cdf91f6c1bac4e90f86083f8bb3 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs
@@ -277,7 +277,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 							if(requiredsize > group.Key.Labels[i].radius)
 							{
 								requiredsize = (General.Interface.MeasureString(group.Value[1], l.Font).Width / 2) / renderer.Scale;
-								l.Text = (requiredsize > group.Key.Labels[i].radius ? "+" : group.Value[1]);
+								if(requiredsize > group.Key.Labels[i].radius)
+									l.Text = (requiredsize > group.Key.Labels[i].radius * 4 ? string.Empty : "+");
+								else
+									l.Text = group.Value[1];
 							}
 							else
 							{
@@ -541,14 +544,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
 							//mxd. Update helper lines
 							UpdateHelperObjects();
 
+							//mxd. Update selection info
+							UpdateSelectionInfo();
+
 							// Update display
 							General.Interface.RedrawDisplay();
 						}
 					}
 				}
-
-				//mxd. Update selection info
-				UpdateSelectionInfo();
 			}
 
 			editpressed = false;
@@ -964,9 +967,20 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				Vector2D v = thing.Position;
 				TextLabel l = new TextLabel();
 				l.TransformCoords = true;
-				l.Rectangle = new RectangleF(v.x - thing.Size + 1, v.y + thing.Size - 1, 0f, 0f);
-				l.AlignX = TextAlignmentX.Left;
-				l.AlignY = TextAlignmentY.Top;
+
+				if(thing.FixedSize)
+				{
+					l.Rectangle = new RectangleF(v.x, v.y, 0f, 0f);
+					l.AlignX = TextAlignmentX.Center;
+					l.AlignY = TextAlignmentY.Middle;
+				}
+				else
+				{
+					l.Rectangle = new RectangleF(v.x - thing.Size + 1, v.y + thing.Size - 1, 0f, 0f);
+					l.AlignX = TextAlignmentX.Left;
+					l.AlignY = TextAlignmentY.Top;
+				}
+				
 				l.Color = (thing == highlighted ? General.Colors.Selection : General.Colors.Highlight);
 				l.Backcolor = General.Colors.Background.WithAlpha(255);
 				l.DrawBackground = true;
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
index a6835e4ec38226b5ced4d00e84e9315c96044497..18fe57b6e10f2c39f56bace491806b06507728bb 100644
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
@@ -3732,6 +3732,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				first.controlSide = start.Sidedef;
 			}
 
+			//mxd
+			HashSet<long> texturehashes = new HashSet<long> { texture.LongName };
+
 			first.forward = true;
 			todo.Push(first);
 
@@ -3761,11 +3764,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 					// Add sidedefs forward (connected to the right vertex)
 					Vertex v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start;
-					AddSidedefsForAlignment(todo, v, true, forwardoffset, 1.0f, texture.LongName, false);
+					AddSidedefsForAlignment(todo, v, true, forwardoffset, 1.0f, texturehashes, false);
 
 					// Add sidedefs backward (connected to the left vertex)
 					v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End;
-					AddSidedefsForAlignment(todo, v, false, backwardoffset, 1.0f, texture.LongName, false);
+					AddSidedefsForAlignment(todo, v, false, backwardoffset, 1.0f, texturehashes, false);
 				} 
 				else 
 				{
@@ -3787,11 +3790,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 					// Add sidedefs backward (connected to the left vertex)
 					Vertex v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End;
-					AddSidedefsForAlignment(todo, v, false, backwardoffset, 1.0f, texture.LongName, false);
+					AddSidedefsForAlignment(todo, v, false, backwardoffset, 1.0f, texturehashes, false);
 
 					// Add sidedefs forward (connected to the right vertex)
 					v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start;
-					AddSidedefsForAlignment(todo, v, true, forwardoffset, 1.0f, texture.LongName, false);
+					AddSidedefsForAlignment(todo, v, true, forwardoffset, 1.0f, texturehashes, false);
 				}
 			}
 		}
@@ -3821,6 +3824,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			else
 				first.controlSide = start.Sidedef;
 
+			//mxd. We potentially need to deal with 2 textures (because of long and short texture names)...
+			HashSet<long> texturehashes = new HashSet<long> { texture.LongName };
+			switch(start.GeometryType)
+			{
+				case VisualGeometryType.WALL_LOWER:
+					texturehashes.Add(first.controlSide.LongLowTexture);
+					break;
+
+				case VisualGeometryType.WALL_MIDDLE:
+				case VisualGeometryType.WALL_MIDDLE_3D:
+					texturehashes.Add(first.controlSide.LongMiddleTexture);
+					break;
+
+				case VisualGeometryType.WALL_UPPER:
+					texturehashes.Add(first.controlSide.LongHighTexture);
+					break;
+			}
+
 			//mxd
 			List<BaseVisualGeometrySidedef> selectedVisualSides = new List<BaseVisualGeometrySidedef>();
 			if(checkSelectedSidedefParts && !singleselection) 
@@ -3904,9 +3925,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				// Get the align job to do
 				SidedefAlignJob j = todo.Pop();
 
-				bool matchtop = (!j.sidedef.Marked && (!singleselection || j.sidedef.LongHighTexture == texture.LongName) && j.sidedef.HighRequired());
-				bool matchbottom = (!j.sidedef.Marked && (!singleselection || j.sidedef.LongLowTexture == texture.LongName) && j.sidedef.LowRequired());
-				bool matchmid = ((!singleselection || j.controlSide.LongMiddleTexture == texture.LongName) && (j.controlSide.MiddleRequired() || j.controlSide.LongMiddleTexture != MapSet.EmptyLongName)); //mxd
+				bool matchtop = (!j.sidedef.Marked && (!singleselection || texturehashes.Contains(j.sidedef.LongHighTexture)) && j.sidedef.HighRequired());
+				bool matchbottom = (!j.sidedef.Marked && (!singleselection || texturehashes.Contains(j.sidedef.LongLowTexture)) && j.sidedef.LowRequired());
+				bool matchmid = ((!singleselection || texturehashes.Contains(j.controlSide.LongMiddleTexture)) && (j.controlSide.MiddleRequired() || j.controlSide.LongMiddleTexture != MapSet.EmptyLongName)); //mxd
 
 				//mxd. If there's a selection, check if matched part is actually selected
 				if(checkSelectedSidedefParts && !singleselection) 
@@ -4037,11 +4058,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 					// Add sidedefs backward (connected to the left vertex)
 					v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End;
-					AddSidedefsForAlignment(todo, v, false, backwardoffset, j.scaleY, texture.LongName, true);
+					AddSidedefsForAlignment(todo, v, false, backwardoffset, j.scaleY, texturehashes, true);
 
 					// Add sidedefs forward (connected to the right vertex)
 					v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start;
-					AddSidedefsForAlignment(todo, v, true, forwardoffset, j.scaleY, texture.LongName, true);
+					AddSidedefsForAlignment(todo, v, true, forwardoffset, j.scaleY, texturehashes, true);
 				} 
 				else 
 				{
@@ -4133,17 +4154,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 					// Add sidedefs forward (connected to the right vertex)
 					v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start;
-					AddSidedefsForAlignment(todo, v, true, forwardoffset, j.scaleY, texture.LongName, true);
+					AddSidedefsForAlignment(todo, v, true, forwardoffset, j.scaleY, texturehashes, true);
 
 					// Add sidedefs backward (connected to the left vertex)
 					v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End;
-					AddSidedefsForAlignment(todo, v, false, backwardoffset, j.scaleY, texture.LongName, true);
+					AddSidedefsForAlignment(todo, v, false, backwardoffset, j.scaleY, texturehashes, true);
 				}
 			}
 		}
 
 		// This adds the matching, unmarked sidedefs from a vertex for texture alignment
-		private void AddSidedefsForAlignment(Stack<SidedefAlignJob> stack, Vertex v, bool forward, float offsetx, float scaleY, long texturelongname, bool udmf) 
+		private void AddSidedefsForAlignment(Stack<SidedefAlignJob> stack, Vertex v, bool forward, float offsetx, float scaleY, HashSet<long> texturelongnames, bool udmf) 
 		{
 			foreach(Linedef ld in v.Linedefs) 
 			{
@@ -4156,7 +4177,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 					foreach(Sidedef s in controlSides) 
 					{
-						if(!singleselection || Tools.SidedefTextureMatch(s, texturelongname)) 
+						if(!singleselection || Tools.SidedefTextureMatch(s, texturelongnames)) 
 						{
 							SidedefAlignJob nj = new SidedefAlignJob();
 							nj.forward = forward;
@@ -4174,7 +4195,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 					foreach(Sidedef s in controlSides) 
 					{
-						if(!singleselection || Tools.SidedefTextureMatch(s, texturelongname)) 
+						if(!singleselection || Tools.SidedefTextureMatch(s, texturelongnames)) 
 						{
 							SidedefAlignJob nj = new SidedefAlignJob();
 							nj.forward = forward;
diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs
index 8de6f796e1bdf2c338e3e19b9f3cda2ae6370f0a..089527faf11881084cc658e8228b1cd0108ac8a3 100644
--- a/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/VisualMiddle3D.cs
@@ -239,6 +239,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 					if(translucent && !othertranslucent && !ef.ClipSidedefs) continue;
 					if(ef.ClipSidedefs == extrafloor.ClipSidedefs || ef.ClipSidedefs) 
 					{
+						//TODO: find out why ef can be not updated at this point
+						//TODO: [this crashed on me once when performing auto-align on myriad of textures on BoA C1M0]
+						if(ef.Floor == null || ef.Ceiling == null) ef.Update();
+						
 						int num = polygons.Count;
 						for(int pi = 0; pi < num; pi++)
 						{