Support mixed indexed/BGRA terrain tiles.

This commit is contained in:
Paul Chote
2020-12-29 12:36:47 +00:00
committed by reaperrr
parent 142870d78a
commit 632af7c7e6
4 changed files with 28 additions and 39 deletions

View File

@@ -36,22 +36,13 @@ namespace OpenRA.Mods.Common.Terrain
public sealed class DefaultTileCache : IDisposable
{
readonly Dictionary<ushort, TheaterTemplate> templates = new Dictionary<ushort, TheaterTemplate>();
SheetBuilder sheetBuilder;
readonly Cache<SheetType, SheetBuilder> sheetBuilders;
readonly Sprite missingTile;
readonly MersenneTwister random;
public DefaultTileCache(DefaultTerrain terrainInfo, Action<uint, string> onMissingImage = null)
{
var allocated = false;
Func<Sheet> allocate = () =>
{
if (allocated)
throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter.");
allocated = true;
return new Sheet(SheetType.Indexed, new Size(terrainInfo.SheetSize, terrainInfo.SheetSize));
};
sheetBuilders = new Cache<SheetType, SheetBuilder>(t => new SheetBuilder(t, terrainInfo.SheetSize));
random = new MersenneTwister();
@@ -99,25 +90,16 @@ namespace OpenRA.Mods.Common.Terrain
var offset = new float3(f.Offset, zOffset);
var type = SheetBuilder.FrameTypeToSheetType(f.Type);
// Defer SheetBuilder creation until we know what type of frames we are loading!
// TODO: Support mixed indexed and BGRA frames
if (sheetBuilder == null)
sheetBuilder = new SheetBuilder(SheetBuilder.FrameTypeToSheetType(f.Type), allocate);
else if (type != sheetBuilder.Type)
throw new YamlException("Sprite type mismatch. Terrain sprites must all be either Indexed or RGBA.");
var s = sheetBuilder.Allocate(f.Size, zRamp, offset);
var s = sheetBuilders[type].Allocate(f.Size, zRamp, offset);
OpenRA.Graphics.Util.FastCopyIntoChannel(s, f.Data, f.Type);
if (terrainInfo.EnableDepth)
{
var depthFrame = allFrames[j + frameCount];
var ss = sheetBuilder.Allocate(f.Size, zRamp, offset);
var depthType = SheetBuilder.FrameTypeToSheetType(depthFrame.Type);
var ss = sheetBuilders[depthType].Allocate(depthFrame.Size, zRamp, offset);
OpenRA.Graphics.Util.FastCopyIntoChannel(ss, depthFrame.Data, depthFrame.Type);
// s and ss are guaranteed to use the same sheet
// because of the custom terrain sheet allocation
s = new SpriteWithSecondaryData(s, s.Sheet, ss.Bounds, ss.Channel);
s = new SpriteWithSecondaryData(s, ss.Sheet, ss.Bounds, ss.Channel);
}
return s;
@@ -137,12 +119,22 @@ namespace OpenRA.Mods.Common.Terrain
}
// 1x1px transparent tile
if (sheetBuilder.Type == SheetType.BGRA)
missingTile = sheetBuilder.Add(new byte[4], SpriteFrameType.Bgra32, new Size(1, 1));
else
missingTile = sheetBuilder.Add(new byte[1], SpriteFrameType.Indexed8, new Size(1, 1));
var missingDataLength = 1;
var missingFrameType = SpriteFrameType.Indexed8;
var missingSheetType = SheetType.Indexed;
Sheet.ReleaseBuffer();
// Avoid creating an indexed sheet if all tiles are BGRA
var missing = sheetBuilders.FirstOrDefault();
if (missing.Value != null && missing.Key == SheetType.BGRA)
{
missingDataLength = 4;
missingFrameType = SpriteFrameType.Bgra32;
missingSheetType = SheetType.BGRA;
}
missingTile = sheetBuilders[missingSheetType].Add(new byte[missingDataLength], missingFrameType, new Size(1, 1));
foreach (var sb in sheetBuilders.Values)
sb.Current.ReleaseBuffer();
}
public bool HasTileSprite(TerrainTile r, int? variant = null)
@@ -162,11 +154,12 @@ namespace OpenRA.Mods.Common.Terrain
return template.Sprites[start * template.Stride + r.Index];
}
public Sheet Sheet { get { return sheetBuilder.Current; } }
public Sprite MissingTile { get { return missingTile; } }
public void Dispose()
{
sheetBuilder.Dispose();
foreach (var sb in sheetBuilders.Values)
sb.Dispose();
}
}
}

View File

@@ -80,9 +80,7 @@ namespace OpenRA.Mods.Common.Traits
void IWorldLoaded.WorldLoaded(World world, WorldRenderer wr)
{
worldRenderer = wr;
var emptySprite = new Sprite(tileCache.Sheet, Rectangle.Empty, TextureChannel.Alpha);
spriteLayer = new TerrainSpriteLayer(world, wr, emptySprite, BlendMode.Alpha, world.Type != WorldType.Editor);
spriteLayer = new TerrainSpriteLayer(world, wr, tileCache.MissingTile, BlendMode.Alpha, world.Type != WorldType.Editor);
foreach (var cell in map.AllCells)
UpdateCell(cell);
@@ -124,7 +122,7 @@ namespace OpenRA.Mods.Common.Traits
disposed = true;
}
Sheet ITiledTerrainRenderer.Sheet { get { return tileCache.Sheet; } }
Sprite ITiledTerrainRenderer.MissingTile { get { return tileCache.MissingTile; } }
Sprite ITiledTerrainRenderer.TileSprite(TerrainTile r, int? variant)
{

View File

@@ -654,7 +654,7 @@ namespace OpenRA.Mods.Common.Traits
[RequireExplicitImplementation]
public interface ITiledTerrainRenderer
{
Sheet Sheet { get; }
Sprite MissingTile { get; }
Sprite TileSprite(TerrainTile r, int? variant = null);
Rectangle TemplateBounds(TerrainTemplateInfo template);
IEnumerable<IRenderable> RenderUIPreview(WorldRenderer wr, TerrainTemplateInfo template, int2 origin, float scale);

View File

@@ -13,7 +13,6 @@ using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.D2k.Traits
@@ -52,8 +51,7 @@ namespace OpenRA.Mods.D2k.Traits
void IWorldLoaded.WorldLoaded(World w, WorldRenderer wr)
{
var emptySprite = new Sprite(terrainRenderer.Sheet, Rectangle.Empty, TextureChannel.Alpha);
render = new TerrainSpriteLayer(w, wr, emptySprite, BlendMode.Alpha, wr.World.Type != WorldType.Editor);
render = new TerrainSpriteLayer(w, wr, terrainRenderer.MissingTile, BlendMode.Alpha, wr.World.Type != WorldType.Editor);
paletteReference = wr.Palette(info.Palette);
}