Files
crtr/Assets/Cryville/Crtr/Motion.cs

501 lines
13 KiB
C#

using Cryville.Common.Buffers;
using Cryville.Common.Collections.Specialized;
using Cryville.Common.Pdt;
using System;
using System.Collections.Generic;
using System.Globalization;
using UnityEngine;
namespace Cryville.Crtr {
public struct MotionRegistry {
readonly Type m_Type;
public Type Type {
get { return m_Type; }
}
readonly Vector m_InitValue;
public Vector InitValue {
get { return m_InitValue.Clone(); }
}
readonly Vector m_GlobalInitValue;
public Vector GlobalInitValue {
get { return m_GlobalInitValue.Clone(); }
}
public MotionRegistry(Type type) : this((Vector)Activator.CreateInstance(type)) { }
public MotionRegistry(Vector init) : this(init, init) { }
public MotionRegistry(Vector init, Vector globalInit) {
m_InitValue = init;
m_GlobalInitValue = globalInit;
if (!init.GetType().Equals(globalInit.GetType())) throw new ArgumentException();
m_Type = init.GetType();
}
}
public class RealtimeMotionValue {
Type _type;
public Vector AbsoluteValue;
public Vector RelativeValue;
public IntKeyedDictionary<MotionNode> RelativeNodes;
internal byte CloneTypeFlag;
public RealtimeMotionValue Init(Vector init) {
_type = init.GetType();
RelativeNodes = new IntKeyedDictionary<MotionNode>();
AbsoluteValue = init;
RelativeValue = (Vector)Activator.CreateInstance(_type);
return this;
}
public RealtimeMotionValue Clone() {
return new RealtimeMotionValue() {
_type = _type,
AbsoluteValue = AbsoluteValue.Clone(),
RelativeValue = RelativeValue.Clone(),
RelativeNodes = RelativeNodes,
};
}
public void CopyTo(RealtimeMotionValue dest, bool cloneNodes) {
AbsoluteValue.CopyTo(dest.AbsoluteValue);
RelativeValue.CopyTo(dest.RelativeValue);
if (cloneNodes) {
dest.ReturnAllRelativeNodes();
foreach (var node in RelativeNodes) {
var dnode = MotionNodePool.Shared.Rent(_type);
node.Value.CopyTo(dnode);
dest.RelativeNodes.Add(node.Key, dnode);
}
}
else dest.RelativeNodes = RelativeNodes;
}
public void ReturnAllRelativeNodes() {
foreach (var node in RelativeNodes) {
MotionNodePool.Shared.Return(_type, node.Value);
}
RelativeNodes.Clear();
}
public MotionNode GetRelativeNode(short id) {
MotionNode result;
RelativeNodes.TryGetValue(id, out result);
return result;
}
public void SetRelativeNode(MotionNode node) {
MotionNode cnode;
if (!RelativeNodes.TryGetValue(node.Id, out cnode)) {
cnode = MotionNodePool.Shared.Rent(_type);
cnode.Id = node.Id;
RelativeNodes.Add(node.Id, cnode);
}
if (node.Time != null) cnode.Time = node.Time;
if (node.EndTime != null) cnode.EndTime = node.EndTime;
if (node.Value != null) node.Value.CopyTo(cnode.Value);
}
/// <summary>
/// Computes the motion value.
/// </summary>
/// <typeparam name="T">The vector type of the value.</typeparam>
/// <param name="result">The result.</param>
public void Compute<T>(ref T result) where T : Vector {
AbsoluteValue.CopyTo(result);
result.ApplyFrom(RelativeValue);
}
}
public class MotionNode {
public short Id = -1;
public bool Reset;
public Vec1 Time;
public Vec1 EndTime;
public PdtExpression Transition;
public Vector Value;
public void Init(Type type) {
if (Time == null) Time = new Vec1(float.NegativeInfinity);
if (EndTime == null) EndTime = new Vec1(float.NegativeInfinity);
if (Value == null) Value = (Vector)Activator.CreateInstance(type);
}
public void CopyTo(MotionNode dest) {
dest.Id = Id;
Time.CopyTo(dest.Time);
EndTime.CopyTo(dest.EndTime);
Value.CopyTo(dest.Value);
}
public void LerpWith(MotionNode start, Vector4 trans, ref MotionNode result) {
result.Id = Id;
if (Time == null) result.Time = start.Time;
else {
var t = (Vector)result.Time;
Time.LerpWith(start.Time, trans, ref t);
}
if (EndTime == null) result.EndTime = start.EndTime;
else {
var t = (Vector)result.EndTime;
EndTime.LerpWith(start.EndTime, trans, ref t);
}
if (Value == null) result.Value = start.Value;
else Value.LerpWith(start.Value, trans, ref result.Value);
}
}
internal class MotionNodePool : CategorizedPool<Type, MotionNode> {
public static MotionNodePool Shared;
private class Bucket : ObjectPool<MotionNode> {
readonly Type _type;
public Bucket(Type type, int capacity) : base(capacity) {
_type = type;
}
protected override MotionNode Construct() {
var result = new MotionNode();
result.Init(_type);
return result;
}
}
readonly Dictionary<Type, ObjectPool<MotionNode>> m_buckets;
protected override IReadOnlyDictionary<Type, ObjectPool<MotionNode>> Buckets { get { return m_buckets; } }
public MotionNodePool() {
m_buckets = new Dictionary<Type, ObjectPool<MotionNode>>();
foreach (var reg in ChartPlayer.motionRegistry) {
var type = reg.Value.Type;
if (!m_buckets.ContainsKey(type))
m_buckets.Add(type, new Bucket(type, 4096));
}
m_buckets.TrimExcess();
}
}
public abstract class Vector {
public Vector() { }
public abstract byte Dimension { get; }
public abstract void ApplyFrom(Vector parent);
public abstract void LerpWith(Vector start, float lerpedTime, ref Vector result);
public abstract void LerpWith(Vector start, Vector4 trans, ref Vector result);
public abstract override string ToString();
public abstract unsafe void ToArray(float* arr);
public Vector Clone() {
return (Vector)MemberwiseClone();
}
public abstract void CopyTo(Vector dest);
static readonly Type[] floatArrayTypeArray = new Type[] { typeof(float[]) };
public static Vector Construct(Type type, float[] values) {
if (!typeof(Vector).IsAssignableFrom(type)) throw new ArgumentException("Type is not vector");
return (Vector)type.GetConstructor(floatArrayTypeArray).Invoke(new object[] { values });
}
}
public class Vec1 : Vector {
public float Value;
public Vec1() { Value = 0; }
public Vec1(float[] v) { Value = v[0]; }
public Vec1(float i) { Value = i; }
public override byte Dimension { get { return 1; } }
public override void ApplyFrom(Vector parent) {
var p = (Vec1)parent;
Value += p.Value;
}
public override void LerpWith(Vector start, float lerpedTime, ref Vector result) {
var r = (Vec1)result;
if (start == null) {
r.Value = Value;
return;
}
var s = (Vec1)start;
r.Value = s.Value * (1 - lerpedTime) + Value * lerpedTime;
}
public override void LerpWith(Vector start, Vector4 trans, ref Vector result) {
var r = (Vec1)result;
if (start == null) {
r.Value = Value;
return;
}
var s = (Vec1)start;
r.Value = s.Value * (1 - trans.x) + Value * trans.x;
}
public override void CopyTo(Vector dest) {
var d = (Vec1)dest;
d.Value = Value;
}
public override string ToString() {
return Value.ToString(CultureInfo.InvariantCulture);
}
public override unsafe void ToArray(float* arr) {
arr[0] = Value;
}
}
public class VecI1 : Vector {
public int Value;
public VecI1() { Value = 0; }
public VecI1(float[] v) { Value = (int)v[0]; }
public VecI1(int i) { Value = i; }
public override byte Dimension { get { return 1; } }
public override void ApplyFrom(Vector parent) {
var p = (VecI1)parent;
Value += p.Value;
}
public override void LerpWith(Vector start, float lerpedTime, ref Vector result) {
var r = (VecI1)result;
if (start == null) {
r.Value = Value;
return;
}
var s = (VecI1)start;
r.Value = (int)(s.Value * (1 - lerpedTime) + Value * lerpedTime);
}
public override void LerpWith(Vector start, Vector4 trans, ref Vector result) {
var r = (VecI1)result;
if (start == null) {
r.Value = Value;
return;
}
var s = (VecI1)start;
r.Value = (int)(s.Value * (1 - trans.x) + Value * trans.x);
}
public override void CopyTo(Vector dest) {
var d = (VecI1)dest;
d.Value = Value;
}
public override string ToString() {
return Value.ToString(CultureInfo.InvariantCulture);
}
public override unsafe void ToArray(float* arr) {
arr[0] = Value;
}
}
public class Vec1m : Vector {
public float Value;
public Vec1m() { Value = 1; }
public Vec1m(float[] v) { Value = v[0]; }
public Vec1m(float i) : base() { Value = i; }
public override byte Dimension { get { return 1; } }
public override void ApplyFrom(Vector parent) {
var p = (Vec1m)parent;
Value *= p.Value;
}
public override void LerpWith(Vector start, float lerpedTime, ref Vector result) {
var r = (Vec1m)result;
if (start == null) {
r.Value = Value;
return;
}
var s = (Vec1m)start;
r.Value = s.Value * (1 - lerpedTime) + Value * lerpedTime;
}
public override void LerpWith(Vector start, Vector4 trans, ref Vector result) {
var r = (Vec1m)result;
if (start == null) {
r.Value = Value;
return;
}
var s = (Vec1m)start;
r.Value = s.Value * (1 - trans.x) + Value * trans.x;
}
public override void CopyTo(Vector dest) {
var d = (Vec1m)dest;
d.Value = Value;
}
public override string ToString() {
return Value.ToString(CultureInfo.InvariantCulture);
}
public override unsafe void ToArray(float* arr) {
arr[0] = Value;
}
}
public class Vec2 : Vector {
float x, y;
public Vec2() { x = y = 0; }
public Vec2(float[] v) { x = v[0]; y = v[1]; }
public Vec2(float x, float y) { this.x = x; this.y = y; }
public override byte Dimension { get { return 2; } }
public override void ApplyFrom(Vector parent) {
var p = (Vec2)parent;
x += p.x; y += p.y;
}
public override void LerpWith(Vector start, float lerpedTime, ref Vector result) {
var r = (Vec2)result;
if (start == null) {
r.x = x;
r.y = y;
return;
}
var s = (Vec2)start;
r.x = s.x * (1 - lerpedTime) + x * lerpedTime;
r.y = s.y * (1 - lerpedTime) + y * lerpedTime;
}
public override void LerpWith(Vector start, Vector4 trans, ref Vector result) {
var r = (Vec2)result;
if (start == null) {
r.x = x;
r.y = y;
return;
}
var s = (Vec2)start;
r.x = s.x * (1 - trans.x) + x * trans.x;
r.y = s.y * (1 - trans.y) + y * trans.y;
}
public Vector3 ToVector2() {
return new Vector3(x, y);
}
public override void CopyTo(Vector dest) {
var d = (Vec2)dest;
d.x = x; d.y = y;
}
public override string ToString() {
return string.Format(CultureInfo.InvariantCulture, "{0},{1}", x, y);
}
public override unsafe void ToArray(float* arr) {
arr[0] = x;
arr[1] = y;
}
}
public class Vec3 : Vector {
float x, y, z;
public Vec3() { x = y = z = 0; }
public Vec3(float[] v) { x = v[0]; y = v[1]; z = v[2]; }
public Vec3(float x, float y, float z) { this.x = x; this.y = y; this.z = z; }
public override byte Dimension { get { return 3; } }
public override void ApplyFrom(Vector parent) {
var p = (Vec3)parent;
x += p.x; y += p.y; z += p.z;
}
public override void LerpWith(Vector start, float lerpedTime, ref Vector result) {
var r = (Vec3)result;
if (start == null) {
r.x = x;
r.y = y;
r.z = z;
return;
}
var s = (Vec3)start;
r.x = s.x * (1 - lerpedTime) + x * lerpedTime;
r.y = s.y * (1 - lerpedTime) + y * lerpedTime;
r.z = s.z * (1 - lerpedTime) + z * lerpedTime;
}
public override void LerpWith(Vector start, Vector4 trans, ref Vector result) {
var r = (Vec3)result;
if (start == null) {
r.x = x;
r.y = y;
r.z = z;
return;
}
var s = (Vec3)start;
r.x = s.x * (1 - trans.x) + x * trans.x;
r.y = s.y * (1 - trans.y) + y * trans.y;
r.z = s.z * (1 - trans.z) + z * trans.z;
}
public Vector3 ToVector3() {
return new Vector3(x, y, z);
}
public override void CopyTo(Vector dest) {
var d = (Vec3)dest;
d.x = x; d.y = y; d.z = z;
}
public override string ToString() {
return string.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", x, y, z);
}
public override unsafe void ToArray(float* arr) {
arr[0] = x;
arr[1] = y;
arr[2] = z;
}
}
public unsafe class VectorSrc : PropSrc.FixedBuffer {
const int MAX_DIMENSION = 4;
protected readonly Func<Vector> _cb;
public VectorSrc(Func<Vector> cb) : base(PdtInternalType.Vector, MAX_DIMENSION * sizeof(float) + sizeof(int)) {
_cb = cb;
fixed (byte* rptr = buf) {
var ptr = (float*)rptr;
*(int*)(ptr + MAX_DIMENSION) = PdtInternalType.Number;
}
}
protected override void InternalGet() {
var v = _cb();
if (v.Dimension > MAX_DIMENSION) throw new NotSupportedException("Vector dimension too large");
fixed (byte* rptr = buf) {
var ptr = (float*)rptr;
v.ToArray(ptr);
}
}
}
public class VectorOp : PropOp {
readonly Action<float[]> _cb;
public VectorOp(Action<float[]> cb) { _cb = cb; }
protected override unsafe void Execute() {
var op = GetOperand(0);
float[] values;
if (op.Type == PdtInternalType.Number) {
values = new float[] { op.AsNumber() };
}
else if (op.Type == PdtInternalType.Vector) {
int type;
op.GetArraySuffix(out type, out _);
if (type != PdtInternalType.Number)
throw new InvalidOperationException("Not a vector of numbers");
values = new float[(op.Length - sizeof(int)) / sizeof(float)];
fixed (float* ptr = values) {
op.CopyTo((byte*)ptr, 0, op.Length - sizeof(int));
}
}
else throw new InvalidOperationException("Invalid operand");
_cb(values);
}
}
}