Make judge functions return judge time and judge vector.
This commit is contained in:
@@ -687,49 +687,87 @@ namespace Cryville.Crtr {
|
||||
_ctxcb = ctxcb;
|
||||
}
|
||||
protected sealed override void Execute() {
|
||||
var ret = GetReturnFrame(PdtInternalType.Number, sizeof(float));
|
||||
var fn = oputil.AsNumber(_ctxcb(_var_fn));
|
||||
var tn = oputil.AsNumber(_ctxcb(_var_tn));
|
||||
var ft = oputil.AsNumber(_ctxcb(_var_ft));
|
||||
var tt = oputil.AsNumber(_ctxcb(_var_tt));
|
||||
var fv = oputil.AsVector(_ctxcb(_var_fv));
|
||||
var tv = oputil.AsVector(_ctxcb(_var_tv));
|
||||
ret.SetNumber(ExecuteImpl(fn, tn, ft, tt, fv, tv));
|
||||
var result = ExecuteImpl(fn, tn, ft, tt, fv, tv);
|
||||
var ret = GetReturnFrame(PdtInternalType.Vector, 6 * sizeof(float) + sizeof(int));
|
||||
ret.SetArraySuffix(PdtInternalType.Number);
|
||||
ret.SetNumber(result.Value);
|
||||
if (result.Value <= 0) return;
|
||||
ret.SetNumber(result.Time, sizeof(float));
|
||||
Vector4 rv;
|
||||
if (result.Time == ft) {
|
||||
if (!fv.HasValue) {
|
||||
if (result.Time == tt) {
|
||||
if (!tv.HasValue) throw new ArgumentException("Internal judge error");
|
||||
rv = tv.Value;
|
||||
}
|
||||
else throw new ArgumentException("Internal judge error");
|
||||
}
|
||||
else rv = fv.Value;
|
||||
}
|
||||
else if (result.Time == tt) {
|
||||
if (!tv.HasValue) throw new ArgumentException("Internal judge error");
|
||||
rv = tv.Value;
|
||||
}
|
||||
else {
|
||||
if (!fv.HasValue || !tv.HasValue) throw new ArgumentException("Internal judge error");
|
||||
var tr = (result.Time - ft) / (tt - ft);
|
||||
rv = (1 - tr) * fv.Value + tr * tv.Value;
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ret.SetNumber(rv[i], (i + 2) * sizeof(float));
|
||||
}
|
||||
}
|
||||
protected abstract JudgeFunctionResult ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv);
|
||||
protected struct JudgeFunctionResult {
|
||||
/// <summary>
|
||||
/// The result value, represented with a signed distance or a result boolean (0 or 1.)
|
||||
/// </summary>
|
||||
public float Value;
|
||||
public float Time;
|
||||
public JudgeFunctionResult(float value, float time = 0) {
|
||||
Value = value;
|
||||
Time = time;
|
||||
}
|
||||
}
|
||||
protected abstract float ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv);
|
||||
}
|
||||
class func_attack_timing : JudgeFunction {
|
||||
public func_attack_timing(Func<int, PropSrc> ctxcb) : base(2, ctxcb) { }
|
||||
protected override float ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (fv != null) return 0;
|
||||
protected override JudgeFunctionResult ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (fv != null) return new JudgeFunctionResult();
|
||||
var t0 = GetOperand(0).AsNumber() + fn;
|
||||
var t1 = GetOperand(1).AsNumber() + tn;
|
||||
return (tt > t0 && tt <= t1) ? 1 : 0;
|
||||
return new JudgeFunctionResult((tt > t0 && tt <= t1) ? 1 : 0, tt);
|
||||
}
|
||||
}
|
||||
class func_enter_timing : JudgeFunction {
|
||||
public func_enter_timing(Func<int, PropSrc> ctxcb) : base(1, ctxcb) { }
|
||||
protected override float ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (fv == null || tv == null) return 0;
|
||||
protected override JudgeFunctionResult ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (fv == null || tv == null) return new JudgeFunctionResult();
|
||||
var t0 = GetOperand(0).AsNumber() + fn;
|
||||
return (ft < t0 && tt >= t0) ? 1 : 0;
|
||||
return new JudgeFunctionResult((ft < t0 && tt >= t0) ? 1 : 0, t0);
|
||||
}
|
||||
}
|
||||
class func_release_timing : JudgeFunction {
|
||||
public func_release_timing(Func<int, PropSrc> ctxcb) : base(2, ctxcb) { }
|
||||
protected override float ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (tv != null) return 0;
|
||||
protected override JudgeFunctionResult ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (tv != null) return new JudgeFunctionResult();
|
||||
var t0 = GetOperand(0).AsNumber() + fn;
|
||||
var t1 = GetOperand(1).AsNumber() + tn;
|
||||
return (ft > t0 && ft <= t1) ? 1 : 0;
|
||||
return new JudgeFunctionResult((ft > t0 && ft <= t1) ? 1 : 0, ft);
|
||||
}
|
||||
}
|
||||
class func_leave_timing : JudgeFunction {
|
||||
public func_leave_timing(Func<int, PropSrc> ctxcb) : base(1, ctxcb) { }
|
||||
protected override float ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (fv == null || tv == null) return 0;
|
||||
protected override JudgeFunctionResult ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (fv == null || tv == null) return new JudgeFunctionResult();
|
||||
var t1 = GetOperand(0).AsNumber() + tn;
|
||||
return (ft < t1 && tt >= t1) ? 1 : 0;
|
||||
return new JudgeFunctionResult((ft < t1 && tt >= t1) ? 1 : 0, t1);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@@ -741,12 +779,18 @@ namespace Cryville.Crtr {
|
||||
readonly PropOp _areaOp;
|
||||
Vector4 _vec;
|
||||
readonly PropSrc _vecSrc;
|
||||
PdtExpression _areaFunc;
|
||||
public AreaJudgeFunction(int pc, Func<int, PropSrc> ctxcb, Func<int, PdtExpression> jacb, PdtEvaluator etor) : base(pc, ctxcb) {
|
||||
_jacb = jacb;
|
||||
_etor = etor;
|
||||
_areaOp = new PropOp.Float(v => _area = v);
|
||||
_vecSrc = new PropSrc.Vector4(() => _vec);
|
||||
}
|
||||
protected sealed override JudgeFunctionResult ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
_areaFunc = _jacb(GetOperand(2).AsIdentifier());
|
||||
return ExecuteImpl2(fn, tn, ft, tt, fv, tv);
|
||||
}
|
||||
protected abstract JudgeFunctionResult ExecuteImpl2(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv);
|
||||
protected float EvaluateArea(Vector4? vec) {
|
||||
if (vec == null) {
|
||||
_etor.ContextSelfValue = PropSrc.Null;
|
||||
@@ -756,58 +800,64 @@ namespace Cryville.Crtr {
|
||||
_vecSrc.Invalidate();
|
||||
_etor.ContextSelfValue = _vecSrc;
|
||||
}
|
||||
_etor.Evaluate(_areaOp, _jacb(GetOperand(2).AsIdentifier()));
|
||||
_etor.Evaluate(_areaOp, _areaFunc);
|
||||
_etor.ContextSelfValue = null;
|
||||
return _area;
|
||||
}
|
||||
protected bool IntersectsWithAreaBounds(Vector4 fiv, Vector4 tiv, bool enter) {
|
||||
protected JudgeFunctionResult IntersectsWithAreaBounds(float ft, float tt, Vector4 fiv, Vector4 tiv, bool enter) {
|
||||
for (int i = 1; i <= ChartPlayer.areaJudgePrecision; i++) {
|
||||
float r = i / ChartPlayer.areaJudgePrecision;
|
||||
if ((EvaluateArea((1 - r) * fiv + r * tiv) > 0) == enter) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
protected bool GetInternalVectors(float t0, float t1, float ft, float tt, Vector4 fv, Vector4 tv, out Vector4 fiv, out Vector4 tiv) {
|
||||
var dt = tt - ft;
|
||||
if (ft < t0) {
|
||||
if (tt < t0) goto failed;
|
||||
var fr = (t0 - ft) / dt;
|
||||
fiv = (1 - fr) * fv + fr * tv;
|
||||
}
|
||||
else if (ft < t1) {
|
||||
fiv = fv;
|
||||
}
|
||||
else goto failed;
|
||||
|
||||
if (tt < t1) tiv = tv;
|
||||
else {
|
||||
var tr = (t1 - ft) / dt;
|
||||
tiv = (1 - tr) * fv + tr * tv;
|
||||
float r = (float)i / ChartPlayer.areaJudgePrecision;
|
||||
if ((EvaluateArea((1 - r) * fiv + r * tiv) > 0) == enter) {
|
||||
float l = (float)(i - 1) / ChartPlayer.areaJudgePrecision;
|
||||
while (!Mathf.Approximately(l, r)) {
|
||||
float m = (l + r) / 2;
|
||||
float v = EvaluateArea((1 - m) * fiv + m * tiv);
|
||||
if (v == 0) return new JudgeFunctionResult(1, (1 - m) * ft + m * tt);
|
||||
else if ((v > 0) == enter) r = m;
|
||||
else l = m;
|
||||
}
|
||||
return new JudgeFunctionResult(1, (1 - l) * ft + l * tt);
|
||||
}
|
||||
}
|
||||
return new JudgeFunctionResult();
|
||||
}
|
||||
protected bool GetInternalTimeAndVector(float t0, float t1, ref float ft, ref float tt, ref Vector4 fv, ref Vector4 tv) {
|
||||
if (ft < t0) {
|
||||
if (tt < t0) return false;
|
||||
var fr = (t0 - ft) / (tt - ft);
|
||||
ft = (1 - fr) * ft + fr * tt;
|
||||
fv = (1 - fr) * fv + fr * tv;
|
||||
}
|
||||
else if (ft < t1) { }
|
||||
else return false;
|
||||
|
||||
if (tt < t1) { }
|
||||
else {
|
||||
var tr = (t1 - ft) / (tt - ft);
|
||||
tt = (1 - tr) * ft + tr * tt;
|
||||
tv = (1 - tr) * fv + tr * tv;
|
||||
}
|
||||
return true;
|
||||
failed:
|
||||
fiv = tiv = default(Vector4);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
class func_attack_timed_area : AreaJudgeFunction {
|
||||
public func_attack_timed_area(Func<int, PropSrc> ctxcb, Func<int, PdtExpression> jacb, PdtEvaluator etor) : base(3, ctxcb, jacb, etor) { }
|
||||
protected override float ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (fv != null) return 0;
|
||||
protected override JudgeFunctionResult ExecuteImpl2(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (fv != null) return new JudgeFunctionResult();
|
||||
var t0 = GetOperand(0).AsNumber() + fn;
|
||||
var t1 = GetOperand(1).AsNumber() + tn;
|
||||
if (tt <= t0 || tt > t1) return 0;
|
||||
return EvaluateArea(tv);
|
||||
if (tt <= t0 || tt > t1) return new JudgeFunctionResult();
|
||||
return new JudgeFunctionResult(EvaluateArea(tv), tt);
|
||||
}
|
||||
}
|
||||
class func_release_timed_area : AreaJudgeFunction {
|
||||
public func_release_timed_area(Func<int, PropSrc> ctxcb, Func<int, PdtExpression> jacb, PdtEvaluator etor) : base(3, ctxcb, jacb, etor) { }
|
||||
protected override float ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (tv != null) return 0;
|
||||
protected override JudgeFunctionResult ExecuteImpl2(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (tv != null) return new JudgeFunctionResult();
|
||||
var t0 = GetOperand(0).AsNumber() + fn;
|
||||
var t1 = GetOperand(1).AsNumber() + tn;
|
||||
if (ft > t0 && ft <= t1) return 0;
|
||||
return EvaluateArea(fv);
|
||||
if (ft > t0 && ft <= t1) return new JudgeFunctionResult();
|
||||
return new JudgeFunctionResult(EvaluateArea(fv), ft);
|
||||
}
|
||||
}
|
||||
class func_enter_or_leave_timed_area : AreaJudgeFunction {
|
||||
@@ -815,14 +865,14 @@ namespace Cryville.Crtr {
|
||||
public func_enter_or_leave_timed_area(Func<int, PropSrc> ctxcb, Func<int, PdtExpression> jacb, PdtEvaluator etor, bool enter) : base(3, ctxcb, jacb, etor) {
|
||||
_enter = enter;
|
||||
}
|
||||
protected override float ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (fv == null || tv == null) return 0;
|
||||
protected override JudgeFunctionResult ExecuteImpl2(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (fv == null || tv == null) return new JudgeFunctionResult();
|
||||
var t0 = GetOperand(0).AsNumber() + fn;
|
||||
var t1 = GetOperand(1).AsNumber() + tn;
|
||||
Vector4 fiv, tiv;
|
||||
if (!GetInternalVectors(t0, t1, ft, tt, fv.Value, tv.Value, out fiv, out tiv)) return 0;
|
||||
if ((EvaluateArea(fiv) > 0) == _enter) return 0;
|
||||
return IntersectsWithAreaBounds(fiv, tiv, _enter) ? 1 : 0;
|
||||
Vector4 fiv = fv.Value, tiv = tv.Value;
|
||||
if (!GetInternalTimeAndVector(t0, t1, ref ft, ref tt, ref fiv, ref tiv)) return new JudgeFunctionResult();
|
||||
if ((EvaluateArea(fiv) > 0) == _enter) return new JudgeFunctionResult();
|
||||
return IntersectsWithAreaBounds(ft, tt, fiv, tiv, _enter);
|
||||
}
|
||||
}
|
||||
class func_enter_or_leave_timing_area : AreaJudgeFunction {
|
||||
@@ -830,14 +880,14 @@ namespace Cryville.Crtr {
|
||||
public func_enter_or_leave_timing_area(Func<int, PropSrc> ctxcb, Func<int, PdtExpression> jacb, PdtEvaluator etor, bool enter) : base(3, ctxcb, jacb, etor) {
|
||||
_enter = enter;
|
||||
}
|
||||
protected override float ExecuteImpl(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (fv == null || tv == null) return 0;
|
||||
protected override JudgeFunctionResult ExecuteImpl2(float fn, float tn, float ft, float tt, Vector4? fv, Vector4? tv) {
|
||||
if (fv == null || tv == null) return new JudgeFunctionResult();
|
||||
var t0 = GetOperand(0).AsNumber() + fn;
|
||||
var t1 = GetOperand(1).AsNumber() + tn;
|
||||
if ((EvaluateArea(fv) > 0 && ft > t0 && ft < t1) == _enter) return 0;
|
||||
Vector4 fiv, tiv;
|
||||
if (!GetInternalVectors(t0, t1, ft, tt, fv.Value, tv.Value, out fiv, out tiv)) return 0;
|
||||
return IntersectsWithAreaBounds(fiv, tiv, _enter) ? 1 : 0;
|
||||
if ((EvaluateArea(fv) > 0 && ft > t0 && ft < t1) == _enter) return new JudgeFunctionResult();
|
||||
Vector4 fiv = fv.Value, tiv = tv.Value;
|
||||
if (!GetInternalTimeAndVector(t0, t1, ref ft, ref tt, ref fiv, ref tiv)) return new JudgeFunctionResult();
|
||||
return IntersectsWithAreaBounds(ft, tt, fiv, tiv, _enter);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
Reference in New Issue
Block a user