214 lines
6.8 KiB
C#
214 lines
6.8 KiB
C#
using Cryville.Common;
|
|
using Cryville.Common.Collections.Specialized;
|
|
using Cryville.Common.Pdt;
|
|
using System;
|
|
using System.Reflection;
|
|
using RBeatTime = Cryville.Crtr.BeatTime;
|
|
using RClip = Cryville.Crtr.Clip;
|
|
using RColor = UnityEngine.Color;
|
|
using RTargetString = Cryville.Common.Buffers.TargetString;
|
|
using RVector2 = UnityEngine.Vector2;
|
|
using RVector3 = UnityEngine.Vector3;
|
|
using RVector4 = UnityEngine.Vector4;
|
|
|
|
namespace Cryville.Crtr {
|
|
public abstract class PropOp : PdtOperator {
|
|
protected PropOp() : base(1) { }
|
|
protected PropOp(int pc) : base(pc) { }
|
|
public class Arbitrary : PropOp {
|
|
public int Name { get; set; }
|
|
protected override void Execute() {
|
|
var op = GetOperand(0);
|
|
var value = new byte[op.Length];
|
|
op.CopyTo(value, 0);
|
|
PdtEvaluator.Instance.ContextCascadeUpdate(Name, new PropSrc.Arbitrary(op.Type, value));
|
|
}
|
|
}
|
|
public abstract class Fixed<T> : PropOp {
|
|
protected readonly Action<T> _cb;
|
|
public Fixed(Action<T> cb) { _cb = cb; }
|
|
public Fixed(int pc, Action<T> cb) : base(pc) { _cb = cb; }
|
|
}
|
|
public class Boolean : Fixed<bool> {
|
|
public Boolean(Action<bool> cb) : base(cb) { }
|
|
protected override void Execute() {
|
|
_cb(GetOperand(0).AsNumber() > 0);
|
|
}
|
|
}
|
|
public class Clip : Fixed<RClip> {
|
|
public Clip(Action<RClip> cb) : base(2, cb) { }
|
|
protected override void Execute() {
|
|
if (LoadedOperandCount < 2)
|
|
throw new ArgumentException("Invalid clip syntax");
|
|
_cb(new RClip(GetOperand(0).AsNumber(), GetOperand(1).AsNumber()));
|
|
}
|
|
}
|
|
public class Integer : Fixed<int> {
|
|
public Integer(Action<int> cb) : base(cb) { }
|
|
protected override void Execute() {
|
|
_cb((int)GetOperand(0).AsNumber());
|
|
}
|
|
}
|
|
public class Float : Fixed<float> {
|
|
public Float(Action<float> cb) : base(cb) { }
|
|
protected override void Execute() {
|
|
_cb(GetOperand(0).AsNumber());
|
|
}
|
|
}
|
|
public class String : Fixed<string> {
|
|
public String(Action<string> cb) : base(cb) { }
|
|
protected override void Execute() {
|
|
_cb(GetOperand(0).AsString());
|
|
}
|
|
}
|
|
public class StringArray : Fixed<string[]> {
|
|
public StringArray(Action<string[]> cb) : base(cb) { }
|
|
protected override unsafe void Execute() {
|
|
var op = GetOperand(0);
|
|
op.GetArraySuffix(out int arrtype, out int len);
|
|
if (arrtype != PdtInternalType.String) throw new InvalidCastException("Not an array of strings");
|
|
var result = new string[len];
|
|
int o = 0;
|
|
for (int i = 0; i < len; i++) {
|
|
string v = op.AsString(o);
|
|
o += v.Length * sizeof(char) + sizeof(int);
|
|
result[i] = v;
|
|
}
|
|
_cb(result);
|
|
}
|
|
}
|
|
public class TargetString : PropOp {
|
|
readonly Func<RTargetString> _cb;
|
|
public TargetString(Func<RTargetString> cb) { _cb = cb; }
|
|
protected override void Execute() {
|
|
var target = _cb();
|
|
var op = GetOperand(0);
|
|
if (op.Type != PdtInternalType.String) throw new ArgumentException("Not a string");
|
|
int len = op.As<int>();
|
|
target.Length = len;
|
|
for (int i = 0; i < len; i++)
|
|
target[i] = op.As<char>(sizeof(int) + i * sizeof(char));
|
|
target.Validate();
|
|
}
|
|
}
|
|
public class Identifier : Fixed<int> {
|
|
public Identifier(Action<int> cb) : base(cb) { }
|
|
protected override void Execute() {
|
|
_cb(GetOperand(0).AsIdentifier());
|
|
}
|
|
}
|
|
public class Enum : Fixed<object> {
|
|
readonly Type _type;
|
|
readonly IntKeyedDictionary<int> _cache = new();
|
|
public Enum(Type type, Action<object> cb) : base(cb) {
|
|
if (!type.IsEnum)
|
|
throw new ArgumentException("Type is not enum");
|
|
_type = type;
|
|
var names = type.GetFields(BindingFlags.Public | BindingFlags.Static);
|
|
for (int i = 0; i < names.Length; i++)
|
|
_cache[IdentifierManager.Shared.Request(names[i].Name)] = Convert.ToInt32(names[i].GetValue(null));
|
|
}
|
|
protected override void Execute() {
|
|
int result = 0;
|
|
for (int i = 0; i < LoadedOperandCount; i++)
|
|
result |= _cache[GetOperand(i).AsIdentifier()];
|
|
_cb(System.Enum.ToObject(_type, result));
|
|
}
|
|
}
|
|
public class Enum<T> : Fixed<T> {
|
|
static readonly IntKeyedDictionary<int> _cache = new();
|
|
readonly Func<int, T> _caster;
|
|
static Enum() {
|
|
if (!typeof(T).IsEnum)
|
|
throw new ArgumentException("Type is not enum");
|
|
var names = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static);
|
|
for (int i = 0; i < names.Length; i++)
|
|
_cache[IdentifierManager.Shared.Request(names[i].Name)] = Convert.ToInt32(names[i].GetValue(null));
|
|
}
|
|
public Enum(Action<T> cb, Func<int, T> caster) : base(cb) {
|
|
_caster = caster;
|
|
}
|
|
protected override void Execute() {
|
|
int result = 0;
|
|
for (int i = 0; i < LoadedOperandCount; i++)
|
|
result |= _cache[GetOperand(i).AsIdentifier()];
|
|
_cb(_caster(result));
|
|
}
|
|
}
|
|
public class BeatTime : Fixed<RBeatTime> {
|
|
public BeatTime(Action<RBeatTime> cb) : base(cb) { }
|
|
protected override unsafe void Execute() {
|
|
var o = GetOperand(0);
|
|
_cb(o.As<RBeatTime>());
|
|
}
|
|
}
|
|
public class Vector2 : Fixed<RVector2> {
|
|
public Vector2(Action<RVector2> cb) : base(cb) { }
|
|
protected override unsafe void Execute() {
|
|
var o = GetOperand(0);
|
|
switch ((o.Length - 4) / 4) {
|
|
case 0: // Number
|
|
case 1: // Array[1]
|
|
float num = o.AsNumber();
|
|
_cb(new RVector2(num, num));
|
|
break;
|
|
case 2:
|
|
_cb(o.As<RVector2>());
|
|
break;
|
|
default:
|
|
throw new InvalidOperationException("Invalid array size");
|
|
}
|
|
}
|
|
}
|
|
public class Vector3 : Fixed<RVector3> {
|
|
public Vector3(Action<RVector3> cb) : base(cb) { }
|
|
protected override unsafe void Execute() {
|
|
var o = GetOperand(0);
|
|
switch ((o.Length - 4) / 4) {
|
|
case 0: // Number
|
|
case 1: // Array[1]
|
|
float num = o.AsNumber();
|
|
_cb(new RVector3(num, num));
|
|
break;
|
|
case 2: _cb(o.As<RVector2>()); break;
|
|
case 3: _cb(o.As<RVector3>()); break;
|
|
default: throw new InvalidOperationException("Invalid array size");
|
|
}
|
|
}
|
|
}
|
|
public class Vector4 : Fixed<RVector4> {
|
|
public Vector4(Action<RVector4> cb) : base(cb) { }
|
|
protected override unsafe void Execute() {
|
|
var o = GetOperand(0);
|
|
switch ((o.Length - 4) / 4) {
|
|
case 0: // Number
|
|
case 1: // Array[1]
|
|
float num = o.AsNumber();
|
|
_cb(new RVector4(num, num, num, num));
|
|
break;
|
|
case 2: _cb(o.As<RVector2>()); break;
|
|
case 3: _cb(o.As<RVector3>()); break;
|
|
case 4: _cb(o.As<RVector4>()); break;
|
|
default: throw new InvalidOperationException("Invalid array size");
|
|
}
|
|
}
|
|
}
|
|
public class Color : Fixed<RColor> {
|
|
public Color(Action<RColor> cb) : base(cb) { }
|
|
protected override unsafe void Execute() {
|
|
var o = GetOperand(0);
|
|
switch ((o.Length - 4) / 4) {
|
|
case 3:
|
|
_cb(new RColor(o.As<float>(), o.As<float>(sizeof(float)), o.As<float>(2 * sizeof(float))));
|
|
break;
|
|
case 4:
|
|
_cb(o.As<RColor>());
|
|
break;
|
|
default:
|
|
throw new InvalidOperationException("Invalid array size");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|