Created
April 18, 2020 13:50
-
-
Save TinkerWorX/049860022a125c79f3c8bcb2b7473817 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class TileAtlas : IReadOnlyList<Rectangle> | |
{ | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
private static Rectangle IndexToRectangle(int index, int stride, int tileSize) => new Rectangle((index % stride) * tileSize, (index / stride) * tileSize, tileSize, tileSize); | |
private readonly int stride; | |
private readonly int colorCount; | |
public TileAtlas(GraphicsDevice graphicsDevice, int tileSize, int atlasSize = 4096) | |
{ | |
this.stride = atlasSize / tileSize; | |
this.colorCount = (int)Math.Pow(tileSize, 2); | |
this.Capacity = (int)Math.Pow(this.stride, 2); | |
this.TileSize = tileSize; | |
this.Texture = new Texture2D(graphicsDevice, atlasSize, atlasSize, false, SurfaceFormat.Color); | |
this.Add(Enumerable.Repeat(Color.Transparent, this.colorCount).ToArray()); | |
} | |
public int TileSize { get; } | |
public Texture2D Texture { get; } | |
public int Capacity { get; } | |
public int Count { get; private set; } | |
public Rectangle this[int index] | |
{ | |
get | |
{ | |
if (index < 0 || index >= this.Capacity) | |
{ | |
throw new IndexOutOfRangeException(); | |
} | |
return IndexToRectangle(index, this.stride, this.TileSize); | |
} | |
} | |
public int Add(Color[] data) | |
{ | |
var index = this.Count; | |
if (index >= this.Capacity) | |
{ | |
throw new InvalidOperationException("TileAtlas is at max capacity."); | |
} | |
this.Count++; | |
this.Texture.SetData(0, IndexToRectangle(index, this.stride, this.TileSize), data, 0, this.colorCount); | |
return index; | |
} | |
public (int firstId, int lastId) AddSet(Texture2D texture) | |
{ | |
var colors = new Color[this.colorCount]; | |
var tilesWide = texture.Width / this.TileSize; | |
var tilesHigh = texture.Height / this.TileSize; | |
int? firstIndex = null; | |
int? lastIndex = null; | |
for (var y = 0; y < tilesHigh; y++) | |
{ | |
for (var x = 0; x < tilesWide; x++) | |
{ | |
var rect = IndexToRectangle((y * tilesWide) + x, tilesWide, this.TileSize); | |
texture.GetData(0, rect, colors, 0, this.colorCount); | |
if (!firstIndex.HasValue) | |
{ | |
lastIndex = firstIndex = this.Add(colors); | |
} | |
else | |
{ | |
lastIndex = this.Add(colors); | |
} | |
} | |
} | |
return (firstIndex.Value, lastIndex.Value); | |
} | |
public void Set(int index, Color[] data) | |
{ | |
if (index < 0 || index >= this.Capacity) | |
{ | |
throw new ArgumentOutOfRangeException(nameof(index)); | |
} | |
this.Texture.SetData(0, IndexToRectangle(index, this.stride, this.TileSize), data, 0, this.colorCount); | |
} | |
public void Clear() | |
{ | |
this.Count = 1; | |
} | |
public IEnumerator<Rectangle> GetEnumerator() | |
{ | |
for (var i = 0; i < this.Count; i++) | |
{ | |
yield return IndexToRectangle(i, this.stride, this.TileSize); | |
} | |
} | |
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment