diff --git a/Source/Plugins/BuilderModes/Resources/Actions.cfg b/Source/Plugins/BuilderModes/Resources/Actions.cfg index 34f1c03915376067befb1b601a951fe3206c9f4a..f5328e9f57cef3c1d24395ca4de8a6f282815bbb 100755 --- a/Source/Plugins/BuilderModes/Resources/Actions.cfg +++ b/Source/Plugins/BuilderModes/Resources/Actions.cfg @@ -1414,4 +1414,16 @@ togglevisualslopepicking allowkeys = true; allowmouse = true; allowscroll = false; + default = 65623; // Shift-W +} + +slopebetweenhandles +{ + title = "Slope Between Handles"; + category = "visual"; + description = "Slopes the selected floors and ceilings between the selected slope handles."; + allowkeys = true; + allowmouse = true; + allowscroll = false; + default = 131142; // Ctrl-F } \ No newline at end of file diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs index fd51b8ea9ebb78981f974f709ac69273db24e433..5a1b4ff73cdf5a5bfac8a381128d2474ce822ce1 100755 --- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs +++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs @@ -2080,6 +2080,32 @@ namespace CodeImp.DoomBuilder.BuilderModes return verts; } + + // This returns all selected slope handles, no doubles + private List<VisualSidedefSlope> GetSelectedSlopeHandles() + { + HashSet<VisualSidedefSlope> added = new HashSet<VisualSidedefSlope>(); + List<VisualSidedefSlope> handles = new List<VisualSidedefSlope>(); + + foreach(IVisualEventReceiver i in selectedobjects) + { + VisualSidedefSlope handle = i as VisualSidedefSlope; + if(handle != null && !added.Contains(handle)) + { + handles.Add(handle); + added.Add(handle); + } + } + + // Add highlight? + if((selectedobjects.Count == 0) && (target.picked is VisualSidedefSlope)) + { + VisualSidedefSlope handle = (VisualSidedefSlope)target.picked; + if (!added.Contains(handle)) handles.Add(handle); + } + + return handles; + } // This returns the IVisualEventReceiver on which the action must be performed private IVisualEventReceiver GetTargetEventReceiver(bool targetonly) @@ -3980,6 +4006,43 @@ namespace CodeImp.DoomBuilder.BuilderModes pickingmode = PickingMode.Default; } + [BeginAction("slopebetweenhandles")] + public void SlopeBetweenHandles() + { + List<VisualSidedefSlope> handles = GetSelectedSlopeHandles(); + if(handles.Count != 2) + { + General.Interface.DisplayStatus(StatusType.Warning, "You need to have exactly two slope handles selected to slope between them."); + return; + } + + List<IVisualEventReceiver> selectedsectors = GetSelectedObjects(true, false, false, false, false); + if(selectedsectors.Count == 0) + { + General.Interface.DisplayStatus(StatusType.Warning, "You need to select floors or ceilings to slope between slope handles."); + return; + } + + General.Map.UndoRedo.CreateUndo("Slope between slope handles"); + + // Create the new plane + Vector3D p1 = new Vector3D(handles[0].Sidedef.Line.Start.Position, handles[0].Level.plane.GetZ(handles[0].Sidedef.Line.Start.Position)); + Vector3D p2 = new Vector3D(handles[0].Sidedef.Line.End.Position, handles[0].Level.plane.GetZ(handles[0].Sidedef.Line.End.Position)); + Vector3D p3 = new Vector3D(handles[1].Sidedef.Line.Line.GetCoordinatesAt(0.5f), handles[1].Level.plane.GetZ(handles[1].Sidedef.Line.Line.GetCoordinatesAt(0.5f))); + Plane plane = new Plane(p1, p2, p3, true); + + // Apply slope + foreach (BaseVisualGeometrySector bvgs in selectedsectors) + { + VisualSidedefSlope.ApplySlope(bvgs.Level, plane, this); + bvgs.Sector.UpdateSectorGeometry(true); + } + + UpdateChangedObjects(); + + General.Interface.DisplayStatus(StatusType.Action, "Sloped between slope handles."); + } + #endregion #region ================== Texture Alignment diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualSidedefSlope.cs b/Source/Plugins/BuilderModes/VisualModes/VisualSidedefSlope.cs index c66607272a81cbf517cc528de5bae683d441b614..ce0778531213f6afddc2914a21486975ba944920 100644 --- a/Source/Plugins/BuilderModes/VisualModes/VisualSidedefSlope.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualSidedefSlope.cs @@ -213,6 +213,54 @@ namespace CodeImp.DoomBuilder.VisualModes return handle; } + public static void ApplySlope(SectorLevel level, Plane plane, BaseVisualMode mode) + { + bool applytoceiling = false; + + Vector2D center = new Vector2D(level.sector.BBox.X + level.sector.BBox.Width / 2, + level.sector.BBox.Y + level.sector.BBox.Height / 2); + + if (level.extrafloor) + { + // The top side of 3D floors is the ceiling of the sector, but it's a "floor" in UDB, so the + // ceiling of the control sector has to be modified + if (level.type == SectorLevelType.Floor) + applytoceiling = true; + } + else + { + if (level.type == SectorLevelType.Ceiling) + applytoceiling = true; + } + + if (applytoceiling) + { + Plane downplane = plane.GetInverted(); + level.sector.CeilSlope = downplane.Normal; + level.sector.CeilSlopeOffset = downplane.Offset; + level.sector.CeilHeight = (int)new Plane(level.sector.CeilSlope, level.sector.CeilSlopeOffset).GetZ(center); + } + else + { + level.sector.FloorSlope = plane.Normal; + level.sector.FloorSlopeOffset = plane.Offset; + level.sector.FloorHeight = (int)new Plane(level.sector.FloorSlope, level.sector.FloorSlopeOffset).GetZ(center); + } + + // Rebuild sector + BaseVisualSector vs; + if (mode.VisualSectorExists(level.sector)) + { + vs = (BaseVisualSector)mode.GetVisualSector(level.sector); + } + else + { + vs = mode.CreateBaseVisualSector(level.sector); + } + + if (vs != null) vs.UpdateSectorGeometry(true); + } + #endregion #region ================== Events @@ -274,51 +322,7 @@ namespace CodeImp.DoomBuilder.VisualModes // Apply slope to surfaces foreach (SectorLevel l in levels) - { - bool applytoceiling = false; - Vector2D center = new Vector2D(l.sector.BBox.X + l.sector.BBox.Width / 2, - l.sector.BBox.Y + l.sector.BBox.Height / 2); - - if(l.extrafloor) - { - // The top side of 3D floors is the ceiling of the sector, but it's a "floor" in UDB, so the - // ceiling of the control sector has to be modified - if (l.type == SectorLevelType.Floor) - applytoceiling = true; - } - else - { - if (l.type == SectorLevelType.Ceiling) - applytoceiling = true; - } - - if (applytoceiling) - { - Plane downplane = plane.GetInverted(); - l.sector.CeilSlope = downplane.Normal; - l.sector.CeilSlopeOffset = downplane.Offset; - l.sector.CeilHeight = (int)new Plane(l.sector.CeilSlope, l.sector.CeilSlopeOffset).GetZ(center); - } - else - { - l.sector.FloorSlope = plane.Normal; - l.sector.FloorSlopeOffset = plane.Offset; - l.sector.FloorHeight = (int)new Plane(l.sector.FloorSlope, l.sector.FloorSlopeOffset).GetZ(center); - } - - // Rebuild sector - BaseVisualSector vs; - if (mode.VisualSectorExists(l.sector)) - { - vs = (BaseVisualSector)mode.GetVisualSector(l.sector); - } - else - { - vs = mode.CreateBaseVisualSector(l.sector); - } - - if (vs != null) vs.UpdateSectorGeometry(true); - } + ApplySlope(l, plane, mode); mode.SetActionResult("Changed slope."); }