5 Commits

7 changed files with 111 additions and 34 deletions

View File

@@ -38,7 +38,7 @@ namespace Cryville.Common.Unity.Input {
} }
public override double GetCurrentTimestamp() { public override double GetCurrentTimestamp() {
return Time.timeAsDouble; return Time.realtimeSinceStartupAsDouble;
} }
} }

View File

@@ -45,7 +45,7 @@ namespace Cryville.Common.Unity.Input {
} }
public override double GetCurrentTimestamp() { public override double GetCurrentTimestamp() {
return Time.timeAsDouble; return Time.realtimeSinceStartupAsDouble;
} }
public class UnityMouseReceiver : MonoBehaviour { public class UnityMouseReceiver : MonoBehaviour {

View File

@@ -45,7 +45,7 @@ namespace Cryville.Common.Unity.Input {
} }
public override double GetCurrentTimestamp() { public override double GetCurrentTimestamp() {
return Time.timeAsDouble; return Time.realtimeSinceStartupAsDouble;
} }
public class UnityPointerReceiver : MonoBehaviour { public class UnityPointerReceiver : MonoBehaviour {

View File

@@ -105,6 +105,7 @@ namespace Cryville.Crtr {
bool texloaddone; bool texloaddone;
diag::Stopwatch texloadtimer = new diag::Stopwatch(); diag::Stopwatch texloadtimer = new diag::Stopwatch();
bool firstFrame; bool firstFrame;
double atime0;
void Update() { void Update() {
// if (Input.GetKeyDown(KeyCode.Return)) TogglePlay(); // if (Input.GetKeyDown(KeyCode.Return)) TogglePlay();
if (started) { if (started) {
@@ -115,16 +116,9 @@ namespace Cryville.Crtr {
? 1f / Application.targetFrameRate ? 1f / Application.targetFrameRate
: Time.deltaTime; : Time.deltaTime;
firstFrame = false; firstFrame = false;
inputProxy.ForceTick();
cbus.ForwardByTime(dt); cbus.ForwardByTime(dt);
bbus.ForwardByTime(dt); bbus.ForwardByTime(dt);
UnityEngine.Profiling.Profiler.BeginSample("ChartPlayer.FeedJudge");
/*judge.StartFrame();
Game.InputManager.EnumerateEvents(ev => {
// Logger.Log("main", 0, "Input", ev.ToString());
judge.Feed(ev);
});
judge.EndFrame();*/
UnityEngine.Profiling.Profiler.EndSample();
UnityEngine.Profiling.Profiler.BeginSample("ChartPlayer.Forward"); UnityEngine.Profiling.Profiler.BeginSample("ChartPlayer.Forward");
UnityEngine.Profiling.Profiler.BeginSample("EventBus.Copy"); UnityEngine.Profiling.Profiler.BeginSample("EventBus.Copy");
bbus.CopyTo(2, tbus); bbus.CopyTo(2, tbus);
@@ -245,6 +239,12 @@ namespace Cryville.Crtr {
UnityEngine.Profiling.Profiler.GetTotalReservedMemory() UnityEngine.Profiling.Profiler.GetTotalReservedMemory()
#endif #endif
); );
if (started) sttext += string.Format(
"\nSTime: {0:R}\nATime: {1:R}\nITime: {2:R}",
cbus.Time,
Game.AudioClient.Position - atime0,
inputProxy.GetTimestampAverage()
);
if (judge != null) sttext += "\n== Scores ==\n" + judge.GetFullFormattedScoreString(); if (judge != null) sttext += "\n== Scores ==\n" + judge.GetFullFormattedScoreString();
status.text = sttext; status.text = sttext;
} }
@@ -408,8 +408,9 @@ namespace Cryville.Crtr {
timer.Stop(); timer.Stop();
Logger.Log("main", 1, "Load/Prehandle", "Prehandling done ({0}ms)", timer.Elapsed.TotalMilliseconds); Logger.Log("main", 1, "Load/Prehandle", "Prehandling done ({0}ms)", timer.Elapsed.TotalMilliseconds);
Game.AudioSequencer.Playing = true; Game.AudioSequencer.Playing = true;
Thread.Sleep((int)(Game.AudioClient.BufferPosition - Game.AudioClient.Position)); atime0 = Game.AudioClient.BufferPosition;
// TODO SyncTime(cbus.Time); Thread.Sleep((int)((atime0 - Game.AudioClient.Position) * 1000));
inputProxy.SyncTime(cbus.Time);
started = true; started = true;
} }
catch (Exception ex) { catch (Exception ex) {

View File

@@ -105,9 +105,11 @@ namespace Cryville.Crtr {
#region Handling #region Handling
public void Activate() { public void Activate() {
_activeCounts.Clear(); _activeCounts.Clear();
foreach (var p in _tproxies.Values) _activeCounts.Add(p.Source.Value, 0);
_vect.Clear(); _vecs.Clear(); _vect.Clear(); _vecs.Clear();
foreach (var src in _sproxies.Keys) src.Handler.Activate(); foreach (var src in _sproxies.Keys) {
_activeCounts.Add(src, 0);
src.Handler.Activate();
}
} }
public void Deactivate() { foreach (var src in _sproxies.Keys) src.Handler.Deactivate(); } public void Deactivate() { foreach (var src in _sproxies.Keys) src.Handler.Deactivate(); }
@@ -115,7 +117,8 @@ namespace Cryville.Crtr {
static readonly int _var_value = IdentifierManager.SharedInstance.Request("value"); static readonly int _var_value = IdentifierManager.SharedInstance.Request("value");
static readonly PropOp.Arbitrary _arbop = new PropOp.Arbitrary(); static readonly PropOp.Arbitrary _arbop = new PropOp.Arbitrary();
readonly byte[] _vecbuf = new byte[3 * sizeof(float) + sizeof(int)]; readonly byte[] _vecbuf = new byte[3 * sizeof(float) + sizeof(int)];
readonly Dictionary<InputSource, int> _activeCounts = new Dictionary<InputSource, int>(); // TODO used for force tick readonly Dictionary<InputHandler, double> _timeOrigins = new Dictionary<InputHandler, double>();
readonly Dictionary<InputSource, int> _activeCounts = new Dictionary<InputSource, int>();
readonly Dictionary<InputIdentifier, float> _vect = new Dictionary<InputIdentifier, float>(); readonly Dictionary<InputIdentifier, float> _vect = new Dictionary<InputIdentifier, float>();
readonly Dictionary<ProxiedInputIdentifier, PropSrc.Arbitrary> _vecs = new Dictionary<ProxiedInputIdentifier, PropSrc.Arbitrary>(); readonly Dictionary<ProxiedInputIdentifier, PropSrc.Arbitrary> _vecs = new Dictionary<ProxiedInputIdentifier, PropSrc.Arbitrary>();
static readonly byte[] _nullvalue = new byte[0]; static readonly byte[] _nullvalue = new byte[0];
@@ -124,7 +127,7 @@ namespace Cryville.Crtr {
InputProxyEntry proxy; InputProxyEntry proxy;
if (_sproxies.TryGetValue(id.Source, out proxy)) { if (_sproxies.TryGetValue(id.Source, out proxy)) {
_etor.ContextCascadeInsert(); _etor.ContextCascadeInsert();
float ft, tt = (float)vec.Time; float ft, tt = (float)(vec.Time - _timeOrigins[id.Source.Handler]);
if (!_vect.TryGetValue(id, out ft)) ft = tt; if (!_vect.TryGetValue(id, out ft)) ft = tt;
if (vec.IsNull) { if (vec.IsNull) {
_etor.ContextCascadeUpdate(_var_value, new PropSrc.Arbitrary(PdtInternalType.Null, _nullvalue)); _etor.ContextCascadeUpdate(_var_value, new PropSrc.Arbitrary(PdtInternalType.Null, _nullvalue));
@@ -177,6 +180,27 @@ namespace Cryville.Crtr {
_vecs[pid] = tv; _vecs[pid] = tv;
} }
} }
public void SyncTime(double time) {
foreach (var s in _sproxies.Keys) {
var h = s.Handler;
if (!_timeOrigins.ContainsKey(h))
_timeOrigins.Add(h, h.GetCurrentTimestamp() - time);
}
}
public void ForceTick() {
foreach (var src in _sproxies.Keys) {
if (_activeCounts[src] == 0) {
OnInput(new InputIdentifier { Source = src, Id = 0 }, new InputVector(src.Handler.GetCurrentTimestamp()));
}
}
}
public double GetTimestampAverage() {
double result = 0;
foreach (var src in _sproxies.Keys) {
result += src.Handler.GetCurrentTimestamp() - _timeOrigins[src.Handler];
}
return result / _sproxies.Count;
}
#endregion #endregion
} }

View File

@@ -5,17 +5,34 @@ using System.Collections.Generic;
namespace Cryville.Crtr { namespace Cryville.Crtr {
public class Judge { public class Judge {
readonly PdtEvaluator _etor;
readonly PdtRuleset _rs; readonly PdtRuleset _rs;
readonly Dictionary<Identifier, float> ct readonly Dictionary<Identifier, float> ct
= new Dictionary<Identifier, float>(); = new Dictionary<Identifier, float>();
readonly Dictionary<Identifier, Dictionary<float, JudgeEvent>> evs readonly Dictionary<Identifier, List<JudgeEvent>> evs
= new Dictionary<Identifier, Dictionary<float, JudgeEvent>>(); = new Dictionary<Identifier, List<JudgeEvent>>();
readonly Dictionary<Identifier, List<JudgeEvent>> activeEvs
= new Dictionary<Identifier, List<JudgeEvent>>();
struct JudgeEvent { struct JudgeEvent {
public float EndTime; public float StartTime { get; set; }
public float EndTime { 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();
class JudgeEventStartTimeComparer : IComparer<JudgeEvent> {
public int Compare(JudgeEvent x, JudgeEvent y) {
return x.StartTime.CompareTo(y.StartTime);
}
}
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;
_rs = rs; _rs = rs;
foreach (var s in rs.scores) { foreach (var s in rs.scores) {
var name = s.Key.Key; var name = s.Key.Key;
@@ -23,19 +40,54 @@ namespace Cryville.Crtr {
scores.Add(name, s.Value.init); scores.Add(name, s.Value.init);
} }
} }
public void Prepare(float time, Identifier input, JudgeDefinition def, ContainerState container) { public void Prepare(float st, float et, Identifier input, JudgeDefinition def, ContainerState container) {
Dictionary<float, JudgeEvent> list; List<JudgeEvent> list;
if (!evs.TryGetValue(input, out list)) { if (!evs.TryGetValue(input, out list)) {
ct.Add(input, 0); ct.Add(input, 0);
evs.Add(input, list = new Dictionary<float, JudgeEvent>()); evs.Add(input, list = new List<JudgeEvent>());
activeEvs.Add(input, new List<JudgeEvent>());
} }
list.Add(time + def.clip[0], new JudgeEvent { EndTime = time + def.clip[1], Definition = def, State = container }); var ev = new JudgeEvent {
StartTime = st + def.clip[0],
EndTime = et + def.clip[1],
Definition = def,
State = container,
};
var index = list.BinarySearch(ev, _stcmp);
if (index < 0) index = ~index;
list.Insert(index, ev);
} }
public void Feed(string target, float ft, float tt) { public void Feed(Identifier target, float ft, float tt) {
Logger.Log("main", 0, "Judge", "Feed {0}: {1}->{2}", target, ft, tt); Forward(target, tt);
var actlist = activeEvs[target];
foreach (var ev in actlist) {
// TODO judge ev
}
}
public void Cleanup(Identifier target, float ft, float tt) {
Forward(target, tt);
var actlist = activeEvs[target];
for (int i = actlist.Count - 1; i >= 0; i--) {
JudgeEvent ev = actlist[i];
if (tt > ev.EndTime) {
actlist.RemoveAt(i);
Logger.Log("main", 0, "Judge", "miss {0}", target);
// TODO miss ev
}
}
}
void Forward(Identifier target, float tt) {
var list = evs[target];
var actlist = activeEvs[target];
JudgeEvent ev;
while (list.Count > 0 && (ev = list[0]).StartTime <= tt) {
list.RemoveAt(0);
var index = actlist.BinarySearch(ev, _etcmp);
if (index < 0) index = ~index;
actlist.Insert(index, ev);
Logger.Log("main", 0, "Judge", "active {0}", target);
// TODO priority?
} }
public void Cleanup(string target, float ft, float tt) {
Logger.Log("main", 0, "Judge", "Cleanup {0}: {1}->{2}", target, ft, tt);
} }
public readonly Dictionary<int, ScoreDefinition> scoreDefs = new Dictionary<int, ScoreDefinition>(); public 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>();

View File

@@ -99,7 +99,7 @@ namespace Cryville.Crtr {
ChartPlayer.etor.ContextEvent = tev; ChartPlayer.etor.ContextEvent = tev;
ChartPlayer.etor.ContextState = s; ChartPlayer.etor.ContextState = s;
ChartPlayer.etor.Evaluate(new PropOp.Identifier(v => name = new Identifier(v)), ruleset.judges[tev.Id].input); ChartPlayer.etor.Evaluate(new PropOp.Identifier(v => name = new Identifier(v)), ruleset.judges[tev.Id].input);
judge.Prepare(ps.Time, name, ruleset.judges[tev.Id], cs); judge.Prepare(ev.Time, ev.Time + ev.Duration, name, ruleset.judges[tev.Id], cs);
ChartPlayer.etor.ContextState = null; ChartPlayer.etor.ContextState = null;
ChartPlayer.etor.ContextEvent = null; ChartPlayer.etor.ContextEvent = null;
} }