From 29d11b170ed293cdc5e00ad3f47d092da3ba4eea Mon Sep 17 00:00:00 2001
From: MaxED <j.maxed@gmail.com>
Date: Tue, 16 Apr 2013 12:52:40 +0000
Subject: [PATCH] Plane Copy effect (118) is now shown in Visual mode. UDMF:
 Reset texture offsets action now works on floors and ceilings. Vertices mode:
 when a linedef is within Split Linedefs range, it's now highlighted using
 Info line color.

---
 .../Plugins/BuilderModes/BuilderModes.csproj  |  1 +
 .../BuilderModes/ClassicModes/VerticesMode.cs | 29 ++++++
 .../Interface/MenusForm.Designer.cs           | 88 ++++++++---------
 .../VisualModes/BaseVisualMode.cs             | 34 +++++++
 .../VisualModes/EffectPlaneCopySlope.cs       | 96 +++++++++++++++++++
 .../BuilderModes/VisualModes/SectorData.cs    |  6 ++
 .../BuilderModes/VisualModes/VisualCeiling.cs | 20 ++++
 .../BuilderModes/VisualModes/VisualFloor.cs   | 21 ++++
 8 files changed, 251 insertions(+), 44 deletions(-)
 create mode 100644 Source/Plugins/BuilderModes/VisualModes/EffectPlaneCopySlope.cs

diff --git a/Source/Plugins/BuilderModes/BuilderModes.csproj b/Source/Plugins/BuilderModes/BuilderModes.csproj
index 210d4f8db..d69f2bf64 100644
--- a/Source/Plugins/BuilderModes/BuilderModes.csproj
+++ b/Source/Plugins/BuilderModes/BuilderModes.csproj
@@ -300,6 +300,7 @@
     <Compile Include="VisualModes\EffectBrightnessLevel.cs" />
     <Compile Include="VisualModes\EffectCopySlope.cs" />
     <Compile Include="VisualModes\EffectLineSlope.cs" />
+    <Compile Include="VisualModes\EffectPlaneCopySlope.cs" />
     <Compile Include="VisualModes\EffectThingLineSlope.cs" />
     <Compile Include="VisualModes\EffectThingVertexSlope.cs" />
     <Compile Include="VisualModes\EffectUDMFVertexOffset.cs" />
diff --git a/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs b/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs
index fb71aae3b..f95e33039 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs
@@ -49,6 +49,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		// Highlighted item
 		protected Vertex highlighted;
+		private Linedef highlightedLine;
 
 		// Interface
 		private bool editpressed;
@@ -191,6 +192,27 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			else
 				General.Interface.HideInfo();
 		}
+
+		//mxd
+		private void HighlightLine(Linedef l) {
+			// Update display
+			if(renderer.StartPlotter(false)) {
+				// Undraw previous highlight
+				if((highlightedLine != null) && !highlightedLine.IsDisposed)
+					renderer.PlotLinedef(highlightedLine, renderer.DetermineLinedefColor(highlightedLine));
+
+				// Set new highlight
+				highlightedLine = l;
+
+				// Render highlighted item
+				if((highlightedLine != null) && !highlightedLine.IsDisposed)
+					renderer.PlotLinedef(highlightedLine, General.Colors.InfoLine);
+
+				// Done
+				renderer.Finish();
+				renderer.Present();
+			}
+		}
 		
 		// Selection
 		protected override void OnSelectBegin()
@@ -426,6 +448,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 				// Highlight if not the same
 				if(v != highlighted) Highlight(v);
+
+				//mxd
+				// Find the nearest linedef within split linedefs range
+				Linedef l = General.Map.Map.NearestLinedefRange(mousemappos, BuilderPlug.Me.SplitLinedefsRange / renderer.Scale);
+
+				// Highlight if not the same
+				if(l != highlightedLine) HighlightLine(l);
 			} 
 		}
 
diff --git a/Source/Plugins/BuilderModes/Interface/MenusForm.Designer.cs b/Source/Plugins/BuilderModes/Interface/MenusForm.Designer.cs
index cef5b245d..365dcd3bf 100644
--- a/Source/Plugins/BuilderModes/Interface/MenusForm.Designer.cs
+++ b/Source/Plugins/BuilderModes/Interface/MenusForm.Designer.cs
@@ -44,25 +44,25 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			this.mergesectorsitem = new System.Windows.Forms.ToolStripMenuItem();
 			this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
 			this.thingsmenu = new System.Windows.Forms.ToolStripMenuItem();
+			this.alignToWallItem = new System.Windows.Forms.ToolStripMenuItem();
+			this.pointAtCursorItem = new System.Windows.Forms.ToolStripMenuItem();
 			this.globalstrip = new System.Windows.Forms.ToolStrip();
 			this.manualstrip = new System.Windows.Forms.ToolStrip();
-			this.seperatorcopypaste = new System.Windows.Forms.ToolStripSeparator();
-			this.separatorsectors1 = new System.Windows.Forms.ToolStripSeparator();
-			this.brightnessGradientMode = new System.Windows.Forms.ToolStripComboBox();
 			this.buttoncopyproperties = new System.Windows.Forms.ToolStripButton();
 			this.buttonpasteproperties = new System.Windows.Forms.ToolStripButton();
+			this.seperatorcopypaste = new System.Windows.Forms.ToolStripSeparator();
 			this.buttonselectionnumbers = new System.Windows.Forms.ToolStripButton();
+			this.separatorsectors1 = new System.Windows.Forms.ToolStripSeparator();
 			this.buttonbrightnessgradient = new System.Windows.Forms.ToolStripButton();
 			this.buttonfloorgradient = new System.Windows.Forms.ToolStripButton();
 			this.buttonceilinggradient = new System.Windows.Forms.ToolStripButton();
 			this.buttonflipselectionh = new System.Windows.Forms.ToolStripButton();
 			this.buttonflipselectionv = new System.Windows.Forms.ToolStripButton();
 			this.buttoncurvelinedefs = new System.Windows.Forms.ToolStripButton();
+			this.brightnessGradientMode = new System.Windows.Forms.ToolStripComboBox();
 			this.buttonMarqueSelectTouching = new System.Windows.Forms.ToolStripButton();
 			this.buttonAlignThingsToWall = new System.Windows.Forms.ToolStripButton();
 			this.buttonTextureOffsetLock = new System.Windows.Forms.ToolStripButton();
-			this.alignToWallItem = new System.Windows.Forms.ToolStripMenuItem();
-			this.pointAtCursorItem = new System.Windows.Forms.ToolStripMenuItem();
 			this.menustrip.SuspendLayout();
 			this.manualstrip.SuspendLayout();
 			this.SuspendLayout();
@@ -201,6 +201,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			this.thingsmenu.Text = "Things";
 			this.thingsmenu.Visible = false;
 			// 
+			// alignToWallItem
+			// 
+			this.alignToWallItem.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.AlignThings;
+			this.alignToWallItem.Name = "alignToWallItem";
+			this.alignToWallItem.Size = new System.Drawing.Size(202, 22);
+			this.alignToWallItem.Tag = "thingaligntowall";
+			this.alignToWallItem.Text = "&Align To Closest Linedef";
+			this.alignToWallItem.Click += new System.EventHandler(this.InvokeTaggedAction);
+			// 
+			// pointAtCursorItem
+			// 
+			this.pointAtCursorItem.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.ThingPointAtCursor;
+			this.pointAtCursorItem.Name = "pointAtCursorItem";
+			this.pointAtCursorItem.Size = new System.Drawing.Size(202, 22);
+			this.pointAtCursorItem.Tag = "thinglookatcursor";
+			this.pointAtCursorItem.Text = "&Point at Cursor";
+			this.pointAtCursorItem.Click += new System.EventHandler(this.InvokeTaggedAction);
+			// 
 			// globalstrip
 			// 
 			this.globalstrip.Location = new System.Drawing.Point(0, 24);
@@ -233,25 +251,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			this.manualstrip.TabIndex = 2;
 			this.manualstrip.Text = "toolStrip1";
 			// 
-			// seperatorcopypaste
-			// 
-			this.seperatorcopypaste.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
-			this.seperatorcopypaste.Name = "seperatorcopypaste";
-			this.seperatorcopypaste.Size = new System.Drawing.Size(6, 25);
-			// 
-			// separatorsectors1
-			// 
-			this.separatorsectors1.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
-			this.separatorsectors1.Name = "separatorsectors1";
-			this.separatorsectors1.Size = new System.Drawing.Size(6, 25);
-			// 
-			// brightnessGradientMode
-			// 
-			this.brightnessGradientMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-			this.brightnessGradientMode.Name = "brightnessGradientMode";
-			this.brightnessGradientMode.Size = new System.Drawing.Size(75, 25);
-			this.brightnessGradientMode.ToolTipText = "Brightness Gradient affects:";
-			// 
 			// buttoncopyproperties
 			// 
 			this.buttoncopyproperties.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
@@ -274,6 +273,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			this.buttonpasteproperties.Text = "Paste Properties";
 			this.buttonpasteproperties.Click += new System.EventHandler(this.InvokeTaggedAction);
 			// 
+			// seperatorcopypaste
+			// 
+			this.seperatorcopypaste.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
+			this.seperatorcopypaste.Name = "seperatorcopypaste";
+			this.seperatorcopypaste.Size = new System.Drawing.Size(6, 25);
+			// 
 			// buttonselectionnumbers
 			// 
 			this.buttonselectionnumbers.CheckOnClick = true;
@@ -285,6 +290,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			this.buttonselectionnumbers.Text = "View Selection Numbering";
 			this.buttonselectionnumbers.Click += new System.EventHandler(this.buttonselectionnumbers_Click);
 			// 
+			// separatorsectors1
+			// 
+			this.separatorsectors1.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
+			this.separatorsectors1.Name = "separatorsectors1";
+			this.separatorsectors1.Size = new System.Drawing.Size(6, 25);
+			// 
 			// buttonbrightnessgradient
 			// 
 			this.buttonbrightnessgradient.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
@@ -352,6 +363,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			this.buttoncurvelinedefs.Text = "Curve Linedefs";
 			this.buttoncurvelinedefs.Click += new System.EventHandler(this.InvokeTaggedAction);
 			// 
+			// brightnessGradientMode
+			// 
+			this.brightnessGradientMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.brightnessGradientMode.Name = "brightnessGradientMode";
+			this.brightnessGradientMode.Size = new System.Drawing.Size(75, 25);
+			this.brightnessGradientMode.ToolTipText = "Brightness Gradient affects:";
+			// 
 			// buttonMarqueSelectTouching
 			// 
 			this.buttonMarqueSelectTouching.CheckOnClick = true;
@@ -384,28 +402,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			this.buttonTextureOffsetLock.ImageTransparentColor = System.Drawing.Color.Magenta;
 			this.buttonTextureOffsetLock.Name = "buttonTextureOffsetLock";
 			this.buttonTextureOffsetLock.Size = new System.Drawing.Size(23, 22);
-			this.buttonTextureOffsetLock.ToolTipText = "When enabled, keeps floor and ceiling texture offsets\r\nconstant while sector is d" +
-				"ragged\r\n";
+			this.buttonTextureOffsetLock.ToolTipText = "Pin Texture Offsets.\r\nWhen enabled, keeps floor and ceiling texture offsets\r\ncons" +
+				"tant while sector is dragged\r\n";
 			this.buttonTextureOffsetLock.Click += new System.EventHandler(this.buttonTextureOffsetLock_Click);
 			// 
-			// alignToWallItem
-			// 
-			this.alignToWallItem.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.AlignThings;
-			this.alignToWallItem.Name = "alignToWallItem";
-			this.alignToWallItem.Size = new System.Drawing.Size(202, 22);
-			this.alignToWallItem.Tag = "thingaligntowall";
-			this.alignToWallItem.Text = "&Align To Closest Linedef";
-			this.alignToWallItem.Click += new System.EventHandler(this.InvokeTaggedAction);
-			// 
-			// pointAtCursorItem
-			// 
-			this.pointAtCursorItem.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.ThingPointAtCursor;
-			this.pointAtCursorItem.Name = "pointAtCursorItem";
-			this.pointAtCursorItem.Size = new System.Drawing.Size(202, 22);
-			this.pointAtCursorItem.Tag = "thinglookatcursor";
-			this.pointAtCursorItem.Text = "&Point at Cursor";
-			this.pointAtCursorItem.Click += new System.EventHandler(this.InvokeTaggedAction);
-			// 
 			// MenusForm
 			// 
 			this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
index 32e53d7a3..125472f86 100644
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
@@ -739,6 +739,40 @@ namespace CodeImp.DoomBuilder.BuilderModes
 						sd.AddEffectLineSlope(l);
 					}
 				}
+				// ========== Plane Copy (mxd) (see http://zdoom.org/wiki/Plane_Copy) ==========
+				else if(l.Action == 118)
+				{
+					//check sodding flags...
+					bool floorCopyToBack = false;
+					bool floorCopyToFront = false;
+					bool ceilingCopyToBack = false;
+					bool ceilingCopyToFront = false;
+
+					if(l.Args[4] > 0 && l.Args[4] != 3 && l.Args[4] != 12) {
+						floorCopyToBack = (l.Args[4] & 1) == 1;
+						floorCopyToFront = (l.Args[4] & 2) == 2;
+						ceilingCopyToBack = (l.Args[4] & 4) == 4;
+						ceilingCopyToFront = (l.Args[4] & 8) == 8;
+					}
+					
+					// Copy slope to front sector
+					//Flags: Back floor to front sector or Back ceiling to front sector
+					if(l.Front != null) {
+						if((l.Args[0] > 0 || l.Args[1] > 0) || (floorCopyToFront && l.Args[2] > 0) || (ceilingCopyToFront && l.Args[3] > 0)) {
+							SectorData sd = GetSectorData(l.Front.Sector);
+							sd.AddEffectPlaneClopySlope(l, true);
+						}
+					}
+
+					// Copy slope to back sector
+					//Flags: Copy front floor to back sector or Front ceiling to back sector
+					if(l.Back != null) {
+						if((l.Args[2] > 0 || l.Args[3] > 0) || (floorCopyToBack && l.Args[0] > 0) || (ceilingCopyToBack && l.Args[1] > 0)) {
+							SectorData sd = GetSectorData(l.Back.Sector);
+							sd.AddEffectPlaneClopySlope(l, false);
+						}
+					}
+				}
 				// ========== Sector 3D floor (see http://zdoom.org/wiki/Sector_Set3dFloor) ==========
 				else if((l.Action == 160) && (l.Front != null))
 				{
diff --git a/Source/Plugins/BuilderModes/VisualModes/EffectPlaneCopySlope.cs b/Source/Plugins/BuilderModes/VisualModes/EffectPlaneCopySlope.cs
new file mode 100644
index 000000000..06b33415f
--- /dev/null
+++ b/Source/Plugins/BuilderModes/VisualModes/EffectPlaneCopySlope.cs
@@ -0,0 +1,96 @@
+using CodeImp.DoomBuilder.Map;
+
+namespace CodeImp.DoomBuilder.BuilderModes
+{
+	internal class EffectPlaneCopySlope : SectorEffect
+	{
+		// Linedef that is used to create this effect
+		private Linedef linedef;
+		private bool isFront;
+
+		public EffectPlaneCopySlope(SectorData data, Linedef sourcelinedef, bool front)	: base(data) {
+			linedef = sourcelinedef;
+			isFront = front;
+
+			// New effect added: This sector needs an update!
+			if(data.Mode.VisualSectorExists(data.Sector)) {
+				BaseVisualSector vs = (BaseVisualSector)data.Mode.GetVisualSector(data.Sector);
+				vs.UpdateSectorGeometry(true);
+			}
+		}
+		
+		// This makes sure we are updated with the source linedef information
+		public override void Update() {
+			Sector sourcesector = null;
+			SectorData sourcesectordata = null;
+
+			//check flags
+			bool floorCopyToBack = false;
+			bool floorCopyToFront = false;
+			bool ceilingCopyToBack = false;
+			bool ceilingCopyToFront = false;
+
+			if(linedef.Args[4] > 0 && linedef.Args[4] != 3 && linedef.Args[4] != 12) {
+				floorCopyToBack = linedef.Args[0] > 0 && (linedef.Args[4] & 1) == 1;
+				floorCopyToFront = linedef.Args[2] > 0 && (linedef.Args[4] & 2) == 2;
+				ceilingCopyToBack = linedef.Args[1] > 0 && (linedef.Args[4] & 4) == 4;
+				ceilingCopyToFront = linedef.Args[3] > 0 && (linedef.Args[4] & 8) == 8;
+			}
+
+			//check which arguments we must use
+			int floorArg = -1;
+			int ceilingArg = -1;
+
+			if(isFront) {
+				floorArg = floorCopyToFront ? 2 : 0;
+				ceilingArg = ceilingCopyToFront ? 3 : 1;
+			} else {
+				floorArg = floorCopyToBack ? 0 : 2;
+				ceilingArg = ceilingCopyToBack ? 1 : 3;
+			}
+
+			//find sector to align floor to
+			if(linedef.Args[floorArg] > 0) {
+				foreach(Sector s in General.Map.Map.Sectors) {
+					if(s.Tag == linedef.Args[floorArg]) {
+						sourcesector = s;
+						break;
+					}
+				}
+
+				if(sourcesector != null) {
+					sourcesectordata = data.Mode.GetSectorData(sourcesector);
+					if(!sourcesectordata.Updated) sourcesectordata.Update();
+
+					data.Floor.plane = sourcesectordata.Floor.plane;
+					sourcesectordata.AddUpdateSector(data.Sector, true);
+				}
+			}
+
+			if(linedef.Args[ceilingArg] > 0) {
+				//find sector to align ceiling to
+				if(linedef.Args[ceilingArg] != linedef.Args[floorArg]) {
+					sourcesector = null;
+
+					foreach(Sector s in General.Map.Map.Sectors) {
+						if(s.Tag == linedef.Args[ceilingArg]) {
+							sourcesector = s;
+							break;
+						}
+					}
+
+					if(sourcesector != null) {
+						sourcesectordata = data.Mode.GetSectorData(sourcesector);
+						if(!sourcesectordata.Updated) sourcesectordata.Update();
+
+						data.Floor.plane = sourcesectordata.Floor.plane;
+						sourcesectordata.AddUpdateSector(data.Sector, true);
+					}
+
+				} else if(sourcesector != null) { //ceiling uses the same sector as floor 
+					data.Ceiling.plane = sourcesectordata.Ceiling.plane;
+				}
+			}
+		}
+	}
+}
diff --git a/Source/Plugins/BuilderModes/VisualModes/SectorData.cs b/Source/Plugins/BuilderModes/VisualModes/SectorData.cs
index 287ed7411..38b2791a8 100644
--- a/Source/Plugins/BuilderModes/VisualModes/SectorData.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/SectorData.cs
@@ -114,6 +114,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			alleffects.Add(e);
 		}
 
+		//mxd. Plane copy slope effect
+		public void AddEffectPlaneClopySlope(Linedef sourcelinedef, bool front) {
+			EffectPlaneCopySlope e = new EffectPlaneCopySlope(this, sourcelinedef, front);
+			alleffects.Add(e);
+		}
+
 		// Copy slope effect
 		public void AddEffectCopySlope(Thing sourcething)
 		{
diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs b/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs
index 91e89bf82..49684fde8 100644
--- a/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs
@@ -185,6 +185,26 @@ namespace CodeImp.DoomBuilder.BuilderModes
             s.UpdateNeeded = true;
 		}
 
+		//mxd
+		public override void OnResetTextureOffset() {
+			if(!General.Map.UDMF) return;
+
+			mode.CreateUndo("Reset texture offsets");
+			mode.SetActionResult("Texture offsets reset.");
+
+			if(Sector.Sector.Fields.ContainsKey("xpanningceiling")) {
+				Sector.Sector.Fields.Remove("xpanningceiling");
+				Sector.Sector.UpdateNeeded = true;
+			}
+			if(Sector.Sector.Fields.ContainsKey("ypanningceiling")) {
+				Sector.Sector.Fields.Remove("ypanningceiling");
+				Sector.Sector.UpdateNeeded = true;
+			}
+
+			if(Sector.Sector.UpdateNeeded)
+				Sector.UpdateSectorGeometry(false);
+		}
+
 		// Paste texture
 		public override void OnPasteTexture()
 		{
diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs b/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs
index b8d75f2f0..ed0083ca2 100644
--- a/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs
@@ -183,6 +183,27 @@ namespace CodeImp.DoomBuilder.BuilderModes
             s.Fields["ypanningfloor"] = new UniValue(UniversalType.Float, oldy + (float)xy.Y);
             s.UpdateNeeded = true;
 		}
+
+		//mxd
+		public override void OnResetTextureOffset() {
+			if(!General.Map.UDMF) return;
+
+			mode.CreateUndo("Reset texture offsets");
+			mode.SetActionResult("Texture offsets reset.");
+			Sector.Sector.Fields.BeforeFieldsChange();
+
+			if(Sector.Sector.Fields.ContainsKey("xpanningfloor")) {
+				Sector.Sector.Fields.Remove("xpanningfloor");
+				Sector.Sector.UpdateNeeded = true;
+			}
+			if(Sector.Sector.Fields.ContainsKey("ypanningfloor")) {
+				Sector.Sector.Fields.Remove("ypanningfloor");
+				Sector.Sector.UpdateNeeded = true;
+			}
+
+			if(Sector.Sector.UpdateNeeded)
+				Sector.UpdateSectorGeometry(false);
+		}
 		
 		// Paste texture
 		public override void OnPasteTexture()
-- 
GitLab