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