Add a utility command to fix implicit tile definitions.

This commit is contained in:
Paul Chote
2015-03-22 11:48:47 +00:00
parent 8844defb44
commit ec77e15e54
2 changed files with 105 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using OpenRA.FileSystem;
using OpenRA.Graphics;
using OpenRA.Traits;
using StyleCop;
namespace OpenRA.Mods.Common.UtilityCommands
{
class FixClassicTilesets : IUtilityCommand
{
public string Name { get { return "--fix-classic-tilesets"; } }
[Desc("Fixes missing template tile definitions and adds filename extensions.")]
public void Run(ModData modData, string[] args)
{
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
GlobalFileSystem.LoadFromManifest(Game.ModData.Manifest);
var imageField = typeof(TerrainTemplateInfo).GetField("Image");
var pickAnyField = typeof(TerrainTemplateInfo).GetField("PickAny");
var tileInfoField = typeof(TerrainTemplateInfo).GetField("tileInfo", BindingFlags.NonPublic | BindingFlags.Instance);
var terrainTypeField = typeof(TerrainTileInfo).GetField("TerrainType");
var terrainLeftColorField = typeof(TerrainTileInfo).GetField("LeftColor");
var terrainRightColorField = typeof(TerrainTileInfo).GetField("RightColor");
var empty = new Size(0, 0);
var single = new int2(1, 1);
foreach (var t in Game.ModData.Manifest.TileSets)
{
var ts = new TileSet(Game.ModData, t);
var exts = new[] { "" }.Concat(ts.Extensions);
var frameCache = new FrameCache(Game.ModData.SpriteLoaders, ts.Extensions);
Console.WriteLine("Tileset: " + ts.Name);
foreach (var template in ts.Templates.Values)
{
// Find the sprite associated with this template
foreach (var ext in exts)
{
Stream s;
if (!GlobalFileSystem.TryOpenWithExts(template.Image, new[] { ext }, out s))
continue;
// Rewrite the template image (normally readonly) using reflection
imageField.SetValue(template, template.Image + ext);
// Fetch the private tileInfo array so that we can write new entries
var tileInfo = (TerrainTileInfo[])tileInfoField.GetValue(template);
// Open the file and search for any implicit frames
var allFrames = frameCache[template.Image];
var frames = template.Frames != null ? template.Frames.Select(f => allFrames[f]).ToArray() : allFrames;
// Resize array for new entries
if (frames.Length > template.TilesCount)
{
var oldLength = template.TilesCount;
var ti = new TerrainTileInfo[frames.Length];
Array.Copy(tileInfo, ti, template.TilesCount);
tileInfoField.SetValue(template, ti);
tileInfo = ti;
}
for (var i = 0; i < template.TilesCount; i++)
{
if (template[i] == null && frames[i] != null && frames[i].Size != empty)
{
tileInfo[i] = new TerrainTileInfo();
var ti = ts.GetTerrainIndex("Clear");
terrainTypeField.SetValue(tileInfo[i], ti);
terrainLeftColorField.SetValue(tileInfo[i], ts[ti].Color);
terrainRightColorField.SetValue(tileInfo[i], ts[ti].Color);
Console.WriteLine("Fixing entry for {0}:{1}", template.Image, i);
}
}
if (template.TilesCount > 1 && template.Size == single)
pickAnyField.SetValue(template, true);
s.Dispose();
}
}
ts.Save(t);
}
}
}
}