Utils.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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. // static readonly List<Color32> s_Colors = new List<Color32>();
  70. // public static void ModifyColorSpaceToLinear(this Mesh self)
  71. // {
  72. // self.GetColors(s_Colors);
  73. //
  74. // for (var i = 0; i < s_Colors.Count; i++)
  75. // s_Colors[i] = ((Color) s_Colors[i]).gamma;
  76. //
  77. // self.SetColors(s_Colors);
  78. // s_Colors.Clear();
  79. // }
  80. public static void Clear(this CombineInstance[] self)
  81. {
  82. for (var i = 0; i < self.Length; i++)
  83. {
  84. MeshPool.Return(self[i].mesh);
  85. self[i].mesh = null;
  86. }
  87. }
  88. }
  89. internal static class MeshPool
  90. {
  91. private static readonly Stack<Mesh> s_Pool = new Stack<Mesh>(32);
  92. private static readonly HashSet<int> s_HashPool = new HashSet<int>();
  93. public static void Init()
  94. {
  95. }
  96. static MeshPool()
  97. {
  98. for (var i = 0; i < 32; i++)
  99. {
  100. var m = new Mesh();
  101. m.MarkDynamic();
  102. s_Pool.Push(m);
  103. s_HashPool.Add(m.GetInstanceID());
  104. }
  105. }
  106. public static Mesh Rent()
  107. {
  108. Mesh m;
  109. while (0 < s_Pool.Count)
  110. {
  111. m = s_Pool.Pop();
  112. if (m)
  113. {
  114. s_HashPool.Remove(m.GetInstanceID());
  115. return m;
  116. }
  117. }
  118. m = new Mesh();
  119. m.MarkDynamic();
  120. return m;
  121. }
  122. public static void Return(Mesh mesh)
  123. {
  124. if (!mesh) return;
  125. var id = mesh.GetInstanceID();
  126. if (s_HashPool.Contains(id)) return;
  127. mesh.Clear(false);
  128. s_Pool.Push(mesh);
  129. s_HashPool.Add(id);
  130. }
  131. }
  132. internal static class CombineInstanceArrayPool
  133. {
  134. private static readonly Dictionary<int, CombineInstance[]> s_Pool;
  135. public static void Init()
  136. {
  137. s_Pool.Clear();
  138. }
  139. static CombineInstanceArrayPool()
  140. {
  141. s_Pool = new Dictionary<int, CombineInstance[]>();
  142. }
  143. public static CombineInstance[] Get(List<CombineInstance> src)
  144. {
  145. CombineInstance[] dst;
  146. var count = src.Count;
  147. if (!s_Pool.TryGetValue(count, out dst))
  148. {
  149. dst = new CombineInstance[count];
  150. s_Pool.Add(count, dst);
  151. }
  152. for (var i = 0; i < src.Count; i++)
  153. {
  154. dst[i].mesh = src[i].mesh;
  155. dst[i].transform = src[i].transform;
  156. }
  157. return dst;
  158. }
  159. public static CombineInstance[] Get(List<CombineInstanceEx> src, int count)
  160. {
  161. CombineInstance[] dst;
  162. if (!s_Pool.TryGetValue(count, out dst))
  163. {
  164. dst = new CombineInstance[count];
  165. s_Pool.Add(count, dst);
  166. }
  167. for (var i = 0; i < count; i++)
  168. {
  169. dst[i].mesh = src[i].mesh;
  170. dst[i].transform = src[i].transform;
  171. }
  172. return dst;
  173. }
  174. }
  175. internal static class ParticleSystemExtensions
  176. {
  177. public static void SortForRendering(this List<ParticleSystem> self, Transform transform, bool sortByMaterial)
  178. {
  179. self.Sort((a, b) =>
  180. {
  181. var tr = transform;
  182. var aRenderer = a.GetComponent<ParticleSystemRenderer>();
  183. var bRenderer = b.GetComponent<ParticleSystemRenderer>();
  184. // Render queue: ascending
  185. var aMat = aRenderer.sharedMaterial ?? aRenderer.trailMaterial;
  186. var bMat = bRenderer.sharedMaterial ?? bRenderer.trailMaterial;
  187. if (!aMat && !bMat) return 0;
  188. if (!aMat) return -1;
  189. if (!bMat) return 1;
  190. if (sortByMaterial)
  191. return aMat.GetInstanceID() - bMat.GetInstanceID();
  192. if (aMat.renderQueue != bMat.renderQueue)
  193. return aMat.renderQueue - bMat.renderQueue;
  194. // Sorting layer: ascending
  195. if (aRenderer.sortingLayerID != bRenderer.sortingLayerID)
  196. return aRenderer.sortingLayerID - bRenderer.sortingLayerID;
  197. // Sorting order: ascending
  198. if (aRenderer.sortingOrder != bRenderer.sortingOrder)
  199. return aRenderer.sortingOrder - bRenderer.sortingOrder;
  200. // Z position & sortingFudge: descending
  201. var aTransform = a.transform;
  202. var bTransform = b.transform;
  203. var aPos = tr.InverseTransformPoint(aTransform.position).z + aRenderer.sortingFudge;
  204. var bPos = tr.InverseTransformPoint(bTransform.position).z + bRenderer.sortingFudge;
  205. if (!Mathf.Approximately(aPos, bPos))
  206. return (int) Mathf.Sign(bPos - aPos);
  207. return (int) Mathf.Sign(GetIndex(self, a) - GetIndex(self, b));
  208. });
  209. }
  210. private static int GetIndex(IList<ParticleSystem> list, Object ps)
  211. {
  212. for (var i = 0; i < list.Count; i++)
  213. {
  214. if (list[i].GetInstanceID() == ps.GetInstanceID()) return i;
  215. }
  216. return 0;
  217. }
  218. public static long GetMaterialHash(this ParticleSystem self, bool trail)
  219. {
  220. if (!self) return 0;
  221. var r = self.GetComponent<ParticleSystemRenderer>();
  222. var mat = trail ? r.trailMaterial : r.sharedMaterial;
  223. if (!mat) return 0;
  224. var tex = trail ? null : self.GetTextureForSprite();
  225. return ((long) mat.GetHashCode() << 32) + (tex ? tex.GetHashCode() : 0);
  226. }
  227. public static Texture2D GetTextureForSprite(this ParticleSystem self)
  228. {
  229. if (!self) return null;
  230. // Get sprite's texture.
  231. var tsaModule = self.textureSheetAnimation;
  232. if (!tsaModule.enabled || tsaModule.mode != ParticleSystemAnimationMode.Sprites) return null;
  233. for (var i = 0; i < tsaModule.spriteCount; i++)
  234. {
  235. var sprite = tsaModule.GetSprite(i);
  236. if (!sprite) continue;
  237. return sprite.GetActualTexture();
  238. }
  239. return null;
  240. }
  241. public static void Exec(this List<ParticleSystem> self, Action<ParticleSystem> action)
  242. {
  243. self.RemoveAll(p => !p);
  244. self.ForEach(action);
  245. }
  246. }
  247. }