暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960
  1. #pragma warning disable 0168 // variable declared but not used.
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Runtime.CompilerServices;
  5. using UnityEngine.Scripting;
  6. using UnityEngine.U2D.Common;
  7. using Unity.Collections;
  8. using Unity.Collections.LowLevel.Unsafe;
  9. using Unity.Profiling;
  10. using UnityEngine.Rendering;
  11. using UnityEngine.Scripting.APIUpdating;
  12. namespace UnityEngine.U2D.Animation
  13. {
  14. /// <summary>
  15. /// Represents vertex position.
  16. /// </summary>
  17. internal struct PositionVertex
  18. {
  19. /// <summary>
  20. /// Vertex position.
  21. /// </summary>
  22. public Vector3 position;
  23. }
  24. /// <summary>
  25. /// Represents vertex position and tangent.
  26. /// </summary>
  27. internal struct PositionTangentVertex
  28. {
  29. /// <summary>
  30. /// Vertex position.
  31. /// </summary>
  32. public Vector3 position;
  33. /// <summary>
  34. /// Vertex tangent.
  35. /// </summary>
  36. public Vector4 tangent;
  37. }
  38. /// <summary>
  39. /// The state of the Sprite Skin.
  40. /// </summary>
  41. public enum SpriteSkinState
  42. {
  43. /// <summary>
  44. /// Sprite Renderer doesn't contain a sprite.
  45. /// </summary>
  46. SpriteNotFound,
  47. /// <summary>
  48. /// Sprite referenced in the Sprite Renderer doesn't have skinning information.
  49. /// </summary>
  50. SpriteHasNoSkinningInformation,
  51. /// <summary>
  52. /// Sprite referenced in the Sprite Renderer doesn't have weights.
  53. /// </summary>
  54. SpriteHasNoWeights,
  55. /// <summary>
  56. /// Root transform is not assigned.
  57. /// </summary>
  58. RootTransformNotFound,
  59. /// <summary>
  60. /// Bone transform array is not assigned.
  61. /// </summary>
  62. InvalidTransformArray,
  63. /// <summary>
  64. /// Bone transform array has incorrect length.
  65. /// </summary>
  66. InvalidTransformArrayLength,
  67. /// <summary>
  68. /// One or more bone transforms is not assigned.
  69. /// </summary>
  70. TransformArrayContainsNull,
  71. /// <summary>
  72. /// Bone weights are invalid.
  73. /// </summary>
  74. InvalidBoneWeights,
  75. /// <summary>
  76. /// Sprite Skin is ready for deformation.
  77. /// </summary>
  78. Ready
  79. }
  80. /// <summary>
  81. /// Deforms the Sprite that is currently assigned to the SpriteRenderer in the same GameObject.
  82. /// </summary>
  83. [Preserve]
  84. [ExecuteInEditMode]
  85. [DefaultExecutionOrder(UpdateOrder.spriteSkinUpdateOrder)]
  86. [DisallowMultipleComponent]
  87. [RequireComponent(typeof(SpriteRenderer))]
  88. [AddComponentMenu("2D Animation/Sprite Skin")]
  89. [IconAttribute(IconUtility.IconPath + "Animation.SpriteSkin.png")]
  90. [MovedFrom("UnityEngine.U2D.Experimental.Animation")]
  91. [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.animation@latest/index.html?subfolder=/manual/SpriteSkin.html")]
  92. public sealed class SpriteSkin : MonoBehaviour, IPreviewable, ISerializationCallbackReceiver
  93. {
  94. internal static class Profiling
  95. {
  96. public static readonly ProfilerMarker cacheCurrentSprite = new ProfilerMarker("SpriteSkin.CacheCurrentSprite");
  97. public static readonly ProfilerMarker cacheHierarchy = new ProfilerMarker("SpriteSkin.CacheHierarchy");
  98. public static readonly ProfilerMarker getSpriteBonesTransformFromGuid = new ProfilerMarker("SpriteSkin.GetSpriteBoneTransformsFromGuid");
  99. public static readonly ProfilerMarker getSpriteBonesTransformFromPath = new ProfilerMarker("SpriteSkin.GetSpriteBoneTransformsFromPath");
  100. }
  101. internal struct TransformData
  102. {
  103. public string fullName;
  104. public Transform transform;
  105. }
  106. [SerializeField]
  107. Transform m_RootBone;
  108. [SerializeField]
  109. Transform[] m_BoneTransforms = Array.Empty<Transform>();
  110. [SerializeField]
  111. Bounds m_Bounds;
  112. [SerializeField]
  113. bool m_AlwaysUpdate = true;
  114. [SerializeField]
  115. bool m_AutoRebind = false;
  116. // The deformed m_SpriteVertices stores all 'HOT' channels only in single-stream and essentially depends on Sprite Asset data.
  117. // The order of storage if present is POSITION, NORMALS, TANGENTS.
  118. NativeByteArray m_DeformedVertices;
  119. int m_CurrentDeformVerticesLength = 0;
  120. SpriteRenderer m_SpriteRenderer;
  121. int m_CurrentDeformSprite = 0;
  122. int m_SpriteId = -1;
  123. bool m_IsValid = false;
  124. SpriteSkinState m_State;
  125. int m_TransformsHash = 0;
  126. bool m_ForceCpuDeformation = false;
  127. int m_TransformId;
  128. NativeArray<int> m_BoneTransformId;
  129. int m_RootBoneTransformId;
  130. NativeCustomSlice<Vector2> m_SpriteUVs;
  131. NativeCustomSlice<Vector3> m_SpriteVertices;
  132. NativeCustomSlice<Vector4> m_SpriteTangents;
  133. NativeCustomSlice<BoneWeight> m_SpriteBoneWeights;
  134. NativeCustomSlice<Matrix4x4> m_SpriteBindPoses;
  135. NativeCustomSlice<int> m_BoneTransformIdNativeSlice;
  136. bool m_SpriteHasTangents;
  137. int m_SpriteVertexStreamSize;
  138. int m_SpriteVertexCount;
  139. int m_SpriteTangentVertexOffset;
  140. int m_DataIndex = -1;
  141. bool m_BoneCacheUpdateToDate = false;
  142. internal Dictionary<int, List<TransformData>> m_HierarchyCache = new Dictionary<int, List<TransformData>>();
  143. NativeArray<int> m_OutlineIndexCache;
  144. NativeArray<Vector3> m_StaticOutlineVertexCache;
  145. NativeArray<Vector3> m_DeformedOutlineVertexCache;
  146. int m_VertexDeformationHash = 0;
  147. Sprite m_Sprite;
  148. internal NativeArray<int> boneTransformId => m_BoneTransformId;
  149. internal int rootBoneTransformId => m_RootBoneTransformId;
  150. internal DeformationMethods currentDeformationMethod { get; private set; }
  151. internal BaseDeformationSystem deformationSystem { get; private set; }
  152. #if ENABLE_URP
  153. /// <summary>
  154. /// Returns an array of the outline indices.
  155. /// The indices are sorted and laid out with line topology.
  156. /// </summary>
  157. internal NativeArray<int> outlineIndices => m_OutlineIndexCache;
  158. /// <summary>
  159. /// Returns an array of the deformed outline vertices.
  160. /// </summary>
  161. internal NativeArray<Vector3> outlineVertices => m_DeformedOutlineVertexCache;
  162. #endif
  163. /// <summary>
  164. /// Returns a hash which is updated every time the mesh is deformed.
  165. /// </summary>
  166. internal int vertexDeformationHash => m_VertexDeformationHash;
  167. internal Sprite sprite => m_Sprite;
  168. internal SpriteRenderer spriteRenderer => m_SpriteRenderer;
  169. internal NativeCustomSlice<BoneWeight> spriteBoneWeights => m_SpriteBoneWeights;
  170. /// <summary>
  171. /// Gets the index of the SpriteSkin in the SpriteSkinComposite.
  172. /// </summary>
  173. internal int dataIndex => m_DataIndex;
  174. /// <summary>
  175. /// Get and set the Auto Rebind property.
  176. /// When enabled, Sprite Skin attempts to automatically locate the Transform that is needed for the current Sprite assigned to the Sprite Renderer.
  177. /// </summary>
  178. public bool autoRebind
  179. {
  180. get => m_AutoRebind;
  181. set
  182. {
  183. m_AutoRebind = value;
  184. if (isActiveAndEnabled)
  185. {
  186. CacheHierarchy();
  187. CacheCurrentSprite(m_AutoRebind);
  188. }
  189. }
  190. }
  191. /// <summary>
  192. /// Returns the Transform Components that are used for deformation.
  193. /// Do not modify elements of the returned array.
  194. /// </summary>
  195. /// <returns>An array of Transform Components.</returns>
  196. public Transform[] boneTransforms => m_BoneTransforms;
  197. /// <summary>
  198. /// Sets the Transform Components that are used for deformation.
  199. /// </summary>
  200. /// <param name="boneTransformsArray">Array of new bone Transforms.</param>
  201. /// <returns>The state of the Sprite Skin.</returns>
  202. public SpriteSkinState SetBoneTransforms(Transform[] boneTransformsArray)
  203. {
  204. m_BoneTransforms = boneTransformsArray;
  205. var result = CacheValidFlag();
  206. if (isActiveAndEnabled)
  207. OnBoneTransformChanged();
  208. return result;
  209. }
  210. /// <summary>
  211. /// Returns the Transform Component that represents the root bone for deformation.
  212. /// </summary>
  213. /// <returns>A Transform Component.</returns>
  214. public Transform rootBone => m_RootBone;
  215. /// <summary>
  216. /// Sets the Transform Component that represents the root bone for deformation.
  217. /// </summary>
  218. /// <param name="rootBoneTransform">Root bone Transform Component.</param>
  219. /// <returns>The state of the Sprite Skin.</returns>
  220. public SpriteSkinState SetRootBone(Transform rootBoneTransform)
  221. {
  222. m_RootBone = rootBoneTransform;
  223. var result = CacheValidFlag();
  224. if (isActiveAndEnabled)
  225. {
  226. CacheHierarchy();
  227. OnRootBoneTransformChanged();
  228. }
  229. return result;
  230. }
  231. internal Bounds bounds
  232. {
  233. get => m_Bounds;
  234. set => m_Bounds = value;
  235. }
  236. /// <summary>
  237. /// Determines if the SpriteSkin executes even if the associated
  238. /// SpriteRenderer has been culled from view.
  239. /// </summary>
  240. public bool alwaysUpdate
  241. {
  242. get => m_AlwaysUpdate;
  243. set => m_AlwaysUpdate = value;
  244. }
  245. /// <summary>
  246. /// Always run a deformation pass on the CPU.<br/>
  247. /// If GPU deformation is enabled, enabling forceCpuDeformation will cause the deformation to run twice, one time on the CPU and one time on the GPU.
  248. /// </summary>
  249. public bool forceCpuDeformation
  250. {
  251. get => m_ForceCpuDeformation;
  252. set
  253. {
  254. if (m_ForceCpuDeformation == value)
  255. return;
  256. m_ForceCpuDeformation = value;
  257. if (isActiveAndEnabled)
  258. {
  259. UpdateSpriteDeformationData();
  260. DeformationManager.instance.CopyToSpriteSkinData(this);
  261. }
  262. }
  263. }
  264. /// <summary>
  265. /// Resets the bone transforms to the bind pose.
  266. /// </summary>
  267. /// <returns>True if successful.</returns>
  268. public bool ResetBindPose()
  269. {
  270. if (!isValid)
  271. return false;
  272. var spriteBones = spriteRenderer.sprite.GetBones();
  273. for (var i = 0; i < boneTransforms.Length; ++i)
  274. {
  275. var boneTransform = boneTransforms[i];
  276. var spriteBone = spriteBones[i];
  277. if (spriteBone.parentId != -1)
  278. {
  279. boneTransform.localPosition = spriteBone.position;
  280. boneTransform.localRotation = spriteBone.rotation;
  281. boneTransform.localScale = Vector3.one;
  282. }
  283. }
  284. return true;
  285. }
  286. internal bool isValid => this.Validate() == SpriteSkinState.Ready;
  287. #if UNITY_EDITOR
  288. internal static Events.UnityEvent onDrawGizmos = new Events.UnityEvent();
  289. void OnDrawGizmos() => onDrawGizmos.Invoke();
  290. internal bool ignoreNextSpriteChange { get; set; } = true;
  291. #endif
  292. internal void Awake()
  293. {
  294. m_SpriteRenderer = GetComponent<SpriteRenderer>();
  295. m_Sprite = m_SpriteRenderer.sprite;
  296. m_SpriteId = m_Sprite != null ? m_Sprite.GetInstanceID() : 0;
  297. }
  298. void OnEnable()
  299. {
  300. m_TransformId = gameObject.transform.GetInstanceID();
  301. m_TransformsHash = 0;
  302. currentDeformationMethod = SpriteSkinUtility.CanSpriteSkinUseGpuDeformation(this) ? DeformationMethods.Gpu : DeformationMethods.Cpu;
  303. Awake();
  304. CacheCurrentSprite(false);
  305. UpdateSpriteDeformationData();
  306. if (m_HierarchyCache.Count == 0)
  307. CacheHierarchy();
  308. RefreshBoneTransforms();
  309. DeformationManager.instance.AddSpriteSkin(this);
  310. SpriteSkinContainer.instance.AddSpriteSkin(this);
  311. m_SpriteRenderer.RegisterSpriteChangeCallback(OnSpriteChanged);
  312. }
  313. void OnDisable()
  314. {
  315. DeactivateSkinning();
  316. BufferManager.instance.ReturnBuffer(GetInstanceID());
  317. deformationSystem?.RemoveSpriteSkin(this);
  318. deformationSystem = null;
  319. SpriteSkinContainer.instance.RemoveSpriteSkin(this);
  320. ResetBoneTransformIdCache();
  321. DisposeOutlineCaches();
  322. }
  323. void RefreshBoneTransforms()
  324. {
  325. DeformationManager.instance.RemoveBoneTransforms(this);
  326. CacheBoneTransformIds();
  327. DeformationManager.instance.AddSpriteSkinBoneTransform(this);
  328. CacheValidFlag();
  329. DeformationManager.instance.CopyToSpriteSkinData(this);
  330. }
  331. void OnSpriteChanged(SpriteRenderer updatedSpriteRenderer)
  332. {
  333. m_Sprite = updatedSpriteRenderer.sprite;
  334. m_SpriteId = m_Sprite != null ? m_Sprite.GetInstanceID() : 0;
  335. }
  336. void CacheBoneTransformIds()
  337. {
  338. m_BoneCacheUpdateToDate = true;
  339. var boneCount = 0;
  340. for (var i = 0; i < boneTransforms?.Length; ++i)
  341. {
  342. if (boneTransforms[i] != null)
  343. ++boneCount;
  344. }
  345. if (m_BoneTransformId != default && m_BoneTransformId.IsCreated)
  346. NativeArrayHelpers.ResizeIfNeeded(ref m_BoneTransformId, boneCount);
  347. else
  348. m_BoneTransformId = new NativeArray<int>(boneCount, Allocator.Persistent);
  349. m_RootBoneTransformId = rootBone != null ? rootBone.GetInstanceID() : 0;
  350. m_BoneTransformIdNativeSlice = new NativeCustomSlice<int>(m_BoneTransformId);
  351. for (int i = 0, j = 0; i < boneTransforms?.Length; ++i)
  352. {
  353. if (boneTransforms[i] != null)
  354. {
  355. m_BoneTransformId[j] = boneTransforms[i].GetInstanceID();
  356. ++j;
  357. }
  358. }
  359. }
  360. void OnBoneTransformChanged()
  361. {
  362. RefreshBoneTransforms();
  363. SpriteSkinContainer.instance.BoneTransformsChanged(this);
  364. }
  365. void OnRootBoneTransformChanged()
  366. {
  367. RefreshBoneTransforms();
  368. SpriteSkinContainer.instance.BoneTransformsChanged(this);
  369. }
  370. /// <summary>
  371. /// Called before object is serialized.
  372. /// </summary>
  373. public void OnBeforeSerialize()
  374. {
  375. OnBeforeSerializeBatch();
  376. }
  377. /// <summary>
  378. /// Called after object is deserialized.
  379. /// </summary>
  380. public void OnAfterDeserialize()
  381. {
  382. OnAfterSerializeBatch();
  383. }
  384. void OnBeforeSerializeBatch() { }
  385. void OnAfterSerializeBatch()
  386. {
  387. #if UNITY_EDITOR
  388. m_BoneCacheUpdateToDate = false;
  389. #endif
  390. }
  391. internal void OnEditorEnable()
  392. {
  393. Awake();
  394. }
  395. SpriteSkinState CacheValidFlag()
  396. {
  397. m_State = this.Validate();
  398. m_IsValid = m_State == SpriteSkinState.Ready;
  399. if (!m_IsValid)
  400. DeactivateSkinning();
  401. return m_State;
  402. }
  403. internal bool BatchValidate()
  404. {
  405. if (!m_BoneCacheUpdateToDate)
  406. {
  407. RefreshBoneTransforms();
  408. }
  409. CacheCurrentSprite(m_AutoRebind);
  410. var hasSprite = m_CurrentDeformSprite != 0;
  411. return m_IsValid && hasSprite && m_SpriteRenderer.enabled && (alwaysUpdate || m_SpriteRenderer.isVisible);
  412. }
  413. void Reset()
  414. {
  415. Awake();
  416. if (isActiveAndEnabled)
  417. {
  418. CacheValidFlag();
  419. if (!m_BoneCacheUpdateToDate)
  420. {
  421. RefreshBoneTransforms();
  422. }
  423. DeformationManager.instance.CopyToSpriteSkinData(this);
  424. }
  425. }
  426. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  427. void ResetBoneTransformIdCache()
  428. {
  429. m_BoneTransformId.DisposeIfCreated();
  430. m_BoneTransformId = default;
  431. m_RootBoneTransformId = -1;
  432. m_BoneCacheUpdateToDate = false;
  433. }
  434. internal NativeByteArray GetDeformedVertices(int spriteVertexCount)
  435. {
  436. if (sprite != null)
  437. {
  438. if (m_CurrentDeformVerticesLength != spriteVertexCount)
  439. {
  440. m_TransformsHash = 0;
  441. m_CurrentDeformVerticesLength = spriteVertexCount;
  442. }
  443. }
  444. else
  445. {
  446. m_CurrentDeformVerticesLength = 0;
  447. }
  448. m_DeformedVertices = BufferManager.instance.GetBuffer(GetInstanceID(), m_CurrentDeformVerticesLength);
  449. return m_DeformedVertices;
  450. }
  451. /// <summary>
  452. /// Returns whether this SpriteSkin has currently deformed vertices.
  453. /// </summary>
  454. /// <returns>Returns true if this SpriteSkin has currently deformed vertices. Returns false otherwise.</returns>
  455. public bool HasCurrentDeformedVertices()
  456. {
  457. if (!m_IsValid)
  458. return false;
  459. return m_DataIndex >= 0 && deformationSystem != null && deformationSystem.IsSpriteSkinActiveForDeformation(this);
  460. }
  461. /// <summary>
  462. /// Gets a byte array to the currently deformed vertices for this SpriteSkin.
  463. /// </summary>
  464. /// <returns>Returns a reference to the currently deformed vertices. This is valid only for this calling frame.</returns>
  465. /// <exception cref="InvalidOperationException">
  466. /// Thrown when there are no currently deformed vertices.
  467. /// HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
  468. /// </exception>
  469. internal NativeArray<byte> GetCurrentDeformedVertices()
  470. {
  471. if (!m_IsValid)
  472. throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
  473. if (m_DataIndex < 0)
  474. throw new InvalidOperationException("There are no currently deformed vertices.");
  475. var buffer = deformationSystem?.GetDeformableBufferForSpriteSkin(this) ?? default;
  476. if (buffer == default)
  477. throw new InvalidOperationException("There are no currently deformed vertices.");
  478. return buffer;
  479. }
  480. /// <summary>
  481. /// Gets an array of currently deformed position vertices for this SpriteSkin.
  482. /// </summary>
  483. /// <returns>Returns a reference to the currently deformed vertices. This is valid only for this calling frame.</returns>
  484. /// <exception cref="InvalidOperationException">
  485. /// Thrown when there are no currently deformed vertices or if the deformed vertices does not contain only
  486. /// position data. HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
  487. /// </exception>
  488. internal NativeSlice<PositionVertex> GetCurrentDeformedVertexPositions()
  489. {
  490. if (!m_IsValid)
  491. throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
  492. if (sprite.HasVertexAttribute(VertexAttribute.Tangent))
  493. throw new InvalidOperationException("This SpriteSkin has deformed tangents");
  494. if (!sprite.HasVertexAttribute(VertexAttribute.Position))
  495. throw new InvalidOperationException("This SpriteSkin does not have deformed positions.");
  496. var deformedBuffer = GetCurrentDeformedVertices();
  497. return deformedBuffer.Slice().SliceConvert<PositionVertex>();
  498. }
  499. /// <summary>
  500. /// Gets an array of currently deformed position and tangent vertices for this SpriteSkin.
  501. /// </summary>
  502. /// <returns>
  503. /// Returns a reference to the currently deformed position and tangent vertices. This is valid only for this calling frame.
  504. /// </returns>
  505. /// <exception cref="InvalidOperationException">
  506. /// Thrown when there are no currently deformed vertices or if the deformed vertices does not contain only
  507. /// position and tangent data. HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
  508. /// </exception>
  509. internal NativeSlice<PositionTangentVertex> GetCurrentDeformedVertexPositionsAndTangents()
  510. {
  511. if (!m_IsValid)
  512. throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
  513. if (!sprite.HasVertexAttribute(VertexAttribute.Tangent))
  514. throw new InvalidOperationException("This SpriteSkin does not have deformed tangents");
  515. if (!sprite.HasVertexAttribute(VertexAttribute.Position))
  516. throw new InvalidOperationException("This SpriteSkin does not have deformed positions.");
  517. var deformedBuffer = GetCurrentDeformedVertices();
  518. return deformedBuffer.Slice().SliceConvert<PositionTangentVertex>();
  519. }
  520. /// <summary>
  521. /// Gets an enumerable to iterate through all deformed vertex positions of this SpriteSkin.
  522. /// </summary>
  523. /// <returns>Returns an IEnumerable to deformed vertex positions.</returns>
  524. /// <exception cref="InvalidOperationException">
  525. /// Thrown when there is no vertex positions or deformed vertices.
  526. /// HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
  527. /// </exception>
  528. public IEnumerable<Vector3> GetDeformedVertexPositionData()
  529. {
  530. if (!m_IsValid)
  531. throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
  532. var hasPosition = sprite.HasVertexAttribute(VertexAttribute.Position);
  533. if (!hasPosition)
  534. throw new InvalidOperationException("Sprite does not have vertex position data.");
  535. var rawBuffer = GetCurrentDeformedVertices();
  536. var rawSlice = rawBuffer.Slice(sprite.GetVertexStreamOffset(VertexAttribute.Position));
  537. return new NativeCustomSliceEnumerator<Vector3>(rawSlice, m_SpriteVertexCount, m_SpriteVertexStreamSize);
  538. }
  539. /// <summary>
  540. /// Gets an enumerable to iterate through all deformed vertex tangents of this SpriteSkin.
  541. /// </summary>
  542. /// <returns>Returns an IEnumerable to deformed vertex tangents.</returns>
  543. /// <exception cref="InvalidOperationException">
  544. /// Thrown when there is no vertex tangents or deformed vertices.
  545. /// HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
  546. /// </exception>
  547. public IEnumerable<Vector4> GetDeformedVertexTangentData()
  548. {
  549. if (!m_IsValid)
  550. throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
  551. var hasTangent = sprite.HasVertexAttribute(VertexAttribute.Tangent);
  552. if (!hasTangent)
  553. throw new InvalidOperationException("Sprite does not have vertex tangent data.");
  554. var rawBuffer = GetCurrentDeformedVertices();
  555. var rawSlice = rawBuffer.Slice(sprite.GetVertexStreamOffset(VertexAttribute.Tangent));
  556. return new NativeCustomSliceEnumerator<Vector4>(rawSlice, m_SpriteVertexCount, m_SpriteVertexStreamSize);
  557. }
  558. void DisposeOutlineCaches()
  559. {
  560. m_OutlineIndexCache.DisposeIfCreated();
  561. m_StaticOutlineVertexCache.DisposeIfCreated();
  562. m_DeformedOutlineVertexCache.DisposeIfCreated();
  563. m_OutlineIndexCache = default;
  564. m_StaticOutlineVertexCache = default;
  565. m_DeformedOutlineVertexCache = default;
  566. }
  567. /// <summary>
  568. /// Used by the animation clip preview window.
  569. /// Recommended to not use outside of this purpose.
  570. /// </summary>
  571. public void OnPreviewUpdate()
  572. {
  573. #if UNITY_EDITOR
  574. if (IsInGUIUpdateLoop())
  575. Deform();
  576. #endif
  577. }
  578. static bool IsInGUIUpdateLoop() => Event.current != null;
  579. void Deform()
  580. {
  581. CacheCurrentSprite(m_AutoRebind);
  582. if (isValid && enabled && (alwaysUpdate || m_SpriteRenderer.isVisible))
  583. {
  584. var transformHash = SpriteSkinUtility.CalculateTransformHash(this);
  585. var spriteVertexCount = sprite.GetVertexStreamSize() * sprite.GetVertexCount();
  586. if (spriteVertexCount > 0 && m_TransformsHash != transformHash)
  587. {
  588. var inputVertices = GetDeformedVertices(spriteVertexCount);
  589. SpriteSkinUtility.Deform(sprite, gameObject.transform.worldToLocalMatrix, boneTransforms, inputVertices.array);
  590. SpriteSkinUtility.UpdateBounds(this, inputVertices.array);
  591. InternalEngineBridge.SetDeformableBuffer(spriteRenderer, inputVertices.array);
  592. m_TransformsHash = transformHash;
  593. m_CurrentDeformSprite = m_SpriteId;
  594. PostDeform(true);
  595. }
  596. }
  597. else if (!InternalEngineBridge.IsUsingDeformableBuffer(spriteRenderer, IntPtr.Zero))
  598. {
  599. DeactivateSkinning();
  600. }
  601. }
  602. internal void PostDeform(bool didDeform)
  603. {
  604. if (didDeform)
  605. {
  606. #if ENABLE_URP
  607. UpdateDeformedOutlineCache();
  608. #endif
  609. m_VertexDeformationHash = Time.frameCount;
  610. }
  611. }
  612. void CacheCurrentSprite(bool rebind)
  613. {
  614. if (m_CurrentDeformSprite == m_SpriteId)
  615. return;
  616. using (Profiling.cacheCurrentSprite.Auto())
  617. {
  618. DeactivateSkinning();
  619. m_CurrentDeformSprite = m_SpriteId;
  620. if (rebind && m_CurrentDeformSprite > 0 && rootBone != null)
  621. {
  622. if (!SpriteSkinHelpers.GetSpriteBonesTransforms(this, out var transforms))
  623. Debug.LogWarning($"Rebind failed for {name}. Could not find all bones required by the Sprite: {sprite.name}.");
  624. SetBoneTransforms(transforms);
  625. }
  626. UpdateSpriteDeformationData();
  627. DeformationManager.instance.CopyToSpriteSkinData(this);
  628. CacheValidFlag();
  629. m_TransformsHash = 0;
  630. }
  631. }
  632. void UpdateSpriteDeformationData()
  633. {
  634. #if ENABLE_URP
  635. CacheSpriteOutline();
  636. #endif
  637. if (sprite == null)
  638. {
  639. m_SpriteUVs = NativeCustomSlice<Vector2>.Default();
  640. m_SpriteVertices = NativeCustomSlice<Vector3>.Default();
  641. m_SpriteTangents = NativeCustomSlice<Vector4>.Default();
  642. m_SpriteBoneWeights = NativeCustomSlice<BoneWeight>.Default();
  643. m_SpriteBindPoses = NativeCustomSlice<Matrix4x4>.Default();
  644. m_SpriteHasTangents = false;
  645. m_SpriteVertexStreamSize = 0;
  646. m_SpriteVertexCount = 0;
  647. m_SpriteTangentVertexOffset = 0;
  648. }
  649. else
  650. {
  651. var cacheFullMesh = currentDeformationMethod == DeformationMethods.Cpu || forceCpuDeformation;
  652. if (cacheFullMesh)
  653. {
  654. m_SpriteVertices = new NativeCustomSlice<Vector3>(sprite.GetVertexAttribute<Vector3>(VertexAttribute.Position));
  655. m_SpriteVertexCount = sprite.GetVertexCount();
  656. m_SpriteVertexStreamSize = sprite.GetVertexStreamSize();
  657. m_SpriteTangents = new NativeCustomSlice<Vector4>(sprite.GetVertexAttribute<Vector4>(VertexAttribute.Tangent));
  658. m_SpriteHasTangents = sprite.HasVertexAttribute(VertexAttribute.Tangent);
  659. m_SpriteTangentVertexOffset = sprite.GetVertexStreamOffset(VertexAttribute.Tangent);
  660. }
  661. else
  662. {
  663. m_SpriteVertices = new NativeCustomSlice<Vector3>(m_StaticOutlineVertexCache);
  664. m_SpriteVertexCount = m_SpriteVertices.length;
  665. m_SpriteVertexStreamSize = sizeof(float) * 3;
  666. m_SpriteTangents = new NativeCustomSlice<Vector4>(sprite.GetVertexAttribute<Vector4>(VertexAttribute.Tangent));
  667. m_SpriteHasTangents = false;
  668. m_SpriteTangentVertexOffset = 0;
  669. }
  670. m_SpriteUVs = new NativeCustomSlice<Vector2>(sprite.GetVertexAttribute<Vector2>(VertexAttribute.TexCoord0));
  671. m_SpriteBoneWeights = new NativeCustomSlice<BoneWeight>(sprite.GetVertexAttribute<BoneWeight>(VertexAttribute.BlendWeight));
  672. m_SpriteBindPoses = new NativeCustomSlice<Matrix4x4>(sprite.GetBindPoses());
  673. }
  674. }
  675. #if ENABLE_URP
  676. void UpdateDeformedOutlineCache()
  677. {
  678. if (sprite == null)
  679. return;
  680. if (!m_OutlineIndexCache.IsCreated || !m_DeformedOutlineVertexCache.IsCreated)
  681. return;
  682. if (!HasCurrentDeformedVertices())
  683. return;
  684. var buffer = GetCurrentDeformedVertices();
  685. var indexCache = m_OutlineIndexCache;
  686. var vertexCache = m_DeformedOutlineVertexCache;
  687. BurstedSpriteSkinUtilities.SetVertexPositionFromByteBuffer(in buffer, in indexCache, ref vertexCache, m_SpriteVertexStreamSize);
  688. m_DeformedOutlineVertexCache = vertexCache;
  689. }
  690. void CacheSpriteOutline()
  691. {
  692. DisposeOutlineCaches();
  693. if (sprite == null)
  694. return;
  695. CacheOutlineIndices(out var maxIndex);
  696. var cacheSize = maxIndex + 1;
  697. CacheOutlineVertices(cacheSize);
  698. }
  699. void CacheOutlineIndices(out int maxIndex)
  700. {
  701. var indices = sprite.GetIndices();
  702. var edgeNativeArr = MeshUtilities.GetOutlineEdges(in indices);
  703. m_OutlineIndexCache = new NativeArray<int>(edgeNativeArr.Length * 2, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
  704. maxIndex = 0;
  705. for (var i = 0; i < edgeNativeArr.Length; ++i)
  706. {
  707. var indexX = edgeNativeArr[i].x;
  708. var indexY = edgeNativeArr[i].y;
  709. m_OutlineIndexCache[i * 2] = indexX;
  710. m_OutlineIndexCache[(i * 2) + 1] = indexY;
  711. if (indexX > maxIndex)
  712. maxIndex = indexX;
  713. if (indexY > maxIndex)
  714. maxIndex = indexY;
  715. }
  716. edgeNativeArr.Dispose();
  717. }
  718. void CacheOutlineVertices(int cacheSize)
  719. {
  720. m_DeformedOutlineVertexCache = new NativeArray<Vector3>(cacheSize, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
  721. m_StaticOutlineVertexCache = new NativeArray<Vector3>(cacheSize, Allocator.Persistent);
  722. var vertices = sprite.GetVertexAttribute<Vector3>(VertexAttribute.Position);
  723. var vertexCache = m_StaticOutlineVertexCache;
  724. for (var i = 0; i < m_OutlineIndexCache.Length; ++i)
  725. {
  726. var index = m_OutlineIndexCache[i];
  727. vertexCache[index] = vertices[index];
  728. }
  729. m_StaticOutlineVertexCache = vertexCache;
  730. }
  731. #endif
  732. internal void CopyToSpriteSkinData(ref SpriteSkinData data, int spriteSkinIndex)
  733. {
  734. if (!m_BoneCacheUpdateToDate)
  735. {
  736. RefreshBoneTransforms();
  737. }
  738. CacheCurrentSprite(m_AutoRebind);
  739. data.vertices = m_SpriteVertices;
  740. data.boneWeights = m_SpriteBoneWeights;
  741. data.bindPoses = m_SpriteBindPoses;
  742. data.tangents = m_SpriteTangents;
  743. data.hasTangents = m_SpriteHasTangents;
  744. data.spriteVertexStreamSize = m_SpriteVertexStreamSize;
  745. data.spriteVertexCount = m_SpriteVertexCount;
  746. data.tangentVertexOffset = m_SpriteTangentVertexOffset;
  747. data.transformId = m_TransformId;
  748. data.boneTransformId = m_BoneTransformIdNativeSlice;
  749. m_DataIndex = spriteSkinIndex;
  750. }
  751. internal bool NeedToUpdateDeformationCache()
  752. {
  753. unsafe
  754. {
  755. var iptr = new IntPtr(sprite.GetVertexAttribute<Vector2>(VertexAttribute.TexCoord0).GetUnsafeReadOnlyPtr());
  756. var rs = m_SpriteUVs.data != iptr;
  757. if (rs)
  758. {
  759. UpdateSpriteDeformationData();
  760. deformationSystem.CopyToSpriteSkinData(this);
  761. DeformationManager.instance.CopyToSpriteSkinData(this);
  762. }
  763. return rs;
  764. }
  765. }
  766. internal void CacheHierarchy()
  767. {
  768. using (Profiling.cacheHierarchy.Auto())
  769. {
  770. m_HierarchyCache.Clear();
  771. if (rootBone == null || !m_AutoRebind)
  772. return;
  773. var boneCount = CountChildren(rootBone);
  774. m_HierarchyCache.EnsureCapacity(boneCount + 1);
  775. SpriteSkinHelpers.CacheChildren(rootBone, m_HierarchyCache);
  776. foreach (var entry in m_HierarchyCache)
  777. {
  778. if (entry.Value.Count == 1)
  779. continue;
  780. var count = entry.Value.Count;
  781. for (var i = 0; i < count; ++i)
  782. {
  783. var transformEntry = entry.Value[i];
  784. transformEntry.fullName = SpriteSkinHelpers.GenerateTransformPath(rootBone, transformEntry.transform);
  785. entry.Value[i] = transformEntry;
  786. }
  787. }
  788. }
  789. }
  790. internal void DeactivateSkinning()
  791. {
  792. if (m_SpriteRenderer != null)
  793. {
  794. var currentSprite = sprite;
  795. if (currentSprite != null)
  796. InternalEngineBridge.SetLocalAABB(m_SpriteRenderer, currentSprite.bounds);
  797. m_SpriteRenderer.DeactivateDeformableBuffer();
  798. }
  799. m_TransformsHash = 0;
  800. }
  801. internal void ResetSprite()
  802. {
  803. m_CurrentDeformSprite = 0;
  804. CacheValidFlag();
  805. }
  806. internal void SetDeformationSystem(BaseDeformationSystem newDeformationSystem)
  807. {
  808. deformationSystem = newDeformationSystem;
  809. currentDeformationMethod = deformationSystem.deformationMethod;
  810. }
  811. static int CountChildren(Transform transform)
  812. {
  813. var childCount = transform.childCount;
  814. var count = childCount;
  815. for (var i = 0; i < childCount; ++i)
  816. count += CountChildren(transform.GetChild(i));
  817. return count;
  818. }
  819. }
  820. }