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());
}
}