123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960 |
- #pragma warning disable 0168 // variable declared but not used.
-
- using System;
- using System.Collections.Generic;
- using System.Runtime.CompilerServices;
- using UnityEngine.Scripting;
- using UnityEngine.U2D.Common;
- using Unity.Collections;
- using Unity.Collections.LowLevel.Unsafe;
- using Unity.Profiling;
- using UnityEngine.Rendering;
- using UnityEngine.Scripting.APIUpdating;
-
- namespace UnityEngine.U2D.Animation
- {
- /// <summary>
- /// Represents vertex position.
- /// </summary>
- internal struct PositionVertex
- {
- /// <summary>
- /// Vertex position.
- /// </summary>
- public Vector3 position;
- }
-
- /// <summary>
- /// Represents vertex position and tangent.
- /// </summary>
- internal struct PositionTangentVertex
- {
- /// <summary>
- /// Vertex position.
- /// </summary>
- public Vector3 position;
-
- /// <summary>
- /// Vertex tangent.
- /// </summary>
- public Vector4 tangent;
- }
-
- /// <summary>
- /// The state of the Sprite Skin.
- /// </summary>
- public enum SpriteSkinState
- {
- /// <summary>
- /// Sprite Renderer doesn't contain a sprite.
- /// </summary>
- SpriteNotFound,
-
- /// <summary>
- /// Sprite referenced in the Sprite Renderer doesn't have skinning information.
- /// </summary>
- SpriteHasNoSkinningInformation,
-
- /// <summary>
- /// Sprite referenced in the Sprite Renderer doesn't have weights.
- /// </summary>
- SpriteHasNoWeights,
-
- /// <summary>
- /// Root transform is not assigned.
- /// </summary>
- RootTransformNotFound,
-
- /// <summary>
- /// Bone transform array is not assigned.
- /// </summary>
- InvalidTransformArray,
-
- /// <summary>
- /// Bone transform array has incorrect length.
- /// </summary>
- InvalidTransformArrayLength,
-
- /// <summary>
- /// One or more bone transforms is not assigned.
- /// </summary>
- TransformArrayContainsNull,
-
- /// <summary>
- /// Bone weights are invalid.
- /// </summary>
- InvalidBoneWeights,
-
- /// <summary>
- /// Sprite Skin is ready for deformation.
- /// </summary>
- Ready
- }
-
- /// <summary>
- /// Deforms the Sprite that is currently assigned to the SpriteRenderer in the same GameObject.
- /// </summary>
- [Preserve]
- [ExecuteInEditMode]
- [DefaultExecutionOrder(UpdateOrder.spriteSkinUpdateOrder)]
- [DisallowMultipleComponent]
- [RequireComponent(typeof(SpriteRenderer))]
- [AddComponentMenu("2D Animation/Sprite Skin")]
- [IconAttribute(IconUtility.IconPath + "Animation.SpriteSkin.png")]
- [MovedFrom("UnityEngine.U2D.Experimental.Animation")]
- [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.animation@latest/index.html?subfolder=/manual/SpriteSkin.html")]
- public sealed class SpriteSkin : MonoBehaviour, IPreviewable, ISerializationCallbackReceiver
- {
- internal static class Profiling
- {
- public static readonly ProfilerMarker cacheCurrentSprite = new ProfilerMarker("SpriteSkin.CacheCurrentSprite");
- public static readonly ProfilerMarker cacheHierarchy = new ProfilerMarker("SpriteSkin.CacheHierarchy");
- public static readonly ProfilerMarker getSpriteBonesTransformFromGuid = new ProfilerMarker("SpriteSkin.GetSpriteBoneTransformsFromGuid");
- public static readonly ProfilerMarker getSpriteBonesTransformFromPath = new ProfilerMarker("SpriteSkin.GetSpriteBoneTransformsFromPath");
- }
-
- internal struct TransformData
- {
- public string fullName;
- public Transform transform;
- }
-
- [SerializeField]
- Transform m_RootBone;
- [SerializeField]
- Transform[] m_BoneTransforms = Array.Empty<Transform>();
- [SerializeField]
- Bounds m_Bounds;
- [SerializeField]
- bool m_AlwaysUpdate = true;
- [SerializeField]
- bool m_AutoRebind = false;
-
- // The deformed m_SpriteVertices stores all 'HOT' channels only in single-stream and essentially depends on Sprite Asset data.
- // The order of storage if present is POSITION, NORMALS, TANGENTS.
- NativeByteArray m_DeformedVertices;
- int m_CurrentDeformVerticesLength = 0;
- SpriteRenderer m_SpriteRenderer;
- int m_CurrentDeformSprite = 0;
- int m_SpriteId = -1;
- bool m_IsValid = false;
- SpriteSkinState m_State;
- int m_TransformsHash = 0;
- bool m_ForceCpuDeformation = false;
-
- int m_TransformId;
- NativeArray<int> m_BoneTransformId;
- int m_RootBoneTransformId;
- NativeCustomSlice<Vector2> m_SpriteUVs;
- NativeCustomSlice<Vector3> m_SpriteVertices;
- NativeCustomSlice<Vector4> m_SpriteTangents;
- NativeCustomSlice<BoneWeight> m_SpriteBoneWeights;
- NativeCustomSlice<Matrix4x4> m_SpriteBindPoses;
- NativeCustomSlice<int> m_BoneTransformIdNativeSlice;
- bool m_SpriteHasTangents;
- int m_SpriteVertexStreamSize;
- int m_SpriteVertexCount;
- int m_SpriteTangentVertexOffset;
- int m_DataIndex = -1;
- bool m_BoneCacheUpdateToDate = false;
-
- internal Dictionary<int, List<TransformData>> m_HierarchyCache = new Dictionary<int, List<TransformData>>();
-
- NativeArray<int> m_OutlineIndexCache;
- NativeArray<Vector3> m_StaticOutlineVertexCache;
- NativeArray<Vector3> m_DeformedOutlineVertexCache;
- int m_VertexDeformationHash = 0;
- Sprite m_Sprite;
-
- internal NativeArray<int> boneTransformId => m_BoneTransformId;
- internal int rootBoneTransformId => m_RootBoneTransformId;
- internal DeformationMethods currentDeformationMethod { get; private set; }
- internal BaseDeformationSystem deformationSystem { get; private set; }
-
- #if ENABLE_URP
- /// <summary>
- /// Returns an array of the outline indices.
- /// The indices are sorted and laid out with line topology.
- /// </summary>
- internal NativeArray<int> outlineIndices => m_OutlineIndexCache;
- /// <summary>
- /// Returns an array of the deformed outline vertices.
- /// </summary>
- internal NativeArray<Vector3> outlineVertices => m_DeformedOutlineVertexCache;
- #endif
-
- /// <summary>
- /// Returns a hash which is updated every time the mesh is deformed.
- /// </summary>
- internal int vertexDeformationHash => m_VertexDeformationHash;
-
- internal Sprite sprite => m_Sprite;
- internal SpriteRenderer spriteRenderer => m_SpriteRenderer;
- internal NativeCustomSlice<BoneWeight> spriteBoneWeights => m_SpriteBoneWeights;
-
- /// <summary>
- /// Gets the index of the SpriteSkin in the SpriteSkinComposite.
- /// </summary>
- internal int dataIndex => m_DataIndex;
-
- /// <summary>
- /// Get and set the Auto Rebind property.
- /// When enabled, Sprite Skin attempts to automatically locate the Transform that is needed for the current Sprite assigned to the Sprite Renderer.
- /// </summary>
- public bool autoRebind
- {
- get => m_AutoRebind;
- set
- {
- m_AutoRebind = value;
- if (isActiveAndEnabled)
- {
- CacheHierarchy();
- CacheCurrentSprite(m_AutoRebind);
- }
- }
- }
-
- /// <summary>
- /// Returns the Transform Components that are used for deformation.
- /// Do not modify elements of the returned array.
- /// </summary>
- /// <returns>An array of Transform Components.</returns>
- public Transform[] boneTransforms => m_BoneTransforms;
-
- /// <summary>
- /// Sets the Transform Components that are used for deformation.
- /// </summary>
- /// <param name="boneTransformsArray">Array of new bone Transforms.</param>
- /// <returns>The state of the Sprite Skin.</returns>
- public SpriteSkinState SetBoneTransforms(Transform[] boneTransformsArray)
- {
- m_BoneTransforms = boneTransformsArray;
-
- var result = CacheValidFlag();
- if (isActiveAndEnabled)
- OnBoneTransformChanged();
-
- return result;
- }
-
- /// <summary>
- /// Returns the Transform Component that represents the root bone for deformation.
- /// </summary>
- /// <returns>A Transform Component.</returns>
- public Transform rootBone => m_RootBone;
-
- /// <summary>
- /// Sets the Transform Component that represents the root bone for deformation.
- /// </summary>
- /// <param name="rootBoneTransform">Root bone Transform Component.</param>
- /// <returns>The state of the Sprite Skin.</returns>
- public SpriteSkinState SetRootBone(Transform rootBoneTransform)
- {
- m_RootBone = rootBoneTransform;
-
- var result = CacheValidFlag();
- if (isActiveAndEnabled)
- {
- CacheHierarchy();
- OnRootBoneTransformChanged();
- }
-
- return result;
- }
-
- internal Bounds bounds
- {
- get => m_Bounds;
- set => m_Bounds = value;
- }
-
- /// <summary>
- /// Determines if the SpriteSkin executes even if the associated
- /// SpriteRenderer has been culled from view.
- /// </summary>
- public bool alwaysUpdate
- {
- get => m_AlwaysUpdate;
- set => m_AlwaysUpdate = value;
- }
-
- /// <summary>
- /// Always run a deformation pass on the CPU.<br/>
- /// 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.
- /// </summary>
- public bool forceCpuDeformation
- {
- get => m_ForceCpuDeformation;
- set
- {
- if (m_ForceCpuDeformation == value)
- return;
- m_ForceCpuDeformation = value;
-
- if (isActiveAndEnabled)
- {
- UpdateSpriteDeformationData();
- DeformationManager.instance.CopyToSpriteSkinData(this);
- }
- }
- }
-
- /// <summary>
- /// Resets the bone transforms to the bind pose.
- /// </summary>
- /// <returns>True if successful.</returns>
- public bool ResetBindPose()
- {
- if (!isValid)
- return false;
-
- var spriteBones = spriteRenderer.sprite.GetBones();
- for (var i = 0; i < boneTransforms.Length; ++i)
- {
- var boneTransform = boneTransforms[i];
- var spriteBone = spriteBones[i];
-
- if (spriteBone.parentId != -1)
- {
- boneTransform.localPosition = spriteBone.position;
- boneTransform.localRotation = spriteBone.rotation;
- boneTransform.localScale = Vector3.one;
- }
- }
-
- return true;
- }
-
- internal bool isValid => this.Validate() == SpriteSkinState.Ready;
-
- #if UNITY_EDITOR
- internal static Events.UnityEvent onDrawGizmos = new Events.UnityEvent();
-
- void OnDrawGizmos() => onDrawGizmos.Invoke();
-
- internal bool ignoreNextSpriteChange { get; set; } = true;
- #endif
-
- internal void Awake()
- {
- m_SpriteRenderer = GetComponent<SpriteRenderer>();
- m_Sprite = m_SpriteRenderer.sprite;
- m_SpriteId = m_Sprite != null ? m_Sprite.GetInstanceID() : 0;
- }
-
- void OnEnable()
- {
- m_TransformId = gameObject.transform.GetInstanceID();
- m_TransformsHash = 0;
- currentDeformationMethod = SpriteSkinUtility.CanSpriteSkinUseGpuDeformation(this) ? DeformationMethods.Gpu : DeformationMethods.Cpu;
-
- Awake();
-
- CacheCurrentSprite(false);
- UpdateSpriteDeformationData();
-
- if (m_HierarchyCache.Count == 0)
- CacheHierarchy();
-
- RefreshBoneTransforms();
-
- DeformationManager.instance.AddSpriteSkin(this);
- SpriteSkinContainer.instance.AddSpriteSkin(this);
-
- m_SpriteRenderer.RegisterSpriteChangeCallback(OnSpriteChanged);
- }
-
- void OnDisable()
- {
- DeactivateSkinning();
- BufferManager.instance.ReturnBuffer(GetInstanceID());
- deformationSystem?.RemoveSpriteSkin(this);
- deformationSystem = null;
- SpriteSkinContainer.instance.RemoveSpriteSkin(this);
- ResetBoneTransformIdCache();
- DisposeOutlineCaches();
- }
-
- void RefreshBoneTransforms()
- {
- DeformationManager.instance.RemoveBoneTransforms(this);
- CacheBoneTransformIds();
- DeformationManager.instance.AddSpriteSkinBoneTransform(this);
-
- CacheValidFlag();
-
- DeformationManager.instance.CopyToSpriteSkinData(this);
- }
-
- void OnSpriteChanged(SpriteRenderer updatedSpriteRenderer)
- {
- m_Sprite = updatedSpriteRenderer.sprite;
- m_SpriteId = m_Sprite != null ? m_Sprite.GetInstanceID() : 0;
- }
-
- void CacheBoneTransformIds()
- {
- m_BoneCacheUpdateToDate = true;
-
- var boneCount = 0;
- for (var i = 0; i < boneTransforms?.Length; ++i)
- {
- if (boneTransforms[i] != null)
- ++boneCount;
- }
-
- if (m_BoneTransformId != default && m_BoneTransformId.IsCreated)
- NativeArrayHelpers.ResizeIfNeeded(ref m_BoneTransformId, boneCount);
- else
- m_BoneTransformId = new NativeArray<int>(boneCount, Allocator.Persistent);
-
- m_RootBoneTransformId = rootBone != null ? rootBone.GetInstanceID() : 0;
- m_BoneTransformIdNativeSlice = new NativeCustomSlice<int>(m_BoneTransformId);
- for (int i = 0, j = 0; i < boneTransforms?.Length; ++i)
- {
- if (boneTransforms[i] != null)
- {
- m_BoneTransformId[j] = boneTransforms[i].GetInstanceID();
- ++j;
- }
- }
- }
-
- void OnBoneTransformChanged()
- {
- RefreshBoneTransforms();
- SpriteSkinContainer.instance.BoneTransformsChanged(this);
- }
-
- void OnRootBoneTransformChanged()
- {
- RefreshBoneTransforms();
- SpriteSkinContainer.instance.BoneTransformsChanged(this);
- }
-
- /// <summary>
- /// Called before object is serialized.
- /// </summary>
- public void OnBeforeSerialize()
- {
- OnBeforeSerializeBatch();
- }
-
- /// <summary>
- /// Called after object is deserialized.
- /// </summary>
- public void OnAfterDeserialize()
- {
- OnAfterSerializeBatch();
- }
-
- void OnBeforeSerializeBatch() { }
-
- void OnAfterSerializeBatch()
- {
- #if UNITY_EDITOR
- m_BoneCacheUpdateToDate = false;
- #endif
- }
-
- internal void OnEditorEnable()
- {
- Awake();
- }
-
- SpriteSkinState CacheValidFlag()
- {
- m_State = this.Validate();
- m_IsValid = m_State == SpriteSkinState.Ready;
- if (!m_IsValid)
- DeactivateSkinning();
-
- return m_State;
- }
-
- internal bool BatchValidate()
- {
- if (!m_BoneCacheUpdateToDate)
- {
- RefreshBoneTransforms();
- }
-
- CacheCurrentSprite(m_AutoRebind);
- var hasSprite = m_CurrentDeformSprite != 0;
- return m_IsValid && hasSprite && m_SpriteRenderer.enabled && (alwaysUpdate || m_SpriteRenderer.isVisible);
- }
-
- void Reset()
- {
- Awake();
- if (isActiveAndEnabled)
- {
- CacheValidFlag();
-
- if (!m_BoneCacheUpdateToDate)
- {
- RefreshBoneTransforms();
- }
-
- DeformationManager.instance.CopyToSpriteSkinData(this);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- void ResetBoneTransformIdCache()
- {
- m_BoneTransformId.DisposeIfCreated();
- m_BoneTransformId = default;
-
- m_RootBoneTransformId = -1;
- m_BoneCacheUpdateToDate = false;
- }
-
- internal NativeByteArray GetDeformedVertices(int spriteVertexCount)
- {
- if (sprite != null)
- {
- if (m_CurrentDeformVerticesLength != spriteVertexCount)
- {
- m_TransformsHash = 0;
- m_CurrentDeformVerticesLength = spriteVertexCount;
- }
- }
- else
- {
- m_CurrentDeformVerticesLength = 0;
- }
-
- m_DeformedVertices = BufferManager.instance.GetBuffer(GetInstanceID(), m_CurrentDeformVerticesLength);
- return m_DeformedVertices;
- }
-
- /// <summary>
- /// Returns whether this SpriteSkin has currently deformed vertices.
- /// </summary>
- /// <returns>Returns true if this SpriteSkin has currently deformed vertices. Returns false otherwise.</returns>
- public bool HasCurrentDeformedVertices()
- {
- if (!m_IsValid)
- return false;
-
- return m_DataIndex >= 0 && deformationSystem != null && deformationSystem.IsSpriteSkinActiveForDeformation(this);
- }
-
- /// <summary>
- /// Gets a byte array to the currently deformed vertices for this SpriteSkin.
- /// </summary>
- /// <returns>Returns a reference to the currently deformed vertices. This is valid only for this calling frame.</returns>
- /// <exception cref="InvalidOperationException">
- /// Thrown when there are no currently deformed vertices.
- /// HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
- /// </exception>
- internal NativeArray<byte> GetCurrentDeformedVertices()
- {
- if (!m_IsValid)
- throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
- if (m_DataIndex < 0)
- throw new InvalidOperationException("There are no currently deformed vertices.");
-
- var buffer = deformationSystem?.GetDeformableBufferForSpriteSkin(this) ?? default;
- if (buffer == default)
- throw new InvalidOperationException("There are no currently deformed vertices.");
-
- return buffer;
- }
-
- /// <summary>
- /// Gets an array of currently deformed position vertices for this SpriteSkin.
- /// </summary>
- /// <returns>Returns a reference to the currently deformed vertices. This is valid only for this calling frame.</returns>
- /// <exception cref="InvalidOperationException">
- /// Thrown when there are no currently deformed vertices or if the deformed vertices does not contain only
- /// position data. HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
- /// </exception>
- internal NativeSlice<PositionVertex> GetCurrentDeformedVertexPositions()
- {
- if (!m_IsValid)
- throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
-
- if (sprite.HasVertexAttribute(VertexAttribute.Tangent))
- throw new InvalidOperationException("This SpriteSkin has deformed tangents");
- if (!sprite.HasVertexAttribute(VertexAttribute.Position))
- throw new InvalidOperationException("This SpriteSkin does not have deformed positions.");
-
- var deformedBuffer = GetCurrentDeformedVertices();
- return deformedBuffer.Slice().SliceConvert<PositionVertex>();
- }
-
- /// <summary>
- /// Gets an array of currently deformed position and tangent vertices for this SpriteSkin.
- /// </summary>
- /// <returns>
- /// Returns a reference to the currently deformed position and tangent vertices. This is valid only for this calling frame.
- /// </returns>
- /// <exception cref="InvalidOperationException">
- /// Thrown when there are no currently deformed vertices or if the deformed vertices does not contain only
- /// position and tangent data. HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
- /// </exception>
- internal NativeSlice<PositionTangentVertex> GetCurrentDeformedVertexPositionsAndTangents()
- {
- if (!m_IsValid)
- throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
-
- if (!sprite.HasVertexAttribute(VertexAttribute.Tangent))
- throw new InvalidOperationException("This SpriteSkin does not have deformed tangents");
- if (!sprite.HasVertexAttribute(VertexAttribute.Position))
- throw new InvalidOperationException("This SpriteSkin does not have deformed positions.");
-
- var deformedBuffer = GetCurrentDeformedVertices();
- return deformedBuffer.Slice().SliceConvert<PositionTangentVertex>();
- }
-
- /// <summary>
- /// Gets an enumerable to iterate through all deformed vertex positions of this SpriteSkin.
- /// </summary>
- /// <returns>Returns an IEnumerable to deformed vertex positions.</returns>
- /// <exception cref="InvalidOperationException">
- /// Thrown when there is no vertex positions or deformed vertices.
- /// HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
- /// </exception>
- public IEnumerable<Vector3> GetDeformedVertexPositionData()
- {
- if (!m_IsValid)
- throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
-
- var hasPosition = sprite.HasVertexAttribute(VertexAttribute.Position);
- if (!hasPosition)
- throw new InvalidOperationException("Sprite does not have vertex position data.");
-
- var rawBuffer = GetCurrentDeformedVertices();
- var rawSlice = rawBuffer.Slice(sprite.GetVertexStreamOffset(VertexAttribute.Position));
- return new NativeCustomSliceEnumerator<Vector3>(rawSlice, m_SpriteVertexCount, m_SpriteVertexStreamSize);
- }
-
- /// <summary>
- /// Gets an enumerable to iterate through all deformed vertex tangents of this SpriteSkin.
- /// </summary>
- /// <returns>Returns an IEnumerable to deformed vertex tangents.</returns>
- /// <exception cref="InvalidOperationException">
- /// Thrown when there is no vertex tangents or deformed vertices.
- /// HasCurrentDeformedVertices can be used to verify if there are any deformed vertices available.
- /// </exception>
- public IEnumerable<Vector4> GetDeformedVertexTangentData()
- {
- if (!m_IsValid)
- throw new InvalidOperationException("The SpriteSkin deformation is not valid.");
-
- var hasTangent = sprite.HasVertexAttribute(VertexAttribute.Tangent);
- if (!hasTangent)
- throw new InvalidOperationException("Sprite does not have vertex tangent data.");
-
- var rawBuffer = GetCurrentDeformedVertices();
- var rawSlice = rawBuffer.Slice(sprite.GetVertexStreamOffset(VertexAttribute.Tangent));
- return new NativeCustomSliceEnumerator<Vector4>(rawSlice, m_SpriteVertexCount, m_SpriteVertexStreamSize);
- }
-
- void DisposeOutlineCaches()
- {
- m_OutlineIndexCache.DisposeIfCreated();
- m_StaticOutlineVertexCache.DisposeIfCreated();
- m_DeformedOutlineVertexCache.DisposeIfCreated();
-
- m_OutlineIndexCache = default;
- m_StaticOutlineVertexCache = default;
- m_DeformedOutlineVertexCache = default;
- }
-
- /// <summary>
- /// Used by the animation clip preview window.
- /// Recommended to not use outside of this purpose.
- /// </summary>
- public void OnPreviewUpdate()
- {
- #if UNITY_EDITOR
- if (IsInGUIUpdateLoop())
- Deform();
- #endif
- }
-
- static bool IsInGUIUpdateLoop() => Event.current != null;
-
- void Deform()
- {
- CacheCurrentSprite(m_AutoRebind);
- if (isValid && enabled && (alwaysUpdate || m_SpriteRenderer.isVisible))
- {
- var transformHash = SpriteSkinUtility.CalculateTransformHash(this);
- var spriteVertexCount = sprite.GetVertexStreamSize() * sprite.GetVertexCount();
- if (spriteVertexCount > 0 && m_TransformsHash != transformHash)
- {
- var inputVertices = GetDeformedVertices(spriteVertexCount);
- SpriteSkinUtility.Deform(sprite, gameObject.transform.worldToLocalMatrix, boneTransforms, inputVertices.array);
- SpriteSkinUtility.UpdateBounds(this, inputVertices.array);
- InternalEngineBridge.SetDeformableBuffer(spriteRenderer, inputVertices.array);
- m_TransformsHash = transformHash;
- m_CurrentDeformSprite = m_SpriteId;
-
- PostDeform(true);
- }
- }
- else if (!InternalEngineBridge.IsUsingDeformableBuffer(spriteRenderer, IntPtr.Zero))
- {
- DeactivateSkinning();
- }
- }
-
- internal void PostDeform(bool didDeform)
- {
- if (didDeform)
- {
- #if ENABLE_URP
- UpdateDeformedOutlineCache();
- #endif
- m_VertexDeformationHash = Time.frameCount;
- }
- }
-
- void CacheCurrentSprite(bool rebind)
- {
- if (m_CurrentDeformSprite == m_SpriteId)
- return;
-
- using (Profiling.cacheCurrentSprite.Auto())
- {
- DeactivateSkinning();
- m_CurrentDeformSprite = m_SpriteId;
- if (rebind && m_CurrentDeformSprite > 0 && rootBone != null)
- {
- if (!SpriteSkinHelpers.GetSpriteBonesTransforms(this, out var transforms))
- Debug.LogWarning($"Rebind failed for {name}. Could not find all bones required by the Sprite: {sprite.name}.");
- SetBoneTransforms(transforms);
- }
-
- UpdateSpriteDeformationData();
- DeformationManager.instance.CopyToSpriteSkinData(this);
-
- CacheValidFlag();
- m_TransformsHash = 0;
- }
- }
-
- void UpdateSpriteDeformationData()
- {
- #if ENABLE_URP
- CacheSpriteOutline();
- #endif
-
- if (sprite == null)
- {
- m_SpriteUVs = NativeCustomSlice<Vector2>.Default();
- m_SpriteVertices = NativeCustomSlice<Vector3>.Default();
- m_SpriteTangents = NativeCustomSlice<Vector4>.Default();
- m_SpriteBoneWeights = NativeCustomSlice<BoneWeight>.Default();
- m_SpriteBindPoses = NativeCustomSlice<Matrix4x4>.Default();
- m_SpriteHasTangents = false;
- m_SpriteVertexStreamSize = 0;
- m_SpriteVertexCount = 0;
- m_SpriteTangentVertexOffset = 0;
- }
- else
- {
- var cacheFullMesh = currentDeformationMethod == DeformationMethods.Cpu || forceCpuDeformation;
- if (cacheFullMesh)
- {
- m_SpriteVertices = new NativeCustomSlice<Vector3>(sprite.GetVertexAttribute<Vector3>(VertexAttribute.Position));
- m_SpriteVertexCount = sprite.GetVertexCount();
- m_SpriteVertexStreamSize = sprite.GetVertexStreamSize();
-
- m_SpriteTangents = new NativeCustomSlice<Vector4>(sprite.GetVertexAttribute<Vector4>(VertexAttribute.Tangent));
- m_SpriteHasTangents = sprite.HasVertexAttribute(VertexAttribute.Tangent);
- m_SpriteTangentVertexOffset = sprite.GetVertexStreamOffset(VertexAttribute.Tangent);
- }
- else
- {
- m_SpriteVertices = new NativeCustomSlice<Vector3>(m_StaticOutlineVertexCache);
- m_SpriteVertexCount = m_SpriteVertices.length;
- m_SpriteVertexStreamSize = sizeof(float) * 3;
-
- m_SpriteTangents = new NativeCustomSlice<Vector4>(sprite.GetVertexAttribute<Vector4>(VertexAttribute.Tangent));
- m_SpriteHasTangents = false;
- m_SpriteTangentVertexOffset = 0;
- }
-
- m_SpriteUVs = new NativeCustomSlice<Vector2>(sprite.GetVertexAttribute<Vector2>(VertexAttribute.TexCoord0));
- m_SpriteBoneWeights = new NativeCustomSlice<BoneWeight>(sprite.GetVertexAttribute<BoneWeight>(VertexAttribute.BlendWeight));
- m_SpriteBindPoses = new NativeCustomSlice<Matrix4x4>(sprite.GetBindPoses());
- }
- }
-
- #if ENABLE_URP
- void UpdateDeformedOutlineCache()
- {
- if (sprite == null)
- return;
- if (!m_OutlineIndexCache.IsCreated || !m_DeformedOutlineVertexCache.IsCreated)
- return;
- if (!HasCurrentDeformedVertices())
- return;
-
- var buffer = GetCurrentDeformedVertices();
- var indexCache = m_OutlineIndexCache;
- var vertexCache = m_DeformedOutlineVertexCache;
- BurstedSpriteSkinUtilities.SetVertexPositionFromByteBuffer(in buffer, in indexCache, ref vertexCache, m_SpriteVertexStreamSize);
- m_DeformedOutlineVertexCache = vertexCache;
- }
-
- void CacheSpriteOutline()
- {
- DisposeOutlineCaches();
-
- if (sprite == null)
- return;
-
- CacheOutlineIndices(out var maxIndex);
- var cacheSize = maxIndex + 1;
- CacheOutlineVertices(cacheSize);
- }
-
- void CacheOutlineIndices(out int maxIndex)
- {
- var indices = sprite.GetIndices();
- var edgeNativeArr = MeshUtilities.GetOutlineEdges(in indices);
-
- m_OutlineIndexCache = new NativeArray<int>(edgeNativeArr.Length * 2, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
-
- maxIndex = 0;
- for (var i = 0; i < edgeNativeArr.Length; ++i)
- {
- var indexX = edgeNativeArr[i].x;
- var indexY = edgeNativeArr[i].y;
- m_OutlineIndexCache[i * 2] = indexX;
- m_OutlineIndexCache[(i * 2) + 1] = indexY;
-
- if (indexX > maxIndex)
- maxIndex = indexX;
- if (indexY > maxIndex)
- maxIndex = indexY;
- }
- edgeNativeArr.Dispose();
- }
-
- void CacheOutlineVertices(int cacheSize)
- {
- m_DeformedOutlineVertexCache = new NativeArray<Vector3>(cacheSize, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
- m_StaticOutlineVertexCache = new NativeArray<Vector3>(cacheSize, Allocator.Persistent);
-
- var vertices = sprite.GetVertexAttribute<Vector3>(VertexAttribute.Position);
- var vertexCache = m_StaticOutlineVertexCache;
- for (var i = 0; i < m_OutlineIndexCache.Length; ++i)
- {
- var index = m_OutlineIndexCache[i];
- vertexCache[index] = vertices[index];
- }
-
- m_StaticOutlineVertexCache = vertexCache;
- }
- #endif
- internal void CopyToSpriteSkinData(ref SpriteSkinData data, int spriteSkinIndex)
- {
- if (!m_BoneCacheUpdateToDate)
- {
- RefreshBoneTransforms();
- }
-
- CacheCurrentSprite(m_AutoRebind);
-
- data.vertices = m_SpriteVertices;
- data.boneWeights = m_SpriteBoneWeights;
- data.bindPoses = m_SpriteBindPoses;
- data.tangents = m_SpriteTangents;
- data.hasTangents = m_SpriteHasTangents;
- data.spriteVertexStreamSize = m_SpriteVertexStreamSize;
- data.spriteVertexCount = m_SpriteVertexCount;
- data.tangentVertexOffset = m_SpriteTangentVertexOffset;
- data.transformId = m_TransformId;
- data.boneTransformId = m_BoneTransformIdNativeSlice;
- m_DataIndex = spriteSkinIndex;
- }
-
- internal bool NeedToUpdateDeformationCache()
- {
- unsafe
- {
- var iptr = new IntPtr(sprite.GetVertexAttribute<Vector2>(VertexAttribute.TexCoord0).GetUnsafeReadOnlyPtr());
- var rs = m_SpriteUVs.data != iptr;
- if (rs)
- {
- UpdateSpriteDeformationData();
- deformationSystem.CopyToSpriteSkinData(this);
- DeformationManager.instance.CopyToSpriteSkinData(this);
- }
-
- return rs;
- }
- }
-
- internal void CacheHierarchy()
- {
- using (Profiling.cacheHierarchy.Auto())
- {
- m_HierarchyCache.Clear();
- if (rootBone == null || !m_AutoRebind)
- return;
-
- var boneCount = CountChildren(rootBone);
- m_HierarchyCache.EnsureCapacity(boneCount + 1);
- SpriteSkinHelpers.CacheChildren(rootBone, m_HierarchyCache);
-
- foreach (var entry in m_HierarchyCache)
- {
- if (entry.Value.Count == 1)
- continue;
- var count = entry.Value.Count;
- for (var i = 0; i < count; ++i)
- {
- var transformEntry = entry.Value[i];
- transformEntry.fullName = SpriteSkinHelpers.GenerateTransformPath(rootBone, transformEntry.transform);
- entry.Value[i] = transformEntry;
- }
- }
- }
- }
-
- internal void DeactivateSkinning()
- {
- if (m_SpriteRenderer != null)
- {
- var currentSprite = sprite;
- if (currentSprite != null)
- InternalEngineBridge.SetLocalAABB(m_SpriteRenderer, currentSprite.bounds);
-
- m_SpriteRenderer.DeactivateDeformableBuffer();
- }
-
- m_TransformsHash = 0;
- }
-
- internal void ResetSprite()
- {
- m_CurrentDeformSprite = 0;
- CacheValidFlag();
- }
-
- internal void SetDeformationSystem(BaseDeformationSystem newDeformationSystem)
- {
- deformationSystem = newDeformationSystem;
- currentDeformationMethod = deformationSystem.deformationMethod;
- }
-
- static int CountChildren(Transform transform)
- {
- var childCount = transform.childCount;
- var count = childCount;
- for (var i = 0; i < childCount; ++i)
- count += CountChildren(transform.GetChild(i));
-
- return count;
- }
- }
- }
|