2020-08-28 13:38:13 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
namespace Coffee.UIExtensions
|
|
|
|
|
{
|
|
|
|
|
internal static class SpriteExtensions
|
|
|
|
|
{
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
private static Type tSpriteEditorExtension = Type.GetType("UnityEditor.Experimental.U2D.SpriteEditorExtension, UnityEditor")
|
|
|
|
|
?? Type.GetType("UnityEditor.U2D.SpriteEditorExtension, UnityEditor");
|
|
|
|
|
|
|
|
|
|
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-09-02 01:39:05 +08:00
|
|
|
|
internal static class LongExtensions
|
2020-08-28 13:38:13 +08:00
|
|
|
|
{
|
2020-09-02 01:39:05 +08:00
|
|
|
|
public static int BitCount(this long self)
|
2020-08-28 13:38:13 +08:00
|
|
|
|
{
|
2020-09-02 01:39:05 +08:00
|
|
|
|
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<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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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<Mesh> s_Pool = new Stack<Mesh>();
|
|
|
|
|
|
|
|
|
|
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<CombineInstance[]> s_Pool;
|
|
|
|
|
|
|
|
|
|
public static void Init()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static CombineInstanceArrayPool()
|
|
|
|
|
{
|
|
|
|
|
s_Pool = new List<CombineInstance[]>(32);
|
|
|
|
|
for (var i = 0; i < 32; i++)
|
|
|
|
|
{
|
|
|
|
|
s_Pool.Add(new CombineInstance[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static CombineInstance[] Get(List<CombineInstance> 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<CombineInstanceEx> 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;
|
2020-08-28 13:38:13 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static class ParticleSystemExtensions
|
|
|
|
|
{
|
|
|
|
|
public static void SortForRendering(this List<ParticleSystem> self, Transform transform)
|
|
|
|
|
{
|
|
|
|
|
self.Sort((a, b) =>
|
|
|
|
|
{
|
|
|
|
|
var tr = transform;
|
|
|
|
|
var ra = a.GetComponent<ParticleSystemRenderer>();
|
|
|
|
|
var rb = b.GetComponent<ParticleSystemRenderer>();
|
|
|
|
|
|
|
|
|
|
if (!Mathf.Approximately(ra.sortingFudge, rb.sortingFudge))
|
|
|
|
|
return ra.sortingFudge < rb.sortingFudge ? 1 : -1;
|
|
|
|
|
|
|
|
|
|
var pa = tr.InverseTransformPoint(a.transform.position).z;
|
|
|
|
|
var pb = tr.InverseTransformPoint(b.transform.position).z;
|
|
|
|
|
|
|
|
|
|
return Mathf.Approximately(pa, pb)
|
|
|
|
|
? 0
|
|
|
|
|
: pa < pb
|
|
|
|
|
? 1
|
|
|
|
|
: -1;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|