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 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:
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
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
|
#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>();
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)))
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
@@ -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
|
||||||
|
|||||||
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