// ===================================================================== // Copyright 2013-2017 Fluffy Underware // All rights reserved // // http://www.fluffyunderware.com // ===================================================================== using UnityEngine; using System.Collections; using System.Collections.Generic; using System; using FluffyUnderware.DevTools.Extensions; namespace FluffyUnderware.DevTools { /// /// Manages the object's pools components /// [HelpURL(DTUtility.HelpUrlBase + "dtpoolmanager")] [ExecuteAlways] [DisallowMultipleComponent] public class PoolManager : DTVersionedMonoBehaviour { [Section("General")] [SerializeField] bool m_AutoCreatePools = true; [AsGroup(Expanded = false)] [SerializeField] PoolSettings m_DefaultSettings = new PoolSettings(); public bool AutoCreatePools { get { return m_AutoCreatePools; } set { if (m_AutoCreatePools != value) m_AutoCreatePools = value; } } public PoolSettings DefaultSettings { get { return m_DefaultSettings; } set { if (m_DefaultSettings != value) m_DefaultSettings = value; if (m_DefaultSettings != null) m_DefaultSettings.OnValidate(); } } public bool IsInitialized { get; private set; } public int Count { get { return Pools.Count + TypePools.Count; } } public Dictionary Pools = new Dictionary(); public Dictionary TypePools = new Dictionary(); IPool[] mPools = new IPool[0]; #if UNITY_EDITOR void OnValidate() { DefaultSettings = m_DefaultSettings; } #endif void OnDisable() { IsInitialized = false; } void Update() { #if UNITY_EDITOR if (!Application.isPlaying) Initialize(); #endif if (!IsInitialized) Initialize(); if (mPools.Length != TypePools.Count) { System.Array.Resize(ref mPools, TypePools.Count); TypePools.Values.CopyTo(mPools, 0); } for (int i = 0; i < mPools.Length; i++) mPools[i].Update(); } void Initialize() { Pools.Clear(); IPool[] goPools = GetComponents(); foreach (IPool p in goPools) { if (p is ComponentPool) { if(Pools.ContainsKey(p.Identifier) == false) Pools.Add(p.Identifier, p); else { DTLog.Log("[DevTools] Found a duplicated ComponentPool for type " + p.Identifier + ". The duplicated pool will be destroyed"); (p as ComponentPool).Destroy(false, false); } } else { p.Identifier = GetUniqueIdentifier(p.Identifier); Pools.Add(p.Identifier, p); } } IsInitialized = true; } public string GetUniqueIdentifier(string ident) { int num = 0; string id = ident; while (Pools.ContainsKey(id)) id = ident + (++num).ToString(); return id; } public Pool GetTypePool() { IPool res = null; if (!TypePools.TryGetValue(typeof(T), out res)) { if (AutoCreatePools) { res = CreateTypePool(); } } return (Pool)res; } public ComponentPool GetComponentPool() where T : Component { if (!IsInitialized) Initialize(); IPool res = null; if (!Pools.TryGetValue(typeof(T).AssemblyQualifiedName, out res)) { if (AutoCreatePools) { res = CreateComponentPool(); } } return (ComponentPool)res; } public PrefabPool GetPrefabPool(string identifier, params GameObject[] prefabs) { if (!IsInitialized) Initialize(); IPool pool; if (!Pools.TryGetValue(identifier, out pool)) { if (AutoCreatePools) pool = CreatePrefabPool(identifier, null, prefabs); } return (PrefabPool)pool; } public Pool CreateTypePool(PoolSettings settings = null) { PoolSettings s = settings ?? new PoolSettings(DefaultSettings); IPool res = null; if (!TypePools.TryGetValue(typeof(T), out res)) { res = new Pool(s); TypePools.Add(typeof(T), res); } return (Pool)res; } public ComponentPool CreateComponentPool(PoolSettings settings = null) where T : Component { if (!IsInitialized) Initialize(); PoolSettings s = settings ?? new PoolSettings(DefaultSettings); IPool res = null; if (!Pools.TryGetValue(typeof(T).AssemblyQualifiedName, out res)) { res = gameObject.AddComponent(); ((ComponentPool)res).Initialize(typeof(T), s); Pools.Add(res.Identifier, res); } return (ComponentPool)res; } public PrefabPool CreatePrefabPool(string name, PoolSettings settings = null, params GameObject[] prefabs) { if (!IsInitialized) Initialize(); PoolSettings s = settings ?? new PoolSettings(DefaultSettings); IPool pool = null; if (!Pools.TryGetValue(name, out pool)) { PrefabPool p = gameObject.AddComponent(); p.Initialize(name, s, prefabs); Pools.Add(name, p); return p; } return (PrefabPool)pool; } public List FindPools(string identifierStartsWith) { List res = new List(); foreach (KeyValuePair kv in Pools) if (kv.Key.StartsWith(identifierStartsWith)) res.Add(kv.Value); return res; } public void DeletePools(string startsWith) { List toDelete = FindPools(startsWith); for (int i = toDelete.Count - 1; i >= 0; i--) DeletePool(toDelete[i]); } public void DeletePool(IPool pool) { if (pool is PrefabPool || pool is ComponentPool) { ((MonoBehaviour) pool).Destroy(false, false); Pools.Remove(pool.Identifier); } } public void DeletePool() { TypePools.Remove(typeof(T)); } } }