From b1ac70348518153bee4d3214d04568d21a3a1476 Mon Sep 17 00:00:00 2001 From: MaxED Date: Fri, 22 Apr 2016 20:17:21 +0000 Subject: [PATCH] Added, Sectors, Linedefs, Things modes: map element selection order of rectangular selection is now direction-dependent. --- Source/Core/Editing/ClassicMode.cs | 27 +++++- .../BuilderModes/ClassicModes/LinedefsMode.cs | 77 +++++++++++++++-- .../BuilderModes/ClassicModes/SectorsMode.cs | 85 +++++++++++++++---- .../BuilderModes/ClassicModes/ThingsMode.cs | 53 ++++++++++-- 4 files changed, 212 insertions(+), 30 deletions(-) diff --git a/Source/Core/Editing/ClassicMode.cs b/Source/Core/Editing/ClassicMode.cs index 73ef18cf..229b662a 100644 --- a/Source/Core/Editing/ClassicMode.cs +++ b/Source/Core/Editing/ClassicMode.cs @@ -68,7 +68,7 @@ namespace CodeImp.DoomBuilder.Editing // Selection protected bool selecting; protected bool selectpressed; //mxd - private Vector2D selectstart; + protected Vector2D selectstart; protected RectangleF selectionrect; protected MarqueSelectionMode marqueSelectionMode; //mxd @@ -588,6 +588,31 @@ namespace CodeImp.DoomBuilder.Editing base.OnMouseUp(e); } + //mxd + public override void OnKeyDown(KeyEventArgs e) + { + // Update marque color when modifier keys are pressed + if(selecting && (e.Control || e.Shift)) + { + OnUpdateMultiSelection(); + General.Interface.RedrawDisplay(); + } + + base.OnKeyDown(e); + } + + //mxd + public override void OnKeyUp(KeyEventArgs e) + { + // Update marque color when modifier keys are released + if(selecting && (!e.Control || !e.Shift)) + { + OnUpdateMultiSelection(); + General.Interface.RedrawDisplay(); + } + base.OnKeyUp(e); + } + /// /// Automatically called when dragging operation starts. /// diff --git a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs index 1900013d..4176e8de 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs @@ -349,6 +349,52 @@ namespace CodeImp.DoomBuilder.BuilderModes return selectionrect.Contains(l.Start.Position.x, l.Start.Position.y) && selectionrect.Contains(l.End.Position.x, l.End.Position.y); } + //mxd. Gets map elements inside of selectionoutline and sorts them by distance to targetpoint + private List GetOrderedSelection(Vector2D targetpoint, List selectionoutline) + { + // Gather affected sectors + List result = new List(); + foreach(Linedef l in General.Map.Map.Linedefs) + { + if(IsInSelectionRect(l, selectionoutline)) result.Add(l); + } + + if(result.Count == 0) return result; + + // Sort by distance to targetpoint + result.Sort(delegate(Linedef l1, Linedef l2) + { + if(l1 == l2) return 0; + + // Get closest distance from l1 to selectstart + float closest1 = float.MaxValue; + + Vector2D pos = l1.Start.Position; + float curdistance = Vector2D.DistanceSq(pos, targetpoint); + if(curdistance < closest1) closest1 = curdistance; + + pos = l1.End.Position; + curdistance = Vector2D.DistanceSq(pos, targetpoint); + if(curdistance < closest1) closest1 = curdistance; + + // Get closest distance from l2 to selectstart + float closest2 = float.MaxValue; + + pos = l2.Start.Position; + curdistance = Vector2D.DistanceSq(pos, targetpoint); + if(curdistance < closest2) closest2 = curdistance; + + pos = l2.End.Position; + curdistance = Vector2D.DistanceSq(pos, targetpoint); + if(curdistance < closest2) closest2 = curdistance; + + // Return closer one + return (int)(closest1 - closest2); + }); + + return result; + } + //mxd. This sets up new labels private void SetupSectorLabels() { @@ -992,7 +1038,7 @@ namespace CodeImp.DoomBuilder.BuilderModes if(selectionvolume) { - List selectionOutline = new List + List selectionoutline = new List { new Line2D(selectionrect.Left, selectionrect.Top, selectionrect.Right, selectionrect.Top), new Line2D(selectionrect.Right, selectionrect.Top, selectionrect.Right, selectionrect.Bottom), @@ -1005,8 +1051,15 @@ namespace CodeImp.DoomBuilder.BuilderModes switch(marqueSelectionMode) { case MarqueSelectionMode.SELECT: - foreach(Linedef l in General.Map.Map.Linedefs) - l.Selected = IsInSelectionRect(l, selectionOutline); + // Get ordered selection + List selectresult = GetOrderedSelection(base.selectstart, selectionoutline); + + // First deselect everything... + foreach(Linedef l in General.Map.Map.Linedefs) l.Selected = false; + + // Then select lines in correct order + foreach(Linedef l in selectresult) l.Selected = true; + if(selectthings) { foreach(Thing t in General.Map.ThingsFilter.VisibleThings) @@ -1015,8 +1068,15 @@ namespace CodeImp.DoomBuilder.BuilderModes break; case MarqueSelectionMode.ADD: - foreach(Linedef l in General.Map.Map.Linedefs) - l.Selected |= IsInSelectionRect(l, selectionOutline); + // Get ordered selection + List addresult = GetOrderedSelection(selectstart, selectionoutline); + + // First deselect everything inside of selection... + foreach(Linedef l in addresult) l.Selected = false; + + // Then reselect in correct order + foreach(Linedef l in addresult) l.Selected = true; + if(selectthings) { foreach(Thing t in General.Map.ThingsFilter.VisibleThings) @@ -1025,8 +1085,9 @@ namespace CodeImp.DoomBuilder.BuilderModes break; case MarqueSelectionMode.SUBTRACT: + // Selection order doesn't matter here foreach(Linedef l in General.Map.Map.Linedefs) - if(IsInSelectionRect(l, selectionOutline)) l.Selected = false; + if(IsInSelectionRect(l, selectionoutline)) l.Selected = false; if(selectthings) { foreach(Thing t in General.Map.ThingsFilter.VisibleThings) @@ -1034,9 +1095,11 @@ namespace CodeImp.DoomBuilder.BuilderModes } break; + // Should be Intersect selection mode default: + // Selection order doesn't matter here foreach(Linedef l in General.Map.Map.Linedefs) - if(!IsInSelectionRect(l, selectionOutline)) l.Selected = false; + if(!IsInSelectionRect(l, selectionoutline)) l.Selected = false; if(selectthings) { foreach(Thing t in General.Map.ThingsFilter.VisibleThings) diff --git a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs index 3bddebb0..32e698fa 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs @@ -606,6 +606,48 @@ namespace CodeImp.DoomBuilder.BuilderModes return false; } + //mxd. Gets map elements inside of selectionoutline and sorts them by distance to targetpoint + private List GetOrderedSelection(Vector2D targetpoint, List selectionoutline) + { + // Gather affected sectors + List result = new List(); + foreach(Sector s in General.Map.Map.Sectors) + { + if(IsInSelectionRect(s, selectionoutline)) result.Add(s); + } + + if(result.Count == 0) return result; + + // Sort by distance to targetpoint + result.Sort(delegate(Sector s1, Sector s2) + { + if(s1 == s2) return 0; + + // Get closest distance from s1 to selectstart + float closest1 = float.MaxValue; + foreach(Sidedef side in s1.Sidedefs) + { + Vector2D pos = (side.IsFront ? side.Line.Start : side.Line.End).Position; + float curdistance = Vector2D.DistanceSq(pos, targetpoint); + if(curdistance < closest1) closest1 = curdistance; + } + + // Get closest distance from s2 to selectstart + float closest2 = float.MaxValue; + foreach(Sidedef side in s2.Sidedefs) + { + Vector2D pos = (side.IsFront ? side.Line.Start : side.Line.End).Position; + float curdistance = Vector2D.DistanceSq(pos, targetpoint); + if(curdistance < closest2) closest2 = curdistance; + } + + // Return closer one + return (int)(closest1 - closest2); + }); + + return result; + } + //mxd public override void SelectMapElement(SelectableElement element) { @@ -1195,54 +1237,63 @@ namespace CodeImp.DoomBuilder.BuilderModes return true; } - // This is called wheh selection ends + //mxd. This is called wheh selection ends protected override void OnEndMultiSelection() { bool selectionvolume = ((Math.Abs(base.selectionrect.Width) > 0.1f) && (Math.Abs(base.selectionrect.Height) > 0.1f)); if(selectionvolume) { - List selectionOutline = new List { + List selectionoutline = new List + { new Line2D(selectionrect.Left, selectionrect.Top, selectionrect.Right, selectionrect.Top), new Line2D(selectionrect.Right, selectionrect.Top, selectionrect.Right, selectionrect.Bottom), new Line2D(selectionrect.Left, selectionrect.Bottom, selectionrect.Right, selectionrect.Bottom), new Line2D(selectionrect.Left, selectionrect.Bottom, selectionrect.Left, selectionrect.Top) }; - //mxd. (de)select sectors + // (De)select sectors switch(marqueSelectionMode) { case MarqueSelectionMode.SELECT: - foreach(Sector s in General.Map.Map.Sectors) - { - bool select = IsInSelectionRect(s, selectionOutline); - if(select && !s.Selected) SelectSector(s, true, false); - else if(!select && s.Selected) SelectSector(s, false, false); - } + // Get ordered selection + List selectresult = GetOrderedSelection(base.selectstart, selectionoutline); + + // First deselect everything... + foreach(Sector s in General.Map.Map.Sectors) SelectSector(s, false, false); + + // Then select sectors in correct order + foreach(Sector s in selectresult) SelectSector(s, true, false); break; case MarqueSelectionMode.ADD: - foreach(Sector s in General.Map.Map.Sectors) - { - if(!s.Selected && IsInSelectionRect(s, selectionOutline)) - SelectSector(s, true, false); - } + // Get ordered selection + List addresult = GetOrderedSelection(selectstart, selectionoutline); + + // First deselect everything inside of selection... + foreach(Sector s in addresult) SelectSector(s, false, false); + + // Then reselect in correct order + foreach(Sector s in addresult) SelectSector(s, true, false); break; case MarqueSelectionMode.SUBTRACT: + // Selection order doesn't matter here foreach(Sector s in General.Map.Map.Sectors) { if(!s.Selected) continue; - if(IsInSelectionRect(s, selectionOutline)) + if(IsInSelectionRect(s, selectionoutline)) SelectSector(s, false, false); } break; - default: //should be Intersect + // Should be Intersect selection mode + default: + // Selection order doesn't matter here foreach(Sector s in General.Map.Map.Sectors) { if(!s.Selected) continue; - if(!IsInSelectionRect(s, selectionOutline)) + if(!IsInSelectionRect(s, selectionoutline)) SelectSector(s, false, false); } break; diff --git a/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs index e4288c10..6a51d176 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs @@ -804,21 +804,36 @@ namespace CodeImp.DoomBuilder.BuilderModes switch(marqueSelectionMode) { case MarqueSelectionMode.SELECT: - foreach(Thing t in General.Map.ThingsFilter.VisibleThings) - t.Selected = selectionrect.Contains(t.Position.x, t.Position.y); + // Get ordered selection + List selectresult = GetOrderedSelection(base.selectstart, selectionrect); + + // First deselect everything... + foreach(Thing t in General.Map.Map.Things) t.Selected = false; + + // Then select things in correct order + foreach(Thing t in selectresult) t.Selected = true; break; case MarqueSelectionMode.ADD: - foreach(Thing t in General.Map.ThingsFilter.VisibleThings) - t.Selected |= selectionrect.Contains(t.Position.x, t.Position.y); + // Get ordered selection + List addresult = GetOrderedSelection(selectstart, selectionrect); + + // First deselect everything inside of selection... + foreach(Thing t in addresult) t.Selected = false; + + // Then reselect in correct order + foreach(Thing t in addresult) t.Selected = true; break; case MarqueSelectionMode.SUBTRACT: + // Selection order doesn't matter here foreach(Thing t in General.Map.ThingsFilter.VisibleThings) if(selectionrect.Contains(t.Position.x, t.Position.y)) t.Selected = false; break; - default: //should be Intersect + // Should be Intersect selection mode + default: + // Selection order doesn't matter here foreach(Thing t in General.Map.ThingsFilter.VisibleThings) if(!selectionrect.Contains(t.Position.x, t.Position.y)) t.Selected = false; break; @@ -891,6 +906,34 @@ namespace CodeImp.DoomBuilder.BuilderModes } } + //mxd. Gets map elements inside of selectionoutline and sorts them by distance to targetpoint + private List GetOrderedSelection(Vector2D targetpoint, RectangleF selection) + { + // Gather affected sectors + List result = new List(); + foreach(Thing t in General.Map.ThingsFilter.VisibleThings) + { + if(selection.Contains(t.Position.x, t.Position.y)) result.Add(t); + } + + if(result.Count == 0) return result; + + // Sort by distance to targetpoint + result.Sort(delegate(Thing t1, Thing t2) + { + if(t1 == t2) return 0; + + // Get closest distance from thing to selectstart + float closest1 = Vector2D.DistanceSq(t1.Position, targetpoint); + float closest2 = Vector2D.DistanceSq(t2.Position, targetpoint); + + // Return closer one + return (int)(closest1 - closest2); + }); + + return result; + } + //mxd. This sets up new labels private void SetupSectorLabels() {