Refactor animation classes.
Specify pause function in constructors of Animation if required, and remove the unused pause function from AnimationWithOffset. Cleanup Animation.cs and reduce code duplication.
This commit is contained in:
@@ -17,36 +17,35 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public class Animation
|
||||
{
|
||||
readonly int defaultTick = 40; // 25 fps == 40 ms
|
||||
public ISpriteSequence CurrentSequence { get; private set; }
|
||||
public bool IsDecoration = false;
|
||||
public Func<bool> Paused;
|
||||
|
||||
readonly Func<int> facingFunc;
|
||||
|
||||
int frame = 0;
|
||||
bool backwards = false;
|
||||
|
||||
string name;
|
||||
|
||||
bool tickAlways;
|
||||
|
||||
public string Name { get { return name; } }
|
||||
public string Name { get; private set; }
|
||||
public bool IsDecoration { get; set; }
|
||||
|
||||
readonly SequenceProvider sequenceProvider;
|
||||
readonly Func<int> facingFunc;
|
||||
readonly Func<bool> paused;
|
||||
|
||||
int frame;
|
||||
bool backwards;
|
||||
bool tickAlways;
|
||||
int timeUntilNextFrame;
|
||||
Action tickFunc = () => { };
|
||||
|
||||
public Animation(World world, string name)
|
||||
: this(world, name, () => 0) { }
|
||||
|
||||
public Animation(World world, string name, Func<int> facingFunc)
|
||||
: this(world.Map.SequenceProvider, name, facingFunc) { }
|
||||
: this(world, name, facingFunc, null) { }
|
||||
|
||||
public Animation(SequenceProvider sequenceProvider, string name, Func<int> facingFunc)
|
||||
public Animation(World world, string name, Func<bool> paused)
|
||||
: this(world, name, () => 0, paused) { }
|
||||
|
||||
public Animation(World world, string name, Func<int> facingFunc, Func<bool> paused)
|
||||
{
|
||||
this.sequenceProvider = sequenceProvider;
|
||||
this.name = name.ToLowerInvariant();
|
||||
this.tickFunc = () => { };
|
||||
sequenceProvider = world.Map.SequenceProvider;
|
||||
Name = name.ToLowerInvariant();
|
||||
this.facingFunc = facingFunc;
|
||||
this.paused = paused;
|
||||
}
|
||||
|
||||
public int CurrentFrame { get { return backwards ? CurrentSequence.Start + CurrentSequence.Length - frame - 1 : frame; } }
|
||||
@@ -76,12 +75,23 @@ namespace OpenRA.Graphics
|
||||
PlayThen(sequenceName, null);
|
||||
}
|
||||
|
||||
int CurrentSequenceTickOrDefault()
|
||||
{
|
||||
const int DefaultTick = 40; // 25 fps == 40 ms
|
||||
return CurrentSequence != null ? CurrentSequence.Tick : DefaultTick;
|
||||
}
|
||||
|
||||
void PlaySequence(string sequenceName)
|
||||
{
|
||||
CurrentSequence = GetSequence(sequenceName);
|
||||
timeUntilNextFrame = CurrentSequenceTickOrDefault();
|
||||
}
|
||||
|
||||
public void PlayRepeating(string sequenceName)
|
||||
{
|
||||
backwards = false;
|
||||
tickAlways = false;
|
||||
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
|
||||
timeUntilNextFrame = CurrentSequence != null ? CurrentSequence.Tick : defaultTick;
|
||||
PlaySequence(sequenceName);
|
||||
|
||||
frame = 0;
|
||||
tickFunc = () =>
|
||||
@@ -97,9 +107,8 @@ namespace OpenRA.Graphics
|
||||
if (!HasSequence(sequenceName))
|
||||
return false;
|
||||
|
||||
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
|
||||
var tick = CurrentSequence != null ? CurrentSequence.Tick : defaultTick;
|
||||
timeUntilNextFrame = Math.Min(tick, timeUntilNextFrame);
|
||||
CurrentSequence = GetSequence(sequenceName);
|
||||
timeUntilNextFrame = Math.Min(CurrentSequenceTickOrDefault(), timeUntilNextFrame);
|
||||
frame %= CurrentSequence.Length;
|
||||
return true;
|
||||
}
|
||||
@@ -108,8 +117,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
backwards = false;
|
||||
tickAlways = false;
|
||||
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
|
||||
timeUntilNextFrame = CurrentSequence != null ? CurrentSequence.Tick : defaultTick;
|
||||
PlaySequence(sequenceName);
|
||||
|
||||
frame = 0;
|
||||
tickFunc = () =>
|
||||
@@ -134,8 +142,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
backwards = false;
|
||||
tickAlways = true;
|
||||
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
|
||||
timeUntilNextFrame = CurrentSequence != null ? CurrentSequence.Tick : defaultTick;
|
||||
PlaySequence(sequenceName);
|
||||
|
||||
frame = func();
|
||||
tickFunc = () => frame = func();
|
||||
@@ -144,8 +151,7 @@ namespace OpenRA.Graphics
|
||||
public void PlayFetchDirection(string sequenceName, Func<int> direction)
|
||||
{
|
||||
tickAlways = false;
|
||||
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
|
||||
timeUntilNextFrame = CurrentSequence != null ? CurrentSequence.Tick : defaultTick;
|
||||
PlaySequence(sequenceName);
|
||||
|
||||
frame = 0;
|
||||
tickFunc = () =>
|
||||
@@ -159,17 +165,12 @@ namespace OpenRA.Graphics
|
||||
};
|
||||
}
|
||||
|
||||
int timeUntilNextFrame;
|
||||
Action tickFunc;
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
if (Paused == null || !Paused())
|
||||
if (paused == null || !paused())
|
||||
Tick(40); // tick one frame
|
||||
}
|
||||
|
||||
public bool HasSequence(string seq) { return sequenceProvider.HasSequence(name, seq); }
|
||||
|
||||
public void Tick(int t)
|
||||
{
|
||||
if (tickAlways)
|
||||
@@ -180,7 +181,7 @@ namespace OpenRA.Graphics
|
||||
while (timeUntilNextFrame <= 0)
|
||||
{
|
||||
tickFunc();
|
||||
timeUntilNextFrame += CurrentSequence != null ? CurrentSequence.Tick : defaultTick;
|
||||
timeUntilNextFrame += CurrentSequenceTickOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,17 +190,19 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
newImage = newImage.ToLowerInvariant();
|
||||
|
||||
if (name != newImage)
|
||||
if (Name != newImage)
|
||||
{
|
||||
name = newImage.ToLowerInvariant();
|
||||
Name = newImage;
|
||||
if (!ReplaceAnim(CurrentSequence.Name))
|
||||
ReplaceAnim(newAnimIfMissing);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasSequence(string seq) { return sequenceProvider.HasSequence(Name, seq); }
|
||||
|
||||
public ISpriteSequence GetSequence(string sequenceName)
|
||||
{
|
||||
return sequenceProvider.GetSequence(name, sequenceName);
|
||||
return sequenceProvider.GetSequence(Name, sequenceName);
|
||||
}
|
||||
|
||||
public string GetRandomExistingSequence(string[] sequences, MersenneTwister random)
|
||||
|
||||
@@ -18,22 +18,20 @@ namespace OpenRA.Graphics
|
||||
public readonly Animation Animation;
|
||||
public readonly Func<WVec> OffsetFunc;
|
||||
public readonly Func<bool> DisableFunc;
|
||||
public readonly Func<bool> Paused;
|
||||
public readonly Func<WPos, int> ZOffset;
|
||||
|
||||
public AnimationWithOffset(Animation a, Func<WVec> offset, Func<bool> disable)
|
||||
: this(a, offset, disable, () => false, null) { }
|
||||
: this(a, offset, disable, null) { }
|
||||
|
||||
public AnimationWithOffset(Animation a, Func<WVec> offset, Func<bool> disable, int zOffset)
|
||||
: this(a, offset, disable, () => false, _ => zOffset) { }
|
||||
: this(a, offset, disable, _ => zOffset) { }
|
||||
|
||||
public AnimationWithOffset(Animation a, Func<WVec> offset, Func<bool> disable, Func<bool> pause, Func<WPos, int> zOffset)
|
||||
public AnimationWithOffset(Animation a, Func<WVec> offset, Func<bool> disable, Func<WPos, int> zOffset)
|
||||
{
|
||||
this.Animation = a;
|
||||
this.Animation.Paused = pause;
|
||||
this.OffsetFunc = offset;
|
||||
this.DisableFunc = disable;
|
||||
this.ZOffset = zOffset;
|
||||
Animation = a;
|
||||
OffsetFunc = offset;
|
||||
DisableFunc = disable;
|
||||
ZOffset = zOffset;
|
||||
}
|
||||
|
||||
public IEnumerable<IRenderable> Render(Actor self, WorldRenderer wr, PaletteReference pal, float scale)
|
||||
@@ -47,7 +45,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
public static implicit operator AnimationWithOffset(Animation a)
|
||||
{
|
||||
return new AnimationWithOffset(a, null, null, null, null);
|
||||
return new AnimationWithOffset(a, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,7 +120,7 @@ namespace OpenRA.Mods.Common.Effects
|
||||
|
||||
if (!string.IsNullOrEmpty(info.Image))
|
||||
{
|
||||
anim = new Animation(world, info.Image, GetEffectiveFacing);
|
||||
anim = new Animation(world, info.Image, new Func<int>(GetEffectiveFacing));
|
||||
anim.PlayRepeating(info.Sequences.Random(world.SharedRandom));
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,7 @@ namespace OpenRA.Mods.Common.Effects
|
||||
this.building = building;
|
||||
|
||||
rb = building.Trait<RepairableBuilding>();
|
||||
anim = new Animation(building.World, rb.Info.IndicatorImage);
|
||||
anim.Paused = () => !rb.RepairActive || rb.IsTraitDisabled;
|
||||
anim = new Animation(building.World, rb.Info.IndicatorImage, () => !rb.RepairActive || rb.IsTraitDisabled);
|
||||
|
||||
CycleRepairer();
|
||||
}
|
||||
|
||||
@@ -165,7 +165,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var muzzleFlash = new AnimationWithOffset(muzzleAnim,
|
||||
() => PortOffset(self, port),
|
||||
() => false,
|
||||
() => false,
|
||||
p => RenderUtils.ZOffsetFromCenter(self, p, 1024));
|
||||
|
||||
muzzles.Add(muzzleFlash);
|
||||
|
||||
@@ -79,8 +79,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
this.info = info;
|
||||
this.self = self;
|
||||
image = info.Image ?? self.Info.Name;
|
||||
anim = new Animation(self.World, image);
|
||||
anim.Paused = () => self.World.Paused;
|
||||
anim = new Animation(self.World, image, () => self.World.Paused);
|
||||
anim.PlayRepeating(info.Sequence);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
rs.Add(new AnimationWithOffset(anim,
|
||||
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
|
||||
() => !visible,
|
||||
() => false,
|
||||
p => ZOffsetFromCenter(self, p, 0)), info.Palette);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var body = self.Trait<BodyOrientation>();
|
||||
|
||||
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>(); // always render instantly for units
|
||||
overlay = new Animation(self.World, rs.GetImage(self));
|
||||
overlay = new Animation(self.World, rs.GetImage(self),
|
||||
() => (info.PauseOnLowPower && self.IsDisabled()) || !buildComplete);
|
||||
if (info.StartSequence != null)
|
||||
overlay.PlayThen(RenderSprites.NormalizeSequence(overlay, self.GetDamageState(), info.StartSequence),
|
||||
() => overlay.PlayRepeating(RenderSprites.NormalizeSequence(overlay, self.GetDamageState(), info.Sequence)));
|
||||
@@ -79,7 +80,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var anim = new AnimationWithOffset(overlay,
|
||||
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
|
||||
() => IsTraitDisabled || !buildComplete,
|
||||
() => (info.PauseOnLowPower && self.IsDisabled()) || !buildComplete,
|
||||
p => RenderUtils.ZOffsetFromCenter(self, p, 1));
|
||||
|
||||
rs.Add(anim, info.Palette, info.IsPlayerPalette);
|
||||
|
||||
@@ -69,7 +69,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
new AnimationWithOffset(muzzleFlash,
|
||||
() => info.IgnoreOffset ? WVec.Zero : armClosure.MuzzleOffset(self, barrel),
|
||||
() => IsTraitDisabled || !visible[barrel],
|
||||
() => false,
|
||||
p => RenderUtils.ZOffsetFromCenter(self, p, 2)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
anim = new AnimationWithOffset(overlay,
|
||||
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
|
||||
() => IsTraitDisabled && !renderProlonged,
|
||||
() => false,
|
||||
p => RenderUtils.ZOffsetFromCenter(self, p, 1));
|
||||
|
||||
var rs = self.Trait<RenderSprites>();
|
||||
|
||||
@@ -47,13 +47,13 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var body = self.Trait<BodyOrientation>();
|
||||
|
||||
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>(); // always render instantly for units
|
||||
overlay = new Animation(self.World, rs.GetImage(self));
|
||||
overlay = new Animation(self.World, rs.GetImage(self),
|
||||
() => info.PauseOnLowPower && self.IsDisabled());
|
||||
overlay.PlayThen(info.Sequence, () => visible = false);
|
||||
|
||||
var anim = new AnimationWithOffset(overlay,
|
||||
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
|
||||
() => !visible || !buildComplete,
|
||||
() => info.PauseOnLowPower && self.IsDisabled(),
|
||||
p => RenderUtils.ZOffsetFromCenter(self, p, 1));
|
||||
|
||||
rs.Add(anim, info.Palette, info.IsPlayerPalette);
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
DefaultAnimation = new Animation(self.World, rs.GetImage(self), () => turreted.TurretFacing);
|
||||
DefaultAnimation.PlayRepeating(NormalizeSequence(self, Info.Sequence));
|
||||
rs.Add(new AnimationWithOffset(
|
||||
DefaultAnimation, () => BarrelOffset(), () => IsTraitDisabled, () => false, p => RenderUtils.ZOffsetFromCenter(self, p, 0)));
|
||||
DefaultAnimation, () => BarrelOffset(), () => IsTraitDisabled, p => RenderUtils.ZOffsetFromCenter(self, p, 0)));
|
||||
|
||||
// Restrict turret facings to match the sprite
|
||||
turreted.QuantizedFacings = DefaultAnimation.CurrentSequence.Facings;
|
||||
|
||||
@@ -51,7 +51,12 @@ namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
var rs = init.Self.Trait<RenderSprites>();
|
||||
|
||||
DefaultAnimation = new Animation(init.World, rs.GetImage(init.Self), baseFacing);
|
||||
Func<bool> paused = null;
|
||||
if (info.PauseAnimationWhenDisabled)
|
||||
paused = () => init.Self.IsDisabled() &&
|
||||
DefaultAnimation.CurrentSequence.Name == NormalizeSequence(init.Self, Info.Sequence);
|
||||
|
||||
DefaultAnimation = new Animation(init.World, rs.GetImage(init.Self), baseFacing, paused);
|
||||
rs.Add(new AnimationWithOffset(DefaultAnimation, null, () => IsTraitDisabled));
|
||||
|
||||
if (info.StartSequence != null)
|
||||
@@ -59,10 +64,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
() => PlayCustomAnimationRepeating(init.Self, info.Sequence));
|
||||
else
|
||||
DefaultAnimation.PlayRepeating(NormalizeSequence(init.Self, info.Sequence));
|
||||
|
||||
if (info.PauseAnimationWhenDisabled)
|
||||
DefaultAnimation.Paused = () =>
|
||||
init.Self.IsDisabled() && DefaultAnimation.CurrentSequence.Name == NormalizeSequence(init.Self, Info.Sequence);
|
||||
}
|
||||
|
||||
public string NormalizeSequence(Actor self, string sequence)
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
rotorAnim.PlayRepeating(info.Sequence);
|
||||
rs.Add(new AnimationWithOffset(rotorAnim,
|
||||
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
|
||||
null, () => false, p => ZOffsetFromCenter(self, p, 1)));
|
||||
null, p => ZOffsetFromCenter(self, p, 1)));
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
DefaultAnimation = new Animation(self.World, rs.GetImage(self), () => t.TurretFacing);
|
||||
DefaultAnimation.PlayRepeating(NormalizeSequence(self, info.Sequence));
|
||||
rs.Add(new AnimationWithOffset(
|
||||
DefaultAnimation, () => TurretOffset(self), () => IsTraitDisabled, () => false, p => RenderUtils.ZOffsetFromCenter(self, p, 1)));
|
||||
DefaultAnimation, () => TurretOffset(self), () => IsTraitDisabled, p => RenderUtils.ZOffsetFromCenter(self, p, 1)));
|
||||
|
||||
// Restrict turret facings to match the sprite
|
||||
t.QuantizedFacings = DefaultAnimation.CurrentSequence.Facings;
|
||||
|
||||
Reference in New Issue
Block a user