ControllerSettingsWindow.axaml.cs 6.0 KB

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