using System.Collections.Generic; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; namespace UnityEngine.Animations.Rigging { /// /// CacheIndex is used in AnimationJobCache to recover the index to the cached data. /// public struct CacheIndex { internal int idx; } /// /// AnimationJobCache can be used in animation jobs to store values that /// can be updated through the AnimationJobCache during the Update loop without /// rebuilding the job. /// public struct AnimationJobCache : System.IDisposable { NativeArray m_Data; internal AnimationJobCache(float[] data) { m_Data = new NativeArray(data, Allocator.Persistent); } /// /// Dispose of the AnimationJobCache memory. /// public void Dispose() { m_Data.Dispose(); } /// /// Gets raw float data at specified index. /// /// CacheIndex value. /// Offset to the CacheIndex. /// The raw float data. public float GetRaw(CacheIndex index, int offset = 0) { return m_Data[index.idx + offset]; } /// /// Sets raw float data at specified index. /// /// Raw float data. /// CacheIndex value. /// Offset to the CacheIndex. public void SetRaw(float val, CacheIndex index, int offset = 0) { m_Data[index.idx + offset] = val; } /// /// Gets value at specified index. /// /// CacheIndex value. /// Offset to the CacheIndex. /// The value type. /// unsafe public T Get(CacheIndex index, int offset = 0) where T : unmanaged { int size = UnsafeUtility.SizeOf(); int stride = size / UnsafeUtility.SizeOf(); T val = default(T); UnsafeUtility.MemCpy(&val, (float*)m_Data.GetUnsafeReadOnlyPtr() + index.idx + offset * stride, size); return val; } /// /// Sets value at specified index. /// /// Value. /// CacheIndex value. /// Offset to the CacheIndex. /// unsafe public void Set(T val, CacheIndex index, int offset = 0) where T : unmanaged { int size = UnsafeUtility.SizeOf(); int stride = size / UnsafeUtility.SizeOf(); UnsafeUtility.MemCpy((float*)m_Data.GetUnsafePtr() + index.idx + offset * stride, &val, size); } /// /// Sets an array of values at specified index. /// /// Array of values. /// CacheIndex value. /// Offset to the CacheIndex. /// unsafe public void SetArray(T[] v, CacheIndex index, int offset = 0) where T : unmanaged { int size = UnsafeUtility.SizeOf(); int stride = size / UnsafeUtility.SizeOf(); fixed (void* ptr = v) { UnsafeUtility.MemCpy((float*)m_Data.GetUnsafePtr() + index.idx + offset * stride, ptr, size * v.Length); } } } /// /// AnimationJobCacheBuilder can be used to create a new AnimationJobCache object. /// public class AnimationJobCacheBuilder { List m_Data; /// /// Constructor. /// public AnimationJobCacheBuilder() { m_Data = new List(); } /// /// Adds a float value to the AnimationJobCache. /// /// Float value. /// CacheIndex that refers to the new value. public CacheIndex Add(float v) { m_Data.Add(v); return new CacheIndex { idx = m_Data.Count - 1 }; } /// /// Adds a Vector2 value to the AnimationJobCache. /// /// Vector2 value. /// CacheIndex that refers to the new value. public CacheIndex Add(Vector2 v) { m_Data.Add(v.x); m_Data.Add(v.y); return new CacheIndex { idx = m_Data.Count - 2 }; } /// /// Adds a Vector3 value to the AnimationJobCache. /// /// Vector3 value. /// CacheIndex that refers to the new value. public CacheIndex Add(Vector3 v) { m_Data.Add(v.x); m_Data.Add(v.y); m_Data.Add(v.z); return new CacheIndex { idx = m_Data.Count - 3 }; } /// /// Adds a Vector4 value to the AnimationJobCache. /// /// Vector4 value. /// CacheIndex that refers to the new value. public CacheIndex Add(Vector4 v) { m_Data.Add(v.x); m_Data.Add(v.y); m_Data.Add(v.z); m_Data.Add(v.w); return new CacheIndex { idx = m_Data.Count - 4 }; } /// /// Adds a Quaternion value to the AnimationJobCache. /// /// Quaternion value. /// CacheIndex that refers to the new value. public CacheIndex Add(Quaternion v) { return Add(new Vector4(v.x, v.y, v.z, v.w)); } /// /// Adds a AffineTransform value to the AnimationJobCache. /// /// AffineTransform value. /// CacheIndex that refers to the new value. public CacheIndex Add(AffineTransform tx) { Add(tx.translation); Add(tx.rotation); return new CacheIndex { idx = m_Data.Count - 7 }; } /// /// Allocates uninitialized chunk of specified size in the AnimationJobCacheBuilder. /// /// Size of chunk to allocate. /// CacheIndex that refers to the allocated chunk. public CacheIndex AllocateChunk(int size) { m_Data.AddRange(new float[size]); return new CacheIndex { idx = m_Data.Count - size }; } /// /// Sets value in AnimationJobCacheBuilder at specified index. /// /// CacheIndex value. /// Offset to the CacheIndex. /// float data. public void SetValue(CacheIndex index, int offset, float value) { if (index.idx + offset < m_Data.Count) m_Data[index.idx + offset] = value; } /// /// Creates a new AnimationJobCache. /// /// AnimationJobCache object with newly set values. public AnimationJobCache Build() => new AnimationJobCache(m_Data.ToArray()); } }