Merge pull request #4185 from pchote/frame-rework
Rewrite sprite handling.
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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]; }
|
||||
|
||||
@@ -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; } }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user