Ingen beskrivning
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.

SpriteSkin.cs 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. #pragma warning disable 0168 // variable declared but not used.
  2. using System;
  3. using System.Collections.Generic;
  4. using UnityEngine.Scripting;
  5. using UnityEngine.U2D.Common;
  6. using Unity.Collections;
  7. using Unity.Collections.LowLevel.Unsafe;
  8. using Unity.Profiling;
  9. using UnityEngine.Rendering;
  10. using UnityEngine.Scripting.APIUpdating;
  11. namespace UnityEngine.U2D.Animation
  12. {
  13. /// <summary>
  14. /// Represents vertex position.
  15. /// </summary>
  16. internal struct PositionVertex
  17. {
  18. /// <summary>
  19. /// Vertex position.
  20. /// </summary>
  21. public Vector3 position;
  22. }
  23. /// <summary>
  24. /// Represents vertex position and tangent.
  25. /// </summary>
  26. internal struct PositionTangentVertex
  27. {
  28. /// <summary>
  29. /// Vertex position.
  30. /// </summary>
  31. public Vector3 position;
  32. /// <summary>
  33. /// Vertex tangent.
  34. /// </summary>
  35. public Vector4 tangent;
  36. }
  37. /// <summary>
  38. /// Deforms the Sprite that is currently assigned to the SpriteRenderer in the same GameObject.
  39. /// </summary>
  40. [Preserve]
  41. [ExecuteInEditMode]
  42. [DefaultExecutionOrder(-1)]
  43. [DisallowMultipleComponent]
  44. [RequireComponent(typeof(SpriteRenderer))]
  45. [AddComponentMenu("2D Animation/Sprite Skin")]
  46. [IconAttribute(IconUtility.IconPath + "Animation.SpriteSkin.png")]
  47. [MovedFrom("UnityEngine.U2D.Experimental.Animation")]
  48. [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.animation@9.0/manual/SpriteSkin.html")]
  49. public sealed class SpriteSkin : MonoBehaviour, IPreviewable, ISerializationCallbackReceiver
  50. {
  51. static class Profiling
  52. {
  53. public static readonly ProfilerMarker cacheCurrentSprite = new ProfilerMarker("SpriteSkin.CacheCurrentSprite");
  54. public static readonly ProfilerMarker cacheHierarchy = new ProfilerMarker("SpriteSkin.CacheHierarchy");
  55. public static readonly ProfilerMarker getSpriteBonesTransformFromGuid = new ProfilerMarker("SpriteSkin.GetSpriteBoneTransformsFromGuid");
  56. public static readonly ProfilerMarker getSpriteBonesTransformFromPath = new ProfilerMarker("SpriteSkin.GetSpriteBoneTransformsFromPath");
  57. }
  58. struct TransformData
  59. {
  60. public string fullName;
  61. public Transform transform;
  62. }
  63. [SerializeField]
  64. Transform m_RootBone;
  65. [SerializeField]
  66. Transform[] m_BoneTransforms = new Transform[0];
  67. [SerializeField]
  68. Bounds m_Bounds;
  69. [SerializeField]
  70. bool m_AlwaysUpdate = true;
  71. [SerializeField]
  72. bool m_AutoRebind = false;
  73. // The deformed m_SpriteVertices stores all 'HOT' channels only in single-stream and essentially depends on Sprite Asset data.
  74. // The order of storage if present is POSITION, NORMALS, TANGENTS.
  75. NativeByteArray m_DeformedVertices;
  76. int m_CurrentDeformVerticesLength = 0;
  77. SpriteRenderer m_SpriteRenderer;
  78. int m_CurrentDeformSprite = 0;
  79. bool m_ForceSkinning;
  80. bool m_IsValid = false;
  81. int m_TransformsHash = 0;
  82. int m_TransformId;
  83. NativeArray<int> m_BoneTransformId;
  84. int m_RootBoneTransformId;
  85. NativeCustomSlice<Vector2> m_SpriteUVs;
  86. NativeCustomSlice<Vector3> m_SpriteVertices;
  87. NativeCustomSlice<Vector4> m_SpriteTangents;
  88. NativeCustomSlice<BoneWeight> m_SpriteBoneWeights;
  89. NativeCustomSlice<Matrix4x4> m_SpriteBindPoses;
  90. NativeCustomSlice<int> m_BoneTransformIdNativeSlice;
  91. bool m_SpriteHasTangents;
  92. int m_SpriteVertexStreamSize;
  93. int m_SpriteVertexCount;
  94. int m_SpriteTangentVertexOffset;
  95. int m_DataIndex = -1;
  96. bool m_BoneCacheUpdateToDate = false;
  97. Dictionary<int, List<TransformData>> m_HierarchyCache = new Dictionary<int, List<TransformData>>();
  98. internal Sprite sprite => spriteRenderer.sprite;
  99. internal SpriteRenderer spriteRenderer => m_SpriteRenderer;
  100. internal NativeCustomSlice<BoneWeight> spriteBoneWeights => m_SpriteBoneWeights;
  101. /// <summary>
  102. /// Get and set the Auto Rebind property.
  103. /// When enabled, Sprite Skin attempts to automatically locate the Transform that is needed for the current Sprite assigned to the Sprite Renderer.
  104. /// </summary>
  105. public bool autoRebind
  106. {
  107. get => m_AutoRebind;
  108. set
  109. {
  110. m_AutoRebind = value;
  111. CacheHierarchy();
  112. CacheCurrentSprite(m_AutoRebind);
  113. }
  114. }
  115. /// <summary>
  116. /// Returns the Transform Components that is used for deformation.
  117. /// Do not modify elements of the returned array.
  118. /// </summary>
  119. /// <returns>An array of Transform Components.</returns>
  120. public Transform[] boneTransforms
  121. {
  122. get => m_BoneTransforms;
  123. internal set
  124. {
  125. m_BoneTransforms = value;
  126. CacheValidFlag();
  127. OnBoneTransformChanged();
  128. }
  129. }
  130. /// <summary>
  131. /// Returns the Transform Component that represents the root bone for deformation.
  132. /// </summary>
  133. /// <returns>A Transform Component.</returns>
  134. public Transform rootBone
  135. {
  136. get => m_RootBone;
  137. internal set
  138. {
  139. m_RootBone = value;
  140. CacheValidFlag();
  141. CacheHierarchy();
  142. OnRootBoneTransformChanged();
  143. }
  144. }
  145. internal Bounds bounds
  146. {
  147. get => m_Bounds;
  148. set => m_Bounds = value;
  149. }
  150. /// <summary>
  151. /// Determines if the SpriteSkin executes even if the associated
  152. /// SpriteRenderer has been culled from view.
  153. /// </summary>
  154. public bool alwaysUpdate
  155. {
  156. get => m_AlwaysUpdate;
  157. set => m_AlwaysUpdate = value;
  158. }
  159. internal bool isValid => this.Validate() == SpriteSkinValidationResult.Ready;
  160. #if UNITY_EDITOR
  161. internal static Events.UnityEvent onDrawGizmos = new Events.UnityEvent();
  162. void OnDrawGizmos()
  163. { onDrawGizmos.Invoke(); }
  164. internal bool ignoreNextSpriteChange
  165. {
  166. get;
  167. set;
  168. } = true;
  169. #endif
  170. int GetSpriteInstanceID()
  171. {
  172. return sprite != null ? sprite.GetInstanceID() : 0;
  173. }
  174. internal void Awake()
  175. {
  176. m_SpriteRenderer = GetComponent<SpriteRenderer>();
  177. }
  178. void OnEnable()
  179. {
  180. Awake();
  181. m_TransformsHash = 0;
  182. CacheCurrentSprite(false);
  183. if (m_HierarchyCache.Count == 0)
  184. CacheHierarchy();
  185. OnEnableBatch();
  186. }
  187. void OnEnableBatch()
  188. {
  189. m_TransformId = gameObject.transform.GetInstanceID();
  190. UpdateSpriteDeform();
  191. CacheBoneTransformIds(true);
  192. SpriteSkinComposite.instance.AddSpriteSkin(this);
  193. }
  194. void OnResetBatch()
  195. {
  196. CacheBoneTransformIds(true);
  197. SpriteSkinComposite.instance.CopyToSpriteSkinData(this);
  198. }
  199. void OnDisableBatch()
  200. {
  201. RemoveTransformFromSpriteSkinComposite();
  202. SpriteSkinComposite.instance.RemoveSpriteSkin(this);
  203. }
  204. void OnBoneTransformChanged()
  205. {
  206. if (enabled)
  207. CacheBoneTransformIds(true);
  208. }
  209. void OnRootBoneTransformChanged()
  210. {
  211. if (enabled)
  212. CacheBoneTransformIds(true);
  213. }
  214. /// <summary>
  215. /// Called before object is serialized.
  216. /// </summary>
  217. public void OnBeforeSerialize()
  218. {
  219. OnBeforeSerializeBatch();
  220. }
  221. /// <summary>
  222. /// Called after object is deserialized.
  223. /// </summary>
  224. public void OnAfterDeserialize()
  225. {
  226. OnAfterSerializeBatch();
  227. }
  228. void OnBeforeSerializeBatch() {}
  229. void OnAfterSerializeBatch()
  230. {
  231. #if UNITY_EDITOR
  232. m_BoneCacheUpdateToDate = false;
  233. #endif
  234. }
  235. internal void OnEditorEnable()
  236. {
  237. Awake();
  238. }
  239. void CacheValidFlag()
  240. {
  241. m_IsValid = isValid;
  242. if(!m_IsValid)
  243. DeactivateSkinning();
  244. }
  245. internal bool BatchValidate()
  246. {
  247. CacheBoneTransformIds();
  248. CacheCurrentSprite(m_AutoRebind);
  249. var hasSprite = m_CurrentDeformSprite != 0;
  250. return (m_IsValid && hasSprite && spriteRenderer.enabled && (alwaysUpdate || spriteRenderer.isVisible));
  251. }
  252. void Reset()
  253. {
  254. Awake();
  255. if (isActiveAndEnabled)
  256. {
  257. CacheValidFlag();
  258. OnResetBatch();
  259. }
  260. }
  261. void CacheBoneTransformIds(bool forceUpdate = false)
  262. {
  263. if (!m_BoneCacheUpdateToDate || forceUpdate)
  264. {
  265. SpriteSkinComposite.instance.RemoveTransformById(m_RootBoneTransformId);
  266. if (rootBone != null)
  267. {
  268. m_RootBoneTransformId = rootBone.GetInstanceID();
  269. if (enabled)
  270. SpriteSkinComposite.instance.AddSpriteSkinRootBoneTransform(this);
  271. }
  272. else
  273. m_RootBoneTransformId = 0;
  274. if (boneTransforms != null)
  275. {
  276. var boneCount = 0;
  277. for (var i = 0; i < boneTransforms.Length; ++i)
  278. {
  279. if (boneTransforms[i] != null)
  280. ++boneCount;
  281. }
  282. if (m_BoneTransformId.IsCreated)
  283. {
  284. for (var i = 0; i < m_BoneTransformId.Length; ++i)
  285. SpriteSkinComposite.instance.RemoveTransformById(m_BoneTransformId[i]);
  286. NativeArrayHelpers.ResizeIfNeeded(ref m_BoneTransformId, boneCount);
  287. }
  288. else
  289. {
  290. m_BoneTransformId = new NativeArray<int>(boneCount, Allocator.Persistent);
  291. }
  292. m_BoneTransformIdNativeSlice = new NativeCustomSlice<int>(m_BoneTransformId);
  293. for (int i = 0, j = 0; i < boneTransforms.Length; ++i)
  294. {
  295. if (boneTransforms[i] != null)
  296. {
  297. m_BoneTransformId[j] = boneTransforms[i].GetInstanceID();
  298. ++j;
  299. }
  300. }
  301. if (enabled)
  302. {
  303. SpriteSkinComposite.instance.AddSpriteSkinBoneTransform(this);
  304. }
  305. }
  306. else
  307. {
  308. if (m_BoneTransformId.IsCreated)
  309. NativeArrayHelpers.ResizeIfNeeded(ref m_BoneTransformId, 0);
  310. else
  311. m_BoneTransformId = new NativeArray<int>(0, Allocator.Persistent);
  312. }
  313. CacheValidFlag();
  314. m_BoneCacheUpdateToDate = true;
  315. SpriteSkinComposite.instance.CopyToSpriteSkinData(this);
  316. }
  317. }
  318. void RemoveTransformFromSpriteSkinComposite()
  319. {
  320. if (m_BoneTransformId.IsCreated)
  321. {
  322. for (var i = 0; i < m_BoneTransformId.Length; ++i)
  323. SpriteSkinComposite.instance.RemoveTransformById(m_BoneTransformId[i]);
  324. m_BoneTransformId.Dispose();
  325. }
  326. SpriteSkinComposite.instance.RemoveTransformById(m_RootBoneTransformId);
  327. m_RootBoneTransformId = -1;
  328. m_BoneCacheUpdateToDate = false;
  329. }
  330. internal NativeByteArray GetDeformedVertices(int spriteVertexCount)
  331. {
  332. if (sprite != null)
  333. {
  334. if (m_CurrentDeformVerticesLength != spriteVertexCount)
  335. {
  336. m_TransformsHash = 0;
  337. m_CurrentDeformVerticesLength = spriteVertexCount;
  338. }
  339. }
  340. else
  341. {
  342. m_CurrentDeformVerticesLength = 0;
  343. }
  344. m_DeformedVertices = BufferManager.instance.GetBuffer(GetInstanceID(), m_CurrentDeformVerticesLength);
  345. return m_DeformedVertices;
  346. }
  347. /// <summary>
  348. /// Returns whether this SpriteSkin has currently deformed vertices.
  349. /// </summary>
  350. /// <returns>Returns true if this SpriteSkin has currently deformed vertices. Returns false otherwise.</returns>
  351. public bool HasCurrentDeformedVertices()
  352. {
  353. if (!m_IsValid)
  354. return false;
  355. return m_DataIndex >= 0 && SpriteSkinComposite.instance.HasDeformableBufferForSprite(m_DataIndex);
  356. }
  357. /// <summary>
  358. /// Gets a byte array to the currently deformed vertices for this SpriteSkin.
  359. /// </summary>
  360. /// <returns>Returns a reference to the currently deformed vertices. This is valid only for this calling frame.</returns>
  361. /// <exception cref="InvalidOperationException">
  362. /// Thrown when there are no currently deformed vertices.
  363. /// HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
  364. /// </exception>
  365. internal NativeArray<byte> GetCurrentDeformedVertices()
  366. {
  367. if (!m_IsValid)
  368. throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
  369. if (m_DataIndex < 0)
  370. {
  371. throw new InvalidOperationException("There are no currently deformed vertices.");
  372. }
  373. return SpriteSkinComposite.instance.GetDeformableBufferForSprite(m_DataIndex);
  374. }
  375. /// <summary>
  376. /// Gets an array of currently deformed position vertices for this SpriteSkin.
  377. /// </summary>
  378. /// <returns>Returns a reference to the currently deformed vertices. This is valid only for this calling frame.</returns>
  379. /// <exception cref="InvalidOperationException">
  380. /// Thrown when there are no currently deformed vertices or if the deformed vertices does not contain only
  381. /// position data. HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
  382. /// </exception>
  383. internal NativeSlice<PositionVertex> GetCurrentDeformedVertexPositions()
  384. {
  385. if (!m_IsValid)
  386. throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
  387. if (sprite.HasVertexAttribute(VertexAttribute.Tangent))
  388. throw new InvalidOperationException("This SpriteSkin has deformed tangents");
  389. if (!sprite.HasVertexAttribute(VertexAttribute.Position))
  390. throw new InvalidOperationException("This SpriteSkin does not have deformed positions.");
  391. var deformedBuffer = GetCurrentDeformedVertices();
  392. return deformedBuffer.Slice().SliceConvert<PositionVertex>();
  393. }
  394. /// <summary>
  395. /// Gets an array of currently deformed position and tangent vertices for this SpriteSkin.
  396. /// </summary>
  397. /// <returns>
  398. /// Returns a reference to the currently deformed position and tangent vertices. This is valid only for this calling frame.
  399. /// </returns>
  400. /// <exception cref="InvalidOperationException">
  401. /// Thrown when there are no currently deformed vertices or if the deformed vertices does not contain only
  402. /// position and tangent data. HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
  403. /// </exception>
  404. internal NativeSlice<PositionTangentVertex> GetCurrentDeformedVertexPositionsAndTangents()
  405. {
  406. if (!m_IsValid)
  407. throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
  408. if (!sprite.HasVertexAttribute(VertexAttribute.Tangent))
  409. throw new InvalidOperationException("This SpriteSkin does not have deformed tangents");
  410. if (!sprite.HasVertexAttribute(VertexAttribute.Position))
  411. throw new InvalidOperationException("This SpriteSkin does not have deformed positions.");
  412. var deformedBuffer = GetCurrentDeformedVertices();
  413. return deformedBuffer.Slice().SliceConvert<PositionTangentVertex>();
  414. }
  415. /// <summary>
  416. /// Gets an enumerable to iterate through all deformed vertex positions of this SpriteSkin.
  417. /// </summary>
  418. /// <returns>Returns an IEnumerable to deformed vertex positions.</returns>
  419. /// <exception cref="InvalidOperationException">
  420. /// Thrown when there is no vertex positions or deformed vertices.
  421. /// HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
  422. /// </exception>
  423. public IEnumerable<Vector3> GetDeformedVertexPositionData()
  424. {
  425. if (!m_IsValid)
  426. throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
  427. var hasPosition = sprite.HasVertexAttribute(VertexAttribute.Position);
  428. if (!hasPosition)
  429. throw new InvalidOperationException("Sprite does not have vertex position data.");
  430. var rawBuffer = GetCurrentDeformedVertices();
  431. var rawSlice = rawBuffer.Slice(sprite.GetVertexStreamOffset(VertexAttribute.Position));
  432. return new NativeCustomSliceEnumerator<Vector3>(rawSlice, sprite.GetVertexCount(), sprite.GetVertexStreamSize());
  433. }
  434. /// <summary>
  435. /// Gets an enumerable to iterate through all deformed vertex tangents of this SpriteSkin.
  436. /// </summary>
  437. /// <returns>Returns an IEnumerable to deformed vertex tangents.</returns>
  438. /// <exception cref="InvalidOperationException">
  439. /// Thrown when there is no vertex tangents or deformed vertices.
  440. /// HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
  441. /// </exception>
  442. public IEnumerable<Vector4> GetDeformedVertexTangentData()
  443. {
  444. if (!m_IsValid)
  445. throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
  446. var hasTangent = sprite.HasVertexAttribute(VertexAttribute.Tangent);
  447. if (!hasTangent)
  448. throw new InvalidOperationException("Sprite does not have vertex tangent data.");
  449. var rawBuffer = GetCurrentDeformedVertices();
  450. var rawSlice = rawBuffer.Slice(sprite.GetVertexStreamOffset(VertexAttribute.Tangent));
  451. return new NativeCustomSliceEnumerator<Vector4>(rawSlice, sprite.GetVertexCount(), sprite.GetVertexStreamSize());
  452. }
  453. void OnDisable()
  454. {
  455. DeactivateSkinning();
  456. BufferManager.instance.ReturnBuffer(GetInstanceID());
  457. OnDisableBatch();
  458. }
  459. /// <summary>
  460. /// Used by the animation clip preview window.
  461. /// Recommended to not use outside of this purpose.
  462. /// </summary>
  463. public void OnPreviewUpdate()
  464. {
  465. #if UNITY_EDITOR
  466. if(IsInGUIUpdateLoop())
  467. Deform();
  468. #endif
  469. }
  470. static bool IsInGUIUpdateLoop() => Event.current != null;
  471. void Deform()
  472. {
  473. CacheCurrentSprite(m_AutoRebind);
  474. if (isValid && this.enabled && (this.alwaysUpdate || this.spriteRenderer.isVisible))
  475. {
  476. var transformHash = SpriteSkinUtility.CalculateTransformHash(this);
  477. var spriteVertexCount = sprite.GetVertexStreamSize() * sprite.GetVertexCount();
  478. if (spriteVertexCount > 0 && m_TransformsHash != transformHash)
  479. {
  480. var inputVertices = GetDeformedVertices(spriteVertexCount);
  481. SpriteSkinUtility.Deform(sprite, gameObject.transform.worldToLocalMatrix, boneTransforms, inputVertices.array);
  482. SpriteSkinUtility.UpdateBounds(this, inputVertices.array);
  483. InternalEngineBridge.SetDeformableBuffer(spriteRenderer, inputVertices.array);
  484. m_TransformsHash = transformHash;
  485. m_CurrentDeformSprite = GetSpriteInstanceID();
  486. }
  487. }
  488. else if(!InternalEngineBridge.IsUsingDeformableBuffer(spriteRenderer, IntPtr.Zero))
  489. {
  490. DeactivateSkinning();
  491. }
  492. }
  493. void CacheCurrentSprite(bool rebind)
  494. {
  495. if (m_CurrentDeformSprite != GetSpriteInstanceID())
  496. {
  497. using (Profiling.cacheCurrentSprite.Auto())
  498. {
  499. DeactivateSkinning();
  500. m_CurrentDeformSprite = GetSpriteInstanceID();
  501. if (rebind && m_CurrentDeformSprite > 0 && rootBone != null)
  502. {
  503. if (!GetSpriteBonesTransforms(this, out var transforms))
  504. Debug.LogWarning($"Rebind failed for {name}. Could not find all bones required by the Sprite: {sprite.name}.");
  505. boneTransforms = transforms;
  506. }
  507. UpdateSpriteDeform();
  508. CacheValidFlag();
  509. m_TransformsHash = 0;
  510. }
  511. }
  512. }
  513. void UpdateSpriteDeform()
  514. {
  515. if (sprite == null)
  516. {
  517. m_SpriteUVs = NativeCustomSlice<Vector2>.Default();
  518. m_SpriteVertices = NativeCustomSlice<Vector3>.Default();
  519. m_SpriteTangents = NativeCustomSlice<Vector4>.Default();
  520. m_SpriteBoneWeights = NativeCustomSlice<BoneWeight>.Default();
  521. m_SpriteBindPoses = NativeCustomSlice<Matrix4x4>.Default();
  522. m_SpriteHasTangents = false;
  523. m_SpriteVertexStreamSize = 0;
  524. m_SpriteVertexCount = 0;
  525. m_SpriteTangentVertexOffset = 0;
  526. }
  527. else
  528. {
  529. m_SpriteUVs = new NativeCustomSlice<Vector2>(sprite.GetVertexAttribute<Vector2>(VertexAttribute.TexCoord0));
  530. m_SpriteVertices = new NativeCustomSlice<Vector3>(sprite.GetVertexAttribute<Vector3>(VertexAttribute.Position));
  531. m_SpriteTangents = new NativeCustomSlice<Vector4>(sprite.GetVertexAttribute<Vector4>(VertexAttribute.Tangent));
  532. m_SpriteBoneWeights = new NativeCustomSlice<BoneWeight>(sprite.GetVertexAttribute<BoneWeight>(VertexAttribute.BlendWeight));
  533. m_SpriteBindPoses = new NativeCustomSlice<Matrix4x4>(sprite.GetBindPoses());
  534. m_SpriteHasTangents = sprite.HasVertexAttribute(VertexAttribute.Tangent);
  535. m_SpriteVertexStreamSize = sprite.GetVertexStreamSize();
  536. m_SpriteVertexCount = sprite.GetVertexCount();
  537. m_SpriteTangentVertexOffset = sprite.GetVertexStreamOffset(VertexAttribute.Tangent);
  538. }
  539. SpriteSkinComposite.instance.CopyToSpriteSkinData(this);
  540. }
  541. internal void CopyToSpriteSkinData(ref SpriteSkinData data, int spriteSkinIndex)
  542. {
  543. CacheBoneTransformIds();
  544. CacheCurrentSprite(m_AutoRebind);
  545. data.vertices = m_SpriteVertices;
  546. data.boneWeights = m_SpriteBoneWeights;
  547. data.bindPoses = m_SpriteBindPoses;
  548. data.tangents = m_SpriteTangents;
  549. data.hasTangents = m_SpriteHasTangents;
  550. data.spriteVertexStreamSize = m_SpriteVertexStreamSize;
  551. data.spriteVertexCount = m_SpriteVertexCount;
  552. data.tangentVertexOffset = m_SpriteTangentVertexOffset;
  553. data.transformId = m_TransformId;
  554. data.boneTransformId = m_BoneTransformIdNativeSlice;
  555. m_DataIndex = spriteSkinIndex;
  556. }
  557. internal bool NeedUpdateCompositeCache()
  558. {
  559. unsafe
  560. {
  561. var iptr = new IntPtr(sprite.GetVertexAttribute<Vector2>(VertexAttribute.TexCoord0).GetUnsafeReadOnlyPtr());
  562. var rs = m_SpriteUVs.data != iptr;
  563. if (rs)
  564. {
  565. UpdateSpriteDeform();
  566. }
  567. return rs;
  568. }
  569. }
  570. void CacheHierarchy()
  571. {
  572. using (Profiling.cacheHierarchy.Auto())
  573. {
  574. m_HierarchyCache.Clear();
  575. if (rootBone == null || !m_AutoRebind)
  576. return;
  577. m_HierarchyCache.EnsureCapacity(rootBone.hierarchyCount);
  578. CacheChildren(rootBone, m_HierarchyCache);
  579. foreach (var entry in m_HierarchyCache)
  580. {
  581. if (entry.Value.Count == 1)
  582. continue;
  583. var count = entry.Value.Count;
  584. for (var i = 0; i < count; ++i)
  585. {
  586. var transformEntry = entry.Value[i];
  587. transformEntry.fullName = GenerateTransformPath(rootBone, transformEntry.transform);
  588. entry.Value[i] = transformEntry;
  589. }
  590. }
  591. }
  592. }
  593. static void CacheChildren(Transform current, Dictionary<int, List<TransformData>> cache)
  594. {
  595. var nameHash = current.name.GetHashCode();
  596. var entry = new TransformData()
  597. {
  598. fullName = String.Empty,
  599. transform = current
  600. };
  601. if (cache.ContainsKey(nameHash))
  602. cache[nameHash].Add(entry);
  603. else
  604. cache.Add(nameHash, new List<TransformData>(1) { entry });
  605. for (var i = 0; i < current.childCount; ++i)
  606. CacheChildren(current.GetChild(i), cache);
  607. }
  608. static string GenerateTransformPath(Transform rootBone, Transform child)
  609. {
  610. var path = child.name;
  611. if (child == rootBone)
  612. return path;
  613. var parent = child.parent;
  614. do
  615. {
  616. path = parent.name + "/" + path;
  617. parent = parent.parent;
  618. }
  619. while (parent != rootBone && parent != null);
  620. return path;
  621. }
  622. internal static bool GetSpriteBonesTransforms(SpriteSkin spriteSkin, out Transform[] outTransform)
  623. {
  624. var rootBone = spriteSkin.rootBone;
  625. var spriteBones = spriteSkin.sprite.GetBones();
  626. if(rootBone == null)
  627. throw new ArgumentException("rootBone parameter cannot be null");
  628. if(spriteBones == null)
  629. throw new ArgumentException("spriteBones parameter cannot be null");
  630. outTransform = new Transform[spriteBones.Length];
  631. var boneObjects = rootBone.GetComponentsInChildren<Bone>();
  632. if (boneObjects != null && boneObjects.Length >= spriteBones.Length)
  633. {
  634. using (Profiling.getSpriteBonesTransformFromGuid.Auto())
  635. {
  636. var i = 0;
  637. for (; i < spriteBones.Length; ++i)
  638. {
  639. var boneHash = spriteBones[i].guid;
  640. var boneTransform = Array.Find(boneObjects, x => (x.guid == boneHash));
  641. if (boneTransform == null)
  642. break;
  643. outTransform[i] = boneTransform.transform;
  644. }
  645. if (i >= spriteBones.Length)
  646. return true;
  647. }
  648. }
  649. var hierarchyCache = spriteSkin.m_HierarchyCache;
  650. if (hierarchyCache.Count == 0)
  651. spriteSkin.CacheHierarchy();
  652. // If unable to successfully map via guid, fall back to path
  653. return GetSpriteBonesTransformFromPath(spriteBones, hierarchyCache, outTransform);
  654. }
  655. static bool GetSpriteBonesTransformFromPath(SpriteBone[] spriteBones, Dictionary<int, List<TransformData>> hierarchyCache, Transform[] outNewBoneTransform)
  656. {
  657. using (Profiling.getSpriteBonesTransformFromPath.Auto())
  658. {
  659. string[] bonePath = null;
  660. var foundBones = true;
  661. for (var i = 0; i < spriteBones.Length; ++i)
  662. {
  663. var nameHash = spriteBones[i].name.GetHashCode();
  664. if (!hierarchyCache.TryGetValue(nameHash, out var children))
  665. {
  666. outNewBoneTransform[i] = null;
  667. foundBones = false;
  668. continue;
  669. }
  670. if (children.Count == 1)
  671. outNewBoneTransform[i] = children[0].transform;
  672. else
  673. {
  674. if (bonePath == null)
  675. bonePath = new string[spriteBones.Length];
  676. if (bonePath[i] == null)
  677. CalculateBoneTransformsPath(i, spriteBones, bonePath);
  678. var m = 0;
  679. for (; m < children.Count; ++m)
  680. {
  681. if (children[m].fullName.Contains(bonePath[i]))
  682. {
  683. outNewBoneTransform[i] = children[m].transform;
  684. break;
  685. }
  686. }
  687. if (m >= children.Count)
  688. {
  689. outNewBoneTransform[i] = null;
  690. foundBones = false;
  691. }
  692. }
  693. }
  694. return foundBones;
  695. }
  696. }
  697. static void CalculateBoneTransformsPath(int index, SpriteBone[] spriteBones, string[] paths)
  698. {
  699. var spriteBone = spriteBones[index];
  700. var parentId = spriteBone.parentId;
  701. var bonePath = spriteBone.name;
  702. if (parentId != -1)
  703. {
  704. if (paths[parentId] == null)
  705. CalculateBoneTransformsPath(spriteBone.parentId, spriteBones, paths);
  706. paths[index] = $"{paths[parentId]}/{bonePath}";
  707. }
  708. else
  709. paths[index] = bonePath;
  710. }
  711. internal void DeactivateSkinning()
  712. {
  713. var currentSprite = spriteRenderer.sprite;
  714. if (currentSprite != null)
  715. InternalEngineBridge.SetLocalAABB(spriteRenderer, currentSprite.bounds);
  716. spriteRenderer.DeactivateDeformableBuffer();
  717. m_TransformsHash = 0;
  718. }
  719. internal void ResetSprite()
  720. {
  721. m_CurrentDeformSprite = 0;
  722. CacheValidFlag();
  723. }
  724. }
  725. }