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 : PropOp { protected readonly Action _cb; public Fixed(Action cb) { _cb = cb; } public Fixed(int pc, Action cb) : base(pc) { _cb = cb; } } public class Boolean : Fixed { public Boolean(Action cb) : base(cb) { } protected override void Execute() { _cb(GetOperand(0).AsNumber() > 0); } } public class Clip : Fixed { public Clip(Action 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 { public Integer(Action cb) : base(cb) { } protected override void Execute() { _cb((int)GetOperand(0).AsNumber()); } } public class Float : Fixed { public Float(Action cb) : base(cb) { } protected override void Execute() { _cb(GetOperand(0).AsNumber()); } } public class String : Fixed { public String(Action cb) : base(cb) { } protected override void Execute() { _cb(GetOperand(0).AsString()); } } public class StringArray : Fixed { public StringArray(Action 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 _cb; public TargetString(Func 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(); target.Length = len; for (int i = 0; i < len; i++) target[i] = op.As(sizeof(int) + i * sizeof(char)); target.Validate(); } } public class Identifier : Fixed { public Identifier(Action cb) : base(cb) { } protected override void Execute() { _cb(GetOperand(0).AsIdentifier()); } } public class Enum : Fixed { readonly Type _type; readonly IntKeyedDictionary _cache = new(); public Enum(Type type, Action 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 : Fixed { static readonly IntKeyedDictionary _cache = new(); readonly Func _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 cb, Func 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 { public BeatTime(Action cb) : base(cb) { } protected override unsafe void Execute() { var o = GetOperand(0); _cb(o.As()); } } public class Vector2 : Fixed { public Vector2(Action 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()); break; default: throw new InvalidOperationException("Invalid array size"); } } } public class Vector3 : Fixed { public Vector3(Action 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()); break; case 3: _cb(o.As()); break; default: throw new InvalidOperationException("Invalid array size"); } } } public class Vector4 : Fixed { public Vector4(Action 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()); break; case 3: _cb(o.As()); break; case 4: _cb(o.As()); break; default: throw new InvalidOperationException("Invalid array size"); } } } public class Color : Fixed { public Color(Action cb) : base(cb) { } protected override unsafe void Execute() { var o = GetOperand(0); switch ((o.Length - 4) / 4) { case 3: _cb(new RColor(o.As(), o.As(sizeof(float)), o.As(2 * sizeof(float)))); break; case 4: _cb(o.As()); break; default: throw new InvalidOperationException("Invalid array size"); } } } } }