using AxiInputSP.UGUI; using System.Collections.Generic; using UnityEngine; namespace AxibugEmuOnline.Client.InputDevices { public abstract class InputResolver { public static InputResolver Create() { #if ENABLE_INPUT_SYSTEM //InputSystem return new ForInputSystem.InputSystemResolver(); #elif UNITY_PSP2 //特化实现 return new ForPSV.PSVResolver(); #elif UNITY_PS3 //SDK throw new System.NotImplementedException(); #else throw new System.NotImplementedException(); #endif } DualWayDictionary<AxiScreenGamepad, ScreenGamepad_D> m_devices = new DualWayDictionary<AxiScreenGamepad, ScreenGamepad_D>(); /// <summary> 禁止外部构造 </summary> protected InputResolver() { AxiScreenGamepad.OnGamepadActive += AxiScreenGamepad_OnGamepadActive; AxiScreenGamepad.OnGamepadDisactive += AxiScreenGamepad_OnGamepadDisactive; OnInit(); } private void AxiScreenGamepad_OnGamepadDisactive(AxiScreenGamepad sender) { if (m_devices.TryGetValue(sender, out var device)) { m_devices.Remove(sender); RaiseDeviceLost(device); } } private void AxiScreenGamepad_OnGamepadActive(AxiScreenGamepad sender) { var newDevice = new ScreenGamepad_D(sender, this); m_devices[sender] = newDevice; RaiseDeviceConnected(newDevice); } protected abstract void OnInit(); List<InputDevice_D> m_devicesResultCache = new List<InputDevice_D>(); /// <summary> /// 获得所有当前已连入的输入设备 /// </summary> /// <returns></returns> public IEnumerable<InputDevice_D> GetDevices() { m_devicesResultCache.Clear(); m_devicesResultCache.AddRange(m_devices.Values); m_devicesResultCache.AddRange(OnGetDevices()); return m_devicesResultCache; } /// <inheritdoc cref="GetDevices"/> protected abstract IEnumerable<InputDevice_D> OnGetDevices(); /// <summary> 检查指定输入设备是否还保持着连接 </summary> public bool CheckOnline(InputDevice_D device) { if (device is ScreenGamepad_D) { return m_devices.TryGetKey(device as ScreenGamepad_D, out var _); } else { return OnCheckOnline(device); } } /// <inheritdoc cref="CheckOnline(InputDevice_D)"/> protected abstract bool OnCheckOnline(InputDevice_D device); /// <param name="lostDevice">丢失的设备</param> public delegate void OnDeviceLostHandle(InputDevice_D lostDevice); /// <summary> 当设备丢失时触发 </summary> public event OnDeviceLostHandle OnDeviceLost; protected void RaiseDeviceLost(InputDevice_D lostDevice) { OnDeviceLost?.Invoke(lostDevice); } /// <param name="connectDevice">建立连接的设备</param> public delegate void OnDeviceConnectedHandle(InputDevice_D connectDevice); /// <summary> 当设备连接时触发 </summary> public event OnDeviceConnectedHandle OnDeviceConnected; protected void RaiseDeviceConnected(InputDevice_D connectDevice) { OnDeviceConnected?.Invoke(connectDevice); } public bool CheckPerforming<CONTROLLER>(CONTROLLER control) where CONTROLLER : InputControl_C { if (control.Device is ScreenGamepad_D) { ScreenGamepad_D device = control.Device as ScreenGamepad_D; return device.CheckPerforming(control); } else return OnCheckPerforming(control); } protected abstract bool OnCheckPerforming<CONTROLLER>(CONTROLLER control) where CONTROLLER : InputControl_C; public Vector2 GetVector2<CONTROLLER>(CONTROLLER control) where CONTROLLER : InputControl_C { if (control.Device is ScreenGamepad_D) { ScreenGamepad_D device = control.Device as ScreenGamepad_D; return device.GetVector2(control); } return OnGetVector2(control); } protected abstract Vector2 OnGetVector2<CONTROLLER>(CONTROLLER control) where CONTROLLER : InputControl_C; public float GetFloat<CONTROLLER>(CONTROLLER control) where CONTROLLER : InputControl_C { return OnGetFloat(control); } protected abstract float OnGetFloat<CONTROLLER>(CONTROLLER control) where CONTROLLER : InputControl_C; /// <summary> /// 获得输入设备的唯一名称 /// </summary> /// <param name="inputDevice">这个设备必须是由resolver提供,并且保持着连接</param> /// <returns></returns> public string GetDeviceName(InputDevice_D inputDevice) { if (inputDevice is ScreenGamepad_D) { m_devices.TryGetKey(inputDevice as ScreenGamepad_D, out var realDeviceScript); return $"{realDeviceScript.GetType().Name}_{realDeviceScript.GetHashCode()}"; } else return OnGetDeviceName(inputDevice); } /// <inheritdoc cref="GetDeviceName(InputDevice_D)"/> protected abstract string OnGetDeviceName(InputDevice_D inputDevice); } }