ControllerInputView.axaml.cs 10 KB

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