Added, Sectors, Linedefs, Things modes: map element selection order of rectangular selection is now direction-dependent.

This commit is contained in:
MaxED 2016-04-22 20:17:21 +00:00
parent e03936a0d6
commit b1ac703485
4 changed files with 212 additions and 30 deletions

View file

@ -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);
}
/// <summary>
/// Automatically called when dragging operation starts.
/// </summary>

View file

@ -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<Linedef> GetOrderedSelection(Vector2D targetpoint, List<Line2D> selectionoutline)
{
// Gather affected sectors
List<Linedef> result = new List<Linedef>();
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<Line2D> selectionOutline = new List<Line2D>
List<Line2D> selectionoutline = new List<Line2D>
{
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<Linedef> 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<Linedef> 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)

View file

@ -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<Sector> GetOrderedSelection(Vector2D targetpoint, List<Line2D> selectionoutline)
{
// Gather affected sectors
List<Sector> result = new List<Sector>();
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<Line2D> selectionOutline = new List<Line2D> {
List<Line2D> selectionoutline = new List<Line2D>
{
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<Sector> 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<Sector> 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;

View file

@ -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<Thing> 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<Thing> 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<Thing> GetOrderedSelection(Vector2D targetpoint, RectangleF selection)
{
// Gather affected sectors
List<Thing> result = new List<Thing>();
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()
{