2020-08-28 13:38:13 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using UnityEngine;
|
2020-10-27 23:39:22 +08:00
|
|
|
|
using Object = UnityEngine.Object;
|
2020-08-28 13:38:13 +08:00
|
|
|
|
|
2020-09-28 20:35:40 +08:00
|
|
|
|
namespace Coffee.UIParticleExtensions
|
2020-08-28 13:38:13 +08:00
|
|
|
|
{
|
|
|
|
|
internal static class SpriteExtensions
|
|
|
|
|
{
|
|
|
|
|
#if UNITY_EDITOR
|
2020-12-04 17:00:22 +08:00
|
|
|
|
private static Type tSpriteEditorExtension =
|
|
|
|
|
Type.GetType("UnityEditor.Experimental.U2D.SpriteEditorExtension, UnityEditor")
|
|
|
|
|
?? Type.GetType("UnityEditor.U2D.SpriteEditorExtension, UnityEditor");
|
2020-08-28 13:38:13 +08:00
|
|
|
|
|
|
|
|
|
private static MethodInfo miGetActiveAtlasTexture = tSpriteEditorExtension
|
|
|
|
|
.GetMethod("GetActiveAtlasTexture", BindingFlags.Static | BindingFlags.NonPublic);
|
|
|
|
|
|
|
|
|
|
public static Texture2D GetActualTexture(this Sprite self)
|
|
|
|
|
{
|
|
|
|
|
if (!self) return null;
|
|
|
|
|
|
|
|
|
|
if (Application.isPlaying) return self.texture;
|
|
|
|
|
var ret = miGetActiveAtlasTexture.Invoke(null, new[] {self}) as Texture2D;
|
|
|
|
|
return ret ? ret : self.texture;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
internal static Texture2D GetActualTexture(this Sprite self)
|
|
|
|
|
{
|
|
|
|
|
return self ? self.texture : null;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-27 23:39:22 +08:00
|
|
|
|
internal static class ListExtensions
|
2020-08-28 13:38:13 +08:00
|
|
|
|
{
|
2020-10-27 23:39:22 +08:00
|
|
|
|
public static bool SequenceEqualFast(this List<bool> self, List<bool> value)
|
2020-08-28 13:38:13 +08:00
|
|
|
|
{
|
2020-10-27 23:39:22 +08:00
|
|
|
|
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;
|
2020-09-02 01:39:05 +08:00
|
|
|
|
}
|
2021-02-18 00:55:53 +08:00
|
|
|
|
|
|
|
|
|
public static bool AnyFast<T>(this List<T> self, Predicate<T> predicate) where T : Object
|
|
|
|
|
{
|
|
|
|
|
for (var i = 0; i < self.Count; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (self[i] && predicate(self[i])) return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-09-02 01:39:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static class MeshExtensions
|
|
|
|
|
{
|
2021-06-09 00:32:28 +08:00
|
|
|
|
// static readonly List<Color32> s_Colors = new List<Color32>();
|
|
|
|
|
|
|
|
|
|
// 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();
|
|
|
|
|
// }
|
2020-09-02 01:39:05 +08:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
{
|
2021-06-09 00:31:39 +08:00
|
|
|
|
private static readonly Stack<Mesh> s_Pool = new Stack<Mesh>(32);
|
|
|
|
|
private static readonly HashSet<int> s_HashPool = new HashSet<int>();
|
2020-09-02 01:39:05 +08:00
|
|
|
|
|
|
|
|
|
public static void Init()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static MeshPool()
|
|
|
|
|
{
|
|
|
|
|
for (var i = 0; i < 32; i++)
|
|
|
|
|
{
|
|
|
|
|
var m = new Mesh();
|
|
|
|
|
m.MarkDynamic();
|
|
|
|
|
s_Pool.Push(m);
|
2021-06-09 00:31:39 +08:00
|
|
|
|
s_HashPool.Add(m.GetInstanceID());
|
2020-09-02 01:39:05 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Mesh Rent()
|
|
|
|
|
{
|
|
|
|
|
Mesh m;
|
|
|
|
|
while (0 < s_Pool.Count)
|
|
|
|
|
{
|
|
|
|
|
m = s_Pool.Pop();
|
2021-06-09 00:31:39 +08:00
|
|
|
|
if (m)
|
|
|
|
|
{
|
|
|
|
|
s_HashPool.Remove(m.GetInstanceID());
|
|
|
|
|
return m;
|
|
|
|
|
}
|
2020-09-02 01:39:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m = new Mesh();
|
|
|
|
|
m.MarkDynamic();
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Return(Mesh mesh)
|
|
|
|
|
{
|
2021-06-09 00:31:39 +08:00
|
|
|
|
if (!mesh) return;
|
|
|
|
|
|
|
|
|
|
var id = mesh.GetInstanceID();
|
|
|
|
|
if (s_HashPool.Contains(id)) return;
|
|
|
|
|
|
2020-09-02 01:39:05 +08:00
|
|
|
|
mesh.Clear(false);
|
|
|
|
|
s_Pool.Push(mesh);
|
2021-06-09 00:31:39 +08:00
|
|
|
|
s_HashPool.Add(id);
|
2020-09-02 01:39:05 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static class CombineInstanceArrayPool
|
|
|
|
|
{
|
2020-10-27 23:39:22 +08:00
|
|
|
|
private static readonly Dictionary<int, CombineInstance[]> s_Pool;
|
2020-09-02 01:39:05 +08:00
|
|
|
|
|
|
|
|
|
public static void Init()
|
|
|
|
|
{
|
2020-10-27 23:39:22 +08:00
|
|
|
|
s_Pool.Clear();
|
2020-09-02 01:39:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static CombineInstanceArrayPool()
|
|
|
|
|
{
|
2020-10-27 23:39:22 +08:00
|
|
|
|
s_Pool = new Dictionary<int, CombineInstance[]>();
|
2020-09-02 01:39:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static CombineInstance[] Get(List<CombineInstance> src)
|
|
|
|
|
{
|
2020-10-27 23:39:22 +08:00
|
|
|
|
CombineInstance[] dst;
|
|
|
|
|
var count = src.Count;
|
|
|
|
|
if (!s_Pool.TryGetValue(count, out dst))
|
|
|
|
|
{
|
|
|
|
|
dst = new CombineInstance[count];
|
|
|
|
|
s_Pool.Add(count, dst);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-02 01:39:05 +08:00
|
|
|
|
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<CombineInstanceEx> src, int count)
|
|
|
|
|
{
|
2020-10-27 23:39:22 +08:00
|
|
|
|
CombineInstance[] dst;
|
|
|
|
|
if (!s_Pool.TryGetValue(count, out dst))
|
|
|
|
|
{
|
|
|
|
|
dst = new CombineInstance[count];
|
|
|
|
|
s_Pool.Add(count, dst);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-02 01:39:05 +08:00
|
|
|
|
for (var i = 0; i < count; i++)
|
|
|
|
|
{
|
|
|
|
|
dst[i].mesh = src[i].mesh;
|
|
|
|
|
dst[i].transform = src[i].transform;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dst;
|
2020-08-28 13:38:13 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static class ParticleSystemExtensions
|
|
|
|
|
{
|
2020-11-20 12:11:08 +08:00
|
|
|
|
public static void SortForRendering(this List<ParticleSystem> self, Transform transform, bool sortByMaterial)
|
2020-08-28 13:38:13 +08:00
|
|
|
|
{
|
|
|
|
|
self.Sort((a, b) =>
|
|
|
|
|
{
|
|
|
|
|
var tr = transform;
|
2020-10-28 11:21:34 +08:00
|
|
|
|
var aRenderer = a.GetComponent<ParticleSystemRenderer>();
|
|
|
|
|
var bRenderer = b.GetComponent<ParticleSystemRenderer>();
|
|
|
|
|
|
|
|
|
|
// Render queue: ascending
|
2020-11-20 09:44:17 +08:00
|
|
|
|
var aMat = aRenderer.sharedMaterial ?? aRenderer.trailMaterial;
|
|
|
|
|
var bMat = bRenderer.sharedMaterial ?? bRenderer.trailMaterial;
|
|
|
|
|
if (!aMat && !bMat) return 0;
|
|
|
|
|
if (!aMat) return -1;
|
|
|
|
|
if (!bMat) return 1;
|
|
|
|
|
|
2020-11-20 12:11:08 +08:00
|
|
|
|
if (sortByMaterial)
|
|
|
|
|
return aMat.GetInstanceID() - bMat.GetInstanceID();
|
|
|
|
|
|
2020-10-28 11:21:34 +08:00
|
|
|
|
if (aMat.renderQueue != bMat.renderQueue)
|
|
|
|
|
return aMat.renderQueue - bMat.renderQueue;
|
|
|
|
|
|
|
|
|
|
// Sorting layer: ascending
|
|
|
|
|
if (aRenderer.sortingLayerID != bRenderer.sortingLayerID)
|
|
|
|
|
return aRenderer.sortingLayerID - bRenderer.sortingLayerID;
|
|
|
|
|
|
|
|
|
|
// Sorting order: ascending
|
|
|
|
|
if (aRenderer.sortingOrder != bRenderer.sortingOrder)
|
|
|
|
|
return aRenderer.sortingOrder - bRenderer.sortingOrder;
|
|
|
|
|
|
|
|
|
|
// Z position & sortingFudge: descending
|
|
|
|
|
var aTransform = a.transform;
|
|
|
|
|
var bTransform = b.transform;
|
2020-11-16 02:07:35 +08:00
|
|
|
|
var aPos = tr.InverseTransformPoint(aTransform.position).z + aRenderer.sortingFudge;
|
|
|
|
|
var bPos = tr.InverseTransformPoint(bTransform.position).z + bRenderer.sortingFudge;
|
2020-10-28 11:21:34 +08:00
|
|
|
|
if (!Mathf.Approximately(aPos, bPos))
|
2020-11-16 02:07:35 +08:00
|
|
|
|
return (int) Mathf.Sign(bPos - aPos);
|
2020-10-28 11:21:34 +08:00
|
|
|
|
|
2020-12-04 17:00:22 +08:00
|
|
|
|
return (int) Mathf.Sign(GetIndex(self, a) - GetIndex(self, b));
|
2020-10-28 11:21:34 +08:00
|
|
|
|
});
|
|
|
|
|
}
|
2020-10-28 01:08:31 +08:00
|
|
|
|
|
2021-01-06 16:43:14 +08:00
|
|
|
|
private static int GetIndex(IList<ParticleSystem> list, Object ps)
|
2020-10-28 11:21:34 +08:00
|
|
|
|
{
|
2020-12-04 17:00:22 +08:00
|
|
|
|
for (var i = 0; i < list.Count; i++)
|
2020-10-28 11:21:34 +08:00
|
|
|
|
{
|
2020-12-04 17:00:22 +08:00
|
|
|
|
if (list[i].GetInstanceID() == ps.GetInstanceID()) return i;
|
2020-10-28 11:21:34 +08:00
|
|
|
|
}
|
2020-12-04 17:00:22 +08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2020-08-28 13:38:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-02 01:39:05 +08:00
|
|
|
|
public static long GetMaterialHash(this ParticleSystem self, bool trail)
|
|
|
|
|
{
|
|
|
|
|
if (!self) return 0;
|
|
|
|
|
|
|
|
|
|
var r = self.GetComponent<ParticleSystemRenderer>();
|
|
|
|
|
var mat = trail ? r.trailMaterial : r.sharedMaterial;
|
|
|
|
|
|
|
|
|
|
if (!mat) return 0;
|
|
|
|
|
|
2020-09-03 00:02:59 +08:00
|
|
|
|
var tex = trail ? null : self.GetTextureForSprite();
|
2020-09-02 01:39:05 +08:00
|
|
|
|
return ((long) mat.GetHashCode() << 32) + (tex ? tex.GetHashCode() : 0);
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-28 13:38:13 +08:00
|
|
|
|
public static Texture2D GetTextureForSprite(this ParticleSystem self)
|
|
|
|
|
{
|
|
|
|
|
if (!self) return null;
|
|
|
|
|
|
|
|
|
|
// Get sprite's texture.
|
|
|
|
|
var tsaModule = self.textureSheetAnimation;
|
|
|
|
|
if (!tsaModule.enabled || tsaModule.mode != ParticleSystemAnimationMode.Sprites) return null;
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < tsaModule.spriteCount; i++)
|
|
|
|
|
{
|
|
|
|
|
var sprite = tsaModule.GetSprite(i);
|
|
|
|
|
if (!sprite) continue;
|
|
|
|
|
|
|
|
|
|
return sprite.GetActualTexture();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Exec(this List<ParticleSystem> self, Action<ParticleSystem> action)
|
|
|
|
|
{
|
|
|
|
|
self.RemoveAll(p => !p);
|
|
|
|
|
self.ForEach(action);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-01-06 16:43:14 +08:00
|
|
|
|
}
|