remove FP sillyness from FindUnits & friends

This commit is contained in:
Chris Forbes
2011-05-04 22:25:35 +12:00
parent ccc245ded4
commit 9b3e6c5c4a
10 changed files with 48 additions and 40 deletions

View File

@@ -28,8 +28,8 @@ namespace OpenRA
IOccupySpace OccupiesSpace;
IHasLocation HasLocation;
Lazy<IMove> Move;
public Cached<RectangleF> Bounds;
public Cached<RectangleF> ExtendedBounds;
public Cached<Rectangle> Bounds;
public Cached<Rectangle> ExtendedBounds;
public int2 Location
{ get {
@@ -76,12 +76,12 @@ namespace OpenRA
{
var si = Info.Traits.GetOrDefault<SelectableInfo>();
if (si != null && si.Bounds != null)
return new float2(si.Bounds[0], si.Bounds[1]);
return new int2(si.Bounds[0], si.Bounds[1]);
// auto size from render
var firstSprite = TraitsImplementing<IRender>().SelectMany(ApplyIRender).FirstOrDefault();
if (firstSprite.Sprite == null) return float2.Zero;
return firstSprite.Sprite.size * firstSprite.Scale;
if (firstSprite.Sprite == null) return int2.Zero;
return (firstSprite.Sprite.size * firstSprite.Scale).ToInt2();
});
ApplyIRender = x => x.Render(this);
@@ -104,7 +104,7 @@ namespace OpenRA
get { return currentActivity == null; }
}
OpenRA.FileFormats.Lazy<float2> Size;
OpenRA.FileFormats.Lazy<int2> Size;
// note: these delegates are cached to avoid massive allocation.
Func<IRender, IEnumerable<Renderable>> ApplyIRender;
@@ -120,24 +120,27 @@ namespace OpenRA
// vertically to altitude = 0 to support FindUnitsInCircle queries
// When false, the bounding box is given for the actor
// at its current altitude
RectangleF CalculateBounds(bool useAltitude)
Rectangle CalculateBounds(bool useAltitude)
{
var size = Size.Value;
var loc = CenterLocation - 0.5f * size;
var loc = CenterLocation - size / 2;
var si = Info.Traits.GetOrDefault<SelectableInfo>();
if (si != null && si.Bounds != null && si.Bounds.Length > 2)
loc += new float2(si.Bounds[2], si.Bounds[3]);
{
loc.X += si.Bounds[2];
loc.Y += si.Bounds[3];
}
var move = Move.Value;
if (move != null)
{
loc -= new float2(0, move.Altitude);
loc.Y -= move.Altitude;
if (useAltitude)
size = new float2(size.X, size.Y + move.Altitude);
size = new int2(size.X, size.Y + move.Altitude);
}
return new RectangleF(loc.X, loc.Y, size.X, size.Y);
return new Rectangle(loc.X, loc.Y, size.X, size.Y);
}
public bool IsInWorld { get; internal set; }

View File

@@ -110,6 +110,9 @@ namespace OpenRA.Graphics
return ViewToWorld(mi.Location);
}
public int2 ViewToWorldPx(int2 loc) { return loc + Location.ToInt2(); }
public int2 ViewToWorldPx(MouseInput mi) { return ViewToWorldPx(mi.Location); }
public void Center(float2 loc)
{
scrollPosition = this.NormalizeScrollPosition((Game.CellSize*loc - screenSize / 2).ToInt2());

View File

@@ -58,8 +58,8 @@ namespace OpenRA.Graphics
bounds.Offset((int)Game.viewport.Location.X, (int)Game.viewport.Location.Y);
var actors = world.FindUnits(
new float2(bounds.Left, bounds.Top),
new float2(bounds.Right, bounds.Bottom));
new int2(bounds.Left, bounds.Top),
new int2(bounds.Right, bounds.Bottom));
var renderables = actors.SelectMany(a => a.Render())
.OrderBy(r => r, comparer);

View File

@@ -54,10 +54,10 @@ namespace OpenRA.Traits
if (bounds.Left >= Game.CellSize * self.World.Map.Bounds.Right) continue;
if (bounds.Top >= Game.CellSize * self.World.Map.Bounds.Bottom) continue;
var i1 = Math.Max(0, (int)bounds.Left / scale);
var i2 = Math.Min(bins.GetUpperBound(0), (int)bounds.Right / scale);
var j1 = Math.Max(0, (int)bounds.Top / scale);
var j2 = Math.Min(bins.GetUpperBound(1), (int)bounds.Bottom / scale);
var i1 = Math.Max(0, bounds.Left / scale);
var i2 = Math.Min(bins.GetUpperBound(0), bounds.Right / scale);
var j1 = Math.Max(0, bounds.Top / scale);
var j2 = Math.Min(bins.GetUpperBound(1), bounds.Bottom / scale);
for (var j = j1; j <= j2; j++)
for (var i = i1; i <= i2; i++)
@@ -77,7 +77,7 @@ namespace OpenRA.Traits
public IEnumerable<Actor> ActorsInBox(int2 a, int2 b)
{
var r = RectangleF.FromLTRB(a.X, a.Y, b.X, b.Y);
var r = Rectangle.FromLTRB(a.X, a.Y, b.X, b.Y);
return ActorsInBins(a.X / scale, b.X / scale, a.Y / scale, b.Y / scale)
.Distinct()

View File

@@ -8,6 +8,7 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
@@ -15,7 +16,6 @@ using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Orders;
using OpenRA.Traits;
using System;
namespace OpenRA.Widgets
{
@@ -23,6 +23,7 @@ namespace OpenRA.Widgets
{
readonly World world;
readonly WorldRenderer worldRenderer;
[ObjectCreator.UseCtor]
public WorldInteractionControllerWidget([ObjectCreator.Param] World world, [ObjectCreator.Param] WorldRenderer worldRenderer)
{
@@ -35,7 +36,7 @@ namespace OpenRA.Widgets
var selbox = SelectionBox;
if (selbox == null)
{
foreach (var u in SelectActorsInBox(world, Game.CellSize * dragStart, Game.CellSize * dragStart))
foreach (var u in SelectActorsInBox(world, dragStart, dragStart))
worldRenderer.DrawRollover(u);
return;
@@ -54,12 +55,12 @@ namespace OpenRA.Widgets
worldRenderer.DrawRollover(u);
}
float2 dragStart, dragEnd;
int2 dragStart, dragEnd;
// TODO: WorldInteractionController doesn't support delegate methods for mouse input
public override bool HandleMouseInput(MouseInput mi)
{
var xy = Game.viewport.ViewToWorld(mi);
var xy = Game.viewport.ViewToWorldPx(mi);
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down)
{
dragStart = dragEnd = xy;
@@ -73,7 +74,7 @@ namespace OpenRA.Widgets
{
if (world.OrderGenerator is UnitOrderGenerator)
{
var newSelection = SelectActorsInBox(world, Game.CellSize * dragStart, Game.CellSize * xy);
var newSelection = SelectActorsInBox(world, dragStart, xy);
world.Selection.Combine(world, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
}
@@ -89,20 +90,20 @@ namespace OpenRA.Widgets
return true;
}
public Pair<float2, float2>? SelectionBox
public Pair<int2, int2>? SelectionBox
{
get
{
if (dragStart == dragEnd) return null;
return Pair.New(Game.CellSize * dragStart, Game.CellSize * dragEnd);
return Pair.New(dragStart, dragEnd);
}
}
public void ApplyOrders(World world, float2 xy, MouseInput mi)
public void ApplyOrders(World world, int2 xy, MouseInput mi)
{
if (world.OrderGenerator == null) return;
var orders = world.OrderGenerator.Order(world, xy.ToInt2(), mi).ToArray();
var orders = world.OrderGenerator.Order(world, Traits.Util.CellContaining(xy), mi).ToArray();
orders.Do( o => world.IssueOrder( o ) );
world.PlayVoiceForOrders(orders);
@@ -119,6 +120,7 @@ namespace OpenRA.Widgets
Modifiers = Game.GetModifierKeys()
};
// TODO: fix this up.
return world.OrderGenerator.GetCursor( world, Game.viewport.ViewToWorld(mi).ToInt2(), mi );
} );
}
@@ -141,7 +143,7 @@ namespace OpenRA.Widgets
}
static readonly Actor[] NoActors = {};
IEnumerable<Actor> SelectActorsInBox(World world, float2 a, float2 b)
IEnumerable<Actor> SelectActorsInBox(World world, int2 a, int2 b)
{
return world.FindUnits(a, b)
.Where( x => x.HasTrait<Selectable>() && world.LocalShroud.IsVisible(x) )

View File

@@ -23,27 +23,27 @@ namespace OpenRA
{
public static IEnumerable<Actor> FindUnitsAtMouse(this World world, int2 mouseLocation)
{
var loc = mouseLocation + Game.viewport.Location;
var loc = Game.viewport.ViewToWorldPx(mouseLocation);
return FindUnits(world, loc, loc).Where(a => world.LocalShroud.IsVisible(a));
}
public static IEnumerable<Actor> FindUnits(this World world, float2 a, float2 b)
public static IEnumerable<Actor> FindUnits(this World world, int2 a, int2 b)
{
var u = float2.Min(a, b).ToInt2();
var v = float2.Max(a, b).ToInt2();
return world.WorldActor.Trait<SpatialBins>().ActorsInBox(u,v);
}
public static IEnumerable<Actor> FindUnitsInCircle(this World world, float2 a, float r)
public static IEnumerable<Actor> FindUnitsInCircle(this World world, int2 a, int r)
{
using (new PerfSample("FindUnitsInCircle"))
{
var min = a - new float2(r, r);
var max = a + new float2(r, r);
var min = a - new int2(r, r);
var max = a + new int2(r, r);
var actors = world.FindUnits(min, max);
var rect = new RectangleF(min.X, min.Y, max.X - min.X, max.Y - min.Y);
var rect = new Rectangle(min.X, min.Y, max.X - min.X, max.Y - min.Y);
var inBox = actors.Where(x => x.ExtendedBounds.Value.IntersectsWith(rect));

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.RA
public void TickIdle( Actor self )
{
var attack = self.Trait<AttackBase>();
var inRange = self.World.FindUnitsInCircle(self.CenterLocation, Game.CellSize * attack.GetMaximumRange());
var inRange = self.World.FindUnitsInCircle(self.CenterLocation, (int)(Game.CellSize * attack.GetMaximumRange()));
var target = inRange
.Where(a => a != self && a.AppearsFriendlyTo(self))

View File

@@ -95,7 +95,7 @@ namespace OpenRA.Mods.RA
nextScanTime = (int)(25 * (info.ScanTimeAverage +
(self.World.SharedRandom.NextDouble() * 2 - 1) * info.ScanTimeSpread));
var inRange = self.World.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range);
var inRange = self.World.FindUnitsInCircle(self.CenterLocation, (int)(Game.CellSize * range));
return inRange
.Where(a => a.Owner != null && a.AppearsHostileTo(self))

View File

@@ -80,7 +80,7 @@ namespace OpenRA.Mods.RA
case DamageModel.Normal:
{
var maxSpread = warhead.Spread * (float)Math.Log(Math.Abs(warhead.Damage), 2);
var hitActors = world.FindUnitsInCircle(args.dest, maxSpread);
var hitActors = world.FindUnitsInCircle(args.dest, (int)maxSpread);
foreach (var victim in hitActors)
{
@@ -92,7 +92,7 @@ namespace OpenRA.Mods.RA
case DamageModel.PerCell:
{
foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0]))
foreach (var unit in world.FindUnits(Game.CellSize * t, Game.CellSize * (t + new float2(1,1))))
foreach (var unit in world.FindUnits(Game.CellSize * t, Game.CellSize * (t + new int2(1,1))))
unit.InflictDamage(args.firedBy,
(int)(warhead.Damage * warhead.EffectivenessAgainst(unit)), warhead);
} break;

View File

@@ -56,7 +56,7 @@ namespace OpenRA.Mods.RA.Render
if (!hasTicked)
{
var oneCell = new float2(Game.CellSize, Game.CellSize);
var oneCell = new int2(Game.CellSize, Game.CellSize);
var adjWalls = self.World.FindUnits(self.CenterLocation - oneCell, self.CenterLocation + oneCell)
.Where(a => a.Info == self.Info && a != self);