From 84378969c3a91a5558fb9e26ba5149c0534cae76 Mon Sep 17 00:00:00 2001 From: Gustas <37534529+PunkPun@users.noreply.github.com> Date: Mon, 27 Jan 2025 19:26:16 +0200 Subject: [PATCH] Make palettes and tilesets optional --- OpenRA.Game/Graphics/SequenceSet.cs | 6 +- .../DumpSequenceSheetsCommand.cs | 84 +++++++++++++------ 2 files changed, 62 insertions(+), 28 deletions(-) diff --git a/OpenRA.Game/Graphics/SequenceSet.cs b/OpenRA.Game/Graphics/SequenceSet.cs index 989912c9c2..9730b74b50 100644 --- a/OpenRA.Game/Graphics/SequenceSet.cs +++ b/OpenRA.Game/Graphics/SequenceSet.cs @@ -44,15 +44,15 @@ namespace OpenRA.Graphics public sealed class SequenceSet : IDisposable { + public readonly string TileSet; readonly ModData modData; - readonly string tileSet; readonly IReadOnlyDictionary> images; public SpriteCache SpriteCache { get; } public SequenceSet(IReadOnlyFileSystem fileSystem, ModData modData, string tileSet, MiniYaml additionalSequences) { this.modData = modData; - this.tileSet = tileSet; + TileSet = tileSet; SpriteCache = new SpriteCache(fileSystem, modData.SpriteLoaders, modData.SpriteSequenceLoader.BgraSheetSize, modData.SpriteSequenceLoader.IndexedSheetSize); using (new Support.PerfTimer("LoadSequences")) images = Load(fileSystem, additionalSequences); @@ -97,7 +97,7 @@ namespace OpenRA.Graphics if (node.Key.StartsWith(ActorInfo.AbstractActorPrefix)) continue; - images[node.Key] = modData.SpriteSequenceLoader.ParseSequences(modData, tileSet, SpriteCache, node); + images[node.Key] = modData.SpriteSequenceLoader.ParseSequences(modData, TileSet, SpriteCache, node); } return images; diff --git a/OpenRA.Mods.Common/UtilityCommands/DumpSequenceSheetsCommand.cs b/OpenRA.Mods.Common/UtilityCommands/DumpSequenceSheetsCommand.cs index e6337d876e..d9accb4ce3 100644 --- a/OpenRA.Mods.Common/UtilityCommands/DumpSequenceSheetsCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/DumpSequenceSheetsCommand.cs @@ -10,6 +10,7 @@ #endregion using System; +using System.Collections.Generic; using OpenRA.FileFormats; using OpenRA.FileSystem; using OpenRA.Graphics; @@ -24,47 +25,80 @@ namespace OpenRA.Mods.Common.UtilityCommands bool IUtilityCommand.ValidateArguments(string[] args) { - return args.Length >= 3; + return args.Length >= 1; } - [Desc("PALETTE", "TILESET-OR-MAP", "Exports sequence texture atlas as a set of png images.")] + [Desc("[PALETTE]", "[TILESET-OR-MAP]", "Exports texture atlas' as a set of png images. " + + "If palette is not specified, only BGRA sheets are exported. " + + "If tileset-or-map is not specified, all tilesets are exported.")] void IUtilityCommand.Run(Utility utility, string[] args) { // HACK: The engine code assumes that Game.modData is set. var modData = Game.ModData = utility.ModData; - var palette = new ImmutablePalette(args[1], [0], []); + var palette = args.Length > 1 ? new ImmutablePalette(args[1], [0], []) : null; + var sequences = new List(); - SequenceSet sequences; - var tilesetUpper = args[2].ToUpperInvariant(); - if (modData.DefaultTerrainInfo.ContainsKey(tilesetUpper)) - sequences = new SequenceSet(modData.ModFiles, modData, tilesetUpper, null); + if (args.Length == 3) + { + var tilesetUpper = args[2].ToUpperInvariant(); + if (modData.DefaultTerrainInfo.ContainsKey(tilesetUpper)) + sequences.Add(new SequenceSet(modData.ModFiles, modData, tilesetUpper, null)); + else + { + var mapPackage = new Folder(Platform.EngineDir).OpenPackage(args[2], modData.ModFiles); + if (mapPackage == null) + throw new InvalidOperationException($"{args[2]} is not a valid tileset or map path"); + + sequences.Add(new Map(modData, mapPackage).Sequences); + } + } else { - var mapPackage = new Folder(Platform.EngineDir).OpenPackage(args[2], modData.ModFiles); - if (mapPackage == null) - throw new InvalidOperationException($"{args[2]} is not a valid tileset or map path"); - - sequences = new Map(modData, mapPackage).Sequences; + foreach (var t in modData.DefaultTerrainInfo.Keys) + sequences.Add(new SequenceSet(modData.ModFiles, modData, t, null)); } - sequences.LoadSprites(); - - var count = 0; - - var sb = sequences.SpriteCache.SheetBuilders[SheetType.Indexed]; - foreach (var s in sb.AllSheets) + var sheetCount = 1; + foreach (var sequence in sequences) { - var max = s == sb.Current ? (int)sb.CurrentChannel + 1 : 4; - for (var i = 0; i < max; i++) - s.AsPng((TextureChannel)ChannelMasks[i], palette).Save($"{count}.{i}.png", Png.Compression.BEST_SPEED); + sequence.LoadSprites(); - count++; + var sequencesName = "sequences"; + var terrainName = "tileset"; + if (sequences.Count > 1) + { + var name = sequence.TileSet.ToLowerInvariant(); + sequencesName += "." + name; + terrainName += "." + name; + } + + var sb = sequence.SpriteCache.SheetBuilders[SheetType.Indexed]; + foreach (var s in sb.AllSheets) + CommitSheet(sb, s, sequencesName, palette, ref sheetCount); + + foreach (var s in sequence.SpriteCache.SheetBuilders[SheetType.BGRA].AllSheets) + CommitSheet(null, s, sequencesName, palette, ref sheetCount); + + sequence.Dispose(); } + } - sb = sequences.SpriteCache.SheetBuilders[SheetType.BGRA]; - foreach (var s in sb.AllSheets) - s.AsPng().Save($"{count++}.png", Png.Compression.BEST_SPEED); + static void CommitSheet(SheetBuilder builder, Sheet sheet, string name, ImmutablePalette palette, ref int count) + { + if (builder == null) + sheet.AsPng().Save($"{count++}.{name}.png", Png.Compression.BEST_SPEED); + else + { + if (palette != null) + { + var channels = sheet == builder.Current ? (int)builder.CurrentChannel + 1 : 4; + for (var i = 0; i < channels; i++) + sheet.AsPng((TextureChannel)ChannelMasks[i], palette).Save($"{count}.{i}.{name}.png", Png.Compression.BEST_SPEED); + + count++; + } + } } } }