InputControl的实现类挪入基本类型,不再每个设备单独实现

This commit is contained in:
ALIENJACK\alien 2025-03-27 11:54:10 +08:00
parent 924727eb7c
commit 8007af0bc5
14 changed files with 242 additions and 240 deletions

View File

@ -1,6 +1,5 @@
using AxibugEmuOnline.Client.InputDevices; using AxibugEmuOnline.Client.InputDevices;
using AxibugProtobuf; using AxibugProtobuf;
using AxiInputSP;
using System; using System;
namespace AxibugEmuOnline.Client.Settings namespace AxibugEmuOnline.Client.Settings

View File

@ -232,7 +232,7 @@ namespace AxibugEmuOnline.Client.Settings
else return totalFloat / totalControl; else return totalFloat / totalControl;
} }
public class MapSetting : Dictionary<T, List<InputDevice.InputControl>> { } public class MapSetting : Dictionary<T, List<InputControl>> { }
public class BindingPage public class BindingPage
{ {
@ -277,7 +277,7 @@ namespace AxibugEmuOnline.Client.Settings
m_mapSetting.Remove(device); m_mapSetting.Remove(device);
} }
public void SetBinding(T emuBtn, InputDevice.InputControl key, int settingSlot) public void SetBinding(T emuBtn, InputControl key, int settingSlot)
{ {
var device = key.Device; var device = key.Device;
m_registedDevices.TryGetValue(device.GetType(), out var inputDevice); m_registedDevices.TryGetValue(device.GetType(), out var inputDevice);
@ -287,7 +287,7 @@ namespace AxibugEmuOnline.Client.Settings
var setting = m_mapSetting[inputDevice]; var setting = m_mapSetting[inputDevice];
if (!setting.TryGetValue(emuBtn, out var settingList)) if (!setting.TryGetValue(emuBtn, out var settingList))
{ {
settingList = new List<InputDevice.InputControl>(); settingList = new List<InputControl>();
setting[emuBtn] = settingList; setting[emuBtn] = settingList;
} }
@ -297,7 +297,7 @@ namespace AxibugEmuOnline.Client.Settings
settingList[settingSlot] = key; settingList[settingSlot] = key;
} }
public InputDevice.InputControl GetBinding(T emuBtn, InputDevice device, int settingSlot) public InputControl GetBinding(T emuBtn, InputDevice device, int settingSlot)
{ {
m_mapSetting.TryGetValue(device, out var mapSetting); m_mapSetting.TryGetValue(device, out var mapSetting);
if (mapSetting == null) return null; if (mapSetting == null) return null;
@ -308,8 +308,8 @@ namespace AxibugEmuOnline.Client.Settings
return settingList[settingSlot]; return settingList[settingSlot];
} }
private List<InputDevice.InputControl> m_caches = new List<InputDevice.InputControl>(); private List<InputControl> m_caches = new List<InputControl>();
public IEnumerable<InputDevice.InputControl> GetBinding(T emuBtn) public IEnumerable<InputControl> GetBinding(T emuBtn)
{ {
m_caches.Clear(); m_caches.Clear();

View File

@ -0,0 +1,17 @@
namespace AxibugEmuOnline.Client.InputDevices
{
/// <summary>
/// 按键类型的输入控件
/// </summary>
public class Button : InputControl
{
string m_controlName;
public Button(InputDevice device, string controlName) : base(device)
{
m_controlName = controlName;
}
public override string ControlName => m_controlName;
}
}

View File

@ -0,0 +1,59 @@
using UnityEngine;
namespace AxibugEmuOnline.Client.InputDevices
{
/// <summary>
/// 输入设备的抽象控件接口
/// </summary>
public abstract class InputControl
{
/// <summary> 控件所属设备 </summary>
public InputDevice Device { get; internal set; }
/// <summary> 获取该控件是否在当前调用帧被激发 </summary>
public bool Start { get; private set; }
/// <summary> 获取该控件是否在当前调用帧被释放 </summary>
public bool Release { get; private set; }
bool m_performingLastFrame;
/// <summary> 获取该控件是否在当前调用帧是否处于活动状态 </summary>
public virtual bool Performing => Device.Resolver.CheckPerforming(this);
/// <summary> 获得该控件的以二维向量表达的值 </summary>
/// <returns></returns>
public virtual Vector2 GetVector2() => Device.Resolver.GetVector2(this);
/// <summary> 获得该控件的以浮点数表达的值 </summary>
public virtual float GetFlaot() => Device.Resolver.GetFloat(this);
internal void Update()
{
UpdateReleaseStartState();
OnUpdate();
}
private void UpdateReleaseStartState()
{
var oldPerforming = m_performingLastFrame;
var newPerforming = Performing;
Start = false;
Release = false;
if (oldPerforming != newPerforming)
{
if (oldPerforming == false) Start = true;
else Release = true;
}
m_performingLastFrame = Performing;
}
protected virtual void OnUpdate() { }
/// <summary> 控件名,这个控件名称必须是唯一的 </summary>
public abstract string ControlName { get; }
internal InputControl(InputDevice device)
{
Device = device;
}
}
}

View File

@ -0,0 +1,70 @@
using UnityEngine;
namespace AxibugEmuOnline.Client.InputDevices
{
/// <summary>
/// 摇杆类型的输入控件,支持的返回值为Vector2
/// </summary>
public class Stick : InputControl
{
string m_controlName;
public override string ControlName => m_controlName;
public VirtualButton UP { get; private set; }
public VirtualButton Down { get; private set; }
public VirtualButton Left { get; private set; }
public VirtualButton Right { get; private set; }
public Stick(InputDevice device, string controlName) : base(device)
{
m_controlName = controlName;
UP = new VirtualButton(device);
Down = new VirtualButton(device);
Left = new VirtualButton(device);
Right = new VirtualButton(device);
}
protected override void OnUpdate()
{
var axis = GetVector2();
UP.m_performing = axis.y > 0f;
UP.Update();
Down.m_performing = axis.y < 0f;
Down.Update();
Left.m_performing = axis.x < 0f;
Left.Update();
Right.m_performing = axis.x > 0f;
Right.Update();
}
public class VirtualButton : InputControl
{
internal bool m_performing;
public VirtualButton(InputDevice device) : base(device) { }
public override bool Performing
{
get => m_performing;
}
public override Vector2 GetVector2()
{
return default;
}
public override float GetFlaot()
{
return Performing ? 1 : 0;
}
public override string ControlName => "VirtualStickButton";
}
}
}

View File

@ -0,0 +1,56 @@
using System.Collections.Generic;
namespace AxibugEmuOnline.Client.InputDevices
{
public abstract class InputDevice
{
public string UniqueName => m_resolver.GetDeviceName(this);
/// <summary> 指示该设备是否在线 </summary>
public bool Online => m_resolver.CheckOnline(this);
/// <summary> 指示该设备当前帧是否有任意控件被激发 </summary>
public bool AnyKeyDown { get; private set; }
/// <summary> 获得输入解决器 </summary>
internal InputResolver Resolver => m_resolver;
protected Dictionary<string, InputControl> m_controlMapper = new Dictionary<string, InputControl>();
protected InputResolver m_resolver;
public InputDevice(InputResolver resolver)
{
m_resolver = resolver;
foreach (var control in DefineControls())
{
m_controlMapper.Add(control.ControlName, control);
}
}
public void Update()
{
AnyKeyDown = false;
foreach (var control in m_controlMapper.Values)
{
control.Update();
if (control.Start)
{
AnyKeyDown = true;
}
}
}
/// <summary> 用于列出这个输入设备的所有输入控件实例 </summary>
/// <returns></returns>
protected abstract List<InputControl> DefineControls();
/// <summary> 通过控件名称,找到对应的控件 </summary>
/// <param name="keyName"></param>
/// <returns></returns>
public InputControl FindControlByName(string controlName)
{
m_controlMapper.TryGetValue(controlName, out var key);
return key;
}
}
}

View File

@ -23,17 +23,15 @@ namespace AxibugEmuOnline.Client.InputDevices
return keys; return keys;
} }
public class KeyboardKey : InputControl public class KeyboardKey : Button
{ {
internal KeyCode m_keycode; internal KeyCode m_keycode;
internal KeyboardKey(KeyCode listenKey, KeyBoard keyboard) internal KeyboardKey(KeyCode listenKey, KeyBoard keyboard)
: base(keyboard) : base(keyboard, listenKey.ToString())
{ {
m_keycode = listenKey; m_keycode = listenKey;
} }
public override string ControlName => m_keycode.ToString();
} }
} }

View File

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine;
namespace AxibugEmuOnline.Client.InputDevices namespace AxibugEmuOnline.Client.InputDevices
{ {
@ -46,82 +45,10 @@ namespace AxibugEmuOnline.Client.InputDevices
Down = new Button(this, "DOWN"); Down = new Button(this, "DOWN");
Left = new Button(this, "LEFT"); Left = new Button(this, "LEFT");
LeftStick = new Stick(this, nameof(LeftStick));
RightStick = new Stick(this, nameof(RightStick));
return result; return result;
} }
public class Button : InputControl
{
internal string m_controlName;
public Button(InputDevice device, string controlName) : base(device)
{
m_controlName = controlName;
}
public override string ControlName => m_controlName;
}
public class Stick : InputControl
{
internal bool m_left;
public VirtualButton UP { get; private set; }
public VirtualButton Down { get; private set; }
public VirtualButton Left { get; private set; }
public VirtualButton Right { get; private set; }
public Stick(InputDevice device, bool left) : base(device)
{
m_left = left;
UP = new VirtualButton(device);
Down = new VirtualButton(device);
Left = new VirtualButton(device);
Right = new VirtualButton(device);
}
protected override void OnUpdate()
{
var axis = GetVector2();
UP.m_performing = axis.y > 0f;
UP.Update();
Down.m_performing = axis.y < 0f;
Down.Update();
Left.m_performing = axis.x < 0f;
Left.Update();
Right.m_performing = axis.x > 0f;
Right.Update();
}
public override string ControlName => $"{nameof(Stick)}_{(m_left ? "left" : "right")}";
public class VirtualButton : InputControl
{
internal bool m_performing;
public VirtualButton(InputDevice device) : base(device) { }
public override bool Performing
{
get => m_performing;
}
public override Vector2 GetVector2()
{
return default;
}
public override float GetFlaot()
{
return Performing ? 1 : 0;
}
public override string ControlName => "VirtualStickButton";
}
}
} }
} }

View File

@ -62,111 +62,4 @@ namespace AxibugEmuOnline.Client.InputDevices
foreach (var device in m_devices.Values) device.Update(); foreach (var device in m_devices.Values) device.Update();
} }
} }
public abstract class InputDevice
{
public string UniqueName => m_resolver.GetDeviceName(this);
/// <summary> 指示该设备是否在线 </summary>
public bool Online => m_resolver.CheckOnline(this);
/// <summary> 指示该设备当前帧是否有任意控件被激发 </summary>
public bool AnyKeyDown { get; private set; }
/// <summary> 获得输入解决器 </summary>
internal InputResolver Resolver => m_resolver;
protected Dictionary<string, InputControl> m_controlMapper = new Dictionary<string, InputControl>();
protected InputResolver m_resolver;
public InputDevice(InputResolver resolver)
{
m_resolver = resolver;
foreach (var control in DefineControls())
{
m_controlMapper.Add(control.ControlName, control);
}
}
public void Update()
{
AnyKeyDown = false;
foreach (var control in m_controlMapper.Values)
{
control.Update();
if (control.Start)
{
AnyKeyDown = true;
}
}
}
/// <summary> 用于列出这个输入设备的所有输入控件实例 </summary>
/// <returns></returns>
protected abstract List<InputControl> DefineControls();
/// <summary> 通过控件名称,找到对应的控件 </summary>
/// <param name="keyName"></param>
/// <returns></returns>
public InputControl FindControlByName(string controlName)
{
m_controlMapper.TryGetValue(controlName, out var key);
return key;
}
/// <summary>
/// 输入设备的抽象控件接口
/// </summary>
public abstract class InputControl
{
/// <summary> 控件所属设备 </summary>
public InputDevice Device { get; internal set; }
/// <summary> 获取该控件是否在当前调用帧被激发 </summary>
public bool Start { get; private set; }
/// <summary> 获取该控件是否在当前调用帧被释放 </summary>
public bool Release { get; private set; }
bool m_performingLastFrame;
/// <summary> 获取该控件是否在当前调用帧是否处于活动状态 </summary>
public virtual bool Performing => Device.Resolver.CheckPerforming(this);
/// <summary> 获得该控件的以二维向量表达的值 </summary>
/// <returns></returns>
public virtual Vector2 GetVector2() => Device.Resolver.GetVector2(this);
/// <summary> 获得该控件的以浮点数表达的值 </summary>
public virtual float GetFlaot() => Device.Resolver.GetFloat(this);
internal void Update()
{
UpdateReleaseStartState();
OnUpdate();
}
private void UpdateReleaseStartState()
{
var oldPerforming = m_performingLastFrame;
var newPerforming = Performing;
Start = false;
Release = false;
if (oldPerforming != newPerforming)
{
if (oldPerforming == false) Start = true;
else Release = true;
}
m_performingLastFrame = Performing;
}
protected virtual void OnUpdate() { }
/// <summary> 控件名,这个控件名称必须是唯一的 </summary>
public abstract string ControlName { get; }
internal InputControl(InputDevice device)
{
Device = device;
}
}
}
} }

View File

@ -56,9 +56,9 @@ namespace AxibugEmuOnline.Client.InputDevices
OnDeviceConnected?.Invoke(connectDevice); OnDeviceConnected?.Invoke(connectDevice);
} }
public abstract bool CheckPerforming<CONTROLLER>(CONTROLLER control) where CONTROLLER : InputDevice.InputControl; public abstract bool CheckPerforming<CONTROLLER>(CONTROLLER control) where CONTROLLER : InputControl;
public abstract Vector2 GetVector2<CONTROLLER>(CONTROLLER control) where CONTROLLER : InputDevice.InputControl; public abstract Vector2 GetVector2<CONTROLLER>(CONTROLLER control) where CONTROLLER : InputControl;
public abstract float GetFloat<CONTROLLER>(CONTROLLER control) where CONTROLLER : InputDevice.InputControl; public abstract float GetFloat<CONTROLLER>(CONTROLLER control) where CONTROLLER : InputControl;
/// <summary> /// <summary>
/// 获得输入设备的唯一名称 /// 获得输入设备的唯一名称
/// </summary> /// </summary>

View File

@ -1,7 +1,6 @@
#if ENABLE_INPUT_SYSTEM #if ENABLE_INPUT_SYSTEM
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.Controls;
using IP = UnityEngine.InputSystem.InputSystem; using IP = UnityEngine.InputSystem.InputSystem;
using IPDevice = UnityEngine.InputSystem.InputDevice; using IPDevice = UnityEngine.InputSystem.InputDevice;
@ -9,8 +8,8 @@ using IPKeyboard = UnityEngine.InputSystem.Keyboard;
namespace AxibugEmuOnline.Client.InputDevices.ForInputSystem namespace AxibugEmuOnline.Client.InputDevices.ForInputSystem
{ {
/// <summary> InputSystem对接类 </summary> /// <summary> 基于UnityInputSystem实现的输入解决器 </summary>
public partial class InputSystemResolver : InputResolver public class InputSystemResolver : InputResolver
{ {
DualWayDictionary<IPDevice, InputDevice> m_devices = new DualWayDictionary<IPDevice, InputDevice>(); DualWayDictionary<IPDevice, InputDevice> m_devices = new DualWayDictionary<IPDevice, InputDevice>();
@ -101,10 +100,7 @@ namespace AxibugEmuOnline.Client.InputDevices.ForInputSystem
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
}
public partial class InputSystemResolver : InputResolver
{
static ButtonControl GetIPKeyboardKey(IPKeyboard keyboard, KeyCode key) static ButtonControl GetIPKeyboardKey(IPKeyboard keyboard, KeyCode key)
{ {
switch (key) switch (key)
@ -228,6 +224,7 @@ namespace AxibugEmuOnline.Client.InputDevices.ForInputSystem
throw new System.NotImplementedException($"Not Find KeyCode Mapper Code from {key}"); throw new System.NotImplementedException($"Not Find KeyCode Mapper Code from {key}");
} }
} }
} }
} }
#endif #endif

View File

@ -1,11 +1,9 @@
using NUnit.Framework.Internal; using System.Collections.Generic;
using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using static Essgee.Emulation.Audio.DMGAudio;
using static VirtualNes.Core.APU_INTERNAL;
namespace AxibugEmuOnline.Client.InputDevices.ForPSV namespace AxibugEmuOnline.Client.InputDevices.ForPSV
{ {
/// <summary> PSV特化输入解决器,只能用于PSV平台,并且只支持PSV控制器 </summary>
public class PSVResolver : InputResolver public class PSVResolver : InputResolver
{ {
List<InputDevice> m_devices = new List<InputDevice>(); List<InputDevice> m_devices = new List<InputDevice>();
@ -38,24 +36,21 @@ namespace AxibugEmuOnline.Client.InputDevices.ForPSV
{ {
if (control.Device is PSVController psvCon) if (control.Device is PSVController psvCon)
{ {
if (control is PSVController.Button button) if (control == psvCon.Cross) return Input.GetKey(KeyCode.Joystick1Button0);
else if (control == psvCon.Circle) return Input.GetKey(KeyCode.Joystick1Button1);
else if (control == psvCon.Square) return Input.GetKey(KeyCode.Joystick1Button2);
else if (control == psvCon.Triangle) return Input.GetKey(KeyCode.Joystick1Button3);
else if (control == psvCon.L) return Input.GetKey(KeyCode.Joystick1Button4);
else if (control == psvCon.R) return Input.GetKey(KeyCode.Joystick1Button5);
else if (control == psvCon.Select) return Input.GetKey(KeyCode.Joystick1Button6);
else if (control == psvCon.Start) return Input.GetKey(KeyCode.Joystick1Button7);
else if (control == psvCon.Up) return Input.GetKey(KeyCode.Joystick1Button8);
else if (control == psvCon.Right) return Input.GetKey(KeyCode.Joystick1Button9);
else if (control == psvCon.Down) return Input.GetKey(KeyCode.Joystick1Button10);
else if (control == psvCon.Left) return Input.GetKey(KeyCode.Joystick1Button11);
else if (control == psvCon.LeftStick || control == psvCon.RightStick)
{ {
if (button == psvCon.Cross) return Input.GetKey(KeyCode.Joystick1Button0); var vec2 = control.GetVector2();
else if (button == psvCon.Circle) return Input.GetKey(KeyCode.Joystick1Button1);
else if (button == psvCon.Square) return Input.GetKey(KeyCode.Joystick1Button2);
else if (button == psvCon.Triangle) return Input.GetKey(KeyCode.Joystick1Button3);
else if (button == psvCon.L) return Input.GetKey(KeyCode.Joystick1Button4);
else if (button == psvCon.R) return Input.GetKey(KeyCode.Joystick1Button5);
else if (button == psvCon.Select) return Input.GetKey(KeyCode.Joystick1Button6);
else if (button == psvCon.Start) return Input.GetKey(KeyCode.Joystick1Button7);
else if (button == psvCon.Up) return Input.GetKey(KeyCode.Joystick1Button8);
else if (button == psvCon.Right) return Input.GetKey(KeyCode.Joystick1Button9);
else if (button == psvCon.Down) return Input.GetKey(KeyCode.Joystick1Button10);
else if (button == psvCon.Left) return Input.GetKey(KeyCode.Joystick1Button11);
}
else if (control is PSVController.Stick stick)
{
var vec2 = stick.GetVector2();
return vec2.x != 0 || vec2.y != 0; return vec2.x != 0 || vec2.y != 0;
} }
} }
@ -65,24 +60,15 @@ namespace AxibugEmuOnline.Client.InputDevices.ForPSV
public override Vector2 GetVector2<CONTROLLER>(CONTROLLER control) public override Vector2 GetVector2<CONTROLLER>(CONTROLLER control)
{ {
if (control.Device is PSVController) if (control.Device is PSVController psvCon)
{ {
if (control is PSVController.Stick stick) if (control == psvCon.LeftStick)
{ {
Vector2 result = Vector2.zero; return new Vector2(Input.GetAxis("Joy1 Axis X"), Input.GetAxis("Joy1 Axis Y"));
}
if (stick.m_left) else if (control == psvCon.RightStick)
{ {
result.x = Input.GetAxis("Joy1 Axis X"); return new Vector2(Input.GetAxis("Joy1 Axis 4"), Input.GetAxis("Joy1 Axis 5"));
result.y = Input.GetAxis("Joy1 Axis Y");
}
else
{
result.x = Input.GetAxis("Joy1 Axis 4");
result.y = Input.GetAxis("Joy1 Axis 5");
}
return result;
} }
} }