Ei kuvausta
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.

SpriteSkinComposite.cs 33KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. #if ENABLE_ANIMATION_COLLECTION
  2. using System;
  3. using Unity.Mathematics;
  4. using System.Collections.Generic;
  5. using Unity.Collections;
  6. using Unity.Jobs;
  7. using Unity.Collections.LowLevel.Unsafe;
  8. using UnityEngine.U2D.Common;
  9. using Unity.Burst;
  10. using Unity.Profiling;
  11. using UnityEngine.Assertions;
  12. namespace UnityEngine.U2D.Animation
  13. {
  14. internal struct PerSkinJobData
  15. {
  16. public int deformVerticesStartPos;
  17. public int2 bindPosesIndex;
  18. public int2 verticesIndex;
  19. }
  20. internal struct SpriteSkinData
  21. {
  22. public NativeCustomSlice<Vector3> vertices;
  23. public NativeCustomSlice<BoneWeight> boneWeights;
  24. public NativeCustomSlice<Matrix4x4> bindPoses;
  25. public NativeCustomSlice<Vector4> tangents;
  26. public bool hasTangents;
  27. public int spriteVertexStreamSize;
  28. public int spriteVertexCount;
  29. public int tangentVertexOffset;
  30. public int deformVerticesStartPos;
  31. public int transformId;
  32. public NativeCustomSlice<int> boneTransformId;
  33. }
  34. #if ENABLE_ANIMATION_BURST
  35. [BurstCompile]
  36. #endif
  37. internal struct PrepareDeformJob :IJob
  38. {
  39. [ReadOnly]
  40. public NativeArray<PerSkinJobData> perSkinJobData;
  41. [ReadOnly]
  42. public int batchDataSize;
  43. [WriteOnly]
  44. public NativeArray<int2> boneLookupData;
  45. [WriteOnly]
  46. public NativeArray<int2> vertexLookupData;
  47. public void Execute()
  48. {
  49. for (var i = 0; i < batchDataSize; ++i)
  50. {
  51. var jobData = perSkinJobData[i];
  52. for (int k = 0, j = jobData.bindPosesIndex.x; j < jobData.bindPosesIndex.y; ++j, ++k)
  53. {
  54. boneLookupData[j] = new int2(i, k);
  55. }
  56. for (int k = 0, j = jobData.verticesIndex.x; j < jobData.verticesIndex.y; ++j, ++k)
  57. {
  58. vertexLookupData[j] = new int2(i, k);
  59. }
  60. }
  61. }
  62. }
  63. #if ENABLE_ANIMATION_BURST
  64. [BurstCompile]
  65. #endif
  66. internal struct BoneDeformBatchedJob : IJobParallelFor
  67. {
  68. [ReadOnly]
  69. public NativeArray<float4x4> boneTransform;
  70. [ReadOnly]
  71. public NativeArray<float4x4> rootTransform;
  72. [ReadOnly]
  73. public NativeArray<int2> boneLookupData;
  74. [ReadOnly]
  75. public NativeArray<SpriteSkinData> spriteSkinData;
  76. [ReadOnly]
  77. public NativeHashMap<int, TransformAccessJob.TransformData> rootTransformIndex;
  78. [ReadOnly]
  79. public NativeHashMap<int, TransformAccessJob.TransformData> boneTransformIndex;
  80. [WriteOnly]
  81. public NativeArray<float4x4> finalBoneTransforms;
  82. public void Execute(int i)
  83. {
  84. var x = boneLookupData[i].x;
  85. var y = boneLookupData[i].y;
  86. var ssd = spriteSkinData[x];
  87. var v = ssd.boneTransformId[y];
  88. var index = boneTransformIndex[v].transformIndex;
  89. if (index < 0)
  90. return;
  91. var aa = boneTransform[index];
  92. var bb = ssd.bindPoses[y];
  93. var cc = rootTransformIndex[ssd.transformId].transformIndex;
  94. finalBoneTransforms[i] = math.mul(rootTransform[cc], math.mul(aa, bb));
  95. }
  96. }
  97. #if ENABLE_ANIMATION_BURST
  98. [BurstCompile]
  99. #endif
  100. internal struct SkinDeformBatchedJob : IJobParallelFor
  101. {
  102. public NativeSlice<byte> vertices;
  103. [ReadOnly]
  104. public NativeArray<float4x4> finalBoneTransforms;
  105. [ReadOnly]
  106. public NativeArray<PerSkinJobData> perSkinJobData;
  107. [ReadOnly]
  108. public NativeArray<SpriteSkinData> spriteSkinData;
  109. [ReadOnly]
  110. public NativeArray<int2> vertexLookupData;
  111. public unsafe void Execute(int i)
  112. {
  113. var j = vertexLookupData[i].x;
  114. var k = vertexLookupData[i].y;
  115. var perSkinData = perSkinJobData[j];
  116. var spriteSkin = spriteSkinData[j];
  117. var srcVertex = (float3)spriteSkin.vertices[k];
  118. var tangents = (float4)spriteSkin.tangents[k];
  119. var influence = spriteSkin.boneWeights[k];
  120. var bone0 = influence.boneIndex0 + perSkinData.bindPosesIndex.x;
  121. var bone1 = influence.boneIndex1 + perSkinData.bindPosesIndex.x;
  122. var bone2 = influence.boneIndex2 + perSkinData.bindPosesIndex.x;
  123. var bone3 = influence.boneIndex3 + perSkinData.bindPosesIndex.x;
  124. var deformedPosOffset = (byte*)vertices.GetUnsafePtr();
  125. var deformedPosStart = deformedPosOffset + spriteSkin.deformVerticesStartPos;
  126. var deformableVerticesFloat3 = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice<float3>(deformedPosStart, spriteSkin.spriteVertexStreamSize, spriteSkin.spriteVertexCount);
  127. #if ENABLE_UNITY_COLLECTIONS_CHECKS
  128. NativeSliceUnsafeUtility.SetAtomicSafetyHandle(ref deformableVerticesFloat3, NativeSliceUnsafeUtility.GetAtomicSafetyHandle(vertices));
  129. #endif
  130. if (spriteSkin.hasTangents)
  131. {
  132. var deformedTanOffset = deformedPosStart + spriteSkin.tangentVertexOffset;
  133. var deformableTangentsFloat4 = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice<float4>(deformedTanOffset, spriteSkin.spriteVertexStreamSize, spriteSkin.spriteVertexCount);
  134. #if ENABLE_UNITY_COLLECTIONS_CHECKS
  135. NativeSliceUnsafeUtility.SetAtomicSafetyHandle(ref deformableTangentsFloat4, NativeSliceUnsafeUtility.GetAtomicSafetyHandle(vertices));
  136. #endif
  137. var tangent = new float4(tangents.xyz, 0.0f);
  138. tangent =
  139. math.mul(finalBoneTransforms[bone0], tangent) * influence.weight0 +
  140. math.mul(finalBoneTransforms[bone1], tangent) * influence.weight1 +
  141. math.mul(finalBoneTransforms[bone2], tangent) * influence.weight2 +
  142. math.mul(finalBoneTransforms[bone3], tangent) * influence.weight3;
  143. deformableTangentsFloat4[k] = new float4(math.normalize(tangent.xyz), tangents.w);
  144. }
  145. deformableVerticesFloat3[k] =
  146. math.transform(finalBoneTransforms[bone0], srcVertex) * influence.weight0 +
  147. math.transform(finalBoneTransforms[bone1], srcVertex) * influence.weight1 +
  148. math.transform(finalBoneTransforms[bone2], srcVertex) * influence.weight2 +
  149. math.transform(finalBoneTransforms[bone3], srcVertex) * influence.weight3;
  150. }
  151. }
  152. #if ENABLE_ANIMATION_BURST
  153. [BurstCompile]
  154. #endif
  155. internal struct CalculateSpriteSkinAABBJob : IJobParallelFor
  156. {
  157. public NativeSlice<byte> vertices;
  158. [ReadOnly]
  159. public NativeArray<bool> isSpriteSkinValidForDeformArray;
  160. [ReadOnly]
  161. public NativeArray<SpriteSkinData> spriteSkinData;
  162. [WriteOnly]
  163. public NativeArray<Bounds> bounds;
  164. public unsafe void Execute(int i)
  165. {
  166. if (!isSpriteSkinValidForDeformArray[i])
  167. return;
  168. var spriteSkin = spriteSkinData[i];
  169. var deformedPosOffset = (byte*)vertices.GetUnsafePtr();
  170. var deformableVerticesFloat3 = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice<float3>(deformedPosOffset + spriteSkin.deformVerticesStartPos, spriteSkin.spriteVertexStreamSize, spriteSkin.spriteVertexCount);
  171. #if ENABLE_UNITY_COLLECTIONS_CHECKS
  172. NativeSliceUnsafeUtility.SetAtomicSafetyHandle(ref deformableVerticesFloat3, NativeSliceUnsafeUtility.GetAtomicSafetyHandle(vertices));
  173. #endif
  174. bounds[i] = SpriteSkinUtility.CalculateSpriteSkinBounds(deformableVerticesFloat3);
  175. }
  176. }
  177. #if ENABLE_ANIMATION_BURST
  178. [BurstCompile]
  179. #endif
  180. internal struct FillPerSkinJobSingleThread : IJob
  181. {
  182. public PerSkinJobData combinedSkinBatch;
  183. [ReadOnly]
  184. public NativeArray<bool> isSpriteSkinValidForDeformArray;
  185. public NativeArray<SpriteSkinData> spriteSkinDataArray;
  186. public NativeArray<PerSkinJobData> perSkinJobDataArray;
  187. public NativeArray<PerSkinJobData> combinedSkinBatchArray;
  188. public void Execute()
  189. {
  190. var startIndex = 0;
  191. var endIndex = spriteSkinDataArray.Length;
  192. for (var index = startIndex; index < endIndex; ++index)
  193. {
  194. var spriteSkinData = spriteSkinDataArray[index];
  195. spriteSkinData.deformVerticesStartPos = -1;
  196. var vertexBufferSize = 0;
  197. var vertexCount = 0;
  198. var bindPoseCount = 0;
  199. if (isSpriteSkinValidForDeformArray[index])
  200. {
  201. spriteSkinData.deformVerticesStartPos = combinedSkinBatch.deformVerticesStartPos;
  202. vertexBufferSize = spriteSkinData.spriteVertexCount * spriteSkinData.spriteVertexStreamSize;
  203. vertexCount = spriteSkinData.spriteVertexCount;
  204. bindPoseCount = spriteSkinData.bindPoses.Length;
  205. }
  206. combinedSkinBatch.verticesIndex.x = combinedSkinBatch.verticesIndex.y;
  207. combinedSkinBatch.verticesIndex.y = combinedSkinBatch.verticesIndex.x + vertexCount;
  208. combinedSkinBatch.bindPosesIndex.x = combinedSkinBatch.bindPosesIndex.y;
  209. combinedSkinBatch.bindPosesIndex.y = combinedSkinBatch.bindPosesIndex.x + bindPoseCount;
  210. spriteSkinDataArray[index] = spriteSkinData;
  211. perSkinJobDataArray[index] = combinedSkinBatch;
  212. combinedSkinBatch.deformVerticesStartPos += vertexBufferSize;
  213. }
  214. combinedSkinBatchArray[0] = combinedSkinBatch;
  215. }
  216. }
  217. #if ENABLE_ANIMATION_BURST
  218. [BurstCompile]
  219. #endif
  220. internal struct CopySpriteRendererBuffersJob : IJobParallelFor
  221. {
  222. [ReadOnly]
  223. public NativeArray<bool> isSpriteSkinValidForDeformArray;
  224. [ReadOnly]
  225. public NativeArray<SpriteSkinData> spriteSkinData;
  226. [ReadOnly, NativeDisableUnsafePtrRestriction]
  227. public IntPtr ptrVertices;
  228. [WriteOnly]
  229. public NativeArray<IntPtr> buffers;
  230. [WriteOnly]
  231. public NativeArray<int> bufferSizes;
  232. public void Execute(int i)
  233. {
  234. var skinData = spriteSkinData[i];
  235. var startVertices = default(IntPtr);
  236. var vertexBufferLength = 0;
  237. if (isSpriteSkinValidForDeformArray[i])
  238. {
  239. startVertices = ptrVertices + skinData.deformVerticesStartPos;
  240. vertexBufferLength = skinData.spriteVertexCount * skinData.spriteVertexStreamSize;
  241. }
  242. buffers[i] = startVertices;
  243. bufferSizes[i] = vertexBufferLength;
  244. }
  245. }
  246. internal class SpriteSkinComposite : ScriptableObject
  247. {
  248. static class Profiling
  249. {
  250. public static readonly ProfilerMarker prepareData = new ProfilerMarker("SpriteSkinComposite.PrepareData");
  251. public static readonly ProfilerMarker validateSpriteSkinData = new ProfilerMarker("SpriteSkinComposite.ValidateSpriteSkinData");
  252. public static readonly ProfilerMarker transformAccessJob = new ProfilerMarker("SpriteSkinComposite.TransformAccessJob");
  253. public static readonly ProfilerMarker getSpriteSkinBatchData = new ProfilerMarker("SpriteSkinComposite.GetSpriteSkinBatchData");
  254. public static readonly ProfilerMarker resizeBuffers = new ProfilerMarker("SpriteSkinComposite.ResizeBuffers");
  255. public static readonly ProfilerMarker prepare = new ProfilerMarker("SpriteSkinComposite.Prepare");
  256. public static readonly ProfilerMarker scheduleJobs = new ProfilerMarker("SpriteSkinComposite.ScheduleJobs");
  257. public static readonly ProfilerMarker setBatchDeformableBufferAndLocalAABB = new ProfilerMarker("SpriteSkinComposite.SetBatchDeformableBufferAndLocalAABB");
  258. public static readonly ProfilerMarker deactivateDeformableBuffer = new ProfilerMarker("SpriteSkinComposite.DeactivateDeformableBuffer");
  259. }
  260. static SpriteSkinComposite s_Instance;
  261. public static SpriteSkinComposite instance
  262. {
  263. get
  264. {
  265. if (s_Instance == null)
  266. {
  267. var composite = Resources.FindObjectsOfTypeAll<SpriteSkinComposite>();
  268. if (composite.Length > 0)
  269. s_Instance = composite[0];
  270. else
  271. s_Instance = ScriptableObject.CreateInstance<SpriteSkinComposite>();
  272. s_Instance.hideFlags = HideFlags.HideAndDontSave;
  273. s_Instance.Init();
  274. }
  275. return s_Instance;
  276. }
  277. }
  278. List<SpriteSkin> m_SpriteSkins = new List<SpriteSkin>();
  279. List<SpriteSkin> m_SpriteSkinLateUpdate = new List<SpriteSkin>();
  280. SpriteRenderer[] m_SpriteRenderers = new SpriteRenderer[0];
  281. NativeByteArray m_DeformedVerticesBuffer;
  282. NativeArray<float4x4> m_FinalBoneTransforms;
  283. NativeArray<bool> m_IsSpriteSkinActiveForDeform;
  284. NativeArray<SpriteSkinData> m_SpriteSkinData;
  285. NativeArray<PerSkinJobData> m_PerSkinJobData;
  286. NativeArray<Bounds> m_BoundsData;
  287. NativeArray<IntPtr> m_Buffers;
  288. NativeArray<int> m_BufferSizes;
  289. NativeArray<int2> m_BoneLookupData;
  290. NativeArray<int2> m_VertexLookupData;
  291. NativeArray<PerSkinJobData> m_SkinBatchArray;
  292. TransformAccessJob m_LocalToWorldTransformAccessJob;
  293. TransformAccessJob m_WorldToLocalTransformAccessJob;
  294. JobHandle m_BoundJobHandle;
  295. JobHandle m_DeformJobHandle;
  296. JobHandle m_CopyJobHandle;
  297. [SerializeField]
  298. GameObject m_Helper;
  299. internal GameObject helperGameObject => m_Helper;
  300. internal void RemoveTransformById(int transformId)
  301. {
  302. m_LocalToWorldTransformAccessJob.RemoveTransformById(transformId);
  303. }
  304. internal void AddSpriteSkinBoneTransform(SpriteSkin spriteSkin)
  305. {
  306. if (spriteSkin == null)
  307. return;
  308. if (spriteSkin.boneTransforms != null)
  309. {
  310. foreach (var t in spriteSkin.boneTransforms)
  311. {
  312. if(t != null)
  313. m_LocalToWorldTransformAccessJob.AddTransform(t);
  314. }
  315. }
  316. }
  317. internal void AddSpriteSkinRootBoneTransform(SpriteSkin spriteSkin)
  318. {
  319. if (spriteSkin == null || spriteSkin.rootBone == null)
  320. return;
  321. m_LocalToWorldTransformAccessJob.AddTransform(spriteSkin.rootBone);
  322. }
  323. internal void AddSpriteSkin(SpriteSkin spriteSkin)
  324. {
  325. if (spriteSkin == null)
  326. return;
  327. var added = m_SpriteSkins.Contains(spriteSkin);
  328. Debug.Assert(!added, $"SpriteSkin {spriteSkin.gameObject.name} is already added");
  329. if (!added)
  330. {
  331. m_SpriteSkins.Add(spriteSkin);
  332. var count = m_SpriteSkins.Count;
  333. Array.Resize(ref m_SpriteRenderers, count);
  334. m_SpriteRenderers[count - 1] = spriteSkin.spriteRenderer;
  335. m_WorldToLocalTransformAccessJob.AddTransform(spriteSkin.transform);
  336. if (m_IsSpriteSkinActiveForDeform.IsCreated)
  337. {
  338. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_IsSpriteSkinActiveForDeform, count);
  339. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_PerSkinJobData, count);
  340. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_SpriteSkinData, count);
  341. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_BoundsData, count);
  342. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_Buffers, count);
  343. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_BufferSizes, count);
  344. CopyToSpriteSkinData(count - 1);
  345. }
  346. }
  347. }
  348. internal void CopyToSpriteSkinData(SpriteSkin spriteSkin)
  349. {
  350. if (spriteSkin == null)
  351. return;
  352. var index = m_SpriteSkins.IndexOf(spriteSkin);
  353. if (index < 0)
  354. return;
  355. CopyToSpriteSkinData(index);
  356. }
  357. private void CopyToSpriteSkinData(int index)
  358. {
  359. if (index < 0 || index >= m_SpriteSkins.Count || !m_SpriteSkinData.IsCreated)
  360. return;
  361. var spriteSkinData = default(SpriteSkinData);
  362. var spriteSkin = m_SpriteSkins[index];
  363. spriteSkin.CopyToSpriteSkinData(ref spriteSkinData, index);
  364. m_SpriteSkinData[index] = spriteSkinData;
  365. m_SpriteRenderers[index] = spriteSkin.spriteRenderer;
  366. }
  367. internal void RemoveSpriteSkin(SpriteSkin spriteSkin)
  368. {
  369. var index = m_SpriteSkins.IndexOf(spriteSkin);
  370. if (index < 0)
  371. return;
  372. // Check if it is not the last SpriteSkin
  373. if (index < m_SpriteSkins.Count - 1)
  374. {
  375. m_SpriteSkins.RemoveAtSwapBack(index);
  376. CopyToSpriteSkinData(index);
  377. }
  378. else
  379. {
  380. m_SpriteSkins.RemoveAt(index);
  381. }
  382. var count = m_SpriteSkins.Count;
  383. Array.Resize(ref m_SpriteRenderers, count);
  384. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_IsSpriteSkinActiveForDeform, count);
  385. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_PerSkinJobData, count);
  386. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_SpriteSkinData, count);
  387. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_BoundsData, count);
  388. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_Buffers, count);
  389. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_BufferSizes, count);
  390. m_WorldToLocalTransformAccessJob.RemoveTransform(spriteSkin.transform);
  391. }
  392. internal void AddSpriteSkinForLateUpdate(SpriteSkin spriteSkin)
  393. {
  394. if (spriteSkin == null)
  395. return;
  396. var added = m_SpriteSkinLateUpdate.Contains(spriteSkin);
  397. Debug.Assert(!added, $"SpriteSkin {spriteSkin.gameObject.name} is already added for LateUpdate");
  398. if (!added)
  399. {
  400. m_SpriteSkinLateUpdate.Add(spriteSkin);
  401. }
  402. }
  403. internal void RemoveSpriteSkinForLateUpdate(SpriteSkin spriteSkin)
  404. {
  405. m_SpriteSkinLateUpdate.Remove(spriteSkin);
  406. }
  407. void Init()
  408. {
  409. if (m_LocalToWorldTransformAccessJob == null)
  410. m_LocalToWorldTransformAccessJob = new TransformAccessJob();
  411. if (m_WorldToLocalTransformAccessJob == null)
  412. m_WorldToLocalTransformAccessJob = new TransformAccessJob();
  413. CreateHelper();
  414. }
  415. void CreateHelper()
  416. {
  417. if (m_Helper != null)
  418. return;
  419. m_Helper = new GameObject("SpriteSkinUpdateHelper");
  420. m_Helper.hideFlags = HideFlags.HideAndDontSave;
  421. var helperComponent = m_Helper.AddComponent<SpriteSkinUpdateHelper>();
  422. helperComponent.onDestroyingComponent += OnHelperDestroyed;
  423. #if !UNITY_EDITOR
  424. GameObject.DontDestroyOnLoad(m_Helper);
  425. #endif
  426. }
  427. void OnHelperDestroyed(GameObject helperGo)
  428. {
  429. if (m_Helper != helperGo)
  430. return;
  431. m_Helper = null;
  432. CreateHelper();
  433. }
  434. internal void ResetComposite()
  435. {
  436. foreach (var spriteSkin in m_SpriteSkins)
  437. spriteSkin.batchSkinning = false;
  438. m_SpriteSkins.Clear();
  439. m_LocalToWorldTransformAccessJob.Destroy();
  440. m_WorldToLocalTransformAccessJob.Destroy();
  441. m_LocalToWorldTransformAccessJob = new TransformAccessJob();
  442. m_WorldToLocalTransformAccessJob = new TransformAccessJob();
  443. }
  444. public void OnEnable()
  445. {
  446. s_Instance = this;
  447. m_FinalBoneTransforms = new NativeArray<float4x4>(1, Allocator.Persistent);
  448. m_BoneLookupData = new NativeArray<int2>(1, Allocator.Persistent);
  449. m_VertexLookupData = new NativeArray<int2>(1, Allocator.Persistent);
  450. m_SkinBatchArray = new NativeArray<PerSkinJobData>(1, Allocator.Persistent);
  451. Init();
  452. // Initialise all existing SpriteSkins as execution order is indeterminate
  453. var count = m_SpriteSkins.Count;
  454. if (count > 0)
  455. {
  456. m_IsSpriteSkinActiveForDeform = new NativeArray<bool>(count, Allocator.Persistent);
  457. m_PerSkinJobData = new NativeArray<PerSkinJobData>(count, Allocator.Persistent);
  458. m_SpriteSkinData = new NativeArray<SpriteSkinData>(count, Allocator.Persistent);
  459. m_BoundsData = new NativeArray<Bounds>(count, Allocator.Persistent);
  460. m_Buffers = new NativeArray<IntPtr>(count, Allocator.Persistent);
  461. m_BufferSizes = new NativeArray<int>(count, Allocator.Persistent);
  462. for (var i = 0; i < count; ++i)
  463. {
  464. var spriteSkin = m_SpriteSkins[i];
  465. spriteSkin.batchSkinning = true;
  466. CopyToSpriteSkinData(i);
  467. }
  468. }
  469. else
  470. {
  471. m_IsSpriteSkinActiveForDeform = new NativeArray<bool>(1, Allocator.Persistent);
  472. m_PerSkinJobData = new NativeArray<PerSkinJobData>(1, Allocator.Persistent);
  473. m_SpriteSkinData = new NativeArray<SpriteSkinData>(1, Allocator.Persistent);
  474. m_BoundsData = new NativeArray<Bounds>(1, Allocator.Persistent);
  475. m_Buffers = new NativeArray<IntPtr>(1, Allocator.Persistent);
  476. m_BufferSizes = new NativeArray<int>(1, Allocator.Persistent);
  477. }
  478. }
  479. void OnDisable()
  480. {
  481. m_DeformJobHandle.Complete();
  482. m_BoundJobHandle.Complete();
  483. m_CopyJobHandle.Complete();
  484. foreach (var spriteSkin in m_SpriteSkins)
  485. spriteSkin.batchSkinning = false;
  486. m_SpriteSkins.Clear();
  487. m_SpriteRenderers = new SpriteRenderer[0];
  488. BufferManager.instance.ReturnBuffer(GetInstanceID());
  489. m_IsSpriteSkinActiveForDeform.DisposeIfCreated();
  490. m_PerSkinJobData.DisposeIfCreated();
  491. m_SpriteSkinData.DisposeIfCreated();
  492. m_Buffers.DisposeIfCreated();
  493. m_BufferSizes.DisposeIfCreated();
  494. m_BoneLookupData.DisposeIfCreated();
  495. m_VertexLookupData.DisposeIfCreated();
  496. m_SkinBatchArray.DisposeIfCreated();
  497. m_FinalBoneTransforms.DisposeIfCreated();
  498. m_BoundsData.DisposeIfCreated();
  499. if (m_Helper != null)
  500. {
  501. m_Helper.GetComponent<SpriteSkinUpdateHelper>().onDestroyingComponent -= OnHelperDestroyed;
  502. GameObject.DestroyImmediate(m_Helper);
  503. }
  504. m_LocalToWorldTransformAccessJob.Destroy();
  505. m_WorldToLocalTransformAccessJob.Destroy();
  506. }
  507. internal unsafe void LateUpdate()
  508. {
  509. foreach (var ss in m_SpriteSkinLateUpdate)
  510. {
  511. if(ss != null)
  512. ss.OnLateUpdate();
  513. }
  514. var count = m_SpriteSkins.Count;
  515. if (count == 0)
  516. return;
  517. Profiling.prepareData.Begin();
  518. Assert.AreEqual(m_IsSpriteSkinActiveForDeform.Length, count);
  519. Assert.AreEqual(m_PerSkinJobData.Length, count);
  520. Assert.AreEqual(m_SpriteSkinData.Length, count);
  521. Assert.AreEqual(m_BoundsData.Length, count);
  522. Assert.AreEqual(m_Buffers.Length, count);
  523. Assert.AreEqual(m_BufferSizes.Length, count);
  524. Assert.AreEqual(m_SpriteRenderers.Length, count);
  525. using (Profiling.validateSpriteSkinData.Auto())
  526. {
  527. for (var i = 0; i < m_SpriteSkins.Count; ++i)
  528. {
  529. var spriteSkin = m_SpriteSkins[i];
  530. m_IsSpriteSkinActiveForDeform[i] = spriteSkin.BatchValidate();
  531. if (m_IsSpriteSkinActiveForDeform[i] && spriteSkin.NeedUpdateCompositeCache())
  532. {
  533. CopyToSpriteSkinData(i);
  534. }
  535. }
  536. }
  537. Profiling.transformAccessJob.Begin();
  538. var localToWorldJobHandle = m_LocalToWorldTransformAccessJob.StartLocalToWorldJob();
  539. var worldToLocalJobHandle = m_WorldToLocalTransformAccessJob.StartWorldToLocalJob();
  540. Profiling.transformAccessJob.End();
  541. using (Profiling.getSpriteSkinBatchData.Auto())
  542. {
  543. NativeArrayHelpers.ResizeIfNeeded(ref m_SkinBatchArray, 1);
  544. var fillPerSkinJobSingleThread = new FillPerSkinJobSingleThread()
  545. {
  546. isSpriteSkinValidForDeformArray = m_IsSpriteSkinActiveForDeform,
  547. combinedSkinBatchArray = m_SkinBatchArray,
  548. spriteSkinDataArray = m_SpriteSkinData,
  549. perSkinJobDataArray = m_PerSkinJobData,
  550. };
  551. fillPerSkinJobSingleThread.Run();
  552. }
  553. Profiling.prepareData.End();
  554. var skinBatch = m_SkinBatchArray[0];
  555. var batchCount = m_SpriteSkinData.Length;
  556. var vertexBufferSize = skinBatch.deformVerticesStartPos;
  557. if (vertexBufferSize <= 0)
  558. {
  559. localToWorldJobHandle.Complete();
  560. worldToLocalJobHandle.Complete();
  561. DeactivateDeformableBuffers();
  562. return;
  563. }
  564. using (Profiling.resizeBuffers.Auto())
  565. {
  566. m_DeformedVerticesBuffer = BufferManager.instance.GetBuffer(GetInstanceID(), vertexBufferSize);
  567. NativeArrayHelpers.ResizeIfNeeded(ref m_FinalBoneTransforms, skinBatch.bindPosesIndex.y);
  568. NativeArrayHelpers.ResizeIfNeeded(ref m_BoneLookupData, skinBatch.bindPosesIndex.y);
  569. NativeArrayHelpers.ResizeIfNeeded(ref m_VertexLookupData, skinBatch.verticesIndex.y);
  570. }
  571. Profiling.prepare.Begin();
  572. var prepareJob = new PrepareDeformJob
  573. {
  574. batchDataSize = batchCount,
  575. perSkinJobData = m_PerSkinJobData,
  576. boneLookupData = m_BoneLookupData,
  577. vertexLookupData = m_VertexLookupData
  578. };
  579. var jobHandle = prepareJob.Schedule();
  580. Profiling.prepare.End();
  581. Profiling.scheduleJobs.Begin();
  582. var boneJobBatched = new BoneDeformBatchedJob()
  583. {
  584. boneTransform = m_LocalToWorldTransformAccessJob.transformMatrix,
  585. rootTransform = m_WorldToLocalTransformAccessJob.transformMatrix,
  586. spriteSkinData = m_SpriteSkinData,
  587. boneLookupData = m_BoneLookupData,
  588. finalBoneTransforms = m_FinalBoneTransforms,
  589. rootTransformIndex = m_WorldToLocalTransformAccessJob.transformData,
  590. boneTransformIndex = m_LocalToWorldTransformAccessJob.transformData
  591. };
  592. jobHandle = JobHandle.CombineDependencies(localToWorldJobHandle, worldToLocalJobHandle, jobHandle);
  593. jobHandle = boneJobBatched.Schedule(skinBatch.bindPosesIndex.y, 8, jobHandle);
  594. var skinJobBatched = new SkinDeformBatchedJob()
  595. {
  596. vertices = m_DeformedVerticesBuffer.array,
  597. vertexLookupData = m_VertexLookupData,
  598. spriteSkinData = m_SpriteSkinData,
  599. perSkinJobData = m_PerSkinJobData,
  600. finalBoneTransforms = m_FinalBoneTransforms,
  601. };
  602. m_DeformJobHandle = skinJobBatched.Schedule(skinBatch.verticesIndex.y, 16, jobHandle);
  603. var copySpriteRendererBuffersJob = new CopySpriteRendererBuffersJob()
  604. {
  605. isSpriteSkinValidForDeformArray = m_IsSpriteSkinActiveForDeform,
  606. spriteSkinData = m_SpriteSkinData,
  607. ptrVertices = (IntPtr) NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(m_DeformedVerticesBuffer.array),
  608. buffers = m_Buffers,
  609. bufferSizes = m_BufferSizes,
  610. };
  611. m_CopyJobHandle = copySpriteRendererBuffersJob.Schedule(batchCount, 16, jobHandle);
  612. var updateBoundJob = new CalculateSpriteSkinAABBJob
  613. {
  614. vertices = m_DeformedVerticesBuffer.array,
  615. isSpriteSkinValidForDeformArray = m_IsSpriteSkinActiveForDeform,
  616. spriteSkinData = m_SpriteSkinData,
  617. bounds = m_BoundsData,
  618. };
  619. m_BoundJobHandle = updateBoundJob.Schedule(batchCount, 4, m_DeformJobHandle);
  620. Profiling.scheduleJobs.End();
  621. JobHandle.ScheduleBatchedJobs();
  622. jobHandle = JobHandle.CombineDependencies(m_BoundJobHandle, m_CopyJobHandle);
  623. jobHandle.Complete();
  624. using (Profiling.setBatchDeformableBufferAndLocalAABB.Auto())
  625. {
  626. InternalEngineBridge.SetBatchDeformableBufferAndLocalAABBArray(m_SpriteRenderers, m_Buffers, m_BufferSizes, m_BoundsData);
  627. }
  628. DeactivateDeformableBuffers();
  629. }
  630. void DeactivateDeformableBuffers()
  631. {
  632. using (Profiling.deactivateDeformableBuffer.Auto())
  633. {
  634. for (var i = 0; i < m_IsSpriteSkinActiveForDeform.Length; ++i)
  635. {
  636. if (m_IsSpriteSkinActiveForDeform[i] || InternalEngineBridge.IsUsingDeformableBuffer(m_SpriteRenderers[i], IntPtr.Zero))
  637. continue;
  638. m_SpriteRenderers[i].DeactivateDeformableBuffer();
  639. }
  640. }
  641. }
  642. internal bool HasDeformableBufferForSprite(int dataIndex)
  643. {
  644. if (dataIndex < 0 && m_IsSpriteSkinActiveForDeform.Length >= dataIndex)
  645. throw new InvalidOperationException("Invalid index for deformable buffer");
  646. return m_IsSpriteSkinActiveForDeform[dataIndex];
  647. }
  648. internal unsafe NativeArray<byte> GetDeformableBufferForSprite(int dataIndex)
  649. {
  650. if (dataIndex < 0 && m_SpriteSkinData.Length >= dataIndex)
  651. throw new InvalidOperationException("Invalid index for deformable buffer");
  652. if (!m_DeformJobHandle.IsCompleted)
  653. m_DeformJobHandle.Complete();
  654. var skinData = m_SpriteSkinData[dataIndex];
  655. if (skinData.deformVerticesStartPos < 0)
  656. throw new InvalidOperationException("There are no currently deformed vertices.");
  657. var vertexBufferLength = skinData.spriteVertexCount * skinData.spriteVertexStreamSize;
  658. byte* ptrVertices = (byte*)m_DeformedVerticesBuffer.array.GetUnsafeReadOnlyPtr();
  659. ptrVertices += skinData.deformVerticesStartPos;
  660. var buffer = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<byte>(ptrVertices, vertexBufferLength, Allocator.None);
  661. #if ENABLE_UNITY_COLLECTIONS_CHECKS
  662. NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref buffer, NativeArrayUnsafeUtility.GetAtomicSafetyHandle(m_DeformedVerticesBuffer.array));
  663. #endif
  664. return buffer;
  665. }
  666. // Code for tests
  667. #region Code For Tests
  668. internal string GetDebugLog()
  669. {
  670. var log = "";
  671. log = "====SpriteSkinLateUpdate===\n";
  672. log += "Count: " + m_SpriteSkinLateUpdate.Count +"\n";
  673. foreach (var ss in m_SpriteSkinLateUpdate)
  674. {
  675. log += ss == null ? "null" : ss.name;
  676. log += "\n";
  677. }
  678. log += "\n";
  679. log += "===SpriteSkinBatch===\n";
  680. log += "Count: " + m_SpriteSkins.Count +"\n";
  681. foreach (var ss in m_SpriteSkins)
  682. {
  683. log += ss == null ? "null" : ss.name;
  684. log += "\n";
  685. }
  686. log += "===LocalToWorldTransformAccessJob===\n";
  687. log += m_LocalToWorldTransformAccessJob.GetDebugLog();
  688. log += "\n";
  689. log += "===WorldToLocalTransformAccessJob===\n";
  690. log += "\n";
  691. log += m_WorldToLocalTransformAccessJob.GetDebugLog();
  692. return log;
  693. }
  694. internal SpriteSkin[] GetSpriteSkins()
  695. {
  696. return m_SpriteSkins.ToArray();
  697. }
  698. internal TransformAccessJob GetWorldToLocalTransformAccessJob()
  699. {
  700. return m_WorldToLocalTransformAccessJob;
  701. }
  702. internal TransformAccessJob GetLocalToWorldTransformAccessJob()
  703. {
  704. return m_LocalToWorldTransformAccessJob;
  705. }
  706. #endregion
  707. }
  708. }
  709. #endif