diff --git a/CHANGELOG.md b/CHANGELOG.md index df113c5..0db859b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [3.0.0-preview.28](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.27...v3.0.0-preview.28) (2020-09-01) + + +### Features + +* support AnimatableProperty for multiple materials ([062d988](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/062d9887fb8b096250ec3b43d9aa82637940a8bb)) + # [3.0.0-preview.27](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.26...v3.0.0-preview.27) (2020-09-01) diff --git a/Scripts/BakingCamera.cs b/Scripts/BakingCamera.cs index f0005bb..728f542 100644 --- a/Scripts/BakingCamera.cs +++ b/Scripts/BakingCamera.cs @@ -45,7 +45,7 @@ namespace Coffee.UIExtensions } private Camera _camera; - private int _refCount; + // private int _refCount; private static BakingCamera Create() { @@ -70,26 +70,6 @@ namespace Coffee.UIExtensions DontDestroyOnLoad(gameObject); } - public static void Register() - { - Instance._refCount++; - } - - public static void Unregister() - { - if (s_Instance == null) return; - - Instance._refCount--; - if (0 < Instance._refCount) return; - - if (Application.isPlaying) - Destroy(Instance.gameObject); - else - DestroyImmediate(Instance.gameObject); - - s_Instance = null; - } - public static Camera GetCamera(Canvas canvas) { if (!canvas) return Camera.main; diff --git a/Scripts/CombineInstanceEx.cs b/Scripts/CombineInstanceEx.cs new file mode 100644 index 0000000..9ff470a --- /dev/null +++ b/Scripts/CombineInstanceEx.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Coffee.UIExtensions +{ + internal class CombineInstanceEx + { + private int count; + public long hash = -1; + public int index = -1; + private readonly List combineInstances = new List(32); + public Mesh mesh; + public Matrix4x4 transform; + + public void Combine() + { + switch (count) + { + case 0: + return; + case 1: + mesh = combineInstances[0].mesh; + transform = combineInstances[0].transform; + return; + default: + { + var cis = CombineInstanceArrayPool.Get(combineInstances); + mesh = MeshPool.Rent(); + mesh.CombineMeshes(cis, true, true); + transform = Matrix4x4.identity; + cis.Clear(); + return; + } + } + } + + public void Clear() + { + for (var i = 0; i < combineInstances.Count; i++) + { + var inst = combineInstances[i]; + MeshPool.Return(inst.mesh); + inst.mesh = null; + combineInstances[i] = inst; + } + + combineInstances.Clear(); + + MeshPool.Return(mesh); + mesh = null; + + count = 0; + hash = -1; + index = -1; + } + + public void Push(Mesh mesh, Matrix4x4 transform) + { + combineInstances.Add(new CombineInstance {mesh = mesh, transform = transform}); + count++; + } + } +} diff --git a/Scripts/CombineInstanceEx.cs.meta b/Scripts/CombineInstanceEx.cs.meta new file mode 100644 index 0000000..629b238 --- /dev/null +++ b/Scripts/CombineInstanceEx.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0328b9fb8360e4f8e8a842f87d330466 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Editor/AnimatedPropertiesEditor.cs b/Scripts/Editor/AnimatedPropertiesEditor.cs index 6e2660d..6e598cd 100644 --- a/Scripts/Editor/AnimatedPropertiesEditor.cs +++ b/Scripts/Editor/AnimatedPropertiesEditor.cs @@ -1,3 +1,4 @@ +using System; using UnityEditor; using UnityEngine; using System.Collections.Generic; @@ -8,8 +9,9 @@ namespace Coffee.UIExtensions { internal class AnimatedPropertiesEditor { - static readonly List s_ActiveNames = new List(); - static readonly System.Text.StringBuilder s_Sb = new System.Text.StringBuilder(); + private static readonly List s_ActiveNames = new List(); + private static readonly System.Text.StringBuilder s_Sb = new System.Text.StringBuilder(); + private static readonly HashSet s_Names = new HashSet(); private string _name; private ShaderPropertyType _type; @@ -39,10 +41,8 @@ namespace Coffee.UIExtensions return s_Sb.ToString(); } - public static void DrawAnimatableProperties(SerializedProperty sp, Material mat) + public static void DrawAnimatableProperties(SerializedProperty sp, Material[] mats) { - if (!mat || !mat.shader) return; - bool isClicked; using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false))) { @@ -72,17 +72,27 @@ namespace Coffee.UIExtensions } } - for (var i = 0; i < ShaderUtil.GetPropertyCount(mat.shader); i++) + s_Names.Clear(); + foreach (var mat in mats) { - var pName = ShaderUtil.GetPropertyName(mat.shader, i); - var type = (ShaderPropertyType) ShaderUtil.GetPropertyType(mat.shader, i); - AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName, _type = type}, true); + if (!mat || !mat.shader) continue; - if (type != ShaderPropertyType.Texture) continue; + for (var i = 0; i < ShaderUtil.GetPropertyCount(mat.shader); i++) + { + var pName = ShaderUtil.GetPropertyName(mat.shader, i); + var type = (ShaderPropertyType) ShaderUtil.GetPropertyType(mat.shader, i); + var name = string.Format("{0} ({1})", pName, type); + if (s_Names.Contains(name)) continue; + s_Names.Add(name); - AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_ST", _type = ShaderPropertyType.Vector}, true); - AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_HDR", _type = ShaderPropertyType.Vector}, true); - AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_TexelSize", _type = ShaderPropertyType.Vector}, true); + AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName, _type = type}, true); + + if (type != ShaderPropertyType.Texture) continue; + + AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_ST", _type = ShaderPropertyType.Vector}, true); + AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_HDR", _type = ShaderPropertyType.Vector}, true); + AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_TexelSize", _type = ShaderPropertyType.Vector}, true); + } } gm.ShowAsContext(); diff --git a/Scripts/Editor/UIParticleEditor.cs b/Scripts/Editor/UIParticleEditor.cs index 921c351..5f41458 100644 --- a/Scripts/Editor/UIParticleEditor.cs +++ b/Scripts/Editor/UIParticleEditor.cs @@ -2,6 +2,7 @@ using UnityEditor; using UnityEditor.UI; using UnityEngine; using System.Collections.Generic; +using System.Linq; using UnityEditorInternal; using UnityEngine.UI; @@ -100,7 +101,12 @@ namespace Coffee.UIExtensions EditorGUILayout.PropertyField(_spScale); // AnimatableProperties - AnimatedPropertiesEditor.DrawAnimatableProperties(_spAnimatableProperties, current.material); + var mats = current.particles + .Where(x => x) + .Select(x => x.GetComponent().sharedMaterial) + .Where(x => x) + .ToArray(); + AnimatedPropertiesEditor.DrawAnimatableProperties(_spAnimatableProperties, mats); _ro.DoLayoutList(); @@ -125,19 +131,21 @@ namespace Coffee.UIExtensions // Does the shader support UI masks? - if (FixButton(current.m_IsTrail,"This UIParticle component should be removed. The UIParticle for trails is no longer needed.")) + if (FixButton(current.m_IsTrail, "This UIParticle component should be removed. The UIParticle for trails is no longer needed.")) { DestroyUIParticle(current); return; } + current.GetComponentsInParent(true, s_TempParents); - if (FixButton(1 < s_TempParents.Count,"This UIParticle component should be removed. The parent UIParticle exists.")) + if (FixButton(1 < s_TempParents.Count, "This UIParticle component should be removed. The parent UIParticle exists.")) { DestroyUIParticle(current); return; } + current.GetComponentsInChildren(true, s_TempChildren); - if (FixButton(1 < s_TempChildren.Count,"The children UIParticle component should be removed.")) + if (FixButton(1 < s_TempChildren.Count, "The children UIParticle component should be removed.")) { s_TempChildren.ForEach(child => DestroyUIParticle(child, true)); } diff --git a/Scripts/MeshHelper.cs b/Scripts/MeshHelper.cs index bf3a7e4..f18ce1b 100644 --- a/Scripts/MeshHelper.cs +++ b/Scripts/MeshHelper.cs @@ -1,104 +1,106 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using UnityEngine; +using UnityEngine.Profiling; namespace Coffee.UIExtensions { internal static class MeshHelper { - private static CombineInstance[] s_CombineInstances; - private static int s_TempIndex; - private static int s_CurrentIndex; - static readonly List s_Colors = new List(); - private static int s_RefCount; - private static Matrix4x4 s_Transform; - public static uint activeMeshIndices { get; private set; } + public static long activeMeshIndices { get; private set; } + private static readonly List s_CachedInstance; + private static int count; - public static void Register() + public static void Init() { - if (0 < s_RefCount++) return; - s_CombineInstances = new CombineInstance[8]; } - public static void Unregister() + static MeshHelper() { - s_RefCount--; - - if (0 < s_RefCount || s_CombineInstances == null) return; - - for (var i = 0; i < s_CombineInstances.Length; i++) + s_CachedInstance = new List(8); + for (var i = 0; i < 8; i++) { -#if UNITY_EDITOR - if (!Application.isPlaying) - Object.DestroyImmediate(s_CombineInstances[i].mesh); - else -#endif - { - Object.Destroy(s_CombineInstances[i].mesh); - } + s_CachedInstance.Add(new CombineInstanceEx()); + } + } + + private static CombineInstanceEx Get(int index, long hash) + { + if (0 < count && s_CachedInstance[count - 1].hash == hash) + return s_CachedInstance[count - 1]; + + if (s_CachedInstance.Count <= count) + { + var newInst = new CombineInstanceEx(); + s_CachedInstance.Add(newInst); } - s_CombineInstances = null; + var inst = s_CachedInstance[count]; + inst.hash = hash; + if (inst.index != -1) return inst; + + inst.index = index; + count++; + return inst; } - public static Mesh GetTemporaryMesh(int index) + public static Mesh GetTemporaryMesh() { - if (s_CombineInstances.Length <= s_TempIndex) s_TempIndex = s_CombineInstances.Length - 1; - s_CurrentIndex = index; - activeMeshIndices += (uint)(1 << s_CurrentIndex); - s_CombineInstances[s_TempIndex].transform = s_Transform; - return s_CombineInstances[s_TempIndex++].mesh; + return MeshPool.Rent(); } - public static void DiscardTemporaryMesh() + public static void Push(int index, long hash, Mesh mesh, Matrix4x4 transform) { - if (s_TempIndex == 0) return; - s_TempIndex--; - activeMeshIndices -= (uint)(1 << s_CurrentIndex); - } + if (mesh.vertexCount <= 0) + { + DiscardTemporaryMesh(mesh); + return; + } - public static void SetTransform(Matrix4x4 transform) - { - s_Transform = transform; + Profiler.BeginSample("[UIParticle] MeshHelper > Get CombineInstanceEx"); + var inst = Get(index, hash); + Profiler.EndSample(); + + Profiler.BeginSample("[UIParticle] MeshHelper > Push To Mesh Helper"); + inst.Push(mesh, transform); + Profiler.EndSample(); + + activeMeshIndices |= (long) 1 << inst.index; } public static void Clear() { - if (s_CombineInstances == null) return; - s_CurrentIndex = 0; + count = 0; activeMeshIndices = 0; - s_TempIndex = 0; - for (var i = 0; i < s_CombineInstances.Length; i++) + foreach (var inst in s_CachedInstance) { - if (!s_CombineInstances[i].mesh) - { - var mesh = new Mesh(); - mesh.MarkDynamic(); - s_CombineInstances[i].mesh = mesh; - } - else - { - s_CombineInstances[i].mesh.Clear(false); - } + inst.Clear(); } } public static void CombineMesh(Mesh result) { - if (!result || s_TempIndex == 0) return; + if (count == 0) return; + + for (var i = 0; i < count; i++) + { + Profiler.BeginSample("[UIParticle] MeshHelper > Combine Mesh Internal"); + s_CachedInstance[i].Combine(); + Profiler.EndSample(); + } + + Profiler.BeginSample("[UIParticle] MeshHelper > Combine Mesh"); + var cis = CombineInstanceArrayPool.Get(s_CachedInstance, count); + result.CombineMeshes(cis, false, true); + cis.Clear(); + Profiler.EndSample(); - result.CombineMeshes(s_CombineInstances, false, true); result.RecalculateBounds(); } - public static void ModifyColorSpaceToLinear(this Mesh self) + public static void DiscardTemporaryMesh(Mesh mesh) { - self.GetColors(s_Colors); - - for (var i = 0; i < s_Colors.Count; i++) - s_Colors[i] = ((Color) s_Colors[i]).gamma; - - self.SetColors(s_Colors); - s_Colors.Clear(); + MeshPool.Return(mesh); } } } diff --git a/Scripts/UIParticle.cs b/Scripts/UIParticle.cs index f0b51ff..9874ac1 100755 --- a/Scripts/UIParticle.cs +++ b/Scripts/UIParticle.cs @@ -39,7 +39,7 @@ namespace Coffee.UIExtensions private Mesh _bakedMesh; private readonly List _modifiedMaterials = new List(); private readonly List _maskMaterials = new List(); - private uint _activeMeshIndices; + private long _activeMeshIndices; private Vector3 _cachedPosition; private static readonly List s_TempMaterials = new List(2); private static MaterialPropertyBlock s_Mpb; @@ -91,7 +91,7 @@ namespace Coffee.UIExtensions get { return _modifiedMaterials; } } - internal uint activeMeshIndices + internal long activeMeshIndices { get { return _activeMeshIndices; } set @@ -190,7 +190,7 @@ namespace Coffee.UIExtensions r.GetSharedMaterials(s_TempMaterials); // Main - var bit = 1 << (i * 2); + var bit = (long) 1 << (i * 2); if (0 < (activeMeshIndices & bit) && 0 < s_TempMaterials.Count) { var mat = GetModifiedMaterial(s_TempMaterials[0], ps.GetTextureForSprite()); @@ -264,8 +264,7 @@ namespace Coffee.UIExtensions } // Create objects. - _bakedMesh = new Mesh(); - _bakedMesh.MarkDynamic(); + _bakedMesh = MeshPool.Rent(); base.OnEnable(); @@ -283,7 +282,7 @@ namespace Coffee.UIExtensions _tracker.Clear(); // Destroy object. - DestroyImmediate(_bakedMesh); + MeshPool.Return(_bakedMesh); _bakedMesh = null; base.OnDisable(); diff --git a/Scripts/UIParticleUpdater.cs b/Scripts/UIParticleUpdater.cs index 90142e4..29141eb 100755 --- a/Scripts/UIParticleUpdater.cs +++ b/Scripts/UIParticleUpdater.cs @@ -16,18 +16,12 @@ namespace Coffee.UIExtensions { if (!particle) return; s_ActiveParticles.Add(particle); - - MeshHelper.Register(); - BakingCamera.Register(); } public static void Unregister(UIParticle particle) { if (!particle) return; s_ActiveParticles.Remove(particle); - - MeshHelper.Unregister(); - BakingCamera.Unregister(); } #if UNITY_EDITOR @@ -36,6 +30,10 @@ namespace Coffee.UIExtensions [RuntimeInitializeOnLoadMethod] private static void InitializeOnLoad() { + MeshHelper.Init(); + MeshPool.Init(); + CombineInstanceArrayPool.Init(); + Canvas.willRenderCanvases -= Refresh; Canvas.willRenderCanvases += Refresh; } @@ -59,26 +57,26 @@ namespace Coffee.UIExtensions { if (!particle || !particle.canvas || !particle.canvasRenderer) return; - Profiler.BeginSample("Modify scale"); + Profiler.BeginSample("[UIParticle] Modify scale"); ModifyScale(particle); Profiler.EndSample(); - Profiler.BeginSample("Bake mesh"); + Profiler.BeginSample("[UIParticle] Bake mesh"); BakeMesh(particle); Profiler.EndSample(); if (QualitySettings.activeColorSpace == ColorSpace.Linear) { - Profiler.BeginSample("Modify color space to linear"); + Profiler.BeginSample("[UIParticle] Modify color space to linear"); particle.bakedMesh.ModifyColorSpaceToLinear(); Profiler.EndSample(); } - Profiler.BeginSample("Set mesh to CanvasRenderer"); + Profiler.BeginSample("[UIParticle] Set mesh to CanvasRenderer"); particle.canvasRenderer.SetMesh(particle.bakedMesh); Profiler.EndSample(); - Profiler.BeginSample("Update Animatable Material Properties"); + Profiler.BeginSample("[UIParticle] Update Animatable Material Properties"); // UpdateAnimatableMaterialProperties(particle); Profiler.EndSample(); } @@ -170,12 +168,12 @@ namespace Coffee.UIExtensions matrix = GetScaledMatrix(currentPs); } - // Set transform - MeshHelper.SetTransform(scaleMatrix * matrix); + matrix = scaleMatrix * matrix; // Extra world simulation. if (currentPs.main.simulationSpace == ParticleSystemSimulationSpace.World && 0 < diff.sqrMagnitude) { + Profiler.BeginSample("[UIParticle] Bake Mesh > Extra world simulation"); var count = currentPs.particleCount; if (s_Particles.Length < count) { @@ -192,48 +190,55 @@ namespace Coffee.UIExtensions } currentPs.SetParticles(s_Particles, count); + Profiler.EndSample(); } // Bake main particles. var r = currentPs.GetComponent(); if (CanBakeMesh(r)) { - var m = MeshHelper.GetTemporaryMesh(i * 2); - r.BakeMesh(m, camera, true); - - if (m.vertexCount == 0) - MeshHelper.DiscardTemporaryMesh(); - else + Profiler.BeginSample("[UIParticle] Bake Mesh > Bake Main Particles"); + var hash = currentPs.GetMaterialHash(false); + if (hash != 0) { - var index = MeshHelper.activeMeshIndices.BitCount() - 1; - particle.UpdateMaterialProperties(r, index); + var m = MeshHelper.GetTemporaryMesh(); + r.BakeMesh(m, camera, true); + MeshHelper.Push(i * 2, hash, m, matrix); } + + Profiler.EndSample(); } // Bake trails particles. if (currentPs.trails.enabled) { - var m = MeshHelper.GetTemporaryMesh(i * 2 + 1); - try + Profiler.BeginSample("[UIParticle] Bake Mesh > Bake Trails Particles"); + var hash = currentPs.GetMaterialHash(true); + if (hash != 0) { - r.BakeTrailsMesh(m, camera, true); + var m = MeshHelper.GetTemporaryMesh(); + try + { + r.BakeTrailsMesh(m, camera, true); + MeshHelper.Push(i * 2 + 1, hash, m, matrix); + } + catch + { + MeshHelper.DiscardTemporaryMesh(m); + } + } - if (m.vertexCount == 0) - MeshHelper.DiscardTemporaryMesh(); - } - catch - { - MeshHelper.DiscardTemporaryMesh(); - } + Profiler.EndSample(); } } - // Set active indices. particle.activeMeshIndices = MeshHelper.activeMeshIndices; // Combine + Profiler.BeginSample("[UIParticle] Bake Mesh > CombineMesh"); MeshHelper.CombineMesh(particle.bakedMesh); + Profiler.EndSample(); } private static bool CanBakeMesh(ParticleSystemRenderer renderer) @@ -246,31 +251,5 @@ namespace Coffee.UIExtensions return true; } - - /// - /// Copy the value from MaterialPropertyBlock to CanvasRenderer - /// - private static void UpdateAnimatableMaterialProperties(UIParticle particle, ParticleSystemRenderer renderer) - { -#if UNITY_EDITOR - if (!Application.isPlaying) return; -#endif - if (0 == particle.m_AnimatableProperties.Length) return; - if (0 == particle.canvasRenderer.materialCount) return; - - var mat = particle.canvasRenderer.GetMaterial(0); - if (!mat) return; - - // #41: Copy the value from MaterialPropertyBlock to CanvasRenderer - if (s_Mpb == null) - s_Mpb = new MaterialPropertyBlock(); - renderer.GetPropertyBlock(s_Mpb); - foreach (var ap in particle.m_AnimatableProperties) - { - ap.UpdateMaterialProperties(mat, s_Mpb); - } - - s_Mpb.Clear(); - } } } diff --git a/Scripts/Utils.cs b/Scripts/Utils.cs index 6713544..dcb46b7 100644 --- a/Scripts/Utils.cs +++ b/Scripts/Utils.cs @@ -30,15 +30,120 @@ namespace Coffee.UIExtensions #endif } - internal static class UintExtensions + internal static class LongExtensions { - public static int BitCount(this uint self) + public static int BitCount(this long self) { - self = (self & 0x55555555) + ((self >> 1) & 0x55555555); - self = (self & 0x33333333) + ((self >> 2) & 0x33333333); - self = (self & 0x0F0F0F0F) + ((self >> 4) & 0x0F0F0F0F); - self = (self & 0x00FF00FF) + ((self >> 8) & 0x00FF00FF); - return (int) ((self & 0x0000ffff) + (self >> 16)); + self = self - ((self >> 1) & 0x5555555555555555L); + self = (self & 0x3333333333333333L) + ((self >> 2) & 0x3333333333333333L); + return (int) (unchecked(((self + (self >> 4)) & 0xF0F0F0F0F0F0F0FL) * 0x101010101010101L) >> 56); + } + } + + internal static class MeshExtensions + { + static readonly List s_Colors = new List(); + + public static void ModifyColorSpaceToLinear(this Mesh self) + { + self.GetColors(s_Colors); + + for (var i = 0; i < s_Colors.Count; i++) + s_Colors[i] = ((Color) s_Colors[i]).gamma; + + self.SetColors(s_Colors); + s_Colors.Clear(); + } + + public static void Clear(this CombineInstance[] self) + { + for (var i = 0; i < self.Length; i++) + { + MeshPool.Return(self[i].mesh); + self[i].mesh = null; + } + } + } + + internal static class MeshPool + { + private static readonly Stack s_Pool = new Stack(); + + public static void Init() + { + } + + static MeshPool() + { + for (var i = 0; i < 32; i++) + { + var m = new Mesh(); + m.MarkDynamic(); + s_Pool.Push(m); + } + } + + public static Mesh Rent() + { + Mesh m; + while (0 < s_Pool.Count) + { + m = s_Pool.Pop(); + if (m) return m; + } + + m = new Mesh(); + m.MarkDynamic(); + return m; + } + + public static void Return(Mesh mesh) + { + if (!mesh || s_Pool.Contains(mesh)) return; + mesh.Clear(false); + s_Pool.Push(mesh); + } + } + + internal static class CombineInstanceArrayPool + { + private static readonly List s_Pool; + + public static void Init() + { + } + + static CombineInstanceArrayPool() + { + s_Pool = new List(32); + for (var i = 0; i < 32; i++) + { + s_Pool.Add(new CombineInstance[i]); + } + } + + public static CombineInstance[] Get(List src) + { + var dst = s_Pool[src.Count]; + for (var i = 0; i < src.Count; i++) + { + dst[i].mesh = src[i].mesh; + dst[i].transform = src[i].transform; + } + + return dst; + } + + public static CombineInstance[] Get(List src, int count) + { + var dst = s_Pool[count]; + for (var i = 0; i < count; i++) + { + dst[i].mesh = src[i].mesh; + dst[i].transform = src[i].transform; + } + + return dst; } } @@ -66,6 +171,19 @@ namespace Coffee.UIExtensions }); } + public static long GetMaterialHash(this ParticleSystem self, bool trail) + { + if (!self) return 0; + + var r = self.GetComponent(); + var mat = trail ? r.trailMaterial : r.sharedMaterial; + + if (!mat) return 0; + + var tex = self.GetTextureForSprite(); + return ((long) mat.GetHashCode() << 32) + (tex ? tex.GetHashCode() : 0); + } + public static Texture2D GetTextureForSprite(this ParticleSystem self) { if (!self) return null; @@ -91,5 +209,4 @@ namespace Coffee.UIExtensions self.ForEach(action); } } - } diff --git a/package.json b/package.json index 7f7b2ad..e4436e5 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "com.coffee.ui-particle", "displayName": "UI Particle", "description": "This plugin provide a component to render particle effect for uGUI.\nThe particle rendering is maskable and sortable, without Camera, RenderTexture or Canvas.", - "version": "3.0.0-preview.27", + "version": "3.0.0-preview.28", "unity": "2018.2", "license": "MIT", "repository": {