Merge pull request #7707 from pchote/tileset-fixes
Automated correctness fixes for tileset definitions.
This commit is contained in:
@@ -44,8 +44,10 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
var mapX = x + b.Left;
|
||||
var mapY = y + b.Top;
|
||||
var type = tileset[tileset.GetTerrainIndex(mapTiles[new MPos(mapX, mapY)])];
|
||||
colors[y * stride + x] = type.Color.ToArgb();
|
||||
var type = tileset.GetTileInfo(mapTiles[new MPos(mapX, mapY)]);
|
||||
var color = type != null ? type.LeftColor : Color.Black;
|
||||
|
||||
colors[y * stride + x] = color.ToArgb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
@@ -24,11 +25,29 @@ namespace OpenRA
|
||||
public readonly Color LeftColor;
|
||||
public readonly Color RightColor;
|
||||
|
||||
public MiniYaml Save() { return FieldSaver.Save(this); }
|
||||
public MiniYaml Save(TileSet tileSet)
|
||||
{
|
||||
var root = new List<MiniYamlNode>();
|
||||
if (Height != 0)
|
||||
root.Add(FieldSaver.SaveField(this, "Height"));
|
||||
|
||||
if (RampType != 0)
|
||||
root.Add(FieldSaver.SaveField(this, "RampType"));
|
||||
|
||||
if (LeftColor != tileSet.TerrainInfo[TerrainType].Color)
|
||||
root.Add(FieldSaver.SaveField(this, "LeftColor"));
|
||||
|
||||
if (RightColor != tileSet.TerrainInfo[TerrainType].Color)
|
||||
root.Add(FieldSaver.SaveField(this, "RightColor"));
|
||||
|
||||
return new MiniYaml(tileSet.TerrainInfo[TerrainType].Type, root);
|
||||
}
|
||||
}
|
||||
|
||||
public class TerrainTypeInfo
|
||||
{
|
||||
static readonly TerrainTypeInfo Default = new TerrainTypeInfo();
|
||||
|
||||
public readonly string Type;
|
||||
public readonly string[] TargetTypes = { };
|
||||
public readonly string[] AcceptsSmudgeType = { };
|
||||
@@ -36,15 +55,17 @@ namespace OpenRA
|
||||
public readonly Color Color;
|
||||
public readonly string CustomCursor;
|
||||
|
||||
public TerrainTypeInfo() { }
|
||||
// Private default ctor for serialization comparison
|
||||
TerrainTypeInfo() { }
|
||||
|
||||
public TerrainTypeInfo(MiniYaml my) { FieldLoader.Load(this, my); }
|
||||
|
||||
public MiniYaml Save() { return FieldSaver.Save(this); }
|
||||
public MiniYaml Save() { return FieldSaver.SaveDifferences(this, Default); }
|
||||
}
|
||||
|
||||
public class TerrainTemplateInfo
|
||||
{
|
||||
static readonly string[] Fields = { "Id", "Image", "Frames", "Size", "PickAny", "Category" };
|
||||
static readonly TerrainTemplateInfo Default = new TerrainTemplateInfo(0, null, int2.Zero, null);
|
||||
|
||||
public readonly ushort Id;
|
||||
public readonly string Image;
|
||||
@@ -129,28 +150,22 @@ namespace OpenRA
|
||||
|
||||
public MiniYaml Save(TileSet tileSet)
|
||||
{
|
||||
var root = new List<MiniYamlNode>();
|
||||
foreach (var field in Fields)
|
||||
{
|
||||
var f = this.GetType().GetField(field);
|
||||
if (f.GetValue(this) == null)
|
||||
continue;
|
||||
var root = FieldSaver.SaveDifferences(this, Default);
|
||||
|
||||
root.Add(new MiniYamlNode(field, FieldSaver.FormatValue(this, f)));
|
||||
}
|
||||
var tileYaml = tileInfo
|
||||
.Select((ti, i) => Pair.New(i.ToString(), ti))
|
||||
.Where(t => t.Second != null)
|
||||
.Select(t => new MiniYamlNode(t.First, t.Second.Save(tileSet)))
|
||||
.ToList();
|
||||
|
||||
root.Add(new MiniYamlNode("Tiles", null,
|
||||
tileInfo.Select((terrainTypeIndex, templateIndex) => new MiniYamlNode(templateIndex.ToString(), terrainTypeIndex.Save())).ToList()));
|
||||
root.Nodes.Add(new MiniYamlNode("Tiles", null, tileYaml));
|
||||
|
||||
return new MiniYaml(null, root);
|
||||
return root;
|
||||
}
|
||||
}
|
||||
|
||||
public class TileSet
|
||||
{
|
||||
static readonly string[] Fields = { "Name", "Id", "SheetSize", "Palette", "PlayerPalette", "Extensions", "WaterPaletteRotationBase",
|
||||
"EditorTemplateOrder", "IgnoreTileSpriteOffsets", "MaximumHeight" };
|
||||
|
||||
public readonly string Name;
|
||||
public readonly string Id;
|
||||
public readonly int SheetSize = 512;
|
||||
@@ -163,12 +178,17 @@ namespace OpenRA
|
||||
public readonly string[] EditorTemplateOrder;
|
||||
public readonly bool IgnoreTileSpriteOffsets;
|
||||
|
||||
[FieldLoader.Ignore]
|
||||
public readonly Dictionary<ushort, TerrainTemplateInfo> Templates = new Dictionary<ushort, TerrainTemplateInfo>();
|
||||
|
||||
[FieldLoader.Ignore]
|
||||
public readonly TerrainTypeInfo[] TerrainInfo;
|
||||
readonly Dictionary<string, byte> terrainIndexByType = new Dictionary<string, byte>();
|
||||
readonly byte defaultWalkableTerrainIndex;
|
||||
|
||||
// Private default ctor for serialization comparison
|
||||
TileSet() { }
|
||||
|
||||
public TileSet(ModData modData, string filepath)
|
||||
{
|
||||
var yaml = MiniYaml.DictFromFile(filepath);
|
||||
@@ -269,18 +289,7 @@ namespace OpenRA
|
||||
public void Save(string filepath)
|
||||
{
|
||||
var root = new List<MiniYamlNode>();
|
||||
var gen = new List<MiniYamlNode>();
|
||||
|
||||
foreach (var field in Fields)
|
||||
{
|
||||
var f = this.GetType().GetField(field);
|
||||
if (f.GetValue(this) == null)
|
||||
continue;
|
||||
|
||||
gen.Add(new MiniYamlNode(field, FieldSaver.FormatValue(this, f)));
|
||||
}
|
||||
|
||||
root.Add(new MiniYamlNode("General", null, gen));
|
||||
root.Add(new MiniYamlNode("General", FieldSaver.SaveDifferences(this, new TileSet())));
|
||||
|
||||
root.Add(new MiniYamlNode("Terrain", null,
|
||||
TerrainInfo.Select(t => new MiniYamlNode("TerrainType@{0}".F(t.Type), t.Save())).ToList()));
|
||||
|
||||
@@ -617,6 +617,7 @@
|
||||
<Compile Include="Widgets\VqaPlayerWidget.cs" />
|
||||
<Compile Include="Traits\Render\WithInfantryBody.cs" />
|
||||
<Compile Include="UtilityCommands\CheckSequenceSprites.cs" />
|
||||
<Compile Include="UtilityCommands\FixClassicTilesets.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
|
||||
104
OpenRA.Mods.Common/UtilityCommands/FixClassicTilesets.cs
Normal file
104
OpenRA.Mods.Common/UtilityCommands/FixClassicTilesets.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user