Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul sequence filename definitions #20580

Merged
merged 4 commits into from
Jan 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions OpenRA.Mods.Cnc/Graphics/ClassicSpriteSequence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public class ClassicSpriteSequenceLoader : DefaultSpriteSequenceLoader
public ClassicSpriteSequenceLoader(ModData modData)
: base(modData) { }

public override ISpriteSequence CreateSequence(ModData modData, string tileSet, SpriteCache cache, string sequence, string animation, MiniYaml info)
public override ISpriteSequence CreateSequence(ModData modData, string tileset, SpriteCache cache, string image, string sequence, MiniYaml data, MiniYaml defaults)
pchote marked this conversation as resolved.
Show resolved Hide resolved
{
return new ClassicSpriteSequence(modData, tileSet, cache, this, sequence, animation, info);
return new ClassicSpriteSequence(modData, tileset, cache, this, image, sequence, data, defaults);
}
}

Expand All @@ -33,15 +33,13 @@ public class ClassicSpriteSequence : DefaultSpriteSequence
static readonly SpriteSequenceField<bool> UseClassicFacings = new SpriteSequenceField<bool>(nameof(UseClassicFacings), false);
readonly bool useClassicFacings;

public ClassicSpriteSequence(ModData modData, string tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info)
: base(modData, tileSet, cache, loader, sequence, animation, info)
public ClassicSpriteSequence(ModData modData, string tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string image, string sequence, MiniYaml data, MiniYaml defaults)
: base(modData, tileSet, cache, loader, image, sequence, data, defaults)
{
var d = info.ToDictionary();
useClassicFacings = LoadField(d, UseClassicFacings);
useClassicFacings = LoadField(UseClassicFacings, data, defaults);

if (useClassicFacings && facings != 32)
throw new InvalidOperationException(
$"{info.Nodes[0].Location}: Sequence {sequence}.{animation}: UseClassicFacings is only valid for 32 facings");
pchote marked this conversation as resolved.
Show resolved Hide resolved
throw new InvalidOperationException($"Sequence {image}.{sequence}: UseClassicFacings is only valid for 32 facings");
}

protected override int GetFacingFrameOffset(WAngle facing)
Expand Down
77 changes: 14 additions & 63 deletions OpenRA.Mods.Cnc/Graphics/ClassicTilesetSpecificSpriteSequence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,85 +18,36 @@ namespace OpenRA.Mods.Cnc.Graphics
{
public class ClassicTilesetSpecificSpriteSequenceLoader : ClassicSpriteSequenceLoader
{
public readonly string DefaultSpriteExtension = ".shp";
public readonly Dictionary<string, string> TilesetExtensions = new Dictionary<string, string>();
public readonly Dictionary<string, string> TilesetCodes = new Dictionary<string, string>();

public ClassicTilesetSpecificSpriteSequenceLoader(ModData modData)
: base(modData)
{
var metadata = modData.Manifest.Get<SpriteSequenceFormat>().Metadata;
if (metadata.TryGetValue("DefaultSpriteExtension", out var yaml))
DefaultSpriteExtension = yaml.Value;

if (metadata.TryGetValue("TilesetExtensions", out yaml))
TilesetExtensions = yaml.ToDictionary(kv => kv.Value);

if (metadata.TryGetValue("TilesetCodes", out yaml))
TilesetCodes = yaml.ToDictionary(kv => kv.Value);
}
: base(modData) { }

public override ISpriteSequence CreateSequence(ModData modData, string tileSet, SpriteCache cache, string sequence, string animation, MiniYaml info)
public override ISpriteSequence CreateSequence(ModData modData, string tileset, SpriteCache cache, string image, string sequence, MiniYaml data, MiniYaml defaults)
{
return new ClassicTilesetSpecificSpriteSequence(modData, tileSet, cache, this, sequence, animation, info);
return new ClassicTilesetSpecificSpriteSequence(modData, tileset, cache, this, image, sequence, data, defaults);
}
}

[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
{
[Desc("Dictionary of <string: string> with tileset name to override -> tileset name to use instead.")]
static readonly SpriteSequenceField<Dictionary<string, string>> TilesetOverrides = new SpriteSequenceField<Dictionary<string, string>>(nameof(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.")]
static readonly SpriteSequenceField<bool> UseTilesetCode = new SpriteSequenceField<bool>(nameof(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).")]
static readonly SpriteSequenceField<bool> AddExtension = new SpriteSequenceField<bool>(nameof(AddExtension), true);

[Desc("Whether `mod.yaml`'s `TilesetExtensions` should be used with the sequence's file name.")]
static readonly SpriteSequenceField<bool> UseTilesetExtension = new SpriteSequenceField<bool>(nameof(UseTilesetExtension), false);

public ClassicTilesetSpecificSpriteSequence(ModData modData, string tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info)
: base(modData, tileSet, cache, loader, sequence, animation, info) { }

static string ResolveTilesetId(string tileSet, Dictionary<string, MiniYaml> d)
{
if (d.TryGetValue(nameof(TilesetOverrides), out var yaml))
{
var tsNode = yaml.Nodes.FirstOrDefault(n => n.Key == tileSet);
if (tsNode != null)
tileSet = tsNode.Value.Value;
}
[Desc("Dictionary of <tileset name>: filename to override the Filename key.")]
static readonly SpriteSequenceField<Dictionary<string, string>> TilesetFilenames = new SpriteSequenceField<Dictionary<string, string>>(nameof(TilesetFilenames), null);

return tileSet;
}
public ClassicTilesetSpecificSpriteSequence(ModData modData, string tileset, SpriteCache cache, ISpriteSequenceLoader loader, string image, string sequence, MiniYaml data, MiniYaml defaults)
: base(modData, tileset, cache, loader, image, sequence, data, defaults) { }

protected override string GetSpriteSrc(ModData modData, string tileSet, string sequence, string animation, string sprite, Dictionary<string, MiniYaml> d)
protected override string GetSpriteFilename(ModData modData, string tileset, string image, string sequence, MiniYaml data, MiniYaml defaults)
{
var loader = (ClassicTilesetSpecificSpriteSequenceLoader)Loader;

var spriteName = sprite ?? sequence;

if (LoadField(d, UseTilesetCode))
var node = data.Nodes.FirstOrDefault(n => n.Key == TilesetFilenames.Key) ?? defaults.Nodes.FirstOrDefault(n => n.Key == TilesetFilenames.Key);
if (node != null)
{
if (loader.TilesetCodes.TryGetValue(ResolveTilesetId(tileSet, d), out var code))
spriteName = spriteName.Substring(0, 1) + code + spriteName.Substring(2, spriteName.Length - 2);
}

if (LoadField(d, AddExtension))
{
if (LoadField(d, UseTilesetExtension) && loader.TilesetExtensions.TryGetValue(ResolveTilesetId(tileSet, d), out var tilesetExtension))
return spriteName + tilesetExtension;

return spriteName + loader.DefaultSpriteExtension;
var tilesetNode = node.Value.Nodes.FirstOrDefault(n => n.Key == tileset);
if (tilesetNode != null)
return tilesetNode.Value.Value;
}

return spriteName;
return base.GetSpriteFilename(modData, tileset, image, sequence, data, defaults);
}
}
}
Loading