Introduce IMouseBounds and split/rework mouse rectangles.

The render bounds for an actor now include the area covered
by bibs, shadows, and any other widgets. In many cases this
area is much larger than we really want to consider for
tooltips and mouse selection.

An optional Margin is added to Selectable to support cases
like infantry, where we want the mouse area of the actor
to be larger than the drawn selection box.
This commit is contained in:
Paul Chote
2017-12-07 23:15:07 +00:00
committed by reaperrr
parent 8fcc80b05a
commit 6f5d035e79
25 changed files with 349 additions and 117 deletions

View File

@@ -9,6 +9,10 @@
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
namespace OpenRA.Traits
{
[Desc("This actor is selectable. Defines bounds of selectable area, selection class and selection priority.")]
@@ -19,6 +23,9 @@ namespace OpenRA.Traits
[Desc("Bounds for the selectable area.")]
public readonly int[] Bounds = null;
[Desc("Area outside the visible selection box that is enabled for selection")]
public readonly int Margin = 0;
[Desc("All units having the same selection class specified will be selected with select-by-type commands (e.g. double-click). "
+ "Defaults to the actor name when not defined or inherited.")]
public readonly string Class = null;
@@ -28,7 +35,7 @@ namespace OpenRA.Traits
public object Create(ActorInitializer init) { return new Selectable(init.Self, this); }
}
public class Selectable
public class Selectable : IMouseBounds
{
public readonly string Class = null;
@@ -39,5 +46,20 @@ namespace OpenRA.Traits
Class = string.IsNullOrEmpty(info.Class) ? self.Info.Name : info.Class;
Info = info;
}
Rectangle IMouseBounds.MouseoverBounds(Actor self, WorldRenderer wr)
{
if (Info.Bounds == null)
return Rectangle.Empty;
var size = new int2(Info.Bounds[0], Info.Bounds[1]);
var offset = -size / 2 - new int2(Info.Margin, Info.Margin);
if (Info.Bounds.Length > 2)
offset += new int2(Info.Bounds[2], Info.Bounds[3]);
var xy = wr.ScreenPxPosition(self.CenterPosition) + offset;
return new Rectangle(xy.X, xy.Y, size.X + 2 * Info.Margin, size.Y + 2 * Info.Margin);
}
}
}