using System; using System.Collections.Generic; using System.Reflection; namespace Cryville.Common.Unity.Input { public class InputManager { static readonly List HandlerRegistries = new List { typeof(WindowsPointerHandler), typeof(UnityKeyHandler), typeof(UnityKeyHandler), typeof(UnityMouseHandler), typeof(UnityTouchHandler), }; readonly List _handlers = new List(); readonly Dictionary _timeOrigins = new Dictionary(); readonly object _lock = new object(); 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; _handlers.Add(h); _timeOrigins.Add(h, 0); Logger.Log("main", 1, "Input", "Initialized {0}", ReflectionHelper.GetSimpleName(t)); } catch (TargetInvocationException ex) { Logger.Log("main", 1, "Input", "Cannot initialize {0}: {1}", ReflectionHelper.GetSimpleName(t), ex.InnerException.Message); } } } public void Activate() { lock (_lock) { _events.Clear(); } foreach (var h in _handlers) h.Activate(); } public void SyncTime(double time) { foreach (var h in _handlers) { _timeOrigins[h] = time - h.GetCurrentTimestamp(); } } public void Deactivate() { foreach (var h in _handlers) h.Deactivate(); } void Callback(InputIdentifier id, InputVector vec) { lock (_lock) { double timeOrigin = _timeOrigins[id.Source.Handler]; vec.Time += timeOrigin; InputVector vec0; if (_vectors.TryGetValue(id, out vec0)) { _events.Add(new InputEvent { Id = id, From = vec0, To = vec, }); if (vec.IsNull) _vectors.Remove(id); else _vectors[id] = vec; } else { _events.Add(new InputEvent { Id = id, From = new InputVector(vec.Time), To = vec, }); _vectors.Add(id, vec); } } } public void EnumerateEvents(Action cb) { lock (_lock) { foreach (var ev in _events) cb(ev); _events.Clear(); } } } }