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

@@ -55,12 +55,13 @@ namespace OpenRA.Graphics
public IRenderable[] Render(WPos pos, WVec offset, int zOffset, PaletteReference palette) public IRenderable[] Render(WPos pos, WVec offset, int zOffset, PaletteReference palette)
{ {
var tintModifiers = CurrentSequence.IgnoreWorldTint ? TintModifiers.IgnoreWorldTint : TintModifiers.None; 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) if (CurrentSequence.ShadowStart >= 0)
{ {
var shadow = CurrentSequence.GetShadow(CurrentFrame, facingFunc()); 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 }; return new IRenderable[] { shadowRenderable, imageRenderable };
} }
@@ -72,7 +73,8 @@ namespace OpenRA.Graphics
scale *= CurrentSequence.Scale; scale *= CurrentSequence.Scale;
var screenOffset = (scale * wr.ScreenVectorComponents(offset)).XY.ToInt2(); 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 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) if (CurrentSequence.ShadowStart >= 0)
{ {

View File

@@ -38,6 +38,7 @@ namespace OpenRA.Graphics
Sprite GetSprite(int frame); Sprite GetSprite(int frame);
Sprite GetSprite(int frame, WAngle facing); Sprite GetSprite(int frame, WAngle facing);
Sprite GetShadow(int frame, WAngle facing); Sprite GetShadow(int frame, WAngle facing);
float GetAlpha(int frame);
} }
public interface ISpriteSequenceLoader public interface ISpriteSequenceLoader

View File

@@ -29,12 +29,6 @@ namespace OpenRA.Graphics
readonly float alpha; readonly float alpha;
readonly bool isDecoration; 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) 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; this.sprite = sprite;

View File

@@ -21,8 +21,9 @@ namespace OpenRA.Graphics
readonly int zOffset; readonly int zOffset;
readonly PaletteReference palette; readonly PaletteReference palette;
readonly float scale; 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.sprite = sprite;
this.effectiveWorldPos = effectiveWorldPos; this.effectiveWorldPos = effectiveWorldPos;
@@ -30,6 +31,7 @@ namespace OpenRA.Graphics
this.zOffset = zOffset; this.zOffset = zOffset;
this.palette = palette; this.palette = palette;
this.scale = scale; this.scale = scale;
this.alpha = alpha;
} }
// Does not exist in the world, so a world positions don't make sense // 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 PaletteReference Palette { get { return palette; } }
public int ZOffset { get { return zOffset; } } 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 WithZOffset(int newOffset) { return this; }
public IRenderable OffsetBy(WVec vec) { return this; } public IRenderable OffsetBy(WVec vec) { return this; }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
@@ -48,7 +50,7 @@ namespace OpenRA.Graphics
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
public void Render(WorldRenderer wr) 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) public void RenderDebugGeometry(WorldRenderer wr)

View File

@@ -149,7 +149,7 @@ namespace OpenRA.Mods.Cnc.Graphics
var pos = wr.ProjectedPosition((z + new float2(step[2], step[3])).ToInt2()); var pos = wr.ProjectedPosition((z + new float2(step[2], step[3])).ToInt2());
var tintModifiers = s.IgnoreWorldTint ? TintModifiers.IgnoreWorldTint : TintModifiers.None; 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]); z += new float2(step[0], step[1]);
if (rs.Count >= 1000) if (rs.Count >= 1000)

View File

@@ -200,9 +200,8 @@ namespace OpenRA.Mods.Cnc.Traits
{ {
readonly List<Actor> minelayers; readonly List<Actor> minelayers;
readonly Minelayer minelayer; readonly Minelayer minelayer;
readonly Sprite tileOk; readonly Sprite validTile, unknownTile, blockedTile;
readonly Sprite tileUnknown; readonly float validAlpha, unknownAlpha, blockedAlpha;
readonly Sprite tileBlocked;
readonly CPos minefieldStart; readonly CPos minefieldStart;
readonly bool queued; readonly bool queued;
@@ -215,19 +214,43 @@ namespace OpenRA.Mods.Cnc.Traits
minelayer = a.Trait<Minelayer>(); minelayer = a.Trait<Minelayer>();
var tileset = a.World.Map.Tileset.ToLowerInvariant(); var tileset = a.World.Map.Tileset.ToLowerInvariant();
if (a.World.Map.Rules.Sequences.HasSequence("overlay", "{0}-{1}".F(minelayer.Info.TileValidName, tileset))) 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 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))) 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 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))) 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 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) public void AddMinelayer(Actor a, CPos xy)
@@ -276,18 +299,31 @@ namespace OpenRA.Mods.Cnc.Traits
var pal = wr.Palette(TileSet.TerrainPaletteInternalName); var pal = wr.Palette(TileSet.TerrainPaletteInternalName);
foreach (var c in minefield) foreach (var c in minefield)
{ {
var tile = tileOk; var tile = validTile;
var alpha = validAlpha;
if (!world.Map.Contains(c)) if (!world.Map.Contains(c))
tile = tileBlocked; {
tile = blockedTile;
alpha = blockedAlpha;
}
else if (world.ShroudObscures(c)) else if (world.ShroudObscures(c))
tile = tileBlocked; {
tile = blockedTile;
alpha = blockedAlpha;
}
else if (world.FogObscures(c)) else if (world.FogObscures(c))
tile = tileUnknown; {
tile = unknownTile;
alpha = unknownAlpha;
}
else if (!this.minelayer.IsCellAcceptable(minelayer, c) else if (!this.minelayer.IsCellAcceptable(minelayer, c)
|| !movement.CanEnterCell(c, null, BlockedByActor.Immovable) || (mobile != null && !mobile.CanStayInCell(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);
} }
} }

View File

@@ -143,6 +143,7 @@ namespace OpenRA.Mods.Cnc.Traits
readonly char[] footprint; readonly char[] footprint;
readonly CVec dimensions; readonly CVec dimensions;
readonly Sprite tile; readonly Sprite tile;
readonly float alpha;
readonly SupportPowerManager manager; readonly SupportPowerManager manager;
readonly string order; readonly string order;
@@ -157,9 +158,11 @@ namespace OpenRA.Mods.Cnc.Traits
this.power = power; this.power = power;
var info = (ChronoshiftPowerInfo)power.Info; 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(); footprint = info.Footprint.Where(c => !char.IsWhiteSpace(c)).ToArray();
dimensions = info.Dimensions; 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<Order> OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) protected override IEnumerable<Order> 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 tiles = power.CellsMatching(xy, footprint, dimensions);
var palette = wr.Palette(((ChronoshiftPowerInfo)power.Info).TargetOverlayPalette); var palette = wr.Palette(((ChronoshiftPowerInfo)power.Info).TargetOverlayPalette);
foreach (var t in tiles) 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) 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 char[] footprint;
readonly CVec dimensions; readonly CVec dimensions;
readonly Sprite validTile, invalidTile, sourceTile; readonly Sprite validTile, invalidTile, sourceTile;
readonly float validAlpha, invalidAlpha, sourceAlpha;
readonly SupportPowerManager manager; readonly SupportPowerManager manager;
readonly string order; readonly string order;
@@ -236,12 +240,25 @@ namespace OpenRA.Mods.Cnc.Traits
var sequences = world.Map.Rules.Sequences; var sequences = world.Map.Rules.Sequences;
var tilesetValid = info.ValidFootprintSequence + "-" + world.Map.Tileset.ToLowerInvariant(); var tilesetValid = info.ValidFootprintSequence + "-" + world.Map.Tileset.ToLowerInvariant();
if (sequences.HasSequence(info.FootprintImage, tilesetValid)) 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 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); var invalidSequence = sequences.GetSequence(info.FootprintImage, info.InvalidFootprintSequence);
sourceTile = sequences.GetSequence(info.FootprintImage, info.SourceFootprintSequence).GetSprite(0); 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<Order> OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) protected override IEnumerable<Order> OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi)
@@ -287,8 +304,10 @@ namespace OpenRA.Mods.Cnc.Traits
var delta = xy - sourceLocation; var delta = xy - sourceLocation;
foreach (var t in power.CellsMatching(sourceLocation, footprint, dimensions)) foreach (var t in power.CellsMatching(sourceLocation, footprint, dimensions))
{ {
var tile = manager.Self.Owner.Shroud.IsExplored(t + delta) ? validTile : invalidTile; var isValid = manager.Self.Owner.Shroud.IsExplored(t + delta);
yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t + delta), WVec.Zero, -511, palette, 1f, true, TintModifiers.IgnoreWorldTint); 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 // Unit previews
@@ -300,7 +319,8 @@ namespace OpenRA.Mods.Cnc.Traits
var canEnter = manager.Self.Owner.Shroud.IsExplored(targetCell) && var canEnter = manager.Self.Owner.Shroud.IsExplored(targetCell) &&
unit.Trait<Chronoshiftable>().CanChronoshiftTo(unit, targetCell); unit.Trait<Chronoshiftable>().CanChronoshiftTo(unit, targetCell);
var tile = canEnter ? validTile : invalidTile; 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); var offset = world.Map.CenterOfCell(xy) - world.Map.CenterOfCell(sourceLocation);
@@ -330,7 +350,7 @@ namespace OpenRA.Mods.Cnc.Traits
// Source tiles // Source tiles
foreach (var t in power.CellsMatching(sourceLocation, footprint, dimensions)) 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) bool IsValidTarget(CPos xy)

View File

@@ -117,6 +117,7 @@ namespace OpenRA.Mods.Common.Graphics
Sprite ISpriteSequence.GetSprite(int frame) { throw exception; } Sprite ISpriteSequence.GetSprite(int frame) { throw exception; }
Sprite ISpriteSequence.GetSprite(int frame, WAngle facing) { throw exception; } Sprite ISpriteSequence.GetSprite(int frame, WAngle facing) { throw exception; }
Sprite ISpriteSequence.GetShadow(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 public class DefaultSpriteSequence : ISpriteSequence
@@ -125,6 +126,7 @@ namespace OpenRA.Mods.Common.Graphics
protected Sprite[] sprites; protected Sprite[] sprites;
readonly bool reverseFacings, transpose; readonly bool reverseFacings, transpose;
readonly string sequence; readonly string sequence;
readonly float[] alpha;
protected readonly ISpriteSequenceLoader Loader; protected readonly ISpriteSequenceLoader Loader;
@@ -316,6 +318,23 @@ namespace OpenRA.Mods.Common.Graphics
s.Channel, blendMode) : null).ToArray(); 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); var depthSprite = LoadField<string>(d, "DepthSprite", null);
if (!string.IsNullOrEmpty(depthSprite)) if (!string.IsNullOrEmpty(depthSprite))
{ {
@@ -418,5 +437,10 @@ namespace OpenRA.Mods.Common.Graphics
{ {
return Util.IndexFacing(facing, Facings); 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( return footprint.Select(c => (IRenderable)(new SpriteRenderable(
terrainRenderer.TileSprite(new TerrainTile(template, c.Value)), 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; bool initialized;

View File

@@ -51,8 +51,8 @@ namespace OpenRA.Mods.Common.Traits
readonly FootprintPlaceBuildingPreviewInfo info; readonly FootprintPlaceBuildingPreviewInfo info;
readonly IPlaceBuildingDecorationInfo[] decorations; readonly IPlaceBuildingDecorationInfo[] decorations;
readonly int2 topLeftScreenOffset; readonly int2 topLeftScreenOffset;
readonly Sprite buildOk; readonly Sprite validTile, blockedTile;
readonly Sprite buildBlocked; readonly float validAlpha, blockedAlpha;
public FootprintPlaceBuildingPreviewPreview(WorldRenderer wr, ActorInfo ai, FootprintPlaceBuildingPreviewInfo info, TypeDictionary init) 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(); var tileset = world.Map.Tileset.ToLowerInvariant();
if (world.Map.Rules.Sequences.HasSequence("overlay", "build-valid-{0}".F(tileset))) 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 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() { } protected virtual void TickInner() { }
@@ -84,11 +95,12 @@ namespace OpenRA.Mods.Common.Traits
if ((c.Value & filter) == 0) if ((c.Value & filter) == 0)
continue; 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 pos = wr.World.Map.CenterOfCell(c.Key);
var offset = new WVec(0, 0, topLeftPos.Z - pos.Z); var offset = new WVec(0, 0, topLeftPos.Z - pos.Z);
var alpha = (c.Value & PlaceBuildingCellType.LineBuild) != 0 ? info.LineBuildFootprintAlpha : info.FootprintAlpha; var traitAlpha = (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); 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) if (!a.IsCanceling)
foreach (var n in a.TargetLineNodes(self)) foreach (var n in a.TargetLineNodes(self))
if (n.Tile != null && n.Target.Type != TargetType.Invalid) 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; } } 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++) for (var i = 0; i < pipCount; i++)
{ {
pips.PlayRepeating(currentAmmo * pipCount > i * totalAmmo ? Info.FullSequence : Info.EmptySequence); 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; screenPos += pipStride;
} }

View File

@@ -92,7 +92,7 @@ namespace OpenRA.Mods.Common.Traits.Render
for (var i = 0; i < pipCount; i++) for (var i = 0; i < pipCount; i++)
{ {
pips.PlayRepeating(GetPipSequence(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; screenPos += pipStride;
} }

View File

@@ -62,7 +62,7 @@ namespace OpenRA.Mods.Common.Traits.Render
return new IRenderable[] 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++) for (var i = 0; i < Info.PipCount; i++)
{ {
pips.PlayRepeating(GetPipSequence(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; screenPos += pipStride;
} }

View File

@@ -180,8 +180,9 @@ namespace OpenRA.Mods.Common.Traits.Render
var dat = self.World.Map.DistanceAboveTerrain(self.CenterPosition); var dat = self.World.Map.DistanceAboveTerrain(self.CenterPosition);
var pos = self.CenterPosition - new WVec(0, 0, dat.Length); var pos = self.CenterPosition - new WVec(0, 0, dat.Length);
var palette = wr.Palette(info.Palette); var palette = wr.Palette(info.Palette);
var alpha = shadow.CurrentSequence.GetAlpha(shadow.CurrentFrame);
var tintModifiers = shadow.CurrentSequence.IgnoreWorldTint ? TintModifiers.ReplaceColor | TintModifiers.IgnoreWorldTint : TintModifiers.ReplaceColor; 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) 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++) for (var i = 0; i < Info.PipCount; i++)
{ {
pips.PlayRepeating(player.Resources * Info.PipCount > i * player.ResourceCapacity ? Info.FullSequence : Info.EmptySequence); 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; screenPos += pipStride;
} }

View File

@@ -65,7 +65,7 @@ namespace OpenRA.Mods.Common.Traits.Render
var palette = wr.Palette(Info.Palette); var palette = wr.Palette(Info.Palette);
return new IRenderable[] 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 char[] footprint;
readonly CVec dimensions; readonly CVec dimensions;
readonly Sprite tile; readonly Sprite tile;
readonly float alpha;
readonly SupportPowerManager manager; readonly SupportPowerManager manager;
readonly string order; readonly string order;
@@ -124,7 +125,10 @@ namespace OpenRA.Mods.Common.Traits
this.power = power; this.power = power;
footprint = power.info.Footprint.Where(c => !char.IsWhiteSpace(c)).ToArray(); footprint = power.info.Footprint.Where(c => !char.IsWhiteSpace(c)).ToArray();
dimensions = power.info.Dimensions; 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) 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); var pal = wr.Palette(TileSet.TerrainPaletteInternalName);
foreach (var t in power.CellsMatching(xy, footprint, dimensions)) 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) 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 sequence = wr.World.Map.Rules.Sequences.GetSequence("resources", variant);
var sprite = sequence.GetSprite(Resource.MaxDensity - 1); var sprite = sequence.GetSprite(Resource.MaxDensity - 1);
var palette = wr.Palette(Resource.Palette); var palette = wr.Palette(Resource.Palette);
var alpha = sequence.GetAlpha(Resource.MaxDensity - 1);
var tintModifiers = sequence.IgnoreWorldTint ? TintModifiers.IgnoreWorldTint : TintModifiers.None; 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 EditorSelectionLayerInfo info;
readonly Map map; readonly Map map;
readonly Sprite copySprite; readonly Sprite copyTile, pasteTile;
readonly Sprite pasteSprite; readonly float copyAlpha, pasteAlpha;
PaletteReference palette; PaletteReference palette;
public CellRegion CopyRegion { get; private set; } public CellRegion CopyRegion { get; private set; }
@@ -57,8 +57,14 @@ namespace OpenRA.Mods.Common.Traits
this.info = info; this.info = info;
map = self.World.Map; 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) void IWorldLoaded.WorldLoaded(World w, WorldRenderer wr)
@@ -91,13 +97,13 @@ namespace OpenRA.Mods.Common.Traits
if (CopyRegion != null) if (CopyRegion != null)
foreach (var c in CopyRegion) foreach (var c in CopyRegion)
yield return new SpriteRenderable(copySprite, wr.World.Map.CenterOfCell(c), yield return new SpriteRenderable(copyTile, wr.World.Map.CenterOfCell(c),
WVec.Zero, -511, palette, 1f, info.FootprintAlpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); WVec.Zero, -511, palette, 1f, copyAlpha * info.FootprintAlpha, float3.Ones, TintModifiers.IgnoreWorldTint, true);
if (PasteRegion != null) if (PasteRegion != null)
foreach (var c in PasteRegion) foreach (var c in PasteRegion)
yield return new SpriteRenderable(pasteSprite, wr.World.Map.CenterOfCell(c), yield return new SpriteRenderable(pasteTile, wr.World.Map.CenterOfCell(c),
WVec.Zero, -511, palette, 1f, info.FootprintAlpha, float3.Ones, TintModifiers.IgnoreWorldTint, true); WVec.Zero, -511, palette, 1f, pasteAlpha * info.FootprintAlpha, float3.Ones, TintModifiers.IgnoreWorldTint, true);
} }
bool IRenderAboveShroud.SpatiallyPartitionable { get { return false; } } 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 offset = map.Offset(new CVec(x, y), tileInfo.Height);
var palette = wr.Palette(template.Palette ?? TileSet.TerrainPaletteInternalName); 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);
} }
} }
} }

View File

@@ -45,9 +45,8 @@ namespace OpenRA.Mods.D2k.Traits
{ {
readonly D2kActorPreviewPlaceBuildingPreviewInfo info; readonly D2kActorPreviewPlaceBuildingPreviewInfo info;
readonly bool checkUnsafeTiles; readonly bool checkUnsafeTiles;
readonly Sprite buildOk; readonly Sprite validTile, unsafeTile, blockedTile;
readonly Sprite buildUnsafe; readonly float validAlpha, unsafeAlpha, blockedAlpha;
readonly Sprite buildBlocked;
readonly CachedTransform<CPos, List<CPos>> unpathableCells; readonly CachedTransform<CPos, List<CPos>> unpathableCells;
public D2kActorPreviewPlaceBuildingPreviewPreview(WorldRenderer wr, ActorInfo ai, D2kActorPreviewPlaceBuildingPreviewInfo info, TypeDictionary init) public D2kActorPreviewPlaceBuildingPreviewPreview(WorldRenderer wr, ActorInfo ai, D2kActorPreviewPlaceBuildingPreviewInfo info, TypeDictionary init)
@@ -61,9 +60,17 @@ namespace OpenRA.Mods.D2k.Traits
var techTree = init.Get<OwnerInit>().Value(world).PlayerActor.Trait<TechTree>(); var techTree = init.Get<OwnerInit>().Value(world).PlayerActor.Trait<TechTree>();
checkUnsafeTiles = info.RequiresPrerequisites.Any() && techTree.HasPrerequisites(info.RequiresPrerequisites); checkUnsafeTiles = info.RequiresPrerequisites.Any() && techTree.HasPrerequisites(info.RequiresPrerequisites);
buildOk = sequences.GetSequence("overlay", "build-valid").GetSprite(0); var validSequence = sequences.GetSequence("overlay", "build-valid");
buildUnsafe = sequences.GetSequence("overlay", "build-unsafe").GetSprite(0); validTile = validSequence.GetSprite(0);
buildBlocked = sequences.GetSequence("overlay", "build-invalid").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<BuildingInfo>(); var buildingInfo = ai.TraitInfo<BuildingInfo>();
unpathableCells = new CachedTransform<CPos, List<CPos>>(topLeft => buildingInfo.OccupiedTiles(topLeft).ToList()); unpathableCells = new CachedTransform<CPos, List<CPos>>(topLeft => buildingInfo.OccupiedTiles(topLeft).ToList());
@@ -81,14 +88,14 @@ namespace OpenRA.Mods.D2k.Traits
if ((c.Value & filter) == 0) if ((c.Value & filter) == 0)
continue; continue;
var tile = (c.Value & PlaceBuildingCellType.Invalid) != 0 ? buildBlocked : var isUnsafe = checkUnsafeTiles && candidateSafeTiles.Contains(c.Key) && info.UnsafeTerrainTypes.Contains(wr.World.Map.GetTerrainInfo(c.Key).Type);
(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;
? buildUnsafe : buildOk; var sequenceAlpha = (c.Value & PlaceBuildingCellType.Invalid) != 0 ? blockedAlpha : isUnsafe ? unsafeAlpha : validAlpha;
var pos = wr.World.Map.CenterOfCell(c.Key); var pos = wr.World.Map.CenterOfCell(c.Key);
var offset = new WVec(0, 0, topLeftPos.Z - pos.Z); var offset = new WVec(0, 0, topLeftPos.Z - pos.Z);
var alpha = (c.Value & PlaceBuildingCellType.LineBuild) != 0 ? info.LineBuildFootprintAlpha : info.FootprintAlpha; var traitAlpha = (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); yield return new SpriteRenderable(tile, pos, offset, -511, palette, 1f, sequenceAlpha * traitAlpha, float3.Ones, TintModifiers.IgnoreWorldTint, true);
} }
} }
} }