Tokenize ruleset keys. Remove MotionName.

This commit is contained in:
2022-11-09 14:01:27 +08:00
parent 55efc7a428
commit c33186086c
13 changed files with 153 additions and 112 deletions

View File

@@ -0,0 +1,34 @@
using System;
namespace Cryville.Common {
public struct Identifier : IEquatable<Identifier> {
public int Key { get; private set; }
public object Name { get { return IdentifierManager.SharedInstance.Retrieve(Key); } }
public Identifier(int key) {
Key = key;
}
public Identifier(object name) {
Key = IdentifierManager.SharedInstance.Request(name);
}
public override bool Equals(object obj) {
if (obj == null && Key == 0) return true;
if (obj == null || !(obj is Identifier)) return false;
return Equals((Identifier)obj);
}
public bool Equals(Identifier other) {
return Key == other.Key;
}
public override int GetHashCode() {
return Key;
}
public override string ToString() {
return Name.ToString();
}
public static implicit operator Identifier(string identifier) {
return new Identifier(identifier);
}
public static implicit operator string(Identifier identifier) {
return identifier.ToString();
}
}
}

View File

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

View File

@@ -15,6 +15,13 @@ namespace Cryville.Common {
object _syncRoot = new object();
/// <summary>
/// Creates an instance of the <see cref="IdentifierManager" /> class.
/// </summary>
public IdentifierManager() {
Request(this);
}
/// <summary>
/// Requests an integer ID for an identifier.
/// </summary>

View File

@@ -276,8 +276,8 @@ namespace Cryville.Crtr {
private void LoadFromString(string s) {
Match m = Regex.Match(s, @"^(.+?)(#(\d+))?(@(.+?))?(\^(.+?))?(\*(.+?))?(:(.+))?$");
if (!m.Success) throw new ArgumentException(); // TODO
name = new MotionName(m.Groups[1].Value);
var registry = ChartPlayer.motionRegistry[name.MainName];
name = new Identifier(m.Groups[1].Value);
var registry = ChartPlayer.motionRegistry[name];
if (m.Groups[3].Success) {
ushort id = ushort.Parse(m.Groups[3].Value);
Vec1 time = m.Groups[5].Success ? new Vec1(m.Groups[5].Value) : null;
@@ -313,15 +313,15 @@ namespace Cryville.Crtr {
return result;
}
private MotionName name;
private Identifier name;
[JsonIgnore]
public MotionName Name {
public Identifier Name {
get {
return name;
}
private set {
MotionRegistry reg;
if (!ChartPlayer.motionRegistry.TryGetValue(value.MainName, out reg))
if (!ChartPlayer.motionRegistry.TryGetValue(value, out reg))
throw new ArgumentException("Invalid motion name");
if (RelativeNode != null) RelativeNode.Value = reg.InitValue;
else AbsoluteValue = reg.InitValue;
@@ -351,16 +351,16 @@ namespace Cryville.Crtr {
else return AbsoluteValue;
}));
SubmitPropOp("motion", new PropOp.String(v => motion = v));
SubmitPropOp("name", new PropOp.String(v => {
var n = new MotionName(v);
SubmitPropOp("name", new PropOp.Identifier(v => {
var n = new Identifier(v);
if (Name.Equals(n)) { }
else if (Name.Equals(default(MotionName))) Name = n;
else if (Name.Equals(default(Identifier))) Name = n;
else throw new RulesetViolationException(string.Format(
"Motion name not matched, expected {0}, got {1}", n, Name
));
}));
SubmitPropOp("value", new VectorOp(v => {
var vec = Vector.Construct(ChartPlayer.motionRegistry[Name.MainName].Type, v);
var vec = Vector.Construct(ChartPlayer.motionRegistry[Name].Type, v);
if (RelativeNode != null) RelativeNode.Value = vec;
else AbsoluteValue = vec;
}));
@@ -379,7 +379,7 @@ namespace Cryville.Crtr {
public Note() {
SubmitPropSrc("track", new PropSrc.Float(() => {
var i = motions.FirstOrDefault(m => m.RelativeNode == null && m.Name.MainName == "track");
var i = motions.FirstOrDefault(m => m.RelativeNode == null && m.Name == "track");
if (i == null) return ((Vec1)ChartPlayer.motionRegistry["track"].InitValue).Value;
else return ((Vec1)i.AbsoluteValue).Value;
}));

View File

@@ -63,7 +63,7 @@ namespace Cryville.Crtr {
static float startOffset = 0;
public static float sv = 16f;
public static Dictionary<string, MotionRegistry> motionRegistry = new Dictionary<string, MotionRegistry>();
public static Dictionary<Identifier, MotionRegistry> motionRegistry = new Dictionary<Identifier, MotionRegistry>();
public static PdtEvaluator etor;

View File

@@ -66,9 +66,9 @@ namespace Cryville.Crtr.Event {
readonly RMVPool RMVPool = new RMVPool();
protected Dictionary<StampedEvent, RealtimeMotionValue> PlayingMotions = new Dictionary<StampedEvent, RealtimeMotionValue>();
protected Dictionary<MotionName, RealtimeMotionValue> Values = new Dictionary<MotionName, RealtimeMotionValue>();
protected Dictionary<MotionName, Vector> CachedValues = new Dictionary<MotionName, Vector>();
protected Dictionary<MotionName, bool> CachedValueStates = new Dictionary<MotionName, bool>();
protected Dictionary<Identifier, RealtimeMotionValue> Values;
protected Dictionary<Identifier, Vector> CachedValues;
protected Dictionary<Identifier, bool> CachedValueStates;
/// <summary>
/// Gets a motion value.
@@ -76,12 +76,12 @@ namespace Cryville.Crtr.Event {
/// <param name="name">The motion name.</param>
/// <param name="clone">Returns a cloned motion value instead.</param>
/// <returns>A motion value.</returns>
RealtimeMotionValue GetMotionValue(MotionName name, bool clone = false) {
RealtimeMotionValue GetMotionValue(Identifier name, bool clone = false) {
RealtimeMotionValue value;
if (!Values.TryGetValue(name, out value)) {
value = new RealtimeMotionValue().Init(Parent == null
? ChartPlayer.motionRegistry[name.MainName].GlobalInitValue
: ChartPlayer.motionRegistry[name.MainName].InitValue
? ChartPlayer.motionRegistry[name].GlobalInitValue
: ChartPlayer.motionRegistry[name].InitValue
);
Values.Add(name, value);
}
@@ -89,7 +89,7 @@ namespace Cryville.Crtr.Event {
return value;
}
void InvalidateMotion(MotionName name) {
void InvalidateMotion(Identifier name) {
CachedValueStates[name] = false;
foreach (var c in Children)
c.Value.InvalidateMotion(name);
@@ -103,8 +103,11 @@ namespace Cryville.Crtr.Event {
Parent = parent;
}
Values = new Dictionary<Identifier, RealtimeMotionValue>(ChartPlayer.motionRegistry.Count);
CachedValues = new Dictionary<Identifier, Vector>(ChartPlayer.motionRegistry.Count);
CachedValueStates = new Dictionary<Identifier, bool>(ChartPlayer.motionRegistry.Count);
foreach (var m in ChartPlayer.motionRegistry)
Values.Add(new MotionName(m.Key), new RealtimeMotionValue().Init(Parent == null ? m.Value.GlobalInitValue : m.Value.InitValue));
Values.Add(m.Key, new RealtimeMotionValue().Init(Parent == null ? m.Value.GlobalInitValue : m.Value.InitValue));
}
static void AddChild(EventContainer c, ContainerState s, ContainerState target) {
@@ -117,19 +120,19 @@ namespace Cryville.Crtr.Event {
public ContainerState Clone(byte ct) {
var r = (ContainerState)MemberwiseClone();
var mvs = new Dictionary<MotionName, RealtimeMotionValue>(Values.Count);
var mvs = new Dictionary<Identifier, RealtimeMotionValue>(ChartPlayer.motionRegistry.Count);
foreach (var mv in Values) {
mvs.Add(mv.Key, mv.Value.Clone());
}
r.Values = mvs;
var cvs = new Dictionary<MotionName, Vector>(CachedValues.Count);
var cvs = new Dictionary<Identifier, Vector>(ChartPlayer.motionRegistry.Count);
foreach (var cv in CachedValues) {
cvs.Add(cv.Key, cv.Value.Clone());
}
r.CachedValues = cvs;
var cvss = new Dictionary<MotionName, bool>(CachedValueStates.Count);
var cvss = new Dictionary<Identifier, bool>(ChartPlayer.motionRegistry.Count);
foreach (var cv in CachedValueStates) {
cvss.Add(cv.Key, cv.Value);
}
@@ -211,7 +214,7 @@ namespace Cryville.Crtr.Event {
this.judge = judge;
}
public T GetRawValue<T>(MotionName key) where T : Vector {
public T GetRawValue<T>(Identifier key) where T : Vector {
Vector tr;
if (!CachedValues.TryGetValue(key, out tr)) {
tr = (Vector)ReflectionHelper.InvokeEmptyConstructor(typeof(T));
@@ -232,7 +235,15 @@ namespace Cryville.Crtr.Event {
return r;
}
static readonly MotionName n_dir = new MotionName("dir");
static readonly Identifier n_pt = new Identifier("pt");
public Vector2 ScreenPoint {
get {
var mv = GetRawValue<VecPt>(n_pt);
return mv.ToVector2(ChartPlayer.hitRect);
}
}
static readonly Identifier n_dir = new Identifier("dir");
public Vector3 Direction {
get {
Vec3 r = GetRawValue<Vec3>(n_dir);
@@ -240,7 +251,7 @@ namespace Cryville.Crtr.Event {
}
}
static readonly MotionName n_normal = new MotionName("normal");
static readonly Identifier n_normal = new Identifier("normal");
public Vector3 Normal {
get {
Vec3 r = GetRawValue<Vec3>(n_normal);
@@ -254,16 +265,8 @@ namespace Cryville.Crtr.Event {
}
}
static readonly MotionName n_pt = new MotionName("pt");
public Vector2 ScreenPoint {
get {
var mv = GetRawValue<VecPt>(n_pt);
return mv.ToVector2(ChartPlayer.hitRect);
}
}
static readonly MotionName n_sv = new MotionName("sv");
static readonly MotionName n_svm = new MotionName("svm");
static readonly Identifier n_sv = new Identifier("sv");
static readonly Identifier n_svm = new Identifier("svm");
public float ScrollVelocity {
get {
return GetRawValue<VecPtComp>(n_sv).ToFloat(ChartPlayer.hitRect)
@@ -271,7 +274,7 @@ namespace Cryville.Crtr.Event {
}
}
static readonly MotionName n_dist = new MotionName("dist");
static readonly Identifier n_dist = new Identifier("dist");
public float Distance {
get {
var mv = GetRawValue<VecPtComp>(n_dist);
@@ -279,15 +282,15 @@ namespace Cryville.Crtr.Event {
}
}
static readonly MotionName n_corner = new MotionName("corner");
static readonly Identifier n_corner = new Identifier("corner");
public bool Corner {
get {
return GetRawValue<VecI1>(n_corner).Value % 2 >= 1;
}
}
static readonly MotionName n_ctrl0 = new MotionName("ctrl0");
static readonly MotionName n_ctrl1 = new MotionName("ctrl1");
static readonly Identifier n_ctrl0 = new Identifier("ctrl0");
static readonly Identifier n_ctrl1 = new Identifier("ctrl1");
public Vector3 GetControlPoint(bool alt1, float deltaz) {
var mv = GetRawValue<VecCtrl>(alt1 ? n_ctrl1 : n_ctrl0);
if (alt1 && mv.IsZero()) {
@@ -296,7 +299,7 @@ namespace Cryville.Crtr.Event {
return mv.ToVector3(ChartPlayer.hitRect, deltaz);
}
static readonly MotionName n_track = new MotionName("track");
static readonly Identifier n_track = new Identifier("track");
public float Track {
get {
return GetRawValue<Vec1>(n_track).Value;

View File

@@ -1,4 +1,5 @@
using Cryville.Common.Buffers;
using Cryville.Common;
using Cryville.Common.Buffers;
using System.Collections.Generic;
namespace Cryville.Crtr.Event {
@@ -12,16 +13,16 @@ namespace Cryville.Crtr.Event {
return new RealtimeMotionValue().Init(_reg.InitValue);
}
}
static Dictionary<string, Bucket> _buckets;
static Dictionary<Identifier, Bucket> _buckets;
public static void Prepare() {
_buckets = new Dictionary<string, Bucket>(ChartPlayer.motionRegistry.Count);
_buckets = new Dictionary<Identifier, Bucket>(ChartPlayer.motionRegistry.Count);
foreach (var reg in ChartPlayer.motionRegistry)
_buckets.Add(reg.Key, new Bucket(reg.Key, 4096));
}
readonly Dictionary<RealtimeMotionValue, string> _rented = new Dictionary<RealtimeMotionValue, string>();
public RealtimeMotionValue Rent(MotionName name) {
var n = name.MainName;
public RealtimeMotionValue Rent(Identifier name) {
var n = name;
var obj = _buckets[n].Rent();
_rented.Add(obj, n);
return obj;

View File

@@ -85,7 +85,7 @@ namespace Cryville.Crtr {
AudioSequencer.Playing = true;
AudioClient.Start();
ChartPlayer.motionRegistry = new Dictionary<string, MotionRegistry> {
ChartPlayer.motionRegistry = new Dictionary<Identifier, MotionRegistry> {
{ "pt" , new MotionRegistry(typeof(VecPt)) },
{ "dir" , new MotionRegistry(typeof(Vec3)) },
{ "normal" , new MotionRegistry(typeof(Vec3)) },

View File

@@ -9,7 +9,7 @@ namespace Cryville.Crtr {
public Judge(PdtRuleset rs) {
_rs = rs;
foreach (var s in rs.scores) {
var name = IdentifierManager.SharedInstance.Request(s.Key);
var name = s.Key.Key;
scoreDefs.Add(name, s.Value);
scores.Add(name, s.Value.init);
}
@@ -45,14 +45,15 @@ namespace Cryville.Crtr {
public class InputDefinition {
public int dim;
public bool notnull;
public Dictionary<string, PdtExpression> pass;
public Dictionary<Identifier, PdtExpression> pass;
}
public class JudgeDefinition {
public PdtExpression clip;
public Identifier input;
public PdtExpression hit;
public string[] pass;
public string miss;
public Dictionary<string, PdtExpression> scores;
public Identifier[] pass;
public Identifier miss;
public Dictionary<Identifier, PdtExpression> scores;
}
public class ScoreOperation {
public int name;

View File

@@ -139,41 +139,6 @@ namespace Cryville.Crtr {
}
}
public struct MotionName : IEquatable<MotionName> {
public string MainName { get; private set; }
public string SubName { get; private set; }
public string FullName { get; private set; }
readonly int hash;
public MotionName(string mainName, string subName) {
MainName = mainName;
SubName = subName;
FullName = subName == null ? mainName : string.Format("{0}!{1}", mainName, subName);
hash = FullName.GetHashCode();
}
public MotionName(string fullName) {
var names = fullName.Split('!');
if (names.Length > 2) throw new ArgumentException("Invalid name");
FullName = fullName;
hash = FullName.GetHashCode();
MainName = names[0];
SubName = names.Length == 1 ? "" : names[1];
}
public override bool Equals(object obj) {
if (!(obj is MotionName)) return false;
return Equals((MotionName)obj);
}
public bool Equals(MotionName other) {
return hash == other.hash;
}
public override int GetHashCode() {
return hash;
}
public override string ToString() {
return FullName;
}
}
public struct MotionRegistry {
readonly Type m_Type;
public Type Type {

View File

@@ -91,28 +91,28 @@ namespace Cryville.Crtr {
if (ev == null) { }
else if (ev.Unstamped == null) { }
else if (ev.Unstamped is Chart.Motion) {
var tev = (Chart.Motion)ev.Unstamped;
if (tev.Name.MainName != "judge") return;
phMotions.Add(tev, (Vec1)s.GetRawValue<Vec1>(tev.Name).Clone());
/*var tev = (Chart.Motion)ev.Unstamped;
if (tev.Name != "judge") return;
phMotions.Add(tev, (Vec1)s.GetRawValue<Vec1>(tev.Name).Clone());*/
}
else if (ev.Unstamped is InstantEvent) {
var oev = ((InstantEvent)ev.Unstamped).Original;
/*var oev = ((InstantEvent)ev.Unstamped).Original;
if (oev is Chart.Motion) {
var tev = (Chart.Motion)oev;
if (tev.Name.MainName != "judge") return;
if (tev.Name != "judge") return;
var v0 = phMotions[tev];
var v1 = s.GetRawValue<Vec1>(tev.Name);
// var etor = new Evaluator();
for (var vi = Mathf.Ceil(v0.Value); vi < v1.Value; vi++) {
var v = new Vec1(vi);
var t = MotionLerper.Delerp(v, ev.Time, v1, ev.Origin.Time, v0, tev.transition, tev.rate);
/*CompiledRuleset.PatchJudge(
CompiledRuleset.PatchJudge(
Event, ChartPlayer.cruleset.primary_judges[tev.Name.SubName],
t, etor, patchedJudgeEvents
);*/
);
}
phMotions.Remove(tev);
}
}*/
}
}
}
@@ -137,12 +137,12 @@ namespace Cryville.Crtr {
public override void MotionUpdate(byte ct, Chart.Motion ev) {
base.MotionUpdate(ct, ev);
if (ct == 0) {
if (ev.Name.MainName == "judge") {
/*if (ev.Name == "judge") {
if (invalidated) return;
if (ev.Name.SubName == null)
if (ev.Name == null)
throw new InvalidOperationException();
// judge.IssueImmediate(this, ev.Name.SubName, GetFramePoint(cs.Parent, cs.Track));
}
judge.IssueImmediate(this, ev.Name.SubName, GetFramePoint(cs.Parent, cs.Track));
}*/
}
else if (ct == 16) {
/*var etor = new EvalImpl();

View File

@@ -45,6 +45,13 @@ namespace Cryville.Crtr {
_cb(GetOperand(0).AsString());
}
}
public class Identifier : PropOp {
readonly Action<int> _cb;
public Identifier(Action<int> cb) { _cb = cb; }
protected override void Execute() {
_cb(GetOperand(0).AsIdentifier());
}
}
public class Enum<T> : PropOp {
readonly static Dictionary<int, int> _cache = new Dictionary<int, int>();
readonly Action<T> _cb;

View File

@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using SIdentifier = Cryville.Common.Identifier;
namespace Cryville.Crtr {
public class Ruleset {
@@ -31,9 +32,9 @@ namespace Cryville.Crtr {
[Binder(typeof(PdtRulesetBinder))]
public class PdtRuleset {
public Dictionary<string, InputDefinition> inputs;
public Dictionary<string, JudgeDefinition> judges;
public Dictionary<string, ScoreDefinition> scores;
public Dictionary<Identifier, InputDefinition> inputs;
public Dictionary<Identifier, JudgeDefinition> judges;
public Dictionary<Identifier, ScoreDefinition> scores;
public Constraint constraints;
public void Optimize(PdtEvaluatorBase etor) {
foreach (var i in inputs.Values) {
@@ -142,39 +143,50 @@ namespace Cryville.Crtr {
return result;
}
else if (type.Equals(typeof(string))) {
string result = null;
string result = default(string);
ChartPlayer.etor.Evaluate(new PropOp.String(r => result = r), exp);
return result;
}
else if (type.Equals(typeof(Identifier))) {
Identifier result = default(Identifier);
ChartPlayer.etor.Evaluate(new pop_identstr(r => result = r), exp);
return result;
}
else if (type.Equals(typeof(string[]))) {
string[] result = null;
else if (type.Equals(typeof(Identifier[]))) {
Identifier[] result = null;
ChartPlayer.etor.Evaluate(new pop_identstrarr(r => result = r), exp);
return result;
}
}
else if (value is string) {
var exp = (string)value;
if (type.Equals(typeof(Identifier))) {
return (Identifier)exp;
}
}
return base.ChangeType(value, type, culture);
}
#pragma warning disable IDE1006
class pop_identstr : PropOp {
readonly Action<string> _cb;
public pop_identstr(Action<string> cb) { _cb = cb; }
readonly Action<SIdentifier> _cb;
public pop_identstr(Action<SIdentifier> cb) { _cb = cb; }
protected override void Execute() {
var op = GetOperand(0);
if (op.Type == PdtInternalType.Undefined) _cb((string)IdentifierManager.SharedInstance.Retrieve(op.AsIdentifier()));
else if (op.Type == PdtInternalType.String) _cb(op.AsString());
if (op.Type == PdtInternalType.Undefined) _cb(new SIdentifier(op.AsIdentifier()));
else if (op.Type == PdtInternalType.String) _cb(new SIdentifier(op.AsString()));
else throw new InvalidCastException("Not an identifier or string");
}
}
class pop_identstrarr : PdtOperator {
readonly Action<string[]> _cb;
public pop_identstrarr(Action<string[]> cb) : base(16) { _cb = cb; }
readonly Action<SIdentifier[]> _cb;
public pop_identstrarr(Action<SIdentifier[]> cb) : base(16) { _cb = cb; }
protected override void Execute() {
var result = new string[LoadedOperandCount];
var result = new SIdentifier[LoadedOperandCount];
for (int i = 0; i < LoadedOperandCount; i++) {
var op = GetOperand(i);
if (op.Type != PdtInternalType.Undefined)
throw new InvalidCastException("Not an identifier");
result[i] = (string)IdentifierManager.SharedInstance.Retrieve(op.AsIdentifier());
result[i] = new SIdentifier(op.AsIdentifier());
}
_cb(result);
}