Add area judge functions.
This commit is contained in:
@@ -195,10 +195,19 @@ namespace Cryville.Crtr {
|
|||||||
|
|
||||||
Func<int, PropSrc> cccb = k => ContextCascadeLookup(k);
|
Func<int, PropSrc> cccb = k => ContextCascadeLookup(k);
|
||||||
_ctxops.Add(IdentifierManager.Shared.Request("attack_timing"), new func_attack_timing(cccb));
|
_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("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("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
|
#region Operators
|
||||||
#pragma warning disable IDE1006
|
#pragma warning disable IDE1006
|
||||||
@@ -637,6 +646,7 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
#region Judge Functions
|
#region Judge Functions
|
||||||
|
#region Timing
|
||||||
static readonly int _var_fn = IdentifierManager.Shared.Request("judge_clip_from");
|
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_tn = IdentifierManager.Shared.Request("judge_clip_to");
|
||||||
static readonly int _var_ft = IdentifierManager.Shared.Request("input_time_from");
|
static readonly int _var_ft = IdentifierManager.Shared.Request("input_time_from");
|
||||||
@@ -703,6 +713,131 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#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 {
|
static unsafe class oputil {
|
||||||
public static float AsNumber(PropSrc src) {
|
public static float AsNumber(PropSrc src) {
|
||||||
if (src == null) throw new ArgumentNullException("src");
|
if (src == null) throw new ArgumentNullException("src");
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
using Cryville.Common.Pdt;
|
using Cryville.Common.Pdt;
|
||||||
using System;
|
using System;
|
||||||
using RBeatTime = Cryville.Crtr.BeatTime;
|
using RBeatTime = Cryville.Crtr.BeatTime;
|
||||||
|
using RVector4 = UnityEngine.Vector4;
|
||||||
|
|
||||||
namespace Cryville.Crtr {
|
namespace Cryville.Crtr {
|
||||||
public abstract class PropSrc {
|
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