Merge pull request #4391 from pchote/rectangular-tiles

Add support for TS terrain sprites and non-square cell sizes.
This commit is contained in:
Matthias Mailänder
2013-12-29 14:34:52 -08:00
21 changed files with 234 additions and 73 deletions

View File

@@ -11,11 +11,16 @@ NEW:
Converted production exits to world coordinates. Converted production exits to world coordinates.
Converted weapon projectiles to world coordinates. Converted weapon projectiles to world coordinates.
Converted actor speed to world coordinates. Converted actor speed to world coordinates.
Added support for rectangular cells with forced perspective.
Added initial support for Tmp(TS) sprites.
Asset Browser:
Filenames are now listed in alphabetical order
Mod / Custom map compatibility: Mod / Custom map compatibility:
Altitude is no longer parsed from actor templates in maps. Specify CenterPosition instead. Altitude is no longer parsed from actor templates in maps. Specify CenterPosition instead.
Run `OpenRA.Utility.exe --upgrade-mod <mod> 20131223` to automatically upgrade mod rules. Run `OpenRA.Utility.exe --upgrade-mod <mod> 20131223` to automatically upgrade mod rules.
Run `OpenRA.Utility.exe --upgrade-map <map path> 20131223` to automatically upgrade custom map rules. Run `OpenRA.Utility.exe --upgrade-map <map path> 20131223` to automatically upgrade custom map rules.
Added a new trait Demolishable for buildings to handle the C4 demolition. Added a new trait Demolishable for buildings to handle the C4 demolition.
Mods that use custom TileSize must specify both width and height.
20131223: 20131223:
All mods: All mods:

View File

@@ -63,8 +63,8 @@ namespace OpenRA.Editor
public void Preview(Surface surface, SGraphics g) public void Preview(Surface surface, SGraphics g)
{ {
g.DrawImage(brushTemplate.Bitmap, g.DrawImage(brushTemplate.Bitmap,
surface.TileSetRenderer.TileSize.Width * surface.GetBrushLocation().X * surface.Zoom + surface.GetOffset().X, surface.TileSetRenderer.TileSize * surface.GetBrushLocation().X * surface.Zoom + surface.GetOffset().X,
surface.TileSetRenderer.TileSize.Height * surface.GetBrushLocation().Y * surface.Zoom + surface.GetOffset().Y, surface.TileSetRenderer.TileSize * surface.GetBrushLocation().Y * surface.Zoom + surface.GetOffset().Y,
brushTemplate.Bitmap.Width * surface.Zoom, brushTemplate.Bitmap.Width * surface.Zoom,
brushTemplate.Bitmap.Height * surface.Zoom); brushTemplate.Bitmap.Height * surface.Zoom);
} }

View File

@@ -145,7 +145,7 @@ namespace OpenRA.Editor
{ {
Rules.LoadRules(manifest, map); Rules.LoadRules(manifest, map);
tileset = Rules.TileSets[map.Tileset]; tileset = Rules.TileSets[map.Tileset];
tilesetRenderer = new TileSetRenderer(tileset, new Size(manifest.TileSize, manifest.TileSize)); tilesetRenderer = new TileSetRenderer(tileset, manifest.TileSize);
var shadowIndex = new int[] { 3, 4 }; var shadowIndex = new int[] { 3, 4 };
var palette = new Palette(FileSystem.Open(tileset.Palette), shadowIndex); var palette = new Palette(FileSystem.Open(tileset.Palette), shadowIndex);

View File

@@ -257,7 +257,7 @@ namespace OpenRA.Editor
Bitmap RenderChunk(int u, int v) Bitmap RenderChunk(int u, int v)
{ {
var bitmap = new Bitmap(ChunkSize * TileSetRenderer.TileSize.Width, ChunkSize * TileSetRenderer.TileSize.Height); var bitmap = new Bitmap(ChunkSize * TileSetRenderer.TileSize, ChunkSize * TileSetRenderer.TileSize);
var data = bitmap.LockBits(bitmap.Bounds(), var data = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
@@ -274,9 +274,9 @@ namespace OpenRA.Editor
var tile = TileSetRenderer.Data(tr.Type); var tile = TileSetRenderer.Data(tr.Type);
var index = (tr.Index < tile.Count) ? tr.Index : (byte)0; var index = (tr.Index < tile.Count) ? tr.Index : (byte)0;
var rawImage = tile[index]; var rawImage = tile[index];
for (var x = 0; x < TileSetRenderer.TileSize.Width; x++) for (var x = 0; x < TileSetRenderer.TileSize; x++)
for (var y = 0; y < TileSetRenderer.TileSize.Height; y++) for (var y = 0; y < TileSetRenderer.TileSize; y++)
p[(j * TileSetRenderer.TileSize.Width + y) * stride + i * TileSetRenderer.TileSize.Width + x] = Palette.GetColor(rawImage[x + TileSetRenderer.TileSize.Width * y]).ToArgb(); p[(j * TileSetRenderer.TileSize + y) * stride + i * TileSetRenderer.TileSize + x] = Palette.GetColor(rawImage[x + TileSetRenderer.TileSize * y]).ToArgb();
if (Map.MapResources.Value[u * ChunkSize + i, v * ChunkSize + j].Type != 0) if (Map.MapResources.Value[u * ChunkSize + i, v * ChunkSize + j].Type != 0)
{ {
@@ -287,12 +287,12 @@ namespace OpenRA.Editor
int* q = (int*)srcdata.Scan0.ToPointer(); int* q = (int*)srcdata.Scan0.ToPointer();
var srcstride = srcdata.Stride >> 2; var srcstride = srcdata.Stride >> 2;
for (var x = 0; x < TileSetRenderer.TileSize.Width; x++) for (var x = 0; x < TileSetRenderer.TileSize; x++)
for (var y = 0; y < TileSetRenderer.TileSize.Height; y++) for (var y = 0; y < TileSetRenderer.TileSize; y++)
{ {
var c = q[y * srcstride + x]; var c = q[y * srcstride + x];
if ((c & 0xff000000) != 0) /* quick & dirty, i cbf doing real alpha */ if ((c & 0xff000000) != 0) /* quick & dirty, i cbf doing real alpha */
p[(j * TileSetRenderer.TileSize.Width + y) * stride + i * TileSetRenderer.TileSize.Width + x] = c; p[(j * TileSetRenderer.TileSize + y) * stride + i * TileSetRenderer.TileSize + x] = c;
} }
resourceImage.UnlockBits(srcdata); resourceImage.UnlockBits(srcdata);
@@ -303,14 +303,16 @@ namespace OpenRA.Editor
bitmap.UnlockBits(data); bitmap.UnlockBits(data);
if (ShowGrid) if (ShowGrid)
{
using (var g = SGraphics.FromImage(bitmap)) using (var g = SGraphics.FromImage(bitmap))
{ {
var ts = Game.modData.Manifest.TileSize;
var rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); var rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
ControlPaint.DrawGrid(g, rect, new Size(2, Game.CellSize), Color.DarkRed); ControlPaint.DrawGrid(g, rect, new Size(2, ts.Height), Color.DarkRed);
ControlPaint.DrawGrid(g, rect, new Size(Game.CellSize, 2), Color.DarkRed); ControlPaint.DrawGrid(g, rect, new Size(ts.Width, 2), Color.DarkRed);
ControlPaint.DrawGrid(g, rect, new Size(Game.CellSize, Game.CellSize), Color.Red); ControlPaint.DrawGrid(g, rect, new Size(ts.Width, ts.Height), Color.Red);
} }
}
return bitmap; return bitmap;
} }
@@ -318,15 +320,15 @@ namespace OpenRA.Editor
{ {
var vX = (int)Math.Floor((mousePos.X - Offset.X) / Zoom); var vX = (int)Math.Floor((mousePos.X - Offset.X) / Zoom);
var vY = (int)Math.Floor((mousePos.Y - Offset.Y) / Zoom); var vY = (int)Math.Floor((mousePos.Y - Offset.Y) / Zoom);
return new CPos(vX / TileSetRenderer.TileSize.Width, vY / TileSetRenderer.TileSize.Height); return new CPos(vX / TileSetRenderer.TileSize, vY / TileSetRenderer.TileSize);
} }
public CPos GetBrushLocationBR() public CPos GetBrushLocationBR()
{ {
var vX = (int)Math.Floor((mousePos.X - Offset.X) / Zoom); var vX = (int)Math.Floor((mousePos.X - Offset.X) / Zoom);
var vY = (int)Math.Floor((mousePos.Y - Offset.Y) / Zoom); var vY = (int)Math.Floor((mousePos.Y - Offset.Y) / Zoom);
return new CPos((vX + TileSetRenderer.TileSize.Width - 1) / TileSetRenderer.TileSize.Width, return new CPos((vX + TileSetRenderer.TileSize - 1) / TileSetRenderer.TileSize,
(vY + TileSetRenderer.TileSize.Height - 1) / TileSetRenderer.TileSize.Height); (vY + TileSetRenderer.TileSize - 1) / TileSetRenderer.TileSize);
} }
public void DrawActor(SGraphics g, CPos p, ActorTemplate t, ColorPalette cp) public void DrawActor(SGraphics g, CPos p, ActorTemplate t, ColorPalette cp)
@@ -340,11 +342,11 @@ namespace OpenRA.Editor
float2 GetDrawPosition(CPos location, Bitmap bmp, bool centered) float2 GetDrawPosition(CPos location, Bitmap bmp, bool centered)
{ {
float offsetX = centered ? bmp.Width / 2 - TileSetRenderer.TileSize.Width / 2 : 0; float offsetX = centered ? bmp.Width / 2 - TileSetRenderer.TileSize / 2 : 0;
float drawX = TileSetRenderer.TileSize.Width * location.X * Zoom + Offset.X - offsetX; float drawX = TileSetRenderer.TileSize * location.X * Zoom + Offset.X - offsetX;
float offsetY = centered ? bmp.Height / 2 - TileSetRenderer.TileSize.Height / 2 : 0; float offsetY = centered ? bmp.Height / 2 - TileSetRenderer.TileSize / 2 : 0;
float drawY = TileSetRenderer.TileSize.Height * location.Y * Zoom + Offset.Y - offsetY; float drawY = TileSetRenderer.TileSize * location.Y * Zoom + Offset.Y - offsetY;
return new float2(drawX, drawY); return new float2(drawX, drawY);
} }
@@ -412,24 +414,24 @@ namespace OpenRA.Editor
var bmp = Chunks[x]; var bmp = Chunks[x];
var drawX = TileSetRenderer.TileSize.Width * (float)ChunkSize * (float)x.X * Zoom + Offset.X; var drawX = TileSetRenderer.TileSize * (float)ChunkSize * (float)x.X * Zoom + Offset.X;
var drawY = TileSetRenderer.TileSize.Height * (float)ChunkSize * (float)x.Y * Zoom + Offset.Y; var drawY = TileSetRenderer.TileSize * (float)ChunkSize * (float)x.Y * Zoom + Offset.Y;
RectangleF sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height); RectangleF sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height);
RectangleF destRect = new RectangleF(drawX, drawY, bmp.Width * Zoom, bmp.Height * Zoom); RectangleF destRect = new RectangleF(drawX, drawY, bmp.Width * Zoom, bmp.Height * Zoom);
e.Graphics.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel); e.Graphics.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel);
} }
e.Graphics.DrawRectangle(CordonPen, e.Graphics.DrawRectangle(CordonPen,
Map.Bounds.Left * TileSetRenderer.TileSize.Width * Zoom + Offset.X, Map.Bounds.Left * TileSetRenderer.TileSize * Zoom + Offset.X,
Map.Bounds.Top * TileSetRenderer.TileSize.Height * Zoom + Offset.Y, Map.Bounds.Top * TileSetRenderer.TileSize * Zoom + Offset.Y,
Map.Bounds.Width * TileSetRenderer.TileSize.Width * Zoom, Map.Bounds.Width * TileSetRenderer.TileSize * Zoom,
Map.Bounds.Height * TileSetRenderer.TileSize.Height * Zoom); Map.Bounds.Height * TileSetRenderer.TileSize * Zoom);
e.Graphics.DrawRectangle(SelectionPen, e.Graphics.DrawRectangle(SelectionPen,
(SelectionStart.X * TileSetRenderer.TileSize.Width * Zoom) + Offset.X, (SelectionStart.X * TileSetRenderer.TileSize * Zoom) + Offset.X,
(SelectionStart.Y * TileSetRenderer.TileSize.Height * Zoom) + Offset.Y, (SelectionStart.Y * TileSetRenderer.TileSize * Zoom) + Offset.Y,
(SelectionEnd - SelectionStart).X * TileSetRenderer.TileSize.Width * Zoom, (SelectionEnd - SelectionStart).X * TileSetRenderer.TileSize * Zoom,
(SelectionEnd - SelectionStart).Y * TileSetRenderer.TileSize.Height * Zoom); (SelectionEnd - SelectionStart).Y * TileSetRenderer.TileSize * Zoom);
if (IsPaste) if (IsPaste)
{ {
@@ -438,10 +440,10 @@ namespace OpenRA.Editor
var height = Math.Abs((SelectionStart - SelectionEnd).Y); var height = Math.Abs((SelectionStart - SelectionEnd).Y);
e.Graphics.DrawRectangle(PastePen, e.Graphics.DrawRectangle(PastePen,
(loc.X * TileSetRenderer.TileSize.Width * Zoom) + Offset.X, (loc.X * TileSetRenderer.TileSize * Zoom) + Offset.X,
(loc.Y * TileSetRenderer.TileSize.Height * Zoom) + Offset.Y, (loc.Y * TileSetRenderer.TileSize * Zoom) + Offset.Y,
width * (TileSetRenderer.TileSize.Width * Zoom), width * (TileSetRenderer.TileSize * Zoom),
height * (TileSetRenderer.TileSize.Height * Zoom)); height * (TileSetRenderer.TileSize * Zoom));
} }
foreach (var ar in Map.Actors.Value) foreach (var ar in Map.Actors.Value)
@@ -457,8 +459,8 @@ namespace OpenRA.Editor
foreach (var ar in Map.Actors.Value) foreach (var ar in Map.Actors.Value)
if (!ar.Key.StartsWith("Actor")) // if it has a custom name if (!ar.Key.StartsWith("Actor")) // if it has a custom name
e.Graphics.DrawStringContrast(Font, ar.Key, e.Graphics.DrawStringContrast(Font, ar.Key,
(int)(ar.Value.Location().X * TileSetRenderer.TileSize.Width * Zoom + Offset.X), (int)(ar.Value.Location().X * TileSetRenderer.TileSize * Zoom + Offset.X),
(int)(ar.Value.Location().Y * TileSetRenderer.TileSize.Height * Zoom + Offset.Y), (int)(ar.Value.Location().Y * TileSetRenderer.TileSize * Zoom + Offset.Y),
Brushes.White, Brushes.White,
Brushes.Black); Brushes.Black);
@@ -468,7 +470,7 @@ namespace OpenRA.Editor
{ {
if (i % 8 == 0) if (i % 8 == 0)
{ {
PointF point = new PointF(i * TileSetRenderer.TileSize.Width * Zoom + Offset.X, (Map.Bounds.Top - 8) * TileSetRenderer.TileSize.Height * Zoom + Offset.Y); PointF point = new PointF(i * TileSetRenderer.TileSize * Zoom + Offset.X, (Map.Bounds.Top - 8) * TileSetRenderer.TileSize * Zoom + Offset.Y);
e.Graphics.DrawString((i - Map.Bounds.Left).ToString(), MarkerFont, TextBrush, point); e.Graphics.DrawString((i - Map.Bounds.Left).ToString(), MarkerFont, TextBrush, point);
} }
} }
@@ -477,7 +479,7 @@ namespace OpenRA.Editor
{ {
if (i % 8 == 0) if (i % 8 == 0)
{ {
PointF point = new PointF((Map.Bounds.Left - 8) * TileSetRenderer.TileSize.Width * Zoom + Offset.X, i * TileSetRenderer.TileSize.Height * Zoom + Offset.Y); PointF point = new PointF((Map.Bounds.Left - 8) * TileSetRenderer.TileSize * Zoom + Offset.X, i * TileSetRenderer.TileSize * Zoom + Offset.Y);
e.Graphics.DrawString((i - Map.Bounds.Left).ToString(), MarkerFont, TextBrush, point); e.Graphics.DrawString((i - Map.Bounds.Left).ToString(), MarkerFont, TextBrush, point);
} }
} }

View File

@@ -8,6 +8,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
@@ -21,7 +22,27 @@ namespace OpenRA.Editor
{ {
public TileSet TileSet; public TileSet TileSet;
Dictionary<ushort, List<byte[]>> templates; Dictionary<ushort, List<byte[]>> templates;
public Size TileSize; public readonly int TileSize;
// Extract a square tile that the editor can render
byte[] ExtractSquareTile(ISpriteFrame frame)
{
var data = new byte[TileSize * TileSize];
// Invalid tile size: return blank tile
if (frame.Size.Width < TileSize || frame.Size.Height < TileSize)
return data;
var frameData = frame.Data;
var xOffset = (frame.Size.Width - TileSize) / 2;
var yOffset = (frame.Size.Height - TileSize) / 2;
for (var y = 0; y < TileSize; y++)
for (var x = 0; x < TileSize; x++)
data[y * TileSize + x] = frameData[(yOffset + y) * frame.Size.Width + x + xOffset];
return data;
}
List<byte[]> LoadTemplate(string filename, string[] exts, Dictionary<string, ISpriteSource> sourceCache, int[] frames) List<byte[]> LoadTemplate(string filename, string[] exts, Dictionary<string, ISpriteSource> sourceCache, int[] frames)
{ {
@@ -42,18 +63,18 @@ namespace OpenRA.Editor
var ret = new List<byte[]>(); var ret = new List<byte[]>();
var srcFrames = source.Frames.ToArray(); var srcFrames = source.Frames.ToArray();
foreach (var i in frames) foreach (var i in frames)
ret.Add(srcFrames[i].Data); ret.Add(ExtractSquareTile(srcFrames[i]));
return ret; return ret;
} }
return source.Frames.Select(f => f.Data).ToList(); return source.Frames.Select(f => ExtractSquareTile(f)).ToList();
} }
public TileSetRenderer(TileSet tileset, Size tileSize) public TileSetRenderer(TileSet tileset, Size tileSize)
{ {
this.TileSet = tileset; this.TileSet = tileset;
this.TileSize = tileSize; this.TileSize = Math.Min(tileSize.Width, tileSize.Height);
templates = new Dictionary<ushort, List<byte[]>>(); templates = new Dictionary<ushort, List<byte[]>>();
var sourceCache = new Dictionary<string, ISpriteSource>(); var sourceCache = new Dictionary<string, ISpriteSource>();
@@ -66,7 +87,7 @@ namespace OpenRA.Editor
var template = TileSet.Templates[id]; var template = TileSet.Templates[id];
var templateData = templates[id]; var templateData = templates[id];
var bitmap = new Bitmap(TileSize.Width * template.Size.X, TileSize.Height * template.Size.Y, var bitmap = new Bitmap(TileSize * template.Size.X, TileSize * template.Size.Y,
PixelFormat.Format8bppIndexed); PixelFormat.Format8bppIndexed);
bitmap.Palette = p.AsSystemPalette(); bitmap.Palette = p.AsSystemPalette();
@@ -86,15 +107,15 @@ namespace OpenRA.Editor
var rawImage = templateData[u + v * template.Size.X]; var rawImage = templateData[u + v * template.Size.X];
if (rawImage != null && rawImage.Length > 0) if (rawImage != null && rawImage.Length > 0)
{ {
for (var i = 0; i < TileSize.Width; i++) for (var i = 0; i < TileSize; i++)
for (var j = 0; j < TileSize.Height; j++) for (var j = 0; j < TileSize; j++)
q[(v * TileSize.Width + j) * stride + u * TileSize.Width + i] = rawImage[i + TileSize.Width * j]; q[(v * TileSize + j) * stride + u * TileSize + i] = rawImage[i + TileSize * j];
} }
else else
{ {
for (var i = 0; i < TileSize.Width; i++) for (var i = 0; i < TileSize; i++)
for (var j = 0; j < TileSize.Height; j++) for (var j = 0; j < TileSize; j++)
q[(v * TileSize.Width + j) * stride + u * TileSize.Width + i] = 0; q[(v * TileSize + j) * stride + u * TileSize + i] = 0;
} }
} }
} }

View File

@@ -282,6 +282,12 @@ namespace OpenRA.FileFormats
return ret; return ret;
} }
else if (fieldType == typeof(Size))
{
var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
return new Size(int.Parse(parts[0]), int.Parse(parts[1]));
}
else if (fieldType == typeof(int2)) else if (fieldType == typeof(int2))
{ {
var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

View File

@@ -29,7 +29,7 @@ namespace OpenRA.FileFormats
bool CacheWhenLoadingTileset { get; } bool CacheWhenLoadingTileset { get; }
} }
public enum SpriteType { Unknown, ShpTD, ShpTS, ShpD2, TmpTD, TmpRA, R8 } public enum SpriteType { Unknown, ShpTD, ShpTS, ShpD2, TmpTD, TmpRA, TmpTS, R8 }
public static class SpriteSource public static class SpriteSource
{ {
static bool IsTmpRA(Stream s) static bool IsTmpRA(Stream s)
@@ -57,6 +57,29 @@ namespace OpenRA.FileFormats
return a == 0 && b == 0x0D1AFFFF; return a == 0 && b == 0x0D1AFFFF;
} }
static bool IsTmpTS(Stream s)
{
var start = s.Position;
s.Position += 8;
var sx = s.ReadUInt32();
var sy = s.ReadUInt32();
// Find the first frame
var offset = s.ReadUInt32();
if (offset > s.Length - 52)
{
s.Position = start;
return false;
}
s.Position = offset + 12;
var test = s.ReadUInt32();
s.Position = start;
return test == sx * sy / 2 + 52;
}
static bool IsShpTS(Stream s) static bool IsShpTS(Stream s)
{ {
var start = s.Position; var start = s.Position;
@@ -204,6 +227,9 @@ namespace OpenRA.FileFormats
if (IsTmpTD(s)) if (IsTmpTD(s))
return SpriteType.TmpTD; return SpriteType.TmpTD;
if (IsTmpTS(s))
return SpriteType.TmpTS;
if (IsShpD2(s)) if (IsShpD2(s))
return SpriteType.ShpD2; return SpriteType.ShpD2;
@@ -225,6 +251,8 @@ namespace OpenRA.FileFormats
return new TmpRAReader(s); return new TmpRAReader(s);
case SpriteType.TmpTD: case SpriteType.TmpTD:
return new TmpTDReader(s); return new TmpTDReader(s);
case SpriteType.TmpTS:
return new TmpTSReader(s);
case SpriteType.ShpD2: case SpriteType.ShpD2:
return new ShpD2Reader(s); return new ShpD2Reader(s);
case SpriteType.Unknown: case SpriteType.Unknown:

View File

@@ -0,0 +1,75 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 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;
namespace OpenRA.FileFormats
{
public class TmpTSTile : ISpriteFrame
{
public Size Size { get; private set; }
public Size FrameSize { get { return Size; } }
public float2 Offset { get { return float2.Zero; } }
public byte[] Data { get; set; }
public TmpTSTile(Stream s, Size size)
{
Size = size;
// Ignore tile header for now
s.Position += 52;
Data = new byte[size.Width * size.Height];
// Unpack tile data
var width = 4;
for (var i = 0; i < size.Height; i++)
{
var start = i * size.Width + (size.Width - width) / 2;
for (var j = 0; j < width; j++)
Data[start + j] = s.ReadUInt8();
width += (i < size.Height / 2 - 1? 1 : -1) * 4;
}
// Ignore Z-data for now
// Ignore extra data for now
}
}
public class TmpTSReader : ISpriteSource
{
readonly List<TmpTSTile> tiles = new List<TmpTSTile>();
public IEnumerable<ISpriteFrame> Frames { get { return tiles.Cast<ISpriteFrame>(); } }
public bool CacheWhenLoadingTileset { get { return false; } }
public TmpTSReader(Stream s)
{
var templateWidth = s.ReadUInt32();
var templateHeight = s.ReadUInt32();
var tileWidth = s.ReadInt32();
var tileHeight = s.ReadInt32();
var size = new Size(tileWidth, tileHeight);
var offsets = new uint[templateWidth * templateHeight];
for (var i = 0; i < offsets.Length; i++)
offsets[i] = s.ReadUInt32();
for (var i = 0; i < offsets.Length; i++)
{
s.Position = offsets[i];
tiles.Add(new TmpTSTile(s, size));
}
}
}
}

View File

@@ -9,6 +9,7 @@
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -28,7 +29,7 @@ namespace OpenRA.FileFormats
public readonly MiniYaml LoadScreen; public readonly MiniYaml LoadScreen;
public readonly MiniYaml LobbyDefaults; public readonly MiniYaml LobbyDefaults;
public readonly Dictionary<string, Pair<string, int>> Fonts; public readonly Dictionary<string, Pair<string, int>> Fonts;
public readonly int TileSize = 24; public readonly Size TileSize = new Size(24, 24);
public Manifest(string mod) public Manifest(string mod)
{ {
@@ -68,7 +69,7 @@ namespace OpenRA.FileFormats
int.Parse(x.Value.NodesDict["Size"].Value))); int.Parse(x.Value.NodesDict["Size"].Value)));
if (yaml.ContainsKey("TileSize")) if (yaml.ContainsKey("TileSize"))
TileSize = int.Parse(yaml["TileSize"].Value); TileSize = FieldLoader.GetValue<Size>("TileSize", yaml["TileSize"].Value);
// Allow inherited mods to import parent maps. // Allow inherited mods to import parent maps.
var compat = new List<string>(); var compat = new List<string>();

View File

@@ -156,6 +156,7 @@
<Compile Include="FileSystem\Pak.cs" /> <Compile Include="FileSystem\Pak.cs" />
<Compile Include="CPos.cs" /> <Compile Include="CPos.cs" />
<Compile Include="CVec.cs" /> <Compile Include="CVec.cs" />
<Compile Include="Graphics\TmpTSReader.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5"> <BootstrapperPackage Include="Microsoft.Net.Client.3.5">

View File

@@ -27,8 +27,6 @@ namespace OpenRA
{ {
public static class Game public static class Game
{ {
public static int CellSize { get { return modData.Manifest.TileSize; } }
public static MouseButtonPreference mouseButtonPreference = new MouseButtonPreference(); public static MouseButtonPreference mouseButtonPreference = new MouseButtonPreference();
public static ModData modData; public static ModData modData;

View File

@@ -235,8 +235,8 @@ namespace OpenRA.Graphics
// Conversion between world and screen coordinates // Conversion between world and screen coordinates
public float2 ScreenPosition(WPos pos) public float2 ScreenPosition(WPos pos)
{ {
var c = Game.CellSize / 1024f; var ts = Game.modData.Manifest.TileSize;
return new float2(c * pos.X, c * (pos.Y - pos.Z)); return new float2(ts.Width * pos.X / 1024f, ts.Height * (pos.Y - pos.Z) / 1024f);
} }
public int2 ScreenPxPosition(WPos pos) public int2 ScreenPxPosition(WPos pos)
@@ -249,8 +249,8 @@ namespace OpenRA.Graphics
// For scaling vectors to pixel sizes in the voxel renderer // For scaling vectors to pixel sizes in the voxel renderer
public float[] ScreenVector(WVec vec) public float[] ScreenVector(WVec vec)
{ {
var c = Game.CellSize / 1024f; var ts = Game.modData.Manifest.TileSize;
return new float[] { c * vec.X, c * vec.Y, c * vec.Z, 1 }; return new float[] { ts.Width * vec.X / 1024f, ts.Height * vec.Y / 1024f, ts.Height * vec.Z / 1024f, 1 };
} }
public int2 ScreenPxOffset(WVec vec) public int2 ScreenPxOffset(WVec vec)
@@ -262,12 +262,14 @@ namespace OpenRA.Graphics
public float ScreenZPosition(WPos pos, int offset) public float ScreenZPosition(WPos pos, int offset)
{ {
return (pos.Y + pos.Z + offset) * Game.CellSize / 1024f; var ts = Game.modData.Manifest.TileSize;
return (pos.Y + pos.Z + offset) * ts.Height / 1024f;
} }
public WPos Position(int2 screenPx) public WPos Position(int2 screenPx)
{ {
return new WPos(1024 * screenPx.X / Game.CellSize, 1024 * screenPx.Y / Game.CellSize, 0); var ts = Game.modData.Manifest.TileSize;
return new WPos(1024 * screenPx.X / ts.Width, 1024 * screenPx.Y / ts.Height, 0);
} }
} }
} }

View File

@@ -36,8 +36,9 @@ namespace OpenRA.Traits
public ScreenMap(World world, ScreenMapInfo info) public ScreenMap(World world, ScreenMapInfo info)
{ {
this.info = info; this.info = info;
cols = world.Map.MapSize.X * Game.CellSize / info.BinSize + 1; var ts = Game.modData.Manifest.TileSize;
rows = world.Map.MapSize.Y * Game.CellSize / info.BinSize + 1; cols = world.Map.MapSize.X * ts.Width / info.BinSize + 1;
rows = world.Map.MapSize.Y * ts.Height / info.BinSize + 1;
frozen = new Cache<Player, Dictionary<FrozenActor, Rectangle>[]>(InitializeFrozenActors); frozen = new Cache<Player, Dictionary<FrozenActor, Rectangle>[]>(InitializeFrozenActors);
actors = new Dictionary<Actor, Rectangle>[rows * cols]; actors = new Dictionary<Actor, Rectangle>[rows * cols];

View File

@@ -95,9 +95,9 @@ namespace OpenRA.Mods.RA
// Synthesize unexplored tile if it isn't defined // Synthesize unexplored tile if it isn't defined
if (!info.Index.Contains(0)) if (!info.Index.Contains(0))
{ {
var size = new Size(Game.modData.Manifest.TileSize, Game.modData.Manifest.TileSize); var ts = Game.modData.Manifest.TileSize;
var data = Exts.MakeArray<byte>(size.Width * size.Height, _ => (byte)info.ShroudColor); var data = Exts.MakeArray<byte>(ts.Width * ts.Height, _ => (byte)info.ShroudColor);
var s = Game.modData.SheetBuilder.Add(data, size); var s = Game.modData.SheetBuilder.Add(data, ts);
unexploredTile = new Sprite(s.sheet, s.bounds, s.offset, s.channel, info.ShroudBlend); unexploredTile = new Sprite(s.sheet, s.bounds, s.offset, s.channel, info.ShroudBlend);
} }
else else

View File

@@ -181,7 +181,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (assetSource == null) if (assetSource == null)
return; return;
var files = assetSource.AllFileNames(); var files = assetSource.AllFileNames().OrderBy(s => s);
foreach (var file in files) foreach (var file in files)
{ {
if (AllowedExtensions.Any(ext => file.EndsWith(ext, true, CultureInfo.InvariantCulture))) if (AllowedExtensions.Any(ext => file.EndsWith(ext, true, CultureInfo.InvariantCulture)))

View File

@@ -43,7 +43,8 @@ namespace OpenRA.Utility
static void ConvertPxToRange(ref string input, int scaleMult, int scaleDiv) static void ConvertPxToRange(ref string input, int scaleMult, int scaleDiv)
{ {
var value = int.Parse(input); var value = int.Parse(input);
var world = value * 1024 * scaleMult / (scaleDiv * Game.CellSize); var ts = Game.modData.Manifest.TileSize;
var world = value * 1024 * scaleMult / (scaleDiv * ts.Height);
var cells = world / 1024; var cells = world / 1024;
var subcells = world - 1024 * cells; var subcells = world - 1024 * cells;
@@ -59,7 +60,8 @@ namespace OpenRA.Utility
static void ConvertInt2ToWVec(ref string input) static void ConvertInt2ToWVec(ref string input)
{ {
var offset = FieldLoader.GetValue<int2>("(value)", input); var offset = FieldLoader.GetValue<int2>("(value)", input);
var world = new WVec(offset.X * 1024 / Game.CellSize, offset.Y * 1024 / Game.CellSize, 0); var ts = Game.modData.Manifest.TileSize;
var world = new WVec(offset.X * 1024 / ts.Width, offset.Y * 1024 / ts.Height, 0);
input = world.ToString(); input = world.ToString();
} }

View File

@@ -91,7 +91,7 @@ Notifications:
TileSets: TileSets:
mods/d2k/tilesets/arrakis.yaml mods/d2k/tilesets/arrakis.yaml
TileSize: 32 TileSize: 32,32
Music: Music:
mods/d2k/music.yaml mods/d2k/music.yaml

Binary file not shown.

Binary file not shown.

View File

@@ -19,8 +19,6 @@ MapFolders:
~^/maps/ts ~^/maps/ts
Packages: Packages:
# Red Alert
interior.mix
# Tiberian Sun # Tiberian Sun
~scores.mix:CRC32 ~scores.mix:CRC32
~sidenc01.mix:CRC32 ~sidenc01.mix:CRC32
@@ -132,7 +130,9 @@ Notifications:
mods/ts/notifications.yaml mods/ts/notifications.yaml
TileSets: TileSets:
mods/ra/tilesets/interior.yaml mods/ts/tilesets/interior.yaml
TileSize: 48,24
Music: Music:
mods/ts/music.yaml mods/ts/music.yaml

View File

@@ -0,0 +1,19 @@
General:
Name: Interior
Id: INTERIOR
Extensions: .tem, .shp
Palette: isotem.pal
Terrain:
TerrainType@Clear:
Type: Clear
AcceptsSmudgeType: Crater, Scorch
Color: 0, 0, 0
Templates:
Template@255:
Id: 255
Image: clear01
Size: 1,1
Tiles:
0: Clear