From 4fbcc114189c0464472f310d801ad8c05c97dfe8 Mon Sep 17 00:00:00 2001 From: biwa <6475593+biwa@users.noreply.github.com> Date: Sat, 13 Jun 2020 00:24:24 +0200 Subject: [PATCH] Added functionality to duplicate 3D floor control sectors of selected sectors and paste selected sectors with the new control sectors assigned --- Source/Core/Editing/CopyPasteManager.cs | 4 +- .../Plugins/3DFloorMode/Resources/Actions.cfg | 10 ++ Source/Plugins/3DFloorMode/ThreeDFloor.cs | 13 +- Source/Plugins/3DFloorMode/ThreeDFloorMode.cs | 117 +++++++++++++++++- .../ClassicModes/BaseClassicMode.cs | 1 + .../ClassicModes/EditSelectionMode.cs | 14 ++- 6 files changed, 150 insertions(+), 9 deletions(-) diff --git a/Source/Core/Editing/CopyPasteManager.cs b/Source/Core/Editing/CopyPasteManager.cs index 6274d4b20..665d03a53 100755 --- a/Source/Core/Editing/CopyPasteManager.cs +++ b/Source/Core/Editing/CopyPasteManager.cs @@ -225,7 +225,7 @@ namespace CodeImp.DoomBuilder.Editing } // This performs the copy. Returns false when copy was cancelled. - private static bool DoCopySelection(string desc) + public static bool DoCopySelection(string desc) { // Check if possible to copy/paste if(General.Editing.Mode.Attributes.AllowCopyPaste) @@ -285,7 +285,7 @@ namespace CodeImp.DoomBuilder.Editing } // This performs the paste. Returns false when paste was cancelled. - private static void DoPasteSelection(PasteOptions options) + public static void DoPasteSelection(PasteOptions options) { // Check if possible to copy/paste if(General.Editing.Mode.Attributes.AllowCopyPaste) diff --git a/Source/Plugins/3DFloorMode/Resources/Actions.cfg b/Source/Plugins/3DFloorMode/Resources/Actions.cfg index 75eb71270..1529ef290 100644 --- a/Source/Plugins/3DFloorMode/Resources/Actions.cfg +++ b/Source/Plugins/3DFloorMode/Resources/Actions.cfg @@ -155,4 +155,14 @@ select3dfloorcontrolsector allowkeys = true; allowmouse = true; allowscroll = true; +} + +duplicate3dfloorgeometry +{ + title = "Duplicate and paste geometry"; + category = "threedfloorplugin"; + description = "Duplicates and pastes selected geometry and its 3D floors"; + allowkeys = true; + allowmouse = true; + allowscroll = true; } \ No newline at end of file diff --git a/Source/Plugins/3DFloorMode/ThreeDFloor.cs b/Source/Plugins/3DFloorMode/ThreeDFloor.cs index 61cd17296..9e622f7e2 100644 --- a/Source/Plugins/3DFloorMode/ThreeDFloor.cs +++ b/Source/Plugins/3DFloorMode/ThreeDFloor.cs @@ -218,6 +218,13 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode } public bool CreateGeometry(List<int> tagblacklist) + { + int newtag; + + return CreateGeometry(tagblacklist, false, out newtag); + } + + public bool CreateGeometry(List<int> tagblacklist, bool forcenewtag, out int newtag) { List<DrawnVertex> drawnvertices = new List<DrawnVertex>(); List<Vertex> vertices = new List<Vertex>(); @@ -225,6 +232,8 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode Vector3D slopebottomthingpos = new Vector3D(0, 0, 0); Line2D slopeline = new Line2D(0, 0, 0, 0); + newtag = -1; + drawnvertices = BuilderPlug.Me.ControlSectorArea.GetNewControlSectorVertices(); if (Tools.DrawLines(drawnvertices) == false) @@ -257,9 +266,9 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode // With multiple tag support in UDMF only one tag is needed, so bind it right away if (General.Map.UDMF == true) { - if (isnew) + if (isnew || forcenewtag) { - udmftag = BuilderPlug.Me.ControlSectorArea.GetNewSectorTag(tagblacklist); + newtag = udmftag = BuilderPlug.Me.ControlSectorArea.GetNewSectorTag(tagblacklist); tagblacklist.Add(udmftag); } diff --git a/Source/Plugins/3DFloorMode/ThreeDFloorMode.cs b/Source/Plugins/3DFloorMode/ThreeDFloorMode.cs index 3813e3ebd..a620029a4 100644 --- a/Source/Plugins/3DFloorMode/ThreeDFloorMode.cs +++ b/Source/Plugins/3DFloorMode/ThreeDFloorMode.cs @@ -40,6 +40,7 @@ using CodeImp.DoomBuilder.Types; using CodeImp.DoomBuilder.BuilderModes; using CodeImp.DoomBuilder.BuilderModes.Interface; using CodeImp.DoomBuilder.Controls; +using CodeImp.DoomBuilder.Config; // using CodeImp.DoomBuilder.GZBuilder.Geometry; #endregion @@ -1176,7 +1177,29 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode SelectSector(highlighted, true, true); } - return base.OnCopyBegin(); + General.Map.Map.MarkAllSelectedGeometry(true, false, true, true, false); + + return General.Map.Map.GetMarkedSectors(true).Count > 0; + } + + public override bool OnPasteBegin(PasteOptions options) + { + return true; + } + + // This is called when something was pasted. + public override void OnPasteEnd(PasteOptions options) + { + General.Map.Map.ClearAllSelected(); + General.Map.Map.SelectMarkedGeometry(true, true); + General.Map.Renderer2D.UpdateExtraFloorFlag(); //mxd + + // Switch to EditSelectionMode + EditSelectionMode editmode = new EditSelectionMode(); + editmode.Pasting = true; + editmode.UpdateSlopes = true; + editmode.PasteOptions = options; + General.Editing.ChangeMode(editmode); } // When undo is used @@ -1460,6 +1483,98 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode General.Interface.DisplayStatus(StatusType.Info, String.Format("3D floor control sector selected. {0} sector(s) selected.", General.Map.Map.GetSelectedSectors(true).Count)); } + [BeginAction("duplicate3dfloorgeometry")] + public void Duplicate3DFloorGeometry() + { + List<Sector> selectedsectors; + List<ThreeDFloor> duplicatethreedfloors; + Dictionary<int, int> tagreplacements = new Dictionary<int, int>(); + List<int> tagblacklist = new List<int>(); + + // No selection made? But we have a highlight! + if ((General.Map.Map.GetSelectedSectors(true).Count == 0) && (highlighted != null)) + { + // Make the highlight the selection + SelectSector(highlighted, true, true); + } + + selectedsectors = General.Map.Map.GetSelectedSectors(true).ToList(); + + // Get the 3D floors we need to duplicate + duplicatethreedfloors = BuilderPlug.GetThreeDFloors(selectedsectors); + + // Create a list of all tags used by the control sectors. This is necessary so that + // tags that will be assigned to not yet existing geometry will not be used + foreach (ThreeDFloor tdf in threedfloors) + foreach (int tag in tdf.Tags) + if (!tagblacklist.Contains(tag)) + tagblacklist.Add(tag); + + if (duplicatethreedfloors.Count == 0) + return; + + General.Map.UndoRedo.CreateUndo("Duplicate 3D floor control sectors before pasting"); + + // Create a new control sector for each 3D floor that needs to be duplicated. Force it to generate + // a new tag, and store the old (current) and new tag + foreach (ThreeDFloor tdf in duplicatethreedfloors) + { + int newtag; + int oldtag = tdf.UDMFTag; + + if(tdf.CreateGeometry(new List<int>(), true, out newtag)) + { + tagreplacements[oldtag] = newtag; + } + else + { + General.Interface.DisplayStatus(StatusType.Warning, "Could not create 3D floor control sector geometry"); + General.Map.UndoRedo.WithdrawUndo(); + return; + } + } + + // Replace the old tags of the selected sectors with the new tags + foreach (Sector s in selectedsectors) + { + foreach (int oldtag in tagreplacements.Keys) + { + if (s.Tags.Contains(oldtag)) + { + s.Tags.Remove(oldtag); + s.Tags.Add(tagreplacements[oldtag]); + } + } + } + + // Store the selected sectors (with the new tags) in the clipboard + if(!CopyPasteManager.DoCopySelection("3D floor test copy!")) + { + General.Interface.DisplayStatus(StatusType.Warning, "Something failed trying to copy the selection"); + General.Map.UndoRedo.WithdrawUndo(); + return; + } + + // Now set the tags of the selected sectors back to the old tags + foreach(Sector s in selectedsectors) + { + foreach(int oldtag in tagreplacements.Keys) + { + if(s.Tags.Contains(tagreplacements[oldtag])) + { + s.Tags.Remove(tagreplacements[oldtag]); + s.Tags.Add(oldtag); + } + } + } + + // For this operation we have to make sure the tags and actions are not changed, no matter + // what the user preference is, otherwise it will not work + PasteOptions po = new PasteOptions() { ChangeTags = 0, RemoveActions = false }; + + CopyPasteManager.DoPasteSelection(po); + } + #endregion } } diff --git a/Source/Plugins/BuilderModes/ClassicModes/BaseClassicMode.cs b/Source/Plugins/BuilderModes/ClassicModes/BaseClassicMode.cs index cd3849336..85d866c2b 100755 --- a/Source/Plugins/BuilderModes/ClassicModes/BaseClassicMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/BaseClassicMode.cs @@ -100,6 +100,7 @@ namespace CodeImp.DoomBuilder.BuilderModes // Switch to EditSelectionMode EditSelectionMode editmode = new EditSelectionMode(); editmode.Pasting = true; + editmode.UpdateSlopes = false; editmode.PasteOptions = options; General.Editing.ChangeMode(editmode); } diff --git a/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs b/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs index b65bdcf2d..4127904c3 100755 --- a/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs @@ -212,7 +212,9 @@ namespace CodeImp.DoomBuilder.BuilderModes // Options private bool snaptogrid; // SHIFT to toggle - private bool snaptonearest; // CTRL to enable + private bool snaptonearest; // CTRL to enable + + private bool updateslopes; #endregion @@ -222,6 +224,8 @@ namespace CodeImp.DoomBuilder.BuilderModes public bool Pasting { get { return pasting; } set { pasting = value; } } public PasteOptions PasteOptions { get { return pasteoptions; } set { pasteoptions = value.Copy(); } } + + public bool UpdateSlopes { get { return updateslopes; } set { updateslopes = value; } } //mxd. Modification internal bool UsePrecisePosition { get { return usepreciseposition; } set { usepreciseposition = value; } } @@ -246,6 +250,7 @@ namespace CodeImp.DoomBuilder.BuilderModes { // Initialize mode = ModifyMode.None; + updateslopes = true; } //mxd. Another constructor. Used indirectly from ImportObjAsTerrainMode.OnAccept. @@ -254,6 +259,7 @@ namespace CodeImp.DoomBuilder.BuilderModes // Initialize this.pasting = pasting; this.mode = ModifyMode.None; + this.updateslopes = true; } // Disposer @@ -1591,7 +1597,7 @@ namespace CodeImp.DoomBuilder.BuilderModes // Create cache of 3D floor control sectors that reference the selected sectors. Only do it if not pasting, since the slopes // will only be updated when not pasting, since it'd otherwise screw up the original slopes - if (!pasting) + if (updateslopes) { foreach (Linedef ld in General.Map.Map.Linedefs) { @@ -1646,7 +1652,7 @@ namespace CodeImp.DoomBuilder.BuilderModes } // Update the slopes of 3D floor control sectors. Only do it if not pasting, since it'd otherwise screw up the original slopes - if (!pasting && controlsectors.ContainsKey(s)) + if (updateslopes && controlsectors.ContainsKey(s)) { foreach (Sector cs in controlsectors[s]) { @@ -1699,7 +1705,7 @@ namespace CodeImp.DoomBuilder.BuilderModes } // Update the slopes of 3D floor control sectors. Only do it if not pasting, since it'd otherwise screw up the original slopes - if (!pasting && controlsectors.ContainsKey(s)) + if (updateslopes && controlsectors.ContainsKey(s)) { foreach (Sector cs in controlsectors[s]) { -- GitLab