diff --git a/Assets/Cryville/Common/Unity/Input/InputHandler.cs b/Assets/Cryville/Common/Unity/Input/InputHandler.cs index c8702eb..11f2167 100644 --- a/Assets/Cryville/Common/Unity/Input/InputHandler.cs +++ b/Assets/Cryville/Common/Unity/Input/InputHandler.cs @@ -4,7 +4,7 @@ using UnityEngine; namespace Cryville.Common.Unity.Input { public delegate void InputEventDelegate(InputIdentifier id, InputVector vec); public abstract class InputHandler : IDisposable { - public InputEventDelegate Callback { private get; set; } + public event InputEventDelegate OnInput; ~InputHandler() { Dispose(false); @@ -14,15 +14,27 @@ namespace Cryville.Common.Unity.Input { GC.SuppressFinalize(this); } - public abstract void Activate(); - public abstract void Deactivate(); + public bool Activated { get; private set; } + public void Activate() { + if (Activated) return; + Activated = true; + ActivateImpl(); + } + protected abstract void ActivateImpl(); + public void Deactivate() { + if (!Activated) return; + Activated = false; + DeactivateImpl(); + } + protected abstract void DeactivateImpl(); public abstract void Dispose(bool disposing); public abstract bool IsNullable(int type); public abstract byte GetDimension(int type); public abstract string GetTypeName(int type); public abstract double GetCurrentTimestamp(); - protected void OnInput(int type, int id, InputVector vec) { - if (Callback != null) Callback(new InputIdentifier { Source = new InputSource { Handler = this, Type = type }, Id = id }, vec); + protected void Feed(int type, int id, InputVector vec) { + var del = OnInput; + if (del != null) del(new InputIdentifier { Source = new InputSource { Handler = this, Type = type }, Id = id }, vec); } } diff --git a/Assets/Cryville/Common/Unity/Input/InputManager.cs b/Assets/Cryville/Common/Unity/Input/InputManager.cs index 8d73d50..2e6f272 100644 --- a/Assets/Cryville/Common/Unity/Input/InputManager.cs +++ b/Assets/Cryville/Common/Unity/Input/InputManager.cs @@ -17,12 +17,11 @@ namespace Cryville.Common.Unity.Input { readonly Dictionary _vectors = new Dictionary(); readonly List _events = new List(); public InputManager() { - var cb = new InputEventDelegate(Callback); foreach (var t in HandlerRegistries) { try { if (!typeof(InputHandler).IsAssignableFrom(t)) continue; var h = (InputHandler)ReflectionHelper.InvokeEmptyConstructor(t); - h.Callback = Callback; + h.OnInput += OnInput; _handlers.Add(h); _timeOrigins.Add(h, 0); Logger.Log("main", 1, "Input", "Initialized {0}", ReflectionHelper.GetSimpleName(t)); @@ -46,7 +45,7 @@ namespace Cryville.Common.Unity.Input { public void Deactivate() { foreach (var h in _handlers) h.Deactivate(); } - void Callback(InputIdentifier id, InputVector vec) { + void OnInput(InputIdentifier id, InputVector vec) { lock (_lock) { double timeOrigin = _timeOrigins[id.Source.Handler]; vec.Time += timeOrigin; diff --git a/Assets/Cryville/Common/Unity/Input/UnityKeyHandler.cs b/Assets/Cryville/Common/Unity/Input/UnityKeyHandler.cs index a371624..2aa6d90 100644 --- a/Assets/Cryville/Common/Unity/Input/UnityKeyHandler.cs +++ b/Assets/Cryville/Common/Unity/Input/UnityKeyHandler.cs @@ -9,19 +9,19 @@ namespace Cryville.Common.Unity.Input { public UnityKeyHandler() { } - public override void Activate() { + protected override void ActivateImpl() { receiver = new GameObject("__keyrecv__"); recvcomp = receiver.AddComponent(); - recvcomp.SetCallback(OnInput); + recvcomp.SetCallback(Feed); } - public override void Deactivate() { + protected override void DeactivateImpl() { if (receiver) GameObject.Destroy(receiver); } public override void Dispose(bool disposing) { if (disposing) { - Deactivate(); + DeactivateImpl(); } } diff --git a/Assets/Cryville/Common/Unity/Input/UnityMouseHandler.cs b/Assets/Cryville/Common/Unity/Input/UnityMouseHandler.cs index e8ce656..565fde9 100644 --- a/Assets/Cryville/Common/Unity/Input/UnityMouseHandler.cs +++ b/Assets/Cryville/Common/Unity/Input/UnityMouseHandler.cs @@ -12,18 +12,18 @@ namespace Cryville.Common.Unity.Input { } } - public override void Activate() { + protected override void ActivateImpl() { receiver = new GameObject("__mouserecv__"); receiver.AddComponent().SetHandler(this); } - public override void Deactivate() { + protected override void DeactivateImpl() { if (receiver) GameObject.Destroy(receiver); } public override void Dispose(bool disposing) { if (disposing) { - Deactivate(); + DeactivateImpl(); } } @@ -57,7 +57,7 @@ namespace Cryville.Common.Unity.Input { double time = Time.timeAsDouble; Vector2 pos = unity::Input.mousePosition; pos.y = Screen.height - pos.y; - handler.OnInput(0, 0, new InputVector(time, pos)); + handler.Feed(0, 0, new InputVector(time, pos)); } } } diff --git a/Assets/Cryville/Common/Unity/Input/UnityTouchHandler.cs b/Assets/Cryville/Common/Unity/Input/UnityTouchHandler.cs index bee9f8f..cef659e 100644 --- a/Assets/Cryville/Common/Unity/Input/UnityTouchHandler.cs +++ b/Assets/Cryville/Common/Unity/Input/UnityTouchHandler.cs @@ -12,18 +12,18 @@ namespace Cryville.Common.Unity.Input { } } - public override void Activate() { + protected override void ActivateImpl() { receiver = new GameObject("__touchrecv__"); receiver.AddComponent().SetHandler(this); } - public override void Deactivate() { + protected override void DeactivateImpl() { if (receiver) GameObject.Destroy(receiver); } public override void Dispose(bool disposing) { if (disposing) { - Deactivate(); + DeactivateImpl(); } } @@ -61,11 +61,11 @@ namespace Cryville.Common.Unity.Input { pos.y = Screen.height - pos.y; var vec = new InputVector(time, pos); if (t.phase == TouchPhase.Began || t.phase == TouchPhase.Stationary || t.phase == TouchPhase.Moved) { - handler.OnInput(0, t.fingerId, vec); + handler.Feed(0, t.fingerId, vec); } else if (t.phase == TouchPhase.Ended || t.phase == TouchPhase.Canceled) { - handler.OnInput(0, t.fingerId, vec); - handler.OnInput(0, t.fingerId, new InputVector(time)); + handler.Feed(0, t.fingerId, vec); + handler.Feed(0, t.fingerId, new InputVector(time)); } } } diff --git a/Assets/Cryville/Common/Unity/Input/WindowsPointerHandler.cs b/Assets/Cryville/Common/Unity/Input/WindowsPointerHandler.cs index 4d9c968..515b34c 100644 --- a/Assets/Cryville/Common/Unity/Input/WindowsPointerHandler.cs +++ b/Assets/Cryville/Common/Unity/Input/WindowsPointerHandler.cs @@ -56,40 +56,18 @@ namespace Cryville.Common.Unity.Input { } } - public override void Activate() { - RegisterWindowProc(WndProc); - if (!NativeMethods.RegisterTouchWindow(hMainWindow, NativeMethods.TOUCH_WINDOW_FLAGS.TWF_WANTPALM)) { - throw new InvalidOperationException("Failed to register touch window"); - } - DisablePressAndHold(); - } - - public override void Deactivate() { - EnablePressAndHold(); - if (!NativeMethods.UnregisterTouchWindow(hMainWindow)) { - throw new InvalidOperationException("Failed to unregister touch window"); - } - UnregisterWindowProc(); - } - - void RegisterWindowProc(WndProcDelegate windowProc) { - newWndProc = windowProc; - newWndProcPtr = Marshal.GetFunctionPointerForDelegate(newWndProc); - oldWndProcPtr = SetWindowLongPtr(hMainWindow, -4, newWndProcPtr); - } - - void UnregisterWindowProc() { - SetWindowLongPtr(hMainWindow, -4, oldWndProcPtr); - newWndProcPtr = IntPtr.Zero; - newWndProc = null; - } - public const int TABLET_DISABLE_PRESSANDHOLD = 0x00000001; public const int TABLET_DISABLE_PENTAPFEEDBACK = 0x00000008; public const int TABLET_DISABLE_PENBARRELFEEDBACK = 0x00000010; public const int TABLET_DISABLE_FLICKS = 0x00010000; - protected void DisablePressAndHold() { + protected override void ActivateImpl() { + newWndProc = WndProc; + newWndProcPtr = Marshal.GetFunctionPointerForDelegate(newWndProc); + oldWndProcPtr = SetWindowLongPtr(hMainWindow, -4, newWndProcPtr); + if (!NativeMethods.RegisterTouchWindow(hMainWindow, NativeMethods.TOUCH_WINDOW_FLAGS.TWF_WANTPALM)) { + throw new InvalidOperationException("Failed to register touch window"); + } pressAndHoldAtomID = NativeMethods.GlobalAddAtom(PRESS_AND_HOLD_ATOM); NativeMethods.SetProp(hMainWindow, PRESS_AND_HOLD_ATOM, TABLET_DISABLE_PRESSANDHOLD | // disables press and hold (right-click) gesture @@ -99,11 +77,17 @@ namespace Cryville.Common.Unity.Input { ); } - protected void EnablePressAndHold() { + protected override void DeactivateImpl() { if (pressAndHoldAtomID != 0) { NativeMethods.RemoveProp(hMainWindow, PRESS_AND_HOLD_ATOM); NativeMethods.GlobalDeleteAtom(pressAndHoldAtomID); } + if (!NativeMethods.UnregisterTouchWindow(hMainWindow)) { + throw new InvalidOperationException("Failed to unregister touch window"); + } + SetWindowLongPtr(hMainWindow, -4, oldWndProcPtr); + newWndProcPtr = IntPtr.Zero; + newWndProc = null; } const string UnityWindowClassName = "UnityWndClass"; @@ -158,7 +142,7 @@ namespace Cryville.Common.Unity.Input { } public override void Dispose(bool disposing) { - Deactivate(); + DeactivateImpl(); if (usePointerMessage) NativeMethods.EnableMouseInPointer(false); Instance = null; @@ -244,7 +228,7 @@ namespace Cryville.Common.Unity.Input { default: type = 0; break; } if (rawpinfo.pointerFlags.HasFlag(NativeMethods.POINTER_FLAGS.POINTER_FLAG_CANCELED)) { - OnInput(type, id, new InputVector(time)); + Feed(type, id, new InputVector(time)); return; } @@ -253,11 +237,11 @@ namespace Cryville.Common.Unity.Input { switch ((WindowMessages)msg) { case WindowMessages.WM_POINTERDOWN: case WindowMessages.WM_POINTERUPDATE: - OnInput(type, id, vec); + Feed(type, id, vec); break; case WindowMessages.WM_POINTERUP: - OnInput(type, id, vec); - OnInput(type, id, new InputVector(time)); + Feed(type, id, vec); + Feed(type, id, new InputVector(time)); break; } } @@ -332,11 +316,11 @@ namespace Cryville.Common.Unity.Input { if (touch.dwFlags.HasFlag(NativeMethods.TOUCHINPUT_Flags.TOUCHEVENTF_MOVE) || touch.dwFlags.HasFlag(NativeMethods.TOUCHINPUT_Flags.TOUCHEVENTF_DOWN)) { - OnInput(255, id, vec); + Feed(255, id, vec); } else if (touch.dwFlags.HasFlag(NativeMethods.TOUCHINPUT_Flags.TOUCHEVENTF_UP)) { - OnInput(255, id, vec); - OnInput(255, id, new InputVector(time)); + Feed(255, id, vec); + Feed(255, id, new InputVector(time)); } } diff --git a/Assets/Cryville/Crtr/InputProxy.cs b/Assets/Cryville/Crtr/InputProxy.cs index 0e9fbc4..02a99cb 100644 --- a/Assets/Cryville/Crtr/InputProxy.cs +++ b/Assets/Cryville/Crtr/InputProxy.cs @@ -1,16 +1,28 @@ -using Cryville.Common.Unity.Input; +using Cryville.Common; +using Cryville.Common.Pdt; +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 _hash1 = new Dictionary(); - readonly Dictionary _hash2 = new Dictionary(); + readonly Dictionary _tproxies = new Dictionary(); + readonly Dictionary _sproxies = new Dictionary(); readonly Dictionary _use = new Dictionary(); readonly Dictionary> _rev = new Dictionary>(); + readonly Dictionary _vecs = new Dictionary(); public event EventHandler ProxyChanged; public InputProxy(PdtRuleset ruleset) { + unsafe { + fixed (byte* ptr = _vecbuf) { + *(int*)(ptr + 3 * sizeof(float)) = PdtInternalType.Number; + } + } + _etor = ChartPlayer.etor; _ruleset = ruleset; foreach (var i in ruleset.inputs) { _use.Add(i.Key, 0); @@ -23,27 +35,30 @@ namespace Cryville.Crtr { } } } + #region Settings public void Set(InputProxyEntry proxy) { var name = proxy.Target; - if (_hash1.ContainsKey(name)) Remove(proxy); + if (_tproxies.ContainsKey(name)) Remove(proxy); if (_use[proxy.Target] > 0) throw new InvalidOperationException("Input already assigned"); if (proxy.Source != null) { - _hash1.Add(proxy.Target, proxy); - _hash2.Add(proxy.Source.Value, proxy); + proxy.Source.Value.Handler.OnInput += OnInput; + _tproxies.Add(proxy.Target, proxy); + _sproxies.Add(proxy.Source.Value, proxy); IncrementUseRecursive(name); IncrementReversedUseRecursive(name); } } void Remove(InputProxyEntry proxy) { var name = proxy.Target; - _hash2.Remove(_hash1[name].Source.Value); - _hash1.Remove(name); + proxy.Source.Value.Handler.OnInput -= OnInput; + _sproxies.Remove(_tproxies[name].Source.Value); + _tproxies.Remove(name); DecrementUseRecursive(name); DecrementReversedUseRecursive(name); } public bool IsUsed(InputSource src) { - return _hash2.ContainsKey(src); + return _sproxies.ContainsKey(src); } void IncrementUseRecursive(string name) { BroadcastProxyChanged(name); @@ -80,8 +95,47 @@ namespace Cryville.Crtr { } } void BroadcastProxyChanged(string name) { - ProxyChanged(this, new ProxyChangedEventArgs(name, _hash1.ContainsKey(name) ? _hash1[name].Source : null, _use[name] > 0)); + ProxyChanged(this, new ProxyChangedEventArgs(name, _tproxies.ContainsKey(name) ? _tproxies[name].Source : null, _use[name] > 0)); } + #endregion + + #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(); } + void OnInput(InputIdentifier id, InputVector vec) { + InputProxyEntry proxy; + if (_sproxies.TryGetValue(id.Source, out proxy)) { + OnInput(id, vec, proxy.Target); + } + } + 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(); + fixed (byte* ptr = _vecbuf) { + *(Vector3*)ptr = vec.Vector; + } + _etor.ContextCascadeUpdate(_var_value, new PropSrc.Arbitrary(PdtInternalType.Vector, _vecbuf)); + OnInput(id, target); + _etor.ContextCascadeDiscard(); + } + unsafe void OnInput(InputIdentifier id, string target) { + var def = _ruleset.inputs[target]; + if (def.pass != null) { + foreach (var p in def.pass) { + _arbop.Name = _var_value; + _etor.ContextCascadeInsert(); + _etor.Evaluate(_arbop, p.Value); + OnInput(id, p.Key); + _etor.ContextCascadeDiscard(); + } + } + else { + Logger.Log("main", 0, "Input/Proxy", "input recv {0}", target); + } + } + #endregion } public class ProxyChangedEventArgs : EventArgs { @@ -100,45 +154,4 @@ namespace Cryville.Crtr { public string Target { get; set; } public byte[] Mapping { get; private set; } } - - public sealed class InputProxyHandler : InputHandler { - readonly InputDefinition _def; - - public InputProxyHandler(InputDefinition def, InputHandler src) : base() { - _def = def; - src.Callback = OnInput; - } - - public override void Activate() { - throw new NotImplementedException(); - } - - public override void Deactivate() { - throw new NotImplementedException(); - } - - public override void Dispose(bool disposing) { - throw new NotImplementedException(); - } - - public override bool IsNullable(int type) { - throw new NotImplementedException(); - } - - public override byte GetDimension(int type) { - throw new NotImplementedException(); - } - - public override string GetTypeName(int type) { - throw new NotImplementedException(); - } - - public override double GetCurrentTimestamp() { - throw new NotImplementedException(); - } - - void OnInput(InputIdentifier id, InputVector vec) { - - } - } }