| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 | 
							- using System;
 
- using System.Collections.Generic;
 
- using Coffee.UIParticleExtensions;
 
- using UnityEngine;
 
- using UnityEngine.Profiling;
 
- namespace Coffee.UIExtensions
 
- {
 
-     internal static class UIParticleUpdater
 
-     {
 
-         static readonly List<UIParticle> s_ActiveParticles = new List<UIParticle>();
 
-         static MaterialPropertyBlock s_Mpb;
 
-         static ParticleSystem.Particle[] s_Particles = new ParticleSystem.Particle[2048];
 
-         private static int frameCount = 0;
 
-         public static void Register(UIParticle particle)
 
-         {
 
-             if (!particle) return;
 
-             s_ActiveParticles.Add(particle);
 
-         }
 
-         public static void Unregister(UIParticle particle)
 
-         {
 
-             if (!particle) return;
 
-             s_ActiveParticles.Remove(particle);
 
-         }
 
- #if UNITY_EDITOR
 
-         [UnityEditor.InitializeOnLoadMethod]
 
- #endif
 
-         [RuntimeInitializeOnLoadMethod]
 
-         private static void InitializeOnLoad()
 
-         {
 
-             MeshHelper.Init();
 
-             MeshPool.Init();
 
-             CombineInstanceArrayPool.Init();
 
-             Canvas.willRenderCanvases -= Refresh;
 
-             Canvas.willRenderCanvases += Refresh;
 
-         }
 
-         private static void Refresh()
 
-         {
 
-             // Do not allow it to be called in the same frame.
 
-             if (frameCount == Time.frameCount) return;
 
-             frameCount = Time.frameCount;
 
-             Profiler.BeginSample("[UIParticle] Refresh");
 
-             for (var i = 0; i < s_ActiveParticles.Count; i++)
 
-             {
 
-                 try
 
-                 {
 
-                     Refresh(s_ActiveParticles[i]);
 
-                 }
 
-                 catch (Exception e)
 
-                 {
 
-                     Debug.LogException(e);
 
-                 }
 
-             }
 
-             Profiler.EndSample();
 
-         }
 
-         private static void Refresh(UIParticle particle)
 
-         {
 
-             if (!particle || !particle.bakedMesh || !particle.canvas || !particle.canvasRenderer) return;
 
-             Profiler.BeginSample("[UIParticle] Modify scale");
 
-             ModifyScale(particle);
 
-             Profiler.EndSample();
 
-             Profiler.BeginSample("[UIParticle] Bake mesh");
 
-             BakeMesh(particle);
 
-             Profiler.EndSample();
 
-             // if (QualitySettings.activeColorSpace == ColorSpace.Linear)
 
-             // {
 
-             //     Profiler.BeginSample("[UIParticle] Modify color space to linear");
 
-             //     particle.bakedMesh.ModifyColorSpaceToLinear();
 
-             //     Profiler.EndSample();
 
-             // }
 
-             Profiler.BeginSample("[UIParticle] Set mesh to CanvasRenderer");
 
-             particle.canvasRenderer.SetMesh(particle.bakedMesh);
 
-             Profiler.EndSample();
 
-             Profiler.BeginSample("[UIParticle] Update Animatable Material Properties");
 
-             particle.UpdateMaterialProperties();
 
-             Profiler.EndSample();
 
-         }
 
-         private static void ModifyScale(UIParticle particle)
 
-         {
 
-             if (!particle.ignoreCanvasScaler || !particle.canvas) return;
 
-             // Ignore Canvas scaling.
 
-             var s = particle.canvas.rootCanvas.transform.localScale;
 
-             var modifiedScale = new Vector3(
 
-                 Mathf.Approximately(s.x, 0) ? 1 : 1 / s.x,
 
-                 Mathf.Approximately(s.y, 0) ? 1 : 1 / s.y,
 
-                 Mathf.Approximately(s.z, 0) ? 1 : 1 / s.z);
 
-             // Scale is already modified.
 
-             var transform = particle.transform;
 
-             if (Mathf.Approximately((transform.localScale - modifiedScale).sqrMagnitude, 0)) return;
 
-             transform.localScale = modifiedScale;
 
-         }
 
-         private static Matrix4x4 GetScaledMatrix(ParticleSystem particle)
 
-         {
 
-             var transform = particle.transform;
 
-             var main = particle.main;
 
-             var space = main.simulationSpace;
 
-             if (space == ParticleSystemSimulationSpace.Custom && !main.customSimulationSpace)
 
-                 space = ParticleSystemSimulationSpace.Local;
 
-             switch (space)
 
-             {
 
-                 case ParticleSystemSimulationSpace.Local:
 
-                     return Matrix4x4.Rotate(transform.rotation).inverse
 
-                            * Matrix4x4.Scale(transform.lossyScale).inverse;
 
-                 case ParticleSystemSimulationSpace.World:
 
-                     return transform.worldToLocalMatrix;
 
-                 case ParticleSystemSimulationSpace.Custom:
 
-                     // #78: Support custom simulation space.
 
-                     return transform.worldToLocalMatrix
 
-                            * Matrix4x4.Translate(main.customSimulationSpace.position);
 
-                 default:
 
-                     return Matrix4x4.identity;
 
-             }
 
-         }
 
-         private static void BakeMesh(UIParticle particle)
 
-         {
 
-             // Clear mesh before bake.
 
-             Profiler.BeginSample("[UIParticle] Bake Mesh > Clear mesh before bake");
 
-             MeshHelper.Clear();
 
-             particle.bakedMesh.Clear(false);
 
-             Profiler.EndSample();
 
-             // Get camera for baking mesh.
 
-             var camera = BakingCamera.GetCamera(particle.canvas);
 
-             var root = particle.transform;
 
-             var rootMatrix = Matrix4x4.Rotate(root.rotation).inverse
 
-                              * Matrix4x4.Scale(root.lossyScale).inverse;
 
-             var scale = particle.ignoreCanvasScaler
 
-                 ? Vector3.Scale(particle.canvas.rootCanvas.transform.localScale, particle.scale3D)
 
-                 : particle.scale3D;
 
-             var scaleMatrix = Matrix4x4.Scale(scale);
 
-             // Cache position
 
-             var position = particle.transform.position;
 
-             var diff = position - particle.cachedPosition;
 
-             diff.x *= 1f - 1f / Mathf.Max(0.001f, scale.x);
 
-             diff.y *= 1f - 1f / Mathf.Max(0.001f, scale.y);
 
-             diff.z *= 1f - 1f / Mathf.Max(0.001f, scale.z);
 
-             particle.cachedPosition = position;
 
-             if (particle.activeMeshIndices.CountFast() == 0)
 
-                 diff = Vector3.zero;
 
-             for (var i = 0; i < particle.particles.Count; i++)
 
-             {
 
-                 Profiler.BeginSample("[UIParticle] Bake Mesh > Push index");
 
-                 MeshHelper.activeMeshIndices.Add(false);
 
-                 MeshHelper.activeMeshIndices.Add(false);
 
-                 Profiler.EndSample();
 
-                 // No particle to render.
 
-                 var currentPs = particle.particles[i];
 
-                 if (!currentPs || !currentPs.IsAlive() || currentPs.particleCount == 0) continue;
 
-                 var r = currentPs.GetComponent<ParticleSystemRenderer>();
 
-                 if (!r.sharedMaterial && !r.trailMaterial) continue;
 
-                 // Calc matrix.
 
-                 Profiler.BeginSample("[UIParticle] Bake Mesh > Calc matrix");
 
-                 var matrix = rootMatrix;
 
-                 if (currentPs.transform != root)
 
-                 {
 
-                     if (currentPs.main.simulationSpace == ParticleSystemSimulationSpace.Local)
 
-                     {
 
-                         var relativePos = root.InverseTransformPoint(currentPs.transform.position);
 
-                         matrix = Matrix4x4.Translate(relativePos) * matrix;
 
-                     }
 
-                     else
 
-                     {
 
-                         matrix = matrix * Matrix4x4.Translate(-root.position);
 
-                     }
 
-                 }
 
-                 else
 
-                 {
 
-                     matrix = GetScaledMatrix(currentPs);
 
-                 }
 
-                 matrix = scaleMatrix * matrix;
 
-                 Profiler.EndSample();
 
-                 // 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)
 
-                     {
 
-                         var size = Mathf.NextPowerOfTwo(count);
 
-                         s_Particles = new ParticleSystem.Particle[size];
 
-                     }
 
-                     currentPs.GetParticles(s_Particles);
 
-                     for (var j = 0; j < count; j++)
 
-                     {
 
-                         var p = s_Particles[j];
 
-                         p.position += diff;
 
-                         s_Particles[j] = p;
 
-                     }
 
-                     currentPs.SetParticles(s_Particles, count);
 
-                     Profiler.EndSample();
 
-                 }
 
- #if UNITY_2018_3_OR_NEWER
 
-                 // #102: Do not bake particle system to mesh when the alpha is zero.
 
-                 if (Mathf.Approximately(particle.canvasRenderer.GetInheritedAlpha(), 0))
 
-                     continue;
 
- #endif
 
-                 // Bake main particles.
 
-                 if (CanBakeMesh(r))
 
-                 {
 
-                     Profiler.BeginSample("[UIParticle] Bake Mesh > Bake Main Particles");
 
-                     var hash = currentPs.GetMaterialHash(false);
 
-                     if (hash != 0)
 
-                     {
 
-                         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)
 
-                 {
 
-                     Profiler.BeginSample("[UIParticle] Bake Mesh > Bake Trails Particles");
 
-                     var hash = currentPs.GetMaterialHash(true);
 
-                     if (hash != 0)
 
-                     {
 
-                         matrix = currentPs.main.simulationSpace == ParticleSystemSimulationSpace.Local && currentPs.trails.worldSpace
 
-                             ? matrix * Matrix4x4.Translate(-currentPs.transform.position)
 
-                             : matrix;
 
-                         var m = MeshHelper.GetTemporaryMesh();
 
-                         try
 
-                         {
 
-                             r.BakeTrailsMesh(m, camera, true);
 
-                             MeshHelper.Push(i * 2 + 1, hash, m, matrix);
 
-                         }
 
-                         catch
 
-                         {
 
-                             MeshHelper.DiscardTemporaryMesh(m);
 
-                         }
 
-                     }
 
-                     Profiler.EndSample();
 
-                 }
 
-             }
 
-             // Set active indices.
 
-             Profiler.BeginSample("[UIParticle] Bake Mesh > Set active indices");
 
-             particle.activeMeshIndices = MeshHelper.activeMeshIndices;
 
-             Profiler.EndSample();
 
-             // Combine
 
-             Profiler.BeginSample("[UIParticle] Bake Mesh > CombineMesh");
 
-             MeshHelper.CombineMesh(particle.bakedMesh);
 
-             MeshHelper.Clear();
 
-             Profiler.EndSample();
 
-         }
 
-         private static bool CanBakeMesh(ParticleSystemRenderer renderer)
 
-         {
 
-             // #69: Editor crashes when mesh is set to null when `ParticleSystem.RenderMode = Mesh`
 
-             if (renderer.renderMode == ParticleSystemRenderMode.Mesh && renderer.mesh == null) return false;
 
-             // #61: When `ParticleSystem.RenderMode = None`, an error occurs
 
-             if (renderer.renderMode == ParticleSystemRenderMode.None) return false;
 
-             return true;
 
-         }
 
-     }
 
- }
 
 
  |