Utils.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using UnityEngine;
  5. using Object = UnityEngine.Object;
  6. namespace Coffee.UIParticleExtensions
  7. {
  8. internal static class SpriteExtensions
  9. {
  10. #if UNITY_EDITOR
  11. private static Type tSpriteEditorExtension =
  12. Type.GetType("UnityEditor.Experimental.U2D.SpriteEditorExtension, UnityEditor")
  13. ?? Type.GetType("UnityEditor.U2D.SpriteEditorExtension, UnityEditor");
  14. private static MethodInfo miGetActiveAtlasTexture = tSpriteEditorExtension
  15. .GetMethod("GetActiveAtlasTexture", BindingFlags.Static | BindingFlags.NonPublic);
  16. public static Texture2D GetActualTexture(this Sprite self)
  17. {
  18. if (!self) return null;
  19. if (Application.isPlaying) return self.texture;
  20. var ret = miGetActiveAtlasTexture.Invoke(null, new[] { self }) as Texture2D;
  21. return ret ? ret : self.texture;
  22. }
  23. #else
  24. internal static Texture2D GetActualTexture(this Sprite self)
  25. {
  26. return self ? self.texture : null;
  27. }
  28. #endif
  29. }
  30. internal static class ListExtensions
  31. {
  32. public static bool SequenceEqualFast(this List<bool> self, List<bool> value)
  33. {
  34. if (self.Count != value.Count) return false;
  35. for (var i = 0; i < self.Count; ++i)
  36. {
  37. if (self[i] != value[i]) return false;
  38. }
  39. return true;
  40. }
  41. public static int CountFast(this List<bool> self)
  42. {
  43. var count = 0;
  44. for (var i = 0; i < self.Count; ++i)
  45. {
  46. if (self[i]) count++;
  47. }
  48. return count;
  49. }
  50. public static bool AnyFast<T>(this List<T> self) where T : Object
  51. {
  52. for (var i = 0; i < self.Count; ++i)
  53. {
  54. if (self[i]) return true;
  55. }
  56. return false;
  57. }
  58. public static bool AnyFast<T>(this List<T> self, Predicate<T> predicate) where T : Object
  59. {
  60. for (var i = 0; i < self.Count; ++i)
  61. {
  62. if (self[i] && predicate(self[i])) return true;
  63. }
  64. return false;
  65. }
  66. }
  67. internal static class MeshExtensions
  68. {
  69. public static void Clear(this CombineInstance[] self)
  70. {
  71. for (var i = 0; i < self.Length; i++)
  72. {
  73. MeshPool.Return(self[i].mesh);
  74. self[i].mesh = null;
  75. }
  76. }
  77. }
  78. internal static class MeshPool
  79. {
  80. private static readonly Stack<Mesh> s_Pool = new Stack<Mesh>(32);
  81. private static readonly HashSet<int> s_HashPool = new HashSet<int>();
  82. public static void Init()
  83. {
  84. }
  85. static MeshPool()
  86. {
  87. for (var i = 0; i < 32; i++)
  88. {
  89. var m = new Mesh();
  90. m.MarkDynamic();
  91. s_Pool.Push(m);
  92. s_HashPool.Add(m.GetInstanceID());
  93. }
  94. }
  95. public static Mesh Rent()
  96. {
  97. Mesh m;
  98. while (0 < s_Pool.Count)
  99. {
  100. m = s_Pool.Pop();
  101. if (m)
  102. {
  103. s_HashPool.Remove(m.GetInstanceID());
  104. return m;
  105. }
  106. }
  107. m = new Mesh();
  108. m.MarkDynamic();
  109. return m;
  110. }
  111. public static void Return(Mesh mesh)
  112. {
  113. if (!mesh) return;
  114. var id = mesh.GetInstanceID();
  115. if (s_HashPool.Contains(id)) return;
  116. mesh.Clear(false);
  117. s_Pool.Push(mesh);
  118. s_HashPool.Add(id);
  119. }
  120. }
  121. internal static class CombineInstanceArrayPool
  122. {
  123. private static readonly Dictionary<int, CombineInstance[]> s_Pool;
  124. public static void Init()
  125. {
  126. s_Pool.Clear();
  127. }
  128. static CombineInstanceArrayPool()
  129. {
  130. s_Pool = new Dictionary<int, CombineInstance[]>();
  131. }
  132. public static CombineInstance[] Get(List<CombineInstance> src)
  133. {
  134. CombineInstance[] dst;
  135. var count = src.Count;
  136. if (!s_Pool.TryGetValue(count, out dst))
  137. {
  138. dst = new CombineInstance[count];
  139. s_Pool.Add(count, dst);
  140. }
  141. for (var i = 0; i < src.Count; i++)
  142. {
  143. dst[i].mesh = src[i].mesh;
  144. dst[i].transform = src[i].transform;
  145. }
  146. return dst;
  147. }
  148. public static CombineInstance[] Get(List<CombineInstanceEx> src, int count)
  149. {
  150. CombineInstance[] dst;
  151. if (!s_Pool.TryGetValue(count, out dst))
  152. {
  153. dst = new CombineInstance[count];
  154. s_Pool.Add(count, dst);
  155. }
  156. for (var i = 0; i < count; i++)
  157. {
  158. dst[i].mesh = src[i].mesh;
  159. dst[i].transform = src[i].transform;
  160. }
  161. return dst;
  162. }
  163. }
  164. internal static class ParticleSystemExtensions
  165. {
  166. public static void SortForRendering(this List<ParticleSystem> self, Transform transform, bool sortByMaterial)
  167. {
  168. self.Sort((a, b) =>
  169. {
  170. var tr = transform;
  171. var aRenderer = a.GetComponent<ParticleSystemRenderer>();
  172. var bRenderer = b.GetComponent<ParticleSystemRenderer>();
  173. // Render queue: ascending
  174. var aMat = aRenderer.sharedMaterial ?? aRenderer.trailMaterial;
  175. var bMat = bRenderer.sharedMaterial ?? bRenderer.trailMaterial;
  176. if (!aMat && !bMat) return 0;
  177. if (!aMat) return -1;
  178. if (!bMat) return 1;
  179. if (sortByMaterial)
  180. return aMat.GetInstanceID() - bMat.GetInstanceID();
  181. if (aMat.renderQueue != bMat.renderQueue)
  182. return aMat.renderQueue - bMat.renderQueue;
  183. // Sorting layer: ascending
  184. if (aRenderer.sortingLayerID != bRenderer.sortingLayerID)
  185. return aRenderer.sortingLayerID - bRenderer.sortingLayerID;
  186. // Sorting order: ascending
  187. if (aRenderer.sortingOrder != bRenderer.sortingOrder)
  188. return aRenderer.sortingOrder - bRenderer.sortingOrder;
  189. // Z position & sortingFudge: descending
  190. var aTransform = a.transform;
  191. var bTransform = b.transform;
  192. var aPos = tr.InverseTransformPoint(aTransform.position).z + aRenderer.sortingFudge;
  193. var bPos = tr.InverseTransformPoint(bTransform.position).z + bRenderer.sortingFudge;
  194. if (!Mathf.Approximately(aPos, bPos))
  195. return (int)Mathf.Sign(bPos - aPos);
  196. return (int)Mathf.Sign(GetIndex(self, a) - GetIndex(self, b));
  197. });
  198. }
  199. private static int GetIndex(IList<ParticleSystem> list, Object ps)
  200. {
  201. for (var i = 0; i < list.Count; i++)
  202. {
  203. if (list[i].GetInstanceID() == ps.GetInstanceID()) return i;
  204. }
  205. return 0;
  206. }
  207. public static long GetMaterialHash(this ParticleSystem self, bool trail)
  208. {
  209. if (!self) return 0;
  210. var r = self.GetComponent<ParticleSystemRenderer>();
  211. var mat = trail ? r.trailMaterial : r.sharedMaterial;
  212. if (!mat) return 0;
  213. var tex = trail ? null : self.GetTextureForSprite();
  214. return ((long)mat.GetHashCode() << 32) + (tex ? tex.GetHashCode() : 0);
  215. }
  216. public static Texture2D GetTextureForSprite(this ParticleSystem self)
  217. {
  218. if (!self) return null;
  219. // Get sprite's texture.
  220. var tsaModule = self.textureSheetAnimation;
  221. if (!tsaModule.enabled || tsaModule.mode != ParticleSystemAnimationMode.Sprites) return null;
  222. for (var i = 0; i < tsaModule.spriteCount; i++)
  223. {
  224. var sprite = tsaModule.GetSprite(i);
  225. if (!sprite) continue;
  226. return sprite.GetActualTexture();
  227. }
  228. return null;
  229. }
  230. public static void Exec(this List<ParticleSystem> self, Action<ParticleSystem> action)
  231. {
  232. self.RemoveAll(p => !p);
  233. self.ForEach(action);
  234. }
  235. }
  236. }