10 Commits

14 changed files with 257 additions and 87 deletions

View File

@@ -34,6 +34,16 @@ namespace Cryville.Common.Pdt {
} }
} }
/// <summary> /// <summary>
/// Patches an expression with a lefthand variable and a compound operator.
/// </summary>
/// <param name="target">The name of the lefthand variable.</param>
/// <param name="op">The name of the compound operator.</param>
/// <param name="exp">The expression.</param>
public void PatchCompound(int target, int op, PdtExpression exp) {
exp.Instructions.AddFirst(new PdtInstruction.PushVariable(target));
exp.Instructions.AddLast(new PdtInstruction.Operate(op, 2));
}
/// <summary>
/// Optimizes an expression by merging its instructions. /// Optimizes an expression by merging its instructions.
/// </summary> /// </summary>
/// <param name="exp">The expression to optimize.</param> /// <param name="exp">The expression to optimize.</param>

View File

@@ -51,9 +51,8 @@ namespace Cryville.Common.Pdt {
} }
public class PushVariable : PdtInstruction { public class PushVariable : PdtInstruction {
public int Name { get; private set; } public int Name { get; private set; }
public PushVariable(string name) { public PushVariable(int name) { Name = name; }
Name = IdentifierManager.SharedInstance.Request(name); public PushVariable(string name) : this(IdentifierManager.SharedInstance.Request(name)) { }
}
internal override void Execute(PdtEvaluatorBase etor) { internal override void Execute(PdtEvaluatorBase etor) {
etor.PushVariable(Name); etor.PushVariable(Name);
} }
@@ -63,6 +62,9 @@ namespace Cryville.Common.Pdt {
} }
public class Operate : PdtInstruction { public class Operate : PdtInstruction {
public PdtOperatorSignature Signature { get; private set; } public PdtOperatorSignature Signature { get; private set; }
public Operate(int name, int paramCount) {
Signature = new PdtOperatorSignature(name, paramCount);
}
public Operate(string name, int paramCount) { public Operate(string name, int paramCount) {
Signature = new PdtOperatorSignature(name, paramCount); Signature = new PdtOperatorSignature(name, paramCount);
} }

View File

@@ -50,7 +50,7 @@ namespace Cryville.Common.Unity.Input {
} }
public abstract string GetKeyName(int type); public abstract string GetKeyName(int type);
void Update() { void Update() {
double time = Time.timeAsDouble; double time = Time.realtimeSinceStartupAsDouble;
foreach (var k in Keys) { foreach (var k in Keys) {
Callback(k, 0, new InputVector(time, Vector3.zero)); Callback(k, 0, new InputVector(time, Vector3.zero));
} }
@@ -64,7 +64,7 @@ namespace Cryville.Common.Unity.Input {
void OnGUI() { void OnGUI() {
var e = Event.current; var e = Event.current;
if (e.keyCode == KeyCode.None) return; if (e.keyCode == KeyCode.None) return;
double time = Time.timeAsDouble; double time = Time.realtimeSinceStartupAsDouble;
var key = (int)e.keyCode; var key = (int)e.keyCode;
switch (e.type) { switch (e.type) {
case EventType.KeyDown: case EventType.KeyDown:
@@ -92,7 +92,7 @@ namespace Cryville.Common.Unity.Input {
} }
void OnGUI() { void OnGUI() {
var e = Event.current; var e = Event.current;
double time = Time.timeAsDouble; double time = Time.realtimeSinceStartupAsDouble;
var key = e.button; var key = e.button;
switch (e.type) { switch (e.type) {
case EventType.MouseDown: case EventType.MouseDown:

View File

@@ -54,7 +54,7 @@ namespace Cryville.Common.Unity.Input {
handler = h; handler = h;
} }
void Update() { void Update() {
double time = Time.timeAsDouble; double time = Time.realtimeSinceStartupAsDouble;
Vector3 pos = UnityCameraUtils.ScreenToWorldPoint(unity::Input.mousePosition); Vector3 pos = UnityCameraUtils.ScreenToWorldPoint(unity::Input.mousePosition);
handler.Feed(0, 0, new InputVector(time, pos)); handler.Feed(0, 0, new InputVector(time, pos));
} }

View File

@@ -54,7 +54,7 @@ namespace Cryville.Common.Unity.Input {
handler = h; handler = h;
} }
void Update() { void Update() {
double time = Time.timeAsDouble; double time = Time.realtimeSinceStartupAsDouble;
for (int i = 0; i < unity::Input.touchCount; i++) { for (int i = 0; i < unity::Input.touchCount; i++) {
var t = unity::Input.GetTouch(i); var t = unity::Input.GetTouch(i);
Vector2 pos = UnityCameraUtils.ScreenToWorldPoint(t.position); Vector2 pos = UnityCameraUtils.ScreenToWorldPoint(t.position);

View File

@@ -504,11 +504,11 @@ namespace Cryville.Crtr {
cbus = batcher.Batch(); cbus = batcher.Batch();
Logger.Log("main", 0, "Load/WorkerThread", "Batched {0} event batches", cbus.events.Count); Logger.Log("main", 0, "Load/WorkerThread", "Batched {0} event batches", cbus.events.Count);
LoadSkin(info.skinFile);
judge = new Judge(pruleset); judge = new Judge(pruleset);
etor.ContextJudge = judge; etor.ContextJudge = judge;
LoadSkin(info.skinFile);
cbus.AttachSystems(pskin, judge); cbus.AttachSystems(pskin, judge);
Logger.Log("main", 0, "Load/WorkerThread", "Attaching handlers"); Logger.Log("main", 0, "Load/WorkerThread", "Attaching handlers");
var ch = new ChartHandler(chart, dir); var ch = new ChartHandler(chart, dir);

View File

@@ -96,6 +96,7 @@ namespace Cryville.Crtr.Components {
float sum_x; float sum_x;
void UpdateMeshes() { void UpdateMeshes() {
// TODO optimize GC
if (meshes.Count == 0) return; if (meshes.Count == 0) return;
sum_x = 0; sum_x = 0;
int vc = m_value.Length * 4; int vc = m_value.Length * 4;

View File

@@ -162,19 +162,13 @@ namespace Cryville.Crtr {
PropSrc.Arbitrary fv, tv = _etor.ContextCascadeLookup(_var_value); PropSrc.Arbitrary fv, tv = _etor.ContextCascadeLookup(_var_value);
if (!_vecs.TryGetValue(pid, out fv)) fv = new PropSrc.Arbitrary(PdtInternalType.Null, _nullvalue); if (!_vecs.TryGetValue(pid, out fv)) fv = new PropSrc.Arbitrary(PdtInternalType.Null, _nullvalue);
if (fv.Type != PdtInternalType.Null || tv.Type != PdtInternalType.Null) { if (fv.Type != PdtInternalType.Null || tv.Type != PdtInternalType.Null) {
if (fv.Type == PdtInternalType.Null) { if (fv.Type == PdtInternalType.Null) _activeCounts[id.Source]++;
_activeCounts[id.Source]++;
Logger.Log("main", 0, "Input/Proxy", "active {0} # {1} (+)", id.Source, _activeCounts[id.Source]);
}
_etor.ContextCascadeInsert(); _etor.ContextCascadeInsert();
_etor.ContextCascadeUpdate(_var_fv, fv); _etor.ContextCascadeUpdate(_var_fv, fv);
_etor.ContextCascadeUpdate(_var_tv, tv); _etor.ContextCascadeUpdate(_var_tv, tv);
_judge.Feed(target, ft, tt); _judge.Feed(target, ft, tt);
_etor.ContextCascadeDiscard(); _etor.ContextCascadeDiscard();
if (tv.Type == PdtInternalType.Null) { if (tv.Type == PdtInternalType.Null) _activeCounts[id.Source]--;
_activeCounts[id.Source]--;
Logger.Log("main", 0, "Input/Proxy", "active {0} # {1} (-)", id.Source, _activeCounts[id.Source]);
}
} }
_judge.Cleanup(target, ft, tt); _judge.Cleanup(target, ft, tt);
_vecs[pid] = tv; _vecs[pid] = tv;

View File

@@ -16,28 +16,27 @@ namespace Cryville.Crtr {
struct JudgeEvent { struct JudgeEvent {
public float StartTime { get; set; } public float StartTime { get; set; }
public float EndTime { get; set; } public float EndTime { get; set; }
public float StartClip { get; set; }
public float EndClip { get; set; }
public JudgeDefinition Definition { get; set; } public JudgeDefinition Definition { get; set; }
public ContainerState State { get; set; } public ContainerState State { get; set; }
} }
static IComparer<JudgeEvent> _stcmp = new JudgeEventStartTimeComparer(); static readonly IComparer<JudgeEvent> _stcmp = new JudgeEventStartTimeComparer();
class JudgeEventStartTimeComparer : IComparer<JudgeEvent> { class JudgeEventStartTimeComparer : IComparer<JudgeEvent> {
public int Compare(JudgeEvent x, JudgeEvent y) { public int Compare(JudgeEvent x, JudgeEvent y) {
return x.StartTime.CompareTo(y.StartTime); return x.StartClip.CompareTo(y.StartClip);
}
}
static IComparer<JudgeEvent> _etcmp = new JudgeEventEndTimeComparer();
class JudgeEventEndTimeComparer : IComparer<JudgeEvent> {
public int Compare(JudgeEvent x, JudgeEvent y) {
return x.EndTime.CompareTo(y.EndTime);
} }
} }
public Judge(PdtRuleset rs) { public Judge(PdtRuleset rs) {
_etor = ChartPlayer.etor; _etor = ChartPlayer.etor;
_rs = rs; _rs = rs;
foreach (var s in rs.scores) { foreach (var s in rs.scores) {
var name = s.Key.Key; var key = s.Key;
scoreDefs.Add(name, s.Value); scoreSrcs.Add(key.Key, new PropSrc.Float(() => scores[key.Key]));
scores.Add(name, s.Value.init); scoreOps.Add(key.Key, new PropOp.Float(v => scores[key.Key] = v));
scoreFmtKeys.Add(key.Key, IdentifierManager.SharedInstance.Request("_score_" + (string)key.Name));
scoreDefs.Add(key.Key, s.Value);
scores.Add(key.Key, s.Value.init);
} }
} }
public void Prepare(float st, float et, Identifier input, JudgeDefinition def, ContainerState container) { public void Prepare(float st, float et, Identifier input, JudgeDefinition def, ContainerState container) {
@@ -48,8 +47,10 @@ namespace Cryville.Crtr {
activeEvs.Add(input, new List<JudgeEvent>()); activeEvs.Add(input, new List<JudgeEvent>());
} }
var ev = new JudgeEvent { var ev = new JudgeEvent {
StartTime = st + def.clip[0], StartTime = st,
EndTime = et + def.clip[1], EndTime = et,
StartClip = st + def.clip[0],
EndClip = et + def.clip[1],
Definition = def, Definition = def,
State = container, State = container,
}; };
@@ -57,22 +58,79 @@ namespace Cryville.Crtr {
if (index < 0) index = ~index; if (index < 0) index = ~index;
list.Insert(index, ev); list.Insert(index, ev);
} }
static bool _flag;
static readonly PropOp.Boolean _flagop = new PropOp.Boolean(v => _flag = v);
static readonly int _var_fn = IdentifierManager.SharedInstance.Request("fn");
static readonly int _var_tn = IdentifierManager.SharedInstance.Request("tn");
static readonly int _var_ft = IdentifierManager.SharedInstance.Request("ft");
static readonly int _var_tt = IdentifierManager.SharedInstance.Request("tt");
readonly byte[] _numbuf1 = new byte[sizeof(float)];
readonly byte[] _numbuf2 = new byte[sizeof(float)];
readonly byte[] _numbuf3 = new byte[sizeof(float)];
readonly byte[] _numbuf4 = new byte[sizeof(float)];
unsafe void LoadNum(byte[] buffer, float value) {
fixed (byte* ptr = buffer) *(float*)ptr = value;
}
// Adopted from System.Collections.Generic.ArraySortHelper<T>.InternalBinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
int BinarySearch(List<JudgeEvent> list, float time, int stack) {
int num = 0;
int num2 = list.Count - 1;
while (num <= num2) {
int num3 = num + (num2 - num >> 1);
int num4 = -list[num3].Definition.stack.CompareTo(stack);
if (num4 == 0) num4 = list[num3].StartClip.CompareTo(time);
if (num4 == 0) return num3;
else if (num4 < 0) num = num3 + 1;
else num2 = num3 - 1;
}
return ~num;
}
public void Feed(Identifier target, float ft, float tt) { public void Feed(Identifier target, float ft, float tt) {
Forward(target, tt); Forward(target, tt);
var actlist = activeEvs[target]; var actlist = activeEvs[target];
foreach (var ev in actlist) { if (actlist.Count > 0) {
// TODO judge ev LoadNum(_numbuf3, ft); _etor.ContextCascadeUpdate(_var_ft, new PropSrc.Arbitrary(PdtInternalType.Number, _numbuf3));
LoadNum(_numbuf4, tt); _etor.ContextCascadeUpdate(_var_tt, new PropSrc.Arbitrary(PdtInternalType.Number, _numbuf4));
var index = 0;
while (index >= 0 && index < actlist.Count) {
var ev = actlist[index];
LoadNum(_numbuf1, ev.StartTime); _etor.ContextCascadeUpdate(_var_fn, new PropSrc.Arbitrary(PdtInternalType.Number, _numbuf1));
LoadNum(_numbuf2, ev.EndTime); _etor.ContextCascadeUpdate(_var_tn, new PropSrc.Arbitrary(PdtInternalType.Number, _numbuf2));
var def = ev.Definition;
if (def.hit != null) _etor.Evaluate(_flagop, def.hit);
else _flag = true;
if (_flag) {
if (def.scores != null) UpdateScore(def.scores);
if (def.pass != null) Pass(def.pass);
actlist.RemoveAt(index);
index = BinarySearch(actlist, ev.StartClip, def.prop);
if (index < 0) index = ~index;
}
else index++;
}
} }
} }
bool Pass(Identifier[] ids) {
foreach (var i in ids) {
var def = _rs.judges[i];
if (def.hit != null) _etor.Evaluate(_flagop, def.hit);
else _flag = true;
if (_flag) {
if (def.scores != null) UpdateScore(def.scores);
if (def.pass != null) Pass(def.pass);
return true;
}
}
return false;
}
public void Cleanup(Identifier target, float ft, float tt) { public void Cleanup(Identifier target, float ft, float tt) {
Forward(target, tt); Forward(target, tt);
var actlist = activeEvs[target]; var actlist = activeEvs[target];
for (int i = actlist.Count - 1; i >= 0; i--) { for (int i = actlist.Count - 1; i >= 0; i--) {
JudgeEvent ev = actlist[i]; JudgeEvent ev = actlist[i];
if (tt > ev.EndTime) { if (tt > ev.EndClip) {
actlist.RemoveAt(i); actlist.RemoveAt(i);
Logger.Log("main", 0, "Judge", "miss {0}", target); if (ev.Definition.miss != null) Pass(ev.Definition.miss);
// TODO miss ev
} }
} }
} }
@@ -80,16 +138,31 @@ namespace Cryville.Crtr {
var list = evs[target]; var list = evs[target];
var actlist = activeEvs[target]; var actlist = activeEvs[target];
JudgeEvent ev; JudgeEvent ev;
while (list.Count > 0 && (ev = list[0]).StartTime <= tt) { while (list.Count > 0 && (ev = list[0]).StartClip <= tt) {
list.RemoveAt(0); list.RemoveAt(0);
var index = actlist.BinarySearch(ev, _etcmp); var index = BinarySearch(actlist, ev.StartClip, ev.Definition.stack);
if (index < 0) index = ~index; if (index < 0) index = ~index;
actlist.Insert(index, ev); actlist.Insert(index, ev);
Logger.Log("main", 0, "Judge", "active {0}", target);
// TODO priority?
} }
} }
public readonly Dictionary<int, ScoreDefinition> scoreDefs = new Dictionary<int, ScoreDefinition>(); void UpdateScore(Dictionary<ScoreOperation, PdtExpression> scoreops) {
foreach (var scoreop in scoreops) {
var key = scoreop.Key;
_etor.ContextSelfValue = scoreSrcs[key.name.Key];
_etor.Evaluate(scoreOps[key.name.Key], scoreop.Value);
foreach (var s in _rs.scores) {
if (s.Value.value != null) {
_etor.ContextSelfValue = scoreSrcs[s.Key.Key];
_etor.Evaluate(scoreOps[s.Key.Key], s.Value.value);
}
}
}
ScoreCache.Clear();
}
readonly Dictionary<int, int> scoreFmtKeys = new Dictionary<int, int>();
readonly Dictionary<int, PropSrc> scoreSrcs = new Dictionary<int, PropSrc>();
readonly Dictionary<int, PropOp> scoreOps = new Dictionary<int, PropOp>();
readonly Dictionary<int, ScoreDefinition> scoreDefs = new Dictionary<int, ScoreDefinition>();
public readonly Dictionary<int, float> scores = new Dictionary<int, float>(); public readonly Dictionary<int, float> scores = new Dictionary<int, float>();
readonly Dictionary<int, string> ScoreCache = new Dictionary<int, string>(); readonly Dictionary<int, string> ScoreCache = new Dictionary<int, string>();
readonly object _lock = new object(); readonly object _lock = new object();
@@ -97,7 +170,7 @@ namespace Cryville.Crtr {
lock (_lock) { lock (_lock) {
if (ScoreCache.Count == 0) { if (ScoreCache.Count == 0) {
foreach (var s in scores) foreach (var s in scores)
ScoreCache.Add(s.Key, s.Value.ToString(scoreDefs[s.Key].format)); ScoreCache.Add(scoreFmtKeys[s.Key], s.Value.ToString(scoreDefs[s.Key].format));
} }
return ScoreCache; return ScoreCache;
} }
@@ -122,8 +195,10 @@ namespace Cryville.Crtr {
public PdtExpression input; public PdtExpression input;
public PdtExpression hit; public PdtExpression hit;
public Identifier[] pass; public Identifier[] pass;
public Identifier miss; public Identifier[] miss;
public Dictionary<ScoreOperation, PdtExpression> scores; public Dictionary<ScoreOperation, PdtExpression> scores;
public int stack;
public int prop = -1;
} }
public class ScoreOperation { public class ScoreOperation {
public Identifier name; public Identifier name;

View File

@@ -284,21 +284,15 @@ namespace Cryville.Crtr {
} }
// Adopted from System.Collections.Generic.ArraySortHelper<T>.InternalBinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer) // Adopted from System.Collections.Generic.ArraySortHelper<T>.InternalBinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
internal int BinarySearch(float value) { int BinarySearch(float value) {
int num = 0; int num = 0;
int num2 = RelativeNodes.Count - 1; int num2 = RelativeNodes.Count - 1;
while (num <= num2) { while (num <= num2) {
int num3 = num + (num2 - num >> 1); int num3 = num + (num2 - num >> 1);
int num4 = RelativeNodes[num3].Time.Value.CompareTo(value); int num4 = RelativeNodes[num3].Time.Value.CompareTo(value);
if (num4 == 0) { if (num4 == 0) return num3;
return num3; if (num4 < 0) num = num3 + 1;
} else num2 = num3 - 1;
if (num4 < 0) {
num = num3 + 1;
}
else {
num2 = num3 - 1;
}
} }
return ~num; return ~num;
} }

View File

@@ -24,6 +24,7 @@ namespace Cryville.Crtr {
var id = new Identifier(name); var id = new Identifier(name);
PropSrc prop; PropSrc prop;
string str; string str;
float num;
if (ContextEvent != null && ContextEvent.PropSrcs.TryGetValue(name, out prop)) { if (ContextEvent != null && ContextEvent.PropSrcs.TryGetValue(name, out prop)) {
prop.Get(out type, out value); prop.Get(out type, out value);
} }
@@ -31,6 +32,12 @@ namespace Cryville.Crtr {
var vec = ContextState.GetRawValue(id); var vec = ContextState.GetRawValue(id);
new VectorSrc(() => vec).Get(out type, out value); new VectorSrc(() => vec).Get(out type, out value);
} }
else if (ContextJudge != null && ContextJudge.scores.TryGetValue(name, out num)) {
type = PdtInternalType.Number;
LoadNum(num);
value = _numbuf;
RevokePotentialConstant();
}
else if (ContextJudge != null && ContextJudge.GetFormattedScoreStrings().TryGetValue(name, out str)) { else if (ContextJudge != null && ContextJudge.GetFormattedScoreStrings().TryGetValue(name, out str)) {
type = PdtInternalType.String; type = PdtInternalType.String;
value = GetBytes(str); value = GetBytes(str);
@@ -92,8 +99,8 @@ namespace Cryville.Crtr {
static readonly int _colop_and = IdentifierManager.SharedInstance.Request("&"); static readonly int _colop_and = IdentifierManager.SharedInstance.Request("&");
static readonly int _colop_or = IdentifierManager.SharedInstance.Request("|"); static readonly int _colop_or = IdentifierManager.SharedInstance.Request("|");
protected override bool Collapse(int name, PdtVariableMemory param) { protected override bool Collapse(int name, PdtVariableMemory param) {
if (name == _colop_and) return param.AsNumber() <= 0; if (name == _colop_and) return param.Type == PdtInternalType.Number && param.AsNumber() <= 0;
else if (name == _colop_or) return param.AsNumber() > 0; else if (name == _colop_or) return param.Type != PdtInternalType.Number || param.AsNumber() > 0;
else throw new KeyNotFoundException(string.Format("Undefined collapse operator {0}", name)); else throw new KeyNotFoundException(string.Format("Undefined collapse operator {0}", name));
} }
@@ -134,6 +141,11 @@ namespace Cryville.Crtr {
_ctxops.Add(IdentifierManager.SharedInstance.Request("min"), new func_min(() => ContextSelfValue)); _ctxops.Add(IdentifierManager.SharedInstance.Request("min"), new func_min(() => ContextSelfValue));
_ctxops.Add(IdentifierManager.SharedInstance.Request("max"), new func_max(() => ContextSelfValue)); _ctxops.Add(IdentifierManager.SharedInstance.Request("max"), new func_max(() => ContextSelfValue));
_ctxops.Add(IdentifierManager.SharedInstance.Request("abs"), new func_abs(() => ContextSelfValue)); _ctxops.Add(IdentifierManager.SharedInstance.Request("abs"), new func_abs(() => ContextSelfValue));
Func<int, PropSrc> cccb = k => ContextCascadeLookup(k);
_ctxops.Add(IdentifierManager.SharedInstance.Request("attack_timing"), new func_attack_timing(cccb));
_ctxops.Add(IdentifierManager.SharedInstance.Request("enter_timing"), new func_enter_timing(cccb));
_ctxops.Add(IdentifierManager.SharedInstance.Request("release_timing"), new func_release_timing(cccb));
} }
static PdtEvaluator() { static PdtEvaluator() {
_shortops.Add(new PdtOperatorSignature("@", 2), new op_at_2()); _shortops.Add(new PdtOperatorSignature("@", 2), new op_at_2());
@@ -158,6 +170,7 @@ namespace Cryville.Crtr {
} }
#region Operators #region Operators
#pragma warning disable IDE1006 #pragma warning disable IDE1006
#region Basic Operators
class op_add_1 : PdtOperator { class op_add_1 : PdtOperator {
public op_add_1() : base(1) { } public op_add_1() : base(1) { }
protected override void Execute() { protected override void Execute() {
@@ -273,6 +286,8 @@ namespace Cryville.Crtr {
else throw new InvalidOperationException("Not a vector or number"); else throw new InvalidOperationException("Not a vector or number");
} }
} }
#endregion
#region Basic Functions
class func_frame_seq : PdtOperator { class func_frame_seq : PdtOperator {
public func_frame_seq() : base(3) { } public func_frame_seq() : base(3) { }
protected override unsafe void Execute() { protected override unsafe void Execute() {
@@ -303,6 +318,39 @@ namespace Cryville.Crtr {
} }
} }
} }
class func_in_area : PdtOperator {
public func_in_area() : base(1) { }
protected override unsafe void Execute() {
var arg = GetOperand(0);
if (arg.Type == PdtInternalType.Error) {
throw new InvalidOperationException("Error");
}
else if (arg.Type == PdtInternalType.Number && arg.AsNumber() <= 0) {
GetReturnFrame(PdtInternalType.Null, 0);
}
else {
var ret = GetReturnFrame(arg.Type, arg.Length);
arg.CopyTo(ret);
}
}
}
class func_int_map : PdtOperator {
public func_int_map(int pc) : base(pc) {
if (pc < 4) throw new ArgumentOutOfRangeException("Too few parameters for int_map");
}
protected override unsafe void Execute() {
var value = GetOperand(0).AsNumber();
var offset = GetOperand(1).AsNumber();
var step = GetOperand(2).AsNumber();
var index = (int)((value - offset) / step);
if (index < 0 || index >= LoadedOperandCount - 3) index = 0;
var hit = GetOperand(index + 3);
var ret = GetReturnFrame(hit.Type, hit.Length);
hit.CopyTo(ret);
}
}
#endregion
#region Contextual Functions
class func_screen_edge : PdtOperator { class func_screen_edge : PdtOperator {
readonly Func<Transform> _ctxcb; readonly Func<Transform> _ctxcb;
public func_screen_edge(Func<Transform> ctxcb) : base(1) { public func_screen_edge(Func<Transform> ctxcb) : base(1) {
@@ -408,41 +456,61 @@ namespace Cryville.Crtr {
ret.SetNumber(Mathf.Abs(arg)); ret.SetNumber(Mathf.Abs(arg));
} }
} }
class func_in_area : PdtOperator { #endregion
public func_in_area() : base(1) { } #region Judge Functions
protected override unsafe void Execute() { static readonly int _var_fn = IdentifierManager.SharedInstance.Request("fn");
var arg = GetOperand(0); static readonly int _var_tn = IdentifierManager.SharedInstance.Request("tn");
if (arg.Type == PdtInternalType.Error) { static readonly int _var_ft = IdentifierManager.SharedInstance.Request("ft");
throw new InvalidOperationException("Error"); static readonly int _var_tt = IdentifierManager.SharedInstance.Request("tt");
} static readonly int _var_fv = IdentifierManager.SharedInstance.Request("fv");
else if (arg.Type == PdtInternalType.Number && arg.AsNumber() <= 0) { static readonly int _var_tv = IdentifierManager.SharedInstance.Request("tv");
GetReturnFrame(PdtInternalType.Null, 0); abstract class JudgeFunction : PdtOperator {
} readonly Func<int, PropSrc> _ctxcb;
else { protected JudgeFunction(int pc, Func<int, PropSrc> ctxcb) : base(pc) {
var ret = GetReturnFrame(arg.Type, arg.Length); _ctxcb = ctxcb;
arg.CopyTo(ret); }
} 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) ? 1 : 0);
}
protected abstract bool ExecuteImpl(float fn, float tn, float ft, float tt, Vector3? fv, Vector3? tv);
}
class func_attack_timing : JudgeFunction {
public func_attack_timing(Func<int, PropSrc> ctxcb) : base(2, ctxcb) { }
protected override bool ExecuteImpl(float fn, float tn, float ft, float tt, Vector3? fv, Vector3? tv) {
if (fv != null) return false;
var t0 = GetOperand(0).AsNumber() + fn;
var t1 = GetOperand(1).AsNumber() + tn;
return tt > t0 && tt <= t1;
} }
} }
class func_int_map : PdtOperator { class func_enter_timing : JudgeFunction {
public func_int_map(int pc) : base(pc) { public func_enter_timing(Func<int, PropSrc> ctxcb) : base(1, ctxcb) { }
if (pc < 4) throw new ArgumentOutOfRangeException("Too few parameters for int_map"); protected override bool ExecuteImpl(float fn, float tn, float ft, float tt, Vector3? fv, Vector3? tv) {
} if (fv == null || tv == null) return false;
protected override unsafe void Execute() { var t0 = GetOperand(0).AsNumber() + fn;
var value = GetOperand(0).AsNumber(); return ft < t0 && tt >= t0;
var offset = GetOperand(1).AsNumber();
var step = GetOperand(2).AsNumber();
var index = (int)((value - offset) / step);
if (index < 0 || index >= LoadedOperandCount - 3) index = 0;
var hit = GetOperand(index + 3);
var ret = GetReturnFrame(hit.Type, hit.Length);
hit.CopyTo(ret);
} }
} }
class func_release_timing : JudgeFunction {
public func_release_timing(Func<int, PropSrc> ctxcb) : base(2, ctxcb) { }
protected override bool ExecuteImpl(float fn, float tn, float ft, float tt, Vector3? fv, Vector3? tv) {
if (tv != null) return false;
var t0 = GetOperand(0).AsNumber() + fn;
var t1 = GetOperand(1).AsNumber() + tn;
return ft > t0 && ft <= t1;
}
}
#endregion
unsafe static class oputil { unsafe static class oputil {
public static float AsNumber(PropSrc src) { public static float AsNumber(PropSrc src) {
if (src == null) if (src == null) throw new ArgumentNullException("src");
throw new ArgumentNullException("src");
int type; byte[] value; int type; byte[] value;
src.Get(out type, out value); src.Get(out type, out value);
if (type != PdtInternalType.Number) if (type != PdtInternalType.Number)
@@ -451,6 +519,25 @@ namespace Cryville.Crtr {
return *(float*)ptr; return *(float*)ptr;
} }
} }
public static Vector3? AsVector(PropSrc src) {
if (src == null) throw new ArgumentNullException("src");
int type; byte[] value;
src.Get(out type, out value);
if (type == PdtInternalType.Vector) {
fixed (byte* ptr = value) {
return *(Vector3*)ptr;
}
}
else if (type == PdtInternalType.Number) {
fixed (byte* ptr = value) {
return new Vector3(*(float*)ptr, 0, 0);
}
}
else if (type == PdtInternalType.Null) {
return null;
}
else throw new ArgumentException("Not a number");
}
} }
#pragma warning restore IDE1006 #pragma warning restore IDE1006
#endregion #endregion

View File

@@ -21,7 +21,7 @@ namespace Cryville.Crtr {
readonly Action<bool> _cb; readonly Action<bool> _cb;
public Boolean(Action<bool> cb) { _cb = cb; } public Boolean(Action<bool> cb) { _cb = cb; }
protected override void Execute() { protected override void Execute() {
_cb(GetOperand(0).AsNumber() != 0); _cb(GetOperand(0).AsNumber() > 0);
} }
} }
public class Integer : PropOp { public class Integer : PropOp {

View File

@@ -45,8 +45,12 @@ namespace Cryville.Crtr {
} }
foreach (var j in judges.Values) { foreach (var j in judges.Values) {
if (j.hit != null) etor.Optimize(j.hit); if (j.hit != null) etor.Optimize(j.hit);
if (j.scores != null) foreach (var e in j.scores.Values) { if (j.scores != null) {
etor.Optimize(e); foreach (var s in j.scores) {
if (s.Key.op != default(Identifier))
etor.PatchCompound(s.Key.name.Key, s.Key.op.Key, s.Value);
etor.Optimize(s.Value);
}
} }
} }
foreach (var s in scores.Values) { foreach (var s in scores.Values) {

View File

@@ -37,3 +37,6 @@ using System.Diagnostics.CodeAnalysis;
// Index operator not supported // Index operator not supported
[assembly: SuppressMessage("Style", "IDE0056")] [assembly: SuppressMessage("Style", "IDE0056")]
// Local function not supported
[assembly: SuppressMessage("Style", "IDE0039")]