From 895a7bb71968da96724dda4aebbe9a841b4d7c37 Mon Sep 17 00:00:00 2001
From: MaxED <j.maxed@gmail.com>
Date: Wed, 4 May 2016 11:16:17 +0000
Subject: [PATCH] Fixed, MODELDEF parser: negative frame number of FrameIndex
 definition should be treated as "skip model rendering". Also added some more
 corner case handling. Fixed, Sound Environment mode: in some cases the view
 was not updated after updating sound environments. Added, Sound Environment
 mode: Sound environment things of currently highlighted sound environment are
 now highlighted.

---
 Source/Core/ZDoom/ModeldefParser.cs           |  12 +-
 Source/Core/ZDoom/ModeldefStructure.cs        |  31 ++---
 .../SoundEnvironmentMode.cs                   | 112 ++++++++++--------
 3 files changed, 88 insertions(+), 67 deletions(-)

diff --git a/Source/Core/ZDoom/ModeldefParser.cs b/Source/Core/ZDoom/ModeldefParser.cs
index cc9f5f53d..30280d58b 100644
--- a/Source/Core/ZDoom/ModeldefParser.cs
+++ b/Source/Core/ZDoom/ModeldefParser.cs
@@ -100,6 +100,7 @@ namespace CodeImp.DoomBuilder.ZDoom
 								md.SetTransform(mrotation, moffset, mds.Scale);
 
 								// Add models
+								int disabledframescount = 0;
 								foreach(var fs in mds.Frames[targetsprite])
 								{
 									// Sanity checks
@@ -108,6 +109,13 @@ namespace CodeImp.DoomBuilder.ZDoom
 										LogWarning("Model definition \"" + classname + "\", frame \"" + fs.SpriteName + " " + fs.FrameName + "\" references undefiend model index " + fs.ModelIndex);
 										continue;
 									}
+
+									//INFO: setting frame index to a negative number disables model rendering in GZDoom
+									if(fs.FrameIndex < 0)
+									{
+										disabledframescount++;
+										continue;
+									}
 									
 									// Texture name will be empty when skin path is embedded in the model
 									string texturename = (!string.IsNullOrEmpty(mds.TextureNames[fs.ModelIndex]) ? mds.TextureNames[fs.ModelIndex].ToLowerInvariant() : string.Empty);
@@ -121,7 +129,9 @@ namespace CodeImp.DoomBuilder.ZDoom
 								// More sanity checks...
 								if(md.ModelNames.Count == 0)
 								{
-									LogWarning("Model definition \"" + classname + "\" has no defined models");
+									// Show warning only when frames were not delibeartely disabled
+									if(mds.Frames[targetsprite].Count > 0 && disabledframescount < mds.Frames[targetsprite].Count)
+										LogWarning("Model definition \"" + classname + "\" has no defined models");
 								}
 								else
 								{
diff --git a/Source/Core/ZDoom/ModeldefStructure.cs b/Source/Core/ZDoom/ModeldefStructure.cs
index da09a7ba7..af5dbc678 100644
--- a/Source/Core/ZDoom/ModeldefStructure.cs
+++ b/Source/Core/ZDoom/ModeldefStructure.cs
@@ -103,18 +103,19 @@ namespace CodeImp.DoomBuilder.ZDoom
 						parser.SkipWhitespace(true);
 
 						// Model index
-						int index;
+						int index = 0;
 						token = parser.ReadToken();
-						if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out index) || index < 0) 
+						if(!parser.ReadSignedInt(token, ref index))
 						{
 							// Not numeric!
 							parser.ReportError("Expected model index, but got \"" + token + "\"");
 							return false;
 						}
 
-						if(index >= MAX_MODELS) 
+						if(index < 0 || index > MAX_MODELS - 1)
 						{
-							parser.ReportError("GZDoom doesn't allow more than " + MAX_MODELS + " models per MODELDEF entry");
+							// Out of bounds
+							parser.ReportError("Model index must be in [0.." + (MAX_MODELS - 1) + "] range");
 							return false;
 						}
 
@@ -153,18 +154,19 @@ namespace CodeImp.DoomBuilder.ZDoom
 						parser.SkipWhitespace(true);
 
 						// Skin index
-						int skinindex;
+						int skinindex = 0;
 						token = parser.ReadToken();
-						if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out skinindex) || skinindex < 0) 
+						if(!parser.ReadSignedInt(token, ref skinindex))
 						{
 							// Not numeric!
 							parser.ReportError("Expected skin index, but got \"" + token + "\"");
 							return false;
 						}
 
-						if(skinindex >= MAX_MODELS) 
+						if(skinindex < 0 || skinindex >= MAX_MODELS)
 						{
-							parser.ReportError("GZDoom doesn't allow more than " + MAX_MODELS + " skins per MODELDEF entry");
+							// Out of bounds
+							parser.ReportError("Skin index must be in [0.." + (MAX_MODELS - 1) + "] range");
 							return false;
 						}
 
@@ -333,9 +335,9 @@ namespace CodeImp.DoomBuilder.ZDoom
 
 						// Model index
 						parser.SkipWhitespace(true);
-						int fimodelindnex;
+						int fimodelindnex = 0;
 						token = parser.ReadToken();
-						if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out fimodelindnex))
+						if(!parser.ReadSignedInt(token, ref fimodelindnex))
 						{
 							// Not numeric!
 							parser.ReportError("Expected model index, but got \"" + token + "\"");
@@ -350,9 +352,10 @@ namespace CodeImp.DoomBuilder.ZDoom
 
 						// Frame number
 						parser.SkipWhitespace(true);
-						int fiframeindnex;
+						int fiframeindnex = 0;
 						token = parser.ReadToken();
-						if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out fiframeindnex) || fiframeindnex < 0)
+						//INFO: setting frame index to a negative number disables model rendering in GZDoom
+						if(!parser.ReadSignedInt(token, ref fiframeindnex))
 						{
 							// Not numeric!
 							parser.ReportError("Expected frame index, but got \"" + token + "\"");
@@ -411,9 +414,9 @@ namespace CodeImp.DoomBuilder.ZDoom
 
 						// Model index
 						parser.SkipWhitespace(true);
-						int modelindnex;
+						int modelindnex = 0;
 						token = parser.ReadToken();
-						if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out modelindnex))
+						if(!parser.ReadSignedInt(token, ref modelindnex))
 						{
 							// Not numeric!
 							parser.ReportError("Expected model index, but got \"" + token + "\"");
diff --git a/Source/Plugins/SoundPropagationMode/SoundEnvironmentMode.cs b/Source/Plugins/SoundPropagationMode/SoundEnvironmentMode.cs
index 49e575cdd..647f3d4f4 100644
--- a/Source/Plugins/SoundPropagationMode/SoundEnvironmentMode.cs
+++ b/Source/Plugins/SoundPropagationMode/SoundEnvironmentMode.cs
@@ -18,15 +18,14 @@
 #region ================== Namespaces
 
 using System;
-using System.Windows.Forms;
 using System.ComponentModel;
+using System.Windows.Forms;
 using CodeImp.DoomBuilder.Actions;
-using CodeImp.DoomBuilder.Geometry;
-using CodeImp.DoomBuilder.Windows;
+using CodeImp.DoomBuilder.Controls;
+using CodeImp.DoomBuilder.Editing;
 using CodeImp.DoomBuilder.Map;
 using CodeImp.DoomBuilder.Rendering;
-using CodeImp.DoomBuilder.Editing;
-using CodeImp.DoomBuilder.Controls;
+using CodeImp.DoomBuilder.Windows;
 
 #endregion
 
@@ -48,6 +47,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 		// Highlighted item
 		private Sector highlighted;
 		private SoundEnvironment highlightedsoundenvironment;
+		private SoundEnvironment oldhighlightedsoundenvironment; //mxd
 		private Linedef highlightedline; //mxd
 		private Thing highlightedthing; //mxd
 
@@ -236,6 +236,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 		{
 			panel.HighlightSoundEnvironment(highlightedsoundenvironment); //mxd. Expand highlighted node in the treeview
 			General.Interface.DisplayStatus(StatusType.Ready, "Finished updating sound environments");
+			General.Interface.RedrawDisplay(); //mxd
 		}
 
 		private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
@@ -285,7 +286,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 
 				// Since there will usually be way less blocking linedefs than total linedefs, it's presumably
 				// faster to draw them on their own instead of checking if each linedef is in BlockingLinedefs
-				lock (BuilderPlug.Me.BlockingLinedefs)
+				lock(BuilderPlug.Me.BlockingLinedefs)
 				{
 					foreach(Linedef ld in BuilderPlug.Me.BlockingLinedefs)
 					{
@@ -309,11 +310,20 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 				renderer.RenderThingSet(General.Map.ThingsFilter.HiddenThings, General.Settings.HiddenThingsAlpha);
 				renderer.RenderThingSet(General.Map.ThingsFilter.VisibleThings, General.Settings.InactiveThingsAlpha);
 
-				lock (BuilderPlug.Me.SoundEnvironments)
+				lock(BuilderPlug.Me.SoundEnvironments)
 				{
 					foreach(SoundEnvironment se in BuilderPlug.Me.SoundEnvironments)
 					{
-						if(se.Things.Count > 0) renderer.RenderThingSet(se.Things, General.Settings.ActiveThingsAlpha);
+						if(se.Things.Count == 0) continue;
+						if(se == highlightedsoundenvironment)
+						{
+							foreach(Thing t in se.Things)
+								renderer.RenderThing(t, General.Colors.Highlight, General.Settings.ActiveThingsAlpha);
+						}
+						else
+						{
+							renderer.RenderThingSet(se.Things, General.Settings.ActiveThingsAlpha);
+						}
 					}
 				}
 
@@ -327,7 +337,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 			// Render overlay geometry (sectors)
 			if(BuilderPlug.Me.OverlayGeometry != null)
 			{
-				lock (BuilderPlug.Me.OverlayGeometry)
+				lock(BuilderPlug.Me.OverlayGeometry)
 				{
 					if(BuilderPlug.Me.OverlayGeometry.Length > 0 && renderer.StartOverlay(true))
 					{
@@ -407,6 +417,13 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 					redrawrequired = true;
 				}
 
+				//mxd. Highlighted environment changed?
+				if(oldhighlightedsoundenvironment != highlightedsoundenvironment)
+				{
+					oldhighlightedsoundenvironment = highlightedsoundenvironment;
+					redrawrequired = true;
+				}
+
 				//mxd. Find the nearest thing within default highlight range
 				if(highlightedline == null && highlightedsoundenvironment != null)
 				{
@@ -459,21 +476,50 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 
 		// This creates a new thing at the mouse position
 		[BeginAction("insertitem", BaseAction = true)]
-		public virtual void InsertThing() 
+		public void InsertThing()
 		{
 			// Mouse in window?
 			if(mouseinside) 
 			{
-				// Insert new thing
+				// Check the boundaries
+				if(mousemappos.x < General.Map.Config.LeftBoundary || mousemappos.x > General.Map.Config.RightBoundary ||
+				   mousemappos.y > General.Map.Config.TopBoundary || mousemappos.y < General.Map.Config.BottomBoundary)
+				{
+					General.Interface.DisplayStatus(StatusType.Warning, "Failed to insert thing: outside of map boundaries.");
+					return;
+				}
+				
+				// Create undo
 				General.Map.UndoRedo.CreateUndo("Insert sound environment thing");
-				Thing t = InsertThing(mousemappos);
-
-				if(t == null) 
+				
+				// Create thing
+				Thing t = General.Map.Map.CreateThing();
+				if(t == null)
 				{
 					General.Map.UndoRedo.WithdrawUndo();
 					return;
 				}
 
+				General.Settings.ApplyDefaultThingSettings(t);
+				t.Type = BuilderPlug.SOUND_ENVIROMNEMT_THING_TYPE;
+				t.Move(mousemappos);
+				t.UpdateConfiguration();
+
+				// Update things filter so that it includes this thing
+				General.Map.ThingsFilter.Update();
+
+				// Snap to grid enabled?
+				if(General.Interface.SnapToGrid)
+				{
+					// Snap to grid
+					t.SnapToGrid();
+				}
+				else
+				{
+					// Snap to map format accuracy
+					t.SnapToAccuracy();
+				}
+
 				// Add to current sound environment
 				if(highlightedsoundenvironment != null) 
 				{
@@ -501,44 +547,6 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 			}
 		}
 
-		// This creates a new thing
-		private static Thing InsertThing(Vector2D pos) 
-		{
-			if(pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary ||
-				pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary) 
-			{
-				General.Interface.DisplayStatus(StatusType.Warning, "Failed to insert thing: outside of map boundaries.");
-				return null;
-			}
-
-			// Create thing
-			Thing t = General.Map.Map.CreateThing();
-			if(t != null) 
-			{
-				General.Settings.ApplyDefaultThingSettings(t);
-				t.Type = BuilderPlug.SOUND_ENVIROMNEMT_THING_TYPE;
-				t.Move(pos);
-				t.UpdateConfiguration();
-
-				// Update things filter so that it includes this thing
-				General.Map.ThingsFilter.Update();
-
-				// Snap to grid enabled?
-				if(General.Interface.SnapToGrid) 
-				{
-					// Snap to grid
-					t.SnapToGrid();
-				} 
-				else 
-				{
-					// Snap to map format accuracy
-					t.SnapToAccuracy();
-				}
-			}
-
-			return t;
-		}
-
 		[BeginAction("deleteitem", BaseAction = true)]
 		public void DeleteItem() 
 		{
-- 
GitLab