using System; using System.Collections.Generic; using UnityEngine; namespace Assets.ThoMagic.Renderer { internal class CellLayoutPool { private static readonly Dictionary _hashLookup = new Dictionary(); private static readonly Dictionary _sharedCells = new Dictionary(); private static readonly Dictionary> _usageTracker = new Dictionary>(); public static int Count => CellLayoutPool._sharedCells.Count; internal static bool Validate() => CellLayoutPool._hashLookup.Count == CellLayoutPool._sharedCells.Count && CellLayoutPool._hashLookup.Count == CellLayoutPool._usageTracker.Count; public static CellLayout Get( object owner, float cellSizeX, float cellSizeZ, int cellsX, int cellsZ, Bounds bounds) { if (owner == null) throw new ArgumentNullException(nameof(owner)); int hashCode = CellLayoutPool.GetHashCode(cellSizeX, cellSizeZ, cellsX, cellsZ, bounds.min); CellLayout key; if (!CellLayoutPool._sharedCells.TryGetValue(hashCode, out key)) { CellLayoutPool._sharedCells[hashCode] = key = new CellLayout(cellSizeX, cellSizeZ, bounds); CellLayoutPool._hashLookup[key] = hashCode; } CellLayoutPool.IncreaseUsage(hashCode, owner); return key; } public static void Return(object owner, CellLayout layout) { if (owner == null) throw new ArgumentNullException(nameof(owner)); int hash = layout != null ? CellLayoutPool.GetHashCode(layout) : throw new ArgumentNullException(nameof(layout)); if (CellLayoutPool.DecreaseUsage(hash, owner) != 0) return; CellLayoutPool.Dispose(hash, layout); } private static void Dispose(int hash, CellLayout layout) { CellLayoutPool._usageTracker.Remove(hash); CellLayoutPool._sharedCells.Remove(hash); CellLayoutPool._hashLookup.Remove(layout); } private static int GetHashCode(CellLayout layout) => CellLayoutPool._hashLookup[layout]; private static void IncreaseUsage(int hash, object owner) { HashSet intSet; if (!CellLayoutPool._usageTracker.TryGetValue(hash, out intSet) || intSet == null) CellLayoutPool._usageTracker[hash] = intSet = new HashSet(); int hashCode = owner.GetHashCode(); if (intSet.Contains(hashCode)) return; intSet.Add(hashCode); } private static int DecreaseUsage(int hash, object owner) { HashSet intSet = CellLayoutPool._usageTracker[hash]; intSet.Remove(owner.GetHashCode()); return intSet.Count; } private static int GetHashCode( float cellSizeX, float cellSizeZ, int cellsX, int cellsZ, Vector3 initialOrigin) { return HashCode.Combine(cellSizeX, cellSizeZ, cellsX, cellsZ, initialOrigin); } } }