From 0975102e922426263990669c46ef0a5c0b41066a Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 31 Jan 2021 23:24:12 +0000 Subject: [PATCH] Add Alpha support to sequences. Alpha can specify a single value for the sequence or values for each frame in the sequence. AlphaFade: True can be specified to linearly fade to transparent over the length of the animation. --- OpenRA.Game/Graphics/Animation.cs | 8 ++- OpenRA.Game/Graphics/SequenceProvider.cs | 1 + OpenRA.Game/Graphics/SpriteRenderable.cs | 6 -- OpenRA.Game/Graphics/UISpriteRenderable.cs | 8 ++- .../Graphics/TeslaZapRenderable.cs | 2 +- OpenRA.Mods.Cnc/Traits/Minelayer.cs | 66 ++++++++++++++----- .../Traits/SupportPowers/ChronoshiftPower.cs | 40 ++++++++--- .../Graphics/DefaultSpriteSequence.cs | 24 +++++++ OpenRA.Mods.Common/Traits/Buildings/Bridge.cs | 3 +- .../FootprintPlaceBuildingPreview.cs | 28 +++++--- .../Traits/Render/DrawLineToTarget.cs | 2 +- .../Traits/Render/WithAmmoPipsDecoration.cs | 2 +- .../Traits/Render/WithCargoPipsDecoration.cs | 2 +- .../Traits/Render/WithDecoration.cs | 2 +- .../Render/WithHarvesterPipsDecoration.cs | 2 +- .../Traits/Render/WithParachute.cs | 3 +- .../WithResourceStoragePipsDecoration.cs | 2 +- .../WithSpriteControlGroupDecoration.cs | 2 +- .../GrantExternalConditionPower.cs | 8 ++- .../Traits/World/EditorCursorLayer.cs | 3 +- .../Traits/World/EditorSelectionLayer.cs | 22 ++++--- .../Traits/World/TerrainRenderer.cs | 2 +- .../D2kActorPreviewPlaceBuildingPreview.cs | 29 ++++---- 23 files changed, 189 insertions(+), 78 deletions(-) diff --git a/OpenRA.Game/Graphics/Animation.cs b/OpenRA.Game/Graphics/Animation.cs index d93be68cc8..bf4f682286 100644 --- a/OpenRA.Game/Graphics/Animation.cs +++ b/OpenRA.Game/Graphics/Animation.cs @@ -55,12 +55,13 @@ namespace OpenRA.Graphics public IRenderable[] Render(WPos pos, WVec offset, int zOffset, PaletteReference palette) { var tintModifiers = CurrentSequence.IgnoreWorldTint ? TintModifiers.IgnoreWorldTint : TintModifiers.None; - var imageRenderable = new SpriteRenderable(Image, pos, offset, CurrentSequence.ZOffset + zOffset, palette, CurrentSequence.Scale, IsDecoration, tintModifiers); + var alpha = CurrentSequence.GetAlpha(CurrentFrame); + var imageRenderable = new SpriteRenderable(Image, pos, offset, CurrentSequence.ZOffset + zOffset, palette, CurrentSequence.Scale, alpha, float3.Ones, tintModifiers, IsDecoration); if (CurrentSequence.ShadowStart >= 0) { var shadow = CurrentSequence.GetShadow(CurrentFrame, facingFunc()); - var shadowRenderable = new SpriteRenderable(shadow, pos, offset, CurrentSequence.ShadowZOffset + zOffset, palette, CurrentSequence.Scale, true, tintModifiers); + var shadowRenderable = new SpriteRenderable(shadow, pos, offset, CurrentSequence.ShadowZOffset + zOffset, palette, CurrentSequence.Scale, 1f, float3.Ones, tintModifiers, true); return new IRenderable[] { shadowRenderable, imageRenderable }; } @@ -72,7 +73,8 @@ namespace OpenRA.Graphics scale *= CurrentSequence.Scale; var screenOffset = (scale * wr.ScreenVectorComponents(offset)).XY.ToInt2(); var imagePos = pos + screenOffset - new int2((int)(scale * Image.Size.X / 2), (int)(scale * Image.Size.Y / 2)); - var imageRenderable = new UISpriteRenderable(Image, WPos.Zero + offset, imagePos, CurrentSequence.ZOffset + zOffset, palette, scale); + var alpha = CurrentSequence.GetAlpha(CurrentFrame); + var imageRenderable = new UISpriteRenderable(Image, WPos.Zero + offset, imagePos, CurrentSequence.ZOffset + zOffset, palette, scale, alpha); if (CurrentSequence.ShadowStart >= 0) { diff --git a/OpenRA.Game/Graphics/SequenceProvider.cs b/OpenRA.Game/Graphics/SequenceProvider.cs index 63a32879f7..659da8880f 100644 --- a/OpenRA.Game/Graphics/SequenceProvider.cs +++ b/OpenRA.Game/Graphics/SequenceProvider.cs @@ -38,6 +38,7 @@ namespace OpenRA.Graphics Sprite GetSprite(int frame); Sprite GetSprite(int frame, WAngle facing); Sprite GetShadow(int frame, WAngle facing); + float GetAlpha(int frame); } public interface ISpriteSequenceLoader diff --git a/OpenRA.Game/Graphics/SpriteRenderable.cs b/OpenRA.Game/Graphics/SpriteRenderable.cs index 07f68d41d4..ef8bdba409 100644 --- a/OpenRA.Game/Graphics/SpriteRenderable.cs +++ b/OpenRA.Game/Graphics/SpriteRenderable.cs @@ -29,12 +29,6 @@ namespace OpenRA.Graphics readonly float alpha; readonly bool isDecoration; - public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, bool isDecoration) - : this(sprite, pos, offset, zOffset, palette, scale, 1f, float3.Ones, TintModifiers.None, isDecoration) { } - - public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, bool isDecoration, TintModifiers tintModifiers) - : this(sprite, pos, offset, zOffset, palette, scale, 1f, float3.Ones, tintModifiers, isDecoration) { } - public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, float alpha, float3 tint, TintModifiers tintModifiers, bool isDecoration) { this.sprite = sprite; diff --git a/OpenRA.Game/Graphics/UISpriteRenderable.cs b/OpenRA.Game/Graphics/UISpriteRenderable.cs index dd572a50c3..0afac9c62e 100644 --- a/OpenRA.Game/Graphics/UISpriteRenderable.cs +++ b/OpenRA.Game/Graphics/UISpriteRenderable.cs @@ -21,8 +21,9 @@ namespace OpenRA.Graphics readonly int zOffset; readonly PaletteReference palette; readonly float scale; + readonly float alpha; - public UISpriteRenderable(Sprite sprite, WPos effectiveWorldPos, int2 screenPos, int zOffset, PaletteReference palette, float scale) + public UISpriteRenderable(Sprite sprite, WPos effectiveWorldPos, int2 screenPos, int zOffset, PaletteReference palette, float scale = 1f, float alpha = 1f) { this.sprite = sprite; this.effectiveWorldPos = effectiveWorldPos; @@ -30,6 +31,7 @@ namespace OpenRA.Graphics this.zOffset = zOffset; this.palette = palette; this.scale = scale; + this.alpha = alpha; } // Does not exist in the world, so a world positions don't make sense @@ -40,7 +42,7 @@ namespace OpenRA.Graphics public PaletteReference Palette { get { return palette; } } public int ZOffset { get { return zOffset; } } - public IPalettedRenderable WithPalette(PaletteReference newPalette) { return new UISpriteRenderable(sprite, effectiveWorldPos, screenPos, zOffset, newPalette, scale); } + public IPalettedRenderable WithPalette(PaletteReference newPalette) { return new UISpriteRenderable(sprite, effectiveWorldPos, screenPos, zOffset, newPalette, scale, alpha); } public IRenderable WithZOffset(int newOffset) { return this; } public IRenderable OffsetBy(WVec vec) { return this; } public IRenderable AsDecoration() { return this; } @@ -48,7 +50,7 @@ namespace OpenRA.Graphics public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public void Render(WorldRenderer wr) { - Game.Renderer.SpriteRenderer.DrawSprite(sprite, screenPos, palette, scale * sprite.Size); + Game.Renderer.SpriteRenderer.DrawSprite(sprite, screenPos, palette, scale * sprite.Size, float3.Ones, alpha); } public void RenderDebugGeometry(WorldRenderer wr) diff --git a/OpenRA.Mods.Cnc/Graphics/TeslaZapRenderable.cs b/OpenRA.Mods.Cnc/Graphics/TeslaZapRenderable.cs index eb9938a80f..69d69d234b 100644 --- a/OpenRA.Mods.Cnc/Graphics/TeslaZapRenderable.cs +++ b/OpenRA.Mods.Cnc/Graphics/TeslaZapRenderable.cs @@ -149,7 +149,7 @@ namespace OpenRA.Mods.Cnc.Graphics var pos = wr.ProjectedPosition((z + new float2(step[2], step[3])).ToInt2()); var tintModifiers = s.IgnoreWorldTint ? TintModifiers.IgnoreWorldTint : TintModifiers.None; - rs.Add(new SpriteRenderable(s.GetSprite(step[4]), pos, WVec.Zero, 0, pal, 1f, true, tintModifiers).PrepareRender(wr)); + rs.Add(new SpriteRenderable(s.GetSprite(step[4]), pos, WVec.Zero, 0, pal, 1f, s.GetAlpha(step[4]), float3.Ones, tintModifiers, true).PrepareRender(wr)); z += new float2(step[0], step[1]); if (rs.Count >= 1000) diff --git a/OpenRA.Mods.Cnc/Traits/Minelayer.cs b/OpenRA.Mods.Cnc/Traits/Minelayer.cs index 6d7f8539fd..fe1fc0f2e4 100644 --- a/OpenRA.Mods.Cnc/Traits/Minelayer.cs +++ b/OpenRA.Mods.Cnc/Traits/Minelayer.cs @@ -200,9 +200,8 @@ namespace OpenRA.Mods.Cnc.Traits { readonly List minelayers; readonly Minelayer minelayer; - readonly Sprite tileOk; - readonly Sprite tileUnknown; - readonly Sprite tileBlocked; + readonly Sprite validTile, unknownTile, blockedTile; + readonly float validAlpha, unknownAlpha, blockedAlpha; readonly CPos minefieldStart; readonly bool queued; @@ -215,19 +214,43 @@ namespace OpenRA.Mods.Cnc.Traits minelayer = a.Trait(); var tileset = a.World.Map.Tileset.ToLowerInvariant(); if (a.World.Map.Rules.Sequences.HasSequence("overlay", "{0}-{1}".F(minelayer.Info.TileValidName, tileset))) - tileOk = a.World.Map.Rules.Sequences.GetSequence("overlay", "{0}-{1}".F(minelayer.Info.TileValidName, tileset)).GetSprite(0); + { + var validSequence = a.World.Map.Rules.Sequences.GetSequence("overlay", "{0}-{1}".F(minelayer.Info.TileValidName, tileset)); + validTile = validSequence.GetSprite(0); + validAlpha = validSequence.GetAlpha(0); + } else - tileOk = a.World.Map.Rules.Sequences.GetSequence("overlay", minelayer.Info.TileValidName).GetSprite(0); + { + var validSequence = a.World.Map.Rules.Sequences.GetSequence("overlay", minelayer.Info.TileValidName); + validTile = validSequence.GetSprite(0); + validAlpha = validSequence.GetAlpha(0); + } if (a.World.Map.Rules.Sequences.HasSequence("overlay", "{0}-{1}".F(minelayer.Info.TileUnknownName, tileset))) - tileUnknown = a.World.Map.Rules.Sequences.GetSequence("overlay", "{0}-{1}".F(minelayer.Info.TileUnknownName, tileset)).GetSprite(0); + { + var unknownSequence = a.World.Map.Rules.Sequences.GetSequence("overlay", "{0}-{1}".F(minelayer.Info.TileUnknownName, tileset)); + unknownTile = unknownSequence.GetSprite(0); + unknownAlpha = unknownSequence.GetAlpha(0); + } else - tileUnknown = a.World.Map.Rules.Sequences.GetSequence("overlay", minelayer.Info.TileUnknownName).GetSprite(0); + { + var unknownSequence = a.World.Map.Rules.Sequences.GetSequence("overlay", minelayer.Info.TileUnknownName); + unknownTile = unknownSequence.GetSprite(0); + unknownAlpha = unknownSequence.GetAlpha(0); + } if (a.World.Map.Rules.Sequences.HasSequence("overlay", "{0}-{1}".F(minelayer.Info.TileInvalidName, tileset))) - tileBlocked = a.World.Map.Rules.Sequences.GetSequence("overlay", "{0}-{1}".F(minelayer.Info.TileInvalidName, tileset)).GetSprite(0); + { + var blockedSequence = a.World.Map.Rules.Sequences.GetSequence("overlay", "{0}-{1}".F(minelayer.Info.TileInvalidName, tileset)); + blockedTile = blockedSequence.GetSprite(0); + blockedAlpha = blockedSequence.GetAlpha(0); + } else - tileBlocked = a.World.Map.Rules.Sequences.GetSequence("overlay", minelayer.Info.TileInvalidName).GetSprite(0); + { + var blockedSequence = a.World.Map.Rules.Sequences.GetSequence("overlay", minelayer.Info.TileInvalidName); + blockedTile = blockedSequence.GetSprite(0); + blockedAlpha = blockedSequence.GetAlpha(0); + } } public void AddMinelayer(Actor a, CPos xy) @@ -276,18 +299,31 @@ namespace OpenRA.Mods.Cnc.Traits var pal = wr.Palette(TileSet.TerrainPaletteInternalName); foreach (var c in minefield) { - var tile = tileOk; + var tile = validTile; + var alpha = validAlpha; if (!world.Map.Contains(c)) - tile = tileBlocked; + { + tile = blockedTile; + alpha = blockedAlpha; + } else if (world.ShroudObscures(c)) - tile = tileBlocked; + { + tile = blockedTile; + alpha = blockedAlpha; + } else if (world.FogObscures(c)) - tile = tileUnknown; + { + tile = unknownTile; + alpha = unknownAlpha; + } else if (!this.minelayer.IsCellAcceptable(minelayer, c) || !movement.CanEnterCell(c, null, BlockedByActor.Immovable) || (mobile != null && !mobile.CanStayInCell(c))) - tile = tileBlocked; + { + tile = blockedTile; + alpha = blockedAlpha; + } - yield return new SpriteRenderable(tile, world.Map.CenterOfCell(c), WVec.Zero, -511, pal, 1f, true, TintModifiers.IgnoreWorldTint); + yield return new SpriteRenderable(tile, world.Map.CenterOfCell(c), WVec.Zero, -511, pal, 1f, alpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); } } diff --git a/OpenRA.Mods.Cnc/Traits/SupportPowers/ChronoshiftPower.cs b/OpenRA.Mods.Cnc/Traits/SupportPowers/ChronoshiftPower.cs index 4cb0abb4ac..bfbd62cb2d 100644 --- a/OpenRA.Mods.Cnc/Traits/SupportPowers/ChronoshiftPower.cs +++ b/OpenRA.Mods.Cnc/Traits/SupportPowers/ChronoshiftPower.cs @@ -143,6 +143,7 @@ namespace OpenRA.Mods.Cnc.Traits readonly char[] footprint; readonly CVec dimensions; readonly Sprite tile; + readonly float alpha; readonly SupportPowerManager manager; readonly string order; @@ -157,9 +158,11 @@ namespace OpenRA.Mods.Cnc.Traits this.power = power; var info = (ChronoshiftPowerInfo)power.Info; + var s = world.Map.Rules.Sequences.GetSequence(info.FootprintImage, info.SourceFootprintSequence); footprint = info.Footprint.Where(c => !char.IsWhiteSpace(c)).ToArray(); dimensions = info.Dimensions; - tile = world.Map.Rules.Sequences.GetSequence(info.FootprintImage, info.SourceFootprintSequence).GetSprite(0); + tile = s.GetSprite(0); + alpha = s.GetAlpha(0); } protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) @@ -203,7 +206,7 @@ namespace OpenRA.Mods.Cnc.Traits var tiles = power.CellsMatching(xy, footprint, dimensions); var palette = wr.Palette(((ChronoshiftPowerInfo)power.Info).TargetOverlayPalette); foreach (var t in tiles) - yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, palette, 1f, true, TintModifiers.IgnoreWorldTint); + yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, palette, 1f, alpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); } protected override string GetCursor(World world, CPos cell, int2 worldPixel, MouseInput mi) @@ -219,6 +222,7 @@ namespace OpenRA.Mods.Cnc.Traits readonly char[] footprint; readonly CVec dimensions; readonly Sprite validTile, invalidTile, sourceTile; + readonly float validAlpha, invalidAlpha, sourceAlpha; readonly SupportPowerManager manager; readonly string order; @@ -236,12 +240,25 @@ namespace OpenRA.Mods.Cnc.Traits var sequences = world.Map.Rules.Sequences; var tilesetValid = info.ValidFootprintSequence + "-" + world.Map.Tileset.ToLowerInvariant(); if (sequences.HasSequence(info.FootprintImage, tilesetValid)) - validTile = sequences.GetSequence(info.FootprintImage, tilesetValid).GetSprite(0); + { + var validSequence = sequences.GetSequence(info.FootprintImage, tilesetValid); + validTile = validSequence.GetSprite(0); + validAlpha = validSequence.GetAlpha(0); + } else - validTile = sequences.GetSequence(info.FootprintImage, info.ValidFootprintSequence).GetSprite(0); + { + var validSequence = sequences.GetSequence(info.FootprintImage, info.ValidFootprintSequence); + validTile = validSequence.GetSprite(0); + validAlpha = validSequence.GetAlpha(0); + } - invalidTile = sequences.GetSequence(info.FootprintImage, info.InvalidFootprintSequence).GetSprite(0); - sourceTile = sequences.GetSequence(info.FootprintImage, info.SourceFootprintSequence).GetSprite(0); + var invalidSequence = sequences.GetSequence(info.FootprintImage, info.InvalidFootprintSequence); + invalidTile = invalidSequence.GetSprite(0); + invalidAlpha = invalidSequence.GetAlpha(0); + + var sourceSequence = sequences.GetSequence(info.FootprintImage, info.SourceFootprintSequence); + sourceTile = sourceSequence.GetSprite(0); + sourceAlpha = sourceSequence.GetAlpha(0); } protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) @@ -287,8 +304,10 @@ namespace OpenRA.Mods.Cnc.Traits var delta = xy - sourceLocation; foreach (var t in power.CellsMatching(sourceLocation, footprint, dimensions)) { - var tile = manager.Self.Owner.Shroud.IsExplored(t + delta) ? validTile : invalidTile; - yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t + delta), WVec.Zero, -511, palette, 1f, true, TintModifiers.IgnoreWorldTint); + var isValid = manager.Self.Owner.Shroud.IsExplored(t + delta); + var tile = isValid ? validTile : invalidTile; + var alpha = isValid ? validAlpha : invalidAlpha; + yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t + delta), WVec.Zero, -511, palette, 1f, alpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); } // Unit previews @@ -300,7 +319,8 @@ namespace OpenRA.Mods.Cnc.Traits var canEnter = manager.Self.Owner.Shroud.IsExplored(targetCell) && unit.Trait().CanChronoshiftTo(unit, targetCell); var tile = canEnter ? validTile : invalidTile; - yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(targetCell), WVec.Zero, -511, palette, 1f, true, TintModifiers.IgnoreWorldTint); + var alpha = canEnter ? validAlpha : invalidAlpha; + yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(targetCell), WVec.Zero, -511, palette, 1f, alpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); } var offset = world.Map.CenterOfCell(xy) - world.Map.CenterOfCell(sourceLocation); @@ -330,7 +350,7 @@ namespace OpenRA.Mods.Cnc.Traits // Source tiles foreach (var t in power.CellsMatching(sourceLocation, footprint, dimensions)) - yield return new SpriteRenderable(sourceTile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, palette, 1f, true, TintModifiers.IgnoreWorldTint); + yield return new SpriteRenderable(sourceTile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, palette, 1f, sourceAlpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); } bool IsValidTarget(CPos xy) diff --git a/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs b/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs index 09fcf32c9c..11afc336e4 100644 --- a/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs +++ b/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs @@ -117,6 +117,7 @@ namespace OpenRA.Mods.Common.Graphics Sprite ISpriteSequence.GetSprite(int frame) { throw exception; } Sprite ISpriteSequence.GetSprite(int frame, WAngle facing) { throw exception; } Sprite ISpriteSequence.GetShadow(int frame, WAngle facing) { throw exception; } + float ISpriteSequence.GetAlpha(int frame) { throw exception; } } public class DefaultSpriteSequence : ISpriteSequence @@ -125,6 +126,7 @@ namespace OpenRA.Mods.Common.Graphics protected Sprite[] sprites; readonly bool reverseFacings, transpose; readonly string sequence; + readonly float[] alpha; protected readonly ISpriteSequenceLoader Loader; @@ -316,6 +318,23 @@ namespace OpenRA.Mods.Common.Graphics s.Channel, blendMode) : null).ToArray(); } + alpha = LoadField(d, "Alpha", (float[])null); + if (alpha != null) + { + if (alpha.Length == 1) + alpha = Exts.MakeArray(Length, _ => alpha[0]); + else if (alpha.Length != Length) + throw new YamlException("Sequence {0}.{1} must define either 1 or {2} Alpha values.".F(sequence, animation, Length)); + } + + if (LoadField(d, "AlphaFade", false)) + { + if (alpha != null) + throw new YamlException("Sequence {0}.{1} cannot define both AlphaFade and Alpha.".F(sequence, animation)); + + alpha = Exts.MakeArray(Length, i => float2.Lerp(1f, 0f, i / (Length - 1f))); + } + var depthSprite = LoadField(d, "DepthSprite", null); if (!string.IsNullOrEmpty(depthSprite)) { @@ -418,5 +437,10 @@ namespace OpenRA.Mods.Common.Graphics { return Util.IndexFacing(facing, Facings); } + + public virtual float GetAlpha(int frame) + { + return alpha?[frame] ?? 1f; + } } } diff --git a/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs b/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs index 72eca21bef..64caa81b2d 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs @@ -210,7 +210,8 @@ namespace OpenRA.Mods.Common.Traits return footprint.Select(c => (IRenderable)(new SpriteRenderable( terrainRenderer.TileSprite(new TerrainTile(template, c.Value)), - wr.World.Map.CenterOfCell(c.Key), WVec.Zero, -offset, palette, 1f, true))).ToArray(); + wr.World.Map.CenterOfCell(c.Key), WVec.Zero, -offset, palette, 1f, 1f, + float3.Ones, TintModifiers.None, true))).ToArray(); } bool initialized; diff --git a/OpenRA.Mods.Common/Traits/Buildings/FootprintPlaceBuildingPreview.cs b/OpenRA.Mods.Common/Traits/Buildings/FootprintPlaceBuildingPreview.cs index ccc11d64c9..2abff29f85 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/FootprintPlaceBuildingPreview.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/FootprintPlaceBuildingPreview.cs @@ -51,8 +51,8 @@ namespace OpenRA.Mods.Common.Traits readonly FootprintPlaceBuildingPreviewInfo info; readonly IPlaceBuildingDecorationInfo[] decorations; readonly int2 topLeftScreenOffset; - readonly Sprite buildOk; - readonly Sprite buildBlocked; + readonly Sprite validTile, blockedTile; + readonly float validAlpha, blockedAlpha; public FootprintPlaceBuildingPreviewPreview(WorldRenderer wr, ActorInfo ai, FootprintPlaceBuildingPreviewInfo info, TypeDictionary init) { @@ -66,10 +66,21 @@ namespace OpenRA.Mods.Common.Traits var tileset = world.Map.Tileset.ToLowerInvariant(); if (world.Map.Rules.Sequences.HasSequence("overlay", "build-valid-{0}".F(tileset))) - buildOk = world.Map.Rules.Sequences.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0); + { + var validSequence = world.Map.Rules.Sequences.GetSequence("overlay", "build-valid-{0}".F(tileset)); + validTile = validSequence.GetSprite(0); + validAlpha = validSequence.GetAlpha(0); + } else - buildOk = world.Map.Rules.Sequences.GetSequence("overlay", "build-valid").GetSprite(0); - buildBlocked = world.Map.Rules.Sequences.GetSequence("overlay", "build-invalid").GetSprite(0); + { + var validSequence = world.Map.Rules.Sequences.GetSequence("overlay", "build-valid"); + validTile = validSequence.GetSprite(0); + validAlpha = validSequence.GetAlpha(0); + } + + var blockedSequence = world.Map.Rules.Sequences.GetSequence("overlay", "build-invalid"); + blockedTile = blockedSequence.GetSprite(0); + blockedAlpha = blockedSequence.GetAlpha(0); } protected virtual void TickInner() { } @@ -84,11 +95,12 @@ namespace OpenRA.Mods.Common.Traits if ((c.Value & filter) == 0) continue; - var tile = (c.Value & PlaceBuildingCellType.Invalid) != 0 ? buildBlocked : buildOk; + var tile = (c.Value & PlaceBuildingCellType.Invalid) != 0 ? blockedTile : validTile; + var sequenceAlpha = (c.Value & PlaceBuildingCellType.Invalid) != 0 ? blockedAlpha : validAlpha; var pos = wr.World.Map.CenterOfCell(c.Key); var offset = new WVec(0, 0, topLeftPos.Z - pos.Z); - var alpha = (c.Value & PlaceBuildingCellType.LineBuild) != 0 ? info.LineBuildFootprintAlpha : info.FootprintAlpha; - yield return new SpriteRenderable(tile, pos, offset, -511, palette, 1f, alpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); + var traitAlpha = (c.Value & PlaceBuildingCellType.LineBuild) != 0 ? info.LineBuildFootprintAlpha : info.FootprintAlpha; + yield return new SpriteRenderable(tile, pos, offset, -511, palette, 1f, sequenceAlpha * traitAlpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); } } diff --git a/OpenRA.Mods.Common/Traits/Render/DrawLineToTarget.cs b/OpenRA.Mods.Common/Traits/Render/DrawLineToTarget.cs index c1216cc805..422d2e3943 100644 --- a/OpenRA.Mods.Common/Traits/Render/DrawLineToTarget.cs +++ b/OpenRA.Mods.Common/Traits/Render/DrawLineToTarget.cs @@ -90,7 +90,7 @@ namespace OpenRA.Mods.Common.Traits if (!a.IsCanceling) foreach (var n in a.TargetLineNodes(self)) if (n.Tile != null && n.Target.Type != TargetType.Invalid) - yield return new SpriteRenderable(n.Tile, n.Target.CenterPosition, WVec.Zero, -511, pal, 1f, true, TintModifiers.IgnoreWorldTint); + yield return new SpriteRenderable(n.Tile, n.Target.CenterPosition, WVec.Zero, -511, pal, 1f, 1f, float3.Ones, TintModifiers.IgnoreWorldTint, true); } bool IRenderAboveShroud.SpatiallyPartitionable { get { return false; } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithAmmoPipsDecoration.cs b/OpenRA.Mods.Common/Traits/Render/WithAmmoPipsDecoration.cs index 31149f9bee..2a7e3624c4 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithAmmoPipsDecoration.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithAmmoPipsDecoration.cs @@ -74,7 +74,7 @@ namespace OpenRA.Mods.Common.Traits.Render for (var i = 0; i < pipCount; i++) { pips.PlayRepeating(currentAmmo * pipCount > i * totalAmmo ? Info.FullSequence : Info.EmptySequence); - yield return new UISpriteRenderable(pips.Image, self.CenterPosition, screenPos, 0, palette, 1f); + yield return new UISpriteRenderable(pips.Image, self.CenterPosition, screenPos, 0, palette); screenPos += pipStride; } diff --git a/OpenRA.Mods.Common/Traits/Render/WithCargoPipsDecoration.cs b/OpenRA.Mods.Common/Traits/Render/WithCargoPipsDecoration.cs index 757eb4c8f0..bd002b5fa3 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithCargoPipsDecoration.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithCargoPipsDecoration.cs @@ -92,7 +92,7 @@ namespace OpenRA.Mods.Common.Traits.Render for (var i = 0; i < pipCount; i++) { pips.PlayRepeating(GetPipSequence(i)); - yield return new UISpriteRenderable(pips.Image, self.CenterPosition, screenPos, 0, palette, 1f); + yield return new UISpriteRenderable(pips.Image, self.CenterPosition, screenPos, 0, palette); screenPos += pipStride; } diff --git a/OpenRA.Mods.Common/Traits/Render/WithDecoration.cs b/OpenRA.Mods.Common/Traits/Render/WithDecoration.cs index 2a60dcf72a..c12874e4c1 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithDecoration.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithDecoration.cs @@ -62,7 +62,7 @@ namespace OpenRA.Mods.Common.Traits.Render return new IRenderable[] { - new UISpriteRenderable(anim.Image, self.CenterPosition, screenPos - (0.5f * anim.Image.Size.XY).ToInt2(), 0, GetPalette(self, wr), 1f) + new UISpriteRenderable(anim.Image, self.CenterPosition, screenPos - (0.5f * anim.Image.Size.XY).ToInt2(), 0, GetPalette(self, wr)) }; } diff --git a/OpenRA.Mods.Common/Traits/Render/WithHarvesterPipsDecoration.cs b/OpenRA.Mods.Common/Traits/Render/WithHarvesterPipsDecoration.cs index f473830f69..8e4d1d7c20 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithHarvesterPipsDecoration.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithHarvesterPipsDecoration.cs @@ -89,7 +89,7 @@ namespace OpenRA.Mods.Common.Traits.Render for (var i = 0; i < Info.PipCount; i++) { pips.PlayRepeating(GetPipSequence(i)); - yield return new UISpriteRenderable(pips.Image, self.CenterPosition, screenPos, 0, palette, 1f); + yield return new UISpriteRenderable(pips.Image, self.CenterPosition, screenPos, 0, palette); screenPos += pipStride; } diff --git a/OpenRA.Mods.Common/Traits/Render/WithParachute.cs b/OpenRA.Mods.Common/Traits/Render/WithParachute.cs index e407732231..0b512e90d5 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithParachute.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithParachute.cs @@ -180,8 +180,9 @@ namespace OpenRA.Mods.Common.Traits.Render var dat = self.World.Map.DistanceAboveTerrain(self.CenterPosition); var pos = self.CenterPosition - new WVec(0, 0, dat.Length); var palette = wr.Palette(info.Palette); + var alpha = shadow.CurrentSequence.GetAlpha(shadow.CurrentFrame); var tintModifiers = shadow.CurrentSequence.IgnoreWorldTint ? TintModifiers.ReplaceColor | TintModifiers.IgnoreWorldTint : TintModifiers.ReplaceColor; - return new IRenderable[] { new SpriteRenderable(shadow.Image, pos, info.ShadowOffset, info.ShadowZOffset, palette, 1, shadowAlpha, shadowColor, tintModifiers, true) }; + return new IRenderable[] { new SpriteRenderable(shadow.Image, pos, info.ShadowOffset, info.ShadowZOffset, palette, 1, shadowAlpha * alpha, shadowColor, tintModifiers, true) }; } IEnumerable IRender.ScreenBounds(Actor self, WorldRenderer wr) diff --git a/OpenRA.Mods.Common/Traits/Render/WithResourceStoragePipsDecoration.cs b/OpenRA.Mods.Common/Traits/Render/WithResourceStoragePipsDecoration.cs index adea5a5036..9e5ebac949 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithResourceStoragePipsDecoration.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithResourceStoragePipsDecoration.cs @@ -65,7 +65,7 @@ namespace OpenRA.Mods.Common.Traits.Render for (var i = 0; i < Info.PipCount; i++) { pips.PlayRepeating(player.Resources * Info.PipCount > i * player.ResourceCapacity ? Info.FullSequence : Info.EmptySequence); - yield return new UISpriteRenderable(pips.Image, self.CenterPosition, screenPos, 0, palette, 1f); + yield return new UISpriteRenderable(pips.Image, self.CenterPosition, screenPos, 0, palette); screenPos += pipStride; } diff --git a/OpenRA.Mods.Common/Traits/Render/WithSpriteControlGroupDecoration.cs b/OpenRA.Mods.Common/Traits/Render/WithSpriteControlGroupDecoration.cs index cc3cec3bbb..ad15ac5820 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithSpriteControlGroupDecoration.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithSpriteControlGroupDecoration.cs @@ -65,7 +65,7 @@ namespace OpenRA.Mods.Common.Traits.Render var palette = wr.Palette(Info.Palette); return new IRenderable[] { - new UISpriteRenderable(anim.Image, self.CenterPosition, screenPos, 0, palette, 1f) + new UISpriteRenderable(anim.Image, self.CenterPosition, screenPos, 0, palette) }; } } diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/GrantExternalConditionPower.cs b/OpenRA.Mods.Common/Traits/SupportPowers/GrantExternalConditionPower.cs index 706732db66..c8bb02b4f2 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/GrantExternalConditionPower.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/GrantExternalConditionPower.cs @@ -110,6 +110,7 @@ namespace OpenRA.Mods.Common.Traits readonly char[] footprint; readonly CVec dimensions; readonly Sprite tile; + readonly float alpha; readonly SupportPowerManager manager; readonly string order; @@ -124,7 +125,10 @@ namespace OpenRA.Mods.Common.Traits this.power = power; footprint = power.info.Footprint.Where(c => !char.IsWhiteSpace(c)).ToArray(); dimensions = power.info.Dimensions; - tile = world.Map.Rules.Sequences.GetSequence("overlay", "target-select").GetSprite(0); + + var sequence = world.Map.Rules.Sequences.GetSequence("overlay", "target-select"); + tile = sequence.GetSprite(0); + alpha = sequence.GetAlpha(0); } protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) @@ -161,7 +165,7 @@ namespace OpenRA.Mods.Common.Traits var pal = wr.Palette(TileSet.TerrainPaletteInternalName); foreach (var t in power.CellsMatching(xy, footprint, dimensions)) - yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, pal, 1f, true, TintModifiers.IgnoreWorldTint); + yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, pal, 1f, alpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); } protected override string GetCursor(World world, CPos cell, int2 worldPixel, MouseInput mi) diff --git a/OpenRA.Mods.Common/Traits/World/EditorCursorLayer.cs b/OpenRA.Mods.Common/Traits/World/EditorCursorLayer.cs index df2f3fa7a1..ed372304c4 100644 --- a/OpenRA.Mods.Common/Traits/World/EditorCursorLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/EditorCursorLayer.cs @@ -81,9 +81,10 @@ namespace OpenRA.Mods.Common.Traits var sequence = wr.World.Map.Rules.Sequences.GetSequence("resources", variant); var sprite = sequence.GetSprite(Resource.MaxDensity - 1); var palette = wr.Palette(Resource.Palette); + var alpha = sequence.GetAlpha(Resource.MaxDensity - 1); var tintModifiers = sequence.IgnoreWorldTint ? TintModifiers.IgnoreWorldTint : TintModifiers.None; - terrainOrResourcePreview.Add(new SpriteRenderable(sprite, pos, WVec.Zero, 0, palette, 1, false, tintModifiers)); + terrainOrResourcePreview.Add(new SpriteRenderable(sprite, pos, WVec.Zero, 0, palette, 1f, alpha, float3.Ones, tintModifiers, false)); } } } diff --git a/OpenRA.Mods.Common/Traits/World/EditorSelectionLayer.cs b/OpenRA.Mods.Common/Traits/World/EditorSelectionLayer.cs index 43171dca7d..711aef147e 100644 --- a/OpenRA.Mods.Common/Traits/World/EditorSelectionLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/EditorSelectionLayer.cs @@ -43,8 +43,8 @@ namespace OpenRA.Mods.Common.Traits { readonly EditorSelectionLayerInfo info; readonly Map map; - readonly Sprite copySprite; - readonly Sprite pasteSprite; + readonly Sprite copyTile, pasteTile; + readonly float copyAlpha, pasteAlpha; PaletteReference palette; public CellRegion CopyRegion { get; private set; } @@ -57,8 +57,14 @@ namespace OpenRA.Mods.Common.Traits this.info = info; map = self.World.Map; - copySprite = map.Rules.Sequences.GetSequence(info.Image, info.CopySequence).GetSprite(0); - pasteSprite = map.Rules.Sequences.GetSequence(info.Image, info.PasteSequence).GetSprite(0); + + var copySequence = map.Rules.Sequences.GetSequence(info.Image, info.CopySequence); + copyTile = copySequence.GetSprite(0); + copyAlpha = copySequence.GetAlpha(0); + + var pasteSequence = map.Rules.Sequences.GetSequence(info.Image, info.PasteSequence); + pasteTile = pasteSequence.GetSprite(0); + pasteAlpha = pasteSequence.GetAlpha(0); } void IWorldLoaded.WorldLoaded(World w, WorldRenderer wr) @@ -91,13 +97,13 @@ namespace OpenRA.Mods.Common.Traits if (CopyRegion != null) foreach (var c in CopyRegion) - yield return new SpriteRenderable(copySprite, wr.World.Map.CenterOfCell(c), - WVec.Zero, -511, palette, 1f, info.FootprintAlpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); + yield return new SpriteRenderable(copyTile, wr.World.Map.CenterOfCell(c), + WVec.Zero, -511, palette, 1f, copyAlpha * info.FootprintAlpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); if (PasteRegion != null) foreach (var c in PasteRegion) - yield return new SpriteRenderable(pasteSprite, wr.World.Map.CenterOfCell(c), - WVec.Zero, -511, palette, 1f, info.FootprintAlpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); + yield return new SpriteRenderable(pasteTile, wr.World.Map.CenterOfCell(c), + WVec.Zero, -511, palette, 1f, pasteAlpha * info.FootprintAlpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); } bool IRenderAboveShroud.SpatiallyPartitionable { get { return false; } } diff --git a/OpenRA.Mods.Common/Traits/World/TerrainRenderer.cs b/OpenRA.Mods.Common/Traits/World/TerrainRenderer.cs index ff29f01c41..d0bac0689e 100644 --- a/OpenRA.Mods.Common/Traits/World/TerrainRenderer.cs +++ b/OpenRA.Mods.Common/Traits/World/TerrainRenderer.cs @@ -203,7 +203,7 @@ namespace OpenRA.Mods.Common.Traits var offset = map.Offset(new CVec(x, y), tileInfo.Height); var palette = wr.Palette(template.Palette ?? TileSet.TerrainPaletteInternalName); - yield return new SpriteRenderable(sprite, origin, offset, 0, palette, 1, false); + yield return new SpriteRenderable(sprite, origin, offset, 0, palette, 1f, 1f, float3.Ones, TintModifiers.None, false); } } } diff --git a/OpenRA.Mods.D2k/Traits/Buildings/D2kActorPreviewPlaceBuildingPreview.cs b/OpenRA.Mods.D2k/Traits/Buildings/D2kActorPreviewPlaceBuildingPreview.cs index 36bc46ad74..332e52d26b 100644 --- a/OpenRA.Mods.D2k/Traits/Buildings/D2kActorPreviewPlaceBuildingPreview.cs +++ b/OpenRA.Mods.D2k/Traits/Buildings/D2kActorPreviewPlaceBuildingPreview.cs @@ -45,9 +45,8 @@ namespace OpenRA.Mods.D2k.Traits { readonly D2kActorPreviewPlaceBuildingPreviewInfo info; readonly bool checkUnsafeTiles; - readonly Sprite buildOk; - readonly Sprite buildUnsafe; - readonly Sprite buildBlocked; + readonly Sprite validTile, unsafeTile, blockedTile; + readonly float validAlpha, unsafeAlpha, blockedAlpha; readonly CachedTransform> unpathableCells; public D2kActorPreviewPlaceBuildingPreviewPreview(WorldRenderer wr, ActorInfo ai, D2kActorPreviewPlaceBuildingPreviewInfo info, TypeDictionary init) @@ -61,9 +60,17 @@ namespace OpenRA.Mods.D2k.Traits var techTree = init.Get().Value(world).PlayerActor.Trait(); checkUnsafeTiles = info.RequiresPrerequisites.Any() && techTree.HasPrerequisites(info.RequiresPrerequisites); - buildOk = sequences.GetSequence("overlay", "build-valid").GetSprite(0); - buildUnsafe = sequences.GetSequence("overlay", "build-unsafe").GetSprite(0); - buildBlocked = sequences.GetSequence("overlay", "build-invalid").GetSprite(0); + var validSequence = sequences.GetSequence("overlay", "build-valid"); + validTile = validSequence.GetSprite(0); + validAlpha = validSequence.GetAlpha(0); + + var unsafeSequence = sequences.GetSequence("overlay", "build-unsafe"); + unsafeTile = unsafeSequence.GetSprite(0); + unsafeAlpha = unsafeSequence.GetAlpha(0); + + var blockedSequence = sequences.GetSequence("overlay", "build-invalid"); + blockedTile = blockedSequence.GetSprite(0); + blockedAlpha = blockedSequence.GetAlpha(0); var buildingInfo = ai.TraitInfo(); unpathableCells = new CachedTransform>(topLeft => buildingInfo.OccupiedTiles(topLeft).ToList()); @@ -81,14 +88,14 @@ namespace OpenRA.Mods.D2k.Traits if ((c.Value & filter) == 0) continue; - var tile = (c.Value & PlaceBuildingCellType.Invalid) != 0 ? buildBlocked : - (checkUnsafeTiles && candidateSafeTiles.Contains(c.Key) && info.UnsafeTerrainTypes.Contains(wr.World.Map.GetTerrainInfo(c.Key).Type)) - ? buildUnsafe : buildOk; + var isUnsafe = checkUnsafeTiles && candidateSafeTiles.Contains(c.Key) && info.UnsafeTerrainTypes.Contains(wr.World.Map.GetTerrainInfo(c.Key).Type); + var tile = (c.Value & PlaceBuildingCellType.Invalid) != 0 ? blockedTile : isUnsafe ? unsafeTile : validTile; + var sequenceAlpha = (c.Value & PlaceBuildingCellType.Invalid) != 0 ? blockedAlpha : isUnsafe ? unsafeAlpha : validAlpha; var pos = wr.World.Map.CenterOfCell(c.Key); var offset = new WVec(0, 0, topLeftPos.Z - pos.Z); - var alpha = (c.Value & PlaceBuildingCellType.LineBuild) != 0 ? info.LineBuildFootprintAlpha : info.FootprintAlpha; - yield return new SpriteRenderable(tile, pos, offset, -511, palette, 1f, alpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); + var traitAlpha = (c.Value & PlaceBuildingCellType.LineBuild) != 0 ? info.LineBuildFootprintAlpha : info.FootprintAlpha; + yield return new SpriteRenderable(tile, pos, offset, -511, palette, 1f, sequenceAlpha * traitAlpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); } } }