Support mixed indexed/BGRA terrain tiles.
This commit is contained in:
@@ -36,22 +36,13 @@ namespace OpenRA.Mods.Common.Terrain
|
|||||||
public sealed class DefaultTileCache : IDisposable
|
public sealed class DefaultTileCache : IDisposable
|
||||||
{
|
{
|
||||||
readonly Dictionary<ushort, TheaterTemplate> templates = new Dictionary<ushort, TheaterTemplate>();
|
readonly Dictionary<ushort, TheaterTemplate> templates = new Dictionary<ushort, TheaterTemplate>();
|
||||||
SheetBuilder sheetBuilder;
|
readonly Cache<SheetType, SheetBuilder> sheetBuilders;
|
||||||
readonly Sprite missingTile;
|
readonly Sprite missingTile;
|
||||||
readonly MersenneTwister random;
|
readonly MersenneTwister random;
|
||||||
|
|
||||||
public DefaultTileCache(DefaultTerrain terrainInfo, Action<uint, string> onMissingImage = null)
|
public DefaultTileCache(DefaultTerrain terrainInfo, Action<uint, string> onMissingImage = null)
|
||||||
{
|
{
|
||||||
var allocated = false;
|
sheetBuilders = new Cache<SheetType, SheetBuilder>(t => new SheetBuilder(t, terrainInfo.SheetSize));
|
||||||
|
|
||||||
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));
|
|
||||||
};
|
|
||||||
|
|
||||||
random = new MersenneTwister();
|
random = new MersenneTwister();
|
||||||
|
|
||||||
@@ -99,25 +90,16 @@ namespace OpenRA.Mods.Common.Terrain
|
|||||||
var offset = new float3(f.Offset, zOffset);
|
var offset = new float3(f.Offset, zOffset);
|
||||||
var type = SheetBuilder.FrameTypeToSheetType(f.Type);
|
var type = SheetBuilder.FrameTypeToSheetType(f.Type);
|
||||||
|
|
||||||
// Defer SheetBuilder creation until we know what type of frames we are loading!
|
var s = sheetBuilders[type].Allocate(f.Size, zRamp, offset);
|
||||||
// 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);
|
|
||||||
OpenRA.Graphics.Util.FastCopyIntoChannel(s, f.Data, f.Type);
|
OpenRA.Graphics.Util.FastCopyIntoChannel(s, f.Data, f.Type);
|
||||||
|
|
||||||
if (terrainInfo.EnableDepth)
|
if (terrainInfo.EnableDepth)
|
||||||
{
|
{
|
||||||
var depthFrame = allFrames[j + frameCount];
|
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);
|
OpenRA.Graphics.Util.FastCopyIntoChannel(ss, depthFrame.Data, depthFrame.Type);
|
||||||
|
s = new SpriteWithSecondaryData(s, ss.Sheet, ss.Bounds, ss.Channel);
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
@@ -137,12 +119,22 @@ namespace OpenRA.Mods.Common.Terrain
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 1x1px transparent tile
|
// 1x1px transparent tile
|
||||||
if (sheetBuilder.Type == SheetType.BGRA)
|
var missingDataLength = 1;
|
||||||
missingTile = sheetBuilder.Add(new byte[4], SpriteFrameType.Bgra32, new Size(1, 1));
|
var missingFrameType = SpriteFrameType.Indexed8;
|
||||||
else
|
var missingSheetType = SheetType.Indexed;
|
||||||
missingTile = sheetBuilder.Add(new byte[1], SpriteFrameType.Indexed8, new Size(1, 1));
|
|
||||||
|
|
||||||
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)
|
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];
|
return template.Sprites[start * template.Stride + r.Index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sheet Sheet { get { return sheetBuilder.Current; } }
|
public Sprite MissingTile { get { return missingTile; } }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
sheetBuilder.Dispose();
|
foreach (var sb in sheetBuilders.Values)
|
||||||
|
sb.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,9 +80,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
void IWorldLoaded.WorldLoaded(World world, WorldRenderer wr)
|
void IWorldLoaded.WorldLoaded(World world, WorldRenderer wr)
|
||||||
{
|
{
|
||||||
worldRenderer = wr;
|
worldRenderer = wr;
|
||||||
var emptySprite = new Sprite(tileCache.Sheet, Rectangle.Empty, TextureChannel.Alpha);
|
spriteLayer = new TerrainSpriteLayer(world, wr, tileCache.MissingTile, BlendMode.Alpha, world.Type != WorldType.Editor);
|
||||||
spriteLayer = new TerrainSpriteLayer(world, wr, emptySprite, BlendMode.Alpha, world.Type != WorldType.Editor);
|
|
||||||
|
|
||||||
foreach (var cell in map.AllCells)
|
foreach (var cell in map.AllCells)
|
||||||
UpdateCell(cell);
|
UpdateCell(cell);
|
||||||
|
|
||||||
@@ -124,7 +122,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
disposed = true;
|
disposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sheet ITiledTerrainRenderer.Sheet { get { return tileCache.Sheet; } }
|
Sprite ITiledTerrainRenderer.MissingTile { get { return tileCache.MissingTile; } }
|
||||||
|
|
||||||
Sprite ITiledTerrainRenderer.TileSprite(TerrainTile r, int? variant)
|
Sprite ITiledTerrainRenderer.TileSprite(TerrainTile r, int? variant)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -654,7 +654,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
[RequireExplicitImplementation]
|
[RequireExplicitImplementation]
|
||||||
public interface ITiledTerrainRenderer
|
public interface ITiledTerrainRenderer
|
||||||
{
|
{
|
||||||
Sheet Sheet { get; }
|
Sprite MissingTile { get; }
|
||||||
Sprite TileSprite(TerrainTile r, int? variant = null);
|
Sprite TileSprite(TerrainTile r, int? variant = null);
|
||||||
Rectangle TemplateBounds(TerrainTemplateInfo template);
|
Rectangle TemplateBounds(TerrainTemplateInfo template);
|
||||||
IEnumerable<IRenderable> RenderUIPreview(WorldRenderer wr, TerrainTemplateInfo template, int2 origin, float scale);
|
IEnumerable<IRenderable> RenderUIPreview(WorldRenderer wr, TerrainTemplateInfo template, int2 origin, float scale);
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Primitives;
|
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.D2k.Traits
|
namespace OpenRA.Mods.D2k.Traits
|
||||||
@@ -52,8 +51,7 @@ namespace OpenRA.Mods.D2k.Traits
|
|||||||
|
|
||||||
void IWorldLoaded.WorldLoaded(World w, WorldRenderer wr)
|
void IWorldLoaded.WorldLoaded(World w, WorldRenderer wr)
|
||||||
{
|
{
|
||||||
var emptySprite = new Sprite(terrainRenderer.Sheet, Rectangle.Empty, TextureChannel.Alpha);
|
render = new TerrainSpriteLayer(w, wr, terrainRenderer.MissingTile, BlendMode.Alpha, wr.World.Type != WorldType.Editor);
|
||||||
render = new TerrainSpriteLayer(w, wr, emptySprite, BlendMode.Alpha, wr.World.Type != WorldType.Editor);
|
|
||||||
paletteReference = wr.Palette(info.Palette);
|
paletteReference = wr.Palette(info.Palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user