Refactored IQuantizeBodyOrientation implementation

Moved BodyOrientation and related interfaces from Game to Mods.Common.
Introduced QuantizeFacingsFromSequence trait.
With*Body render traits no longer implement IQuantizeBodyOrientation
themselves.
This commit is contained in:
reaperrr
2015-07-13 01:36:42 +02:00
parent 1d3cfcf378
commit 006e66a3c3
17 changed files with 83 additions and 67 deletions

View File

@@ -12,6 +12,7 @@ using System.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Graphics;
using OpenRA.Mods.Common.Traits;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Effects

View File

@@ -398,6 +398,8 @@
<Compile Include="Traits\ProvidesRadar.cs" />
<Compile Include="Traits\ProximityCaptor.cs" />
<Compile Include="Traits\ProximityCapturable.cs" />
<Compile Include="Traits\BodyOrientation.cs" />
<Compile Include="Traits\QuantizeFacingsFromSequence.cs" />
<Compile Include="Traits\RadarColorFromTerrain.cs" />
<Compile Include="Traits\Render\AutoSelectionSize.cs" />
<Compile Include="Traits\Render\Hovers.cs" />

View File

@@ -0,0 +1,99 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 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.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class BodyOrientationInfo : ITraitInfo, IBodyOrientationInfo
{
[Desc("Number of facings for gameplay calculations. -1 indicates auto-detection from another trait")]
public readonly int QuantizedFacings = -1;
[Desc("Camera pitch for rotation calculations")]
public readonly WAngle CameraPitch = WAngle.FromDegrees(40);
[Desc("Fudge the coordinate system angles like the early games.")]
public readonly bool UseClassicPerspectiveFudge = true;
public WVec LocalToWorld(WVec vec)
{
// Rotate by 90 degrees
if (!UseClassicPerspectiveFudge)
return new WVec(vec.Y, -vec.X, vec.Z);
// RA's 2d perspective doesn't correspond to an orthonormal 3D
// coordinate system, so fudge the y axis to make things look good
return new WVec(vec.Y, -CameraPitch.Sin() * vec.X / 1024, vec.Z);
}
public WRot QuantizeOrientation(WRot orientation, int facings)
{
// Quantization disabled
if (facings == 0)
return orientation;
// Map yaw to the closest facing
var facing = Util.QuantizeFacing(orientation.Yaw.Angle / 4, facings) * (256 / facings);
// Roll and pitch are always zero if yaw is quantized
return new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facing));
}
public object Create(ActorInitializer init) { return new BodyOrientation(init, this); }
}
public class BodyOrientation : IBodyOrientation
{
readonly BodyOrientationInfo info;
readonly Lazy<int> quantizedFacings;
[Sync] public int QuantizedFacings { get { return quantizedFacings.Value; } }
public BodyOrientation(ActorInitializer init, BodyOrientationInfo info)
{
this.info = info;
var self = init.Self;
var faction = init.Contains<FactionInit>() ? init.Get<FactionInit, string>() : self.Owner.Faction.InternalName;
quantizedFacings = Exts.Lazy(() =>
{
// Override value is set
if (info.QuantizedFacings >= 0)
return info.QuantizedFacings;
var qboi = self.Info.Traits.GetOrDefault<IQuantizeBodyOrientationInfo>();
var isb = self.HasTrait<ISpriteBody>();
// If a sprite actor has neither custom QuantizedFacings nor a trait implementing IQuantizeBodyOrientationInfo, throw
if (qboi == null && isb)
throw new InvalidOperationException("Actor" + self.Info.Name + "has a sprite body but no facing quantization."
+ " Either add the QuantizeFacingsFromSequence trait or set custom QuantizedFacings on BodyOrientation.");
return qboi.QuantizedBodyFacings(self.Info, self.World.Map.SequenceProvider, faction);
});
}
public WAngle CameraPitch { get { return info.CameraPitch; } }
public WVec LocalToWorld(WVec vec)
{
return info.LocalToWorld(vec);
}
public WRot QuantizeOrientation(Actor self, WRot orientation)
{
return info.QuantizeOrientation(orientation, quantizedFacings.Value);
}
}
}

View File

@@ -0,0 +1,43 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 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.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Derive facings from sprite body sequence.")]
public class QuantizeFacingsFromSequenceInfo : UpgradableTraitInfo, IQuantizeBodyOrientationInfo, Requires<RenderSpritesInfo>
{
[Desc("Defines sequence to derive facings from."), SequenceReference]
public readonly string Sequence = "idle";
public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string race)
{
if (string.IsNullOrEmpty(Sequence))
throw new InvalidOperationException("Actor " + ai.Name + " is missing sequence to quantize facings from.");
var rsi = ai.Traits.Get<RenderSpritesInfo>();
return sequenceProvider.GetSequence(rsi.GetImage(ai, sequenceProvider, race), Sequence).Facings;
}
public override object Create(ActorInitializer init) { return new QuantizeFacingsFromSequence(this); }
}
public class QuantizeFacingsFromSequence : UpgradableTrait<QuantizeFacingsFromSequenceInfo>
{
public QuantizeFacingsFromSequence(QuantizeFacingsFromSequenceInfo info)
: base(info) { }
}
}

View File

@@ -17,7 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Basic render trait for immobile actors. Deprecated, use RenderSprites + WithSpriteBody instead.")]
public class RenderSimpleInfo : RenderSpritesInfo, IRenderActorPreviewSpritesInfo, IQuantizeBodyOrientationInfo, Requires<IBodyOrientationInfo>
public class RenderSimpleInfo : RenderSpritesInfo, IRenderActorPreviewSpritesInfo, Requires<IBodyOrientationInfo>
{
[SequenceReference] public readonly string Sequence = "idle";
@@ -33,11 +33,6 @@ namespace OpenRA.Mods.Common.Traits
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale);
}
public virtual int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction)
{
return sequenceProvider.GetSequence(GetImage(ai, sequenceProvider, faction), Sequence).Facings;
}
}
public class RenderSimple : RenderSprites, IAutoSelectionSize

View File

@@ -18,7 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Renders crates with both water and land variants.")]
class WithCrateBodyInfo : ITraitInfo, Requires<RenderSpritesInfo>, IQuantizeBodyOrientationInfo, IRenderActorPreviewSpritesInfo
class WithCrateBodyInfo : ITraitInfo, Requires<RenderSpritesInfo>, IRenderActorPreviewSpritesInfo
{
[Desc("Easteregg sequences to use in december.")]
public readonly string[] XmasImages = { };
@@ -35,8 +35,6 @@ namespace OpenRA.Mods.Common.Traits
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), IdleSequence));
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale);
}
public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction) { return 1; }
}
class WithCrateBody : INotifyParachuteLanded

View File

@@ -30,12 +30,6 @@ namespace OpenRA.Mods.Common.Traits
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale);
}
public override int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction)
{
var rsi = ai.Traits.Get<RenderSpritesInfo>();
return sequenceProvider.GetSequence(rsi.GetImage(ai, sequenceProvider, faction), Sequence).Facings;
}
}
public class WithFacingSpriteBody : WithSpriteBody

View File

@@ -16,8 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class WithInfantryBodyInfo : UpgradableTraitInfo, IQuantizeBodyOrientationInfo, IRenderActorPreviewSpritesInfo,
Requires<IMoveInfo>, Requires<RenderSpritesInfo>
public class WithInfantryBodyInfo : UpgradableTraitInfo, IRenderActorPreviewSpritesInfo, Requires<IMoveInfo>, Requires<RenderSpritesInfo>
{
public readonly int MinIdleWaitTicks = 30;
public readonly int MaxIdleWaitTicks = 110;
@@ -40,12 +39,6 @@ namespace OpenRA.Mods.Common.Traits
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), StandSequences.First()));
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale);
}
public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction)
{
var rsi = ai.Traits.Get<RenderSpritesInfo>();
return sequenceProvider.GetSequence(rsi.GetImage(ai, sequenceProvider, faction), StandSequences.First()).Facings;
}
}
public class WithInfantryBody : UpgradableTrait<WithInfantryBodyInfo>, ITick, INotifyAttack, INotifyIdle, INotifyCreated

View File

@@ -17,8 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Default trait for rendering sprite-based actors.")]
public class WithSpriteBodyInfo : UpgradableTraitInfo, IRenderActorPreviewSpritesInfo, IQuantizeBodyOrientationInfo,
Requires<RenderSpritesInfo>
public class WithSpriteBodyInfo : UpgradableTraitInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo>
{
[Desc("Animation to play when the actor is created.")]
[SequenceReference] public readonly string StartSequence = null;
@@ -35,11 +34,6 @@ namespace OpenRA.Mods.Common.Traits
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale);
}
public virtual int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction)
{
return 1;
}
}
public class WithSpriteBody : UpgradableTrait<WithSpriteBodyInfo>, ISpriteBody, INotifyDamageStateChanged

View File

@@ -18,7 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Also returns a default selection size that is calculated automatically from the voxel dimensions.")]
public class WithVoxelBodyInfo : ITraitInfo, IQuantizeBodyOrientationInfo, IRenderActorPreviewVoxelsInfo, Requires<RenderVoxelsInfo>
public class WithVoxelBodyInfo : ITraitInfo, IRenderActorPreviewVoxelsInfo, Requires<RenderVoxelsInfo>
{
public readonly string Sequence = "idle";
@@ -33,8 +33,6 @@ namespace OpenRA.Mods.Common.Traits
() => bodyOrientation,
() => false, () => 0);
}
public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction) { return 0; }
}
public class WithVoxelBody : IAutoSelectionSize

View File

@@ -25,6 +25,25 @@ namespace OpenRA.Mods.Common.Traits
void PlayCustomAnimationBackwards(Actor self, string name, Action after);
}
public interface IBodyOrientation
{
WAngle CameraPitch { get; }
int QuantizedFacings { get; }
WVec LocalToWorld(WVec vec);
WRot QuantizeOrientation(Actor self, WRot orientation);
}
public interface IBodyOrientationInfo : ITraitInfo
{
WVec LocalToWorld(WVec vec);
WRot QuantizeOrientation(WRot orientation, int facings);
}
public interface IQuantizeBodyOrientationInfo : ITraitInfo
{
int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string race);
}
public interface INotifyResourceClaimLost
{
void OnNotifyResourceClaimLost(Actor self, ResourceClaim claim, Actor claimer);