From a6f3db0a45712bab547bb83477eaefd86755832f Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 29 Dec 2022 14:31:26 +1300 Subject: [PATCH] Allow all sprites to use interpolated facings. --- OpenRA.Game/Graphics/SequenceProvider.cs | 1 - .../Graphics/DefaultSpriteSequence.cs | 21 +++++++------------ .../Traits/QuantizeFacingsFromSequence.cs | 7 +++---- OpenRA.Mods.Common/Util.cs | 9 ++++---- 4 files changed, 16 insertions(+), 22 deletions(-) diff --git a/OpenRA.Game/Graphics/SequenceProvider.cs b/OpenRA.Game/Graphics/SequenceProvider.cs index 6a02507f98..19fd095d0b 100644 --- a/OpenRA.Game/Graphics/SequenceProvider.cs +++ b/OpenRA.Game/Graphics/SequenceProvider.cs @@ -24,7 +24,6 @@ namespace OpenRA.Graphics string Name { get; } int Length { get; } int Facings { get; } - int InterpolatedFacings { get; } int Tick { get; } int ZOffset { get; } int ShadowZOffset { get; } diff --git a/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs b/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs index 9a4116016c..1c48d7b8ad 100644 --- a/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs +++ b/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs @@ -85,7 +85,6 @@ namespace OpenRA.Mods.Common.Graphics string ISpriteSequence.Name => throw exception; int ISpriteSequence.Length => throw exception; int ISpriteSequence.Facings => throw exception; - int ISpriteSequence.InterpolatedFacings => throw exception; int ISpriteSequence.Tick => throw exception; int ISpriteSequence.ZOffset => throw exception; int ISpriteSequence.ShadowZOffset => throw exception; @@ -144,13 +143,12 @@ namespace OpenRA.Mods.Common.Graphics [Desc("The amount of directions the unit faces. Use negative values to rotate counter-clockwise.")] static readonly SpriteSequenceField Facings = new SpriteSequenceField(nameof(Facings), 1); - int ISpriteSequence.Facings => facings; + int ISpriteSequence.Facings => interpolatedFacings ?? facings; protected int facings; [Desc("The amount of directions the unit faces. Use negative values to rotate counter-clockwise.")] - static readonly SpriteSequenceField InterpolatedFacings = new SpriteSequenceField(nameof(InterpolatedFacings), 1); - int ISpriteSequence.InterpolatedFacings => interpolatedFacings; - protected int interpolatedFacings; + static readonly SpriteSequenceField InterpolatedFacings = new SpriteSequenceField(nameof(InterpolatedFacings), null); + protected int? interpolatedFacings; [Desc("Time (in milliseconds at default game speed) to wait until playing the next frame in the animation.")] static readonly SpriteSequenceField Tick = new SpriteSequenceField(nameof(Tick), 40); @@ -282,10 +280,9 @@ namespace OpenRA.Mods.Common.Graphics var zRamp = LoadField(ZRamp, data, defaults); facings = LoadField(Facings, data, defaults); - interpolatedFacings = LoadField(InterpolatedFacings.Key, -1, data, defaults); - if (interpolatedFacings != -1 && (interpolatedFacings <= 1 || interpolatedFacings <= Math.Abs(facings) || interpolatedFacings > 1024 - || !Exts.IsPowerOf2(interpolatedFacings))) - throw new YamlException($"InterpolatedFacings must be greater than Facings, within the range of 2 to 1024, and a power of 2."); + interpolatedFacings = LoadField(InterpolatedFacings, data, defaults); + if (interpolatedFacings != null && (interpolatedFacings <= 1 || interpolatedFacings <= Math.Abs(facings) || interpolatedFacings > 1024 || !Exts.IsPowerOf2(interpolatedFacings.Value))) + throw new YamlException($"Sequence {image}.{sequence}: InterpolatedFacings must be greater than Facings, within the range of 2 to 1024, and a power of 2."); if (facings < 0) { @@ -508,10 +505,8 @@ namespace OpenRA.Mods.Common.Graphics public (Sprite, WAngle) GetSpriteWithRotation(int frame, WAngle facing) { var rotation = WAngle.Zero; - - // Note: Error checking is not done here as it is done on load - if (interpolatedFacings != -1) - rotation = Util.GetInterpolatedFacing(facing, Math.Abs(facings), interpolatedFacings); + if (interpolatedFacings != null) + rotation = Util.GetInterpolatedFacingRotation(facing, Math.Abs(facings), interpolatedFacings.Value); return (GetSprite(start, frame, facing), rotation); } diff --git a/OpenRA.Mods.Common/Traits/QuantizeFacingsFromSequence.cs b/OpenRA.Mods.Common/Traits/QuantizeFacingsFromSequence.cs index d4dcb7a46d..0d45d00f85 100644 --- a/OpenRA.Mods.Common/Traits/QuantizeFacingsFromSequence.cs +++ b/OpenRA.Mods.Common/Traits/QuantizeFacingsFromSequence.cs @@ -23,14 +23,13 @@ namespace OpenRA.Mods.Common.Traits [Desc("Defines sequence to derive facings from.")] public readonly string Sequence = "idle"; - public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string race) + public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequences, string faction) { if (string.IsNullOrEmpty(Sequence)) - throw new InvalidOperationException("Actor " + ai.Name + " is missing sequence to quantize facings from."); + throw new InvalidOperationException($"Actor {ai.Name} is missing sequence to quantize facings from."); var rsi = ai.TraitInfo(); - var seq = sequenceProvider.GetSequence(rsi.GetImage(ai, race), Sequence); - return seq.InterpolatedFacings == -1 ? seq.Facings : seq.InterpolatedFacings; + return sequences.GetSequence(rsi.GetImage(ai, faction), Sequence).Facings; } public override object Create(ActorInitializer init) { return new QuantizeFacingsFromSequence(this); } diff --git a/OpenRA.Mods.Common/Util.cs b/OpenRA.Mods.Common/Util.cs index 501df13546..fca31ffcb3 100644 --- a/OpenRA.Mods.Common/Util.cs +++ b/OpenRA.Mods.Common/Util.cs @@ -84,16 +84,17 @@ namespace OpenRA.Mods.Common return new WAngle(a % step - step / 2); } - public static WAngle GetInterpolatedFacing(WAngle facing, int facings, int interpolatedFacings) + /// Returns the angle that the closest facing sprite should be rotated by to achieve the closest interpolated facing. + public static WAngle GetInterpolatedFacingRotation(WAngle facing, int facings, int interpolatedFacings) { var step = 1024 / interpolatedFacings; return new WAngle(AngleDiffToStep(facing, facings).Angle / step * step); } - /// Rounds the given facing value to the nearest quantized step. - public static WAngle QuantizeFacing(WAngle facing, int steps) + /// Rounds the given facing value to the nearest quantized facing. + public static WAngle QuantizeFacing(WAngle facing, int facings) { - return new WAngle(IndexFacing(facing, steps) * (1024 / steps)); + return new WAngle(IndexFacing(facing, facings) * (1024 / facings)); } /// Wraps an arbitrary integer facing value into the range 0 - 255