TransformAccessJob.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #if ENABLE_ANIMATION_COLLECTION && ENABLE_ANIMATION_BURST
  2. using System;
  3. using System.Collections.Generic;
  4. using Unity.Collections;
  5. using Unity.Jobs;
  6. using Unity.Mathematics;
  7. using UnityEngine.Jobs;
  8. using UnityEngine.Profiling;
  9. using Unity.Burst;
  10. namespace UnityEngine.U2D.Animation
  11. {
  12. internal class TransformAccessJob
  13. {
  14. internal struct TransformData
  15. {
  16. public int transformIndex;
  17. public int refCount;
  18. public TransformData(int index)
  19. {
  20. transformIndex = index;
  21. refCount = 1;
  22. }
  23. }
  24. Transform[] m_Transform;
  25. TransformAccessArray m_TransformAccessArray;
  26. NativeHashMap<int, TransformData> m_TransformData;
  27. NativeArray<float4x4> m_TransformMatrix;
  28. bool m_Dirty;
  29. JobHandle m_JobHandle;
  30. public TransformAccessJob()
  31. {
  32. m_TransformMatrix = new NativeArray<float4x4>(1, Allocator.Persistent);
  33. m_TransformData = new NativeHashMap<int, TransformData>(1, Allocator.Persistent);
  34. m_Transform = new Transform[0];
  35. m_Dirty = false;
  36. m_JobHandle = default(JobHandle);
  37. }
  38. public void Destroy()
  39. {
  40. m_JobHandle.Complete();
  41. if (m_TransformMatrix.IsCreated)
  42. m_TransformMatrix.Dispose();
  43. if (m_TransformAccessArray.isCreated)
  44. m_TransformAccessArray.Dispose();
  45. if (m_TransformData.IsCreated)
  46. m_TransformData.Dispose();
  47. }
  48. public NativeHashMap<int, TransformData> transformData
  49. {
  50. get { return m_TransformData; }
  51. }
  52. public NativeArray<float4x4> transformMatrix
  53. {
  54. get { return m_TransformMatrix; }
  55. }
  56. public void AddTransform(Transform t)
  57. {
  58. if (t == null || !m_TransformData.IsCreated)
  59. return;
  60. m_JobHandle.Complete();
  61. int instanceId = t.GetInstanceID();
  62. if (m_TransformData.ContainsKey(instanceId))
  63. {
  64. var transformData = m_TransformData[instanceId];
  65. transformData.refCount += 1;
  66. m_TransformData[instanceId] = transformData;
  67. }
  68. else
  69. {
  70. m_TransformData.TryAdd(instanceId, new TransformData(-1));
  71. ArrayAdd(ref m_Transform, t);
  72. m_Dirty = true;
  73. }
  74. }
  75. static void ArrayAdd<T>(ref T[] array, T item)
  76. {
  77. int arraySize = array.Length;
  78. Array.Resize(ref array, arraySize + 1);
  79. array[arraySize] = item;
  80. }
  81. static void ArrayRemove<T>(ref T[] array, T item)
  82. {
  83. List<T> newList = new List<T>(array);
  84. newList.Remove(item);
  85. array = newList.ToArray();
  86. }
  87. public static void ArrayRemoveAt<T>(ref T[] array, int index)
  88. {
  89. List<T> list = new List<T>(array);
  90. list.RemoveAt(index);
  91. array = list.ToArray();
  92. }
  93. public void RemoveTransform(Transform t)
  94. {
  95. if (t == null || !m_TransformData.IsCreated)
  96. return;
  97. m_JobHandle.Complete();
  98. int instanceId = t.GetInstanceID();
  99. if (m_TransformData.ContainsKey(instanceId))
  100. {
  101. var transformData = m_TransformData[instanceId];
  102. if (transformData.refCount == 1)
  103. {
  104. m_TransformData.Remove(instanceId);
  105. ArrayRemove(ref m_Transform, t);
  106. m_Dirty = true;
  107. }
  108. else
  109. {
  110. transformData.refCount -= 1;
  111. m_TransformData[instanceId] = transformData;
  112. }
  113. }
  114. }
  115. void UpdateTransformIndex()
  116. {
  117. if (!m_Dirty)
  118. return;
  119. m_Dirty = false;
  120. Profiler.BeginSample("UpdateTransformIndex");
  121. NativeArrayHelpers.ResizeIfNeeded(ref m_TransformMatrix, m_Transform.Length);
  122. if (!m_TransformAccessArray.isCreated)
  123. TransformAccessArray.Allocate(m_Transform.Length, -1, out m_TransformAccessArray);
  124. else if (m_TransformAccessArray.capacity != m_Transform.Length)
  125. m_TransformAccessArray.capacity = m_Transform.Length;
  126. m_TransformAccessArray.SetTransforms(m_Transform);
  127. for (int i = 0; i < m_Transform.Length; ++i)
  128. {
  129. if (m_Transform[i] != null)
  130. {
  131. var instanceId = m_Transform[i].GetInstanceID();
  132. var transformData = m_TransformData[instanceId];
  133. transformData.transformIndex = i;
  134. m_TransformData[instanceId] = transformData;
  135. }
  136. }
  137. Profiler.EndSample();
  138. }
  139. public JobHandle StartLocalToWorldJob()
  140. {
  141. if (m_Transform.Length > 0)
  142. {
  143. m_JobHandle.Complete();
  144. UpdateTransformIndex();
  145. Profiler.BeginSample("StartLocalToWorldJob");
  146. var job = new LocalToWorldTransformAccessJob()
  147. {
  148. outMatrix = transformMatrix,
  149. };
  150. m_JobHandle = job.Schedule(m_TransformAccessArray);
  151. Profiler.EndSample();
  152. return m_JobHandle;
  153. }
  154. return default(JobHandle);
  155. }
  156. public JobHandle StartWorldToLocalJob()
  157. {
  158. if (m_Transform.Length > 0)
  159. {
  160. m_JobHandle.Complete();
  161. UpdateTransformIndex();
  162. Profiler.BeginSample("StartWorldToLocalJob");
  163. var job = new WorldToLocalTransformAccessJob()
  164. {
  165. outMatrix = transformMatrix,
  166. };
  167. m_JobHandle = job.Schedule(m_TransformAccessArray);
  168. Profiler.EndSample();
  169. return m_JobHandle;
  170. }
  171. return default(JobHandle);
  172. }
  173. internal string GetDebugLog()
  174. {
  175. var log = "";
  176. log += "TransformData Count: " + m_TransformData.Count() + "\n";
  177. log += "Transform Count: " + m_Transform.Length + "\n";
  178. foreach (var ss in m_Transform)
  179. {
  180. log += ss == null ? "null" : ss.name + " " + ss.GetInstanceID();
  181. log += "\n";
  182. if (ss != null)
  183. {
  184. log += "RefCount: " + m_TransformData[ss.GetInstanceID()].refCount + "\n";
  185. }
  186. log += "\n";
  187. }
  188. return log;
  189. }
  190. internal void RemoveTransformById(int transformId)
  191. {
  192. if (!m_TransformData.IsCreated)
  193. return;
  194. m_JobHandle.Complete();
  195. if (m_TransformData.ContainsKey(transformId))
  196. {
  197. var transformData = m_TransformData[transformId];
  198. if (transformData.refCount == 1)
  199. {
  200. m_TransformData.Remove(transformId);
  201. var index = Array.FindIndex(m_Transform, t => t.GetInstanceID() == transformId);
  202. if (index >= 0)
  203. {
  204. ArrayRemoveAt(ref m_Transform, index);
  205. }
  206. m_Dirty = true;
  207. }
  208. else
  209. {
  210. transformData.refCount -= 1;
  211. m_TransformData[transformId] = transformData;
  212. }
  213. }
  214. }
  215. }
  216. [BurstCompile]
  217. internal struct LocalToWorldTransformAccessJob : IJobParallelForTransform
  218. {
  219. [WriteOnly]
  220. public NativeArray<float4x4> outMatrix;
  221. public void Execute(int index, TransformAccess transform)
  222. {
  223. outMatrix[index] = transform.localToWorldMatrix;
  224. }
  225. }
  226. [BurstCompile]
  227. internal struct WorldToLocalTransformAccessJob : IJobParallelForTransform
  228. {
  229. [WriteOnly]
  230. public NativeArray<float4x4> outMatrix;
  231. public void Execute(int index, TransformAccess transform)
  232. {
  233. outMatrix[index] = transform.worldToLocalMatrix;
  234. }
  235. }
  236. }
  237. #endif