diff --git a/Runtime/Internal/Extensions/ComponentExtensions.cs b/Runtime/Internal/Extensions/ComponentExtensions.cs index d65be22..f14fc1d 100644 --- a/Runtime/Internal/Extensions/ComponentExtensions.cs +++ b/Runtime/Internal/Extensions/ComponentExtensions.cs @@ -18,10 +18,10 @@ namespace Coffee.UIParticleInternal public static T[] GetComponentsInChildren(this Component self, int depth) where T : Component { - var results = ListPool.Rent(); + var results = InternalListPool.Rent(); self.GetComponentsInChildren_Internal(results, depth); var array = results.ToArray(); - ListPool.Return(ref results); + InternalListPool.Return(ref results); return array; } diff --git a/Runtime/Internal/Utilities/FastAction.cs b/Runtime/Internal/Utilities/FastAction.cs index 0428d6d..c5fbf50 100755 --- a/Runtime/Internal/Utilities/FastAction.cs +++ b/Runtime/Internal/Utilities/FastAction.cs @@ -10,8 +10,9 @@ namespace Coffee.UIParticleInternal /// internal class FastActionBase { - private static readonly ObjectPool> s_NodePool = - new ObjectPool>(() => new LinkedListNode(default), _ => true, x => x.Value = default); + private static readonly InternalObjectPool> s_NodePool = + new InternalObjectPool>(() => new LinkedListNode(default), _ => true, + x => x.Value = default); private readonly LinkedList _delegates = new LinkedList(); diff --git a/Runtime/Internal/Utilities/Misc.cs b/Runtime/Internal/Utilities/Misc.cs index fb1a210..26c03cf 100644 --- a/Runtime/Internal/Utilities/Misc.cs +++ b/Runtime/Internal/Utilities/Misc.cs @@ -1,6 +1,13 @@ +using System; using System.Diagnostics; using UnityEditor; using UnityEngine; +using Object = UnityEngine.Object; +#if UNITY_EDITOR && UNITY_2021_2_OR_NEWER +using UnityEditor.SceneManagement; +#elif UNITY_EDITOR +using UnityEditor.Experimental.SceneManagement; +#endif namespace Coffee.UIParticleInternal { @@ -53,5 +60,15 @@ namespace Coffee.UIParticleInternal EditorUtility.SetDirty(obj); #endif } + +#if UNITY_EDITOR + public static T[] GetAllComponentsInPrefabStage() where T : Component + { + var prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); + if (prefabStage == null) return Array.Empty(); + + return prefabStage.prefabContentsRoot.GetComponentsInChildren(true); + } +#endif } } diff --git a/Runtime/Internal/Utilities/ObjectPool.cs b/Runtime/Internal/Utilities/ObjectPool.cs index fa1c848..141cccf 100644 --- a/Runtime/Internal/Utilities/ObjectPool.cs +++ b/Runtime/Internal/Utilities/ObjectPool.cs @@ -6,15 +6,58 @@ namespace Coffee.UIParticleInternal /// /// Object pool. /// - internal class ObjectPool + internal class InternalObjectPool where T : class { +#if UNITY_2021_1_OR_NEWER + private readonly Predicate _onValid; // Delegate for checking if instances are valid + private readonly UnityEngine.Pool.ObjectPool _pool; + + public InternalObjectPool(Func onCreate, Predicate onValid, Action onReturn) + { + _pool = new UnityEngine.Pool.ObjectPool(onCreate, null, onReturn); + _onValid = onValid; + } + + /// + /// Rent an instance from the pool. + /// When you no longer need it, return it with . + /// + public T Rent() + { + while (0 < _pool.CountInactive) + { + var instance = _pool.Get(); + if (_onValid(instance)) + { + return instance; + } + } + + // If there are no instances in the pool, create a new one. + Logging.Log(this, $"A new instance is created (pooled: {_pool.CountInactive}, created: {_pool.CountAll})."); + return _pool.Get(); + } + + /// + /// Return an instance to the pool and assign null. + /// Be sure to return the instance obtained with with this method. + /// + public void Return(ref T instance) + { + if (instance == null) return; // Ignore if already pooled or null. + + _pool.Release(instance); + Logging.Log(this, $"An instance is released (pooled: {_pool.CountInactive}, created: {_pool.CountAll})."); + instance = default; // Set the reference to null. + } +#else private readonly Func _onCreate; // Delegate for creating instances private readonly Action _onReturn; // Delegate for returning instances to the pool private readonly Predicate _onValid; // Delegate for checking if instances are valid private readonly Stack _pool = new Stack(32); // Object pool private int _count; // Total count of created instances - public ObjectPool(Func onCreate, Predicate onValid, Action onReturn) + public InternalObjectPool(Func onCreate, Predicate onValid, Action onReturn) { _onCreate = onCreate; _onValid = onValid; @@ -54,15 +97,40 @@ namespace Coffee.UIParticleInternal Logging.Log(this, $"An instance is released (pooled: {_pool.Count}, created: {_count})."); instance = default; // Set the reference to null. } +#endif } /// /// Object pool for . /// - internal static class ListPool + internal static class InternalListPool { - private static readonly ObjectPool> s_ListPool = - new ObjectPool>(() => new List(), _ => true, x => x.Clear()); +#if UNITY_2021_1_OR_NEWER + /// + /// Rent an instance from the pool. + /// When you no longer need it, return it with . + /// + public static List Rent() + { + return UnityEngine.Pool.ListPool.Get(); + } + + /// + /// Return an instance to the pool and assign null. + /// Be sure to return the instance obtained with with this method. + /// + public static void Return(ref List toRelease) + { + if (toRelease != null) + { + UnityEngine.Pool.ListPool.Release(toRelease); + } + + toRelease = null; + } +#else + private static readonly InternalObjectPool> s_ListPool = + new InternalObjectPool>(() => new List(), _ => true, x => x.Clear()); /// /// Rent an instance from the pool. @@ -81,5 +149,6 @@ namespace Coffee.UIParticleInternal { s_ListPool.Return(ref toRelease); } +#endif } } diff --git a/Runtime/UIParticleRenderer.cs b/Runtime/UIParticleRenderer.cs index 3417e10..80936b8 100644 --- a/Runtime/UIParticleRenderer.cs +++ b/Runtime/UIParticleRenderer.cs @@ -421,7 +421,7 @@ namespace Coffee.UIExtensions workerMesh.LinearToGamma(); } - var components = ListPool.Rent(); + var components = InternalListPool.Rent(); GetComponents(typeof(IMeshModifier), components); for (var i = 0; i < components.Count; i++) { @@ -430,7 +430,7 @@ namespace Coffee.UIExtensions #pragma warning restore CS0618 // Type or member is obsolete } - ListPool.Return(ref components); + InternalListPool.Return(ref components); } Profiler.EndSample(); @@ -442,7 +442,7 @@ namespace Coffee.UIExtensions // Get grouped renderers. Profiler.BeginSample("[UIParticleRenderer] Set Mesh"); - var renderers = ListPool.Rent(); + var renderers = InternalListPool.Rent(); if (_parent.useMeshSharing) { UIParticleUpdater.GetGroupedRenderers(_parent.groupId, _index, renderers); @@ -459,7 +459,7 @@ namespace Coffee.UIExtensions r.canvasRenderer.SetMaterial(materialForRendering, 0); } - ListPool.Return(ref renderers); + InternalListPool.Return(ref renderers); if (_parent.canRender) {