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()
{