Implement InputProxy.

This commit is contained in:
2022-11-07 12:21:50 +08:00
parent 0d7018c964
commit f311eb5e8d
6 changed files with 109 additions and 36 deletions

View File

@@ -4,19 +4,13 @@ using Cryville.Common.Unity.Input;
using System;
using System.Collections.Generic;
using UnityEngine;
using Logger = Cryville.Common.Logger;
namespace Cryville.Crtr {
public class InputProxy {
readonly PdtEvaluator _etor;
readonly PdtRuleset _ruleset;
readonly Dictionary<string, InputProxyEntry> _tproxies = new Dictionary<string, InputProxyEntry>();
readonly Dictionary<InputSource, InputProxyEntry> _sproxies = new Dictionary<InputSource, InputProxyEntry>();
readonly Dictionary<string, int> _use = new Dictionary<string, int>();
readonly Dictionary<string, List<string>> _rev = new Dictionary<string, List<string>>();
readonly Dictionary<InputIdentifier, InputVector> _vecs = new Dictionary<InputIdentifier, InputVector>();
public event EventHandler<ProxyChangedEventArgs> ProxyChanged;
public InputProxy(PdtRuleset ruleset) {
readonly Judge _judge;
public InputProxy(PdtRuleset ruleset, Judge judge) {
unsafe {
fixed (byte* ptr = _vecbuf) {
*(int*)(ptr + 3 * sizeof(float)) = PdtInternalType.Number;
@@ -24,6 +18,7 @@ namespace Cryville.Crtr {
}
_etor = ChartPlayer.etor;
_ruleset = ruleset;
_judge = judge;
foreach (var i in ruleset.inputs) {
_use.Add(i.Key, 0);
_rev.Add(i.Key, new List<string>());
@@ -36,6 +31,11 @@ namespace Cryville.Crtr {
}
}
#region Settings
readonly Dictionary<string, InputProxyEntry> _tproxies = new Dictionary<string, InputProxyEntry>();
readonly Dictionary<InputSource, InputProxyEntry> _sproxies = new Dictionary<InputSource, InputProxyEntry>();
readonly Dictionary<string, int> _use = new Dictionary<string, int>();
readonly Dictionary<string, List<string>> _rev = new Dictionary<string, List<string>>();
public event EventHandler<ProxyChangedEventArgs> ProxyChanged;
public void Set(InputProxyEntry proxy) {
var name = proxy.Target;
if (_tproxies.ContainsKey(name)) Remove(proxy);
@@ -103,32 +103,49 @@ namespace Cryville.Crtr {
#region Handling
public void Activate() { foreach (var src in _sproxies.Keys) src.Handler.Activate(); }
public void Deactivate() { foreach (var src in _sproxies.Keys) src.Handler.Deactivate(); }
readonly object _lock = new object();
void OnInput(InputIdentifier id, InputVector vec) {
static readonly int _var_value = IdentifierManager.SharedInstance.Request("value");
static readonly int _var_ft = IdentifierManager.SharedInstance.Request("ft");
static readonly int _var_tt = IdentifierManager.SharedInstance.Request("tt");
static readonly PropOp.Arbitrary _arbop = new PropOp.Arbitrary();
readonly byte[] _numbuf = new byte[sizeof(float)];
readonly byte[] _numbuf2 = new byte[sizeof(float)];
readonly byte[] _vecbuf = new byte[3 * sizeof(float) + sizeof(int)];
readonly Dictionary<InputIdentifier, float> _vect = new Dictionary<InputIdentifier, float>();
readonly Dictionary<ProxiedInputIdentifier, PropSrc.Arbitrary> _vecs = new Dictionary<ProxiedInputIdentifier, PropSrc.Arbitrary>();
unsafe void LoadNum(float value) {
fixed (byte* ptr = _numbuf) *(float*)ptr = value;
}
unsafe void LoadNum2(float value) {
fixed (byte* ptr = _numbuf2) *(float*)ptr = value;
}
unsafe void OnInput(InputIdentifier id, InputVector vec) {
lock (_lock) {
InputProxyEntry proxy;
if (_sproxies.TryGetValue(id.Source, out proxy)) {
OnInput(id, vec, proxy.Target);
_etor.ContextCascadeInsert();
float ft, tt = (float)vec.Time;
if (!_vect.TryGetValue(id, out ft)) ft = tt;
LoadNum(ft); _etor.ContextCascadeUpdate(_var_ft, new PropSrc.Arbitrary(PdtInternalType.Number, _numbuf));
LoadNum2(tt); _etor.ContextCascadeUpdate(_var_tt, new PropSrc.Arbitrary(PdtInternalType.Number, _numbuf2));
_vect[id] = tt;
if (vec.IsNull) {
_etor.ContextCascadeUpdate(_var_value, new PropSrc.Arbitrary(PdtInternalType.Null, new byte[0]));
}
else {
fixed (byte* ptr = _vecbuf) {
*(Vector3*)ptr = vec.Vector;
}
_etor.ContextCascadeUpdate(_var_value, new PropSrc.Arbitrary(PdtInternalType.Vector, _vecbuf));
}
OnInput(id, proxy.Target);
_etor.ContextCascadeDiscard();
}
}
}
static readonly int _var_value = IdentifierManager.SharedInstance.Request("value");
static readonly PropOp.Arbitrary _arbop = new PropOp.Arbitrary();
readonly byte[] _vecbuf = new byte[3 * sizeof(float) + sizeof(int)];
unsafe void OnInput(InputIdentifier id, InputVector vec, string target) {
_etor.ContextCascadeInsert();
if (vec.IsNull) {
_etor.ContextCascadeUpdate(_var_value, new PropSrc.Arbitrary(PdtInternalType.Null, new byte[0]));
}
else {
fixed (byte* ptr = _vecbuf) {
*(Vector3*)ptr = vec.Vector;
}
_etor.ContextCascadeUpdate(_var_value, new PropSrc.Arbitrary(PdtInternalType.Vector, _vecbuf));
}
OnInput(id, target);
_etor.ContextCascadeDiscard();
}
static readonly int _var_fv = IdentifierManager.SharedInstance.Request("fv");
static readonly int _var_tv = IdentifierManager.SharedInstance.Request("tv");
unsafe void OnInput(InputIdentifier id, string target) {
var def = _ruleset.inputs[target];
if (def.pass != null) {
@@ -141,7 +158,17 @@ namespace Cryville.Crtr {
}
}
else {
Logger.Log("main", 0, "Input/Proxy", "input recv {0}", target);
var pid = new ProxiedInputIdentifier { Source = id, Target = target };
PropSrc.Arbitrary fv, tv = _etor.ContextCascadeLookup(_var_value);
if (!_vecs.TryGetValue(pid, out fv)) fv = new PropSrc.Arbitrary(PdtInternalType.Null, new byte[0]);
if (fv.Type != PdtInternalType.Null || tv.Type != PdtInternalType.Null) {
_etor.ContextCascadeInsert();
_etor.ContextCascadeUpdate(_var_tv, tv);
_etor.ContextCascadeUpdate(_var_fv, fv);
_judge.Feed(target);
_etor.ContextCascadeDiscard();
}
_vecs[pid] = tv;
}
}
#endregion
@@ -163,4 +190,28 @@ namespace Cryville.Crtr {
public string Target { get; set; }
public byte[] Mapping { get; private set; }
}
public struct ProxiedInputIdentifier : IEquatable<ProxiedInputIdentifier> {
public InputIdentifier Source { get; set; }
public string Target { get; set; }
public override bool Equals(object obj) {
if (obj == null || !(obj is ProxiedInputIdentifier)) return false;
return Equals((ProxiedInputIdentifier)obj);
}
public bool Equals(ProxiedInputIdentifier other) {
return Source == other.Source && Target == other.Target;
}
public override int GetHashCode() {
return Source.GetHashCode() ^ Target.GetHashCode();
}
public override string ToString() {
return string.Format("{0}->{1}", Source, Target);
}
public static bool operator ==(ProxiedInputIdentifier lhs, ProxiedInputIdentifier rhs) {
return lhs.Equals(rhs);
}
public static bool operator !=(ProxiedInputIdentifier lhs, ProxiedInputIdentifier rhs) {
return !lhs.Equals(rhs);
}
}
}