Няма описание
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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  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. /// <summary>
  15. /// Represents vertex position.
  16. /// </summary>
  17. public 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. public 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. /// Deforms the Sprite that is currently assigned to the SpriteRenderer in the same GameObject
  40. /// </summary>
  41. [Preserve]
  42. [ExecuteInEditMode]
  43. [DefaultExecutionOrder(-1)]
  44. [DisallowMultipleComponent]
  45. [RequireComponent(typeof(SpriteRenderer))]
  46. [AddComponentMenu("2D Animation/Sprite Skin")]
  47. [MovedFrom("UnityEngine.U2D.Experimental.Animation")]
  48. [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.animation@7.0/manual/SpriteSkin.html")]
  49. public sealed partial class SpriteSkin : MonoBehaviour, ISerializationCallbackReceiver
  50. {
  51. [SerializeField]
  52. private Transform m_RootBone;
  53. [SerializeField]
  54. private Transform[] m_BoneTransforms = new Transform[0];
  55. [SerializeField]
  56. private Bounds m_Bounds;
  57. [SerializeField]
  58. private bool m_UseBatching = true;
  59. [SerializeField]
  60. private bool m_AlwaysUpdate = true;
  61. [SerializeField]
  62. private bool m_AutoRebind = false;
  63. // The deformed m_SpriteVertices stores all 'HOT' channels only in single-stream and essentially depends on Sprite Asset data.
  64. // The order of storage if present is POSITION, NORMALS, TANGENTS.
  65. private NativeByteArray m_DeformedVertices;
  66. private int m_CurrentDeformVerticesLength = 0;
  67. private SpriteRenderer m_SpriteRenderer;
  68. private int m_CurrentDeformSprite = 0;
  69. private bool m_ForceSkinning;
  70. private bool m_BatchSkinning = false;
  71. bool m_IsValid = false;
  72. int m_TransformsHash = 0;
  73. internal bool batchSkinning
  74. {
  75. get { return m_BatchSkinning; }
  76. set { m_BatchSkinning = value; }
  77. }
  78. internal bool autoRebind
  79. {
  80. get => m_AutoRebind;
  81. set
  82. {
  83. m_AutoRebind = value;
  84. CacheCurrentSprite(m_AutoRebind);
  85. }
  86. }
  87. #if UNITY_EDITOR
  88. internal static Events.UnityEvent onDrawGizmos = new Events.UnityEvent();
  89. private void OnDrawGizmos() { onDrawGizmos.Invoke(); }
  90. private bool m_IgnoreNextSpriteChange = true;
  91. internal bool ignoreNextSpriteChange
  92. {
  93. get { return m_IgnoreNextSpriteChange; }
  94. set { m_IgnoreNextSpriteChange = value; }
  95. }
  96. #endif
  97. private int GetSpriteInstanceID()
  98. {
  99. return sprite != null ? sprite.GetInstanceID() : 0;
  100. }
  101. internal void Awake()
  102. {
  103. m_SpriteRenderer = GetComponent<SpriteRenderer>();
  104. }
  105. void OnEnable()
  106. {
  107. Awake();
  108. m_TransformsHash = 0;
  109. CacheCurrentSprite(false);
  110. OnEnableBatch();
  111. }
  112. internal void OnEditorEnable()
  113. {
  114. Awake();
  115. }
  116. void CacheValidFlag()
  117. {
  118. m_IsValid = isValid;
  119. if(!m_IsValid)
  120. DeactivateSkinning();
  121. }
  122. void Reset()
  123. {
  124. Awake();
  125. if (isActiveAndEnabled)
  126. {
  127. CacheValidFlag();
  128. OnResetBatch();
  129. }
  130. }
  131. internal void UseBatching(bool value)
  132. {
  133. if (m_UseBatching != value)
  134. {
  135. m_UseBatching = value;
  136. UseBatchingBatch();
  137. }
  138. }
  139. internal NativeByteArray GetDeformedVertices(int spriteVertexCount)
  140. {
  141. if (sprite != null)
  142. {
  143. if (m_CurrentDeformVerticesLength != spriteVertexCount)
  144. {
  145. m_TransformsHash = 0;
  146. m_CurrentDeformVerticesLength = spriteVertexCount;
  147. }
  148. }
  149. else
  150. {
  151. m_CurrentDeformVerticesLength = 0;
  152. }
  153. m_DeformedVertices = BufferManager.instance.GetBuffer(GetInstanceID(), m_CurrentDeformVerticesLength);
  154. return m_DeformedVertices;
  155. }
  156. /// <summary>
  157. /// Returns whether this SpriteSkin has currently deformed vertices.
  158. /// </summary>
  159. /// <returns>Returns true if this SpriteSkin has currently deformed vertices. Returns false otherwise.</returns>
  160. public bool HasCurrentDeformedVertices()
  161. {
  162. if (!m_IsValid)
  163. return false;
  164. #if ENABLE_SPRITESKIN_COMPOSITE
  165. return m_DataIndex >= 0 && SpriteSkinComposite.instance.HasDeformableBufferForSprite(m_DataIndex);
  166. #else
  167. return m_CurrentDeformVerticesLength > 0 && m_DeformedVertices.IsCreated;
  168. #endif
  169. }
  170. /// <summary>
  171. /// Gets a byte array to the currently deformed vertices for this SpriteSkin.
  172. /// </summary>
  173. /// <returns>Returns a reference to the currently deformed vertices. This is valid only for this calling frame.</returns>
  174. /// <exception cref="InvalidOperationException">Thrown when there are no currently deformed vertices</exception>
  175. internal NativeArray<byte> GetCurrentDeformedVertices()
  176. {
  177. if (!m_IsValid)
  178. throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
  179. #if ENABLE_SPRITESKIN_COMPOSITE
  180. if (m_DataIndex < 0)
  181. {
  182. throw new InvalidOperationException("There are no currently deformed vertices.");
  183. }
  184. return SpriteSkinComposite.instance.GetDeformableBufferForSprite(m_DataIndex);
  185. #else
  186. if (m_CurrentDeformVerticesLength <= 0)
  187. throw new InvalidOperationException("There are no currently deformed vertices.");
  188. if (!m_DeformedVertices.IsCreated)
  189. throw new InvalidOperationException("There are no currently deformed vertices.");
  190. return m_DeformedVertices.array;
  191. #endif
  192. }
  193. /// <summary>
  194. /// Gets an array of currently deformed position vertices for this SpriteSkin.
  195. /// </summary>
  196. /// <returns>Returns a reference to the currently deformed vertices. This is valid only for this calling frame.</returns>
  197. /// <exception cref="InvalidOperationException">
  198. /// Thrown when there are no currently deformed vertices or if the deformed vertices does not contain only
  199. /// position data.
  200. /// </exception>
  201. internal NativeSlice<PositionVertex> GetCurrentDeformedVertexPositions()
  202. {
  203. if (sprite.HasVertexAttribute(VertexAttribute.Tangent))
  204. throw new InvalidOperationException("This SpriteSkin has deformed tangents");
  205. if (!sprite.HasVertexAttribute(VertexAttribute.Position))
  206. throw new InvalidOperationException("This SpriteSkin does not have deformed positions.");
  207. var deformedBuffer = GetCurrentDeformedVertices();
  208. return deformedBuffer.Slice().SliceConvert<PositionVertex>();
  209. }
  210. /// <summary>
  211. /// Gets an array of currently deformed position and tangent vertices for this SpriteSkin.
  212. /// </summary>
  213. /// <returns>
  214. /// Returns a reference to the currently deformed position and tangent vertices. This is valid only for this calling frame.
  215. /// </returns>
  216. /// <exception cref="InvalidOperationException">
  217. /// Thrown when there are no currently deformed vertices or if the deformed vertices does not contain only
  218. /// position and tangent data.
  219. /// </exception>
  220. internal NativeSlice<PositionTangentVertex> GetCurrentDeformedVertexPositionsAndTangents()
  221. {
  222. if (!sprite.HasVertexAttribute(VertexAttribute.Tangent))
  223. throw new InvalidOperationException("This SpriteSkin does not have deformed tangents");
  224. if (!sprite.HasVertexAttribute(VertexAttribute.Position))
  225. throw new InvalidOperationException("This SpriteSkin does not have deformed positions.");
  226. var deformedBuffer = GetCurrentDeformedVertices();
  227. return deformedBuffer.Slice().SliceConvert<PositionTangentVertex>();
  228. }
  229. /// <summary>
  230. /// Gets an enumerable to iterate through all deformed vertex positions of this SpriteSkin.
  231. /// </summary>
  232. /// <returns>Returns an IEnumerable to deformed vertex positions.</returns>
  233. /// <exception cref="InvalidOperationException">Thrown when there is no vertex positions or deformed vertices.</exception>
  234. public IEnumerable<Vector3> GetDeformedVertexPositionData()
  235. {
  236. bool hasPosition = sprite.HasVertexAttribute(Rendering.VertexAttribute.Position);
  237. if (!hasPosition)
  238. throw new InvalidOperationException("Sprite does not have vertex position data.");
  239. var rawBuffer = GetCurrentDeformedVertices();
  240. var rawSlice = rawBuffer.Slice(sprite.GetVertexStreamOffset(VertexAttribute.Position));
  241. return new NativeCustomSliceEnumerator<Vector3>(rawSlice, sprite.GetVertexCount(), sprite.GetVertexStreamSize());
  242. }
  243. /// <summary>
  244. /// Gets an enumerable to iterate through all deformed vertex tangents of this SpriteSkin.
  245. /// </summary>
  246. /// <returns>Returns an IEnumerable to deformed vertex tangents.</returns>
  247. /// <exception cref="InvalidOperationException">Thrown when there is no vertex tangents or deformed vertices.</exception>
  248. public IEnumerable<Vector4> GetDeformedVertexTangentData()
  249. {
  250. bool hasTangent = sprite.HasVertexAttribute(Rendering.VertexAttribute.Tangent);
  251. if (!hasTangent)
  252. throw new InvalidOperationException("Sprite does not have vertex tangent data.");
  253. var rawBuffer = GetCurrentDeformedVertices();
  254. var rawSlice = rawBuffer.Slice(sprite.GetVertexStreamOffset(VertexAttribute.Tangent));
  255. return new NativeCustomSliceEnumerator<Vector4>(rawSlice, sprite.GetVertexCount(), sprite.GetVertexStreamSize());
  256. }
  257. void OnDisable()
  258. {
  259. DeactivateSkinning();
  260. BufferManager.instance.ReturnBuffer(GetInstanceID());
  261. OnDisableBatch();
  262. }
  263. #if ENABLE_SPRITESKIN_COMPOSITE
  264. internal void OnLateUpdate()
  265. #else
  266. void LateUpdate()
  267. #endif
  268. {
  269. CacheCurrentSprite(m_AutoRebind);
  270. if (isValid && !batchSkinning && this.enabled && (this.alwaysUpdate || this.spriteRenderer.isVisible))
  271. {
  272. var transformHash = SpriteSkinUtility.CalculateTransformHash(this);
  273. var spriteVertexCount = sprite.GetVertexStreamSize() * sprite.GetVertexCount();
  274. if (spriteVertexCount > 0 && m_TransformsHash != transformHash)
  275. {
  276. var inputVertices = GetDeformedVertices(spriteVertexCount);
  277. SpriteSkinUtility.Deform(sprite, gameObject.transform.worldToLocalMatrix, boneTransforms, inputVertices.array);
  278. SpriteSkinUtility.UpdateBounds(this, inputVertices.array);
  279. InternalEngineBridge.SetDeformableBuffer(spriteRenderer, inputVertices.array);
  280. m_TransformsHash = transformHash;
  281. m_CurrentDeformSprite = GetSpriteInstanceID();
  282. }
  283. }
  284. else if(!InternalEngineBridge.IsUsingDeformableBuffer(spriteRenderer, IntPtr.Zero))
  285. {
  286. DeactivateSkinning();
  287. }
  288. }
  289. void CacheCurrentSprite(bool rebind)
  290. {
  291. if (m_CurrentDeformSprite != GetSpriteInstanceID())
  292. {
  293. DeactivateSkinning();
  294. m_CurrentDeformSprite = GetSpriteInstanceID();
  295. if (rebind && m_CurrentDeformSprite > 0 && rootBone != null)
  296. {
  297. var spriteBones = sprite.GetBones();
  298. var transforms = new Transform[spriteBones.Length];
  299. if (GetSpriteBonesTransforms(spriteBones, rootBone, transforms))
  300. boneTransforms = transforms;
  301. }
  302. UpdateSpriteDeform();
  303. CacheValidFlag();
  304. m_TransformsHash = 0;
  305. }
  306. }
  307. internal Sprite sprite => spriteRenderer.sprite;
  308. internal SpriteRenderer spriteRenderer => m_SpriteRenderer;
  309. /// <summary>
  310. /// Returns the Transform Components that is used for deformation.
  311. /// Do not modify elements of the returned array.
  312. /// </summary>
  313. /// <returns>An array of Transform Components.</returns>
  314. public Transform[] boneTransforms
  315. {
  316. get { return m_BoneTransforms; }
  317. internal set
  318. {
  319. m_BoneTransforms = value;
  320. CacheValidFlag();
  321. OnBoneTransformChanged();
  322. }
  323. }
  324. /// <summary>
  325. /// Returns the Transform Component that represents the root bone for deformation
  326. /// </summary>
  327. /// <returns>A Transform Component</returns>
  328. public Transform rootBone
  329. {
  330. get { return m_RootBone; }
  331. internal set
  332. {
  333. m_RootBone = value;
  334. CacheValidFlag();
  335. OnRootBoneTransformChanged();
  336. }
  337. }
  338. internal Bounds bounds
  339. {
  340. get { return m_Bounds; }
  341. set { m_Bounds = value; }
  342. }
  343. /// <summary>
  344. /// Determines if the SpriteSkin executes even if the associated
  345. /// SpriteRenderer has been culled from view.
  346. /// </summary>
  347. public bool alwaysUpdate
  348. {
  349. get => m_AlwaysUpdate;
  350. set => m_AlwaysUpdate = value;
  351. }
  352. internal static bool GetSpriteBonesTransforms(SpriteBone[] spriteBones, Transform rootBone, Transform[] outTransform)
  353. {
  354. if(rootBone == null)
  355. throw new ArgumentException("rootBone parameter cannot be null");
  356. if(spriteBones == null)
  357. throw new ArgumentException("spritebone parameter cannot be null");
  358. if(outTransform == null)
  359. throw new ArgumentException("outTransform parameter cannot be null");
  360. if(spriteBones.Length != outTransform.Length)
  361. throw new ArgumentException("spritebone and outTransform array length must be the same");
  362. var boneObjects = rootBone.GetComponentsInChildren<Bone>();
  363. if (boneObjects != null && boneObjects.Length >= spriteBones.Length)
  364. {
  365. int i = 0;
  366. for (; i < spriteBones.Length; ++i)
  367. {
  368. var boneHash = spriteBones[i].guid;
  369. var boneTransform = Array.Find(boneObjects, x => (x.guid == boneHash));
  370. if (boneTransform == null)
  371. break;
  372. outTransform[i] = boneTransform.transform;
  373. }
  374. if(i >= spriteBones.Length)
  375. return true;
  376. }
  377. // If unable to successfuly map via guid, fall back to path
  378. return GetSpriteBonesTranformFromPath(spriteBones, rootBone, outTransform);
  379. }
  380. static bool GetSpriteBonesTranformFromPath(SpriteBone[] spriteBones, Transform rootBone, Transform[] outNewBoneTransform)
  381. {
  382. var bonePath = new string[spriteBones.Length];
  383. for (int i = 0; i < spriteBones.Length; ++i)
  384. {
  385. if (bonePath[i] == null)
  386. CalculateBoneTransformsPath(i, spriteBones, bonePath);
  387. if (rootBone.name == spriteBones[i].name)
  388. outNewBoneTransform[i] = rootBone;
  389. else
  390. {
  391. var bone = rootBone.Find(bonePath[i]);
  392. if (bone == null)
  393. return false;
  394. outNewBoneTransform[i] = bone;
  395. }
  396. }
  397. return true;
  398. }
  399. private static void CalculateBoneTransformsPath(int index, SpriteBone[] spriteBones, string[] paths)
  400. {
  401. var spriteBone = spriteBones[index];
  402. var parentId = spriteBone.parentId;
  403. var bonePath = spriteBone.name;
  404. if (parentId != -1 && spriteBones[parentId].parentId != -1)
  405. {
  406. if (paths[parentId] == null)
  407. CalculateBoneTransformsPath(spriteBone.parentId, spriteBones, paths);
  408. paths[index] = string.Format("{0}/{1}", paths[parentId], bonePath);
  409. }
  410. else
  411. paths[index] = bonePath;
  412. }
  413. internal bool isValid
  414. {
  415. get { return this.Validate() == SpriteSkinValidationResult.Ready; }
  416. }
  417. void OnDestroy()
  418. {
  419. DeactivateSkinning();
  420. }
  421. internal void DeactivateSkinning()
  422. {
  423. var sprite = spriteRenderer.sprite;
  424. if (sprite != null)
  425. InternalEngineBridge.SetLocalAABB(spriteRenderer, sprite.bounds);
  426. spriteRenderer.DeactivateDeformableBuffer();
  427. m_TransformsHash = 0;
  428. }
  429. internal void ResetSprite()
  430. {
  431. m_CurrentDeformSprite = 0;
  432. CacheValidFlag();
  433. }
  434. /// <summary>
  435. /// Called before object is serialized.
  436. /// </summary>
  437. public void OnBeforeSerialize()
  438. {
  439. OnBeforeSerializeBatch();
  440. }
  441. /// <summary>
  442. /// Called after object is deserialized.
  443. /// </summary>
  444. public void OnAfterDeserialize()
  445. {
  446. OnAfterSerializeBatch();
  447. }
  448. }
  449. }