From e71450366b914310dae79654aab567f33951324f Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Mon, 15 May 2023 18:36:23 +0200 Subject: [PATCH] additional runtime texture packer improvements --- CHANGELOG.md | 1 + MLEM.Data/RuntimeTexturePacker.cs | 13 +++++++++++-- Tests/TexturePackerTests.cs | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fd9d42..35c3d85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ Fixes ### MLEM.Data Improvements - Improved RuntimeTexturePacker performance for differently sized textures +- Allow querying the amount of RuntimeTexturePacker regions ## 6.1.0 diff --git a/MLEM.Data/RuntimeTexturePacker.cs b/MLEM.Data/RuntimeTexturePacker.cs index 369c0bc..50813e1 100644 --- a/MLEM.Data/RuntimeTexturePacker.cs +++ b/MLEM.Data/RuntimeTexturePacker.cs @@ -33,10 +33,15 @@ namespace MLEM.Data { /// The time that took the last time it was called /// public TimeSpan LastTotalTime => this.LastCalculationTime + this.LastPackTime; + /// + /// The amount of currently packed texture regions. + /// + public int PackedTextures => this.packedTextures.Count; private readonly List texturesToPack = new List(); private readonly List packedTextures = new List(); private readonly Dictionary occupiedPositions = new Dictionary(); + private readonly Dictionary initialPositions = new Dictionary(); private readonly Dictionary dataCache = new Dictionary(); private readonly bool autoIncreaseMaxWidth; private readonly bool forcePowerOfTwo; @@ -222,6 +227,7 @@ namespace MLEM.Data { this.LastPackTime = TimeSpan.Zero; this.texturesToPack.Clear(); this.packedTextures.Clear(); + this.initialPositions.Clear(); this.occupiedPositions.Clear(); this.dataCache.Clear(); } @@ -240,14 +246,17 @@ namespace MLEM.Data { if (size.X <= 0 || size.Y <= 0) return Rectangle.Empty; - var area = new Rectangle(0, 0, size.X, size.Y); + var pos = this.initialPositions.TryGetValue(size, out var first) ? first : Point.Zero; + var area = new Rectangle(pos.X, pos.Y, size.X, size.Y); var lowestY = int.MaxValue; while (true) { // check if the current area is already occupied if (!this.occupiedPositions.TryGetValue(area.Location, out var existing)) { existing = this.packedTextures.FirstOrDefault(t => t.PackedArea.Intersects(area)); + // if no texture is occupying this space, we have found a free area if (existing == null) { - // if no texture is occupying this space, we have found a free area + // if this is the first position that this request fit in, no other requests of the same size will find a position before it + this.initialPositions[area.Size] = area.Location; this.occupiedPositions.Add(area.Location, request); return area; } diff --git a/Tests/TexturePackerTests.cs b/Tests/TexturePackerTests.cs index 9079bd1..4043f88 100644 --- a/Tests/TexturePackerTests.cs +++ b/Tests/TexturePackerTests.cs @@ -126,7 +126,7 @@ public class TexturePackerTests { [Test] public void TestPackTimes() { - for (var total = 1; total <= 1001; total += 100) { + for (var total = 1; total <= 10001; total += 1000) { using var sameSizePacker = new RuntimeTexturePacker(); using var diffSizePacker = new RuntimeTexturePacker(); for (var i = 0; i < total; i++) {