Brak opisu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TransformAccessJob.cs 8.5KB

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