feat: un-limit on the number of mesh instances
parent
4be56669fb
commit
f1338813ca
|
@ -6,12 +6,13 @@ namespace Coffee.UIParticleExtensions
|
|||
{
|
||||
internal static class MeshHelper
|
||||
{
|
||||
public static long activeMeshIndices { get; private set; }
|
||||
public static List<bool> activeMeshIndices { get; private set; }
|
||||
private static readonly List<CombineInstanceEx> s_CachedInstance;
|
||||
private static int count;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
activeMeshIndices = new List<bool>();
|
||||
}
|
||||
|
||||
static MeshHelper()
|
||||
|
@ -64,13 +65,13 @@ namespace Coffee.UIParticleExtensions
|
|||
inst.Push(mesh, transform);
|
||||
Profiler.EndSample();
|
||||
|
||||
activeMeshIndices |= (long) 1 << inst.index;
|
||||
activeMeshIndices[inst.index] = true;
|
||||
}
|
||||
|
||||
public static void Clear()
|
||||
{
|
||||
count = 0;
|
||||
activeMeshIndices = 0;
|
||||
activeMeshIndices.Clear();
|
||||
foreach (var inst in s_CachedInstance)
|
||||
{
|
||||
inst.Clear();
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Coffee.UIParticleExtensions;
|
||||
using UnityEngine;
|
||||
|
@ -44,7 +43,7 @@ namespace Coffee.UIExtensions
|
|||
private Mesh _bakedMesh;
|
||||
private readonly List<Material> _modifiedMaterials = new List<Material>();
|
||||
private readonly List<Material> _maskMaterials = new List<Material>();
|
||||
private long _activeMeshIndices;
|
||||
private readonly List<bool> _activeMeshIndices = new List<bool>();
|
||||
private Vector3 _cachedPosition;
|
||||
private static readonly List<Material> s_TempMaterials = new List<Material>(2);
|
||||
private static MaterialPropertyBlock s_Mpb;
|
||||
|
@ -117,13 +116,14 @@ namespace Coffee.UIExtensions
|
|||
get { return _modifiedMaterials; }
|
||||
}
|
||||
|
||||
internal long activeMeshIndices
|
||||
public List<bool> activeMeshIndices
|
||||
{
|
||||
get { return _activeMeshIndices; }
|
||||
set
|
||||
{
|
||||
if (_activeMeshIndices == value) return;
|
||||
_activeMeshIndices = value;
|
||||
if (_activeMeshIndices.SequenceEqualFast(value)) return;
|
||||
_activeMeshIndices.Clear();
|
||||
_activeMeshIndices.AddRange(value);
|
||||
UpdateMaterial();
|
||||
}
|
||||
}
|
||||
|
@ -228,9 +228,9 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
|
||||
// No mesh to render.
|
||||
if (activeMeshIndices == 0 || !isActiveAndEnabled || particles.Count == 0)
|
||||
var count = activeMeshIndices.CountFast();
|
||||
if (count == 0 || !isActiveAndEnabled || particles.Count == 0)
|
||||
{
|
||||
_activeMeshIndices = 0;
|
||||
canvasRenderer.Clear();
|
||||
|
||||
foreach (var m in s_PrevMaskMaterials)
|
||||
|
@ -242,7 +242,7 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
|
||||
//
|
||||
var materialCount = Mathf.Max(8, activeMeshIndices.BitCount());
|
||||
var materialCount = Mathf.Max(8, count);
|
||||
canvasRenderer.materialCount = materialCount;
|
||||
var j = 0;
|
||||
for (var i = 0; i < particles.Count; i++)
|
||||
|
@ -255,8 +255,8 @@ namespace Coffee.UIExtensions
|
|||
r.GetSharedMaterials(s_TempMaterials);
|
||||
|
||||
// Main
|
||||
var bit = (long) 1 << (i * 2);
|
||||
if (0 < (activeMeshIndices & bit) && 0 < s_TempMaterials.Count)
|
||||
var index = i * 2;
|
||||
if (activeMeshIndices[index] && 0 < s_TempMaterials.Count)
|
||||
{
|
||||
var mat = GetModifiedMaterial(s_TempMaterials[0], ps.GetTextureForSprite());
|
||||
canvasRenderer.SetMaterial(mat, j);
|
||||
|
@ -265,9 +265,9 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
|
||||
// Trails
|
||||
index++;
|
||||
if (materialCount <= j) break;
|
||||
bit <<= 1;
|
||||
if (0 < (activeMeshIndices & bit) && 1 < s_TempMaterials.Count)
|
||||
if (activeMeshIndices[index] && 1 < s_TempMaterials.Count)
|
||||
{
|
||||
var mat = GetModifiedMaterial(s_TempMaterials[1], null);
|
||||
canvasRenderer.SetMaterial(mat, j++);
|
||||
|
@ -303,7 +303,8 @@ namespace Coffee.UIExtensions
|
|||
if (m_AnimatableProperties.Length == 0) return;
|
||||
|
||||
//
|
||||
var materialCount = Mathf.Max(8, activeMeshIndices.BitCount());
|
||||
var count = activeMeshIndices.CountFast();
|
||||
var materialCount = Mathf.Max(8, count);
|
||||
canvasRenderer.materialCount = materialCount;
|
||||
var j = 0;
|
||||
for (var i = 0; i < particles.Count; i++)
|
||||
|
@ -316,8 +317,7 @@ namespace Coffee.UIExtensions
|
|||
r.GetSharedMaterials(s_TempMaterials);
|
||||
|
||||
// Main
|
||||
var bit = (long) 1 << (i * 2);
|
||||
if (0 < (activeMeshIndices & bit) && 0 < s_TempMaterials.Count)
|
||||
if (activeMeshIndices[i * 2] && 0 < s_TempMaterials.Count)
|
||||
{
|
||||
UpdateMaterialProperties(r, j);
|
||||
j++;
|
||||
|
@ -350,7 +350,7 @@ namespace Coffee.UIExtensions
|
|||
protected override void OnEnable()
|
||||
{
|
||||
_cachedPosition = transform.localPosition;
|
||||
_activeMeshIndices = 0;
|
||||
activeMeshIndices.Clear();
|
||||
|
||||
UIParticleUpdater.Register(this);
|
||||
particles.Exec(p => p.GetComponent<ParticleSystemRenderer>().enabled = false);
|
||||
|
@ -418,7 +418,7 @@ namespace Coffee.UIExtensions
|
|||
return;
|
||||
}
|
||||
|
||||
if (!this || particles.Any(x => x)) return;
|
||||
if (!this || particles.AnyFast()) return;
|
||||
|
||||
// refresh.
|
||||
#if UNITY_EDITOR
|
||||
|
|
|
@ -129,8 +129,10 @@ namespace Coffee.UIExtensions
|
|||
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);
|
||||
|
@ -153,11 +155,17 @@ namespace Coffee.UIExtensions
|
|||
|
||||
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;
|
||||
|
||||
// Calc matrix.
|
||||
Profiler.BeginSample("[UIParticle] Bake Mesh > Calc matrix");
|
||||
var matrix = rootMatrix;
|
||||
if (currentPs.transform != root)
|
||||
{
|
||||
|
@ -177,6 +185,7 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
|
||||
matrix = scaleMatrix * matrix;
|
||||
Profiler.EndSample();
|
||||
|
||||
// Extra world simulation.
|
||||
if (currentPs.main.simulationSpace == ParticleSystemSimulationSpace.World && 0 < diff.sqrMagnitude)
|
||||
|
@ -245,7 +254,9 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
|
||||
// Set active indices.
|
||||
Profiler.BeginSample("[UIParticle] Bake Mesh > Set active indices");
|
||||
particle.activeMeshIndices = MeshHelper.activeMeshIndices;
|
||||
Profiler.EndSample();
|
||||
|
||||
// Combine
|
||||
Profiler.BeginSample("[UIParticle] Bake Mesh > CombineMesh");
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Coffee.UIParticleExtensions
|
||||
{
|
||||
|
@ -30,13 +31,38 @@ namespace Coffee.UIParticleExtensions
|
|||
#endif
|
||||
}
|
||||
|
||||
internal static class LongExtensions
|
||||
internal static class ListExtensions
|
||||
{
|
||||
public static int BitCount(this long self)
|
||||
public static bool SequenceEqualFast(this List<bool> self, List<bool> value)
|
||||
{
|
||||
self = self - ((self >> 1) & 0x5555555555555555L);
|
||||
self = (self & 0x3333333333333333L) + ((self >> 2) & 0x3333333333333333L);
|
||||
return (int) (unchecked(((self + (self >> 4)) & 0xF0F0F0F0F0F0F0FL) * 0x101010101010101L) >> 56);
|
||||
if (self.Count != value.Count) return false;
|
||||
for (var i = 0; i < self.Count; ++i)
|
||||
{
|
||||
if (self[i] != value[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int CountFast(this List<bool> self)
|
||||
{
|
||||
var count = 0;
|
||||
for (var i = 0; i < self.Count; ++i)
|
||||
{
|
||||
if (self[i]) count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public static bool AnyFast<T>(this List<T> self) where T : Object
|
||||
{
|
||||
for (var i = 0; i < self.Count; ++i)
|
||||
{
|
||||
if (self[i]) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,24 +133,28 @@ namespace Coffee.UIParticleExtensions
|
|||
|
||||
internal static class CombineInstanceArrayPool
|
||||
{
|
||||
private static readonly List<CombineInstance[]> s_Pool;
|
||||
private static readonly Dictionary<int, CombineInstance[]> s_Pool;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
s_Pool.Clear();
|
||||
}
|
||||
|
||||
static CombineInstanceArrayPool()
|
||||
{
|
||||
s_Pool = new List<CombineInstance[]>(32);
|
||||
for (var i = 0; i < 32; i++)
|
||||
{
|
||||
s_Pool.Add(new CombineInstance[i]);
|
||||
}
|
||||
s_Pool = new Dictionary<int, CombineInstance[]>();
|
||||
}
|
||||
|
||||
public static CombineInstance[] Get(List<CombineInstance> src)
|
||||
{
|
||||
var dst = s_Pool[src.Count];
|
||||
CombineInstance[] dst;
|
||||
var count = src.Count;
|
||||
if (!s_Pool.TryGetValue(count, out dst))
|
||||
{
|
||||
dst = new CombineInstance[count];
|
||||
s_Pool.Add(count, dst);
|
||||
}
|
||||
|
||||
for (var i = 0; i < src.Count; i++)
|
||||
{
|
||||
dst[i].mesh = src[i].mesh;
|
||||
|
@ -136,7 +166,13 @@ namespace Coffee.UIParticleExtensions
|
|||
|
||||
public static CombineInstance[] Get(List<CombineInstanceEx> src, int count)
|
||||
{
|
||||
var dst = s_Pool[count];
|
||||
CombineInstance[] dst;
|
||||
if (!s_Pool.TryGetValue(count, out dst))
|
||||
{
|
||||
dst = new CombineInstance[count];
|
||||
s_Pool.Add(count, dst);
|
||||
}
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
dst[i].mesh = src[i].mesh;
|
||||
|
|
Loading…
Reference in New Issue