New types for cell and pixel coordinate position/vectors.

This commit is contained in:
James Dunne
2012-06-20 23:22:27 -05:00
parent 0b98a8ce5e
commit 9c49143534
162 changed files with 1291 additions and 865 deletions

View File

@@ -32,9 +32,9 @@ namespace OpenRA
public IOccupySpace OccupiesSpace { get { return occupySpace.Value; } }
public int2 Location { get { return occupySpace.Value.TopLeft; } }
public CPos Location { get { return occupySpace.Value.TopLeft; } }
public int2 CenterLocation
public PPos CenterLocation
{
get
{
@@ -123,22 +123,30 @@ namespace OpenRA
// at its current altitude
Rectangle CalculateBounds(bool useAltitude)
{
var size = Size.Value;
var size = (PVecInt)(Size.Value);
var loc = CenterLocation - size / 2;
var si = Info.Traits.GetOrDefault<SelectableInfo>();
if (si != null && si.Bounds != null && si.Bounds.Length > 2)
{
#if true
loc += new PVecInt(si.Bounds[2], si.Bounds[3]);
#else
loc.X += si.Bounds[2];
loc.Y += si.Bounds[3];
#endif
}
var move = Move.Value;
if (move != null)
{
#if true
loc -= new PVecInt(0, move.Altitude);
#else
loc.Y -= move.Altitude;
#endif
if (useAltitude)
size = new int2(size.X, size.Y + move.Altitude);
size = new PVecInt(size.X, size.Y + move.Altitude);
}
return new Rectangle(loc.X, loc.Y, size.X, size.Y);

View File

@@ -62,12 +62,12 @@ namespace OpenRA
public int Value( World world ) { return value; }
}
public class LocationInit : IActorInit<int2>
public class LocationInit : IActorInit<CPos>
{
[FieldFromYamlKey] public readonly int2 value = int2.Zero;
public LocationInit() { }
public LocationInit( int2 init ) { value = init; }
public int2 Value( World world ) { return value; }
public LocationInit( CPos init ) { value = init.ToInt2(); }
public CPos Value(World world) { return (CPos)value; }
}
public class SubCellInit : IActorInit<SubCell>
@@ -78,12 +78,12 @@ namespace OpenRA
public SubCell Value(World world) { return (SubCell)value; }
}
public class CenterLocationInit : IActorInit<int2>
public class CenterLocationInit : IActorInit<PPos>
{
[FieldFromYamlKey] public readonly int2 value = int2.Zero;
public CenterLocationInit() { }
public CenterLocationInit( int2 init ) { value = init; }
public int2 Value( World world ) { return value; }
public CenterLocationInit(PPos init) { value = init.ToInt2(); }
public PPos Value(World world) { return (PPos)value; }
}
public class OwnerInit : IActorInit<Player>

View File

@@ -37,7 +37,7 @@ namespace OpenRA
world.ActorRemoved += a => Remove( a, a.OccupiesSpace );
}
public IEnumerable<Actor> GetUnitsAt( int2 a )
public IEnumerable<Actor> GetUnitsAt(CPos a)
{
if (!map.IsInMap(a)) yield break;
@@ -46,7 +46,7 @@ namespace OpenRA
yield return i.actor;
}
public IEnumerable<Actor> GetUnitsAt( int2 a, SubCell sub )
public IEnumerable<Actor> GetUnitsAt(CPos a, SubCell sub)
{
if (!map.IsInMap(a)) yield break;
@@ -55,7 +55,7 @@ namespace OpenRA
yield return i.actor;
}
public bool HasFreeSubCell(int2 a)
public bool HasFreeSubCell(CPos a)
{
if (!AnyUnitsAt(a))
return true;
@@ -64,12 +64,12 @@ namespace OpenRA
SubCell.BottomLeft, SubCell.BottomRight }.Any(b => !AnyUnitsAt(a,b));
}
public bool AnyUnitsAt(int2 a)
public bool AnyUnitsAt(CPos a)
{
return influence[ a.X, a.Y ] != null;
}
public bool AnyUnitsAt(int2 a, SubCell sub)
public bool AnyUnitsAt(CPos a, SubCell sub)
{
for( var i = influence[ a.X, a.Y ] ; i != null ; i = i.next )
if (i.subCell == sub || i.subCell == SubCell.FullCell)

71
OpenRA.Game/CPos.cs Normal file
View File

@@ -0,0 +1,71 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Cell coordinate position in the world (coarse).
/// </summary>
public struct CPos
{
public readonly int X, Y;
public CPos(int x, int y) { X = x; Y = y; }
public static readonly CPos Zero = new CPos(0, 0);
public static explicit operator CPos(int2 a) { return new CPos(a.X, a.Y); }
public static CPos operator +(CVec a, CPos b) { return new CPos(a.X + b.X, a.Y + b.Y); }
public static CPos operator +(CPos a, CVec b) { return new CPos(a.X + b.X, a.Y + b.Y); }
public static CPos operator -(CPos a, CVec b) { return new CPos(a.X - b.X, a.Y - b.Y); }
public static CVec operator -(CPos a, CPos b) { return new CVec(a.X - b.X, a.Y - b.Y); }
public static bool operator ==(CPos me, CPos other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(CPos me, CPos other) { return !(me == other); }
public static CPos Max(CPos a, CPos b) { return new CPos(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static CPos Min(CPos a, CPos b) { return new CPos(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public PPos ToPPos() { return new PPos(Game.CellSize * X, Game.CellSize * Y); }
public CPos Clamp(Rectangle r)
{
return new CPos(Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top)));
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
CPos o = (CPos)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
public static class RectangleExtensions
{
public static CPos TopLeftAsCPos(this Rectangle r) { return new CPos(r.Left, r.Top); }
public static CPos BottomRightAsCPos(this Rectangle r) { return new CPos(r.Right, r.Bottom); }
}
}

76
OpenRA.Game/CVec.cs Normal file
View File

@@ -0,0 +1,76 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Cell coordinate vector (coarse).
/// </summary>
public struct CVec
{
public readonly int X, Y;
public CVec(int x, int y) { X = x; Y = y; }
public CVec(Size p) { X = p.Width; Y = p.Height; }
public static readonly CVec Zero = new CVec(0, 0);
public static explicit operator CVec(int2 a) { return new CVec(a.X, a.Y); }
public static explicit operator CVec(float2 a) { return new CVec((int)a.X, (int)a.Y); }
public static CVec operator +(CVec a, CVec b) { return new CVec(a.X + b.X, a.Y + b.Y); }
public static CVec operator -(CVec a, CVec b) { return new CVec(a.X - b.X, a.Y - b.Y); }
public static CVec operator *(int a, CVec b) { return new CVec(a * b.X, a * b.Y); }
public static CVec operator *(CVec b, int a) { return new CVec(a * b.X, a * b.Y); }
public static CVec operator /(CVec a, int b) { return new CVec(a.X / b, a.Y / b); }
public static CVec operator -(CVec a) { return new CVec(-a.X, -a.Y); }
public static bool operator ==(CVec me, CVec other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(CVec me, CVec other) { return !(me == other); }
public static CVec Max(CVec a, CVec b) { return new CVec(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static CVec Min(CVec a, CVec b) { return new CVec(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static int Dot(CVec a, CVec b) { return a.X * b.X + a.Y * b.Y; }
public CVec Sign() { return new CVec(Math.Sign(X), Math.Sign(Y)); }
public CVec Abs() { return new CVec(Math.Abs(X), Math.Abs(Y)); }
public int LengthSquared { get { return X * X + Y * Y; } }
public int Length { get { return (int)Math.Sqrt(LengthSquared); } }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public CVec Clamp(Rectangle r)
{
return new CVec(
Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top))
);
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
CVec o = (CVec)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
}

View File

@@ -72,11 +72,11 @@ namespace OpenRA.GameRules
{
public WeaponInfo weapon;
public Actor firedBy;
public int2 src;
public PPos src;
public int srcAltitude;
public int facing;
public Target target;
public int2 dest;
public PPos dest;
public int destAltitude;
public float firepowerModifier = 1.0f;
}

View File

@@ -35,7 +35,7 @@ namespace OpenRA.Graphics
public Renderable Image(Actor self, string pal)
{
var p = self.CenterLocation;
var loc = p - 0.5f * Animation.Image.size
var loc = p.ToFloat2() - 0.5f * Animation.Image.size
+ (OffsetFunc != null ? OffsetFunc() : float2.Zero);
var r = new Renderable(Animation.Image, loc, pal, p.Y);

View File

@@ -149,18 +149,18 @@ namespace OpenRA.Graphics
}
// Convert from viewport coords to cell coords (not px)
public float2 ViewToWorld(MouseInput mi) { return ViewToWorld(mi.Location); }
public float2 ViewToWorld(int2 loc)
public CPos ViewToWorld(MouseInput mi) { return ViewToWorld(mi.Location); }
public CPos ViewToWorld(int2 loc)
{
return (1f / Game.CellSize) * (1f/Zoom*loc.ToFloat2() + Location);
return (CPos)( (1f / Game.CellSize) * (1f/Zoom*loc.ToFloat2() + Location) ).ToInt2();
}
public int2 ViewToWorldPx(int2 loc) { return (1f/Zoom*loc.ToFloat2() + Location).ToInt2(); }
public int2 ViewToWorldPx(MouseInput mi) { return ViewToWorldPx(mi.Location); }
public PPos ViewToWorldPx(int2 loc) { return (PPos)(1f/Zoom*loc.ToFloat2() + Location).ToInt2(); }
public PPos ViewToWorldPx(MouseInput mi) { return ViewToWorldPx(mi.Location); }
public void Center(float2 loc)
{
scrollPosition = NormalizeScrollPosition((Game.CellSize*loc - 1f/(2*Zoom)*screenSize.ToFloat2()).ToInt2());
scrollPosition = NormalizeScrollPosition((Game.CellSize * loc - 1f/(2*Zoom)*screenSize.ToFloat2()).ToInt2());
}
public void Center(IEnumerable<Actor> actors)
@@ -168,9 +168,9 @@ namespace OpenRA.Graphics
if (!actors.Any()) return;
var avgPos = actors
.Select(a => a.CenterLocation)
.Select(a => (PVecInt)a.CenterLocation)
.Aggregate((a, b) => a + b) / actors.Count();
scrollPosition = NormalizeScrollPosition((avgPos - 1f/(2*Zoom)*screenSize.ToFloat2()).ToInt2());
scrollPosition = NormalizeScrollPosition(((PVecFloat)avgPos - (PVecFloat)(1f / (2 * Zoom) * screenSize.ToFloat2())).ToInt2());
}
// Rectangle (in viewport coords) that contains things to be drawn

View File

@@ -53,8 +53,9 @@ namespace OpenRA.Graphics
var comparer = new SpriteComparer();
var actors = world.FindUnits(
new int2(Game.CellSize*bounds.Left, Game.CellSize*bounds.Top),
new int2(Game.CellSize*bounds.Right, Game.CellSize*bounds.Bottom));
bounds.TopLeftAsCPos().ToPPos(),
bounds.BottomRightAsCPos().ToPPos()
);
var renderables = actors.SelectMany(a => a.Render())
.OrderBy(r => r, comparer);
@@ -140,25 +141,21 @@ namespace OpenRA.Graphics
selectable.DrawRollover(this, unit);
}
public void DrawLocus(Color c, int2[] cells)
public void DrawLocus(Color c, CPos[] cells)
{
var dict = cells.ToDictionary(a => a, a => 0);
var wlr = Game.Renderer.WorldLineRenderer;
foreach (var t in dict.Keys)
{
if (!dict.ContainsKey(t + new int2(-1, 0)))
wlr.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(0, 1)),
c, c);
if (!dict.ContainsKey(t + new int2(1, 0)))
wlr.DrawLine(Game.CellSize * (t + new int2(1, 0)), Game.CellSize * (t + new int2(1, 1)),
c, c);
if (!dict.ContainsKey(t + new int2(0, -1)))
wlr.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(1, 0)),
c, c);
if (!dict.ContainsKey(t + new int2(0, 1)))
wlr.DrawLine(Game.CellSize * (t + new int2(0, 1)), Game.CellSize * (t + new int2(1, 1)),
c, c);
if (!dict.ContainsKey(t + new CVec(-1, 0)))
wlr.DrawLine(t.ToPPos().ToFloat2(), (t + new CVec(0, 1)).ToPPos().ToFloat2(), c, c);
if (!dict.ContainsKey(t + new CVec(1, 0)))
wlr.DrawLine((t + new CVec(1, 0)).ToPPos().ToFloat2(), (t + new CVec(1, 1)).ToPPos().ToFloat2(), c, c);
if (!dict.ContainsKey(t + new CVec(0, -1)))
wlr.DrawLine(t.ToPPos().ToFloat2(), (t + new CVec(1, 0)).ToPPos().ToFloat2(), c, c);
if (!dict.ContainsKey(t + new CVec(0, 1)))
wlr.DrawLine((t + new CVec(0, 1)).ToPPos().ToFloat2(), (t + new CVec(1, 1)).ToPPos().ToFloat2(), c, c);
}
}

View File

@@ -338,7 +338,7 @@ namespace OpenRA
return dataStream.ToArray();
}
public bool IsInMap(int2 xy) { return IsInMap(xy.X, xy.Y); }
public bool IsInMap(CPos xy) { return IsInMap(xy.X, xy.Y); }
public bool IsInMap(int x, int y) { return Bounds.Contains(x,y); }
static T[,] ResizeArray<T>(T[,] ts, T t, int width, int height)

View File

@@ -39,15 +39,15 @@ namespace OpenRA
public readonly Actor Subject;
public readonly bool Queued;
public Actor TargetActor;
public int2 TargetLocation;
public CPos TargetLocation;
public string TargetString;
public int2 ExtraLocation;
public CPos ExtraLocation;
public bool IsImmediate;
public Player Player { get { return Subject.Owner; } }
Order(string orderString, Actor subject,
Actor targetActor, int2 targetLocation, string targetString, bool queued, int2 extraLocation)
Actor targetActor, CPos targetLocation, string targetString, bool queued, CPos extraLocation)
{
this.OrderString = orderString;
this.Subject = subject;
@@ -60,10 +60,10 @@ namespace OpenRA
// For scripting special powers
public Order()
: this(null, null, null, int2.Zero, null, false, int2.Zero) { }
: this(null, null, null, CPos.Zero, null, false, CPos.Zero) { }
public Order(string orderString, Actor subject, bool queued)
: this(orderString, subject, null, int2.Zero, null, queued, int2.Zero) { }
: this(orderString, subject, null, CPos.Zero, null, queued, CPos.Zero) { }
public Order(string orderstring, Order order)
: this(orderstring, order.Subject, order.TargetActor, order.TargetLocation,
@@ -98,21 +98,21 @@ namespace OpenRA
OrderFields fields = 0;
if (TargetActor != null) fields |= OrderFields.TargetActor;
if (TargetLocation != int2.Zero) fields |= OrderFields.TargetLocation;
if (TargetLocation != CPos.Zero) fields |= OrderFields.TargetLocation;
if (TargetString != null) fields |= OrderFields.TargetString;
if (Queued) fields |= OrderFields.Queued;
if (ExtraLocation != int2.Zero) fields |= OrderFields.ExtraLocation;
if (ExtraLocation != CPos.Zero) fields |= OrderFields.ExtraLocation;
w.Write((byte)fields);
if (TargetActor != null)
w.Write(UIntFromActor(TargetActor));
if (TargetLocation != int2.Zero)
w.Write(TargetLocation);
if (TargetLocation != CPos.Zero)
w.Write(TargetLocation.ToInt2());
if (TargetString != null)
w.Write(TargetString);
if (ExtraLocation != int2.Zero)
w.Write(ExtraLocation);
if (ExtraLocation != CPos.Zero)
w.Write(ExtraLocation.ToInt2());
return ret.ToArray();
}
@@ -130,10 +130,10 @@ namespace OpenRA
var flags = (OrderFields)r.ReadByte();
var targetActorId = flags.HasField(OrderFields.TargetActor) ? r.ReadUInt32() : 0xffffffff;
var targetLocation = flags.HasField(OrderFields.TargetLocation) ? r.ReadInt2() : int2.Zero;
var targetLocation = (CPos)( flags.HasField(OrderFields.TargetLocation) ? r.ReadInt2() : int2.Zero );
var targetString = flags.HasField(OrderFields.TargetString) ? r.ReadString() : null;
var queued = flags.HasField(OrderFields.Queued);
var extraLocation = flags.HasField(OrderFields.ExtraLocation) ? r.ReadInt2() : int2.Zero;
var extraLocation = (CPos)(flags.HasField(OrderFields.ExtraLocation) ? r.ReadInt2() : int2.Zero);
Actor subject, targetActor;
if( !TryGetActorFromUInt( world, subjectId, out subject ) || !TryGetActorFromUInt( world, targetActorId, out targetActor ) )
@@ -218,17 +218,17 @@ namespace OpenRA
public static Order StartProduction(Actor subject, string item, int count)
{
return new Order("StartProduction", subject, false) { TargetLocation = new int2(count, 0), TargetString = item };
return new Order("StartProduction", subject, false) { TargetLocation = new CPos(count, 0), TargetString = item };
}
public static Order PauseProduction(Actor subject, string item, bool pause)
{
return new Order("PauseProduction", subject, false) { TargetLocation = new int2(pause ? 1 : 0, 0), TargetString = item };
return new Order("PauseProduction", subject, false) { TargetLocation = new CPos(pause ? 1 : 0, 0), TargetString = item };
}
public static Order CancelProduction(Actor subject, string item, int count)
{
return new Order("CancelProduction", subject, false) { TargetLocation = new int2(count, 0), TargetString = item };
return new Order("CancelProduction", subject, false) { TargetLocation = new CPos(count, 0), TargetString = item };
}
}
}

View File

@@ -78,6 +78,9 @@
<Compile Include="ActorInitializer.cs" />
<Compile Include="ActorMap.cs" />
<Compile Include="ActorReference.cs" />
<Compile Include="PVecInt.cs" />
<Compile Include="PVecFloat.cs" />
<Compile Include="PPos.cs" />
<Compile Include="Download.cs" />
<Compile Include="Effects\DelayedAction.cs" />
<Compile Include="Effects\FlashTarget.cs" />
@@ -114,6 +117,8 @@
<Compile Include="Graphics\WorldRenderer.cs" />
<Compile Include="Group.cs" />
<Compile Include="InputHandler.cs" />
<Compile Include="CVec.cs" />
<Compile Include="CPos.cs" />
<Compile Include="Map.cs" />
<Compile Include="ModData.cs" />
<Compile Include="Network\Connection.cs" />

View File

@@ -48,14 +48,14 @@ namespace OpenRA.Orders
}
public IEnumerable<Order> Order(World world, int2 xy, MouseInput mi)
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
{
if (mi.Button != expectedButton)
world.CancelInputMode();
return OrderInner(world, xy, mi);
}
IEnumerable<Order> OrderInner(World world, int2 xy, MouseInput mi)
IEnumerable<Order> OrderInner(World world, CPos xy, MouseInput mi)
{
if (mi.Button == expectedButton && world.Map.IsInMap(xy))
{
@@ -68,6 +68,6 @@ namespace OpenRA.Orders
public virtual void Tick(World world) { }
public void RenderBeforeWorld(WorldRenderer wr, World world) { }
public void RenderAfterWorld(WorldRenderer wr, World world) { }
public string GetCursor(World world, int2 xy, MouseInput mi) { return world.Map.IsInMap(xy) ? cursor : "generic-blocked"; }
public string GetCursor(World world, CPos xy, MouseInput mi) { return world.Map.IsInMap(xy) ? cursor : "generic-blocked"; }
}
}

View File

@@ -15,10 +15,10 @@ namespace OpenRA
{
public interface IOrderGenerator
{
IEnumerable<Order> Order(World world, int2 xy, MouseInput mi);
IEnumerable<Order> Order(World world, CPos xy, MouseInput mi);
void Tick(World world);
void RenderBeforeWorld(WorldRenderer wr, World world);
void RenderAfterWorld(WorldRenderer wr, World world);
string GetCursor(World world, int2 xy, MouseInput mi);
string GetCursor(World world, CPos xy, MouseInput mi);
}
}

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Orders
{
class UnitOrderGenerator : IOrderGenerator
{
public IEnumerable<Order> Order( World world, int2 xy, MouseInput mi )
public IEnumerable<Order> Order( World world, CPos xy, MouseInput mi )
{
var underCursor = world.FindUnitsAtMouse(mi.Location)
.Where(a => a.HasTrait<ITargetable>())
@@ -45,7 +45,7 @@ namespace OpenRA.Orders
public void RenderBeforeWorld( WorldRenderer wr, World world ) { }
public void RenderAfterWorld( WorldRenderer wr, World world ) { }
public string GetCursor( World world, int2 xy, MouseInput mi )
public string GetCursor(World world, CPos xy, MouseInput mi)
{
bool useSelect = false;
@@ -68,7 +68,7 @@ namespace OpenRA.Orders
return orders[0].cursor ?? ((useSelect) ? "select" : "default");
}
static UnitOrderResult OrderForUnit( Actor self, int2 xy, MouseInput mi, Actor underCursor )
static UnitOrderResult OrderForUnit(Actor self, CPos xy, MouseInput mi, Actor underCursor)
{
if (self.Owner != self.World.LocalPlayer)
return null;

70
OpenRA.Game/PPos.cs Normal file
View File

@@ -0,0 +1,70 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Pixel coordinate position in the world (fine).
/// </summary>
public struct PPos
{
public readonly int X, Y;
public PPos(int x, int y) { X = x; Y = y; }
public static readonly PPos Zero = new PPos(0, 0);
public static explicit operator PPos(int2 a) { return new PPos(a.X, a.Y); }
public static explicit operator PVecInt(PPos a) { return new PVecInt(a.X, a.Y); }
public static explicit operator PVecFloat(PPos a) { return new PVecFloat(a.X, a.Y); }
public static PPos operator +(PPos a, PVecInt b) { return new PPos(a.X + b.X, a.Y + b.Y); }
public static PVecInt operator -(PPos a, PPos b) { return new PVecInt(a.X - b.X, a.Y - b.Y); }
public static PPos operator -(PPos a, PVecInt b) { return new PPos(a.X - b.X, a.Y - b.Y); }
public static bool operator ==(PPos me, PPos other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(PPos me, PPos other) { return !(me == other); }
public static PPos Max(PPos a, PPos b) { return new PPos(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static PPos Min(PPos a, PPos b) { return new PPos(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static PPos Lerp(PPos a, PPos b, int mul, int div)
{
return a + ((PVecInt)(b - a) * mul / div);
}
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public CPos ToCPos() { return new CPos((int)(1f / Game.CellSize * X), (int)(1f / Game.CellSize * Y)); }
public PPos Clamp(Rectangle r)
{
return new PPos(Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top)));
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
PPos o = (PPos)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
}

97
OpenRA.Game/PVecFloat.cs Normal file
View File

@@ -0,0 +1,97 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Pixel coordinate vector (fine; float)
/// </summary>
public struct PVecFloat
{
public readonly float X, Y;
public PVecFloat(float x, float y) { X = x; Y = y; }
public PVecFloat(Size p) { X = p.Width; Y = p.Height; }
public static readonly PVecFloat Zero = new PVecFloat(0, 0);
public static explicit operator PVecInt(PVecFloat a) { return new PVecInt((int)a.X, (int)a.Y); }
public static explicit operator PVecFloat(float2 a) { return new PVecFloat(a.X, a.Y); }
public static PVecFloat operator +(PVecFloat a, PVecFloat b) { return new PVecFloat(a.X + b.X, a.Y + b.Y); }
public static PVecFloat operator -(PVecFloat a, PVecFloat b) { return new PVecFloat(a.X - b.X, a.Y - b.Y); }
public static PVecFloat operator *(float a, PVecFloat b) { return new PVecFloat(a * b.X, a * b.Y); }
public static PVecFloat operator *(PVecFloat b, float a) { return new PVecFloat(a * b.X, a * b.Y); }
public static PVecFloat operator /(PVecFloat a, float b) { return new PVecFloat(a.X / b, a.Y / b); }
public static PVecFloat operator -(PVecFloat a) { return new PVecFloat(-a.X, -a.Y); }
public static bool operator ==(PVecFloat me, PVecFloat other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(PVecFloat me, PVecFloat other) { return !(me == other); }
public static PVecFloat Max(PVecFloat a, PVecFloat b) { return new PVecFloat(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static PVecFloat Min(PVecFloat a, PVecFloat b) { return new PVecFloat(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static float Dot(PVecFloat a, PVecFloat b) { return a.X * b.X + a.Y * b.Y; }
public static PVecFloat FromAngle(float a) { return new PVecFloat((float)Math.Sin(a), (float)Math.Cos(a)); }
public static PVecFloat Lerp(PVecFloat a, PVecFloat b, float t)
{
return new PVecFloat(
float2.Lerp(a.X, b.X, t),
float2.Lerp(a.Y, b.Y, t)
);
}
public static PVecFloat Lerp(PVecFloat a, PVecFloat b, PVecFloat t)
{
return new PVecFloat(
float2.Lerp(a.X, b.X, t.X),
float2.Lerp(a.Y, b.Y, t.Y)
);
}
public PVecFloat Sign() { return new PVecFloat(Math.Sign(X), Math.Sign(Y)); }
public PVecFloat Abs() { return new PVecFloat(Math.Abs(X), Math.Abs(Y)); }
public PVecFloat Round() { return new PVecFloat((float)Math.Round(X), (float)Math.Round(Y)); }
public float LengthSquared { get { return X * X + Y * Y; } }
public float Length { get { return (float)Math.Sqrt(LengthSquared); } }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2((int)X, (int)Y); }
static float Constrain(float x, float a, float b) { return x < a ? a : x > b ? b : x; }
public PVecFloat Constrain(PVecFloat min, PVecFloat max)
{
return new PVecFloat(
Constrain(X, min.X, max.X),
Constrain(Y, min.Y, max.Y)
);
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
PVecFloat o = (PVecFloat)obj;
return o == this;
}
public override string ToString() { return "({0},{1})".F(X, Y); }
}
}

79
OpenRA.Game/PVecInt.cs Normal file
View File

@@ -0,0 +1,79 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Pixel coordinate vector (fine; integer)
/// </summary>
public struct PVecInt
{
public readonly int X, Y;
public PVecInt(int x, int y) { X = x; Y = y; }
public PVecInt(Size p) { X = p.Width; Y = p.Height; }
public static readonly PVecInt Zero = new PVecInt(0, 0);
public static PVecInt OneCell { get { return new PVecInt(Game.CellSize, Game.CellSize); } }
public static implicit operator PVecFloat(PVecInt a) { return new PVecFloat((float)a.X, (float)a.Y); }
public static explicit operator PVecInt(int2 a) { return new PVecInt(a.X, a.Y); }
public static PVecInt FromRadius(int r) { return new PVecInt(r, r); }
public static PVecInt operator +(PVecInt a, PVecInt b) { return new PVecInt(a.X + b.X, a.Y + b.Y); }
public static PVecInt operator -(PVecInt a, PVecInt b) { return new PVecInt(a.X - b.X, a.Y - b.Y); }
public static PVecInt operator *(int a, PVecInt b) { return new PVecInt(a * b.X, a * b.Y); }
public static PVecInt operator *(PVecInt b, int a) { return new PVecInt(a * b.X, a * b.Y); }
public static PVecInt operator /(PVecInt a, int b) { return new PVecInt(a.X / b, a.Y / b); }
public static PVecInt operator -(PVecInt a) { return new PVecInt(-a.X, -a.Y); }
public static bool operator ==(PVecInt me, PVecInt other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(PVecInt me, PVecInt other) { return !(me == other); }
public static PVecInt Max(PVecInt a, PVecInt b) { return new PVecInt(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static PVecInt Min(PVecInt a, PVecInt b) { return new PVecInt(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static int Dot(PVecInt a, PVecInt b) { return a.X * b.X + a.Y * b.Y; }
public PVecInt Sign() { return new PVecInt(Math.Sign(X), Math.Sign(Y)); }
public PVecInt Abs() { return new PVecInt(Math.Abs(X), Math.Abs(Y)); }
public int LengthSquared { get { return X * X + Y * Y; } }
public int Length { get { return (int)Math.Sqrt(LengthSquared); } }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public PVecInt Clamp(Rectangle r)
{
return new PVecInt(
Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top))
);
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
PVecInt o = (PVecInt)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
}

View File

@@ -64,7 +64,7 @@ namespace OpenRA
public static void SetListenerPosition(float2 position) { soundEngine.SetListenerPosition(position); }
static ISound Play(Player player, string name, bool headRelative, float2 pos, float volumeModifier)
static ISound Play(Player player, string name, bool headRelative, PPos pos, float volumeModifier)
{
if (player != null && player != player.World.LocalPlayer)
return null;
@@ -72,16 +72,16 @@ namespace OpenRA
return null;
return soundEngine.Play2D(sounds[name],
false, headRelative, pos,
false, headRelative, pos.ToFloat2(),
InternalSoundVolume * volumeModifier);
}
public static ISound Play(string name) { return Play(null, name, true, float2.Zero, 1); }
public static ISound Play(string name, float2 pos) { return Play(null, name, false, pos, 1); }
public static ISound Play(string name, float volumeModifier) { return Play(null, name, true, float2.Zero, volumeModifier); }
public static ISound Play(string name, float2 pos, float volumeModifier) { return Play(null, name, false, pos, volumeModifier); }
public static ISound PlayToPlayer(Player player, string name) { return Play( player, name, true, float2.Zero, 1); }
public static ISound PlayToPlayer(Player player, string name, float2 pos) { return Play(player, name, false, pos, 1); }
public static ISound Play(string name) { return Play(null, name, true, PPos.Zero, 1); }
public static ISound Play(string name, PPos pos) { return Play(null, name, false, pos, 1); }
public static ISound Play(string name, float volumeModifier) { return Play(null, name, true, PPos.Zero, volumeModifier); }
public static ISound Play(string name, PPos pos, float volumeModifier) { return Play(null, name, false, pos, volumeModifier); }
public static ISound PlayToPlayer(Player player, string name) { return Play(player, name, true, PPos.Zero, 1); }
public static ISound PlayToPlayer(Player player, string name, PPos pos) { return Play(player, name, false, pos, 1); }
public static void PlayVideo(byte[] raw)
{

View File

@@ -50,6 +50,26 @@ namespace OpenRA
il.EmitCall(OpCodes.Call, ((Func<int2, int>)hash_int2).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(CPos))
{
il.EmitCall(OpCodes.Call, ((Func<CPos, int>)hash_CPos).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(CVec))
{
il.EmitCall(OpCodes.Call, ((Func<CVec, int>)hash_CVec).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(PPos))
{
il.EmitCall(OpCodes.Call, ((Func<PPos, int>)hash_PPos).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(PVecInt))
{
il.EmitCall(OpCodes.Call, ((Func<PVecInt, int>)hash_PVecInt).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(TypeDictionary))
{
il.EmitCall(OpCodes.Call, ((Func<TypeDictionary, int>)hash_tdict).Method, null);
@@ -110,6 +130,26 @@ namespace OpenRA
return ( ( i2.X * 5 ) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_CPos( CPos i2 )
{
return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_CVec( CVec i2 )
{
return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_PPos( PPos i2 )
{
return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_PVecInt( PVecInt i2 )
{
return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_tdict( TypeDictionary d )
{
int ret = 0;

View File

@@ -52,12 +52,12 @@ namespace OpenRA.Traits
return;
var move = self.TraitOrDefault<IMove>();
var origin = move != null ? self.CenterLocation - new int2(0, move.Altitude) : self.CenterLocation;
var origin = (move != null ? self.CenterLocation - new PVecInt(0, move.Altitude) : self.CenterLocation).ToFloat2();
var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(origin, target.CenterLocation, c, c);
DrawTargetMarker(wlr, target.CenterLocation);
wlr.DrawLine(origin, target.CenterLocation.ToFloat2(), c, c);
DrawTargetMarker(wlr, target.CenterLocation.ToFloat2());
DrawTargetMarker(wlr, origin);
}

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Traits
class RevealsShroud : ITick
{
RevealsShroudInfo Info;
int2 previousLocation;
CPos previousLocation;
public RevealsShroud(RevealsShroudInfo info)
{

View File

@@ -146,12 +146,12 @@ namespace OpenRA.Traits
{
var alt = new float2(0, -mobile.Altitude);
var targets = activity.GetTargets(self);
var start = self.CenterLocation + alt;
var start = self.CenterLocation.ToFloat2() + alt;
var c = Color.Green;
var wlr = Game.Renderer.WorldLineRenderer;
foreach (var step in targets.Select(p => p.CenterLocation))
foreach (var step in targets.Select(p => p.CenterLocation.ToFloat2()))
{
var stp = step + alt;
wlr.DrawLine(stp + new float2(-1, -1), stp + new float2(-1, 1), c, c);

View File

@@ -16,7 +16,7 @@ namespace OpenRA.Traits
Actor actor;
Player owner;
int2 pos;
PPos pos;
bool valid;
public static Target FromActor(Actor a)
@@ -28,8 +28,8 @@ namespace OpenRA.Traits
owner = (a != null) ? a.Owner : null
};
}
public static Target FromPos(int2 p) { return new Target { pos = p, valid = true }; }
public static Target FromCell(int2 c) { return new Target { pos = Util.CenterOfCell(c), valid = true }; }
public static Target FromPos(PPos p) { return new Target { pos = p, valid = true }; }
public static Target FromCell(CPos c) { return new Target { pos = Util.CenterOfCell(c), valid = true }; }
public static Target FromOrder(Order o)
{
return o.TargetActor != null
@@ -40,8 +40,8 @@ namespace OpenRA.Traits
public static readonly Target None = new Target();
public bool IsValid { get { return valid && (actor == null || (actor.IsInWorld && actor.Owner == owner)); } }
public int2 PxPosition { get { return IsActor ? actor.Trait<IHasLocation>().PxPosition : pos; } }
public int2 CenterLocation { get { return PxPosition; } }
public PPos PxPosition { get { return IsActor ? actor.Trait<IHasLocation>().PxPosition : pos; } }
public PPos CenterLocation { get { return PxPosition; } }
public Actor Actor { get { return IsActor ? actor : null; } }
public bool IsActor { get { return actor != null && !actor.Destroyed; } }

View File

@@ -47,7 +47,7 @@ namespace OpenRA.Traits
string OrderID { get; }
int OrderPriority { get; }
bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueue, ref string cursor);
bool CanTargetLocation(Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceQueue, ref string cursor);
bool CanTargetLocation(Actor self, CPos location, List<Actor> actorsAtLocation, bool forceAttack, bool forceQueue, ref string cursor);
bool IsQueued { get; }
}
@@ -60,7 +60,7 @@ namespace OpenRA.Traits
public interface INotifyKilled { void Killed(Actor self, AttackInfo e); }
public interface INotifyAppliedDamage { void AppliedDamage(Actor self, Actor damaged, AttackInfo e); }
public interface INotifyBuildComplete { void BuildingComplete(Actor self); }
public interface INotifyProduction { void UnitProduced(Actor self, Actor other, int2 exit); }
public interface INotifyProduction { void UnitProduced(Actor self, Actor other, CPos exit); }
public interface INotifyCapture { void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner); }
public interface INotifyOtherCaptured { void OnActorCaptured(Actor self, Actor captured, Actor captor, Player oldOwner, Player newOwner); }
public interface IAcceptSpy { void OnInfiltrate(Actor self, Actor spy); }
@@ -79,23 +79,23 @@ namespace OpenRA.Traits
public interface IRadarSignature
{
IEnumerable<int2> RadarSignatureCells(Actor self);
IEnumerable<CPos> RadarSignatureCells(Actor self);
Color RadarSignatureColor(Actor self);
}
public interface IVisibilityModifier { bool IsVisible(Actor self); }
public interface IRadarColorModifier { Color RadarColorOverride(Actor self); }
public interface IHasLocation { int2 PxPosition { get; } }
public interface IHasLocation { PPos PxPosition { get; } }
public interface IOccupySpace : IHasLocation
{
int2 TopLeft { get; }
IEnumerable<Pair<int2, SubCell>> OccupiedCells();
CPos TopLeft { get; }
IEnumerable<Pair<CPos, SubCell>> OccupiedCells();
}
public static class IOccupySpaceExts
{
public static int2 NearestCellTo(this IOccupySpace ios, int2 other)
public static CPos NearestCellTo(this IOccupySpace ios, CPos other)
{
var nearest = ios.TopLeft;
var nearestDistance = int.MaxValue;
@@ -125,10 +125,10 @@ namespace OpenRA.Traits
public interface ITeleportable : IHasLocation /* crap name! */
{
bool CanEnterCell(int2 location);
void SetPosition(Actor self, int2 cell);
void SetPxPosition(Actor self, int2 px);
void AdjustPxPosition(Actor self, int2 px); /* works like SetPxPosition, but visual only */
bool CanEnterCell(CPos location);
void SetPosition(Actor self, CPos cell);
void SetPxPosition(Actor self, PPos px);
void AdjustPxPosition(Actor self, PPos px); /* works like SetPxPosition, but visual only */
}
public interface IMove : ITeleportable { int Altitude { get; set; } }
@@ -212,7 +212,7 @@ namespace OpenRA.Traits
public interface ITargetable
{
string[] TargetTypes { get; }
IEnumerable<int2> TargetableCells(Actor self);
IEnumerable<CPos> TargetableCells(Actor self);
bool TargetableBy(Actor self, Actor byActor);
}

View File

@@ -30,6 +30,16 @@ namespace OpenRA.Traits
return ( facing - rot ) & 0xFF;
}
public static int GetFacing(PVecInt d, int currentFacing)
{
return GetFacing(d.ToInt2(), currentFacing);
}
public static int GetFacing(CVec d, int currentFacing)
{
return GetFacing(d.ToInt2(), currentFacing);
}
public static int GetFacing( int2 d, int currentFacing )
{
if (d == int2.Zero)
@@ -80,14 +90,14 @@ namespace OpenRA.Traits
ecc * (cosAngle * v.Y - sinAngle * v.X));
}
public static int2 CenterOfCell(int2 loc)
public static PPos CenterOfCell(CPos loc)
{
return new int2( Game.CellSize / 2, Game.CellSize / 2 ) + Game.CellSize * loc;
return loc.ToPPos() + new PVecInt(Game.CellSize / 2, Game.CellSize / 2);
}
public static int2 BetweenCells(int2 from, int2 to)
public static PPos BetweenCells(CPos from, CPos to)
{
return int2.Lerp( CenterOfCell( from ), CenterOfCell( to ), 1, 2 );
return PPos.Lerp(CenterOfCell(from), CenterOfCell(to), 1, 2);
}
public static int2 AsInt2(this int[] xs) { return new int2(xs[0], xs[1]); }
@@ -120,6 +130,7 @@ namespace OpenRA.Traits
public static Color ArrayToColor(int[] x) { return Color.FromArgb(x[0], x[1], x[2]); }
[Obsolete("Use ToCPos() method", true)]
public static int2 CellContaining(float2 pos) { return (1f / Game.CellSize * pos).ToInt2(); }
/* pretty crap */
@@ -134,39 +145,39 @@ namespace OpenRA.Traits
}
}
static IEnumerable<int2> Neighbours(int2 c, bool allowDiagonal)
static IEnumerable<CPos> Neighbours(CPos c, bool allowDiagonal)
{
yield return c;
yield return new int2(c.X - 1, c.Y);
yield return new int2(c.X + 1, c.Y);
yield return new int2(c.X, c.Y - 1);
yield return new int2(c.X, c.Y + 1);
yield return new CPos(c.X - 1, c.Y);
yield return new CPos(c.X + 1, c.Y);
yield return new CPos(c.X, c.Y - 1);
yield return new CPos(c.X, c.Y + 1);
if (allowDiagonal)
{
yield return new int2(c.X - 1, c.Y - 1);
yield return new int2(c.X + 1, c.Y - 1);
yield return new int2(c.X - 1, c.Y + 1);
yield return new int2(c.X + 1, c.Y + 1);
yield return new CPos(c.X - 1, c.Y - 1);
yield return new CPos(c.X + 1, c.Y - 1);
yield return new CPos(c.X - 1, c.Y + 1);
yield return new CPos(c.X + 1, c.Y + 1);
}
}
public static IEnumerable<int2> ExpandFootprint(IEnumerable<int2> cells, bool allowDiagonal)
public static IEnumerable<CPos> ExpandFootprint(IEnumerable<CPos> cells, bool allowDiagonal)
{
var result = new Dictionary<int2, bool>();
var result = new Dictionary<CPos, bool>();
foreach (var c in cells.SelectMany(c => Neighbours(c, allowDiagonal)))
result[c] = true;
return result.Keys;
}
public static IEnumerable<int2> AdjacentCells( Target target )
public static IEnumerable<CPos> AdjacentCells(Target target)
{
var cells = target.IsActor
? target.Actor.OccupiesSpace.OccupiedCells().Select(c => c.First).ToArray()
: new int2[] {};
: new CPos[] {};
if (cells.Length == 0)
cells = new [] { Util.CellContaining(target.CenterLocation) };
cells = new CPos[] { target.CenterLocation.ToCPos() };
return Util.ExpandFootprint(cells, true);
}

View File

@@ -20,16 +20,16 @@ namespace OpenRA.Traits
class Waypoint : IOccupySpace, ISync
{
[Sync] int2 location;
[Sync] CPos location;
public Waypoint(ActorInitializer init)
{
this.location = init.Get<LocationInit,int2>();
this.location = init.Get<LocationInit, CPos>();
}
public int2 TopLeft { get { return location; } }
public CPos TopLeft { get { return location; } }
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { yield break; }
public int2 PxPosition { get { return Util.CenterOfCell( location ); } }
public IEnumerable<Pair<CPos, SubCell>> OccupiedCells() { yield break; }
public PPos PxPosition { get { return Util.CenterOfCell(location); } }
}
}

View File

@@ -39,13 +39,13 @@ namespace OpenRA.Traits
for (int x = clip.Left; x < clip.Right; x++)
for (int y = clip.Top; y < clip.Bottom; y++)
{
if (!world.LocalShroud.IsExplored(new int2(x, y)))
if (!world.LocalShroud.IsExplored(new CPos(x, y)))
continue;
var c = content[x, y];
if (c.image != null)
c.image[c.density].DrawAt(
Game.CellSize * new int2(x, y),
new CPos(x, y).ToPPos().ToFloat2(),
c.type.info.PaletteIndex);
}
}
@@ -70,7 +70,7 @@ namespace OpenRA.Traits
if (type == null)
continue;
if (!AllowResourceAt(type, new int2(x,y)))
if (!AllowResourceAt(type, new CPos(x,y)))
continue;
content[x, y].type = type;
@@ -86,7 +86,7 @@ namespace OpenRA.Traits
}
}
public bool AllowResourceAt(ResourceType rt, int2 a)
public bool AllowResourceAt(ResourceType rt, CPos a)
{
if (!world.Map.IsInMap(a.X, a.Y)) return false;
if (!rt.info.AllowedTerrainTypes.Contains(world.GetTerrainInfo(a).Type)) return false;
@@ -136,7 +136,7 @@ namespace OpenRA.Traits
public bool IsFull(int i, int j) { return content[i, j].density == content[i, j].image.Length - 1; }
public ResourceType Harvest(int2 p)
public ResourceType Harvest(CPos p)
{
var type = content[p.X,p.Y].type;
if (type == null) return null;
@@ -150,7 +150,7 @@ namespace OpenRA.Traits
return type;
}
public void Destroy(int2 p)
public void Destroy(CPos p)
{
// Don't break other users of CustomTerrain if there are no resources
if (content[p.X, p.Y].type == null)
@@ -162,7 +162,7 @@ namespace OpenRA.Traits
world.Map.CustomTerrain[p.X, p.Y] = null;
}
public ResourceType GetResource(int2 p) { return content[p.X, p.Y].type; }
public ResourceType GetResource(CPos p) { return content[p.X, p.Y].type; }
public struct CellContents
{

View File

@@ -54,22 +54,22 @@ namespace OpenRA.Traits
// cache of positions that were added, so no matter what crazy trait code does, it
// can't make us invalid.
class ActorVisibility { public int range; public int2[] vis; }
class ActorVisibility { public int range; public CPos[] vis; }
Dictionary<Actor, ActorVisibility> vis = new Dictionary<Actor, ActorVisibility>();
static IEnumerable<int2> FindVisibleTiles(World world, int2 a, int r)
static IEnumerable<CPos> FindVisibleTiles(World world, CPos a, int r)
{
var min = a - new int2(r, r);
var max = a + new int2(r, r);
if (min.X < world.Map.Bounds.Left - 1) min.X = world.Map.Bounds.Left - 1;
if (min.Y < world.Map.Bounds.Top - 1) min.Y = world.Map.Bounds.Top - 1;
if (max.X > world.Map.Bounds.Right) max.X = world.Map.Bounds.Right;
if (max.Y > world.Map.Bounds.Bottom) max.Y = world.Map.Bounds.Bottom;
var min = a - new CVec(r, r);
var max = a + new CVec(r, r);
if (min.X < world.Map.Bounds.Left - 1) min = new CPos(world.Map.Bounds.Left - 1, min.Y);
if (min.Y < world.Map.Bounds.Top - 1) min = new CPos(min.X, world.Map.Bounds.Top - 1);
if (max.X > world.Map.Bounds.Right) max = new CPos(world.Map.Bounds.Right, max.Y);
if (max.Y > world.Map.Bounds.Bottom) max = new CPos(max.X, world.Map.Bounds.Bottom);
for (var j = min.Y; j <= max.Y; j++)
for (var i = min.X; i <= max.X; i++)
if (r * r >= (new int2(i, j) - a).LengthSquared)
yield return new int2(i, j);
if (r * r >= (new CPos(i, j) - a).LengthSquared)
yield return new CPos(i, j);
}
void AddActor(Actor a)
@@ -148,7 +148,7 @@ namespace OpenRA.Traits
AddActor(a);
}
public static IEnumerable<int2> GetVisOrigins(Actor a)
public static IEnumerable<CPos> GetVisOrigins(Actor a)
{
var ios = a.OccupiesSpace;
if (ios != null)
@@ -157,7 +157,7 @@ namespace OpenRA.Traits
if (cells.Any()) return cells.Select(c => c.First);
}
return new[] { a.CenterLocation / Game.CellSize };
return new[] { a.CenterLocation.ToCPos() };
}
void RemoveActor(Actor a)
@@ -183,7 +183,7 @@ namespace OpenRA.Traits
RemoveActor(a); AddActor(a);
}
public void Explore(World world, int2 center, int range)
public void Explore(World world, CPos center, int range)
{
foreach (var q in FindVisibleTiles(world, center, range))
exploredCells[q.X, q.Y] = true;
@@ -216,7 +216,7 @@ namespace OpenRA.Traits
Dirty();
}
public bool IsExplored(int2 xy) { return IsExplored(xy.X, xy.Y); }
public bool IsExplored(CPos xy) { return IsExplored(xy.X, xy.Y); }
public bool IsExplored(int x, int y)
{
if (!map.IsInMap(x, y))
@@ -228,7 +228,7 @@ namespace OpenRA.Traits
return exploredCells[x,y];
}
public bool IsVisible(int2 xy) { return IsVisible(xy.X, xy.Y); }
public bool IsVisible(CPos xy) { return IsVisible(xy.X, xy.Y); }
public bool IsVisible(int x, int y)
{
if (Disabled)

View File

@@ -75,7 +75,7 @@ namespace OpenRA.Traits
yield return a;
}
public IEnumerable<Actor> ActorsInBox(int2 a, int2 b)
public IEnumerable<Actor> ActorsInBox(PPos a, PPos b)
{
var r = Rectangle.FromLTRB(a.X, a.Y, b.X, b.Y);

View File

@@ -42,12 +42,12 @@ namespace OpenRA.Widgets
return;
}
Game.Renderer.WorldLineRenderer.DrawRect(selbox.Value.First, selbox.Value.Second, Color.White);
Game.Renderer.WorldLineRenderer.DrawRect(selbox.Value.First.ToFloat2(), selbox.Value.Second.ToFloat2(), Color.White);
foreach (var u in SelectActorsInBox(world, selbox.Value.First, selbox.Value.Second, _ => true))
worldRenderer.DrawRollover(u);
}
int2 dragStart, dragEnd;
PPos dragStart, dragEnd;
public override bool HandleMouseInput(MouseInput mi)
{
@@ -101,7 +101,7 @@ namespace OpenRA.Widgets
return true;
}
public Pair<int2, int2>? SelectionBox
public Pair<PPos, PPos>? SelectionBox
{
get
{
@@ -110,11 +110,11 @@ namespace OpenRA.Widgets
}
}
public void ApplyOrders(World world, int2 xy, MouseInput mi)
public void ApplyOrders(World world, PPos xy, MouseInput mi)
{
if (world.OrderGenerator == null) return;
var orders = world.OrderGenerator.Order(world, Traits.Util.CellContaining(xy), mi).ToArray();
var orders = world.OrderGenerator.Order(world, xy.ToCPos(), mi).ToArray();
orders.Do( o => world.IssueOrder( o ) );
world.PlayVoiceForOrders(orders);
@@ -135,7 +135,7 @@ namespace OpenRA.Widgets
};
// TODO: fix this up.
return world.OrderGenerator.GetCursor( world, Game.viewport.ViewToWorld(mi).ToInt2(), mi );
return world.OrderGenerator.GetCursor( world, Game.viewport.ViewToWorld(mi), mi );
} );
}
@@ -161,7 +161,7 @@ namespace OpenRA.Widgets
}
static readonly Actor[] NoActors = {};
IEnumerable<Actor> SelectActorsInBox(World world, int2 a, int2 b, Func<Actor, bool> cond)
IEnumerable<Actor> SelectActorsInBox(World world, PPos a, PPos b, Func<Actor, bool> cond)
{
return world.FindUnits(a, b)
.Where( x => x.HasTrait<Selectable>() && world.LocalShroud.IsVisible(x) && cond(x) )

View File

@@ -27,24 +27,24 @@ namespace OpenRA
return FindUnits(world, loc, loc).Where(a => world.LocalShroud.IsVisible(a));
}
public static IEnumerable<Actor> FindUnits(this World world, int2 a, int2 b)
public static IEnumerable<Actor> FindUnits(this World world, PPos a, PPos b)
{
var u = float2.Min(a, b).ToInt2();
var v = float2.Max(a, b).ToInt2();
var u = PPos.Min(a, b);
var v = PPos.Max(a, b);
return world.WorldActor.Trait<SpatialBins>().ActorsInBox(u,v);
}
public static Actor ClosestTo( this IEnumerable<Actor> actors, int2 px )
public static Actor ClosestTo(this IEnumerable<Actor> actors, PPos px)
{
return actors.OrderBy( a => (a.CenterLocation - px).LengthSquared ).FirstOrDefault();
}
public static IEnumerable<Actor> FindUnitsInCircle(this World world, int2 a, int r)
public static IEnumerable<Actor> FindUnitsInCircle(this World world, PPos a, int r)
{
using (new PerfSample("FindUnitsInCircle"))
{
var min = a - new int2(r, r);
var max = a + new int2(r, r);
var min = a - PVecInt.FromRadius(r);
var max = a + PVecInt.FromRadius(r);
var actors = world.FindUnits(min, max);
@@ -56,48 +56,48 @@ namespace OpenRA
}
}
public static IEnumerable<int2> FindTilesInCircle(this World world, int2 a, int r)
public static IEnumerable<CPos> FindTilesInCircle(this World world, CPos a, int r)
{
var min = world.ClampToWorld(a - new int2(r, r));
var max = world.ClampToWorld(a + new int2(r, r));
var min = world.ClampToWorld(a - new CVec(r, r));
var max = world.ClampToWorld(a + new CVec(r, r));
for (var j = min.Y; j <= max.Y; j++)
for (var i = min.X; i <= max.X; i++)
if (r * r >= (new int2(i, j) - a).LengthSquared)
yield return new int2(i, j);
if (r * r >= (new CPos(i, j) - a).LengthSquared)
yield return new CPos(i, j);
}
public static string GetTerrainType(this World world, int2 cell)
public static string GetTerrainType(this World world, CPos cell)
{
var custom = world.Map.CustomTerrain[cell.X, cell.Y];
return custom != null ? custom : world.TileSet.GetTerrainType(world.Map.MapTiles.Value[cell.X, cell.Y]);
}
public static TerrainTypeInfo GetTerrainInfo(this World world, int2 cell)
public static TerrainTypeInfo GetTerrainInfo(this World world, CPos cell)
{
return world.TileSet.Terrain[world.GetTerrainType(cell)];
}
public static int2 ClampToWorld( this World world, int2 xy )
public static CPos ClampToWorld(this World world, CPos xy)
{
var r = world.Map.Bounds;
return xy.Clamp(new Rectangle(r.X,r.Y,r.Width-1, r.Height-1));
}
public static int2 ChooseRandomEdgeCell(this World w)
public static CPos ChooseRandomEdgeCell(this World w)
{
var isX = w.SharedRandom.Next(2) == 0;
var edge = w.SharedRandom.Next(2) == 0;
return new int2(
return new CPos(
isX ? w.SharedRandom.Next(w.Map.Bounds.Left, w.Map.Bounds.Right)
: (edge ? w.Map.Bounds.Left : w.Map.Bounds.Right),
!isX ? w.SharedRandom.Next(w.Map.Bounds.Top, w.Map.Bounds.Bottom)
: (edge ? w.Map.Bounds.Top : w.Map.Bounds.Bottom));
}
public static int2 ChooseRandomCell(this World w, Thirdparty.Random r)
public static CPos ChooseRandomCell(this World w, Thirdparty.Random r)
{
return new int2(
return new CPos(
r.Next(w.Map.Bounds.Left, w.Map.Bounds.Right),
r.Next(w.Map.Bounds.Top, w.Map.Bounds.Bottom));
}