Merge pull request #4391 from pchote/rectangular-tiles
Add support for TS terrain sprites and non-square cell sizes.
This commit is contained in:
@@ -11,11 +11,16 @@ NEW:
|
||||
Converted production exits to world coordinates.
|
||||
Converted weapon projectiles 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:
|
||||
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-map <map path> 20131223` to automatically upgrade custom map rules.
|
||||
Added a new trait Demolishable for buildings to handle the C4 demolition.
|
||||
Mods that use custom TileSize must specify both width and height.
|
||||
|
||||
20131223:
|
||||
All mods:
|
||||
|
||||
@@ -63,8 +63,8 @@ namespace OpenRA.Editor
|
||||
public void Preview(Surface surface, SGraphics g)
|
||||
{
|
||||
g.DrawImage(brushTemplate.Bitmap,
|
||||
surface.TileSetRenderer.TileSize.Width * 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().X * surface.Zoom + surface.GetOffset().X,
|
||||
surface.TileSetRenderer.TileSize * surface.GetBrushLocation().Y * surface.Zoom + surface.GetOffset().Y,
|
||||
brushTemplate.Bitmap.Width * surface.Zoom,
|
||||
brushTemplate.Bitmap.Height * surface.Zoom);
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ namespace OpenRA.Editor
|
||||
{
|
||||
Rules.LoadRules(manifest, map);
|
||||
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 palette = new Palette(FileSystem.Open(tileset.Palette), shadowIndex);
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ namespace OpenRA.Editor
|
||||
|
||||
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(),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
@@ -274,9 +274,9 @@ namespace OpenRA.Editor
|
||||
var tile = TileSetRenderer.Data(tr.Type);
|
||||
var index = (tr.Index < tile.Count) ? tr.Index : (byte)0;
|
||||
var rawImage = tile[index];
|
||||
for (var x = 0; x < TileSetRenderer.TileSize.Width; x++)
|
||||
for (var y = 0; y < TileSetRenderer.TileSize.Height; y++)
|
||||
p[(j * TileSetRenderer.TileSize.Width + y) * stride + i * TileSetRenderer.TileSize.Width + x] = Palette.GetColor(rawImage[x + TileSetRenderer.TileSize.Width * y]).ToArgb();
|
||||
for (var x = 0; x < TileSetRenderer.TileSize; x++)
|
||||
for (var y = 0; y < TileSetRenderer.TileSize; y++)
|
||||
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)
|
||||
{
|
||||
@@ -287,12 +287,12 @@ namespace OpenRA.Editor
|
||||
int* q = (int*)srcdata.Scan0.ToPointer();
|
||||
var srcstride = srcdata.Stride >> 2;
|
||||
|
||||
for (var x = 0; x < TileSetRenderer.TileSize.Width; x++)
|
||||
for (var y = 0; y < TileSetRenderer.TileSize.Height; y++)
|
||||
for (var x = 0; x < TileSetRenderer.TileSize; x++)
|
||||
for (var y = 0; y < TileSetRenderer.TileSize; y++)
|
||||
{
|
||||
var c = q[y * srcstride + x];
|
||||
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);
|
||||
@@ -303,14 +303,16 @@ namespace OpenRA.Editor
|
||||
bitmap.UnlockBits(data);
|
||||
|
||||
if (ShowGrid)
|
||||
{
|
||||
using (var g = SGraphics.FromImage(bitmap))
|
||||
{
|
||||
var ts = Game.modData.Manifest.TileSize;
|
||||
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(Game.CellSize, 2), Color.DarkRed);
|
||||
ControlPaint.DrawGrid(g, rect, new Size(Game.CellSize, Game.CellSize), Color.Red);
|
||||
ControlPaint.DrawGrid(g, rect, new Size(2, ts.Height), Color.DarkRed);
|
||||
ControlPaint.DrawGrid(g, rect, new Size(ts.Width, 2), Color.DarkRed);
|
||||
ControlPaint.DrawGrid(g, rect, new Size(ts.Width, ts.Height), Color.Red);
|
||||
}
|
||||
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@@ -318,15 +320,15 @@ namespace OpenRA.Editor
|
||||
{
|
||||
var vX = (int)Math.Floor((mousePos.X - Offset.X) / 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()
|
||||
{
|
||||
var vX = (int)Math.Floor((mousePos.X - Offset.X) / Zoom);
|
||||
var vY = (int)Math.Floor((mousePos.Y - Offset.Y) / Zoom);
|
||||
return new CPos((vX + TileSetRenderer.TileSize.Width - 1) / TileSetRenderer.TileSize.Width,
|
||||
(vY + TileSetRenderer.TileSize.Height - 1) / TileSetRenderer.TileSize.Height);
|
||||
return new CPos((vX + TileSetRenderer.TileSize - 1) / TileSetRenderer.TileSize,
|
||||
(vY + TileSetRenderer.TileSize - 1) / TileSetRenderer.TileSize);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
float offsetX = centered ? bmp.Width / 2 - TileSetRenderer.TileSize.Width / 2 : 0;
|
||||
float drawX = TileSetRenderer.TileSize.Width * location.X * Zoom + Offset.X - offsetX;
|
||||
float offsetX = centered ? bmp.Width / 2 - TileSetRenderer.TileSize / 2 : 0;
|
||||
float drawX = TileSetRenderer.TileSize * location.X * Zoom + Offset.X - offsetX;
|
||||
|
||||
float offsetY = centered ? bmp.Height / 2 - TileSetRenderer.TileSize.Height / 2 : 0;
|
||||
float drawY = TileSetRenderer.TileSize.Height * location.Y * Zoom + Offset.Y - offsetY;
|
||||
float offsetY = centered ? bmp.Height / 2 - TileSetRenderer.TileSize / 2 : 0;
|
||||
float drawY = TileSetRenderer.TileSize * location.Y * Zoom + Offset.Y - offsetY;
|
||||
|
||||
return new float2(drawX, drawY);
|
||||
}
|
||||
@@ -412,24 +414,24 @@ namespace OpenRA.Editor
|
||||
|
||||
var bmp = Chunks[x];
|
||||
|
||||
var drawX = TileSetRenderer.TileSize.Width * (float)ChunkSize * (float)x.X * Zoom + Offset.X;
|
||||
var drawY = TileSetRenderer.TileSize.Height * (float)ChunkSize * (float)x.Y * Zoom + Offset.Y;
|
||||
var drawX = TileSetRenderer.TileSize * (float)ChunkSize * (float)x.X * Zoom + Offset.X;
|
||||
var drawY = TileSetRenderer.TileSize * (float)ChunkSize * (float)x.Y * Zoom + Offset.Y;
|
||||
RectangleF sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height);
|
||||
RectangleF destRect = new RectangleF(drawX, drawY, bmp.Width * Zoom, bmp.Height * Zoom);
|
||||
e.Graphics.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel);
|
||||
}
|
||||
|
||||
e.Graphics.DrawRectangle(CordonPen,
|
||||
Map.Bounds.Left * TileSetRenderer.TileSize.Width * Zoom + Offset.X,
|
||||
Map.Bounds.Top * TileSetRenderer.TileSize.Height * Zoom + Offset.Y,
|
||||
Map.Bounds.Width * TileSetRenderer.TileSize.Width * Zoom,
|
||||
Map.Bounds.Height * TileSetRenderer.TileSize.Height * Zoom);
|
||||
Map.Bounds.Left * TileSetRenderer.TileSize * Zoom + Offset.X,
|
||||
Map.Bounds.Top * TileSetRenderer.TileSize * Zoom + Offset.Y,
|
||||
Map.Bounds.Width * TileSetRenderer.TileSize * Zoom,
|
||||
Map.Bounds.Height * TileSetRenderer.TileSize * Zoom);
|
||||
|
||||
e.Graphics.DrawRectangle(SelectionPen,
|
||||
(SelectionStart.X * TileSetRenderer.TileSize.Width * Zoom) + Offset.X,
|
||||
(SelectionStart.Y * TileSetRenderer.TileSize.Height * Zoom) + Offset.Y,
|
||||
(SelectionEnd - SelectionStart).X * TileSetRenderer.TileSize.Width * Zoom,
|
||||
(SelectionEnd - SelectionStart).Y * TileSetRenderer.TileSize.Height * Zoom);
|
||||
(SelectionStart.X * TileSetRenderer.TileSize * Zoom) + Offset.X,
|
||||
(SelectionStart.Y * TileSetRenderer.TileSize * Zoom) + Offset.Y,
|
||||
(SelectionEnd - SelectionStart).X * TileSetRenderer.TileSize * Zoom,
|
||||
(SelectionEnd - SelectionStart).Y * TileSetRenderer.TileSize * Zoom);
|
||||
|
||||
if (IsPaste)
|
||||
{
|
||||
@@ -438,10 +440,10 @@ namespace OpenRA.Editor
|
||||
var height = Math.Abs((SelectionStart - SelectionEnd).Y);
|
||||
|
||||
e.Graphics.DrawRectangle(PastePen,
|
||||
(loc.X * TileSetRenderer.TileSize.Width * Zoom) + Offset.X,
|
||||
(loc.Y * TileSetRenderer.TileSize.Height * Zoom) + Offset.Y,
|
||||
width * (TileSetRenderer.TileSize.Width * Zoom),
|
||||
height * (TileSetRenderer.TileSize.Height * Zoom));
|
||||
(loc.X * TileSetRenderer.TileSize * Zoom) + Offset.X,
|
||||
(loc.Y * TileSetRenderer.TileSize * Zoom) + Offset.Y,
|
||||
width * (TileSetRenderer.TileSize * Zoom),
|
||||
height * (TileSetRenderer.TileSize * Zoom));
|
||||
}
|
||||
|
||||
foreach (var ar in Map.Actors.Value)
|
||||
@@ -457,8 +459,8 @@ namespace OpenRA.Editor
|
||||
foreach (var ar in Map.Actors.Value)
|
||||
if (!ar.Key.StartsWith("Actor")) // if it has a custom name
|
||||
e.Graphics.DrawStringContrast(Font, ar.Key,
|
||||
(int)(ar.Value.Location().X * TileSetRenderer.TileSize.Width * Zoom + Offset.X),
|
||||
(int)(ar.Value.Location().Y * TileSetRenderer.TileSize.Height * Zoom + Offset.Y),
|
||||
(int)(ar.Value.Location().X * TileSetRenderer.TileSize * Zoom + Offset.X),
|
||||
(int)(ar.Value.Location().Y * TileSetRenderer.TileSize * Zoom + Offset.Y),
|
||||
Brushes.White,
|
||||
Brushes.Black);
|
||||
|
||||
@@ -468,7 +470,7 @@ namespace OpenRA.Editor
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -477,7 +479,7 @@ namespace OpenRA.Editor
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
@@ -21,7 +22,27 @@ namespace OpenRA.Editor
|
||||
{
|
||||
public TileSet TileSet;
|
||||
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)
|
||||
{
|
||||
@@ -42,18 +63,18 @@ namespace OpenRA.Editor
|
||||
var ret = new List<byte[]>();
|
||||
var srcFrames = source.Frames.ToArray();
|
||||
foreach (var i in frames)
|
||||
ret.Add(srcFrames[i].Data);
|
||||
ret.Add(ExtractSquareTile(srcFrames[i]));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return source.Frames.Select(f => f.Data).ToList();
|
||||
return source.Frames.Select(f => ExtractSquareTile(f)).ToList();
|
||||
}
|
||||
|
||||
public TileSetRenderer(TileSet tileset, Size tileSize)
|
||||
{
|
||||
this.TileSet = tileset;
|
||||
this.TileSize = tileSize;
|
||||
this.TileSize = Math.Min(tileSize.Width, tileSize.Height);
|
||||
|
||||
templates = new Dictionary<ushort, List<byte[]>>();
|
||||
var sourceCache = new Dictionary<string, ISpriteSource>();
|
||||
@@ -66,7 +87,7 @@ namespace OpenRA.Editor
|
||||
var template = TileSet.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);
|
||||
|
||||
bitmap.Palette = p.AsSystemPalette();
|
||||
@@ -86,15 +107,15 @@ namespace OpenRA.Editor
|
||||
var rawImage = templateData[u + v * template.Size.X];
|
||||
if (rawImage != null && rawImage.Length > 0)
|
||||
{
|
||||
for (var i = 0; i < TileSize.Width; i++)
|
||||
for (var j = 0; j < TileSize.Height; j++)
|
||||
q[(v * TileSize.Width + j) * stride + u * TileSize.Width + i] = rawImage[i + TileSize.Width * j];
|
||||
for (var i = 0; i < TileSize; i++)
|
||||
for (var j = 0; j < TileSize; j++)
|
||||
q[(v * TileSize + j) * stride + u * TileSize + i] = rawImage[i + TileSize * j];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < TileSize.Width; i++)
|
||||
for (var j = 0; j < TileSize.Height; j++)
|
||||
q[(v * TileSize.Width + j) * stride + u * TileSize.Width + i] = 0;
|
||||
for (var i = 0; i < TileSize; i++)
|
||||
for (var j = 0; j < TileSize; j++)
|
||||
q[(v * TileSize + j) * stride + u * TileSize + i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,6 +282,12 @@ namespace OpenRA.FileFormats
|
||||
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))
|
||||
{
|
||||
var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace OpenRA.FileFormats
|
||||
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
|
||||
{
|
||||
static bool IsTmpRA(Stream s)
|
||||
@@ -57,6 +57,29 @@ namespace OpenRA.FileFormats
|
||||
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)
|
||||
{
|
||||
var start = s.Position;
|
||||
@@ -204,6 +227,9 @@ namespace OpenRA.FileFormats
|
||||
if (IsTmpTD(s))
|
||||
return SpriteType.TmpTD;
|
||||
|
||||
if (IsTmpTS(s))
|
||||
return SpriteType.TmpTS;
|
||||
|
||||
if (IsShpD2(s))
|
||||
return SpriteType.ShpD2;
|
||||
|
||||
@@ -225,6 +251,8 @@ namespace OpenRA.FileFormats
|
||||
return new TmpRAReader(s);
|
||||
case SpriteType.TmpTD:
|
||||
return new TmpTDReader(s);
|
||||
case SpriteType.TmpTS:
|
||||
return new TmpTSReader(s);
|
||||
case SpriteType.ShpD2:
|
||||
return new ShpD2Reader(s);
|
||||
case SpriteType.Unknown:
|
||||
|
||||
75
OpenRA.FileFormats/Graphics/TmpTSReader.cs
Normal file
75
OpenRA.FileFormats/Graphics/TmpTSReader.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
@@ -28,7 +29,7 @@ namespace OpenRA.FileFormats
|
||||
public readonly MiniYaml LoadScreen;
|
||||
public readonly MiniYaml LobbyDefaults;
|
||||
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)
|
||||
{
|
||||
@@ -68,7 +69,7 @@ namespace OpenRA.FileFormats
|
||||
int.Parse(x.Value.NodesDict["Size"].Value)));
|
||||
|
||||
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.
|
||||
var compat = new List<string>();
|
||||
|
||||
@@ -156,6 +156,7 @@
|
||||
<Compile Include="FileSystem\Pak.cs" />
|
||||
<Compile Include="CPos.cs" />
|
||||
<Compile Include="CVec.cs" />
|
||||
<Compile Include="Graphics\TmpTSReader.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
|
||||
@@ -27,8 +27,6 @@ namespace OpenRA
|
||||
{
|
||||
public static class Game
|
||||
{
|
||||
public static int CellSize { get { return modData.Manifest.TileSize; } }
|
||||
|
||||
public static MouseButtonPreference mouseButtonPreference = new MouseButtonPreference();
|
||||
|
||||
public static ModData modData;
|
||||
|
||||
@@ -235,8 +235,8 @@ namespace OpenRA.Graphics
|
||||
// Conversion between world and screen coordinates
|
||||
public float2 ScreenPosition(WPos pos)
|
||||
{
|
||||
var c = Game.CellSize / 1024f;
|
||||
return new float2(c * pos.X, c * (pos.Y - pos.Z));
|
||||
var ts = Game.modData.Manifest.TileSize;
|
||||
return new float2(ts.Width * pos.X / 1024f, ts.Height * (pos.Y - pos.Z) / 1024f);
|
||||
}
|
||||
|
||||
public int2 ScreenPxPosition(WPos pos)
|
||||
@@ -249,8 +249,8 @@ namespace OpenRA.Graphics
|
||||
// For scaling vectors to pixel sizes in the voxel renderer
|
||||
public float[] ScreenVector(WVec vec)
|
||||
{
|
||||
var c = Game.CellSize / 1024f;
|
||||
return new float[] { c * vec.X, c * vec.Y, c * vec.Z, 1 };
|
||||
var ts = Game.modData.Manifest.TileSize;
|
||||
return new float[] { ts.Width * vec.X / 1024f, ts.Height * vec.Y / 1024f, ts.Height * vec.Z / 1024f, 1 };
|
||||
}
|
||||
|
||||
public int2 ScreenPxOffset(WVec vec)
|
||||
@@ -262,12 +262,14 @@ namespace OpenRA.Graphics
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,9 @@ namespace OpenRA.Traits
|
||||
public ScreenMap(World world, ScreenMapInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
cols = world.Map.MapSize.X * Game.CellSize / info.BinSize + 1;
|
||||
rows = world.Map.MapSize.Y * Game.CellSize / info.BinSize + 1;
|
||||
var ts = Game.modData.Manifest.TileSize;
|
||||
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);
|
||||
actors = new Dictionary<Actor, Rectangle>[rows * cols];
|
||||
|
||||
@@ -95,9 +95,9 @@ namespace OpenRA.Mods.RA
|
||||
// Synthesize unexplored tile if it isn't defined
|
||||
if (!info.Index.Contains(0))
|
||||
{
|
||||
var size = new Size(Game.modData.Manifest.TileSize, Game.modData.Manifest.TileSize);
|
||||
var data = Exts.MakeArray<byte>(size.Width * size.Height, _ => (byte)info.ShroudColor);
|
||||
var s = Game.modData.SheetBuilder.Add(data, size);
|
||||
var ts = Game.modData.Manifest.TileSize;
|
||||
var data = Exts.MakeArray<byte>(ts.Width * ts.Height, _ => (byte)info.ShroudColor);
|
||||
var s = Game.modData.SheetBuilder.Add(data, ts);
|
||||
unexploredTile = new Sprite(s.sheet, s.bounds, s.offset, s.channel, info.ShroudBlend);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -181,7 +181,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
if (assetSource == null)
|
||||
return;
|
||||
|
||||
var files = assetSource.AllFileNames();
|
||||
var files = assetSource.AllFileNames().OrderBy(s => s);
|
||||
foreach (var file in files)
|
||||
{
|
||||
if (AllowedExtensions.Any(ext => file.EndsWith(ext, true, CultureInfo.InvariantCulture)))
|
||||
|
||||
@@ -43,7 +43,8 @@ namespace OpenRA.Utility
|
||||
static void ConvertPxToRange(ref string input, int scaleMult, int scaleDiv)
|
||||
{
|
||||
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 subcells = world - 1024 * cells;
|
||||
|
||||
@@ -59,7 +60,8 @@ namespace OpenRA.Utility
|
||||
static void ConvertInt2ToWVec(ref string 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();
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ Notifications:
|
||||
TileSets:
|
||||
mods/d2k/tilesets/arrakis.yaml
|
||||
|
||||
TileSize: 32
|
||||
TileSize: 32,32
|
||||
|
||||
Music:
|
||||
mods/d2k/music.yaml
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -19,8 +19,6 @@ MapFolders:
|
||||
~^/maps/ts
|
||||
|
||||
Packages:
|
||||
# Red Alert
|
||||
interior.mix
|
||||
# Tiberian Sun
|
||||
~scores.mix:CRC32
|
||||
~sidenc01.mix:CRC32
|
||||
@@ -132,7 +130,9 @@ Notifications:
|
||||
mods/ts/notifications.yaml
|
||||
|
||||
TileSets:
|
||||
mods/ra/tilesets/interior.yaml
|
||||
mods/ts/tilesets/interior.yaml
|
||||
|
||||
TileSize: 48,24
|
||||
|
||||
Music:
|
||||
mods/ts/music.yaml
|
||||
|
||||
19
mods/ts/tilesets/interior.yaml
Normal file
19
mods/ts/tilesets/interior.yaml
Normal 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
|
||||
Reference in New Issue
Block a user