using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; namespace UnityExplorer.UI.ObjectPool { public interface IObjectPool { } public class Pool : IObjectPool where T : IPooledObject { // internal pool management private static readonly Dictionary pools = new Dictionary(); public static Pool GetPool() { var type = typeof(T); if (!pools.ContainsKey(type)) CreatePool(); return (Pool)pools[type]; } private static Pool CreatePool() { var pool = new Pool(); pools.Add(typeof(T), pool); return pool; } public static T Borrow() { return GetPool().BorrowObject(); } public static void Return(T obj) { GetPool().ReturnObject(obj); } // Instance public static Pool Instance { get => s_instance ?? CreatePool(); } private static Pool s_instance; public Pool() { s_instance = this; ExplorerCore.LogWarning("Creating Pool<" + typeof(T).Name + ">"); InactiveHolder = new GameObject($"InactiveHolder_{typeof(T).Name}"); InactiveHolder.transform.parent = UIManager.PoolHolder.transform; InactiveHolder.hideFlags |= HideFlags.HideAndDontSave; InactiveHolder.SetActive(false); // Create an instance (not content) to grab the default height. // Tiny bit wasteful, but not a big deal, only happens once per type // and its just the C# wrapper class being created. var obj = (T)Activator.CreateInstance(typeof(T)); DefaultHeight = obj.DefaultHeight; } public GameObject InactiveHolder { get; } public float DefaultHeight { get; } private readonly HashSet available = new HashSet(); private readonly HashSet borrowed = new HashSet(); public int AvailableObjects => available.Count; private void IncrementPool() { var obj = (T)Activator.CreateInstance(typeof(T)); obj.CreateContent(InactiveHolder); available.Add(obj); } public T BorrowObject() { if (available.Count <= 0) IncrementPool(); var obj = available.First(); available.Remove(obj); borrowed.Add(obj); return obj; } public void ReturnObject(T obj) { if (!borrowed.Contains(obj)) ExplorerCore.LogWarning($"Returning an item to object pool ({typeof(T).Name}) but the item didn't exist in the borrowed list?"); else borrowed.Remove(obj); available.Add(obj); obj.UIRoot.transform.SetParent(InactiveHolder.transform, false); } } }