From 0e3a53bec745d39a5991a455c80d38ddeb85eeee Mon Sep 17 00:00:00 2001 From: reaperrr Date: Sun, 10 May 2015 04:47:41 +0200 Subject: [PATCH] Added WithFacingSpriteBody trait. Extracted AutoSelectionSize into its own trait. RenderUnit -> RenderSprites + WithFacingSpriteBody upgrade rule Remove RenderSimple dependencies of ThrowsParticle and WithHarvestAnimation. --- OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 2 + .../Traits/Render/AutoSelectionSize.cs | 31 ++++++++ .../Traits/Render/RenderSprites.cs | 4 +- .../Traits/Render/WithFacingSpriteBody.cs | 46 ++++++++++++ .../Traits/Render/WithHarvestAnimation.cs | 2 +- .../Traits/Render/WithSpriteBody.cs | 72 +++++++++++++------ OpenRA.Mods.Common/Traits/ThrowsParticle.cs | 4 +- .../UtilityCommands/UpgradeRules.cs | 31 ++++++++ 8 files changed, 165 insertions(+), 27 deletions(-) create mode 100644 OpenRA.Mods.Common/Traits/Render/AutoSelectionSize.cs create mode 100644 OpenRA.Mods.Common/Traits/Render/WithFacingSpriteBody.cs diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index f442976916..0feb272ac3 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -364,6 +364,7 @@ + @@ -405,6 +406,7 @@ + diff --git a/OpenRA.Mods.Common/Traits/Render/AutoSelectionSize.cs b/OpenRA.Mods.Common/Traits/Render/AutoSelectionSize.cs new file mode 100644 index 0000000000..ca00a4c077 --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Render/AutoSelectionSize.cs @@ -0,0 +1,31 @@ +#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 OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + public class AutoSelectionSizeInfo : ITraitInfo, Requires + { + public object Create(ActorInitializer init) { return new AutoSelectionSize(this); } + } + + public class AutoSelectionSize : IAutoSelectionSize + { + public AutoSelectionSize(AutoSelectionSizeInfo info) { } + + public int2 SelectionSize(Actor self) + { + var rs = self.Trait(); + return rs.AutoSelectionSize(self); + } + } +} diff --git a/OpenRA.Mods.Common/Traits/Render/RenderSprites.cs b/OpenRA.Mods.Common/Traits/Render/RenderSprites.cs index 06970f8f8f..ac31eaa169 100644 --- a/OpenRA.Mods.Common/Traits/Render/RenderSprites.cs +++ b/OpenRA.Mods.Common/Traits/Render/RenderSprites.cs @@ -236,8 +236,8 @@ namespace OpenRA.Mods.Common.Traits return sequence; } - // Required by RenderSimple - protected int2 AutoSelectionSize(Actor self) + // Required by RenderSimple, WithSpriteBody and WithInfantryBody + public int2 AutoSelectionSize(Actor self) { return anims.Where(b => b.IsVisible && b.Animation.Animation.CurrentSequence != null) diff --git a/OpenRA.Mods.Common/Traits/Render/WithFacingSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithFacingSpriteBody.cs new file mode 100644 index 0000000000..81622ae687 --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Render/WithFacingSpriteBody.cs @@ -0,0 +1,46 @@ +#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 OpenRA.Graphics; +using OpenRA.Mods.Common.Graphics; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + public class WithFacingSpriteBodyInfo : WithSpriteBodyInfo, Requires, Requires + { + public override object Create(ActorInitializer init) { return new WithFacingSpriteBody(init, this); } + + public override IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) + { + var ifacing = init.Actor.Traits.GetOrDefault(); + var facing = ifacing != null ? init.Contains() ? init.Get() : ifacing.GetInitialFacing() : 0; + + var anim = new Animation(init.World, image, () => facing); + anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence)); + + yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); + } + + public override int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string race) + { + var rsi = ai.Traits.Get(); + return sequenceProvider.GetSequence(rsi.GetImage(ai, sequenceProvider, race), Sequence).Facings; + } + } + + public class WithFacingSpriteBody : WithSpriteBody + { + public WithFacingSpriteBody(ActorInitializer init, WithFacingSpriteBodyInfo info) + : base(init, info, RenderSprites.MakeFacingFunc(init.Self)) { } + } +} diff --git a/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs index 22322a1d22..7e03eb43fb 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs @@ -40,7 +40,7 @@ namespace OpenRA.Mods.Common.Traits var rs = self.Trait(); var body = self.Trait(); - anim = new Animation(self.World, rs.GetImage(self), RenderSimple.MakeFacingFunc(self)); + anim = new Animation(self.World, rs.GetImage(self), RenderSprites.MakeFacingFunc(self)); anim.IsDecoration = true; anim.Play(info.Sequence); rs.Add(new AnimationWithOffset(anim, diff --git a/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs index d00cf49ae3..1aa72e50de 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs @@ -9,13 +9,16 @@ #endregion using System; +using System.Collections.Generic; using OpenRA.Graphics; +using OpenRA.Mods.Common.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("Default trait for rendering sprite-based actors.")] - class WithSpriteBodyInfo : UpgradableTraitInfo, ITraitInfo, Requires + public class WithSpriteBodyInfo : UpgradableTraitInfo, ITraitInfo, IRenderActorPreviewSpritesInfo, IQuantizeBodyOrientationInfo, + Requires { [Desc("Animation to play when the actor is created.")] public readonly string StartSequence = null; @@ -23,30 +26,54 @@ namespace OpenRA.Mods.Common.Traits [Desc("Animation to play when the actor is idle.")] public readonly string Sequence = "idle"; - public object Create(ActorInitializer init) { return new WithSpriteBody(init, this); } - } + public virtual object Create(ActorInitializer init) { return new WithSpriteBody(init, this); } - class WithSpriteBody : UpgradableTrait, ISpriteBody - { - readonly Animation body; - readonly WithSpriteBodyInfo info; - - public WithSpriteBody(ActorInitializer init, WithSpriteBodyInfo info) - : base(info) + public virtual IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) { - this.info = info; + var anim = new Animation(init.World, image); + anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence)); - var rs = init.Self.Trait(); - body = new Animation(init.Self.World, rs.GetImage(init.Self)); - PlayCustomAnimation(init.Self, info.StartSequence, () => body.PlayRepeating(info.Sequence)); - rs.Add(new AnimationWithOffset(body, null, () => IsTraitDisabled)); + yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); } - public void PlayCustomAnimation(Actor self, string newAnimation, Action after) + public virtual int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string race) { - body.PlayThen(newAnimation, () => + return 1; + } + } + + public class WithSpriteBody : UpgradableTrait, ISpriteBody + { + public readonly Animation DefaultAnimation; + + public WithSpriteBody(ActorInitializer init, WithSpriteBodyInfo info) + : this(init, info, () => 0) { } + + protected WithSpriteBody(ActorInitializer init, WithSpriteBodyInfo info, Func baseFacing) + : base(info) + { + var rs = init.Self.Trait(); + + DefaultAnimation = new Animation(init.World, rs.GetImage(init.Self), baseFacing); + rs.Add(new AnimationWithOffset(DefaultAnimation, null, () => IsTraitDisabled)); + + if (Info.StartSequence != null) + PlayCustomAnimation(init.Self, Info.StartSequence, + () => DefaultAnimation.PlayRepeating(NormalizeSequence(init.Self, Info.Sequence))); + else + DefaultAnimation.PlayRepeating(NormalizeSequence(init.Self, Info.Sequence)); + } + + public string NormalizeSequence(Actor self, string sequence) + { + return RenderSprites.NormalizeSequence(DefaultAnimation, self.GetDamageState(), sequence); + } + + public void PlayCustomAnimation(Actor self, string name, Action after = null) + { + DefaultAnimation.PlayThen(NormalizeSequence(self, name), () => { - body.Play(info.Sequence); + DefaultAnimation.Play(NormalizeSequence(self, Info.Sequence)); if (after != null) after(); }); @@ -54,14 +81,15 @@ namespace OpenRA.Mods.Common.Traits public void PlayCustomAnimationRepeating(Actor self, string name) { - body.PlayThen(name, () => PlayCustomAnimationRepeating(self, name)); + DefaultAnimation.PlayThen(name, + () => PlayCustomAnimationRepeating(self, name)); } - public void PlayCustomAnimationBackwards(Actor self, string name, Action after) + public void PlayCustomAnimationBackwards(Actor self, string name, Action after = null) { - body.PlayBackwardsThen(name, () => + DefaultAnimation.PlayBackwardsThen(NormalizeSequence(self, name), () => { - body.PlayRepeating(info.Sequence); + DefaultAnimation.PlayRepeating(NormalizeSequence(self, Info.Sequence)); if (after != null) after(); }); diff --git a/OpenRA.Mods.Common/Traits/ThrowsParticle.cs b/OpenRA.Mods.Common/Traits/ThrowsParticle.cs index c9bad3e7a8..3aa7db2d70 100644 --- a/OpenRA.Mods.Common/Traits/ThrowsParticle.cs +++ b/OpenRA.Mods.Common/Traits/ThrowsParticle.cs @@ -13,7 +13,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { - class ThrowsParticleInfo : ITraitInfo, Requires, Requires + class ThrowsParticleInfo : ITraitInfo, Requires, Requires { public readonly string Anim = null; @@ -57,7 +57,7 @@ namespace OpenRA.Mods.Common.Traits public ThrowsParticle(ActorInitializer init, ThrowsParticleInfo info) { var self = init.Self; - var rs = self.Trait(); + var rs = self.Trait(); var body = self.Trait(); // TODO: Carry orientation over from the parent instead of just facing diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index e6f442919f..59fb134a0e 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -1016,6 +1016,37 @@ namespace OpenRA.Mods.Common.UtilityCommands } } + if (engineVersion < 20150528) + { + // Note (stolen from WithInfantryBody upgrade rule): + // These rules are set up to do approximately the right thing for maps, but + // mods need additional manual tweaks. This is the best we can do without having + // much smarter rules parsing, because we currently can't reason about inherited traits. + if (depth == 0) + { + var childKeys = new[] { "Sequence" }; + + var ru = node.Value.Nodes.FirstOrDefault(n => n.Key == "RenderUnit"); + if (ru != null) + { + ru.Key = "WithFacingSpriteBody"; + node.Value.Nodes.Add(new MiniYamlNode("AutoSelectionSize", "")); + + var rsNodes = ru.Value.Nodes.Where(n => !childKeys.Contains(n.Key)).ToList(); + if (rsNodes.Any()) + node.Value.Nodes.Add(new MiniYamlNode("RenderSprites", new MiniYaml("", rsNodes))); + else + node.Value.Nodes.Add(new MiniYamlNode("RenderSprites", "")); + + ru.Value.Nodes.RemoveAll(n => rsNodes.Contains(n)); + } + + var rru = node.Value.Nodes.FirstOrDefault(n => n.Key == "-RenderUnit"); + if (rru != null) + rru.Key = "-WithFacingSpriteBody"; + } + } + UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1); } }