Merge pull request #4185 from pchote/frame-rework

Rewrite sprite handling.
This commit is contained in:
Matthias Mailänder
2013-11-30 14:46:54 -08:00
55 changed files with 1623 additions and 2439 deletions

View File

@@ -10,6 +10,7 @@
using System;
using System.Drawing;
using OpenRA.FileFormats;
using OpenRA.FileFormats.Graphics;
namespace OpenRA.Graphics
@@ -52,9 +53,14 @@ namespace OpenRA.Graphics
this.allocateSheet = allocateSheet;
}
public Sprite Add(ISpriteFrame frame) { return Add(frame.Data, frame.Size, frame.Offset); }
public Sprite Add(byte[] src, Size size) { return Add(src, size, float2.Zero); }
public Sprite Add(byte[] src, Size size, float2 spriteOffset)
{
// Don't bother allocating empty sprites
if (size.Width == 0 || size.Height == 0)
return new Sprite(current, Rectangle.Empty, spriteOffset, channel, BlendMode.Alpha);
var rect = Allocate(size, spriteOffset);
Util.FastCopyIntoChannel(rect, src);
current.CommitData();

View File

@@ -16,39 +16,25 @@ namespace OpenRA.Graphics
{
public class SpriteLoader
{
public SpriteLoader(string[] exts, SheetBuilder sheetBuilder)
{
SheetBuilder = sheetBuilder;
this.exts = exts;
sprites = new Cache<string, Sprite[]>(LoadSprites);
}
readonly SheetBuilder SheetBuilder;
readonly Cache<string, Sprite[]> sprites;
readonly string[] exts;
Sprite[] LoadSprites(string filename)
public SpriteLoader(string[] exts, SheetBuilder sheetBuilder)
{
// TODO: Cleanly abstract file type detection
if (filename.ToLower().EndsWith("r8"))
{
var r8 = new R8Reader(FileSystem.Open(filename));
return r8.Select(a => SheetBuilder.Add(a.Image, a.Size, a.Offset)).ToArray();
}
SheetBuilder = sheetBuilder;
BinaryReader reader = new BinaryReader(FileSystem.OpenWithExts(filename, exts));
// Include extension-less version
this.exts = exts.Append("").ToArray();
sprites = new Cache<string, Sprite[]>(CacheSpriteFrames);
}
var ImageCount = reader.ReadUInt16();
if (ImageCount == 0)
{
var shp = new ShpTSReader(FileSystem.OpenWithExts(filename, exts));
return shp.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray();
}
else
{
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
return shp.Frames.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray();
}
Sprite[] CacheSpriteFrames(string filename)
{
var stream = FileSystem.OpenWithExts(filename, exts);
return SpriteSource.LoadSpriteSource(stream, filename).Frames
.Select(a => SheetBuilder.Add(a))
.ToArray();
}
public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }

View File

@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.FileFormats;
@@ -22,27 +23,31 @@ namespace OpenRA.Graphics
Dictionary<ushort, Sprite[]> templates;
Sprite missingTile;
Sprite[] LoadTemplate(string filename, string[] exts, Cache<string, R8Reader> r8Cache, int[] frames)
Sprite[] LoadTemplate(string filename, string[] exts, Dictionary<string, ISpriteSource> sourceCache, int[] frames)
{
if (exts.Contains(".R8") && FileSystem.Exists(filename+".R8"))
ISpriteSource source;
if (!sourceCache.ContainsKey(filename))
{
return frames.Select(f =>
{
if (f < 0)
return null;
using (var s = FileSystem.OpenWithExts(filename, exts))
source = SpriteSource.LoadSpriteSource(s, filename);
var image = r8Cache[filename][f];
return sheetBuilder.Add(image.Image, new Size(image.Size.Width, image.Size.Height));
}).ToArray();
if (source.CacheWhenLoadingTileset)
sourceCache.Add(filename, source);
}
else
source = sourceCache[filename];
if (frames != null)
{
var ret = new List<Sprite>();
var srcFrames = source.Frames.ToArray();
foreach (var i in frames)
ret.Add(sheetBuilder.Add(srcFrames[i]));
return ret.ToArray();
}
using (var s = FileSystem.OpenWithExts(filename, exts))
{
var t = new Terrain(s);
return t.TileBitmapBytes
.Select(b => b != null ? sheetBuilder.Add(b, new Size(t.Width, t.Height)) : null)
.ToArray();
}
return source.Frames.Select(f => sheetBuilder.Add(f)).ToArray();
}
public Theater(TileSet tileset)
@@ -57,11 +62,11 @@ namespace OpenRA.Graphics
return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize));
};
var r8Cache = new Cache<string, R8Reader>(s => new R8Reader(FileSystem.OpenWithExts(s, ".R8")));
var sourceCache = new Dictionary<string, ISpriteSource>();
templates = new Dictionary<ushort, Sprite[]>();
sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate);
foreach (var t in tileset.Templates)
templates.Add(t.Value.Id, LoadTemplate(t.Value.Image, tileset.Extensions, r8Cache, t.Value.Frames));
templates.Add(t.Value.Id, LoadTemplate(t.Value.Image, tileset.Extensions, sourceCache, t.Value.Frames));
// 1x1px transparent tile
missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1));
@@ -70,11 +75,13 @@ namespace OpenRA.Graphics
public Sprite TileSprite(TileReference<ushort, byte> r)
{
Sprite[] template;
if (templates.TryGetValue(r.Type, out template))
if (template.Length > r.Index && template[r.Index] != null)
return template[r.Index];
if (!templates.TryGetValue(r.Type, out template))
return missingTile;
return missingTile;
if (r.Index >= template.Length)
return missingTile;
return template[r.Index];
}
public Sheet Sheet { get { return sheetBuilder.Current; } }

View File

@@ -75,7 +75,7 @@ namespace OpenRA
ChromeMetrics.Initialize(Manifest.ChromeMetrics);
ChromeProvider.Initialize(Manifest.Chrome);
SheetBuilder = new SheetBuilder(SheetType.Indexed);
SpriteLoader = new SpriteLoader(new string[] { ".shp" }, SheetBuilder);
SpriteLoader = new SpriteLoader(new string[0], SheetBuilder);
VoxelLoader = new VoxelLoader();
CursorProvider.Initialize(Manifest.Cursors);
}

View File

@@ -56,6 +56,7 @@ namespace OpenRA.Widgets
Sprite sprite = null;
string cachedImage = null;
int cachedFrame = -1;
float2 cachedOffset = float2.Zero;
public override void Draw()
{
@@ -68,9 +69,10 @@ namespace OpenRA.Widgets
sprite = Game.modData.SpriteLoader.LoadAllSprites(image)[frame];
cachedImage = image;
cachedFrame = frame;
cachedOffset = 0.5f * (new float2(RenderBounds.Size) - sprite.size);
}
Game.Renderer.SpriteRenderer.DrawSprite(sprite, RenderOrigin, worldRenderer.Palette(palette));
Game.Renderer.SpriteRenderer.DrawSprite(sprite, RenderOrigin + cachedOffset, worldRenderer.Palette(palette));
}
public int FrameCount

View File

@@ -29,14 +29,14 @@ namespace OpenRA.Widgets
Game.Renderer.RgbaSpriteRenderer.DrawSprite(s,pos);
}
public static void DrawSHP(Sprite s, float2 pos, WorldRenderer wr)
public static void DrawSHPCentered(Sprite s, float2 pos, WorldRenderer wr)
{
Game.Renderer.SpriteRenderer.DrawSprite(s, pos, wr.Palette("chrome"));
Game.Renderer.SpriteRenderer.DrawSprite(s, pos - 0.5f * s.size, wr.Palette("chrome"));
}
public static void DrawSHP(Sprite s, float2 pos, WorldRenderer wr, float2 size)
public static void DrawSHPCentered(Sprite s, float2 pos, WorldRenderer wr, float scale)
{
Game.Renderer.SpriteRenderer.DrawSprite(s, pos, wr.Palette("chrome"), size);
Game.Renderer.SpriteRenderer.DrawSprite(s, pos - 0.5f * scale * s.size, wr.Palette("chrome"), scale * s.size);
}
public static void DrawPanel(string collection, Rectangle Bounds)