Add stub for "call" judge action.

This commit is contained in:
2023-06-02 18:20:20 +08:00
parent d5ba09cbea
commit 832facdf5b
2 changed files with 61 additions and 13 deletions

View File

@@ -16,7 +16,7 @@ namespace Cryville.Crtr {
public float? Time { get; set; }
public Vector4 Vector { get; set; }
}
internal struct JudgeEvent {
internal class JudgeEvent {
public double StartTime { get; set; }
public double EndTime { get; set; }
public double StartClip { get; set; }
@@ -25,8 +25,16 @@ namespace Cryville.Crtr {
public JudgeDefinition Definition { get; set; }
public NoteHandler Handler { get; set; }
public JudgeResult JudgeResult { get; set; }
public JudgeCallContext CallContext { get; set; }
}
internal struct JudgeCallContext {
public bool CalledOnMiss { get; set; }
public float CallTime { get; set; }
public JudgeEvent ReturnEvent { get; set; }
public int ReturnIndex { get; set; }
}
internal interface IJudge {
void Call(JudgeEvent ev, float time, Identifier id, bool onMiss, int index);
bool Pass(JudgeEvent ev, float time, Identifier[] ids, int depth);
void UpdateScore(ScoreOperation op, PdtExpression exp);
}
@@ -85,7 +93,7 @@ namespace Cryville.Crtr {
var tev = (Chart.Judge)sev.Unstamped;
InsertEvent(tev, new Clip((float)sev.Time, (float)(sev.Time + sev.Duration)), tev.Id, handler);
}
void InsertEvent(Chart.Judge ev, Clip clip, Identifier id, NoteHandler handler) {
void InsertEvent(Chart.Judge ev, Clip clip, Identifier id, NoteHandler handler, JudgeCallContext call = default(JudgeCallContext)) {
if (id.Key == _var_pause) throw new InvalidOperationException("Cannot assign the special judge \"pause\" to notes");
var def = _rs.judges[id];
_etor.Evaluate(_identop, def.input);
@@ -99,6 +107,7 @@ namespace Cryville.Crtr {
BaseEvent = ev,
Definition = def,
Handler = handler,
CallContext = call,
};
var index = list.BinarySearch(jev, _stcmp);
if (index < 0) index = ~index;
@@ -236,7 +245,7 @@ namespace Cryville.Crtr {
_numbuf2 = (float)hitEvent.EndTime; _numsrc2.Invalidate(); _etor.ContextCascadeUpdate(_var_tn, _numsrc2);
var def = hitEvent.Definition;
if (def == _judgePause) _sys.TogglePause();
if (def.on_hit != null) Execute(hitEvent, (ft + tt) / 2, def.on_hit);
if (def.on_hit != null) Execute(hitEvent, (ft + tt) / 2, def.on_hit, false);
if (def.persist != null) _etor.Evaluate(_flagop, def.persist);
else _flag = false;
if (!_flag) {
@@ -259,7 +268,7 @@ namespace Cryville.Crtr {
JudgeEvent ev = actlist[i];
if (tt > ev.EndClip) {
actlist.RemoveAt(i);
if (ev.Definition.on_miss != null) Execute(ev, tt, ev.Definition.on_miss);
Execute(ev, tt, ev.Definition.on_miss, true);
}
}
}
@@ -275,14 +284,36 @@ namespace Cryville.Crtr {
actlist.Insert(index, ev);
}
}
void Execute(JudgeEvent ev, float time, PairList<JudgeAction, PdtExpression> actions, int depth = 0) {
void Execute(JudgeEvent ev, float time, PairList<JudgeAction, PdtExpression> actions, bool onMiss, int depth = 0, int index = 0) {
if (ev.JudgeResult.Time != null) {
_jnumbuf = ev.JudgeResult.Time.Value; _jnumsrc.Invalidate(); _etor.ContextCascadeUpdate(_var_jt, _jnumsrc);
_jvecbuf = ev.JudgeResult.Vector; _jvecsrc.Invalidate(); _etor.ContextCascadeUpdate(_var_jv, _jvecsrc);
}
foreach (var a in actions) {
if (a.Key.Execute(this, ev, time, a.Value, depth)) break;
if (actions != null) {
// Ensure that all actions that modifies judge result sources break the execution
for (int i = index; i < actions.Count; i++) {
var a = actions[i];
if (a.Key.Execute(this, ev, time, a.Value, onMiss, depth, i).BreakExecution) break;
}
}
else {
var call = ev.CallContext;
if (call.ReturnEvent != null) {
// TODO
if (onMiss)
Execute(call.ReturnEvent, time, call.ReturnEvent.Definition.on_miss, true, depth + 1, 0);
else
Execute(call.ReturnEvent, time, call.ReturnEvent.Definition.on_hit, false, depth + 1, call.ReturnIndex);
}
}
}
void IJudge.Call(JudgeEvent ev, float time, Identifier id, bool onMiss, int index) {
InsertEvent(ev.BaseEvent, new Clip((float)ev.StartTime, (float)ev.EndTime), id, ev.Handler, new JudgeCallContext {
CalledOnMiss = onMiss,
CallTime = time,
ReturnEvent = ev,
ReturnIndex = index + 1,
}); // TODO optimize GC
}
bool IJudge.Pass(JudgeEvent ev, float time, Identifier[] ids, int depth) {
if (depth >= 16) throw new JudgePropagationException();
@@ -296,7 +327,7 @@ namespace Cryville.Crtr {
}
else hitFlag = true;
if (hitFlag) {
Execute(ev, time, def.on_hit, depth + 1);
Execute(ev, time, def.on_hit, false, depth + 1);
ev.Handler.ReportJudge(ev, time, i);
return true;
}