ControllerSettingsWindow.axaml.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. using Avalonia.Controls;
  2. using Avalonia.Controls.Primitives;
  3. using Avalonia.Input;
  4. using Avalonia.Interactivity;
  5. using Avalonia.LogicalTree;
  6. using Ryujinx.Ava.Common.Locale;
  7. using Ryujinx.Ava.UI.Controls;
  8. using Ryujinx.Ava.UI.Helpers;
  9. using Ryujinx.Ava.UI.Models;
  10. using Ryujinx.Ava.UI.ViewModels;
  11. using Ryujinx.Common.Configuration.Hid.Controller;
  12. using Ryujinx.Input;
  13. using Ryujinx.Input.Assigner;
  14. using System;
  15. namespace Ryujinx.Ava.UI.Windows
  16. {
  17. public partial class ControllerSettingsWindow : UserControl
  18. {
  19. private bool _dialogOpen;
  20. private ButtonKeyAssigner _currentAssigner;
  21. internal ControllerSettingsViewModel ViewModel { get; set; }
  22. public ControllerSettingsWindow()
  23. {
  24. DataContext = ViewModel = new ControllerSettingsViewModel(this);
  25. InitializeComponent();
  26. foreach (ILogical visual in SettingButtons.GetLogicalDescendants())
  27. {
  28. if (visual is ToggleButton button && !(visual is CheckBox))
  29. {
  30. button.Checked += Button_Checked;
  31. button.Unchecked += Button_Unchecked;
  32. }
  33. }
  34. }
  35. protected override void OnPointerReleased(PointerReleasedEventArgs e)
  36. {
  37. base.OnPointerReleased(e);
  38. if (_currentAssigner != null && _currentAssigner.ToggledButton != null && !_currentAssigner.ToggledButton.IsPointerOver)
  39. {
  40. _currentAssigner.Cancel();
  41. }
  42. }
  43. private void Button_Checked(object sender, RoutedEventArgs e)
  44. {
  45. if (sender is ToggleButton button)
  46. {
  47. if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
  48. {
  49. return;
  50. }
  51. bool isStick = button.Tag != null && button.Tag.ToString() == "stick";
  52. if (_currentAssigner == null && (bool)button.IsChecked)
  53. {
  54. _currentAssigner = new ButtonKeyAssigner(button);
  55. FocusManager.Instance.Focus(this, NavigationMethod.Pointer);
  56. PointerPressed += MouseClick;
  57. IKeyboard keyboard = (IKeyboard)ViewModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
  58. IButtonAssigner assigner = CreateButtonAssigner(isStick);
  59. _currentAssigner.ButtonAssigned += (sender, e) =>
  60. {
  61. if (e.IsAssigned)
  62. {
  63. ViewModel.IsModified = true;
  64. }
  65. };
  66. _currentAssigner.GetInputAndAssign(assigner, keyboard);
  67. }
  68. else
  69. {
  70. if (_currentAssigner != null)
  71. {
  72. ToggleButton oldButton = _currentAssigner.ToggledButton;
  73. _currentAssigner.Cancel();
  74. _currentAssigner = null;
  75. button.IsChecked = false;
  76. }
  77. }
  78. }
  79. }
  80. public void SaveCurrentProfile()
  81. {
  82. ViewModel.Save();
  83. }
  84. private IButtonAssigner CreateButtonAssigner(bool forStick)
  85. {
  86. IButtonAssigner assigner;
  87. var device = ViewModel.Devices[ViewModel.Device];
  88. if (device.Type == DeviceType.Keyboard)
  89. {
  90. assigner = new KeyboardKeyAssigner((IKeyboard)ViewModel.SelectedGamepad);
  91. }
  92. else if (device.Type == DeviceType.Controller)
  93. {
  94. assigner = new GamepadButtonAssigner(ViewModel.SelectedGamepad, (ViewModel.Config as StandardControllerInputConfig).TriggerThreshold, forStick);
  95. }
  96. else
  97. {
  98. throw new Exception("Controller not supported");
  99. }
  100. return assigner;
  101. }
  102. private void Button_Unchecked(object sender, RoutedEventArgs e)
  103. {
  104. _currentAssigner?.Cancel();
  105. _currentAssigner = null;
  106. }
  107. private void MouseClick(object sender, PointerPressedEventArgs e)
  108. {
  109. bool shouldUnbind = false;
  110. if (e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed)
  111. {
  112. shouldUnbind = true;
  113. }
  114. _currentAssigner?.Cancel(shouldUnbind);
  115. PointerPressed -= MouseClick;
  116. }
  117. private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
  118. {
  119. if (ViewModel.IsModified && !_dialogOpen)
  120. {
  121. _dialogOpen = true;
  122. var result = await ContentDialogHelper.CreateConfirmationDialog(
  123. LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmMessage],
  124. LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmSubMessage],
  125. LocaleManager.Instance[LocaleKeys.InputDialogYes],
  126. LocaleManager.Instance[LocaleKeys.InputDialogNo],
  127. LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
  128. if (result == UserResult.Yes)
  129. {
  130. ViewModel.Save();
  131. }
  132. _dialogOpen = false;
  133. ViewModel.IsModified = false;
  134. if (e.AddedItems.Count > 0)
  135. {
  136. var player = (PlayerModel)e.AddedItems[0];
  137. ViewModel.PlayerId = player.Id;
  138. }
  139. }
  140. }
  141. public void Dispose()
  142. {
  143. _currentAssigner?.Cancel();
  144. _currentAssigner = null;
  145. ViewModel.Dispose();
  146. }
  147. }
  148. }