Files
crtr/Assets/Cryville/Crtr/Evaluator.cs
2022-09-30 17:32:21 +08:00

332 lines
11 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Cryville.Common;
using Cryville.Common.Pdt;
using Cryville.Crtr.Components;
using Cryville.Crtr.Event;
using UnityEngine;
namespace Cryville.Crtr {
#if false
[Obsolete]
public struct Evaluator : IEvaluator {
public object ParseNumber(string exp) {
return float.Parse(exp);
}
public object ParseString(string exp) {
return exp;
}
public object EvalIdentifier(string exp) {
if (exp[0] == '$') {
var r = Context.State.GetRawValue<Vector>(new MotionName(exp.Substring(1)));
if (r is Vec1) return ((Vec1)r).Value;
if (r is Vec1m) return ((Vec1m)r).Value;
if (r is Vec3) return ((Vec3)r).ToVector3();
if (r is VecI1) return ((VecI1)r).Value;
if (r is VecPt) return ((VecPt)r).ToVector2(ChartPlayer.hitRect);
if (r is VecPtComp) return ((VecPtComp)r).ToFloat(ChartPlayer.hitRect);
throw new NotImplementedException();
}
switch (exp) {
case "w": return ChartPlayer.hitRect.width;
case "h": return ChartPlayer.hitRect.height;
case "true": return true;
case "false": return false;
case "pos":
return Context.State.Handler.Position;
// return ctx.Transform.position;
default:
if (Context.Extra != null && Context.Extra.ContainsKey(exp))
return Context.Extra[exp];
if (Context.Reservations != null && Context.Reservations.Contains(exp))
throw new Exception();
if (Context.State == null && !Context.DisableLiteralString)
return exp;
return Context.State.Container.Properties[exp]();
}
}
public object OperateUnary(Operand op, object q) {
switch (op.exp) {
case "-":
if (q is float) return -(float)q;
else throw new NotImplementedException();
default:
throw new NotImplementedException();
}
}
public object OperateBinary(Operand op, object q, object r) {
switch (op.exp) {
case "+":
if (!(q is float && r is float))
throw new ArgumentException(); // TODO
return (float)q + (float)r;
case "-":
if (!(q is float && r is float))
throw new ArgumentException(); // TODO
return (float)q - (float)r;
case "*":
if (!(q is float && r is float))
throw new ArgumentException(); // TODO
return (float)q * (float)r;
case "/":
if (!(q is float && r is float))
throw new ArgumentException(); // TODO
return (float)q / (float)r;
case " ":
if (typeof(List<object>).IsAssignableFrom(q.GetType())) {
((List<object>)q).Add(r);
return q;
}
else {
return new List<object>(){q, r};
}
case ",":
if (q is Stack) {
((Stack)q).Push(r);
return q;
}
else {
var s = new Stack();
s.Push(q); s.Push(r);
return s;
}
default:
throw new NotImplementedException();
}
}
public object OperateFunction(Operand op, object q) {
switch (op.exp) {
case "circle":
var lcirc = (Stack)q;
var radius = (float)Cast(typeof(float), lcirc.Pop());
var circcenter = (Vector2)Cast(typeof(Vector2), lcirc.Pop());
return ((Vector2)Context.Extra["-hitpos"] - circcenter).sqrMagnitude - radius * radius;
case "dist":
var ldist = (Stack)q;
var rhs = (Vector3)Cast(typeof(Vector3), ldist.Pop());
var lhs = (Vector3)Cast(typeof(Vector3), ldist.Pop());
return (lhs - rhs).magnitude;
case "frame_seq":
var lframeseq = (Stack)q;
var ub = (int)(float)Cast(typeof(float), lframeseq.Pop());
var lb = (int)(float)Cast(typeof(float), lframeseq.Pop());
var prefix = (string)lframeseq.Pop();
var frames = new List<object>();
for (int i = lb; i <= ub; i++) {
frames.Add(prefix + i.ToString());
}
return frames;
case "rect":
var lrect = (Stack)q;
var recth = (float)Cast(typeof(float), lrect.Pop()) / 2;
var rectw = (float)Cast(typeof(float), lrect.Pop()) / 2;
var rectcenter = (Vector2)Cast(typeof(Vector2), lrect.Pop());
var recthit = (Vector2)Context.Extra["-hitpos"] - rectcenter;
return (Mathf.Abs(recthit.x) <= Mathf.Abs(rectw) && Mathf.Abs(recthit.y) <= Mathf.Abs(recth)) ? -1f : 1f;
case "screen_edge":
float dist;
var ray = new Ray(Context.Transform.position, Context.Transform.rotation * Vector3.forward);
ChartPlayer.frustumPlanes[(int)(float)q].Raycast(ray, out dist);
return ray.GetPoint(dist);
default:
throw new NotImplementedException(
string.Format("Unknown function: {0}", op.exp)
);
}
}
// TODO [Obsolete]
public object Cast(Type type, object obj) {
if (type.IsAssignableFrom(obj.GetType()))
return obj;
if (typeof(ICollection).IsAssignableFrom(obj.GetType())) {
var o = ((ICollection)obj).Cast<object>().ToList();
if (obj is Stack) o.Reverse();
if (type == typeof(Color)) {
return new Color(
(float)o[0],
(float)o[1],
(float)o[2],
o.Count >= 4 ? (float)o[3] : 1
);
}
else if (type == typeof(Vector3)) {
float z = o.Count >= 3 ? (float)o[2] : 0;
return new Vector3((float)o[0], (float)o[1], z);
}
else if (type == typeof(Vector2)) {
return new Vector2((float)o[0], (float)o[1]);
}
else if (type == typeof(string)) {
return string.Join(",", o.Cast<string>().ToArray());
}
else if (type.BaseType == typeof(Array)) {
var etype = type.GetElementType();
IList r = (IList)ReflectionHelper.InvokeEmptyConstructor(typeof(List<>).MakeGenericType(etype));
foreach (var i in o) {
r.Add(Cast(etype, i));
}
return typeof(Enumerable).GetMethod("ToArray")
.MakeGenericMethod(etype).Invoke(
null, new object[]{r}
);
}
else if (typeof(IList).IsAssignableFrom(type)) {
var etype = type.GetGenericArguments()[0];
IList r = (IList)ReflectionHelper.InvokeEmptyConstructor(typeof(List<>).MakeGenericType(etype));
foreach (var i in o) {
r.Add(Cast(etype, i));
}
return r;
}
}
else if (obj is float) {
float g = (float)obj;
if (type == typeof(Vector3)) {
return new Vector3(g, g, g);
}
else if (type == typeof(Vector2)) {
return new Vector2(g, g);
}
else if (typeof(IConvertible).IsAssignableFrom(type)) {
return ((IConvertible)g).ToInt16(null);
}
}
if (type.IsEnum) {
return Enum.Parse(type, (string)Cast(typeof(string), obj), true);
}
else if (typeof(IConstructable).IsAssignableFrom(type)) {
var r = (IConstructable)Activator.CreateInstance(type);
r.Load(obj, this);
return r;
}
else if (typeof(IList).IsAssignableFrom(type)) {
IList r = (IList)ReflectionHelper.InvokeEmptyConstructor(typeof(List<>).MakeGenericType(obj.GetType()));
r.Add(obj);
return r;
}
throw new InvalidCastException(String.Format("Cannot cast {0} to {1}", obj.GetType(), type));
}
public EvaluatorContext Context { get; set; }
/*object CastBypass(object obj) { return obj; }
object CastListColor(object obj) {
var o = (IList)obj;
float a = o.Count >= 4 ? (float)o[3] : 1;
return new Color(
(float)o[0],
(float)o[1],
(float)o[2],
a
);
}
object CastListVector3(object obj) {
var o = (IList)obj;
float z = o.Count >= 3 ? (float)o[2] : 0;
return new Vector3((float)o[0], (float)o[1], z);
}
object CastListVector2(object obj) {
var o = (IList)obj;
return new Vector2((float)o[0], (float)o[1]);
}
object CastListString(object obj) {
var o = (IList)obj;
return String.Join(",", o.Cast<string>().ToArray());
}
object CastListArray(object obj) {
var o = (IList)obj;
var etype = dest.GetElementType();
IList r = (IList)ReflectionHelper.InvokeEmptyConstructor(typeof(List<>).MakeGenericType(etype));
foreach (var i in o) {
r.Add(Cast(etype, i));
}
return typeof(Enumerable).GetMethod("ToArray")
.MakeGenericMethod(etype).Invoke(
null, new object[] { r }
);
}
object CastNumberVector3(object obj) {
var o = (float)obj;
return new Vector3(o, o, o);
}
object CastNumberVector2(object obj) {
var o = (float)obj;
return new Vector2(o, o);
}
object CastNumberBypass(object obj) {
var o = (float)obj;
return ((IConvertible)o).ToInt16(null);
}
object CastListEnum(object obj) {
var o = (float)obj;
return ((IConvertible)o).ToInt16(null);
}
public override CastCallback GetCastCallback(Type dest, Type source) {
if (dest.IsAssignableFrom(source)) return new CastCallback(CastBypass);
if (typeof(IList).IsAssignableFrom(source)) {
if (dest == typeof(Color)) return new CastCallback(CastListColor);
if (dest == typeof(Vector3)) return new CastCallback(CastListVector3);
if (dest == typeof(Vector2)) return new CastCallback(CastListVector2);
if (dest == typeof(string)) return new CastCallback(CastListString);
if (dest.BaseType == typeof(Array)) {
var etype = type.GetElementType();
IList r = (IList)ReflectionHelper.InvokeEmptyConstructor(typeof(List<>).MakeGenericType(etype));
foreach (var i in o) {
r.Add(Cast(etype, i));
}
return typeof(Enumerable).GetMethod("ToArray")
.MakeGenericMethod(etype).Invoke(
null, new object[] { r }
);
}
else if (typeof(IList).IsAssignableFrom(type)) {
var etype = type.GetGenericArguments()[0];
IList r = (IList)ReflectionHelper.InvokeEmptyConstructor(typeof(List<>).MakeGenericType(etype));
foreach (var i in o) {
r.Add(Cast(etype, i));
}
return r;
}
}
else if (source == typeof(float)) {
if (dest == typeof(Vector3)) return new CastCallback(CastNumberVector3);
if (dest == typeof(Vector2)) return new CastCallback(CastNumberVector2);
if (typeof(IConvertible).IsAssignableFrom(dest)) return new CastCallback(CastNumberBypass);
}
if (type.IsEnum) {
return Enum.Parse(type, (string)Cast(typeof(string), obj), true);
}
else if (typeof(IConstructable).IsAssignableFrom(type)) {
var r = (IConstructable)Activator.CreateInstance(type);
r.Load(obj, this);
return r;
}
else if (typeof(IList).IsAssignableFrom(type)) {
IList r = (IList)ReflectionHelper.InvokeEmptyConstructor(typeof(List<>).MakeGenericType(obj.GetType()));
r.Add(obj);
return r;
}
throw new NotImplementedException();
}*/
}
/*class CastCallback {
public Func<object, object> Callback { get; set; }
public CastCallback Nested { get; set; }
public CastCallback(Func<object, object> cb, CastCallback ncc = null) {
Callback = cb;
Nested = ncc;
}
}*/
[Obsolete]
public struct EvaluatorContext {
public ContainerState State;
public Transform Transform;
public Dictionary<string, object> Extra;
public List<string> Reservations;
public bool DisableLiteralString;
}
#endif
}