123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- using System;
- using System.Collections.Generic;
- using Unity.Collections;
- using Unity.Collections.LowLevel.Unsafe;
- using Unity.Jobs;
- using Unity.Mathematics;
- using Unity.Profiling;
- using UnityEngine.U2D.Common;
-
- namespace UnityEngine.U2D.Animation
- {
- internal abstract class BaseDeformationSystem
- {
- protected static class Profiling
- {
- public static readonly ProfilerMarker transformAccessJob = new ProfilerMarker("BaseDeformationSystem.TransformAccessJob");
- public static readonly ProfilerMarker getSpriteSkinBatchData = new ProfilerMarker("BaseDeformationSystem.GetSpriteSkinBatchData");
- public static readonly ProfilerMarker scheduleJobs = new ProfilerMarker("BaseDeformationSystem.ScheduleJobs");
- public static readonly ProfilerMarker setBatchDeformableBufferAndLocalAABB = new ProfilerMarker("BaseDeformationSystem.SetBatchDeformableBufferAndLocalAABB");
- public static readonly ProfilerMarker setBoneTransformsArray = new ProfilerMarker("BaseDeformationSystem.SetBoneTransformsArray");
- }
-
- public abstract DeformationMethods deformationMethod { get; }
-
- protected int m_ObjectId;
-
- protected readonly HashSet<SpriteSkin> m_SpriteSkins = new HashSet<SpriteSkin>();
- protected SpriteRenderer[] m_SpriteRenderers = new SpriteRenderer[0];
-
- readonly HashSet<SpriteSkin> m_SpriteSkinsToAdd = new HashSet<SpriteSkin>();
- readonly HashSet<SpriteSkin> m_SpriteSkinsToRemove = new HashSet<SpriteSkin>();
- readonly List<int> m_TransformIdsToRemove = new List<int>();
-
- protected NativeByteArray m_DeformedVerticesBuffer;
- protected NativeArray<float4x4> m_FinalBoneTransforms;
-
- protected NativeArray<bool> m_IsSpriteSkinActiveForDeform;
- protected NativeArray<SpriteSkinData> m_SpriteSkinData;
- protected NativeArray<PerSkinJobData> m_PerSkinJobData;
- protected NativeArray<Bounds> m_BoundsData;
- protected NativeArray<IntPtr> m_Buffers;
- protected NativeArray<int> m_BufferSizes;
- protected NativeArray<IntPtr> m_BoneTransformBuffers;
-
- protected NativeArray<int2> m_BoneLookupData;
- protected NativeArray<int2> m_VertexLookupData;
- protected NativeArray<PerSkinJobData> m_SkinBatchArray;
-
- TransformAccessJob m_LocalToWorldTransformAccessJob;
- TransformAccessJob m_WorldToLocalTransformAccessJob;
-
- protected JobHandle m_DeformJobHandle;
-
- internal void RemoveBoneTransforms(SpriteSkin spriteSkin)
- {
- if (!m_SpriteSkins.Contains(spriteSkin))
- return;
-
- m_LocalToWorldTransformAccessJob.RemoveTransformById(spriteSkin.rootBoneTransformId);
- var boneTransforms = spriteSkin.boneTransformId;
- if (boneTransforms == default || !boneTransforms.IsCreated)
- return;
-
- for (var i = 0; i < boneTransforms.Length; ++i)
- m_LocalToWorldTransformAccessJob.RemoveTransformById(boneTransforms[i]);
- }
-
- internal void AddBoneTransforms(SpriteSkin spriteSkin)
- {
- if (!m_SpriteSkins.Contains(spriteSkin))
- return;
-
- m_LocalToWorldTransformAccessJob.AddTransform(spriteSkin.rootBone);
- if (spriteSkin.boneTransforms != null)
- {
- foreach (var t in spriteSkin.boneTransforms)
- {
- if (t != null)
- m_LocalToWorldTransformAccessJob.AddTransform(t);
- }
- }
- }
- internal virtual void UpdateMaterial(SpriteSkin spriteSkin) { }
-
- internal virtual bool AddSpriteSkin(SpriteSkin spriteSkin)
- {
- if (!m_SpriteSkins.Contains(spriteSkin) && !m_SpriteSkinsToAdd.Contains(spriteSkin))
- {
- m_SpriteSkinsToAdd.Add(spriteSkin);
- return true;
- }
-
- if (m_SpriteSkinsToRemove.Contains(spriteSkin))
- {
- m_SpriteSkinsToAdd.Add(spriteSkin);
- return true;
- }
-
- return false;
- }
-
- internal void CopyToSpriteSkinData(SpriteSkin spriteSkin)
- {
- CopyToSpriteSkinDataAtIndex(spriteSkin, spriteSkin.dataIndex);
- }
-
- void CopyToSpriteSkinDataAtIndex(SpriteSkin spriteSkin, int index)
- {
- if (index < 0 || index >= m_SpriteSkins.Count)
- return;
- if (!m_SpriteSkinData.IsCreated)
- return;
-
- var spriteSkinData = default(SpriteSkinData);
- spriteSkin.CopyToSpriteSkinData(ref spriteSkinData, index);
- m_SpriteSkinData[index] = spriteSkinData;
- m_SpriteRenderers[index] = spriteSkin.spriteRenderer;
- }
-
- internal void RemoveSpriteSkin(SpriteSkin spriteSkin)
- {
- if (spriteSkin == null)
- return;
-
- if (m_SpriteSkins.Contains(spriteSkin) && !m_SpriteSkinsToRemove.Contains(spriteSkin))
- {
- m_SpriteSkinsToRemove.Add(spriteSkin);
- m_TransformIdsToRemove.Add(spriteSkin.transform.GetInstanceID());
- }
-
- if (m_SpriteSkinsToAdd.Contains(spriteSkin))
- m_SpriteSkinsToAdd.Remove(spriteSkin);
-
- RemoveBoneTransforms(spriteSkin);
- }
-
- internal HashSet<SpriteSkin> GetSpriteSkins()
- {
- return m_SpriteSkins;
- }
-
- internal void Initialize(int objectId)
- {
- m_ObjectId = objectId;
-
- if (m_LocalToWorldTransformAccessJob == null)
- m_LocalToWorldTransformAccessJob = new TransformAccessJob();
- if (m_WorldToLocalTransformAccessJob == null)
- m_WorldToLocalTransformAccessJob = new TransformAccessJob();
-
- InitializeArrays();
- BatchRemoveSpriteSkins();
- BatchAddSpriteSkins();
-
- // Initialise all existing SpriteSkins as execution order is indeterminate
- var count = 0;
- foreach (var spriteSkin in m_SpriteSkins)
- {
- CopyToSpriteSkinDataAtIndex(spriteSkin, count++);
- }
- }
-
- protected virtual void InitializeArrays()
- {
- const int startingCount = 0;
-
- m_FinalBoneTransforms = new NativeArray<float4x4>(startingCount, Allocator.Persistent);
- m_BoneLookupData = new NativeArray<int2>(startingCount, Allocator.Persistent);
- m_VertexLookupData = new NativeArray<int2>(startingCount, Allocator.Persistent);
- m_SkinBatchArray = new NativeArray<PerSkinJobData>(startingCount, Allocator.Persistent);
-
- m_IsSpriteSkinActiveForDeform = new NativeArray<bool>(startingCount, Allocator.Persistent);
- m_PerSkinJobData = new NativeArray<PerSkinJobData>(startingCount, Allocator.Persistent);
- m_SpriteSkinData = new NativeArray<SpriteSkinData>(startingCount, Allocator.Persistent);
- m_BoundsData = new NativeArray<Bounds>(startingCount, Allocator.Persistent);
- m_Buffers = new NativeArray<IntPtr>(startingCount, Allocator.Persistent);
- m_BufferSizes = new NativeArray<int>(startingCount, Allocator.Persistent);
- }
-
- protected void BatchRemoveSpriteSkins()
- {
- var spritesToRemoveCount = m_SpriteSkinsToRemove.Count;
- if (spritesToRemoveCount == 0)
- return;
-
- m_WorldToLocalTransformAccessJob.RemoveTransformsByIds(m_TransformIdsToRemove);
-
- var updatedCount = Math.Max(m_SpriteSkins.Count - spritesToRemoveCount, 0);
- if (updatedCount == 0)
- {
- m_SpriteSkins.Clear();
- }
- else
- {
- foreach (var spriteSkin in m_SpriteSkinsToRemove)
- m_SpriteSkins.Remove(spriteSkin);
- }
-
- var count = 0;
- foreach (var spriteSkin in m_SpriteSkins)
- CopyToSpriteSkinDataAtIndex(spriteSkin, count++);
-
- Array.Resize(ref m_SpriteRenderers, updatedCount);
- ResizeAndCopyArrays(updatedCount);
-
- m_TransformIdsToRemove.Clear();
- m_SpriteSkinsToRemove.Clear();
- }
-
- protected void BatchAddSpriteSkins()
- {
- if (m_SpriteSkinsToAdd.Count == 0)
- return;
-
- var updatedCount = m_SpriteSkins.Count + m_SpriteSkinsToAdd.Count;
- Array.Resize(ref m_SpriteRenderers, updatedCount);
- if (m_IsSpriteSkinActiveForDeform.IsCreated)
- ResizeAndCopyArrays(updatedCount);
-
- foreach (var spriteSkin in m_SpriteSkinsToAdd)
- {
- if (m_SpriteSkins.Contains(spriteSkin))
- {
- Debug.LogError($"Skin already exists! Name={spriteSkin.name}");
- continue;
- }
-
- m_SpriteSkins.Add(spriteSkin);
- UpdateMaterial(spriteSkin);
- var count = m_SpriteSkins.Count;
-
- m_SpriteRenderers[count - 1] = spriteSkin.spriteRenderer;
- m_WorldToLocalTransformAccessJob.AddTransform(spriteSkin.transform);
-
- if (m_IsSpriteSkinActiveForDeform.IsCreated)
- {
- AddBoneTransforms(spriteSkin);
- CopyToSpriteSkinDataAtIndex(spriteSkin, count - 1);
- }
- }
-
- m_SpriteSkinsToAdd.Clear();
- }
-
- protected virtual void ResizeAndCopyArrays(int updatedCount)
- {
- NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_IsSpriteSkinActiveForDeform, updatedCount);
- NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_PerSkinJobData, updatedCount);
- NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_Buffers, updatedCount);
- NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_BufferSizes, updatedCount);
- NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_SpriteSkinData, updatedCount);
- NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_BoundsData, updatedCount);
- }
-
- internal virtual void Cleanup()
- {
- m_DeformJobHandle.Complete();
-
- m_SpriteSkins.Clear();
- m_SpriteRenderers = new SpriteRenderer[0];
- BufferManager.instance.ReturnBuffer(m_ObjectId);
- m_IsSpriteSkinActiveForDeform.DisposeIfCreated();
- m_PerSkinJobData.DisposeIfCreated();
- m_Buffers.DisposeIfCreated();
- m_BufferSizes.DisposeIfCreated();
- m_SpriteSkinData.DisposeIfCreated();
- m_BoneLookupData.DisposeIfCreated();
- m_VertexLookupData.DisposeIfCreated();
- m_SkinBatchArray.DisposeIfCreated();
- m_FinalBoneTransforms.DisposeIfCreated();
- m_BoundsData.DisposeIfCreated();
-
- m_LocalToWorldTransformAccessJob.Destroy();
- m_WorldToLocalTransformAccessJob.Destroy();
- }
-
- internal abstract void Update();
-
- protected void PrepareDataForDeformation(out JobHandle localToWorldJobHandle, out JobHandle worldToLocalJobHandle)
- {
- ValidateSpriteSkinData();
-
- using (Profiling.transformAccessJob.Auto())
- {
- localToWorldJobHandle = m_LocalToWorldTransformAccessJob.StartLocalToWorldJob();
- worldToLocalJobHandle = m_WorldToLocalTransformAccessJob.StartWorldToLocalJob();
- }
-
- using (Profiling.getSpriteSkinBatchData.Auto())
- {
- NativeArrayHelpers.ResizeIfNeeded(ref m_SkinBatchArray, 1);
- var fillPerSkinJobSingleThread = new FillPerSkinJobSingleThread()
- {
- isSpriteSkinValidForDeformArray = m_IsSpriteSkinActiveForDeform,
- combinedSkinBatchArray = m_SkinBatchArray,
- spriteSkinDataArray = m_SpriteSkinData,
- perSkinJobDataArray = m_PerSkinJobData,
- };
- fillPerSkinJobSingleThread.Run();
- }
- }
-
- void ValidateSpriteSkinData()
- {
- var count = 0;
- foreach (var spriteSkin in m_SpriteSkins)
- {
- var i = count++;
- m_IsSpriteSkinActiveForDeform[i] = spriteSkin.BatchValidate();
- if (m_IsSpriteSkinActiveForDeform[i] && spriteSkin.NeedToUpdateDeformationCache())
- {
- CopyToSpriteSkinDataAtIndex(spriteSkin, i);
- }
- }
- }
-
- protected bool GotVerticesToDeform(out int vertexBufferSize)
- {
- vertexBufferSize = m_SkinBatchArray[0].deformVerticesStartPos;
- return vertexBufferSize > 0;
- }
-
- protected JobHandle SchedulePrepareJob(int batchCount)
- {
- var prepareJob = new PrepareDeformJob
- {
- batchDataSize = batchCount,
- perSkinJobData = m_PerSkinJobData,
- boneLookupData = m_BoneLookupData,
- vertexLookupData = m_VertexLookupData
- };
- return prepareJob.Schedule();
- }
-
- protected JobHandle ScheduleBoneJobBatched(JobHandle jobHandle, PerSkinJobData skinBatch)
- {
- var boneJobBatched = new BoneDeformBatchedJob()
- {
- boneTransform = m_LocalToWorldTransformAccessJob.transformMatrix,
- rootTransform = m_WorldToLocalTransformAccessJob.transformMatrix,
- spriteSkinData = m_SpriteSkinData,
- boneLookupData = m_BoneLookupData,
- finalBoneTransforms = m_FinalBoneTransforms,
- rootTransformIndex = m_WorldToLocalTransformAccessJob.transformData,
- boneTransformIndex = m_LocalToWorldTransformAccessJob.transformData
- };
- jobHandle = boneJobBatched.Schedule(skinBatch.bindPosesIndex.y, 8, jobHandle);
- return jobHandle;
- }
-
- protected JobHandle ScheduleSkinDeformBatchedJob(JobHandle jobHandle, PerSkinJobData skinBatch)
- {
- var skinJobBatched = new SkinDeformBatchedJob()
- {
- vertices = m_DeformedVerticesBuffer.array,
- vertexLookupData = m_VertexLookupData,
- spriteSkinData = m_SpriteSkinData,
- perSkinJobData = m_PerSkinJobData,
- finalBoneTransforms = m_FinalBoneTransforms,
- };
- return skinJobBatched.Schedule(skinBatch.verticesIndex.y, 16, jobHandle);
- }
-
- protected unsafe JobHandle ScheduleCopySpriteRendererBuffersJob(JobHandle jobHandle, int batchCount)
- {
- var copySpriteRendererBuffersJob = new CopySpriteRendererBuffersJob()
- {
- isSpriteSkinValidForDeformArray = m_IsSpriteSkinActiveForDeform,
- spriteSkinData = m_SpriteSkinData,
- ptrVertices = (IntPtr)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(m_DeformedVerticesBuffer.array),
- buffers = m_Buffers,
- bufferSizes = m_BufferSizes,
- };
- return copySpriteRendererBuffersJob.Schedule(batchCount, 16, jobHandle);
- }
-
- protected JobHandle ScheduleCalculateSpriteSkinAABBJob(JobHandle jobHandle, int batchCount)
- {
- var updateBoundJob = new CalculateSpriteSkinAABBJob
- {
- vertices = m_DeformedVerticesBuffer.array,
- isSpriteSkinValidForDeformArray = m_IsSpriteSkinActiveForDeform,
- spriteSkinData = m_SpriteSkinData,
- bounds = m_BoundsData,
- };
- return updateBoundJob.Schedule(batchCount, 4, jobHandle);
- }
-
- protected void DeactivateDeformableBuffers()
- {
- for (var i = 0; i < m_IsSpriteSkinActiveForDeform.Length; ++i)
- {
- if (m_IsSpriteSkinActiveForDeform[i] || InternalEngineBridge.IsUsingDeformableBuffer(m_SpriteRenderers[i], IntPtr.Zero))
- continue;
- m_SpriteRenderers[i].DeactivateDeformableBuffer();
- }
- }
-
- internal bool IsSpriteSkinActiveForDeformation(SpriteSkin spriteSkin)
- {
- return m_IsSpriteSkinActiveForDeform[spriteSkin.dataIndex];
- }
-
- internal unsafe NativeArray<byte> GetDeformableBufferForSpriteSkin(SpriteSkin spriteSkin)
- {
- if (!m_SpriteSkins.Contains(spriteSkin))
- return default;
-
- if (!m_DeformJobHandle.IsCompleted)
- m_DeformJobHandle.Complete();
-
- var skinData = m_SpriteSkinData[spriteSkin.dataIndex];
- if (skinData.deformVerticesStartPos < 0)
- return default;
-
- var vertexBufferLength = skinData.spriteVertexCount * skinData.spriteVertexStreamSize;
- var ptrVertices = (byte*)m_DeformedVerticesBuffer.array.GetUnsafeReadOnlyPtr();
- ptrVertices += skinData.deformVerticesStartPos;
- var buffer = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<byte>(ptrVertices, vertexBufferLength, Allocator.None);
- #if ENABLE_UNITY_COLLECTIONS_CHECKS
- NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref buffer, NativeArrayUnsafeUtility.GetAtomicSafetyHandle(m_DeformedVerticesBuffer.array));
- #endif
- return buffer;
- }
-
- #if UNITY_INCLUDE_TESTS
- internal TransformAccessJob GetWorldToLocalTransformAccessJob() => m_WorldToLocalTransformAccessJob;
- internal TransformAccessJob GetLocalToWorldTransformAccessJob() => m_LocalToWorldTransformAccessJob;
- #endif
- }
- }
|