diff --git a/OpenRA.Game/Graphics/SheetBuilder.cs b/OpenRA.Game/Graphics/SheetBuilder.cs index 74c57f92a2..6b8a0ff930 100644 --- a/OpenRA.Game/Graphics/SheetBuilder.cs +++ b/OpenRA.Game/Graphics/SheetBuilder.cs @@ -15,11 +15,8 @@ namespace OpenRA.Graphics { public class SheetOverflowException : Exception { - public SheetOverflowException() - : base("Sprite sequence spans multiple sheets.\n"+ - "This should be considered as a bug, but you "+ - "can increase the Graphics.SheetSize setting "+ - "to temporarily avoid the problem.") {} + public SheetOverflowException(string message) + : base(message) {} } public enum SheetType @@ -36,28 +33,38 @@ namespace OpenRA.Graphics SheetType type; int rowHeight = 0; Point p; + Func allocateSheet; - internal SheetBuilder(SheetType t) + public static Sheet AllocateSheet() { - current = new Sheet(new Size(Renderer.SheetSize, Renderer.SheetSize));; - channel = TextureChannel.Red; - type = t; + return new Sheet(new Size(Renderer.SheetSize, Renderer.SheetSize));; } - public Sprite Add(byte[] src, Size size, bool allowSheetOverflow) + internal SheetBuilder(SheetType t) + : this(t, AllocateSheet) {} + + internal SheetBuilder(SheetType t, Func allocateSheet) { - var rect = Allocate(size, allowSheetOverflow); + channel = TextureChannel.Red; + type = t; + current = allocateSheet(); + this.allocateSheet = allocateSheet; + } + + public Sprite Add(byte[] src, Size size) + { + var rect = Allocate(size); Util.FastCopyIntoChannel(rect, src); return rect; } - public Sprite Add(Size size, byte paletteIndex, bool allowSheetOverflow) + public Sprite Add(Size size, byte paletteIndex) { var data = new byte[size.Width * size.Height]; for (var i = 0; i < data.Length; i++) data[i] = paletteIndex; - return Add(data, size, allowSheetOverflow); + return Add(data, size); } TextureChannel? NextChannel(TextureChannel t) @@ -69,7 +76,7 @@ namespace OpenRA.Graphics return (TextureChannel)nextChannel; } - public Sprite Allocate(Size imageSize, bool allowSheetOverflow) + public Sprite Allocate(Size imageSize) { if (imageSize.Width + p.X > current.Size.Width) { @@ -85,10 +92,7 @@ namespace OpenRA.Graphics var next = NextChannel(channel); if (next == null) { - if (!allowSheetOverflow) - throw new SheetOverflowException(); - - current = new Sheet(new Size(Renderer.SheetSize, Renderer.SheetSize)); + current = allocateSheet(); channel = TextureChannel.Red; } else diff --git a/OpenRA.Game/Graphics/SpriteFont.cs b/OpenRA.Game/Graphics/SpriteFont.cs index f4284b8055..66e1c8dfb7 100644 --- a/OpenRA.Game/Graphics/SpriteFont.cs +++ b/OpenRA.Game/Graphics/SpriteFont.cs @@ -99,7 +99,7 @@ namespace OpenRA.Graphics face.Glyph.RenderGlyph(RenderMode.Normal); var size = new Size((int)face.Glyph.Metrics.Width >> 6, (int)face.Glyph.Metrics.Height >> 6); - var s = builder.Allocate(size, true); + var s = builder.Allocate(size); var g = new GlyphInfo { diff --git a/OpenRA.Game/Graphics/SpriteLoader.cs b/OpenRA.Game/Graphics/SpriteLoader.cs index ca6e7f49b9..9ada3d035e 100644 --- a/OpenRA.Game/Graphics/SpriteLoader.cs +++ b/OpenRA.Game/Graphics/SpriteLoader.cs @@ -35,12 +35,12 @@ namespace OpenRA.Graphics if (ImageCount == 0) { var shp = new ShpTSReader(FileSystem.OpenWithExts(filename, exts)); - return shp.Select(a => SheetBuilder.Add(a.Image, shp.Size, true)).ToArray(); + 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, true)).ToArray(); + return shp.Frames.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray(); } } diff --git a/OpenRA.Game/Graphics/TerrainRenderer.cs b/OpenRA.Game/Graphics/TerrainRenderer.cs index c8a43df742..240bceca21 100644 --- a/OpenRA.Game/Graphics/TerrainRenderer.cs +++ b/OpenRA.Game/Graphics/TerrainRenderer.cs @@ -29,11 +29,22 @@ namespace OpenRA.Graphics this.world = world; this.map = world.Map; - // TODO: Use a fixed sheet size specified in the tileset yaml - sheetBuilder = new SheetBuilder(SheetType.Indexed); + var allocated = false; + Func allocate = () => + { + if (allocated) + throw new SheetOverflowException("Terrain sheet overflow"); + allocated = true; + + // TODO: Use a fixed sheet size specified in the tileset yaml + return SheetBuilder.AllocateSheet(); + }; + + sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); + var tileSize = new Size(Game.CellSize, Game.CellSize); var tileMapping = new Cache, Sprite>( - x => sheetBuilder.Add(world.TileSet.GetBytes(x), tileSize, false)); + x => sheetBuilder.Add(world.TileSet.GetBytes(x), tileSize)); var terrainPalette = wr.Palette("terrain").Index; var vertices = new Vertex[4 * map.Bounds.Height * map.Bounds.Width]; diff --git a/OpenRA.Game/Graphics/VoxelLoader.cs b/OpenRA.Game/Graphics/VoxelLoader.cs index 89ad57590d..500b41d708 100644 --- a/OpenRA.Game/Graphics/VoxelLoader.cs +++ b/OpenRA.Game/Graphics/VoxelLoader.cs @@ -41,6 +41,20 @@ namespace OpenRA.Graphics int totalVertexCount; int cachedVertexCount; + SheetBuilder CreateSheetBuilder() + { + var allocated = false; + Func allocate = () => + { + if (allocated) + throw new SheetOverflowException(""); + allocated = true; + return SheetBuilder.AllocateSheet(); + }; + + return new SheetBuilder(SheetType.DualIndexed, allocate); + } + public VoxelLoader() { voxels = new Cache, Voxel>(LoadFile); @@ -48,7 +62,7 @@ namespace OpenRA.Graphics totalVertexCount = 0; cachedVertexCount = 0; - sheetBuilder = new SheetBuilder(SheetType.DualIndexed); + sheetBuilder = CreateSheetBuilder(); } static float[] channelSelect = { 0.75f, 0.25f, -0.25f, -0.75f }; @@ -67,7 +81,7 @@ namespace OpenRA.Graphics c++; } - Sprite s = sheetBuilder.Allocate(new Size(su, sv), false); + Sprite s = sheetBuilder.Allocate(new Size(su, sv)); Util.FastCopyIntoChannel(s, 0, colors); Util.FastCopyIntoChannel(s, 1, normals); s.sheet.MakeDirty(); @@ -164,7 +178,7 @@ namespace OpenRA.Graphics { // Sheet overflow - allocate a new sheet and try once more Log.Write("debug", "Voxel sheet overflow! Generating new sheet"); - sheetBuilder = new SheetBuilder(SheetType.DualIndexed); + sheetBuilder = CreateSheetBuilder(); v = GenerateSlicePlanes(l).SelectMany(x => x).ToArray(); } diff --git a/OpenRA.Mods.RA/Bridge.cs b/OpenRA.Mods.RA/Bridge.cs index c3b4425594..b889b4e8c9 100644 --- a/OpenRA.Mods.RA/Bridge.cs +++ b/OpenRA.Mods.RA/Bridge.cs @@ -101,7 +101,7 @@ namespace OpenRA.Mods.RA cachedTileset = self.World.Map.Tileset; var tileSize = new Size(Game.CellSize, Game.CellSize); sprites = new Cache, Sprite>( - x => Game.modData.SheetBuilder.Add(self.World.TileSet.GetBytes(x), tileSize, true)); + x => Game.modData.SheetBuilder.Add(self.World.TileSet.GetBytes(x), tileSize)); } // Cache templates and tiles for the different states