diff --git a/Packages/src/CHANGELOG.md b/Packages/src/CHANGELOG.md index 67c13ed..72a1c62 100644 --- a/Packages/src/CHANGELOG.md +++ b/Packages/src/CHANGELOG.md @@ -1,3 +1,10 @@ +## [4.10.5](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.4...v4.10.5) (2024-12-23) + + +### Bug Fixes + +* '3D' scale toggle in the inspector does not keep on reload ([934f4b8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/934f4b8f1c61f8ff20228d0ebcea9f636a3758ed)), closes [#346](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/346) + ## [4.10.4](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v4.10.3...v4.10.4) (2024-12-19) diff --git a/Packages/src/Editor/UIParticleEditor.cs b/Packages/src/Editor/UIParticleEditor.cs index 16085db..c58924f 100644 --- a/Packages/src/Editor/UIParticleEditor.cs +++ b/Packages/src/Editor/UIParticleEditor.cs @@ -28,6 +28,11 @@ namespace Coffee.UIExtensions [CanEditMultipleObjects] internal class UIParticleEditor : GraphicEditor { + internal class State : ScriptableSingleton + { + public bool is3DScaleMode; + } + //################################ // Constant or Static Members. //################################ @@ -46,7 +51,6 @@ internal class UIParticleEditor : GraphicEditor private static readonly GUIContent s_ContentPrimary = new GUIContent("Primary"); private static readonly Regex s_RegexBuiltInGuid = new Regex(@"^0{16}.0{15}$", RegexOptions.Compiled); private static readonly List s_TempMaterials = new List(); - private static bool s_XYZMode; private SerializedProperty _maskable; private SerializedProperty _scale3D; @@ -60,6 +64,7 @@ internal class UIParticleEditor : GraphicEditor private SerializedProperty _customViewSize; private ReorderableList _ro; private bool _showMax; + private bool _is3DScaleMode; private static readonly HashSet s_Shaders = new HashSet(); #if UNITY_2018 || UNITY_2019 @@ -163,6 +168,19 @@ protected override void OnEnable() uip.RefreshParticles(uip.particles); } } + + // Initialize 3D scale mode. + _is3DScaleMode = State.instance.is3DScaleMode; + if (!_is3DScaleMode) + { + var x = _scale3D.FindPropertyRelative("x"); + var y = _scale3D.FindPropertyRelative("y"); + var z = _scale3D.FindPropertyRelative("z"); + _is3DScaleMode = !Mathf.Approximately(x.floatValue, y.floatValue) || + !Mathf.Approximately(y.floatValue, z.floatValue) || + y.hasMultipleDifferentValues || + z.hasMultipleDifferentValues; + } } /// @@ -181,7 +199,11 @@ public override void OnInspectorGUI() // Scale EditorGUI.BeginDisabledGroup(!_meshSharing.hasMultipleDifferentValues && _meshSharing.intValue == 4); - s_XYZMode = DrawFloatOrVector3Field(_scale3D, s_XYZMode); + if (DrawFloatOrVector3Field(_scale3D, _is3DScaleMode) != _is3DScaleMode) + { + State.instance.is3DScaleMode = _is3DScaleMode = !_is3DScaleMode; + } + EditorGUI.EndDisabledGroup(); // AnimatableProperties diff --git a/Packages/src/Runtime/Internal/Extensions/ComponentExtensions.cs b/Packages/src/Runtime/Internal/Extensions/ComponentExtensions.cs index d65be22..f14fc1d 100644 --- a/Packages/src/Runtime/Internal/Extensions/ComponentExtensions.cs +++ b/Packages/src/Runtime/Internal/Extensions/ComponentExtensions.cs @@ -18,10 +18,10 @@ internal static class ComponentExtensions 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/Packages/src/Runtime/Internal/Utilities/FastAction.cs b/Packages/src/Runtime/Internal/Utilities/FastAction.cs index 0428d6d..c5fbf50 100755 --- a/Packages/src/Runtime/Internal/Utilities/FastAction.cs +++ b/Packages/src/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/Packages/src/Runtime/Internal/Utilities/Misc.cs b/Packages/src/Runtime/Internal/Utilities/Misc.cs index fb1a210..26c03cf 100644 --- a/Packages/src/Runtime/Internal/Utilities/Misc.cs +++ b/Packages/src/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 @@ public static void SetDirty(Object obj) 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/Packages/src/Runtime/Internal/Utilities/ObjectPool.cs b/Packages/src/Runtime/Internal/Utilities/ObjectPool.cs index fa1c848..141cccf 100644 --- a/Packages/src/Runtime/Internal/Utilities/ObjectPool.cs +++ b/Packages/src/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 @@ public void Return(ref T instance) 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 @@ public static void Return(ref List toRelease) { s_ListPool.Return(ref toRelease); } +#endif } } diff --git a/Packages/src/Runtime/UIParticleRenderer.cs b/Packages/src/Runtime/UIParticleRenderer.cs index 3417e10..80936b8 100644 --- a/Packages/src/Runtime/UIParticleRenderer.cs +++ b/Packages/src/Runtime/UIParticleRenderer.cs @@ -421,7 +421,7 @@ public void UpdateMesh(Camera bakeCamera) 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 @@ public void UpdateMesh(Camera bakeCamera) #pragma warning restore CS0618 // Type or member is obsolete } - ListPool.Return(ref components); + InternalListPool.Return(ref components); } Profiler.EndSample(); @@ -442,7 +442,7 @@ public void UpdateMesh(Camera bakeCamera) // 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 @@ public void UpdateMesh(Camera bakeCamera) r.canvasRenderer.SetMaterial(materialForRendering, 0); } - ListPool.Return(ref renderers); + InternalListPool.Return(ref renderers); if (_parent.canRender) { diff --git a/Packages/src/package.json b/Packages/src/package.json index ccf0aa2..d062142 100644 --- a/Packages/src/package.json +++ b/Packages/src/package.json @@ -2,7 +2,7 @@ "name": "com.coffee.ui-particle", "displayName": "UI Particle", "description": "This package provides a component to render particle effects for uGUI.\nThe particle rendering is maskable and sortable, without the need for an extra Camera, RenderTexture, or Canvas.", - "version": "4.10.4", + "version": "4.10.5", "unity": "2018.2", "license": "MIT", "repository": {