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 mapX = x + b.Left;
|
||||||
var mapY = y + b.Top;
|
var mapY = y + b.Top;
|
||||||
var type = tileset[tileset.GetTerrainIndex(mapTiles[new MPos(mapX, mapY)])];
|
var type = tileset.GetTileInfo(mapTiles[new MPos(mapX, mapY)]);
|
||||||
colors[y * stride + x] = type.Color.ToArgb();
|
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.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
|
||||||
namespace OpenRA
|
namespace OpenRA
|
||||||
{
|
{
|
||||||
@@ -24,11 +25,29 @@ namespace OpenRA
|
|||||||
public readonly Color LeftColor;
|
public readonly Color LeftColor;
|
||||||
public readonly Color RightColor;
|
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
|
public class TerrainTypeInfo
|
||||||
{
|
{
|
||||||
|
static readonly TerrainTypeInfo Default = new TerrainTypeInfo();
|
||||||
|
|
||||||
public readonly string Type;
|
public readonly string Type;
|
||||||
public readonly string[] TargetTypes = { };
|
public readonly string[] TargetTypes = { };
|
||||||
public readonly string[] AcceptsSmudgeType = { };
|
public readonly string[] AcceptsSmudgeType = { };
|
||||||
@@ -36,15 +55,17 @@ namespace OpenRA
|
|||||||
public readonly Color Color;
|
public readonly Color Color;
|
||||||
public readonly string CustomCursor;
|
public readonly string CustomCursor;
|
||||||
|
|
||||||
public TerrainTypeInfo() { }
|
// Private default ctor for serialization comparison
|
||||||
|
TerrainTypeInfo() { }
|
||||||
|
|
||||||
public TerrainTypeInfo(MiniYaml my) { FieldLoader.Load(this, my); }
|
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
|
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 ushort Id;
|
||||||
public readonly string Image;
|
public readonly string Image;
|
||||||
@@ -129,28 +150,22 @@ namespace OpenRA
|
|||||||
|
|
||||||
public MiniYaml Save(TileSet tileSet)
|
public MiniYaml Save(TileSet tileSet)
|
||||||
{
|
{
|
||||||
var root = new List<MiniYamlNode>();
|
var root = FieldSaver.SaveDifferences(this, Default);
|
||||||
foreach (var field in Fields)
|
|
||||||
{
|
|
||||||
var f = this.GetType().GetField(field);
|
|
||||||
if (f.GetValue(this) == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
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,
|
root.Nodes.Add(new MiniYamlNode("Tiles", null, tileYaml));
|
||||||
tileInfo.Select((terrainTypeIndex, templateIndex) => new MiniYamlNode(templateIndex.ToString(), terrainTypeIndex.Save())).ToList()));
|
|
||||||
|
|
||||||
return new MiniYaml(null, root);
|
return root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TileSet
|
public class TileSet
|
||||||
{
|
{
|
||||||
static readonly string[] Fields = { "Name", "Id", "SheetSize", "Palette", "PlayerPalette", "Extensions", "WaterPaletteRotationBase",
|
|
||||||
"EditorTemplateOrder", "IgnoreTileSpriteOffsets", "MaximumHeight" };
|
|
||||||
|
|
||||||
public readonly string Name;
|
public readonly string Name;
|
||||||
public readonly string Id;
|
public readonly string Id;
|
||||||
public readonly int SheetSize = 512;
|
public readonly int SheetSize = 512;
|
||||||
@@ -163,12 +178,17 @@ namespace OpenRA
|
|||||||
public readonly string[] EditorTemplateOrder;
|
public readonly string[] EditorTemplateOrder;
|
||||||
public readonly bool IgnoreTileSpriteOffsets;
|
public readonly bool IgnoreTileSpriteOffsets;
|
||||||
|
|
||||||
|
[FieldLoader.Ignore]
|
||||||
public readonly Dictionary<ushort, TerrainTemplateInfo> Templates = new Dictionary<ushort, TerrainTemplateInfo>();
|
public readonly Dictionary<ushort, TerrainTemplateInfo> Templates = new Dictionary<ushort, TerrainTemplateInfo>();
|
||||||
|
|
||||||
|
[FieldLoader.Ignore]
|
||||||
public readonly TerrainTypeInfo[] TerrainInfo;
|
public readonly TerrainTypeInfo[] TerrainInfo;
|
||||||
readonly Dictionary<string, byte> terrainIndexByType = new Dictionary<string, byte>();
|
readonly Dictionary<string, byte> terrainIndexByType = new Dictionary<string, byte>();
|
||||||
readonly byte defaultWalkableTerrainIndex;
|
readonly byte defaultWalkableTerrainIndex;
|
||||||
|
|
||||||
|
// Private default ctor for serialization comparison
|
||||||
|
TileSet() { }
|
||||||
|
|
||||||
public TileSet(ModData modData, string filepath)
|
public TileSet(ModData modData, string filepath)
|
||||||
{
|
{
|
||||||
var yaml = MiniYaml.DictFromFile(filepath);
|
var yaml = MiniYaml.DictFromFile(filepath);
|
||||||
@@ -269,18 +289,7 @@ namespace OpenRA
|
|||||||
public void Save(string filepath)
|
public void Save(string filepath)
|
||||||
{
|
{
|
||||||
var root = new List<MiniYamlNode>();
|
var root = new List<MiniYamlNode>();
|
||||||
var gen = new List<MiniYamlNode>();
|
root.Add(new MiniYamlNode("General", FieldSaver.SaveDifferences(this, new TileSet())));
|
||||||
|
|
||||||
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("Terrain", null,
|
root.Add(new MiniYamlNode("Terrain", null,
|
||||||
TerrainInfo.Select(t => new MiniYamlNode("TerrainType@{0}".F(t.Type), t.Save())).ToList()));
|
TerrainInfo.Select(t => new MiniYamlNode("TerrainType@{0}".F(t.Type), t.Save())).ToList()));
|
||||||
|
|||||||
@@ -617,6 +617,7 @@
|
|||||||
<Compile Include="Widgets\VqaPlayerWidget.cs" />
|
<Compile Include="Widgets\VqaPlayerWidget.cs" />
|
||||||
<Compile Include="Traits\Render\WithInfantryBody.cs" />
|
<Compile Include="Traits\Render\WithInfantryBody.cs" />
|
||||||
<Compile Include="UtilityCommands\CheckSequenceSprites.cs" />
|
<Compile Include="UtilityCommands\CheckSequenceSprites.cs" />
|
||||||
|
<Compile Include="UtilityCommands\FixClassicTilesets.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<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