From ef2f909f6523a6083ab5b634c8cbb54bde6c1178 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 20 Jul 2014 17:29:47 +1200 Subject: [PATCH] Reorganize IBodyOrientation. --- OpenRA.Game/Traits/BodyOrientation.cs | 66 +++++++++++++------- OpenRA.Game/Traits/TraitsInterfaces.cs | 11 +++- OpenRA.Mods.Cnc/RenderGunboat.cs | 9 ++- OpenRA.Mods.RA/Render/RenderBuilding.cs | 2 - OpenRA.Mods.RA/Render/RenderInfantry.cs | 9 ++- OpenRA.Mods.RA/Render/RenderSimple.cs | 8 ++- OpenRA.Mods.RA/Render/WithVoxelBody.cs | 4 +- OpenRA.Mods.TS/Render/WithVoxelUnloadBody.cs | 4 +- OpenRA.Mods.TS/Render/WithVoxelWalkerBody.cs | 4 +- 9 files changed, 80 insertions(+), 37 deletions(-) mode change 100755 => 100644 OpenRA.Mods.RA/Render/WithVoxelBody.cs diff --git a/OpenRA.Game/Traits/BodyOrientation.cs b/OpenRA.Game/Traits/BodyOrientation.cs index 061112e2e3..37d506930d 100755 --- a/OpenRA.Game/Traits/BodyOrientation.cs +++ b/OpenRA.Game/Traits/BodyOrientation.cs @@ -8,56 +8,76 @@ */ #endregion +using System; + namespace OpenRA.Traits { public class BodyOrientationInfo : ITraitInfo, IBodyOrientationInfo { - [Desc("Number of facings for gameplay calculations. -1 indiciates auto-detection from sequence")] + [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); + + public WVec LocalToWorld(WVec vec) + { + // 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.self, this); } } public class BodyOrientation : IBodyOrientation { - [Sync] public int QuantizedFacings { get; private set; } - BodyOrientationInfo info; + readonly BodyOrientationInfo info; + readonly Lazy quantizedFacings; + + [Sync] public int QuantizedFacings { get { return quantizedFacings.Value; } } public BodyOrientation(Actor self, BodyOrientationInfo info) { this.info = info; - if (info.QuantizedFacings > 0) - QuantizedFacings = info.QuantizedFacings; + + quantizedFacings = Exts.Lazy(() => + { + // Override value is set + if (info.QuantizedFacings >= 0) + return info.QuantizedFacings; + + var qboi = self.Info.Traits.GetOrDefault(); + if (qboi == null) + throw new InvalidOperationException("Actor type '" + self.Info.Name + "' does not define a quantized body orientation."); + + return qboi.QuantizedBodyFacings(self.World.Map.SequenceProvider, self.Info); + }); } public WAngle CameraPitch { get { return info.CameraPitch; } } public WVec LocalToWorld(WVec vec) { - // 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, -info.CameraPitch.Sin()*vec.X/1024, vec.Z); + return info.LocalToWorld(vec); } public WRot QuantizeOrientation(Actor self, WRot orientation) { - // Quantization disabled - if (QuantizedFacings == 0) - return orientation; - - // Map yaw to the closest facing - var facing = Util.QuantizeFacing(orientation.Yaw.Angle / 4, QuantizedFacings) * (256 / QuantizedFacings); - - // Roll and pitch are always zero if yaw is quantized - return new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facing)); - } - - public void SetAutodetectedFacings(int facings) - { - if (info.QuantizedFacings < 0) - QuantizedFacings = facings; + return info.QuantizeOrientation(orientation, quantizedFacings.Value); } } } diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 990e85eb2b..712f79acea 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -227,15 +227,22 @@ namespace OpenRA.Traits public interface IRenderShroud { void RenderShroud(WorldRenderer wr, Shroud shroud); } public interface IPostRenderSelection { IEnumerable RenderAfterWorld(WorldRenderer wr); } + public interface IBodyOrientation { WAngle CameraPitch { get; } int QuantizedFacings { get; } WVec LocalToWorld(WVec vec); WRot QuantizeOrientation(Actor self, WRot orientation); - void SetAutodetectedFacings(int facings); } - public interface IBodyOrientationInfo : ITraitInfo { } + + public interface IBodyOrientationInfo : ITraitInfo + { + WVec LocalToWorld(WVec vec); + WRot QuantizeOrientation(WRot orientation, int facings); + } + + public interface IQuantizeBodyOrientationInfo { int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai); } public interface ITargetableInfo { diff --git a/OpenRA.Mods.Cnc/RenderGunboat.cs b/OpenRA.Mods.Cnc/RenderGunboat.cs index 29159b846e..a1e825531b 100644 --- a/OpenRA.Mods.Cnc/RenderGunboat.cs +++ b/OpenRA.Mods.Cnc/RenderGunboat.cs @@ -14,7 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { - class RenderGunboatInfo : RenderSpritesInfo, Requires + class RenderGunboatInfo : RenderSpritesInfo, IQuantizeBodyOrientationInfo, Requires { [Desc("Turreted 'Turret' key to display")] public readonly string Turret = "primary"; @@ -25,6 +25,11 @@ namespace OpenRA.Mods.RA.Render public readonly string WakeRightSequence = "wake-right"; public override object Create(ActorInitializer init) { return new RenderGunboat(init.self, this); } + + public int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai) + { + return 2; + } } class RenderGunboat : RenderSprites, INotifyDamageStateChanged @@ -54,8 +59,6 @@ namespace OpenRA.Mods.RA.Render var rightWake = new Animation(self.World, name); rightWake.Play(info.WakeRightSequence); Add(info.WakeRightSequence, new AnimationWithOffset(rightWake, null, () => facing.Facing <= 128, -87)); - - self.Trait().SetAutodetectedFacings(2); } public void DamageStateChanged(Actor self, AttackInfo e) diff --git a/OpenRA.Mods.RA/Render/RenderBuilding.cs b/OpenRA.Mods.RA/Render/RenderBuilding.cs index 416866cc84..c5973152f2 100755 --- a/OpenRA.Mods.RA/Render/RenderBuilding.cs +++ b/OpenRA.Mods.RA/Render/RenderBuilding.cs @@ -49,8 +49,6 @@ namespace OpenRA.Mods.RA.Render this.info = info; DefaultAnimation.PlayRepeating(NormalizeSequence(self, "idle")); - - self.Trait().SetAutodetectedFacings(DefaultAnimation.CurrentSequence.Facings); } public virtual void BuildingComplete(Actor self) diff --git a/OpenRA.Mods.RA/Render/RenderInfantry.cs b/OpenRA.Mods.RA/Render/RenderInfantry.cs index cbf5cc21a4..2539f198ae 100644 --- a/OpenRA.Mods.RA/Render/RenderInfantry.cs +++ b/OpenRA.Mods.RA/Render/RenderInfantry.cs @@ -8,7 +8,9 @@ */ #endregion +using System.Linq; using OpenRA.Mods.RA.Effects; +using OpenRA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Render @@ -25,6 +27,11 @@ namespace OpenRA.Mods.RA.Render public readonly string[] StandAnimations = { "stand" }; public override object Create(ActorInitializer init) { return new RenderInfantry(init.self, this); } + + public override int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai) + { + return sequenceProvider.GetSequence(RenderSprites.GetImage(ai), StandAnimations.First()).Facings; + } } public class RenderInfantry : RenderSimple, INotifyAttack, INotifyKilled, INotifyIdle @@ -64,8 +71,6 @@ namespace OpenRA.Mods.RA.Render DefaultAnimation.PlayFetchIndex(NormalizeInfantrySequence(self, info.StandAnimations.Random(Game.CosmeticRandom)), () => 0); State = AnimationState.Waiting; move = self.Trait(); - - self.Trait().SetAutodetectedFacings(DefaultAnimation.CurrentSequence.Facings); } public void Attacking(Actor self, Target target) diff --git a/OpenRA.Mods.RA/Render/RenderSimple.cs b/OpenRA.Mods.RA/Render/RenderSimple.cs index 14a640692e..080253dd93 100644 --- a/OpenRA.Mods.RA/Render/RenderSimple.cs +++ b/OpenRA.Mods.RA/Render/RenderSimple.cs @@ -15,7 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { - public class RenderSimpleInfo : RenderSpritesInfo, ILegacyEditorRenderInfo, Requires + public class RenderSimpleInfo : RenderSpritesInfo, IQuantizeBodyOrientationInfo, ILegacyEditorRenderInfo, Requires { public override object Create(ActorInitializer init) { return new RenderSimple(init.self); } @@ -27,6 +27,11 @@ namespace OpenRA.Mods.RA.Render return anim.Render(WPos.Zero, WVec.Zero, 0, pr, Scale); } + public virtual int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai) + { + return sequenceProvider.GetSequence(RenderSprites.GetImage(ai), "idle").Facings; + } + public string EditorPalette { get { return Palette; } } public string EditorImage(ActorInfo actor) { return RenderSimple.GetImage(actor); } } @@ -46,7 +51,6 @@ namespace OpenRA.Mods.RA.Render : this(self, MakeFacingFunc(self)) { DefaultAnimation.PlayRepeating(NormalizeSequence(self, "idle")); - self.Trait().SetAutodetectedFacings(DefaultAnimation.CurrentSequence.Facings); } public int2 SelectionSize(Actor self) { return AutoSelectionSize(self); } diff --git a/OpenRA.Mods.RA/Render/WithVoxelBody.cs b/OpenRA.Mods.RA/Render/WithVoxelBody.cs old mode 100755 new mode 100644 index af28a54528..8814ebefaf --- a/OpenRA.Mods.RA/Render/WithVoxelBody.cs +++ b/OpenRA.Mods.RA/Render/WithVoxelBody.cs @@ -16,11 +16,13 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { [Desc("Also returns a default selection size that is calculated automatically from the voxel dimensions.")] - public class WithVoxelBodyInfo : ITraitInfo, Requires + public class WithVoxelBodyInfo : ITraitInfo, IQuantizeBodyOrientationInfo, Requires { public readonly string Sequence = "idle"; public object Create(ActorInitializer init) { return new WithVoxelBody(init.self, this); } + + public int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai) { return 0; } } public class WithVoxelBody : IAutoSelectionSize diff --git a/OpenRA.Mods.TS/Render/WithVoxelUnloadBody.cs b/OpenRA.Mods.TS/Render/WithVoxelUnloadBody.cs index 5109661dec..2f00fd2a66 100755 --- a/OpenRA.Mods.TS/Render/WithVoxelUnloadBody.cs +++ b/OpenRA.Mods.TS/Render/WithVoxelUnloadBody.cs @@ -16,7 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { - public class WithVoxelUnloadBodyInfo : ITraitInfo, Requires + public class WithVoxelUnloadBodyInfo : ITraitInfo, IQuantizeBodyOrientationInfo, Requires { [Desc("Voxel sequence name to use when docked to a refinery.")] public readonly string UnloadSequence = "unload"; @@ -25,6 +25,8 @@ namespace OpenRA.Mods.RA.Render public readonly string IdleSequence = "idle"; public object Create(ActorInitializer init) { return new WithVoxelUnloadBody(init.self, this); } + + public int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai) { return 0; } } public class WithVoxelUnloadBody : IAutoSelectionSize diff --git a/OpenRA.Mods.TS/Render/WithVoxelWalkerBody.cs b/OpenRA.Mods.TS/Render/WithVoxelWalkerBody.cs index 90e8373c6e..8210f7f8d9 100644 --- a/OpenRA.Mods.TS/Render/WithVoxelWalkerBody.cs +++ b/OpenRA.Mods.TS/Render/WithVoxelWalkerBody.cs @@ -15,10 +15,12 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Render { - public class WithVoxelWalkerBodyInfo : ITraitInfo, Requires, Requires + public class WithVoxelWalkerBodyInfo : ITraitInfo, IQuantizeBodyOrientationInfo, Requires, Requires { public readonly int TickRate = 5; public object Create(ActorInitializer init) { return new WithVoxelWalkerBody(init.self, this); } + + public int QuantizedBodyFacings(SequenceProvider sequenceProvider, ActorInfo ai) { return 0; } } public class WithVoxelWalkerBody : IAutoSelectionSize, ITick