diff --git a/Scripts/ModifiedMaterial.cs b/Scripts/ModifiedMaterial.cs new file mode 100644 index 0000000..0821082 --- /dev/null +++ b/Scripts/ModifiedMaterial.cs @@ -0,0 +1,74 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Coffee.UIParticleExtensions +{ + internal class ModifiedMaterial + { + private static readonly List s_Entries = new List(); + + public static Material Add(Material baseMat, Texture texture, int id) + { + MatEntry e; + for (var i = 0; i < s_Entries.Count; ++i) + { + e = s_Entries[i]; + if (e.baseMat != baseMat || e.texture != texture || e.id != id) continue; + ++e.count; + return e.customMat; + } + + e = new MatEntry(); + e.count = 1; + e.baseMat = baseMat; + e.texture = texture; + e.id = id; + e.customMat = new Material(baseMat); + e.customMat.hideFlags = HideFlags.HideAndDontSave; + if (texture) + e.customMat.mainTexture = texture; + s_Entries.Add(e); + // Debug.LogFormat(">>>> ModifiedMaterial.Add -> count = {0} {1} {2} {3}", s_Entries.Count, baseMat, texture, id); + return e.customMat; + } + + public static void Remove(Material customMat) + { + if (!customMat) return; + + for (var i = 0; i < s_Entries.Count; ++i) + { + var e = s_Entries[i]; + if (e.customMat != customMat) continue; + if (--e.count == 0) + { + // Debug.LogFormat(">>>> ModifiedMaterial.Add -> count = {0} {1} {2} {3}", s_Entries.Count - 1, e.customMat, e.texture, e.id); + DestroyImmediate(e.customMat); + e.baseMat = null; + e.texture = null; + s_Entries.RemoveAt(i); + } + + break; + } + } + + private static void DestroyImmediate(Object obj) + { + if (!obj) return; + if (Application.isEditor) + Object.DestroyImmediate(obj); + else + Object.Destroy(obj); + } + + private class MatEntry + { + public Material baseMat; + public Material customMat; + public int count; + public Texture texture; + public int id; + } + } +} diff --git a/Scripts/ModifiedMaterial.cs.meta b/Scripts/ModifiedMaterial.cs.meta new file mode 100644 index 0000000..83251d7 --- /dev/null +++ b/Scripts/ModifiedMaterial.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b0beae5bb1cb142b9ab90dc0d371f026 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/UIParticle.cs b/Scripts/UIParticle.cs index 778d14d..e78a67c 100755 --- a/Scripts/UIParticle.cs +++ b/Scripts/UIParticle.cs @@ -48,6 +48,8 @@ namespace Coffee.UIExtensions private Vector3 _cachedPosition; private static readonly List s_TempMaterials = new List(2); private static MaterialPropertyBlock s_Mpb; + private static readonly List s_PrevMaskMaterials = new List(); + private static readonly List s_PrevModifiedMaterials = new List(); /// @@ -210,21 +212,11 @@ namespace Coffee.UIExtensions protected override void UpdateMaterial() { // Clear mask materials. - for (var i = 0; i < _maskMaterials.Count; i++) - { - StencilMaterial.Remove(_maskMaterials[i]); - _maskMaterials[i] = null; - } - + s_PrevMaskMaterials.AddRange(_maskMaterials); _maskMaterials.Clear(); // Clear modified materials. - for (var i = 0; i < _modifiedMaterials.Count; i++) - { - DestroyImmediate(_modifiedMaterials[i]); - _modifiedMaterials[i] = null; - } - + s_PrevModifiedMaterials.AddRange(_modifiedMaterials); _modifiedMaterials.Clear(); // Recalculate stencil value. @@ -240,6 +232,12 @@ namespace Coffee.UIExtensions { _activeMeshIndices = 0; canvasRenderer.Clear(); + + foreach (var m in s_PrevMaskMaterials) + StencilMaterial.Remove(m); + + foreach (var m in s_PrevModifiedMaterials) + ModifiedMaterial.Remove(m); return; } @@ -275,6 +273,12 @@ namespace Coffee.UIExtensions canvasRenderer.SetMaterial(mat, j++); } } + + foreach (var m in s_PrevMaskMaterials) + StencilMaterial.Remove(m); + + foreach (var m in s_PrevModifiedMaterials) + ModifiedMaterial.Remove(m); } private Material GetModifiedMaterial(Material baseMaterial, Texture2D texture) @@ -287,10 +291,9 @@ namespace Coffee.UIExtensions if (texture == null && m_AnimatableProperties.Length == 0) return baseMaterial; - baseMaterial = new Material(baseMaterial); + var id = m_AnimatableProperties.Length == 0 ? 0 : GetInstanceID(); + baseMaterial = ModifiedMaterial.Add(baseMaterial, texture, id); _modifiedMaterials.Add(baseMaterial); - if (texture) - baseMaterial.mainTexture = texture; return baseMaterial; }