Unhardcoded SpriteSequence properties

To prepare them for documentation generation.
Also added descriptions to SpriteSequence implementations and their properties.
Also made a few code style fixes.
This commit is contained in:
penev92
2022-03-11 16:11:18 +02:00
committed by Paul Chote
parent d1f7fb8fb8
commit c3c5dbfa35
5 changed files with 195 additions and 90 deletions

View File

@@ -26,24 +26,28 @@ namespace OpenRA.Mods.Cnc.Graphics
} }
} }
[Desc("A sprite sequence that has the oddities that come with first-generation Westwood titles.")]
public class ClassicSpriteSequence : DefaultSpriteSequence public class ClassicSpriteSequence : DefaultSpriteSequence
{ {
readonly bool useClassicFacings; // This needs to be a public property for the documentation generation to work.
[Desc("Incorporate a compensation factor due to the distortion caused by 3D-Studio " +
"when it tried to render 45% angles which was used by Westwood Studios at that time.")]
public bool UseClassicFacings { get; }
public ClassicSpriteSequence(ModData modData, string tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info) public ClassicSpriteSequence(ModData modData, string tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info)
: base(modData, tileSet, cache, loader, sequence, animation, info) : base(modData, tileSet, cache, loader, sequence, animation, info)
{ {
var d = info.ToDictionary(); var d = info.ToDictionary();
useClassicFacings = LoadField(d, "UseClassicFacings", false); UseClassicFacings = LoadField(d, nameof(UseClassicFacings), UseClassicFacings);
if (useClassicFacings && Facings != 32) if (UseClassicFacings && Facings != 32)
throw new InvalidOperationException( throw new InvalidOperationException(
$"{info.Nodes[0].Location}: Sequence {sequence}.{animation}: UseClassicFacings is only valid for 32 facings"); $"{info.Nodes[0].Location}: Sequence {sequence}.{animation}: UseClassicFacings is only valid for 32 facings");
} }
protected override int GetFacingFrameOffset(WAngle facing) protected override int GetFacingFrameOffset(WAngle facing)
{ {
return useClassicFacings ? Util.ClassicIndexFacing(facing, Facings) : Common.Util.IndexFacing(facing, Facings); return UseClassicFacings ? Util.ClassicIndexFacing(facing, Facings) : Common.Util.IndexFacing(facing, Facings);
} }
} }
} }

View File

@@ -41,14 +41,32 @@ namespace OpenRA.Mods.Cnc.Graphics
} }
} }
[Desc("A sprite sequence that can have tileset-specific variants and has the oddities " +
"that come with first-generation Westwood titles.")]
public class ClassicTilesetSpecificSpriteSequence : ClassicSpriteSequence public class ClassicTilesetSpecificSpriteSequence : ClassicSpriteSequence
{ {
// These need to be public properties for the documentation generation to work.
[Desc("Dictionary of <string: string> with tileset name to override -> tileset name to use instead.")]
public static Dictionary<string, string> TilesetOverrides => null;
[Desc("Use `TilesetCodes` as defined in `mod.yaml` to add a letter as a second character " +
"into the sprite filename like the Westwood 2.5D titles did for tileset-specific variants.")]
public static bool UseTilesetCode => false;
[Desc("Append a tileset-specific extension to the file name " +
"- either as defined in `mod.yaml`'s `TilesetExtensions` (if `UseTilesetExtension` is used) " +
"or the default hardcoded one for this sequence type (.shp).")]
public static bool AddExtension => true;
[Desc("Whether `mod.yaml`'s `TilesetExtensions` should be used with the sequence's file name.")]
public static bool UseTilesetExtension { get; private set; }
public ClassicTilesetSpecificSpriteSequence(ModData modData, string tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info) public ClassicTilesetSpecificSpriteSequence(ModData modData, string tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info)
: base(modData, tileSet, cache, loader, sequence, animation, info) { } : base(modData, tileSet, cache, loader, sequence, animation, info) { }
string ResolveTilesetId(string tileSet, Dictionary<string, MiniYaml> d) static string ResolveTilesetId(string tileSet, Dictionary<string, MiniYaml> d)
{ {
if (d.TryGetValue("TilesetOverrides", out var yaml)) if (d.TryGetValue(nameof(TilesetOverrides), out var yaml))
{ {
var tsNode = yaml.Nodes.FirstOrDefault(n => n.Key == tileSet); var tsNode = yaml.Nodes.FirstOrDefault(n => n.Key == tileSet);
if (tsNode != null) if (tsNode != null)
@@ -64,17 +82,16 @@ namespace OpenRA.Mods.Cnc.Graphics
var spriteName = sprite ?? sequence; var spriteName = sprite ?? sequence;
if (LoadField(d, "UseTilesetCode", false)) if (LoadField(d, nameof(UseTilesetCode), UseTilesetCode))
{ {
if (loader.TilesetCodes.TryGetValue(ResolveTilesetId(tileSet, d), out var code)) if (loader.TilesetCodes.TryGetValue(ResolveTilesetId(tileSet, d), out var code))
spriteName = spriteName.Substring(0, 1) + code + spriteName.Substring(2, spriteName.Length - 2); spriteName = spriteName.Substring(0, 1) + code + spriteName.Substring(2, spriteName.Length - 2);
} }
if (LoadField(d, "AddExtension", true)) if (LoadField(d, nameof(AddExtension), AddExtension))
{ {
var useTilesetExtension = LoadField(d, "UseTilesetExtension", false); UseTilesetExtension = LoadField(d, nameof(UseTilesetExtension), UseTilesetExtension);
if (UseTilesetExtension && loader.TilesetExtensions.TryGetValue(ResolveTilesetId(tileSet, d), out var tilesetExtension))
if (useTilesetExtension && loader.TilesetExtensions.TryGetValue(ResolveTilesetId(tileSet, d), out var tilesetExtension))
return spriteName + tilesetExtension; return spriteName + tilesetExtension;
return spriteName + loader.DefaultSpriteExtension; return spriteName + loader.DefaultSpriteExtension;

View File

@@ -122,32 +122,100 @@ namespace OpenRA.Mods.Common.Graphics
float ISpriteSequence.GetAlpha(int frame) { throw exception; } float ISpriteSequence.GetAlpha(int frame) { throw exception; }
} }
[Desc("Generic sprite sequence implementation, mostly unencumbered with game- or artwork-specific logic.")]
public class DefaultSpriteSequence : ISpriteSequence public class DefaultSpriteSequence : ISpriteSequence
{ {
static readonly WDist DefaultShadowSpriteZOffset = new WDist(-5); static readonly WDist DefaultShadowSpriteZOffset = new WDist(-5);
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;
public string Name { get; } public string Name { get; }
public int Start { get; private set; }
public int Length { get; private set; }
public int Stride { get; private set; }
public int Facings { get; }
public int Tick { get; }
public int ZOffset { get; }
public float ZRamp { get; }
public int ShadowStart { get; }
public int ShadowZOffset { get; }
public int[] Frames { get; private set; }
public Rectangle Bounds { get; private set; }
public bool IgnoreWorldTint { get; }
public float Scale { get; }
public readonly uint[] EmbeddedPalette; [Desc("Frame index to start from.")]
public int Start { get; private set; }
[Desc("Number of frames to use. Does not have to be the total amount the sprite sheet has.")]
public int Length { get; private set; } = 1;
[Desc("Multiplier for the number of facings.")]
public int Stride { get; private set; }
[Desc("The amount of directions the unit faces. Use negative values to rotate counter-clockwise.")]
public int Facings { get; } = 1;
[Desc("Time (in milliseconds) to wait until playing the next frame in the animation.")]
public int Tick { get; } = 40;
[Desc("Value controlling the Z-order. A higher values means rendering on top of other sprites at the same position. " +
"Use power of 2 values to avoid glitches.")]
public int ZOffset { get; }
[Desc("")]
public float ZRamp { get; }
[Desc("If the shadow is not part of the sprite, but baked into the same sprite sheet at a fixed offset, " +
"set this to the frame index where it starts.")]
public int ShadowStart { get; } = -1;
[Desc("Set Z-Offset for the separate shadow. Used by the later Westwood 2.5D titles. Defined in WDist units!")]
public int ShadowZOffset { get; }
[Desc("The individual frames to play instead of going through them sequentially from the `Start`.")]
public int[] Frames { get; private set; }
public Rectangle Bounds { get; }
[Desc("Don't apply terrain lighting or colored overlays.")]
public bool IgnoreWorldTint { get; }
[Desc("")]
public float Scale { get; } = 1f;
// These need to be public properties for the documentation generation to work.
[Desc("Play the sprite sequence back and forth.")]
public static bool Reverses => false;
[Desc("Support a frame order where each animation step is split per each direction.")]
public static bool Transpose => false;
[Desc("Mirror on the X axis.")]
public bool FlipX { get; }
[Desc("Mirror on the Y axis.")]
public bool FlipY { get; }
[Desc("Change the position in-game on X, Y, Z.")]
public float3 Offset { get; } = float3.Zero;
[Desc("Apply an OpenGL/Photoshop inspired blend mode.")]
public BlendMode BlendMode { get; } = BlendMode.Alpha;
[Desc("Allows to append multiple sequence definitions which are indented below this node " +
"like when offsets differ per frame or a sequence is spread across individual files.")]
public static object Combine => null;
[Desc("Sets transparency - use one value to set for all frames or provide a value for each frame.")]
public float[] Alpha { get; }
[Desc("Plays a fade out effect.")]
public static bool AlphaFade => false;
[Desc("Name of the file containing the depth data sprite.")]
public string DepthSprite { get; }
[Desc("Frame index containing the depth data.")]
public static int DepthSpriteFrame => 0;
[Desc("")]
public static float2 DepthSpriteOffset => float2.Zero;
[Desc("Use the palette embedded in the defined sprite. (Note: The name given here is actually irrelevant)")]
public static string EmbeddedPalette => null;
public readonly uint[] EmbeddedPaletteData;
protected virtual string GetSpriteSrc(ModData modData, string tileSet, string sequence, string animation, string sprite, Dictionary<string, MiniYaml> d) protected virtual string GetSpriteSrc(ModData modData, string tileSet, string sequence, string animation, string sprite, Dictionary<string, MiniYaml> d)
{ {
@@ -181,39 +249,39 @@ namespace OpenRA.Mods.Common.Graphics
try try
{ {
Start = LoadField(d, "Start", 0); Start = LoadField(d, nameof(Start), 0);
ShadowStart = LoadField(d, "ShadowStart", -1); ShadowStart = LoadField(d, nameof(ShadowStart), ShadowStart);
ShadowZOffset = LoadField(d, "ShadowZOffset", DefaultShadowSpriteZOffset).Length; ShadowZOffset = LoadField(d, nameof(ShadowZOffset), DefaultShadowSpriteZOffset).Length;
ZOffset = LoadField(d, "ZOffset", WDist.Zero).Length; ZOffset = LoadField(d, nameof(ZOffset), WDist.Zero).Length;
ZRamp = LoadField(d, "ZRamp", 0f); ZRamp = LoadField(d, nameof(ZRamp), 0f);
Tick = LoadField(d, "Tick", 40); Tick = LoadField(d, nameof(Tick), Tick);
transpose = LoadField(d, "Transpose", false); transpose = LoadField(d, nameof(Transpose), false);
Frames = LoadField<int[]>(d, "Frames", null); Frames = LoadField<int[]>(d, nameof(Frames), null);
IgnoreWorldTint = LoadField(d, "IgnoreWorldTint", false); IgnoreWorldTint = LoadField(d, nameof(IgnoreWorldTint), false);
Scale = LoadField(d, "Scale", 1f); Scale = LoadField(d, nameof(Scale), Scale);
var flipX = LoadField(d, "FlipX", false); FlipX = LoadField(d, nameof(FlipX), false);
var flipY = LoadField(d, "FlipY", false); FlipY = LoadField(d, nameof(FlipY), false);
Facings = LoadField(d, "Facings", 1); Facings = LoadField(d, nameof(Facings), Facings);
if (Facings < 0) if (Facings < 0)
{ {
reverseFacings = true; reverseFacings = true;
Facings = -Facings; Facings = -Facings;
} }
var offset = LoadField(d, "Offset", float3.Zero); Offset = LoadField(d, nameof(Offset), Offset);
var blendMode = LoadField(d, "BlendMode", BlendMode.Alpha); BlendMode = LoadField(d, nameof(BlendMode), BlendMode);
Func<int, IEnumerable<int>> getUsedFrames = frameCount => Func<int, IEnumerable<int>> getUsedFrames = frameCount =>
{ {
if (d.TryGetValue("Length", out var length) && length.Value == "*") if (d.TryGetValue(nameof(Length), out var length) && length.Value == "*")
Length = Frames != null ? Frames.Length : frameCount - Start; Length = Frames?.Length ?? frameCount - Start;
else else
Length = LoadField(d, "Length", 1); Length = LoadField(d, nameof(Length), Length);
// Plays the animation forwards, and then in reverse // Plays the animation forwards, and then in reverse
if (LoadField(d, "Reverses", false)) if (LoadField(d, nameof(Reverses), false))
{ {
var frames = Frames != null ? Frames.Skip(Start).Take(Length).ToArray() : Exts.MakeArray(Length, i => Start + i); var frames = Frames != null ? Frames.Skip(Start).Take(Length).ToArray() : Exts.MakeArray(Length, i => Start + i);
Frames = frames.Concat(frames.Skip(1).Take(Length - 2).Reverse()).ToArray(); Frames = frames.Concat(frames.Skip(1).Take(Length - 2).Reverse()).ToArray();
@@ -221,7 +289,7 @@ namespace OpenRA.Mods.Common.Graphics
Start = 0; Start = 0;
} }
Stride = LoadField(d, "Stride", Length); Stride = LoadField(d, nameof(Stride), Length);
if (Length > Stride) if (Length > Stride)
throw new YamlException($"Sequence {sequence}.{animation}: Length must be <= stride"); throw new YamlException($"Sequence {sequence}.{animation}: Length must be <= stride");
@@ -263,7 +331,7 @@ namespace OpenRA.Mods.Common.Graphics
return usedFrames; return usedFrames;
}; };
if (d.TryGetValue("Combine", out var combine)) if (d.TryGetValue(nameof(Combine), out var combine))
{ {
var combined = Enumerable.Empty<Sprite>(); var combined = Enumerable.Empty<Sprite>();
foreach (var sub in combine.Nodes) foreach (var sub in combine.Nodes)
@@ -271,19 +339,19 @@ namespace OpenRA.Mods.Common.Graphics
var sd = sub.Value.ToDictionary(); var sd = sub.Value.ToDictionary();
// Allow per-sprite offset, flipping, start, and length // Allow per-sprite offset, flipping, start, and length
var subStart = LoadField(sd, "Start", 0); var subStart = LoadField(sd, nameof(Start), 0);
var subOffset = LoadField(sd, "Offset", float3.Zero); var subOffset = LoadField(sd, nameof(Offset), Offset);
var subFlipX = LoadField(sd, "FlipX", false); var subFlipX = LoadField(sd, nameof(FlipX), false);
var subFlipY = LoadField(sd, "FlipY", false); var subFlipY = LoadField(sd, nameof(FlipY), false);
var subFrames = LoadField<int[]>(sd, "Frames", null); var subFrames = LoadField<int[]>(sd, nameof(Frames), null);
var subLength = 0; var subLength = 0;
Func<int, IEnumerable<int>> subGetUsedFrames = subFrameCount => Func<int, IEnumerable<int>> subGetUsedFrames = subFrameCount =>
{ {
if (sd.TryGetValue("Length", out var subLengthYaml) && subLengthYaml.Value == "*") if (sd.TryGetValue(nameof(Length), out var subLengthYaml) && subLengthYaml.Value == "*")
subLength = subFrames != null ? subFrames.Length : subFrameCount - subStart; subLength = subFrames != null ? subFrames.Length : subFrameCount - subStart;
else else
subLength = LoadField(sd, "Length", 1); subLength = LoadField(sd, nameof(Length), Length);
return subFrames != null ? subFrames.Skip(subStart).Take(subLength) : Enumerable.Range(subStart, subLength); return subFrames != null ? subFrames.Skip(subStart).Take(subLength) : Enumerable.Range(subStart, subLength);
}; };
@@ -295,11 +363,11 @@ namespace OpenRA.Mods.Common.Graphics
return null; return null;
var bounds = FlipRectangle(s.Bounds, subFlipX, subFlipY); var bounds = FlipRectangle(s.Bounds, subFlipX, subFlipY);
var dx = subOffset.X + offset.X + (subFlipX ? -s.Offset.X : s.Offset.X); var dx = subOffset.X + Offset.X + (subFlipX ? -s.Offset.X : s.Offset.X);
var dy = subOffset.Y + offset.Y + (subFlipY ? -s.Offset.Y : s.Offset.Y); var dy = subOffset.Y + Offset.Y + (subFlipY ? -s.Offset.Y : s.Offset.Y);
var dz = subOffset.Z + offset.Z + s.Offset.Z + ZRamp * dy; var dz = subOffset.Z + Offset.Z + s.Offset.Z + ZRamp * dy;
return new Sprite(s.Sheet, bounds, ZRamp, new float3(dx, dy, dz), s.Channel, blendMode); return new Sprite(s.Sheet, bounds, ZRamp, new float3(dx, dy, dz), s.Channel, BlendMode);
}).ToList(); }).ToList();
var frames = subFrames != null ? subFrames.Skip(subStart).Take(subLength).ToArray() : Exts.MakeArray(subLength, i => subStart + i); var frames = subFrames != null ? subFrames.Skip(subStart).Take(subLength).ToArray() : Exts.MakeArray(subLength, i => subStart + i);
@@ -319,39 +387,39 @@ namespace OpenRA.Mods.Common.Graphics
if (s == null) if (s == null)
return null; return null;
var bounds = FlipRectangle(s.Bounds, flipX, flipY); var bounds = FlipRectangle(s.Bounds, FlipX, FlipY);
var dx = offset.X + (flipX ? -s.Offset.X : s.Offset.X); var dx = Offset.X + (FlipX ? -s.Offset.X : s.Offset.X);
var dy = offset.Y + (flipY ? -s.Offset.Y : s.Offset.Y); var dy = Offset.Y + (FlipY ? -s.Offset.Y : s.Offset.Y);
var dz = offset.Z + s.Offset.Z + ZRamp * dy; var dz = Offset.Z + s.Offset.Z + ZRamp * dy;
return new Sprite(s.Sheet, bounds, ZRamp, new float3(dx, dy, dz), s.Channel, blendMode); return new Sprite(s.Sheet, bounds, ZRamp, new float3(dx, dy, dz), s.Channel, BlendMode);
}).ToArray(); }).ToArray();
} }
alpha = LoadField(d, "Alpha", (float[])null); Alpha = LoadField(d, nameof(Alpha), (float[])null);
if (alpha != null) if (Alpha != null)
{ {
if (alpha.Length == 1) if (Alpha.Length == 1)
alpha = Exts.MakeArray(Length, _ => alpha[0]); Alpha = Exts.MakeArray(Length, _ => Alpha[0]);
else if (alpha.Length != Length) else if (Alpha.Length != Length)
throw new YamlException($"Sequence {sequence}.{animation} must define either 1 or {Length} Alpha values."); throw new YamlException($"Sequence {sequence}.{animation} must define either 1 or {Length} Alpha values.");
} }
if (LoadField(d, "AlphaFade", false)) if (LoadField(d, nameof(AlphaFade), false))
{ {
if (alpha != null) if (Alpha != null)
throw new YamlException($"Sequence {sequence}.{animation} cannot define both AlphaFade and Alpha."); throw new YamlException($"Sequence {sequence}.{animation} cannot define both AlphaFade and Alpha.");
alpha = Exts.MakeArray(Length, i => float2.Lerp(1f, 0f, i / (Length - 1f))); Alpha = Exts.MakeArray(Length, i => float2.Lerp(1f, 0f, i / (Length - 1f)));
} }
var depthSprite = LoadField<string>(d, "DepthSprite", null); DepthSprite = LoadField<string>(d, nameof(DepthSprite), null);
if (!string.IsNullOrEmpty(depthSprite)) if (!string.IsNullOrEmpty(DepthSprite))
{ {
var depthSpriteFrame = LoadField(d, "DepthSpriteFrame", 0); var depthSpriteFrame = LoadField(d, nameof(DepthSpriteFrame), 0);
var depthOffset = LoadField(d, "DepthSpriteOffset", float2.Zero); var depthOffset = LoadField(d, nameof(DepthSpriteOffset), DepthSpriteOffset);
Func<int, IEnumerable<int>> getDepthFrame = _ => new int[] { depthSpriteFrame }; IEnumerable<int> GetDepthFrame(int _) => new[] { depthSpriteFrame };
var ds = cache[depthSprite, getDepthFrame][depthSpriteFrame]; var ds = cache[DepthSprite, GetDepthFrame][depthSpriteFrame];
sprites = sprites.Select(s => sprites = sprites.Select(s =>
{ {
@@ -368,15 +436,15 @@ namespace OpenRA.Mods.Common.Graphics
}).ToArray(); }).ToArray();
} }
var exportPalette = LoadField<string>(d, "EmbeddedPalette", null); var exportPalette = LoadField<string>(d, nameof(EmbeddedPalette), null);
if (exportPalette != null) if (exportPalette != null)
{ {
var src = GetSpriteSrc(modData, tileSet, sequence, animation, info.Value, d); var src = GetSpriteSrc(modData, tileSet, sequence, animation, info.Value, d);
var metadata = cache.FrameMetadata(src); var metadata = cache.FrameMetadata(src);
var i = Frames != null ? Frames[0] : Start; var i = Frames != null ? Frames[0] : Start;
var palettes = metadata != null ? metadata.GetOrDefault<EmbeddedSpritePalette>() : null; var palettes = metadata?.GetOrDefault<EmbeddedSpritePalette>();
if (palettes == null || !palettes.TryGetPaletteForFrame(i, out EmbeddedPalette)) if (palettes == null || !palettes.TryGetPaletteForFrame(i, out EmbeddedPaletteData))
throw new YamlException($"Cannot export palettes from {src}: frame {i} does not define an embedded palette"); throw new YamlException($"Cannot export palettes from {src}: frame {i} does not define an embedded palette");
} }
@@ -449,7 +517,7 @@ namespace OpenRA.Mods.Common.Graphics
public virtual float GetAlpha(int frame) public virtual float GetAlpha(int frame)
{ {
return alpha?[frame] ?? 1f; return Alpha?[frame] ?? 1f;
} }
} }
} }

View File

@@ -41,14 +41,31 @@ namespace OpenRA.Mods.Common.Graphics
} }
} }
[Desc("A sprite sequence that can have tileset-specific variants.")]
public class TilesetSpecificSpriteSequence : DefaultSpriteSequence public class TilesetSpecificSpriteSequence : DefaultSpriteSequence
{ {
// These need to be public properties for the documentation generation to work.
[Desc("Dictionary of <string: string> with tileset name to override -> tileset name to use instead.")]
public static Dictionary<string, string> TilesetOverrides => null;
[Desc("Use `TilesetCodes` as defined in `mod.yaml` to add a letter as a second character " +
"into the sprite filename like the Westwood 2.5D titles did for tileset-specific variants.")]
public static bool UseTilesetCode => false;
[Desc("Append a tileset-specific extension to the file name " +
"- either as defined in `mod.yaml`'s `TilesetExtensions` (if `UseTilesetExtension` is used) " +
"or the default hardcoded one for this sequence type (.shp).")]
public static bool AddExtension => true;
[Desc("Whether `mod.yaml`'s `TilesetExtensions` should be used with the sequence's file name.")]
public static bool UseTilesetExtension { get; private set; }
public TilesetSpecificSpriteSequence(ModData modData, string tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info) public TilesetSpecificSpriteSequence(ModData modData, string tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info)
: base(modData, tileSet, cache, loader, sequence, animation, info) { } : base(modData, tileSet, cache, loader, sequence, animation, info) { }
string ResolveTilesetId(string tileSet, Dictionary<string, MiniYaml> d) static string ResolveTilesetId(string tileSet, Dictionary<string, MiniYaml> d)
{ {
if (d.TryGetValue("TilesetOverrides", out var yaml)) if (d.TryGetValue(nameof(TilesetOverrides), out var yaml))
{ {
var tsNode = yaml.Nodes.FirstOrDefault(n => n.Key == tileSet); var tsNode = yaml.Nodes.FirstOrDefault(n => n.Key == tileSet);
if (tsNode != null) if (tsNode != null)
@@ -64,17 +81,16 @@ namespace OpenRA.Mods.Common.Graphics
var spriteName = sprite ?? sequence; var spriteName = sprite ?? sequence;
if (LoadField(d, "UseTilesetCode", false)) if (LoadField(d, nameof(UseTilesetCode), UseTilesetCode))
{ {
if (loader.TilesetCodes.TryGetValue(ResolveTilesetId(tileSet, d), out var code)) if (loader.TilesetCodes.TryGetValue(ResolveTilesetId(tileSet, d), out var code))
spriteName = spriteName.Substring(0, 1) + code + spriteName.Substring(2, spriteName.Length - 2); spriteName = spriteName.Substring(0, 1) + code + spriteName.Substring(2, spriteName.Length - 2);
} }
if (LoadField(d, "AddExtension", true)) if (LoadField(d, nameof(AddExtension), AddExtension))
{ {
var useTilesetExtension = LoadField(d, "UseTilesetExtension", false); UseTilesetExtension = LoadField(d, nameof(UseTilesetExtension), UseTilesetExtension);
if (UseTilesetExtension && loader.TilesetExtensions.TryGetValue(ResolveTilesetId(tileSet, d), out var tilesetExtension))
if (useTilesetExtension && loader.TilesetExtensions.TryGetValue(ResolveTilesetId(tileSet, d), out var tilesetExtension))
return spriteName + tilesetExtension; return spriteName + tilesetExtension;
return spriteName + loader.DefaultSpriteExtension; return spriteName + loader.DefaultSpriteExtension;

View File

@@ -47,7 +47,7 @@ namespace OpenRA.Mods.Common.Traits
ImmutablePalette IProvidesCursorPaletteInfo.ReadPalette(IReadOnlyFileSystem fileSystem) ImmutablePalette IProvidesCursorPaletteInfo.ReadPalette(IReadOnlyFileSystem fileSystem)
{ {
var sequence = (DefaultSpriteSequence)Game.ModData.DefaultSequences.Values.First().GetSequence(Image, Sequence); var sequence = (DefaultSpriteSequence)Game.ModData.DefaultSequences.Values.First().GetSequence(Image, Sequence);
return new ImmutablePalette(sequence.EmbeddedPalette); return new ImmutablePalette(sequence.EmbeddedPaletteData);
} }
} }
@@ -59,7 +59,7 @@ namespace OpenRA.Mods.Common.Traits
public void LoadPalettes(WorldRenderer wr) public void LoadPalettes(WorldRenderer wr)
{ {
var sequence = (DefaultSpriteSequence)wr.World.Map.Rules.Sequences.GetSequence(info.Image, info.Sequence); var sequence = (DefaultSpriteSequence)wr.World.Map.Rules.Sequences.GetSequence(info.Image, info.Sequence);
wr.AddPalette(info.Name, new ImmutablePalette(sequence.EmbeddedPalette), info.AllowModifiers); wr.AddPalette(info.Name, new ImmutablePalette(sequence.EmbeddedPaletteData), info.AllowModifiers);
} }
public IEnumerable<string> PaletteNames { get { yield return info.Name; } } public IEnumerable<string> PaletteNames { get { yield return info.Name; } }