using Cryville.Common; using Cryville.Common.Pdt; using System; using System.Collections.Generic; using System.Reflection; using RBeatTime = Cryville.Crtr.BeatTime; using RClip = Cryville.Crtr.Clip; using RTargetString = Cryville.Common.Buffers.TargetString; 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); ChartPlayer.etor.ContextCascadeUpdate(Name, new PropSrc.Arbitrary(op.Type, value)); } } public class Boolean : PropOp { readonly Action _cb; public Boolean(Action cb) { _cb = cb; } protected override void Execute() { _cb(GetOperand(0).AsNumber() > 0); } } public class Clip : PropOp { readonly Action _cb; public Clip(Action cb) : base(2) { _cb = 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 : PropOp { readonly Action _cb; public Integer(Action cb) { _cb = cb; } protected override void Execute() { _cb((int)GetOperand(0).AsNumber()); } } public class Float : PropOp { readonly Action _cb; public Float(Action cb) { _cb = cb; } protected override void Execute() { _cb(GetOperand(0).AsNumber()); } } public class String : PropOp { readonly Action _cb; public String(Action cb) { _cb = cb; } protected override void Execute() { _cb(GetOperand(0).AsString()); } } public class TargetString : PropOp { readonly Func _cb; public TargetString(Func cb) { _cb = cb; } protected override unsafe void Execute() { var target = _cb(); var op = GetOperand(0); if (op.Type != PdtInternalType.String) throw new ArgumentException("Not a string"); var ptr = (byte*)op.TrustedAsOfLength(op.Length); var len = *(int*)ptr; target.Length = len; var cptr = (char*)(ptr + sizeof(int)); for (int i = 0; i < len; i++) target[i] = cptr[i]; target.Validate(); } } public class Identifier : PropOp { readonly Action _cb; public Identifier(Action cb) { _cb = cb; } protected override void Execute() { _cb(GetOperand(0).AsIdentifier()); } } public class Enum : PropOp { readonly static Dictionary _cache = new Dictionary(); readonly Action _cb; readonly Func _caster; public Enum(Action cb, Func caster) { 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.SharedInstance.Request(names[i].Name)] = Convert.ToInt32(names[i].GetValue(null)); _cb = cb; _caster = caster; } protected override void Execute() { int result = 0; for (int i = 0; i < LoadedOperandCount; i++) result |= _cache[GetOperand(0).AsIdentifier()]; _cb(_caster(result)); } } public class BeatTime : PropOp { readonly Action _cb; public BeatTime(Action cb) { _cb = cb; } protected override unsafe void Execute() { var o = GetOperand(0); _cb(*(RBeatTime*)o.TrustedAsOfLength(sizeof(RBeatTime))); } } public class Vector2 : PropOp { readonly Action _cb; public Vector2(Action cb) { _cb = 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 UnityEngine.Vector2(num, num)); break; case 2: _cb(*(UnityEngine.Vector2*)o.TrustedAsOfLength(sizeof(UnityEngine.Vector2))); break; default: throw new InvalidOperationException("Invalid array size"); } } } public class Vector3 : PropOp { readonly Action _cb; public Vector3(Action cb) { _cb = 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 UnityEngine.Vector3(num, num)); break; case 2: _cb(*(UnityEngine.Vector2*)o.TrustedAsOfLength(sizeof(UnityEngine.Vector2))); break; case 3: _cb(*(UnityEngine.Vector3*)o.TrustedAsOfLength(sizeof(UnityEngine.Vector3))); break; default: throw new InvalidOperationException("Invalid array size"); } } } public class Color : PropOp { readonly Action _cb; public Color(Action cb) { _cb = cb; } protected override unsafe void Execute() { var o = GetOperand(0); switch ((o.Length - 4) / 4) { case 3: var ptr = (float*)o.TrustedAsOfLength(sizeof(float) * 3); _cb(new UnityEngine.Color(ptr[0], ptr[1], ptr[2])); break; case 4: _cb(*(UnityEngine.Color*)o.TrustedAsOfLength(sizeof(UnityEngine.Color))); break; default: throw new InvalidOperationException("Invalid array size"); } } } } }