Skip to content

Commit

Permalink
Tile layer memory consumption (prime31#797)
Browse files Browse the repository at this point in the history
* tile layers now need less memory

* reducing loading time when using base64 encoded layers
  • Loading branch information
stallratte authored and NowSayPillow committed Aug 2, 2024
1 parent aeb1f35 commit da86d4b
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 86 deletions.
46 changes: 7 additions & 39 deletions Nez.Portable/Assets/Tiled/Runtime/Layer.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ public partial class TmxLayer : ITmxLayer
/// <param name="y">The y coordinate.</param>
public TmxLayerTile GetTile(int x, int y)
{
return GetTile(x + y * Width);
Tiles.TryGetValue(Grid[x + y * Width], out var tmxLayerTile);

return tmxLayerTile;
}

public TmxLayerTile GetTile(int index)
Expand All @@ -39,7 +41,6 @@ public TmxLayerTile GetTileAtWorldPosition(Vector2 pos)
/// </summary>
public List<Rectangle> GetCollisionRectangles()
{
var checkedIndexes = new bool?[Grid.Length];
var checkedIndexes = new bool?[Grid.Length];
var rectangles = new List<Rectangle>();
var startCol = -1;
Expand Down Expand Up @@ -146,44 +147,14 @@ public List<TmxLayerTile> GetTilesIntersectingBounds(Rectangle bounds)
/// <returns>The tile.</returns>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
/// <param name="tile">Tile.</param>
[Obsolete("Please use SetTile with gid instead.")]
public TmxLayerTile SetTile(int x, int y, TmxLayerTile tile)
{
return SetTile(x, y, tile.Gid, tile.HorizontalFlip, tile.VerticalFlip, tile.DiagonalFlip);
}

/// <summary>
/// Sets the tile at position x, y.
/// </summary>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
/// <param name="gid">Global Tile ID (without the flip flags)</param>
/// <param name="flipHorizontally">Should the tile be flipped horizontally?</param>
/// <param name="flipVertically">Should the tile be flipped vertically?</param>
/// <param name="flipDiagonally">Should the tile be flipped diagonally?</param>
/// <returns>The tile.</returns>
public TmxLayerTile SetTile(int x, int y, int gid, bool flipHorizontally = false, bool flipVertically = false, bool flipDiagonally = false)
{
if (gid == 0) return null;

uint rawGid = TmxLayerTile.GetRawGid(gid, flipHorizontally, flipVertically, flipDiagonally);

Grid[x + y * Width] = rawGid;
Grid[x + y * Width] = tile.RawGid;
Tiles.Add(tile.RawGid, tile);
tile.Tileset = Map.GetTilesetForTileGid(tile.Gid);

TmxLayerTile tileToSet;

if (!Tiles.TryGetValue(rawGid, out var tmxLayerTile))
{
tileToSet = new TmxLayerTile(Map, rawGid);
Tiles.Add(rawGid, tileToSet);
}
else
tileToSet = tmxLayerTile;

return tileToSet;
return tile;
}

/// <summary>
Expand All @@ -194,8 +165,5 @@ public TmxLayerTile SetTile(int x, int y, int gid, bool flipHorizontally = false
public void RemoveTile(int x, int y) {
Grid[x + y * Width] = 0;
}
public void RemoveTile(int x, int y) {
Grid[x + y * Width] = 0;
}
}
}
62 changes: 26 additions & 36 deletions Nez.Portable/Assets/Tiled/Runtime/TiledMapLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -323,30 +323,26 @@ public static TmxLayer LoadTmxLayer(this TmxLayer layer, TmxMap map, XElement xL

var xData = xLayer.Element("data");
var encoding = (string)xData.Attribute("encoding");

layer.Grid = new uint[width * height];
layer.Tiles = new Dictionary<uint, TmxLayerTile>();

if (encoding == "base64")
{
var decodedStream = new TmxBase64Data(xData);

var index = 0;
using (var stream = decodedStream.Data)
{
using (var br = new BinaryReader(stream))
{
using (var stream = decodedStream.Data) {
using (var br = new BinaryReader(stream)) {
const int uintSizeInBytes = sizeof(uint);

var buffer = new byte[uintSizeInBytes * 1024];
int bytesRead;

while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
{
while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0) {
var numberOfUIntValuesRead = bytesRead / uintSizeInBytes;

for (var i = 0; i < numberOfUIntValuesRead; i++)
{

for (var i = 0; i < numberOfUIntValuesRead; i++) {
var gid = BitConverter.ToUInt32(buffer, i * uintSizeInBytes);
AddTile(layer, map, gid);
layer.Grid[index++] = gid;
Expand All @@ -358,38 +354,31 @@ public static TmxLayer LoadTmxLayer(this TmxLayer layer, TmxMap map, XElement xL
else if (encoding == "csv")
{
var csvData = xData.Value;
var k = 0;
var startIndex = 0;
uint gid;

for (var i = 0; i < csvData.Length; i++)
int k = 0;

int startIndex = 0;
for (var i = 0; i < csvData.Length; i++)
{
if (csvData[i] == ',')
{
gid = ParseString(csvData, startIndex, i - startIndex);

var gid = ParseString(csvData, startIndex, i - startIndex);
AddTile(layer, map, gid);
layer.Grid[k++] = gid;

layer.Grid[k++] = gid;
startIndex = i + 1;
}
}

// Add remaining uid
gid = ParseString(csvData, startIndex, csvData.Length - 1 - startIndex);

AddTile(layer, map, gid);
layer.Grid[k] = gid;
}
else if (encoding == null)
{
int k = 0;
foreach (var e in xData.Elements("tile"))
{
var gid = (uint?)e.Attribute("gid") ?? 0;

AddTile(layer, map, gid);
layer.Grid[k++] = gid;
layer.Grid[k++] = gid;
}
}
else throw new Exception("TmxLayer: Unknown encoding.");
Expand All @@ -399,25 +388,24 @@ public static TmxLayer LoadTmxLayer(this TmxLayer layer, TmxMap map, XElement xL
return layer;
}

private static void AddTile(TmxLayer layer, TmxMap map, uint gid)
{
if (gid != 0 && !layer.Tiles.ContainsKey(gid))
private static void AddTile(TmxLayer layer, TmxMap map, uint gid) {
if (gid != 0 && !layer.Tiles.ContainsKey(gid))
{
layer.Tiles.Add(gid, new TmxLayerTile(map, gid));
}
}

private static uint ParseString(string str, int startIndex, int length)
private static uint ParseString(string str, int startIndex, int length)
{
uint result = 0;
for (int i = startIndex; i < startIndex + length; i++)
{
if (char.IsDigit(str[i]))
if(char.IsDigit(str[i]))
result = result * 10u + (uint)(str[i] - '0');
}
return result;
}

public static TmxObjectGroup LoadTmxObjectGroup(this TmxObjectGroup group, TmxMap map, XElement xObjectGroup)
{
group.Map = map;
Expand Down Expand Up @@ -488,6 +476,7 @@ public static TmxObject LoadTmxObject(this TmxObject obj, TmxMap map, XElement x

if (xGid != null)
{
obj.Tile = new TmxLayerTile(map, (uint)xGid);
obj.Tile = new TmxLayerTile(map, (uint)xGid);
obj.ObjectType = TmxObjectType.Tile;
}
Expand Down Expand Up @@ -542,6 +531,7 @@ public static TmxObject LoadTmxObjectFromTemplate(this TmxObject obj, TmxMap map

if (xGid != null)
{
obj.Tile = new TmxLayerTile(map, (uint)xGid);
obj.Tile = new TmxLayerTile(map, (uint)xGid);
obj.ObjectType = TmxObjectType.Tile;
}
Expand Down
22 changes: 17 additions & 5 deletions Nez.Portable/Assets/Tiled/TiledTypes/Layer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,17 @@ public partial class TmxLayer : ITmxLayer
public uint[] Grid;
public Dictionary<uint, TmxLayerTile> Tiles;

public uint[] Grid;
public Dictionary<uint, TmxLayerTile> Tiles;

/// <summary>
/// returns the TmxLayerTile with gid. This is a slow lookup so cache it!
/// </summary>
/// <param name="gid"></param>
/// <returns></returns>
public TmxLayerTile GetTileWithGid(uint gid) {
Tiles.TryGetValue(gid, out var result);
return result;
public TmxLayerTile GetTileWithGid(uint gid) {
Tiles.TryGetValue(gid, out var result);
return result;
Expand All @@ -47,11 +53,13 @@ public class TmxLayerTile
const uint FLIPPED_VERTICALLY_FLAG = 0x40000000;
const uint FLIPPED_DIAGONALLY_FLAG = 0x20000000;

public readonly TmxTileset Tileset;
public readonly int Gid;
public readonly bool HorizontalFlip;
public readonly bool VerticalFlip;
public readonly bool DiagonalFlip;
public TmxTileset Tileset;
// GID which still contains the flip flags.
public uint RawGid;
public int Gid;
public bool HorizontalFlip;
public bool VerticalFlip;
public bool DiagonalFlip;

int? _tilesetTileIndex;

Expand Down Expand Up @@ -82,8 +90,12 @@ public TmxTilesetTile TilesetTile
}
}

public TmxLayerTile(TmxMap map, uint rawGid)

public TmxLayerTile(TmxMap map, uint rawGid)
{
RawGid = rawGid;

// Scan for tile flip bit flags
bool flip;
flip = (rawGid & FLIPPED_HORIZONTALLY_FLAG) != 0;
Expand Down
Loading

0 comments on commit da86d4b

Please sign in to comment.