using AxibugEmuOnline.Client.InputDevices; using AxibugProtobuf; using System; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace AxibugEmuOnline.Client { /// <summary> /// 管理键位映射设置 /// </summary> public class KeyMapperSetting { Dictionary<RomPlatformType, EmuCoreControllerKeyBinding> m_binders = new Dictionary<RomPlatformType, EmuCoreControllerKeyBinding>(); Dictionary<Type, EmuCoreControllerKeyBinding> m_bindersByType = new Dictionary<Type, EmuCoreControllerKeyBinding>(); public KeyMapperSetting() { var baseType = typeof(EmuCoreControllerKeyBinding); foreach (var t in baseType.Assembly.ExportedTypes) { if (t.IsAbstract) continue; if (!baseType.IsAssignableFrom(t)) continue; var binderIns = Activator.CreateInstance(t) as EmuCoreControllerKeyBinding; m_binders.Add(binderIns.Platform, binderIns); m_bindersByType.Add(binderIns.GetType(), binderIns); } } public T GetBinder<T>() where T : EmuCoreControllerKeyBinding { m_bindersByType.TryGetValue(typeof(T), out var binder); return binder as T; } } /// <summary> /// 此类为内部继承, 请勿继承此类 /// </summary> public abstract class EmuCoreControllerKeyBinding { /// <summary> 所属核心 </summary> public abstract RomPlatformType Platform { get; } /// <summary> 控制器数量 </summary> public abstract int ControllerCount { get; } } /// <summary> /// 模拟器核心控制器键位绑定器 /// </summary> /// <typeparam name="T"></typeparam> public abstract class EmuCoreControllerKeyBinding<T> : EmuCoreControllerKeyBinding where T : Enum { List<BindingPage> m_bindingPages = new List<BindingPage>(); public EmuCoreControllerKeyBinding() { for (int i = 0; i < ControllerCount; i++) { m_bindingPages.Add(new BindingPage(i, this)); } LoadDefaultMapper(); } IEnumerable<T> DefineKeys() { return Enum.GetValues(typeof(T)).Cast<T>(); } /// <summary> /// 加载默认映射 /// </summary> public void LoadDefaultMapper() { foreach (var binding in m_bindingPages) { binding.ClearBinding(); OnLoadDefaultMapper(binding); } } protected abstract void OnLoadDefaultMapper(BindingPage binding); /// <summary> /// 获取指定按键是否处于按下状态 /// </summary> /// <param name="emuBtn"></param> /// <param name="controllerIndex"></param> /// <returns></returns> public bool GetKey(T emuBtn, int controllerIndex) { var binding = m_bindingPages[controllerIndex]; foreach (var key in binding.GetBinding(emuBtn)) { if (key.IsPressing()) return true; } return false; } /// <summary> /// 获取调用帧是否有任意按键触发了按下操作 /// </summary> /// <param name="controllerIndex"></param> /// <returns></returns> public bool AnyKeyDown(int controllerIndex) { var binding = m_bindingPages[controllerIndex]; return binding.AnyKeyDown(); } /// <summary> /// 获取指定按键的值 /// </summary> /// <param name="emuBtn">模拟器平台的具体键枚举</param> /// <param name="controllerIndex">模拟器平台的控制器序号</param> /// <returns></returns> public Vector2 GetVector2(T emuBtn, int controllerIndex) { var binding = m_bindingPages[controllerIndex]; foreach (var key in binding.GetBinding(emuBtn)) { if (!key.IsPressing()) continue; return key.GetVector2(); } return default(Vector2); } /// <summary> /// 获取指定按键的值 /// </summary> /// <param name="emuBtn">模拟器平台的具体键枚举</param> /// <param name="controllerIndex">模拟器平台的控制器序号</param> /// <returns></returns> public float GetFloat(T emuBtn, int controllerIndex) { var binding = m_bindingPages[controllerIndex]; foreach (var key in binding.GetBinding(emuBtn)) { if (!key.IsPressing()) continue; return key.GetFlaot(); } return default(float); } public class BindingPage { Dictionary<T, List<InputDevice.KeyBase>> m_mapSetting = new Dictionary<T, List<InputDevice.KeyBase>>(); public int ControllerIndex { get; } public EmuCoreControllerKeyBinding<T> Host { get; } internal BindingPage(int controllerIndex, EmuCoreControllerKeyBinding<T> host) { ControllerIndex = controllerIndex; Host = host; foreach (var emuBtn in host.DefineKeys()) m_mapSetting[emuBtn] = new List<InputDevice.KeyBase>(); } public void ClearBinding() { foreach (var list in m_mapSetting.Values) list.Clear(); } public void SetBinding(T emuBtn, InputDevice.KeyBase key, int settingSlot) { var settingList = m_mapSetting[emuBtn]; int needFixCount = settingSlot - settingList.Count + 1; if (needFixCount > 0) for (int i = 0; i < needFixCount; i++) settingList.Add(null); settingList[settingSlot] = key; } public InputDevice.KeyBase GetBinding(T emuBtn, int settingSlot) { var settingList = m_mapSetting[emuBtn]; if (settingSlot >= settingList.Count) return null; return settingList[settingSlot]; } public List<InputDevice.KeyBase> GetBinding(T emuBtn) { return m_mapSetting[emuBtn]; } public bool AnyKeyDown() { foreach (var item in m_mapSetting) { foreach (var key in item.Value) { if (key.GetButtonDown()) return true; } } return false; } } } }