ControllerInputView.axaml.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. using Avalonia;
  2. using Avalonia.Controls;
  3. using Avalonia.Controls.Primitives;
  4. using Avalonia.Input;
  5. using Avalonia.Interactivity;
  6. using Avalonia.LogicalTree;
  7. using FluentAvalonia.UI.Controls;
  8. using Ryujinx.Ava.UI.Helpers;
  9. using Ryujinx.Ava.UI.Models;
  10. using Ryujinx.Ava.UI.ViewModels.Input;
  11. using Ryujinx.Common.Configuration.Hid.Controller;
  12. using Ryujinx.Input;
  13. using Ryujinx.Input.Assigner;
  14. using System.Linq;
  15. using Button = Ryujinx.Input.Button;
  16. using StickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
  17. namespace Ryujinx.Ava.UI.Views.Input
  18. {
  19. public partial class ControllerInputView : UserControl
  20. {
  21. private ButtonKeyAssigner _currentAssigner;
  22. public ControllerInputView()
  23. {
  24. InitializeComponent();
  25. foreach (ILogical visual in SettingButtons.GetLogicalDescendants())
  26. {
  27. switch (visual)
  28. {
  29. case ToggleButton button and not CheckBox:
  30. button.IsCheckedChanged += Button_IsCheckedChanged;
  31. break;
  32. case CheckBox check:
  33. check.IsCheckedChanged += CheckBox_IsCheckedChanged;
  34. break;
  35. case Slider slider:
  36. slider.PropertyChanged += Slider_ValueChanged;
  37. break;
  38. }
  39. }
  40. }
  41. protected override void OnPointerReleased(PointerReleasedEventArgs e)
  42. {
  43. base.OnPointerReleased(e);
  44. if (_currentAssigner is { ToggledButton.IsPointerOver: false })
  45. {
  46. _currentAssigner.Cancel();
  47. }
  48. }
  49. private float _changeSlider = float.NaN;
  50. private void Slider_ValueChanged(object sender, AvaloniaPropertyChangedEventArgs e)
  51. {
  52. if (sender is Slider check)
  53. {
  54. _changeSlider = check.IsPointerOver switch
  55. {
  56. true when float.IsNaN(_changeSlider) => (float)check.Value,
  57. false => float.NaN,
  58. _ => _changeSlider
  59. };
  60. if (!float.IsNaN(_changeSlider) && _changeSlider != (float)check.Value)
  61. {
  62. (DataContext as ControllerInputViewModel)!.ParentModel.IsModified = true;
  63. _changeSlider = (float)check.Value;
  64. }
  65. }
  66. }
  67. private void CheckBox_IsCheckedChanged(object sender, RoutedEventArgs e)
  68. {
  69. if (sender is CheckBox { IsPointerOver: true })
  70. {
  71. (DataContext as ControllerInputViewModel)!.ParentModel.IsModified = true;
  72. _currentAssigner?.Cancel();
  73. _currentAssigner = null;
  74. }
  75. }
  76. private void Button_IsCheckedChanged(object sender, RoutedEventArgs e)
  77. {
  78. if (sender is ToggleButton button)
  79. {
  80. if (button.IsChecked is true)
  81. {
  82. if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
  83. {
  84. return;
  85. }
  86. bool isStick = button.Tag != null && button.Tag.ToString() == "stick";
  87. if (_currentAssigner == null)
  88. {
  89. _currentAssigner = new ButtonKeyAssigner(button);
  90. this.Focus(NavigationMethod.Pointer);
  91. PointerPressed += MouseClick;
  92. ControllerInputViewModel viewModel = (DataContext as ControllerInputViewModel);
  93. IKeyboard keyboard =
  94. (IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver
  95. .GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
  96. IButtonAssigner assigner = CreateButtonAssigner(isStick);
  97. _currentAssigner.ButtonAssigned += (sender, e) =>
  98. {
  99. if (e.ButtonValue.HasValue)
  100. {
  101. Button buttonValue = e.ButtonValue.Value;
  102. viewModel.ParentModel.IsModified = true;
  103. switch (button.Name)
  104. {
  105. case "ButtonZl":
  106. viewModel.Config.ButtonZl = buttonValue.AsHidType<GamepadInputId>();
  107. break;
  108. case "ButtonL":
  109. viewModel.Config.ButtonL = buttonValue.AsHidType<GamepadInputId>();
  110. break;
  111. case "ButtonMinus":
  112. viewModel.Config.ButtonMinus = buttonValue.AsHidType<GamepadInputId>();
  113. break;
  114. case "LeftStickButton":
  115. viewModel.Config.LeftStickButton = buttonValue.AsHidType<GamepadInputId>();
  116. break;
  117. case "LeftJoystick":
  118. viewModel.Config.LeftJoystick = buttonValue.AsHidType<StickInputId>();
  119. break;
  120. case "DpadUp":
  121. viewModel.Config.DpadUp = buttonValue.AsHidType<GamepadInputId>();
  122. break;
  123. case "DpadDown":
  124. viewModel.Config.DpadDown = buttonValue.AsHidType<GamepadInputId>();
  125. break;
  126. case "DpadLeft":
  127. viewModel.Config.DpadLeft = buttonValue.AsHidType<GamepadInputId>();
  128. break;
  129. case "DpadRight":
  130. viewModel.Config.DpadRight = buttonValue.AsHidType<GamepadInputId>();
  131. break;
  132. case "LeftButtonSr":
  133. viewModel.Config.LeftButtonSr = buttonValue.AsHidType<GamepadInputId>();
  134. break;
  135. case "LeftButtonSl":
  136. viewModel.Config.LeftButtonSl = buttonValue.AsHidType<GamepadInputId>();
  137. break;
  138. case "RightButtonSr":
  139. viewModel.Config.RightButtonSr = buttonValue.AsHidType<GamepadInputId>();
  140. break;
  141. case "RightButtonSl":
  142. viewModel.Config.RightButtonSl = buttonValue.AsHidType<GamepadInputId>();
  143. break;
  144. case "ButtonZr":
  145. viewModel.Config.ButtonZr = buttonValue.AsHidType<GamepadInputId>();
  146. break;
  147. case "ButtonR":
  148. viewModel.Config.ButtonR = buttonValue.AsHidType<GamepadInputId>();
  149. break;
  150. case "ButtonPlus":
  151. viewModel.Config.ButtonPlus = buttonValue.AsHidType<GamepadInputId>();
  152. break;
  153. case "ButtonA":
  154. viewModel.Config.ButtonA = buttonValue.AsHidType<GamepadInputId>();
  155. break;
  156. case "ButtonB":
  157. viewModel.Config.ButtonB = buttonValue.AsHidType<GamepadInputId>();
  158. break;
  159. case "ButtonX":
  160. viewModel.Config.ButtonX = buttonValue.AsHidType<GamepadInputId>();
  161. break;
  162. case "ButtonY":
  163. viewModel.Config.ButtonY = buttonValue.AsHidType<GamepadInputId>();
  164. break;
  165. case "RightStickButton":
  166. viewModel.Config.RightStickButton = buttonValue.AsHidType<GamepadInputId>();
  167. break;
  168. case "RightJoystick":
  169. viewModel.Config.RightJoystick = buttonValue.AsHidType<StickInputId>();
  170. break;
  171. }
  172. }
  173. };
  174. _currentAssigner.GetInputAndAssign(assigner, keyboard);
  175. }
  176. else
  177. {
  178. if (_currentAssigner != null)
  179. {
  180. _currentAssigner.Cancel();
  181. _currentAssigner = null;
  182. button.IsChecked = false;
  183. }
  184. }
  185. }
  186. else
  187. {
  188. _currentAssigner?.Cancel();
  189. _currentAssigner = null;
  190. }
  191. }
  192. }
  193. private void MouseClick(object sender, PointerPressedEventArgs e)
  194. {
  195. bool shouldUnbind = e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed;
  196. _currentAssigner?.Cancel(shouldUnbind);
  197. PointerPressed -= MouseClick;
  198. }
  199. private IButtonAssigner CreateButtonAssigner(bool forStick)
  200. {
  201. IButtonAssigner assigner;
  202. ControllerInputViewModel controllerInputViewModel = DataContext as ControllerInputViewModel;
  203. assigner = new GamepadButtonAssigner(
  204. controllerInputViewModel.ParentModel.SelectedGamepad,
  205. (controllerInputViewModel.ParentModel.Config as StandardControllerInputConfig).TriggerThreshold,
  206. forStick);
  207. return assigner;
  208. }
  209. protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
  210. {
  211. base.OnDetachedFromVisualTree(e);
  212. foreach (IGamepad gamepad in RyujinxApp.MainWindow.InputManager.GamepadDriver.GetGamepads())
  213. {
  214. gamepad?.ClearLed();
  215. }
  216. _currentAssigner?.Cancel();
  217. _currentAssigner = null;
  218. }
  219. private void ColorPickerButton_OnColorChanged(ColorPickerButton sender, ColorButtonColorChangedEventArgs args)
  220. {
  221. if (!args.NewColor.HasValue) return;
  222. if (DataContext is not ControllerInputViewModel cVm) return;
  223. if (!cVm.Config.EnableLedChanging) return;
  224. cVm.ParentModel.SelectedGamepad.SetLed(args.NewColor.Value.ToUInt32());
  225. }
  226. private void ColorPickerButton_OnAttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
  227. {
  228. if (DataContext is not ControllerInputViewModel cVm) return;
  229. if (!cVm.Config.EnableLedChanging) return;
  230. cVm.ParentModel.SelectedGamepad.SetLed(cVm.Config.LedColor.ToUInt32());
  231. }
  232. }
  233. }