22 Commits

Author SHA1 Message Date
723ec937ad Remove callback parameters on states. 2023-01-03 12:09:16 +08:00
7c77ba83f8 Fix polysec not mapping textures correctly if texture set partly. 2023-01-03 11:58:39 +08:00
6da4b96b24 Optimize motion invalidation performance. 2023-01-02 20:05:14 +08:00
e8f8593555 Fix conditional compilation. 2023-01-01 20:07:58 +08:00
2b5bc5dd08 Optimize GC for RMV pool. 2023-01-01 19:03:19 +08:00
cf6186aa16 Add judge anchor stub. 2023-01-01 19:02:49 +08:00
4d7773a2ac Cleanup anchor related code. 2023-01-01 19:01:34 +08:00
e8f74399f2 Implement judge report. 2023-01-01 19:00:19 +08:00
ca72f7adb5 Implement temporary event injection. (Amend) 2023-01-01 18:55:22 +08:00
5e19a8b886 Code cleanup. 2023-01-01 18:54:53 +08:00
a416f772d4 Add force sync frames. 2023-01-01 18:52:28 +08:00
989a6b5554 Fix osu chart ruleset and effect point. 2023-01-01 18:50:03 +08:00
732af15d9b Add Discord GameSDK. 2023-01-01 18:48:14 +08:00
8cdab36cd6 Fix handling for first timing point of osu chart. 2022-12-31 18:17:24 +08:00
44180c7e0f Optimize GC for PropSrc. 2022-12-25 22:20:46 +08:00
e589e37640 Code cleanup. 2022-12-24 19:12:16 +08:00
94107de97d Optimize GC for temporary anchor event injection. 2022-12-23 17:46:29 +08:00
13c55dc23e Optimize GC for PropOp.Enum<T>. 2022-12-23 17:45:07 +08:00
617eddc030 Reimplement cur anchor. 2022-12-23 16:28:48 +08:00
7475b19547 Implement temporary event injection. 2022-12-23 16:27:34 +08:00
0049ace91a Refactor polysec.suppressed to polysec.partial and polysec.part. 2022-12-23 16:25:57 +08:00
356f4df9a9 Exception cleanup. Code cleanup. 2022-12-23 15:20:16 +08:00
63 changed files with 5270 additions and 297 deletions

View File

@@ -19,7 +19,8 @@ namespace Cryville.Common.Pdt {
/// <returns>The operand at the specified index.</returns> /// <returns>The operand at the specified index.</returns>
/// <exception cref="IndexOutOfRangeException"><paramref name="index" /> is not less than <see cref="LoadedOperandCount" /> or less than 0.</exception> /// <exception cref="IndexOutOfRangeException"><paramref name="index" /> is not less than <see cref="LoadedOperandCount" /> or less than 0.</exception>
protected PdtVariableMemory GetOperand(int index) { protected PdtVariableMemory GetOperand(int index) {
if (index >= LoadedOperandCount || index < 0) throw new IndexOutOfRangeException(); if (index >= LoadedOperandCount || index < 0)
throw new ArgumentOutOfRangeException("index");
int i = index + _loadindex; int i = index + _loadindex;
return _operands[i]; return _operands[i];
} }
@@ -33,11 +34,9 @@ namespace Cryville.Common.Pdt {
_operands = new PdtVariableMemory[pc]; _operands = new PdtVariableMemory[pc];
} }
PdtEvaluatorBase _etor; PdtEvaluatorBase _etor;
bool _failure = false;
bool _rfreq = true; bool _rfreq = true;
internal void Begin(PdtEvaluatorBase etor) { internal void Begin(PdtEvaluatorBase etor) {
_etor = etor; _etor = etor;
_failure = false;
_loadindex = ParamCount; _loadindex = ParamCount;
} }
internal void LoadOperand(PdtVariableMemory mem) { internal void LoadOperand(PdtVariableMemory mem) {
@@ -51,10 +50,6 @@ namespace Cryville.Common.Pdt {
if (_rfreq) _etor.DiscardStack(); if (_rfreq) _etor.DiscardStack();
throw new InvalidOperationException("Evaluation failed", ex); throw new InvalidOperationException("Evaluation failed", ex);
} }
if (_failure) {
if (_rfreq) _etor.DiscardStack();
throw new InvalidOperationException("Evaluation failed");
}
if (!_rfreq && !noset) throw new InvalidOperationException("Return frame not set"); if (!_rfreq && !noset) throw new InvalidOperationException("Return frame not set");
} }
/// <summary> /// <summary>
@@ -69,10 +64,7 @@ namespace Cryville.Common.Pdt {
/// <returns>The return frame.</returns> /// <returns>The return frame.</returns>
/// <exception cref="InvalidOperationException">The return frame has already been requested.</exception> /// <exception cref="InvalidOperationException">The return frame has already been requested.</exception>
protected PdtVariableMemory GetReturnFrame(int type, int len) { protected PdtVariableMemory GetReturnFrame(int type, int len) {
if (_rfreq) { if (_rfreq) throw new InvalidOperationException("Return frame requested twice");
_failure = true;
throw new InvalidOperationException("Return frame already requested");
}
_rfreq = true; _rfreq = true;
return _etor.StackAlloc(type, _prmem, len); return _etor.StackAlloc(type, _prmem, len);
} }

View File

@@ -98,7 +98,7 @@ namespace Cryville.Common.Unity {
#elif UNITY_ANDROID #elif UNITY_ANDROID
GameObject sbtn = GameObject.Instantiate<GameObject>(prefabButton); GameObject sbtn = GameObject.Instantiate<GameObject>(prefabButton);
sbtn.GetComponentInChildren<Text>().text = "Storage"; sbtn.GetComponentInChildren<Text>().text = "Storage";
sbtn.GetComponentInChildren<Button>().onClick.AddListener(() => OnDriveChanged(new DirectoryInfo(androidStorage))); sbtn.GetComponentInChildren<Button>().onClick.AddListener(() => ChangeDirectory(new DirectoryInfo(androidStorage)));
sbtn.transform.SetParent(drives, false); sbtn.transform.SetParent(drives, false);
#else #else
#error No update GUI logic #error No update GUI logic

View File

@@ -28,19 +28,19 @@ namespace Cryville.Common.Unity.Input {
} }
public override bool IsNullable(int type) { public override bool IsNullable(int type) {
if (type != 0) throw new ArgumentOutOfRangeException(nameof(type)); if (type != 0) throw new ArgumentOutOfRangeException("type");
return false; return false;
} }
public override byte GetDimension(int type) { public override byte GetDimension(int type) {
if (type != 0) throw new ArgumentOutOfRangeException(nameof(type)); if (type != 0) throw new ArgumentOutOfRangeException("type");
return 2; return 2;
} }
public override string GetTypeName(int type) { public override string GetTypeName(int type) {
switch (type) { switch (type) {
case 0: return "Mouse Position"; case 0: return "Mouse Position";
default: throw new ArgumentOutOfRangeException(nameof(type)); default: throw new ArgumentOutOfRangeException("type");
} }
} }

View File

@@ -28,19 +28,19 @@ namespace Cryville.Common.Unity.Input {
} }
public override bool IsNullable(int type) { public override bool IsNullable(int type) {
if (type != 0) throw new ArgumentOutOfRangeException(nameof(type)); if (type != 0) throw new ArgumentOutOfRangeException("type");
return true; return true;
} }
public override byte GetDimension(int type) { public override byte GetDimension(int type) {
if (type != 0) throw new ArgumentOutOfRangeException(nameof(type)); if (type != 0) throw new ArgumentOutOfRangeException("type");
return 2; return 2;
} }
public override string GetTypeName(int type) { public override string GetTypeName(int type) {
switch (type) { switch (type) {
case 0: return "Touch"; case 0: return "Touch";
default: throw new ArgumentOutOfRangeException(nameof(type)); default: throw new ArgumentOutOfRangeException("type");
} }
} }

View File

@@ -73,6 +73,9 @@ namespace Cryville.Crtr.Browsing {
Application.LoadLevelAdditive("Play"); Application.LoadLevelAdditive("Play");
#endif #endif
GameObject.Find("/Master").GetComponent<Master>().HideMenu(); GameObject.Find("/Master").GetComponent<Master>().HideMenu();
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
DiscordController.Instance.SetPlaying(string.Format("{0} - {1}", detail.Meta.song.name, detail.Meta.name), detail.Meta.length);
#endif
} }
public void OpenConfig(int id, ChartDetail detail) { public void OpenConfig(int id, ChartDetail detail) {

View File

@@ -203,7 +203,7 @@ namespace Cryville.Crtr {
public virtual EventList GetEventsOfType(string type) { public virtual EventList GetEventsOfType(string type) {
switch (type) { switch (type) {
case "motions": return new EventList<Chart.Motion>(motions); case "motions": return new EventList<Chart.Motion>(motions);
default: throw new ArgumentException("Unknown type"); default: throw new ArgumentException(string.Format("Unknown event type {0}", type));
} }
} }
} }

View File

@@ -54,8 +54,8 @@ namespace Cryville.Crtr {
static bool disableGC = true; static bool disableGC = true;
static float clippingDist = 1f; static float clippingDist = 1f;
static float renderDist = 6f; static float renderDist = 6f;
static float renderStep = 0.05f; static double renderStep = 0.05;
public static float actualRenderStep = 0f; public static double actualRenderStep = 0;
static bool autoRenderStep = false; static bool autoRenderStep = false;
public static float soundOffset = 0; public static float soundOffset = 0;
static float startOffset = 0; static float startOffset = 0;
@@ -111,7 +111,7 @@ namespace Cryville.Crtr {
bool texloaddone; bool texloaddone;
diag::Stopwatch texloadtimer = new diag::Stopwatch(); diag::Stopwatch texloadtimer = new diag::Stopwatch();
bool firstFrame; int forceSyncFrames;
double atime0; double atime0;
void Update() { void Update() {
if (started) GameUpdate(); if (started) GameUpdate();
@@ -123,10 +123,18 @@ namespace Cryville.Crtr {
try { try {
if (Screen.width != screenSize.x || Screen.height != screenSize.y) if (Screen.width != screenSize.x || Screen.height != screenSize.y)
throw new InvalidOperationException("Window resized while playing"); throw new InvalidOperationException("Window resized while playing");
float dt = firstFrame double dt, step;
? 1f / Application.targetFrameRate if (forceSyncFrames != 0) {
: Time.deltaTime; forceSyncFrames--;
firstFrame = false; double target = Game.AudioClient.Position - atime0;
dt = target - cbus.Time;
step = autoRenderStep ? 1f / Application.targetFrameRate : renderStep;
inputProxy.SyncTime(target);
}
else {
dt = Time.deltaTime;
step = autoRenderStep ? Time.smoothDeltaTime : renderStep;
}
inputProxy.ForceTick(); inputProxy.ForceTick();
cbus.ForwardByTime(dt); cbus.ForwardByTime(dt);
bbus.ForwardByTime(dt); bbus.ForwardByTime(dt);
@@ -135,10 +143,6 @@ namespace Cryville.Crtr {
bbus.CopyTo(2, tbus); bbus.CopyTo(2, tbus);
bbus.CopyTo(3, nbus); bbus.CopyTo(3, nbus);
UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.EndSample();
float step = autoRenderStep ? ( firstFrame
? 1f / Application.targetFrameRate
: Time.smoothDeltaTime
) : renderStep;
actualRenderStep = step; actualRenderStep = step;
nbus.ForwardStepByTime(clippingDist, step); nbus.ForwardStepByTime(clippingDist, step);
@@ -250,14 +254,15 @@ namespace Cryville.Crtr {
status.text = sttext; status.text = sttext;
} }
void OnCameraPostRender(Camera cam) { void OnCameraPostRender(Camera cam) {
if (!started) return;
if (!logEnabled) return; if (!logEnabled) return;
if (started) timetext = string.Format( timetext = string.Format(
"\nSTime: {0:R}\nATime: {1:R}\nITime: {2:R}", "\nSTime: {0:R}s {3}\ndATime: {1:+0.0ms;-0.0ms;0} {3}\ndITime: {2:+0.0ms;-0.0ms;0} {3}",
cbus.Time, cbus.Time,
Game.AudioClient.Position - atime0, (Game.AudioClient.Position - atime0 - cbus.Time) * 1e3,
inputProxy.GetTimestampAverage() (inputProxy.GetTimestampAverage() - cbus.Time) * 1e3,
forceSyncFrames != 0 ? "(force sync)" : ""
); );
else timetext = string.Empty;
} }
#endregion #endregion
@@ -278,6 +283,9 @@ namespace Cryville.Crtr {
SceneManager.UnloadSceneAsync("Play"); SceneManager.UnloadSceneAsync("Play");
#elif UNITY_5_3_OR_NEWER #elif UNITY_5_3_OR_NEWER
SceneManager.UnloadScene("Play"); SceneManager.UnloadScene("Play");
#endif
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
DiscordController.Instance.SetIdle();
#endif #endif
} }
#pragma warning restore IDE1006 #pragma warning restore IDE1006
@@ -308,7 +316,7 @@ namespace Cryville.Crtr {
autoRenderStep = renderStep == 0; autoRenderStep = renderStep == 0;
soundOffset = Settings.Default.SoundOffset; soundOffset = Settings.Default.SoundOffset;
startOffset = Settings.Default.StartOffset; startOffset = Settings.Default.StartOffset;
firstFrame = true; forceSyncFrames= Settings.Default.ForceSyncFrames;
texloaddone = false; texloaddone = false;
Game.NetworkTaskWorker.SuspendBackgroundTasks(); Game.NetworkTaskWorker.SuspendBackgroundTasks();
Game.AudioSession = Game.AudioSequencer.NewSession(); Game.AudioSession = Game.AudioSequencer.NewSession();
@@ -542,8 +550,6 @@ namespace Cryville.Crtr {
using (var pbus = cbus.Clone(16)) { using (var pbus = cbus.Clone(16)) {
pbus.Forward(); pbus.Forward();
} }
Logger.Log("main", 0, "Load/WorkerThread", "Patching events");
cbus.DoPatch();
Logger.Log("main", 0, "Load/WorkerThread", "Cloning states (type 1)"); Logger.Log("main", 0, "Load/WorkerThread", "Cloning states (type 1)");
bbus = cbus.Clone(1, -clippingDist); bbus = cbus.Clone(1, -clippingDist);

View File

@@ -9,10 +9,17 @@ namespace Cryville.Crtr.Components {
protected Vector3? prevpt; protected Vector3? prevpt;
protected Quaternion? prevrot; protected Quaternion? prevrot;
protected int vertCount = 0; protected int vertCount = 0;
bool suppressed; Part part = Part.whole;
enum Part {
whole = 0,
idle = 1,
start = 2,
end = 3,
}
public SectionalGameObject() { public SectionalGameObject() {
SubmitProperty("suppressed", new PropOp.Boolean(v => suppressed = v), 2); SubmitProperty("partial", new PropOp.Boolean(v => part = Part.idle));
SubmitProperty("part", new PropOp.Enum<Part>(v => part = v, v => (Part)v));
} }
protected override void OnDestroy() { protected override void OnDestroy() {
@@ -28,7 +35,7 @@ namespace Cryville.Crtr.Components {
} }
public void AppendPoint(Vector3 p, Quaternion r) { public void AppendPoint(Vector3 p, Quaternion r) {
if (prevpt == p && prevrot == r || suppressed) return; if (prevpt == p && prevrot == r || ((int)part & 1) == 1) return;
AppendPointInternal(p, r); AppendPointInternal(p, r);
// if (!headGenerated) Logger.Log("main", 0, "Skin/Polysec", "{0}", r); // if (!headGenerated) Logger.Log("main", 0, "Skin/Polysec", "{0}", r);
prevpt = p; prevpt = p;
@@ -145,6 +152,7 @@ namespace Cryville.Crtr.Components {
List<Vector3> verts; List<Vector3> verts;
List<Vector2> uvs; List<Vector2> uvs;
List<int> trih = null, trib = null, trit = null; List<int> trih = null, trib = null, trit = null;
static List<int> _emptyTris = new List<int>();
public override void Seal() { public override void Seal() {
if (vertCount <= 1 || sumLength == 0) return; if (vertCount <= 1 || sumLength == 0) return;
@@ -185,13 +193,13 @@ namespace Cryville.Crtr.Components {
if (body.Frame != null) { m++; GenerateMeshTo(verts, uvs, out trib, body, ref i, ref t, ref l, headLength, sumLength - tailLength, vcpsec, hvc + bvc); } if (body.Frame != null) { m++; GenerateMeshTo(verts, uvs, out trib, body, ref i, ref t, ref l, headLength, sumLength - tailLength, vcpsec, hvc + bvc); }
if (tail.Frame != null) { m++; GenerateMeshTo(verts, uvs, out trit, tail, ref i, ref t, ref l, sumLength - tailLength, sumLength, vcpsec, vc); } if (tail.Frame != null) { m++; GenerateMeshTo(verts, uvs, out trit, tail, ref i, ref t, ref l, sumLength - tailLength, sumLength, vcpsec, vc); }
mesh.Mesh.subMeshCount = m; mesh.Mesh.subMeshCount = 3;
m = 0; m = 0;
mesh.Mesh.SetVertices(verts); mesh.Mesh.SetVertices(verts);
mesh.Mesh.SetUVs(0, uvs); mesh.Mesh.SetUVs(0, uvs);
if (head.Frame != null) mesh.Mesh.SetTriangles(trih, m++); mesh.Mesh.SetTriangles(head.Frame == null ? _emptyTris : trih, m++);
if (body.Frame != null) mesh.Mesh.SetTriangles(trib, m++); mesh.Mesh.SetTriangles(body.Frame == null ? _emptyTris : trib, m++);
if (tail.Frame != null) mesh.Mesh.SetTriangles(trit, m++); mesh.Mesh.SetTriangles(tail.Frame == null ? _emptyTris : trit, m++);
mesh.Mesh.RecalculateNormals(); mesh.Mesh.RecalculateNormals();
_vertPool.Return(verts); verts = null; _vertPool.Return(verts); verts = null;

View File

@@ -19,7 +19,7 @@ namespace Cryville.Crtr.Components {
private set; private set;
} }
public Rect Rect { public Rect Rect {
get { return Frame.frame; } get { return Frame.Frame; }
} }
/// <summary> /// <summary>
/// The ratio of width divided by height. /// The ratio of width divided by height.
@@ -61,7 +61,7 @@ namespace Cryville.Crtr.Components {
public class SpritePlane : SpriteBase { public class SpritePlane : SpriteBase {
public SpritePlane() { public SpritePlane() {
SubmitProperty("frame", new PropOp.String(v => Frame = v)); SubmitProperty("frame", new PropOp.String(v => Frame = v));
SubmitProperty("fit", new PropOp.Enum<FitMode>(v => Fit = v)); SubmitProperty("fit", new PropOp.Enum<FitMode>(v => Fit = v, v => (FitMode)v));
SubmitProperty("opacity", new PropOp.Float(v => Opacity = v)); SubmitProperty("opacity", new PropOp.Float(v => Opacity = v));
} }

View File

@@ -63,13 +63,13 @@ namespace Cryville.Crtr.Components {
case 1: x = _border.x; bx = b.x; break; case 1: x = _border.x; bx = b.x; break;
case 2: x = _border.y; bx = b.y; break; case 2: x = _border.y; bx = b.y; break;
case 3: x = 1; bx = 1; break; case 3: x = 1; bx = 1; break;
default: throw new Exception(); default: throw new NotSupportedException("Built-in resource corrupted");
} }
float y; float y;
switch ((int)muv[i].y) { switch ((int)muv[i].y) {
case 0: y = 0; break; case 0: y = 0; break;
case 3: y = 1; break; case 3: y = 1; break;
default: throw new Exception(); default: throw new NotSupportedException("Built-in resource corrupted");
} }
uv[i] = frameInfo.Frame.GetUV(x, y); uv[i] = frameInfo.Frame.GetUV(x, y);
bx -= 0.5f; y -= 0.5f; bx -= 0.5f; y -= 0.5f;

View File

@@ -79,7 +79,7 @@ namespace Cryville.Crtr.Components {
foreach (var f in m_frames) { foreach (var f in m_frames) {
f.Value.Load(); f.Value.Load();
if (frameHeight == 0) frameHeight = f.Value.Rect.height; if (frameHeight == 0) frameHeight = f.Value.Rect.height;
else if (frameHeight != f.Value.Rect.height) throw new Exception("Inconsistent frame height"); else if (frameHeight != f.Value.Rect.height) throw new Exception("Inconsistent frame height for text component");
var tex = f.Value.Frame.Texture; var tex = f.Value.Frame.Texture;
if (!meshes.ContainsKey(tex)) { if (!meshes.ContainsKey(tex)) {
var m = new MeshWrapper(); var m = new MeshWrapper();

View File

@@ -0,0 +1,56 @@
using Discord;
using System;
using UnityEngine;
namespace Cryville.Crtr {
internal class DiscordController : MonoBehaviour {
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
public static DiscordController Instance;
const long CLIENT_ID = 1059021675578007622L;
Discord.Discord dc;
ActivityManager am;
long launchTime;
void Start() {
Instance = this;
launchTime = (long)(DateTime.UtcNow - DateTime.UnixEpoch).TotalSeconds;
dc = new Discord.Discord(CLIENT_ID, (UInt64)CreateFlags.Default);
am = dc.GetActivityManager();
SetIdle();
}
void Update() {
dc.RunCallbacks();
}
void OnApplicationQuit() {
dc.Dispose();
}
void Callback(Result result) { }
public void SetIdle() {
am.UpdateActivity(new Activity {
State = "Idle",
Instance = false,
Timestamps = { Start = launchTime },
}, Callback);
}
public void SetPlaying(string detail, double? duration) {
long now = (long)(DateTime.UtcNow - DateTime.UnixEpoch).TotalSeconds;
am.UpdateActivity(new Activity {
State = "Playing a chart",
Details = detail,
Instance = true,
Timestamps = {
Start = now,
End = duration == null ? 0 : now + (long)duration,
},
}, Callback);
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7f7c5da9a520bef4e832e2f89f7b737f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,4 +1,5 @@
using Cryville.Common; using Cryville.Common;
using Cryville.Common.Buffers;
using Cryville.Crtr.Components; using Cryville.Crtr.Components;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -41,26 +42,11 @@ namespace Cryville.Crtr.Event {
protected Transform a_cur; protected Transform a_cur;
protected Transform a_head; protected Transform a_head;
protected Transform a_tail; protected Transform a_tail;
public Vector3 Position { public Vector3 Position { get; protected set; }
get; public Quaternion Rotation { get; protected set; }
protected set; public bool Alive { get; private set; }
} public bool Awoken { get; private set; }
public Quaternion Rotation { public bool Disposed { get; private set; }
get;
protected set;
}
public bool Alive {
get;
private set;
}
public bool Awoken {
get;
private set;
}
public bool Disposed {
get;
private set;
}
public EventContainer Container { public EventContainer Container {
get { return cs.Container; } get { return cs.Container; }
@@ -84,15 +70,16 @@ namespace Cryville.Crtr.Event {
gogroup = new GameObject(TypeName + ":" + Container.GetHashCode().ToString(CultureInfo.InvariantCulture)).transform; gogroup = new GameObject(TypeName + ":" + Container.GetHashCode().ToString(CultureInfo.InvariantCulture)).transform;
if (cs.Parent != null) if (cs.Parent != null)
gogroup.SetParent(cs.Parent.Handler.gogroup, false); gogroup.SetParent(cs.Parent.Handler.gogroup, false);
a_cur = RegisterAnchor(_a_cur); a_cur = RegisterAnchor(_a_cur).Transform;
a_head = RegisterAnchor(_a_head); a_head = RegisterAnchor(_a_head).Transform;
a_tail = RegisterAnchor(_a_tail); a_tail = RegisterAnchor(_a_tail).Transform;
} }
protected Transform RegisterAnchor(int name) { protected Anchor RegisterAnchor(int name) {
var go = new GameObject("." + IdentifierManager.SharedInstance.Retrieve(name)).transform; var go = new GameObject("." + IdentifierManager.SharedInstance.Retrieve(name)).transform;
go.SetParent(gogroup, false); go.SetParent(gogroup, false);
Anchors.Add(name, new Anchor() { Transform = go }); var result = new Anchor() { Transform = go };
return go; Anchors.Add(name, result);
return result;
} }
/// <summary> /// <summary>
@@ -132,13 +119,33 @@ namespace Cryville.Crtr.Event {
Init(); Init();
} }
} }
static readonly SimpleObjectPool<StampedEvent.Anchor> anchorEvPool
= new SimpleObjectPool<StampedEvent.Anchor>(1024);
protected void PushAnchorEvent(int name, double time) {
var tev = anchorEvPool.Rent();
tev.Time = time;
tev.Container = Container;
tev.Name = name;
ts.Bus.PushTempEvent(tev);
}
public virtual void Update(ContainerState s, StampedEvent ev) { public virtual void Update(ContainerState s, StampedEvent ev) {
bool flag = !Awoken && s.CloneType >= 2 && s.CloneType < 16; bool flag = !Awoken && s.CloneType >= 2 && s.CloneType < 16;
if (flag) PreAwake(s); if (flag) PreAwake(s);
if (s.CloneType <= 2) if (gogroup) skinContainer.MatchDynamic(s); if (s.CloneType <= 2) if (gogroup) skinContainer.MatchDynamic(s);
if (flag) Awake(s); if (flag) Awake(s);
} }
public virtual void ExUpdate(ContainerState s, StampedEvent ev) { } public virtual void ExUpdate(ContainerState s, StampedEvent ev) {
if (ev is StampedEvent.Anchor) {
var tev = (StampedEvent.Anchor)ev;
if (gogroup) {
OpenAnchor(tev.Name);
Anchors[tev.Name].Transform.SetPositionAndRotation(Position, Rotation);
skinContainer.MatchDynamic(s);
CloseAnchor(tev.Name);
}
anchorEvPool.Return(tev);
}
}
public virtual void MotionUpdate(byte ct, Chart.Motion ev) { } public virtual void MotionUpdate(byte ct, Chart.Motion ev) { }
public virtual void EndUpdate(ContainerState s) { public virtual void EndUpdate(ContainerState s) {
if (s.CloneType < 16) { if (s.CloneType < 16) {
@@ -146,7 +153,9 @@ namespace Cryville.Crtr.Event {
if (gogroup && s.CloneType <= 2) skinContainer.MatchDynamic(s); if (gogroup && s.CloneType <= 2) skinContainer.MatchDynamic(s);
} }
} }
public virtual void Anchor() { } public virtual void Anchor() {
if (cs.Working) PushAnchorEvent(_a_cur, cs.Time);
}
protected void OpenAnchor(int name) { protected void OpenAnchor(int name) {
if (Anchors.ContainsKey(name)) Anchors[name].Open(); if (Anchors.ContainsKey(name)) Anchors[name].Open();
} }

View File

@@ -81,14 +81,7 @@ namespace Cryville.Crtr.Event {
/// <param name="clone">Returns a cloned motion value instead.</param> /// <param name="clone">Returns a cloned motion value instead.</param>
/// <returns>A motion value.</returns> /// <returns>A motion value.</returns>
RealtimeMotionValue GetMotionValue(Identifier name, bool clone = false) { RealtimeMotionValue GetMotionValue(Identifier name, bool clone = false) {
RealtimeMotionValue value; RealtimeMotionValue value = Values[name];
if (!Values.TryGetValue(name, out value)) {
value = new RealtimeMotionValue().Init(Parent == null
? ChartPlayer.motionRegistry[name].GlobalInitValue
: ChartPlayer.motionRegistry[name].InitValue
);
Values.Add(name, value);
}
if (clone) return value.Clone(); if (clone) return value.Clone();
return value; return value;
} }
@@ -98,8 +91,9 @@ namespace Cryville.Crtr.Event {
if (!CachedValues.TryGetValue(name, out cache)) if (!CachedValues.TryGetValue(name, out cache))
CachedValues.Add(name, cache = new CacheEntry()); CachedValues.Add(name, cache = new CacheEntry());
cache.Valid = false; cache.Valid = false;
foreach (var c in Children) ValidateChildren();
c.Value.InvalidateMotion(name); foreach (var c in WorkingChildren)
Children[c].InvalidateMotion(name);
} }
public ContainerState(Chart c, EventContainer _ev, ContainerState parent = null) { public ContainerState(Chart c, EventContainer _ev, ContainerState parent = null) {
@@ -171,6 +165,7 @@ namespace Cryville.Crtr.Event {
else dest.Values.Add(mv.Key, mv.Value.Clone()); else dest.Values.Add(mv.Key, mv.Value.Clone());
} }
foreach (var cv in dest.CachedValues) cv.Value.Valid = false;
foreach (var cv in CachedValues) { foreach (var cv in CachedValues) {
CacheEntry dv; CacheEntry dv;
if (dest.CachedValues.TryGetValue(cv.Key, out dv)) { if (dest.CachedValues.TryGetValue(cv.Key, out dv)) {
@@ -184,7 +179,7 @@ namespace Cryville.Crtr.Event {
Children[cev].CopyTo(ct, dest.Children[cev]); Children[cev].CopyTo(ct, dest.Children[cev]);
else foreach (var child in Children) else foreach (var child in Children)
child.Value.CopyTo(ct, dest.Children[child.Key]); child.Value.CopyTo(ct, dest.Children[child.Key]);
ValidateChildren(); dest.ValidateChildren();
dest.PlayingMotions.Clear(); dest.PlayingMotions.Clear();
foreach (var m in PlayingMotions) dest.PlayingMotions.Add(m.Key, m.Value); foreach (var m in PlayingMotions) dest.PlayingMotions.Add(m.Key, m.Value);
@@ -205,7 +200,7 @@ namespace Cryville.Crtr.Event {
public void AttachHandler(ContainerHandler h) { public void AttachHandler(ContainerHandler h) {
if (Handler != null) if (Handler != null)
throw new InvalidOperationException(); throw new InvalidOperationException("Handler attached twice");
Handler = h; Handler = h;
h.cs = this; h.cs = this;
} }
@@ -217,9 +212,9 @@ namespace Cryville.Crtr.Event {
public Vector GetRawValue(Identifier key) { public Vector GetRawValue(Identifier key) {
CacheEntry tr; CacheEntry tr;
if (!CachedValues.TryGetValue(key, out tr)) if (!CachedValues.TryGetValue(key, out tr))
CachedValues.Add(key, tr = new CacheEntry { Valid = false }); CachedValues.Add(key, tr = new CacheEntry { });
if (tr.Value == null) if (tr.Value == null)
tr.Value = (Vector)ReflectionHelper.InvokeEmptyConstructor(ChartPlayer.motionRegistry[key].Type); tr.Value = RMVPool.Rent(key).AbsoluteValue;
Vector r = tr.Value; Vector r = tr.Value;
#if !DISABLE_CACHE #if !DISABLE_CACHE
if (tr.Valid) return r; if (tr.Valid) return r;
@@ -317,7 +312,7 @@ namespace Cryville.Crtr.Event {
Working = false; Working = false;
} }
public void Handle(StampedEvent ev, Action<StampedEvent> callback = null) { public void Handle(StampedEvent ev) {
if (breakflag) return; if (breakflag) return;
if (ev != null) { if (ev != null) {
if (ev.Unstamped is Chart.Motion) { if (ev.Unstamped is Chart.Motion) {
@@ -326,7 +321,7 @@ namespace Cryville.Crtr.Event {
mv.CloneTypeFlag = CloneType; mv.CloneTypeFlag = CloneType;
GetMotionValue(tev.Name).CopyTo(mv); GetMotionValue(tev.Name).CopyTo(mv);
PlayingMotions.Add(ev, mv); PlayingMotions.Add(ev, mv);
Callback(ev, callback); Update(ev);
if (!ev.Unstamped.IsLong) { if (!ev.Unstamped.IsLong) {
PlayingMotions.Remove(ev); PlayingMotions.Remove(ev);
RMVPool.Return(mv); RMVPool.Return(mv);
@@ -349,7 +344,7 @@ namespace Cryville.Crtr.Event {
if (tev.IsRelease) { if (tev.IsRelease) {
var nev = tev.Original; var nev = tev.Original;
if (nev is Chart.Motion) { if (nev is Chart.Motion) {
Callback(ev, callback); Update(ev);
var mv = PlayingMotions[ev.Origin]; var mv = PlayingMotions[ev.Origin];
if (mv.CloneTypeFlag == CloneType) RMVPool.Return(mv); if (mv.CloneTypeFlag == CloneType) RMVPool.Return(mv);
PlayingMotions.Remove(ev.Origin); PlayingMotions.Remove(ev.Origin);
@@ -364,15 +359,13 @@ namespace Cryville.Crtr.Event {
} }
} }
} }
Callback(ev.Unstamped == null || ev.Unstamped.Priority >= 0 ? ev : null, callback); Update(ev.Unstamped == null || ev.Unstamped.Priority >= 0 ? ev : null);
} }
else Callback(null, callback); else Update(null);
} }
void Callback(StampedEvent ev, Action<StampedEvent> callback) { void Update(StampedEvent ev) {
UpdateMotions(); UpdateMotions();
if (callback != null)
callback(ev);
if (ev == null || ev.Unstamped != null) Handler.Update(this, ev); if (ev == null || ev.Unstamped != null) Handler.Update(this, ev);
else Handler.ExUpdate(this, ev); else Handler.ExUpdate(this, ev);
foreach (var m in PlayingMotions) foreach (var m in PlayingMotions)

View File

@@ -56,7 +56,7 @@ namespace Cryville.Crtr.Event {
} }
} }
public override void ForwardOnceToTime(double toTime, Action<ChartEvent> callback) { public override void ForwardOnceToTime(double toTime) {
double toBeat = Math.Round(beat + (toTime - Time) * tempo / 60f, 6); double toBeat = Math.Round(beat + (toTime - Time) * tempo / 60f, 6);
if (EventId >= events.Count) if (EventId >= events.Count)
goto return_ahead; goto return_ahead;
@@ -84,7 +84,6 @@ namespace Cryville.Crtr.Event {
} }
stampedEvents.Add(sev); stampedEvents.Add(sev);
if (ev.Priority >= 0) { if (ev.Priority >= 0) {
if (callback != null) callback(ev);
flag = true; flag = true;
} }
if (ev is Chart.Signature) { if (ev is Chart.Signature) {
@@ -93,12 +92,10 @@ namespace Cryville.Crtr.Event {
} }
EventId++; EventId++;
} }
if (callback != null && !flag) callback(batch.First());
return; return;
return_ahead: return_ahead:
Time = toTime; Time = toTime;
beat = toBeat; beat = toBeat;
if (callback != null) callback(null);
} }
IOrderedEnumerable<ChartEvent> GetEventBatch() { IOrderedEnumerable<ChartEvent> GetEventBatch() {

View File

@@ -33,6 +33,7 @@ namespace Cryville.Crtr.Event {
r.activeContainers = new List<EventContainer>(); r.activeContainers = new List<EventContainer>();
r.workingStates = new HashSet<ContainerState>(); r.workingStates = new HashSet<ContainerState>();
r.invalidatedStates = new HashSet<ContainerState>(); r.invalidatedStates = new HashSet<ContainerState>();
r.tempEvents = new List<StampedEvent>();
r.Time += offsetTime; r.Time += offsetTime;
r.RootState = RootState.Clone(ct); r.RootState = RootState.Clone(ct);
r.RootState.StartUpdate(); r.RootState.StartUpdate();
@@ -99,39 +100,46 @@ namespace Cryville.Crtr.Event {
s.AttachSystems(skin, judge); s.AttachSystems(skin, judge);
} }
readonly List<StampedEvent> patch = new List<StampedEvent>(); List<StampedEvent> tempEvents = new List<StampedEvent>();
public void IssuePatch(IEnumerable<StampedEvent> l) { public void PushTempEvent(StampedEvent ev) {
patch.AddRange(l); var index = tempEvents.BinarySearch(ev);
} if (index < 0) index = ~index;
public void DoPatch() { tempEvents.Insert(index, ev);
foreach (var ev in patch) {
var batch = new EventBatch(ev.Time);
var batchIndex = events.BinarySearch(batch);
if (batchIndex >= 0) batch = events[batchIndex];
else events.Insert(~batchIndex, batch);
batch.Add(ev);
}
patch.Clear();
} }
public override void ForwardOnceToTime(double toTime, Action<EventBatch> callback = null) { public override void ForwardOnceToTime(double toTime) {
if (EventId < events.Count && events[EventId].Time <= toTime) { double time1 = EventId < events.Count ? events[EventId].Time : double.PositiveInfinity;
Time = events[EventId].Time; double time2 = tempEvents.Count > 0 ? tempEvents[0].Time : double.PositiveInfinity;
var batch = events[EventId]; double time0 = Math.Min(time1, time2);
if (time0 <= toTime && time0 != double.PositiveInfinity) {
Time = time0;
foreach (var s in workingStates) s.Handle(null); foreach (var s in workingStates) s.Handle(null);
ValidateStates(); ValidateStates();
for (var i = 0; i < batch.Count; i++) { if (time1 == time0) {
var ev = batch[i]; var batch = events[EventId];
if (ev.Container != null) { for (var i = 0; i < batch.Count; i++) {
EnsureActivity(ev.Container); var ev = batch[i];
states[ev.Container].Handle(ev); if (ev.Container != null) {
EnsureActivity(ev.Container);
states[ev.Container].Handle(ev);
}
if (ev.Unstamped is EventContainer) {
if (ev.Container != null) EnsureActivity((EventContainer)ev.Unstamped);
}
} }
if (ev.Unstamped is EventContainer) { EventId++;
if (ev.Container != null) EnsureActivity((EventContainer)ev.Unstamped); }
if (time2 == time0) {
while (tempEvents.Count > 0) {
var ev = tempEvents[0];
if (ev.Container != null) {
EnsureActivity(ev.Container);
states[ev.Container].Handle(ev);
}
tempEvents.RemoveAt(0);
} }
} }
ValidateStates(); ValidateStates();
EventId++;
} }
else { else {
Time = toTime; Time = toTime;
@@ -156,6 +164,7 @@ namespace Cryville.Crtr.Event {
public void BroadcastEndUpdate() { public void BroadcastEndUpdate() {
RootState.BroadcastEndUpdate(); RootState.BroadcastEndUpdate();
tempEvents.Clear();
} }
public void Anchor() { public void Anchor() {

View File

@@ -20,10 +20,13 @@ namespace Cryville.Crtr.Event {
_buckets.Add(reg.Key, new Bucket(reg.Key, 4096)); _buckets.Add(reg.Key, new Bucket(reg.Key, 4096));
} }
readonly Dictionary<RealtimeMotionValue, Identifier> _rented = new Dictionary<RealtimeMotionValue, Identifier>(); static readonly SimpleObjectPool<Dictionary<RealtimeMotionValue, Identifier>> _dictPool
= new SimpleObjectPool<Dictionary<RealtimeMotionValue, Identifier>>(1024);
Dictionary<RealtimeMotionValue, Identifier> _rented;
public RealtimeMotionValue Rent(Identifier name) { public RealtimeMotionValue Rent(Identifier name) {
var n = name; var n = name;
var obj = _buckets[n].Rent(); var obj = _buckets[n].Rent();
if (_rented == null) _rented = _dictPool.Rent();
_rented.Add(obj, n); _rented.Add(obj, n);
return obj; return obj;
} }
@@ -35,6 +38,7 @@ namespace Cryville.Crtr.Event {
foreach (var obj in _rented) foreach (var obj in _rented)
_buckets[obj.Value].Return(obj.Key); _buckets[obj.Value].Return(obj.Key);
_rented.Clear(); _rented.Clear();
_dictPool.Return(_rented);
} }
} }
} }

View File

@@ -18,11 +18,11 @@ namespace Cryville.Crtr.Extensions.Malody {
public override IEnumerable<Resource> ConvertFrom(FileInfo file) { public override IEnumerable<Resource> ConvertFrom(FileInfo file) {
List<Resource> result = new List<Resource>(); List<Resource> result = new List<Resource>();
MalodyChart src; MalodyChart src;
if (file.Extension != ".mc") throw new NotImplementedException("mcz file is not supported"); if (file.Extension != ".mc") throw new NotImplementedException("mcz file is not supported yet");
using (var reader = new StreamReader(file.FullName)) { using (var reader = new StreamReader(file.FullName)) {
src = JsonConvert.DeserializeObject<MalodyChart>(reader.ReadToEnd()); src = JsonConvert.DeserializeObject<MalodyChart>(reader.ReadToEnd());
} }
if (src.meta.mode != 0) throw new NotImplementedException("The chart mode is not supported"); if (src.meta.mode != 0) throw new NotImplementedException(string.Format("{0} mode is not supported yet", MODES[src.meta.mode]));
var ruleset = "malody!" + MODES[src.meta.mode]; var ruleset = "malody!" + MODES[src.meta.mode];
if (src.meta.mode == 0) { if (src.meta.mode == 0) {
@@ -110,7 +110,7 @@ namespace Cryville.Crtr.Extensions.Malody {
offset = -tev.offset / 1000f, offset = -tev.offset / 1000f,
}); });
} }
else throw new NotImplementedException(); else throw new NotImplementedException("Key sounds are not supported yet");
} }
else { else {
var rn = new Chart.Note() { var rn = new Chart.Note() {
@@ -135,9 +135,9 @@ namespace Cryville.Crtr.Extensions.Malody {
var sev = tev.StartEvent; var sev = tev.StartEvent;
longEvents.Remove(sev); longEvents.Remove(sev);
} }
else throw new NotSupportedException(); else throw new NotSupportedException("Unrecognized long event");
} }
else throw new NotSupportedException(); else throw new NotSupportedException("Unrecognized event");
} }
var endbeat = tm.FractionalBeatTime; var endbeat = tm.FractionalBeatTime;
endbeat.b += 4; endbeat.b += 4;

View File

@@ -35,6 +35,7 @@ namespace Cryville.Crtr.Extensions.osu {
var diff = new DifficultyInfo(); var diff = new DifficultyInfo();
var evs = new List<osuEvent>(); var evs = new List<osuEvent>();
bool ftc = false;
using (var reader = new StreamReader(file.FullName, Encoding.UTF8)) { using (var reader = new StreamReader(file.FullName, Encoding.UTF8)) {
Section section = Section.General; Section section = Section.General;
int version; int version;
@@ -45,7 +46,7 @@ namespace Cryville.Crtr.Extensions.osu {
if (line.StartsWith("osu file format v")) { if (line.StartsWith("osu file format v")) {
version = int.Parse(line.Substring(17), CultureInfo.InvariantCulture); version = int.Parse(line.Substring(17), CultureInfo.InvariantCulture);
if (version > 14) throw new NotSupportedException("osu! chart format version too high"); if (version > 14) throw new NotSupportedException("osu! chart format version too high");
else if (version < 5) throw new NotSupportedException("osu! chart format version too low"); // TODO apply offset else if (version < 5) throw new NotImplementedException("osu! chart format version too low"); // TODO apply offset
} }
else throw new NotSupportedException("Unrecognized osu! chart format"); else throw new NotSupportedException("Unrecognized osu! chart format");
flag = true; flag = true;
@@ -57,10 +58,14 @@ namespace Cryville.Crtr.Extensions.osu {
Enum.TryParse(line.Substring(1, line.Length - 2), out section); Enum.TryParse(line.Substring(1, line.Length - 2), out section);
continue; continue;
} }
ParseLine(meta, chart, diff, evs, section, line); ParseLine(meta, chart, diff, evs, ref ftc, section, line);
} }
} }
if (meta.ruleset == "osu!mania") {
chart.ruleset = meta.ruleset += "." + diff.CircleSize.ToString(CultureInfo.InvariantCulture) + "k";
}
if (!ftc) throw new InvalidOperationException("Unconvertible chart: no timing point is present in this beatmap");
result.Add(new RawChartResource(string.Format("{0} - {1}", meta.song.name, meta.name), chart, meta)); result.Add(new RawChartResource(string.Format("{0} - {1}", meta.song.name, meta.name), chart, meta));
var evc = evs.Count; var evc = evs.Count;
for (int i = 0; i < evc; i++) if (evs[i].IsLong) evs.Add(new osuEvent.EndEvent(evs[i])); for (int i = 0; i < evc; i++) if (evs[i].IsLong) evs.Add(new osuEvent.EndEvent(evs[i]));
@@ -81,7 +86,7 @@ namespace Cryville.Crtr.Extensions.osu {
} }
else if (ev is osuEvent.EffectPoint) { else if (ev is osuEvent.EffectPoint) {
var tev = (osuEvent.EffectPoint)ev; var tev = (osuEvent.EffectPoint)ev;
group.motions.Add(new Chart.Motion { motion = string.Format(CultureInfo.InvariantCulture, "svm:{0}", tev.ScrollSpeed) }); group.motions.Add(new Chart.Motion { time = tm.FractionalBeatTime, motion = string.Format(CultureInfo.InvariantCulture, "svm:{0}", tev.ScrollSpeed) });
} }
else if (ev is osuEvent.EndEvent) { else if (ev is osuEvent.EndEvent) {
if (tm == null) throw new InvalidOperationException("Unconvertible chart: timed event before first timing point"); if (tm == null) throw new InvalidOperationException("Unconvertible chart: timed event before first timing point");
@@ -122,13 +127,13 @@ namespace Cryville.Crtr.Extensions.osu {
return result; return result;
} }
void ParseLine(ChartMeta meta, Chart chart, DifficultyInfo diff, List<osuEvent> evs, Section section, string line) { void ParseLine(ChartMeta meta, Chart chart, DifficultyInfo diff, List<osuEvent> evs, ref bool ftc, Section section, string line) {
switch (section) { switch (section) {
case Section.General: HandleGeneral(meta, chart, evs, line); return; case Section.General: HandleGeneral(meta, chart, evs, line); return;
case Section.Metadata: HandleMetadata(meta, line); return; case Section.Metadata: HandleMetadata(meta, line); return;
case Section.Difficulty: HandleDifficulty(diff, line); return; case Section.Difficulty: HandleDifficulty(diff, line); return;
case Section.Events: HandleEvent(evs, line); return; case Section.Events: HandleEvent(evs, line); return;
case Section.TimingPoints: HandleTimingPoint(chart, evs, line); return; case Section.TimingPoints: HandleTimingPoint(chart, evs, ref ftc, line); return;
case Section.HitObjects: HandleHitObject(evs, line); return; case Section.HitObjects: HandleHitObject(evs, line); return;
} }
} }
@@ -143,9 +148,9 @@ namespace Cryville.Crtr.Extensions.osu {
int rulesetID = int.Parse(pair.Value, CultureInfo.InvariantCulture); int rulesetID = int.Parse(pair.Value, CultureInfo.InvariantCulture);
var ruleset = "osu!"; var ruleset = "osu!";
switch (rulesetID) { switch (rulesetID) {
case 0: /*ruleset += "standard";*/ throw new NotSupportedException("osu!standard mode is not supported yet"); case 0: /*ruleset += "standard";*/ throw new NotImplementedException("osu!standard mode is not supported yet");
case 1: /*ruleset += "taiko";*/ throw new NotSupportedException("osu!taiko mode is not supported yet"); case 1: /*ruleset += "taiko";*/ throw new NotImplementedException("osu!taiko mode is not supported yet");
case 2: /*ruleset += "catch";*/ throw new NotSupportedException("osu!catch mode is not supported yet"); case 2: /*ruleset += "catch";*/ throw new NotImplementedException("osu!catch mode is not supported yet");
case 3: ruleset += "mania"; break; case 3: ruleset += "mania"; break;
} }
meta.ruleset = chart.ruleset = ruleset; meta.ruleset = chart.ruleset = ruleset;
@@ -201,7 +206,7 @@ namespace Cryville.Crtr.Extensions.osu {
Animation = 6 Animation = 6
} }
void HandleTimingPoint(Chart chart, List<osuEvent> evs, string line) { void HandleTimingPoint(Chart chart, List<osuEvent> evs, ref bool ftc, string line) {
string[] split = line.Split(','); string[] split = line.Split(',');
double time = double.Parse(split[0].Trim(), CultureInfo.InvariantCulture)/* + offset*/; double time = double.Parse(split[0].Trim(), CultureInfo.InvariantCulture)/* + offset*/;
@@ -230,7 +235,12 @@ namespace Cryville.Crtr.Extensions.osu {
if (timingChange) { if (timingChange) {
if (double.IsNaN(beatLength)) if (double.IsNaN(beatLength))
throw new InvalidDataException("Beat length cannot be NaN in a timing control point"); throw new InvalidDataException("Beat length cannot be NaN in a timing control point");
evs.Add(new osuEvent.TimingChange { StartTime = time, BeatLength = beatLength, TimeSignature = timeSignature }); var ev = new osuEvent.TimingChange { StartTime = time, BeatLength = beatLength, TimeSignature = timeSignature };
if (!ftc) {
ftc = true;
ev.StartTime = time % beatLength - beatLength;
}
evs.Add(ev);
} }
// osu!taiko and osu!mania use effect points rather than difficulty points for scroll speed adjustments. // osu!taiko and osu!mania use effect points rather than difficulty points for scroll speed adjustments.

View File

@@ -5,7 +5,7 @@ using System.Linq;
using UnityEngine; using UnityEngine;
namespace Cryville.Crtr { namespace Cryville.Crtr {
class GroupHandler : ContainerHandler { public class GroupHandler : ContainerHandler {
public ChartHandler ch; public ChartHandler ch;
SquareMatrix matFrame; SquareMatrix matFrame;

View File

@@ -232,8 +232,7 @@ namespace Cryville.Crtr {
public void SyncTime(double time) { public void SyncTime(double time) {
foreach (var s in _sproxies.Keys) { foreach (var s in _sproxies.Keys) {
var h = s.Handler; var h = s.Handler;
if (!_timeOrigins.ContainsKey(h)) _timeOrigins[h] = h.GetCurrentTimestamp() - time;
_timeOrigins.Add(h, h.GetCurrentTimestamp() - time);
} }
} }
public void ForceTick() { public void ForceTick() {

View File

@@ -1,13 +1,13 @@
using Cryville.Common; using Cryville.Common;
using Cryville.Common.Buffers; using Cryville.Common.Buffers;
using Cryville.Common.Pdt; using Cryville.Common.Pdt;
using Cryville.Crtr.Event;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
namespace Cryville.Crtr { namespace Cryville.Crtr {
public class Judge { public class Judge {
#region Data
readonly PdtEvaluator _etor; readonly PdtEvaluator _etor;
readonly PdtRuleset _rs; readonly PdtRuleset _rs;
readonly Dictionary<Identifier, float> ct readonly Dictionary<Identifier, float> ct
@@ -16,13 +16,14 @@ namespace Cryville.Crtr {
= new Dictionary<Identifier, List<JudgeEvent>>(); = new Dictionary<Identifier, List<JudgeEvent>>();
readonly Dictionary<Identifier, List<JudgeEvent>> activeEvs readonly Dictionary<Identifier, List<JudgeEvent>> activeEvs
= new Dictionary<Identifier, List<JudgeEvent>>(); = new Dictionary<Identifier, List<JudgeEvent>>();
struct JudgeEvent { public struct JudgeEvent {
public double StartTime { get; set; } public double StartTime { get; set; }
public double EndTime { get; set; } public double EndTime { get; set; }
public double StartClip { get; set; } public double StartClip { get; set; }
public double EndClip { get; set; } public double EndClip { get; set; }
public Identifier JudgeId { get; set; }
public JudgeDefinition Definition { get; set; } public JudgeDefinition Definition { get; set; }
public ContainerState State { get; set; } public NoteHandler Handler { get; set; }
} }
static readonly IComparer<JudgeEvent> _stcmp = new JudgeEventStartTimeComparer(); static readonly IComparer<JudgeEvent> _stcmp = new JudgeEventStartTimeComparer();
class JudgeEventStartTimeComparer : IComparer<JudgeEvent> { class JudgeEventStartTimeComparer : IComparer<JudgeEvent> {
@@ -33,27 +34,40 @@ namespace Cryville.Crtr {
public Judge(PdtRuleset rs) { public Judge(PdtRuleset rs) {
_etor = ChartPlayer.etor; _etor = ChartPlayer.etor;
_rs = rs; _rs = rs;
InitJudges();
InitScores(); InitScores();
} }
public void Prepare(double st, double et, Identifier input, JudgeDefinition def, ContainerState container) { public void Prepare(double st, double et, Identifier input, Identifier judge, NoteHandler handler) {
List<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 List<JudgeEvent>()); evs.Add(input, list = new List<JudgeEvent>());
activeEvs.Add(input, new List<JudgeEvent>()); activeEvs.Add(input, new List<JudgeEvent>());
} }
var def = _rs.judges[judge];
var ev = new JudgeEvent { var ev = new JudgeEvent {
StartTime = st, StartTime = st,
EndTime = et, EndTime = et,
StartClip = st + def.clip[0], StartClip = st + def.clip[0],
EndClip = et + def.clip[1], EndClip = et + def.clip[1],
JudgeId = judge,
Definition = def, Definition = def,
State = container, Handler = handler,
}; };
var index = list.BinarySearch(ev, _stcmp); var index = list.BinarySearch(ev, _stcmp);
if (index < 0) index = ~index; if (index < 0) index = ~index;
list.Insert(index, ev); list.Insert(index, ev);
} }
#endregion
#region Judge
internal readonly Dictionary<int, int> jtabsMap = new Dictionary<int, int>();
internal readonly Dictionary<int, int> jtrelMap = new Dictionary<int, int>();
void InitJudges() {
foreach (var i in _rs.judges.Keys) {
jtabsMap.Add(i.Key, IdentifierManager.SharedInstance.Request("jtabs_" + i.Name));
jtrelMap.Add(i.Key, IdentifierManager.SharedInstance.Request("jtrel_" + i.Name));
}
}
static bool _flag; static bool _flag;
static readonly PropOp.Boolean _flagop = new PropOp.Boolean(v => _flag = v); static readonly PropOp.Boolean _flagop = new PropOp.Boolean(v => _flag = v);
static readonly int _var_fn = IdentifierManager.SharedInstance.Request("fn"); static readonly int _var_fn = IdentifierManager.SharedInstance.Request("fn");
@@ -112,7 +126,7 @@ namespace Cryville.Crtr {
else _flag = true; else _flag = true;
if (_flag) { if (_flag) {
if (def.scores != null) UpdateScore(def.scores); if (def.scores != null) UpdateScore(def.scores);
if (def.pass != null) Pass(def.pass); if (def.pass != null) Pass(ev, (ft + tt) / 2, def.pass);
actlist.RemoveAt(index); actlist.RemoveAt(index);
if (def.prop != 0 && actlist.Count > 0) { if (def.prop != 0 && actlist.Count > 0) {
index = BinarySearchFirst(actlist, (float)ev.StartClip, def.stack - def.prop); index = BinarySearchFirst(actlist, (float)ev.StartClip, def.stack - def.prop);
@@ -124,14 +138,15 @@ namespace Cryville.Crtr {
} }
} }
} }
bool Pass(Identifier[] ids) { bool Pass(JudgeEvent ev, float time, Identifier[] ids) {
foreach (var i in ids) { foreach (var i in ids) {
var def = _rs.judges[i]; var def = _rs.judges[i];
if (def.hit != null) _etor.Evaluate(_flagop, def.hit); if (def.hit != null) _etor.Evaluate(_flagop, def.hit);
else _flag = true; else _flag = true;
if (_flag) { if (_flag) {
if (def.scores != null) UpdateScore(def.scores); if (def.scores != null) UpdateScore(def.scores);
if (def.pass != null) Pass(def.pass); if (def.pass != null) Pass(ev, time, def.pass);
ev.Handler.ReportJudge(ev, time, i);
return true; return true;
} }
} }
@@ -144,7 +159,7 @@ namespace Cryville.Crtr {
JudgeEvent ev = actlist[i]; JudgeEvent ev = actlist[i];
if (tt > ev.EndClip) { if (tt > ev.EndClip) {
actlist.RemoveAt(i); actlist.RemoveAt(i);
if (ev.Definition.miss != null) Pass(ev.Definition.miss); if (ev.Definition.miss != null) Pass(ev, tt, ev.Definition.miss);
} }
} }
} }
@@ -174,6 +189,8 @@ namespace Cryville.Crtr {
} }
} }
} }
#endregion
#region Score
readonly Dictionary<int, int> scoreStringKeys = new Dictionary<int, int>(); readonly Dictionary<int, int> scoreStringKeys = new Dictionary<int, int>();
readonly Dictionary<int, int> scoreStringKeysRev = new Dictionary<int, int>(); readonly Dictionary<int, int> scoreStringKeysRev = new Dictionary<int, int>();
readonly Dictionary<int, PropSrc> scoreSrcs = new Dictionary<int, PropSrc>(); readonly Dictionary<int, PropSrc> scoreSrcs = new Dictionary<int, PropSrc>();
@@ -240,20 +257,22 @@ namespace Cryville.Crtr {
_buf = null; _buf = null;
} }
} }
protected override unsafe void InternalGet(out int type, out byte[] value) { protected override unsafe int InternalGet() {
var src = _cb(); var src = _cb();
int strlen = src.Length; int strlen = src.Length;
type = PdtInternalType.String; buf = _pool.Rent(sizeof(int) + strlen * sizeof(char));
value = _pool.Rent(sizeof(int) + strlen * sizeof(char)); fixed (byte* _ptr = buf) {
fixed (byte* _ptr = value) {
char* ptr = (char*)(_ptr + sizeof(int)); char* ptr = (char*)(_ptr + sizeof(int));
*(int*)_ptr = strlen; *(int*)_ptr = strlen;
int i = 0; int i = 0;
foreach (var c in src) ptr[i++] = c; foreach (var c in src) ptr[i++] = c;
} }
return PdtInternalType.String;
} }
} }
#endregion
} }
#region Definitions
public class InputDefinition { public class InputDefinition {
public int dim; public int dim;
public bool notnull; public bool notnull;
@@ -282,4 +301,5 @@ namespace Cryville.Crtr {
public float init = 0; public float init = 0;
public string format = ""; public string format = "";
} }
#endregion
} }

View File

@@ -928,25 +928,25 @@ namespace Cryville.Crtr {
public class VectorSrc : PropSrc { public class VectorSrc : PropSrc {
readonly Func<Vector> _cb; readonly Func<Vector> _cb;
public VectorSrc(Func<Vector> cb) { _cb = cb; } public VectorSrc(Func<Vector> cb) { _cb = cb; }
protected override unsafe void InternalGet(out int type, out byte[] value) { protected override unsafe int InternalGet() {
var arr = _cb().ToArray(); var arr = _cb().ToArray();
if (arr.Length == 1) { if (arr.Length == 1) {
type = PdtInternalType.Number; buf = new byte[sizeof(float)];
value = new byte[sizeof(float)]; fixed (byte* ptr = buf) {
fixed (byte* ptr = value) {
*(float*)ptr = arr[0]; *(float*)ptr = arr[0];
} }
return PdtInternalType.Number;
} }
else { else {
type = PdtInternalType.Vector; buf = new byte[sizeof(float) * arr.Length + sizeof(int)];
value = new byte[sizeof(float) * arr.Length + sizeof(int)]; fixed (byte* rptr = buf) {
fixed (byte* rptr = value) {
var ptr = (float*)rptr; var ptr = (float*)rptr;
for (int i = 0; i < arr.Length; i++, ptr++) { for (int i = 0; i < arr.Length; i++, ptr++) {
*ptr = arr[i]; *ptr = arr[i];
} }
*(int*)ptr = PdtInternalType.Number; *(int*)ptr = PdtInternalType.Number;
} }
return PdtInternalType.Vector;
} }
} }
} }

View File

@@ -7,7 +7,7 @@ using System.Collections.Generic;
using UnityEngine; using UnityEngine;
namespace Cryville.Crtr { namespace Cryville.Crtr {
class NoteHandler : ContainerHandler { public class NoteHandler : ContainerHandler {
readonly GroupHandler gh; readonly GroupHandler gh;
public readonly Chart.Note Event; public readonly Chart.Note Event;
readonly PdtRuleset ruleset; readonly PdtRuleset ruleset;
@@ -24,7 +24,32 @@ namespace Cryville.Crtr {
} }
SectionalGameObject[] sgos; SectionalGameObject[] sgos;
readonly Dictionary<Identifier, JudgeState> judges = new Dictionary<Identifier, JudgeState>();
class JudgeState {
public int AbsoluteAnchorName { get; set; }
public int RelativeAnchorName { get; set; }
public bool Judged { get; private set; }
public float AbsoluteTime { get; private set; }
public float RelativeTime { get; private set; }
public JudgeState(NoteHandler handler, int name) {
handler.RegisterAnchor(AbsoluteAnchorName = handler.judge.jtabsMap[name]);
handler.RegisterAnchor(RelativeAnchorName = handler.judge.jtrelMap[name]);
}
public void MarkJudged(float abs, float rel) {
Judged = true;
AbsoluteTime = abs;
RelativeTime = rel;
}
}
public override void PreInit() {
base.PreInit();
foreach (var j in Event.judges) {
if (!judges.ContainsKey(j.Id)) {
judges.Add(j.Id, new JudgeState(this, j.Id.Key));
}
}
}
public override void Init() { public override void Init() {
base.Init(); base.Init();
sgos = gogroup.GetComponentsInChildren<SectionalGameObject>(); sgos = gogroup.GetComponentsInChildren<SectionalGameObject>();
@@ -65,15 +90,7 @@ namespace Cryville.Crtr {
Position = GetFramePoint(s.Parent, s.Track); Position = GetFramePoint(s.Parent, s.Track);
Rotation = GetFrameRotation(s.Parent, s.Track); Rotation = GetFrameRotation(s.Parent, s.Track);
} }
if (s.CloneType == 0) { if (s.CloneType == 2) {
#if UNITY_5_6_OR_NEWER
a_cur.SetPositionAndRotation(Position, Rotation);
#else
a_cur.position = Position;
a_cur.rotation = Rotation;
#endif
}
else if (s.CloneType == 2) {
if (!gogroup) return; if (!gogroup) return;
Chart.Note tev = Event; Chart.Note tev = Event;
if (tev.IsLong) { if (tev.IsLong) {
@@ -90,13 +107,24 @@ 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(ev.Time, ev.Time + ev.Duration, name, ruleset.judges[tev.Id], cs); judge.Prepare(ev.Time, ev.Time + ev.Duration, name, tev.Id, this);
ChartPlayer.etor.ContextState = null; ChartPlayer.etor.ContextState = null;
ChartPlayer.etor.ContextEvent = null; ChartPlayer.etor.ContextEvent = null;
} }
} }
} }
public override void Anchor() {
base.Anchor();
if (cs.Working) {
foreach (var j in judges.Values) {
if (!j.Judged) continue;
// PushAnchorEvent(j.AbsoluteAnchorName, j.AbsoluteTime);
// PushAnchorEvent(j.RelativeAnchorName, j.RelativeTime + cs.Time);
}
}
}
public override void EndUpdate(ContainerState s) { public override void EndUpdate(ContainerState s) {
if (s.CloneType == 2 && gogroup) { if (s.CloneType == 2 && gogroup) {
foreach (var i in sgos) i.Seal(); foreach (var i in sgos) i.Seal();
@@ -166,5 +194,11 @@ namespace Cryville.Crtr {
} }
} }
} }
public void ReportJudge(Judge.JudgeEvent ev, float time, Identifier result) {
JudgeState state;
if (!judges.TryGetValue(ev.JudgeId, out state)) return;
state.MarkJudged(time, (float)(time - cs.Time));
}
} }
} }

View File

@@ -86,7 +86,7 @@ namespace Cryville.Crtr {
protected override bool Collapse(int name, PdtVariableMemory param) { protected override bool Collapse(int name, PdtVariableMemory param) {
if (name == _colop_and) return param.Type == PdtInternalType.Number && param.AsNumber() <= 0; if (name == _colop_and) return param.Type == PdtInternalType.Number && param.AsNumber() <= 0;
else if (name == _colop_or) return param.Type != PdtInternalType.Number || 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}", IdentifierManager.SharedInstance.Retrieve(name)));
} }
public ChartEvent ContextEvent { private get; set; } public ChartEvent ContextEvent { private get; set; }

View File

@@ -72,19 +72,21 @@ namespace Cryville.Crtr {
public class Enum<T> : PropOp { public class Enum<T> : PropOp {
readonly static Dictionary<int, int> _cache = new Dictionary<int, int>(); readonly static Dictionary<int, int> _cache = new Dictionary<int, int>();
readonly Action<T> _cb; readonly Action<T> _cb;
public Enum(Action<T> cb) { readonly Func<int, T> _caster;
public Enum(Action<T> cb, Func<int, T> caster) {
if (!typeof(T).IsEnum) if (!typeof(T).IsEnum)
throw new ArgumentException("Type is not enum"); throw new ArgumentException("Type is not enum");
var names = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static); var names = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static);
for (int i = 0; i < names.Length; i++) for (int i = 0; i < names.Length; i++)
_cache[IdentifierManager.SharedInstance.Request(names[i].Name)] = Convert.ToInt32(names[i].GetValue(null)); _cache[IdentifierManager.SharedInstance.Request(names[i].Name)] = Convert.ToInt32(names[i].GetValue(null));
_cb = cb; _cb = cb;
_caster = caster;
} }
protected override void Execute() { protected override void Execute() {
int result = 0; int result = 0;
for (int i = 0; i < LoadedOperandCount; i++) for (int i = 0; i < LoadedOperandCount; i++)
result |= _cache[GetOperand(0).AsIdentifier()]; result |= _cache[GetOperand(0).AsIdentifier()];
_cb((T)(object)result); _cb(_caster(result));
} }
} }
public class BeatTime : PropOp { public class BeatTime : PropOp {

View File

@@ -5,14 +5,15 @@ using RBeatTime = Cryville.Crtr.BeatTime;
namespace Cryville.Crtr { namespace Cryville.Crtr {
public abstract class PropSrc { public abstract class PropSrc {
int _type; int _type;
byte[] _buf = null; protected byte[] buf = null;
public virtual void Invalidate() { _buf = null; } protected virtual bool Invalidated { get { return buf == null; } }
public virtual void Invalidate() { buf = null; }
public void Get(out int type, out byte[] value) { public void Get(out int type, out byte[] value) {
if (_buf == null) InternalGet(out _type, out _buf); if (Invalidated) _type = InternalGet();
type = _type; type = _type;
value = _buf; value = buf;
} }
protected abstract void InternalGet(out int type, out byte[] value); protected abstract int InternalGet();
public class Arbitrary : PropSrc { public class Arbitrary : PropSrc {
public int Type { get; private set; } public int Type { get; private set; }
readonly byte[] _value; readonly byte[] _value;
@@ -20,65 +21,75 @@ namespace Cryville.Crtr {
Type = type; Type = type;
_value = value; _value = value;
} }
protected override void InternalGet(out int type, out byte[] value) { protected override int InternalGet() {
type = Type; buf = _value;
value = _value; return Type;
} }
} }
public class Boolean : PropSrc { public class Boolean : PropSrc {
readonly Func<bool> _cb; readonly Func<bool> _cb;
public Boolean(Func<bool> cb) { _cb = cb; } bool m_invalidated = true;
protected override void InternalGet(out int type, out byte[] value) { protected override bool Invalidated { get { return m_invalidated; } }
type = PdtInternalType.Number; public override void Invalidate() { m_invalidated = true; }
value = new byte[] { _cb() ? (byte)1 : (byte)0, 0, 0, 0 }; public Boolean(Func<bool> cb) { _cb = cb; buf = new byte[4]; }
protected override int InternalGet() {
m_invalidated = false;
buf[0] = _cb() ? (byte)1 : (byte)0;
return PdtInternalType.Number;
} }
} }
public class Float : PropSrc { public class Float : PropSrc {
readonly Func<float> _cb; readonly Func<float> _cb;
public Float(Func<float> cb) { _cb = cb; } bool m_invalidated = true;
protected override void InternalGet(out int type, out byte[] value) { protected override bool Invalidated { get { return m_invalidated; } }
type = PdtInternalType.Number; public override void Invalidate() { m_invalidated = true; }
value = BitConverter.GetBytes(_cb()); public Float(Func<float> cb) { _cb = cb; buf = new byte[4]; }
protected override unsafe int InternalGet() {
m_invalidated = false;
fixed (byte* _ptr = buf) {
*(float*)_ptr = _cb();
}
return PdtInternalType.Number;
} }
} }
public class String : PropSrc { public class String : PropSrc {
readonly Func<string> _cb; readonly Func<string> _cb;
public String(Func<string> cb) { _cb = cb; } public String(Func<string> cb) { _cb = cb; }
protected override unsafe void InternalGet(out int type, out byte[] value) { protected override unsafe int InternalGet() {
type = PdtInternalType.String;
var v = _cb(); var v = _cb();
int strlen = v.Length; int strlen = v.Length;
value = new byte[strlen * sizeof(char) + sizeof(int)]; buf = new byte[strlen * sizeof(char) + sizeof(int)];
fixed (byte* _ptr = value) { fixed (byte* _ptr = buf) {
char* ptr = (char*)(_ptr + sizeof(int)); char* ptr = (char*)(_ptr + sizeof(int));
*(int*)_ptr = strlen; *(int*)_ptr = strlen;
int i = 0; int i = 0;
foreach (var c in v) ptr[i++] = c; foreach (var c in v) ptr[i++] = c;
} }
return PdtInternalType.String;
} }
} }
public class Identifier : PropSrc { public class Identifier : PropSrc {
readonly Func<int> _cb; readonly Func<int> _cb;
public Identifier(Func<int> cb) { _cb = cb; } public Identifier(Func<int> cb) { _cb = cb; }
protected override void InternalGet(out int type, out byte[] value) { protected override int InternalGet() {
type = PdtInternalType.Undefined; buf = BitConverter.GetBytes(_cb());
value = BitConverter.GetBytes(_cb()); return PdtInternalType.Undefined;
} }
} }
public class BeatTime : PropSrc { public class BeatTime : PropSrc {
readonly Func<RBeatTime> _cb; readonly Func<RBeatTime> _cb;
public BeatTime(Func<RBeatTime> cb) { _cb = cb; } public BeatTime(Func<RBeatTime> cb) { _cb = cb; }
protected override unsafe void InternalGet(out int type, out byte[] value) { protected override unsafe int InternalGet() {
var bt = _cb(); var bt = _cb();
type = PdtInternalType.Vector; buf = new byte[4 * sizeof(int)];
value = new byte[4 * sizeof(int)]; fixed (byte* _ptr = buf) {
fixed (byte* _ptr = value) {
int* ptr = (int*)_ptr; int* ptr = (int*)_ptr;
*ptr++ = bt.b; *ptr++ = bt.b;
*ptr++ = bt.n; *ptr++ = bt.n;
*ptr++ = bt.d; *ptr++ = bt.d;
*ptr++ = PdtInternalType.Number; *ptr++ = PdtInternalType.Number;
} }
return PdtInternalType.Vector;
} }
} }
} }

View File

@@ -34,6 +34,17 @@ namespace Cryville.Crtr {
} }
} }
[Category("gameplay")]
[Range(-1, 5)]
public int ForceSyncFrames {
get {
return PlayerPrefs.GetInt("ForceSyncFrames", 5);
}
set {
PlayerPrefs.SetInt("ForceSyncFrames", value);
}
}
[Browsable(false)] [Browsable(false)]
[Category("data")] [Category("data")]
[Description("The directory where the game files are stored.")] [Description("The directory where the game files are stored.")]

View File

@@ -1,3 +1,4 @@
using Cryville.Common;
using Cryville.Common.Pdt; using Cryville.Common.Pdt;
using Cryville.Crtr.Components; using Cryville.Crtr.Components;
using Cryville.Crtr.Event; using Cryville.Crtr.Event;
@@ -100,10 +101,16 @@ namespace Cryville.Crtr {
SkinProperty GetPropOp(Transform obj, SkinPropertyKey key) { SkinProperty GetPropOp(Transform obj, SkinPropertyKey key) {
var ctype = key.Component; var ctype = key.Component;
var comp = (SkinComponent)obj.GetComponent(ctype); var comp = (SkinComponent)obj.GetComponent(ctype);
if (comp == null) throw new InvalidOperationException("Component instance not found"); if (comp == null) throw new InvalidOperationException(string.Format(
"Trying to set property {0} but the component is not found",
IdentifierManager.SharedInstance.Retrieve(key.Name)
));
SkinProperty result; SkinProperty result;
if (!comp.Properties.TryGetValue(key.Name, out result)) if (!comp.Properties.TryGetValue(key.Name, out result))
throw new ArgumentException(string.Format("Property {0} not found on component", key.Name)); throw new ArgumentException(string.Format(
"Property {0} not found on component",
IdentifierManager.SharedInstance.Retrieve(key.Name)
));
return result; return result;
} }
} }

View File

@@ -3,32 +3,18 @@ using UnityEngine;
namespace Cryville.Crtr { namespace Cryville.Crtr {
public class SpriteFrame { public class SpriteFrame {
#pragma warning disable IDE1006 Rect m_frame;
Rect _frame; public Rect Frame {
public Rect frame { get { return m_frame; }
get { return _frame; } set { m_frame = value; }
set { _frame = value; }
}
public Rect textureRect {
get { return _frame; }
set { _frame = value; }
} }
bool _rotated = false; bool m_rotated = false;
public bool rotated { public bool Rotated {
get { return _rotated; } get { return m_rotated; }
set { _rotated = value; } set { m_rotated = value; }
} }
public bool textureRotated {
get { return _rotated; }
set { _rotated = value; }
}
#pragma warning restore IDE1006
public Vector2 offset;
public Rect sourceColorRect;
public Vector2 sourceSize;
private Rect _uv; private Rect _uv;
private Vector2[] cuv; private Vector2[] cuv;
public Rect UV { public Rect UV {
@@ -41,7 +27,7 @@ namespace Cryville.Crtr {
float x1 = Mathf.Max(_uv.xMin, _uv.xMax); float x1 = Mathf.Max(_uv.xMin, _uv.xMax);
float y0 = Mathf.Min(_uv.yMin, _uv.yMax); float y0 = Mathf.Min(_uv.yMin, _uv.yMax);
float y1 = Mathf.Max(_uv.yMin, _uv.yMax); float y1 = Mathf.Max(_uv.yMin, _uv.yMax);
if (_rotated) cuv = new Vector2[]{ if (m_rotated) cuv = new Vector2[]{
new Vector2(x0, y1), new Vector2(x0, y1),
new Vector2(x1, y0), new Vector2(x1, y0),
new Vector2(x0, y0), new Vector2(x0, y0),
@@ -79,28 +65,17 @@ namespace Cryville.Crtr {
public void Init() { public void Init() {
if (Texture == null) if (Texture == null)
throw new InvalidOperationException("Missing texture"); throw new InvalidOperationException("Missing texture");
_frame = new Rect(Vector2.zero, Size); m_frame = new Rect(Vector2.zero, Size);
var w = _frame.width; var w = m_frame.width;
var h = _frame.height; var h = m_frame.height;
float x = _frame.x / w; float x = m_frame.x / w;
float y = 1 - _frame.y / h; float y = 1 - m_frame.y / h;
float tw = (_rotated ? _frame.height : _frame.width) / w; float tw = (m_rotated ? m_frame.height : m_frame.width) / w;
float th = (_rotated ? _frame.width : _frame.height) / h; float th = (m_rotated ? m_frame.width : m_frame.height) / h;
if (_rotated) UV = new Rect(x, y, tw, -th); if (m_rotated) UV = new Rect(x, y, tw, -th);
else UV = new Rect(x, y, tw, -th); else UV = new Rect(x, y, tw, -th);
} }
public void Init(int w, int h, Texture2D _base) {
if (Texture != null)
throw new InvalidOperationException("Missing texture");
Texture = _base;
float x = _frame.x / w;
float y = 1 - _frame.y / h;
float tw = (_rotated ? _frame.height : _frame.width) / w;
float th = (_rotated ? _frame.width : _frame.height) / h;
if (_rotated) UV = new Rect(x, y, tw, -th);
else UV = new Rect(x, y, tw, -th);
}
public SpriteFrame() { } public SpriteFrame() { }
public SpriteFrame(Texture2D tex) { public SpriteFrame(Texture2D tex) {
Texture = tex; Texture = tex;

View File

@@ -27,27 +27,14 @@ namespace Cryville.Crtr {
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
public class PlaySound : StampedEvent { public class Anchor : StampedEvent {
public new Chart.Sound Unstamped; public int Name;
public override int Priority { public override int Priority {
get { return 0; } get { return 0; }
} }
} }
public class Judge : StampedEvent {
public float NoteTime;
public JudgeDefinition TargetJudge;
public Judge StartEvent;
public bool IsEndJudge;
public override int Priority {
get { return StartEvent == null ? 4 : 6; }
}
protected override int CompareExtra(StampedEvent other) {
return Equals(StartEvent, other) ? 1 : 0;
}
}
public StampedEvent AttackEvent { public StampedEvent AttackEvent {
get { get {
if (attev == null) attev = Subevents.FirstOrDefault(ev => ev.Time == this.Time); if (attev == null) attev = Subevents.FirstOrDefault(ev => ev.Time == this.Time);

View File

@@ -31,41 +31,41 @@ namespace Cryville.Crtr {
breakflag = true; breakflag = true;
} }
public void Forward(Action<T> callback = null) { public void Forward() {
ForwardToTime(double.PositiveInfinity, callback); ForwardToTime(double.PositiveInfinity);
} }
public void ForwardByTime(double time, Action<T> callback = null) { public void ForwardByTime(double time) {
ForwardToTime(Time + time, callback); ForwardToTime(Time + time);
} }
public void ForwardOnceByTime(double time, Action<T> callback = null) { public void ForwardOnceByTime(double time) {
ForwardOnceToTime(Time + time, callback); ForwardOnceToTime(Time + time);
} }
public void ForwardToTime(double toTime, Action<T> callback = null) { public void ForwardToTime(double toTime) {
breakflag = false; breakflag = false;
ForwardOnceToTime(Time, callback); ForwardOnceToTime(Time);
while (Time < toTime) { while (Time < toTime) {
ForwardOnceToTime(toTime, callback); ForwardOnceToTime(toTime);
if (breakflag) break; if (breakflag) break;
} }
} }
public void ForwardStepByTime(double time, double step, Action<T> callback = null) { public void ForwardStepByTime(double time, double step) {
ForwardStepToTime(Time + time, step, callback); ForwardStepToTime(Time + time, step);
} }
public void ForwardStepToTime(double toTime, double step, Action<T> callback = null) { public void ForwardStepToTime(double toTime, double step) {
breakflag = false; breakflag = false;
ForwardOnceToTime(Time, callback); ForwardOnceToTime(Time);
while (Time < toTime) { while (Time < toTime) {
double next = Time + step; double next = Time + step;
ForwardOnceToTime(next < toTime ? next : toTime, callback); ForwardOnceToTime(next < toTime ? next : toTime);
if (breakflag) break; if (breakflag) break;
} }
} }
public abstract void ForwardOnceToTime(double toTime, Action<T> callback = null); public abstract void ForwardOnceToTime(double toTime);
} }
} }

View File

@@ -39,6 +39,7 @@ namespace Cryville.Crtr {
#endif #endif
} }
else if (s.CloneType == 3) { else if (s.CloneType == 3) {
spos = Vector3.zero;
bpos = cpt; bpos = cpt;
brot = Quaternion.Euler(s.Direction); brot = Quaternion.Euler(s.Direction);
} }
@@ -61,18 +62,7 @@ namespace Cryville.Crtr {
public override void Update(ContainerState s, StampedEvent ev) { public override void Update(ContainerState s, StampedEvent ev) {
base.Update(s, ev); base.Update(s, ev);
if (s.CloneType == 0) { if (s.CloneType == 2 || s.CloneType == 3) {
pwp = Vector3.zero;
cpt = s.ScreenPoint;
spos = Vector3.zero;
#if UNITY_5_6_OR_NEWER
a_cur.SetPositionAndRotation(s.ScreenPoint, Quaternion.Euler(s.Direction));
#else
a_cur.position = s.ScreenPoint;
a_cur.rotation = Quaternion.Euler(s.Direction);
#endif
}
else if (s.CloneType == 2 || s.CloneType == 3) {
var tpt = s.ScreenPoint; var tpt = s.ScreenPoint;
var tsv = s.ScrollVelocity; var tsv = s.ScrollVelocity;

View File

@@ -2,7 +2,8 @@
"name": "Cryville.Crtr", "name": "Cryville.Crtr",
"rootNamespace": "", "rootNamespace": "",
"references": [ "references": [
"GUID:d8ea0e0da3ad53a45b65c912ffcacab0" "GUID:d8ea0e0da3ad53a45b65c912ffcacab0",
"GUID:5686e5ee69d0e084c843d61c240d7fdb"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],

Binary file not shown.

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 431a8644546221a40a73de6618f11332
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
using System;
namespace Discord
{
public partial class ActivityManager
{
public void RegisterCommand()
{
RegisterCommand(null);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4bce5beb292181a43b6427b71e8a7e93
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
using System;
namespace Discord
{
static class Constants
{
public const string DllName = "discord_game_sdk";
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 62db490eb0dffd64785623624a77cfd4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 492875a0b937d86409c5dddd1d597026
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
{
"name": "DiscordGameSDK"
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5686e5ee69d0e084c843d61c240d7fdb
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,53 @@
using System;
using System.Runtime.InteropServices;
#if UNITY_EDITOR || UNITY_STANDALONE
using UnityEngine;
#endif
namespace Discord
{
public partial struct ImageHandle
{
static public ImageHandle User(Int64 id)
{
return User(id, 128);
}
static public ImageHandle User(Int64 id, UInt32 size)
{
return new ImageHandle
{
Type = ImageType.User,
Id = id,
Size = size,
};
}
}
public partial class ImageManager
{
public void Fetch(ImageHandle handle, FetchHandler callback)
{
Fetch(handle, false, callback);
}
public byte[] GetData(ImageHandle handle)
{
var dimensions = GetDimensions(handle);
var data = new byte[dimensions.Width * dimensions.Height * 4];
GetData(handle, data);
return data;
}
#if UNITY_EDITOR || UNITY_STANDALONE
public Texture2D GetTexture(ImageHandle handle)
{
var dimensions = GetDimensions(handle);
var texture = new Texture2D((int)dimensions.Width, (int)dimensions.Height, TextureFormat.RGBA32, false, true);
texture.LoadRawTextureData(GetData(handle));
texture.Apply();
return texture;
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a3cfde4503bedc444807a916e1ad2960
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Text;
namespace Discord
{
public partial class LobbyManager
{
public IEnumerable<User> GetMemberUsers(Int64 lobbyID)
{
var memberCount = MemberCount(lobbyID);
var members = new List<User>();
for (var i = 0; i < memberCount; i++)
{
members.Add(GetMemberUser(lobbyID, GetMemberUserId(lobbyID, i)));
}
return members;
}
public void SendLobbyMessage(Int64 lobbyID, string data, SendLobbyMessageHandler handler)
{
SendLobbyMessage(lobbyID, Encoding.UTF8.GetBytes(data), handler);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d49d4d1d5cee72b40a22bf6f6bdd0309
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Discord
{
public partial class StorageManager
{
public IEnumerable<FileStat> Files()
{
var fileCount = Count();
var files = new List<FileStat>();
for (var i = 0; i < fileCount; i++)
{
files.Add(StatAt(i));
}
return files;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 75e55be5cce5be14ca292ed00ff90a43
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Text;
namespace Discord
{
public partial class StoreManager
{
public IEnumerable<Entitlement> GetEntitlements()
{
var count = CountEntitlements();
var entitlements = new List<Entitlement>();
for (var i = 0; i < count; i++)
{
entitlements.Add(GetEntitlementAt(i));
}
return entitlements;
}
public IEnumerable<Sku> GetSkus()
{
var count = CountSkus();
var skus = new List<Sku>();
for (var i = 0; i < count; i++)
{
skus.Add(GetSkuAt(i));
}
return skus;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f28abb9e0c9477541bba93c5c21a7111
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 460f7228edb725a48a1fb6b5f4617ee9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 751d95431111781498a1a512ad9edd8c
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,70 @@
fileFormatVersion: 2
guid: 8bbe28aa384b7cf47bae3469ee3357a2
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 1
Exclude Linux64: 0
Exclude OSXUniversal: 0
Exclude Win: 0
Exclude Win64: 0
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 1
settings:
CPU: x86
- first:
Standalone: Win64
second:
enabled: 1
settings:
CPU: None
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 45f45105fdfb4d348baf39f50ea65c68
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e0215748675da6b43a2f70236d99e492
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,70 @@
fileFormatVersion: 2
guid: 212370df4e6cbbb4eb87395114fb6885
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 0
Exclude Linux64: 0
Exclude OSXUniversal: 0
Exclude Win: 1
Exclude Win64: 0
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 1
settings:
CPU: x86_64
userData:
assetBundleName:
assetBundleVariant: