Add area judge functions.
This commit is contained in:
@@ -195,10 +195,19 @@ namespace Cryville.Crtr {
|
||||
|
||||
Func<int, PropSrc> cccb = k => ContextCascadeLookup(k);
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("attack_timing"), new func_attack_timing(cccb));
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("enter_timing"), new func_enter_timing(cccb));
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("release_timing"), new func_release_timing(cccb));
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("leave_timing"), new func_leave_timing(cccb));
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("contact_timing"), new func_contact_timing(cccb));
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("enter_timing"), new func_enter_timing(cccb));
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("leave_timing"), new func_leave_timing(cccb));
|
||||
|
||||
Func<int, PdtExpression> jacb = k => ContextJudge._areaFuncs[new Identifier(k)];
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("attack_timed_area"), new func_attack_timed_area(cccb, jacb, this));
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("release_timed_area"), new func_release_timed_area(cccb, jacb, this));
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("contact_timed_area"), new func_contact_timed_area(cccb, jacb, this));
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("enter_timed_area"), new func_enter_or_leave_timed_area(cccb, jacb, this, true));
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("leave_timed_area"), new func_enter_or_leave_timed_area(cccb, jacb, this, false));
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("enter_timing_area"), new func_enter_or_leave_timing_area(cccb, jacb, this, true));
|
||||
_ctxops.Add(IdentifierManager.Shared.Request("leave_timing_area"), new func_enter_or_leave_timing_area(cccb, jacb, this, false));
|
||||
}
|
||||
#region Operators
|
||||
#pragma warning disable IDE1006
|
||||
@@ -637,6 +646,7 @@ namespace Cryville.Crtr {
|
||||
}
|
||||
#endregion
|
||||
#region Judge Functions
|
||||
#region Timing
|
||||
static readonly int _var_fn = IdentifierManager.Shared.Request("judge_clip_from");
|
||||
static readonly int _var_tn = IdentifierManager.Shared.Request("judge_clip_to");
|
||||
static readonly int _var_ft = IdentifierManager.Shared.Request("input_time_from");
|
||||
@@ -703,6 +713,131 @@ namespace Cryville.Crtr {
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Timed Area
|
||||
abstract class AreaJudgeFunction : JudgeFunction {
|
||||
readonly Func<int, PdtExpression> _jacb;
|
||||
readonly PdtEvaluator _etor;
|
||||
float _area;
|
||||
readonly PropOp _areaOp;
|
||||
Vector4 _vec;
|
||||
readonly PropSrc _vecSrc;
|
||||
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 float EvaluateArea(Vector4? vec) {
|
||||
if (vec == null) {
|
||||
_etor.ContextSelfValue = PropSrc.Null;
|
||||
}
|
||||
else {
|
||||
_vec = vec.Value;
|
||||
_vecSrc.Invalidate();
|
||||
_etor.ContextSelfValue = _vecSrc;
|
||||
}
|
||||
_etor.Evaluate(_areaOp, _jacb(GetOperand(2).AsIdentifier()));
|
||||
_etor.ContextSelfValue = null;
|
||||
return _area;
|
||||
}
|
||||
protected bool IntersectsWithAreaBounds(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;
|
||||
else if (tt < t1) tiv = tv;
|
||||
else {
|
||||
var tr = (t1 - ft) / dt;
|
||||
tiv = (1 - tr) * fv + tr * tv;
|
||||
}
|
||||
var fr = (t0 - ft) / dt;
|
||||
fiv = (1 - fr) * fv + fr * tv;
|
||||
}
|
||||
else if (ft < t1) {
|
||||
fiv = fv;
|
||||
if (tt < t1) tiv = tv;
|
||||
else {
|
||||
var tr = (t1 - ft) / dt;
|
||||
tiv = (1 - tr) * fv + tr * tv;
|
||||
}
|
||||
}
|
||||
else goto failed;
|
||||
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;
|
||||
var t0 = GetOperand(0).AsNumber() + fn;
|
||||
var t1 = GetOperand(1).AsNumber() + tn;
|
||||
if (tt <= t0 || tt > t1) return 0;
|
||||
return EvaluateArea(tv);
|
||||
}
|
||||
}
|
||||
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;
|
||||
var t0 = GetOperand(0).AsNumber() + fn;
|
||||
var t1 = GetOperand(1).AsNumber() + tn;
|
||||
if (ft > t0 && ft <= t1) return 0;
|
||||
return EvaluateArea(fv);
|
||||
}
|
||||
}
|
||||
class func_contact_timed_area : AreaJudgeFunction {
|
||||
public func_contact_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 || tv == null) return 0;
|
||||
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) return 1;
|
||||
return IntersectsWithAreaBounds(fiv, tiv, true) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
class func_enter_or_leave_timed_area : AreaJudgeFunction {
|
||||
readonly bool _enter;
|
||||
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;
|
||||
if ((EvaluateArea(fv) > 0) == _enter) return 0;
|
||||
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;
|
||||
return IntersectsWithAreaBounds(fiv, tiv, _enter) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
class func_enter_or_leave_timing_area : AreaJudgeFunction {
|
||||
readonly bool _enter;
|
||||
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;
|
||||
var t0 = GetOperand(0).AsNumber() + fn;
|
||||
var t1 = GetOperand(1).AsNumber() + tn;
|
||||
if ((EvaluateArea(fv) > 0 && ft > t0 && tt < 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;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
static unsafe class oputil {
|
||||
public static float AsNumber(PropSrc src) {
|
||||
if (src == null) throw new ArgumentNullException("src");
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using Cryville.Common.Pdt;
|
||||
using System;
|
||||
using RBeatTime = Cryville.Crtr.BeatTime;
|
||||
using RVector4 = UnityEngine.Vector4;
|
||||
|
||||
namespace Cryville.Crtr {
|
||||
public abstract class PropSrc {
|
||||
@@ -95,5 +96,21 @@ namespace Cryville.Crtr {
|
||||
}
|
||||
}
|
||||
}
|
||||
public class Vector4 : FixedBuffer {
|
||||
readonly Func<RVector4> _cb;
|
||||
public Vector4(Func<RVector4> cb) : base(PdtInternalType.Vector, 4 * sizeof(float) + sizeof(int)) { _cb = cb; }
|
||||
protected unsafe override void InternalGet() {
|
||||
base.InternalGet();
|
||||
var vec = _cb();
|
||||
fixed (byte* _ptr = buf) {
|
||||
float* ptr = (float*)_ptr;
|
||||
*ptr++ = vec.x;
|
||||
*ptr++ = vec.y;
|
||||
*ptr++ = vec.z;
|
||||
*ptr++ = vec.w;
|
||||
*(int*)ptr = PdtInternalType.Number;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user