From e84f7d1fe83062eeef0a3aeae8bbbe8d21017485 Mon Sep 17 00:00:00 2001
From: MaxED <j.maxed@gmail.com>
Date: Tue, 24 Feb 2015 20:25:42 +0000
Subject: [PATCH] Linedefs Mode, UDMF: rewritten "Make Gradient Brightness"
 action. Fixed some logic errors, added interpolation modes support.

---
 Source/Core/Geometry/InterpolationTools.cs    |   6 +-
 .../BuilderModes/ClassicModes/LinedefsMode.cs | 174 +++++++-----------
 2 files changed, 70 insertions(+), 110 deletions(-)

diff --git a/Source/Core/Geometry/InterpolationTools.cs b/Source/Core/Geometry/InterpolationTools.cs
index 006842dc7..54d529053 100644
--- a/Source/Core/Geometry/InterpolationTools.cs
+++ b/Source/Core/Geometry/InterpolationTools.cs
@@ -29,7 +29,7 @@ namespace CodeImp.DoomBuilder.Geometry
 		//Based on Robert Penner's original easing equations (http://www.robertpenner.com/easing/)
 		public static int Linear(float val1, float val2, float delta)
 		{
-			return (int)(delta * val2 + (1.0f - delta) * val1);
+			return (int)Math.Round(delta * val2 + (1.0f - delta) * val1);
 		}
 		
 		/**
@@ -39,7 +39,7 @@ namespace CodeImp.DoomBuilder.Geometry
 		{
 			float f_val1 = val1;
 			float f_val2 = val2 - f_val1;
-			return (int)(-f_val2 * Math.Cos(delta * Angle2D.PIHALF) + f_val2 + f_val1);
+			return (int)Math.Round(-f_val2 * Math.Cos(delta * Angle2D.PIHALF) + f_val2 + f_val1);
 		}
 
 		/**
@@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.Geometry
 		 */
 		public static int EaseOutSine(float val1, float val2, float delta) 
 		{
-			return (int)((val2 - val1) * Math.Sin(delta * Angle2D.PIHALF) + val1);
+			return (int)Math.Round((val2 - val1) * Math.Sin(delta * Angle2D.PIHALF) + val1);
 		}
 
 		/**
diff --git a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs
index 5bc6cdf83..67c6a5230 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs
@@ -304,7 +304,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			General.Interface.AddButton(BuilderPlug.Me.MenusForm.PasteProperties);
 			General.Interface.AddButton(BuilderPlug.Me.MenusForm.PastePropertiesOptions); //mxd
 			General.Interface.AddButton(BuilderPlug.Me.MenusForm.SeparatorCopyPaste);
-			if(General.Map.UDMF) General.Interface.AddButton(BuilderPlug.Me.MenusForm.MakeGradientBrightness);//mxd
+			if(General.Map.UDMF) //mxd
+			{
+				General.Interface.AddButton(BuilderPlug.Me.MenusForm.MakeGradientBrightness);
+				General.Interface.AddButton(BuilderPlug.Me.MenusForm.GradientInterpolationMenu);
+			}
 			General.Interface.AddButton(BuilderPlug.Me.MenusForm.MarqueSelectTouching); //mxd
 			General.Interface.AddButton(BuilderPlug.Me.MenusForm.CurveLinedefs);
 			if(General.Map.UDMF) General.Interface.AddButton(BuilderPlug.Me.MenusForm.TextureOffsetLock, ToolbarSection.Geometry); //mxd
@@ -324,7 +328,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			General.Interface.RemoveButton(BuilderPlug.Me.MenusForm.PasteProperties);
 			General.Interface.RemoveButton(BuilderPlug.Me.MenusForm.PastePropertiesOptions); //mxd
 			General.Interface.RemoveButton(BuilderPlug.Me.MenusForm.SeparatorCopyPaste);
-			if(General.Map.UDMF) General.Interface.RemoveButton(BuilderPlug.Me.MenusForm.MakeGradientBrightness);//mxd
+			if(General.Map.UDMF) //mxd
+			{
+				General.Interface.RemoveButton(BuilderPlug.Me.MenusForm.MakeGradientBrightness);
+				General.Interface.RemoveButton(BuilderPlug.Me.MenusForm.GradientInterpolationMenu);
+			}
 			General.Interface.RemoveButton(BuilderPlug.Me.MenusForm.MarqueSelectTouching); //mxd
 			General.Interface.RemoveButton(BuilderPlug.Me.MenusForm.CurveLinedefs);
 			if(General.Map.UDMF) General.Interface.RemoveButton(BuilderPlug.Me.MenusForm.TextureOffsetLock); //mxd
@@ -1267,126 +1275,40 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			ICollection<Linedef> orderedselection = General.Map.Map.GetSelectedLinedefs(true);
 			if(orderedselection.Count > 2) 
 			{
-				General.Interface.DisplayStatus(StatusType.Action, "Created gradient brightness over selected linedefs.");
-				General.Map.UndoRedo.CreateUndo("Linedefs gradient brightness");
-
+				// Gather values
 				Linedef start = General.GetByIndex(orderedselection, 0);
 				Linedef end = General.GetByIndex(orderedselection, orderedselection.Count - 1);
 
-				const string lightKey = "light";
-				const string lightAbsKey = "lightabsolute";
-				float startbrightness = float.NaN;
-				float endbrightness = float.NaN;
+				float startbrightness = GetLinedefBrighness(start);
+				float endbrightness = GetLinedefBrighness(end);
 
-				//get total brightness of start sidedef(s)
-				if(start.Front != null) 
+				if(float.IsNaN(startbrightness))
 				{
-					if(start.Front.Fields.GetValue(lightAbsKey, false)) 
-					{
-						startbrightness = start.Front.Fields.GetValue(lightKey, 0);
-					} 
-					else 
-					{
-						startbrightness = Math.Min(255, Math.Max(0, (float)start.Front.Sector.Brightness + start.Front.Fields.GetValue(lightKey, 0)));
-					}
-				}
-
-				if(start.Back != null) 
-				{
-					float b;
-
-					if(start.Back.Fields.GetValue(lightAbsKey, false)) 
-					{
-						b = start.Back.Fields.GetValue(lightKey, 0);
-					} 
-					else 
-					{
-						b = Math.Min(255, Math.Max(0, (float)start.Back.Sector.Brightness + start.Back.Fields.GetValue(lightKey, 0)));
-					}
-
-					startbrightness = (float.IsNaN(startbrightness) ? b : (startbrightness + b) / 2);
-				}
-
-				//get total brightness of end sidedef(s)
-				if(end.Front != null) 
-				{
-					if(end.Front.Fields.GetValue(lightAbsKey, false)) 
-					{
-						endbrightness = end.Front.Fields.GetValue(lightKey, 0);
-					} 
-					else 
-					{
-						endbrightness = Math.Min(255, Math.Max(0, (float)end.Front.Sector.Brightness + end.Front.Fields.GetValue(lightKey, 0)));
-					}
+					General.Interface.DisplayStatus(StatusType.Warning, "Start linedef doesn't have visible parts!");
+					return;
 				}
 
-				if(end.Back != null) 
+				if(float.IsNaN(endbrightness)) 
 				{
-					float b;
-
-					if(end.Back.Fields.GetValue(lightAbsKey, false)) 
-					{
-						b = end.Back.Fields.GetValue(lightKey, 0);
-					} 
-					else 
-					{
-						b = Math.Min(255, Math.Max(0, (float)end.Back.Sector.Brightness + end.Back.Fields.GetValue(lightKey, 0)));
-					}
-
-					endbrightness = (float.IsNaN(endbrightness) ? b : (endbrightness + b) / 2);
+					General.Interface.DisplayStatus(StatusType.Warning, "End linedef doesn't have visible parts!");
+					return;
 				}
 
-				float delta = endbrightness - startbrightness;
+				//Make undo
+				General.Interface.DisplayStatus(StatusType.Action, "Created gradient brightness over selected linedefs.");
+				General.Map.UndoRedo.CreateUndo("Linedefs gradient brightness");
 
-				// Go for all sectors in between first and last
+				// Apply changes
+				InterpolationTools.Mode interpolationmode = (InterpolationTools.Mode)BuilderPlug.Me.MenusForm.GradientInterpolationMenu.SelectedIndex;
 				int index = 0;
+
+				// Go for all lines in between first and last
 				foreach(Linedef l in orderedselection) 
 				{
 					float u = index / (float)(orderedselection.Count - 1);
-					float b = startbrightness + delta * u;
-
-					if(l.Front != null) 
-					{
-						l.Front.Fields.BeforeFieldsChange();
-
-						//absolute flag set?
-						if(l.Front.Fields.GetValue(lightAbsKey, false)) 
-						{
-							if(l.Front.Fields.ContainsKey(lightKey))
-								l.Front.Fields[lightKey].Value = (int)b;
-							else
-								l.Front.Fields.Add(lightKey, new UniValue(UniversalType.Integer, (int)b));
-						} 
-						else 
-						{
-							if(l.Front.Fields.ContainsKey(lightKey))
-								l.Front.Fields[lightKey].Value = (int)b - l.Front.Sector.Brightness;
-							else
-								l.Front.Fields.Add(lightKey, new UniValue(UniversalType.Integer, (int)b - l.Front.Sector.Brightness));
-						}
-					}
-
-					if(l.Back != null) 
-					{
-						l.Back.Fields.BeforeFieldsChange();
-
-						//absolute flag set?
-						if(l.Back.Fields.GetValue(lightAbsKey, false)) 
-						{
-							if(l.Back.Fields.ContainsKey(lightKey))
-								l.Back.Fields[lightKey].Value = (int)b;
-							else
-								l.Back.Fields.Add(lightKey, new UniValue(UniversalType.Integer, (int)b));
-						} 
-						else 
-						{
-							if(l.Back.Fields.ContainsKey(lightKey))
-								l.Back.Fields[lightKey].Value = (int)b - l.Back.Sector.Brightness;
-							else
-								l.Back.Fields.Add(lightKey, new UniValue(UniversalType.Integer, (int)b - l.Back.Sector.Brightness));
-						}
-					}
-
+					int b = InterpolationTools.Interpolate(startbrightness, endbrightness, u, interpolationmode);
+					if(SidedefHasVisibleParts(l.Front)) ApplySidedefBrighness(l.Front, b);
+					if(SidedefHasVisibleParts(l.Back)) ApplySidedefBrighness(l.Back, b);
 					index++;
 				}
 
@@ -1402,6 +1324,44 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			}
 		}
 
+		//mxd. gradientbrightness utility
+		private static bool SidedefHasVisibleParts(Sidedef side) 
+		{
+			if(side == null || side.Sector == null) return false;
+			return side.HighRequired() || side.LowRequired() || (side.MiddleRequired() || (side.Other != null && side.MiddleTexture != "-"));
+		}
+
+		//mxd. gradientbrightness utility
+		private static float GetLinedefBrighness(Linedef line) 
+		{
+			float frontbrightness = (SidedefHasVisibleParts(line.Front) ? GetSidedefBrighness(line.Front) : float.NaN);
+			float backbrightness = (SidedefHasVisibleParts(line.Back) ? GetSidedefBrighness(line.Back) : float.NaN);
+
+			if(float.IsNaN(frontbrightness) && float.IsNaN(backbrightness)) return float.NaN;
+			if(float.IsNaN(frontbrightness)) return backbrightness;
+			if(float.IsNaN(backbrightness)) return frontbrightness;
+			return (frontbrightness + backbrightness) / 2;
+		}
+
+		//mxd. gradientbrightness utility
+		private static float GetSidedefBrighness(Sidedef side) 
+		{
+			if(side.Fields.GetValue("lightabsolute", false)) return side.Fields.GetValue("light", 0);
+			return Math.Min(255, Math.Max(0, (float)side.Sector.Brightness + side.Fields.GetValue("light", 0)));
+		}
+
+		//mxd. gradientbrightness utility
+		private static void ApplySidedefBrighness(Sidedef side, int brightness) 
+		{
+			side.Fields.BeforeFieldsChange();
+
+			//absolute flag set?
+			if(side.Fields.GetValue("lightabsolute", false))
+				side.Fields["light"].Value = brightness;
+			else
+				UDMFTools.SetInteger(side.Fields, "light", brightness - side.Sector.Brightness, 0);
+		}
+
 		[BeginAction("placethings")] //mxd
 		public void PlaceThings() 
 		{
-- 
GitLab