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();
}
}
}