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 committed by spherallic
parent d2f9150ecb
commit bb97aa354b
4 changed files with 212 additions and 30 deletions

View file

@ -68,7 +68,7 @@ namespace CodeImp.DoomBuilder.Editing
// Selection // Selection
protected bool selecting; protected bool selecting;
protected bool selectpressed; //mxd protected bool selectpressed; //mxd
private Vector2D selectstart; protected Vector2D selectstart;
protected RectangleF selectionrect; protected RectangleF selectionrect;
protected MarqueSelectionMode marqueSelectionMode; //mxd protected MarqueSelectionMode marqueSelectionMode; //mxd
@ -588,6 +588,31 @@ namespace CodeImp.DoomBuilder.Editing
base.OnMouseUp(e); 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> /// <summary>
/// Automatically called when dragging operation starts. /// Automatically called when dragging operation starts.
/// </summary> /// </summary>

View file

@ -438,6 +438,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); 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 //mxd. This sets up new labels
private void SetupSectorLabels() private void SetupSectorLabels()
{ {
@ -1092,7 +1138,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(selectionvolume) 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.Left, selectionrect.Top, selectionrect.Right, selectionrect.Top),
new Line2D(selectionrect.Right, selectionrect.Top, selectionrect.Right, selectionrect.Bottom), new Line2D(selectionrect.Right, selectionrect.Top, selectionrect.Right, selectionrect.Bottom),
@ -1105,8 +1151,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
switch(marqueSelectionMode) switch(marqueSelectionMode)
{ {
case MarqueSelectionMode.SELECT: case MarqueSelectionMode.SELECT:
foreach(Linedef l in General.Map.Map.Linedefs) // Get ordered selection
l.Selected = IsInSelectionRect(l, selectionOutline); 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) if(selectthings)
{ {
foreach(Thing t in General.Map.ThingsFilter.VisibleThings) foreach(Thing t in General.Map.ThingsFilter.VisibleThings)
@ -1115,8 +1168,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
break; break;
case MarqueSelectionMode.ADD: case MarqueSelectionMode.ADD:
foreach(Linedef l in General.Map.Map.Linedefs) // Get ordered selection
l.Selected |= IsInSelectionRect(l, selectionOutline); 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) if(selectthings)
{ {
foreach(Thing t in General.Map.ThingsFilter.VisibleThings) foreach(Thing t in General.Map.ThingsFilter.VisibleThings)
@ -1125,8 +1185,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
break; break;
case MarqueSelectionMode.SUBTRACT: case MarqueSelectionMode.SUBTRACT:
// Selection order doesn't matter here
foreach(Linedef l in General.Map.Map.Linedefs) foreach(Linedef l in General.Map.Map.Linedefs)
if(IsInSelectionRect(l, selectionOutline)) l.Selected = false; if(IsInSelectionRect(l, selectionoutline)) l.Selected = false;
if(selectthings) if(selectthings)
{ {
foreach(Thing t in General.Map.ThingsFilter.VisibleThings) foreach(Thing t in General.Map.ThingsFilter.VisibleThings)
@ -1134,9 +1195,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
break; break;
// Should be Intersect selection mode
default: default:
// Selection order doesn't matter here
foreach(Linedef l in General.Map.Map.Linedefs) foreach(Linedef l in General.Map.Map.Linedefs)
if(!IsInSelectionRect(l, selectionOutline)) l.Selected = false; if(!IsInSelectionRect(l, selectionoutline)) l.Selected = false;
if(selectthings) if(selectthings)
{ {
foreach(Thing t in General.Map.ThingsFilter.VisibleThings) foreach(Thing t in General.Map.ThingsFilter.VisibleThings)

View file

@ -606,6 +606,48 @@ namespace CodeImp.DoomBuilder.BuilderModes
return false; 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 //mxd
public override void SelectMapElement(SelectableElement element) public override void SelectMapElement(SelectableElement element)
{ {
@ -1207,54 +1249,63 @@ namespace CodeImp.DoomBuilder.BuilderModes
return true; return true;
} }
// This is called wheh selection ends //mxd. This is called wheh selection ends
protected override void OnEndMultiSelection() protected override void OnEndMultiSelection()
{ {
bool selectionvolume = ((Math.Abs(base.selectionrect.Width) > 0.1f) && (Math.Abs(base.selectionrect.Height) > 0.1f)); bool selectionvolume = ((Math.Abs(base.selectionrect.Width) > 0.1f) && (Math.Abs(base.selectionrect.Height) > 0.1f));
if(selectionvolume) 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.Left, selectionrect.Top, selectionrect.Right, selectionrect.Top),
new Line2D(selectionrect.Right, selectionrect.Top, selectionrect.Right, selectionrect.Bottom), 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.Right, selectionrect.Bottom),
new Line2D(selectionrect.Left, selectionrect.Bottom, selectionrect.Left, selectionrect.Top) new Line2D(selectionrect.Left, selectionrect.Bottom, selectionrect.Left, selectionrect.Top)
}; };
//mxd. (de)select sectors // (De)select sectors
switch(marqueSelectionMode) switch(marqueSelectionMode)
{ {
case MarqueSelectionMode.SELECT: case MarqueSelectionMode.SELECT:
foreach(Sector s in General.Map.Map.Sectors) // Get ordered selection
{ List<Sector> selectresult = GetOrderedSelection(base.selectstart, selectionoutline);
bool select = IsInSelectionRect(s, selectionOutline);
if(select && !s.Selected) SelectSector(s, true, false); // First deselect everything...
else if(!select && s.Selected) SelectSector(s, false, false); 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; break;
case MarqueSelectionMode.ADD: case MarqueSelectionMode.ADD:
foreach(Sector s in General.Map.Map.Sectors) // Get ordered selection
{ List<Sector> addresult = GetOrderedSelection(selectstart, selectionoutline);
if(!s.Selected && IsInSelectionRect(s, selectionOutline))
SelectSector(s, true, false); // 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; break;
case MarqueSelectionMode.SUBTRACT: case MarqueSelectionMode.SUBTRACT:
// Selection order doesn't matter here
foreach(Sector s in General.Map.Map.Sectors) foreach(Sector s in General.Map.Map.Sectors)
{ {
if(!s.Selected) continue; if(!s.Selected) continue;
if(IsInSelectionRect(s, selectionOutline)) if(IsInSelectionRect(s, selectionoutline))
SelectSector(s, false, false); SelectSector(s, false, false);
} }
break; 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) foreach(Sector s in General.Map.Map.Sectors)
{ {
if(!s.Selected) continue; if(!s.Selected) continue;
if(!IsInSelectionRect(s, selectionOutline)) if(!IsInSelectionRect(s, selectionoutline))
SelectSector(s, false, false); SelectSector(s, false, false);
} }
break; break;

View file

@ -822,21 +822,36 @@ namespace CodeImp.DoomBuilder.BuilderModes
switch(marqueSelectionMode) switch(marqueSelectionMode)
{ {
case MarqueSelectionMode.SELECT: case MarqueSelectionMode.SELECT:
foreach(Thing t in General.Map.ThingsFilter.VisibleThings) // Get ordered selection
t.Selected = selectionrect.Contains(t.Position.x, t.Position.y); 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; break;
case MarqueSelectionMode.ADD: case MarqueSelectionMode.ADD:
foreach(Thing t in General.Map.ThingsFilter.VisibleThings) // Get ordered selection
t.Selected |= selectionrect.Contains(t.Position.x, t.Position.y); 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; break;
case MarqueSelectionMode.SUBTRACT: case MarqueSelectionMode.SUBTRACT:
// Selection order doesn't matter here
foreach(Thing t in General.Map.ThingsFilter.VisibleThings) foreach(Thing t in General.Map.ThingsFilter.VisibleThings)
if(selectionrect.Contains(t.Position.x, t.Position.y)) t.Selected = false; if(selectionrect.Contains(t.Position.x, t.Position.y)) t.Selected = false;
break; 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) foreach(Thing t in General.Map.ThingsFilter.VisibleThings)
if(!selectionrect.Contains(t.Position.x, t.Position.y)) t.Selected = false; if(!selectionrect.Contains(t.Position.x, t.Position.y)) t.Selected = false;
break; break;
@ -909,6 +924,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 //mxd. This sets up new labels
private void SetupSectorLabels() private void SetupSectorLabels()
{ {