SpriteSkin.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. #pragma warning disable 0168 // variable declared but not used.
  2. #if ENABLE_ANIMATION_COLLECTION && ENABLE_ANIMATION_BURST
  3. #define ENABLE_SPRITESKIN_COMPOSITE
  4. #endif
  5. using System;
  6. using System.Collections.Generic;
  7. using UnityEngine.Scripting;
  8. using UnityEngine.U2D.Common;
  9. using Unity.Collections;
  10. using UnityEngine.Rendering;
  11. using UnityEngine.Scripting.APIUpdating;
  12. namespace UnityEngine.U2D.Animation
  13. {
  14. public struct PositionVertex
  15. {
  16. public Vector3 position;
  17. }
  18. public struct PositionTangentVertex
  19. {
  20. public Vector3 position;
  21. public Vector4 tangent;
  22. }
  23. /// <summary>
  24. /// Deforms the Sprite that is currently assigned to the SpriteRenderer in the same GameObject
  25. /// </summary>
  26. [Preserve]
  27. [ExecuteInEditMode]
  28. [DefaultExecutionOrder(-1)]
  29. [DisallowMultipleComponent]
  30. [RequireComponent(typeof(SpriteRenderer))]
  31. [AddComponentMenu("2D Animation/Sprite Skin")]
  32. [MovedFrom("UnityEngine.U2D.Experimental.Animation")]
  33. [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.animation@latest/index.html?subfolder=/manual/index.html%23sprite-skin-component")]
  34. public sealed partial class SpriteSkin : MonoBehaviour, ISerializationCallbackReceiver
  35. {
  36. [SerializeField]
  37. private Transform m_RootBone;
  38. [SerializeField]
  39. private Transform[] m_BoneTransforms = new Transform[0];
  40. [SerializeField]
  41. private Bounds m_Bounds;
  42. [SerializeField]
  43. private bool m_UseBatching = true;
  44. [SerializeField]
  45. private bool m_AlwaysUpdate = true;
  46. // The deformed m_SpriteVertices stores all 'HOT' channels only in single-stream and essentially depends on Sprite Asset data.
  47. // The order of storage if present is POSITION, NORMALS, TANGENTS.
  48. private NativeByteArray m_DeformedVertices;
  49. private int m_CurrentDeformVerticesLength = 0;
  50. private SpriteRenderer m_SpriteRenderer;
  51. private int m_CurrentDeformSprite = 0;
  52. private bool m_ForceSkinning;
  53. private bool m_BatchSkinning = false;
  54. bool m_IsValid = false;
  55. int m_TransformsHash = 0;
  56. internal bool batchSkinning
  57. {
  58. get { return m_BatchSkinning; }
  59. set { m_BatchSkinning = value; }
  60. }
  61. #if UNITY_EDITOR
  62. internal static Events.UnityEvent onDrawGizmos = new Events.UnityEvent();
  63. private void OnDrawGizmos() { onDrawGizmos.Invoke(); }
  64. private bool m_IgnoreNextSpriteChange = true;
  65. internal bool ignoreNextSpriteChange
  66. {
  67. get { return m_IgnoreNextSpriteChange; }
  68. set { m_IgnoreNextSpriteChange = value; }
  69. }
  70. #endif
  71. private int GetSpriteInstanceID()
  72. {
  73. return sprite != null ? sprite.GetInstanceID() : 0;
  74. }
  75. internal void Awake()
  76. {
  77. m_SpriteRenderer = GetComponent<SpriteRenderer>();
  78. }
  79. void OnEnable()
  80. {
  81. Awake();
  82. m_TransformsHash = 0;
  83. CacheCurrentSprite();
  84. OnEnableBatch();
  85. }
  86. internal void OnEditorEnable()
  87. {
  88. Awake();
  89. }
  90. void CacheValidFlag()
  91. {
  92. m_IsValid = isValid;
  93. if(!m_IsValid)
  94. DeactivateSkinning();
  95. }
  96. void Reset()
  97. {
  98. Awake();
  99. if (isActiveAndEnabled)
  100. {
  101. CacheValidFlag();
  102. OnResetBatch();
  103. }
  104. }
  105. internal void UseBatching(bool value)
  106. {
  107. if (m_UseBatching != value)
  108. {
  109. m_UseBatching = value;
  110. UseBatchingBatch();
  111. }
  112. }
  113. internal NativeByteArray GetDeformedVertices(int spriteVertexCount)
  114. {
  115. if (sprite != null)
  116. {
  117. if (m_CurrentDeformVerticesLength != spriteVertexCount)
  118. {
  119. m_TransformsHash = 0;
  120. m_CurrentDeformVerticesLength = spriteVertexCount;
  121. }
  122. }
  123. else
  124. {
  125. m_CurrentDeformVerticesLength = 0;
  126. }
  127. m_DeformedVertices = BufferManager.instance.GetBuffer(GetInstanceID(), m_CurrentDeformVerticesLength);
  128. return m_DeformedVertices;
  129. }
  130. /// <summary>
  131. /// Returns whether this SpriteSkin has currently deformed vertices.
  132. /// </summary>
  133. /// <returns>Returns true if this SpriteSkin has currently deformed vertices. Returns false otherwise.</returns>
  134. public bool HasCurrentDeformedVertices()
  135. {
  136. if (!m_IsValid)
  137. return false;
  138. #if ENABLE_SPRITESKIN_COMPOSITE
  139. return m_DataIndex >= 0 && SpriteSkinComposite.instance.HasDeformableBufferForSprite(m_DataIndex);
  140. #else
  141. return m_CurrentDeformVerticesLength > 0 && m_DeformedVertices.IsCreated;
  142. #endif
  143. }
  144. /// <summary>
  145. /// Gets a byte array to the currently deformed vertices for this SpriteSkin.
  146. /// </summary>
  147. /// <returns>Returns a reference to the currently deformed vertices. This is valid only for this calling frame.</returns>
  148. /// <exception cref="InvalidOperationException">Thrown when there are no currently deformed vertices</exception>
  149. internal NativeArray<byte> GetCurrentDeformedVertices()
  150. {
  151. if (!m_IsValid)
  152. throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
  153. #if ENABLE_SPRITESKIN_COMPOSITE
  154. if (m_DataIndex < 0)
  155. {
  156. throw new InvalidOperationException("There are no currently deformed vertices.");
  157. }
  158. return SpriteSkinComposite.instance.GetDeformableBufferForSprite(m_DataIndex);
  159. #else
  160. if (m_CurrentDeformVerticesLength <= 0)
  161. throw new InvalidOperationException("There are no currently deformed vertices.");
  162. if (!m_DeformedVertices.IsCreated)
  163. throw new InvalidOperationException("There are no currently deformed vertices.");
  164. return m_DeformedVertices.array;
  165. #endif
  166. }
  167. /// <summary>
  168. /// Gets an array of currently deformed position vertices for this SpriteSkin.
  169. /// </summary>
  170. /// <returns>Returns a reference to the currently deformed vertices. This is valid only for this calling frame.</returns>
  171. /// <exception cref="InvalidOperationException">
  172. /// Thrown when there are no currently deformed vertices or if the deformed vertices does not contain only
  173. /// position data.
  174. /// </exception>
  175. internal NativeSlice<PositionVertex> GetCurrentDeformedVertexPositions()
  176. {
  177. if (sprite.HasVertexAttribute(VertexAttribute.Tangent))
  178. throw new InvalidOperationException("This SpriteSkin has deformed tangents");
  179. if (!sprite.HasVertexAttribute(VertexAttribute.Position))
  180. throw new InvalidOperationException("This SpriteSkin does not have deformed positions.");
  181. var deformedBuffer = GetCurrentDeformedVertices();
  182. return deformedBuffer.Slice().SliceConvert<PositionVertex>();
  183. }
  184. /// <summary>
  185. /// Gets an array of currently deformed position and tangent vertices for this SpriteSkin.
  186. /// </summary>
  187. /// <returns>
  188. /// Returns a reference to the currently deformed position and tangent vertices. This is valid only for this calling frame.
  189. /// </returns>
  190. /// <exception cref="InvalidOperationException">
  191. /// Thrown when there are no currently deformed vertices or if the deformed vertices does not contain only
  192. /// position and tangent data.
  193. /// </exception>
  194. internal NativeSlice<PositionTangentVertex> GetCurrentDeformedVertexPositionsAndTangents()
  195. {
  196. if (!sprite.HasVertexAttribute(VertexAttribute.Tangent))
  197. throw new InvalidOperationException("This SpriteSkin does not have deformed tangents");
  198. if (!sprite.HasVertexAttribute(VertexAttribute.Position))
  199. throw new InvalidOperationException("This SpriteSkin does not have deformed positions.");
  200. var deformedBuffer = GetCurrentDeformedVertices();
  201. return deformedBuffer.Slice().SliceConvert<PositionTangentVertex>();
  202. }
  203. /// <summary>
  204. /// Gets an enumerable to iterate through all deformed vertex positions of this SpriteSkin.
  205. /// </summary>
  206. /// <returns>Returns an IEnumerable to deformed vertex positions.</returns>
  207. /// <exception cref="InvalidOperationException">Thrown when there is no vertex positions or deformed vertices.</exception>
  208. public IEnumerable<Vector3> GetDeformedVertexPositionData()
  209. {
  210. bool hasPosition = sprite.HasVertexAttribute(Rendering.VertexAttribute.Position);
  211. if (!hasPosition)
  212. throw new InvalidOperationException("Sprite does not have vertex position data.");
  213. var rawBuffer = GetCurrentDeformedVertices();
  214. var rawSlice = rawBuffer.Slice(sprite.GetVertexStreamOffset(VertexAttribute.Position));
  215. return new NativeCustomSliceEnumerator<Vector3>(rawSlice, sprite.GetVertexCount(), sprite.GetVertexStreamSize());
  216. }
  217. /// <summary>
  218. /// Gets an enumerable to iterate through all deformed vertex tangents of this SpriteSkin.
  219. /// </summary>
  220. /// <returns>Returns an IEnumerable to deformed vertex tangents.</returns>
  221. /// <exception cref="InvalidOperationException">Thrown when there is no vertex tangents or deformed vertices.</exception>
  222. public IEnumerable<Vector4> GetDeformedVertexTangentData()
  223. {
  224. bool hasTangent = sprite.HasVertexAttribute(Rendering.VertexAttribute.Tangent);
  225. if (!hasTangent)
  226. throw new InvalidOperationException("Sprite does not have vertex tangent data.");
  227. var rawBuffer = GetCurrentDeformedVertices();
  228. var rawSlice = rawBuffer.Slice(sprite.GetVertexStreamOffset(VertexAttribute.Tangent));
  229. return new NativeCustomSliceEnumerator<Vector4>(rawSlice, sprite.GetVertexCount(), sprite.GetVertexStreamSize());
  230. }
  231. void OnDisable()
  232. {
  233. DeactivateSkinning();
  234. BufferManager.instance.ReturnBuffer(GetInstanceID());
  235. OnDisableBatch();
  236. }
  237. #if ENABLE_SPRITESKIN_COMPOSITE
  238. internal void OnLateUpdate()
  239. #else
  240. void LateUpdate()
  241. #endif
  242. {
  243. CacheCurrentSprite();
  244. if (isValid && !batchSkinning && this.enabled && (this.alwaysUpdate || this.spriteRenderer.isVisible))
  245. {
  246. var transformHash = SpriteSkinUtility.CalculateTransformHash(this);
  247. var spriteVertexCount = sprite.GetVertexStreamSize() * sprite.GetVertexCount();
  248. if (spriteVertexCount > 0 && m_TransformsHash != transformHash)
  249. {
  250. var inputVertices = GetDeformedVertices(spriteVertexCount);
  251. SpriteSkinUtility.Deform(sprite, gameObject.transform.worldToLocalMatrix, boneTransforms, inputVertices.array);
  252. SpriteSkinUtility.UpdateBounds(this, inputVertices.array);
  253. InternalEngineBridge.SetDeformableBuffer(spriteRenderer, inputVertices.array);
  254. m_TransformsHash = transformHash;
  255. m_CurrentDeformSprite = GetSpriteInstanceID();
  256. }
  257. }
  258. }
  259. void CacheCurrentSprite()
  260. {
  261. if (m_CurrentDeformSprite != GetSpriteInstanceID())
  262. {
  263. DeactivateSkinning();
  264. m_CurrentDeformSprite = GetSpriteInstanceID();
  265. UpdateSpriteDeform();
  266. CacheValidFlag();
  267. m_TransformsHash = 0;
  268. }
  269. }
  270. internal Sprite sprite => spriteRenderer.sprite;
  271. internal SpriteRenderer spriteRenderer => m_SpriteRenderer;
  272. /// <summary>
  273. /// Returns the Transform Components that is used for deformation
  274. /// </summary>
  275. /// <returns>An array of Transform Components</returns>
  276. public Transform[] boneTransforms
  277. {
  278. get { return m_BoneTransforms; }
  279. internal set
  280. {
  281. m_BoneTransforms = value;
  282. CacheValidFlag();
  283. OnBoneTransformChanged();
  284. }
  285. }
  286. /// <summary>
  287. /// Returns the Transform Component that represents the root bone for deformation
  288. /// </summary>
  289. /// <returns>A Transform Component</returns>
  290. public Transform rootBone
  291. {
  292. get { return m_RootBone; }
  293. internal set
  294. {
  295. m_RootBone = value;
  296. CacheValidFlag();
  297. OnRootBoneTransformChanged();
  298. }
  299. }
  300. internal Bounds bounds
  301. {
  302. get { return m_Bounds; }
  303. set { m_Bounds = value; }
  304. }
  305. /// <summary>
  306. /// Determines if the SpriteSkin executes even if the associated
  307. /// SpriteRenderer has been culled from view.
  308. /// </summary>
  309. public bool alwaysUpdate
  310. {
  311. get => m_AlwaysUpdate;
  312. set => m_AlwaysUpdate = value;
  313. }
  314. internal bool isValid
  315. {
  316. get { return this.Validate() == SpriteSkinValidationResult.Ready; }
  317. }
  318. void OnDestroy()
  319. {
  320. DeactivateSkinning();
  321. }
  322. internal void DeactivateSkinning()
  323. {
  324. var sprite = spriteRenderer.sprite;
  325. if (sprite != null)
  326. InternalEngineBridge.SetLocalAABB(spriteRenderer, sprite.bounds);
  327. SpriteRendererDataAccessExtensions.DeactivateDeformableBuffer(spriteRenderer);
  328. }
  329. internal void ResetSprite()
  330. {
  331. m_CurrentDeformSprite = 0;
  332. CacheValidFlag();
  333. }
  334. public void OnBeforeSerialize()
  335. {
  336. OnBeforeSerializeBatch();
  337. }
  338. public void OnAfterDeserialize()
  339. {
  340. OnAfterSerializeBatch();
  341. }
  342. }
  343. }