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.
This commit is contained in:
Paul Chote
2021-01-31 23:24:12 +00:00
committed by teinarss
parent 445d943549
commit 0975102e92
23 changed files with 189 additions and 78 deletions

View File

@@ -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<string>(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;
}
}
}

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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; } }

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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))
};
}

View File

@@ -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;
}

View File

@@ -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<Rectangle> IRender.ScreenBounds(Actor self, WorldRenderer wr)

View File

@@ -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;
}

View File

@@ -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)
};
}
}

View File

@@ -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<Order> 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)

View File

@@ -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));
}
}
}

View File

@@ -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; } }

View File

@@ -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);
}
}
}