aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Ryujinx.Ava/Assets/Locales/en_US.json99
-rw-r--r--src/Ryujinx.Ava/Assets/Styles/Styles.xaml5
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs28
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs157
-rw-r--r--src/Ryujinx.Ava/UI/Models/Input/ControllerInputConfig.cs580
-rw-r--r--src/Ryujinx.Ava/UI/Models/Input/KeyboardInputConfig.cs422
-rw-r--r--src/Ryujinx.Ava/UI/Models/InputConfiguration.cs456
-rw-r--r--src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs (renamed from src/Ryujinx.Ava/UI/ViewModels/Input/InputViewModel.cs)93
-rw-r--r--src/Ryujinx.Ava/UI/ViewModels/Input/ControllerInputViewModel.cs84
-rw-r--r--src/Ryujinx.Ava/UI/ViewModels/Input/KeyboardInputViewModel.cs73
-rw-r--r--src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs (renamed from src/Ryujinx.Ava/UI/ViewModels/Input/MotionInputViewModel.cs)2
-rw-r--r--src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs (renamed from src/Ryujinx.Ava/UI/ViewModels/Input/RumbleInputViewModel.cs)2
-rw-r--r--src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml616
-rw-r--r--src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs160
-rw-r--r--src/Ryujinx.Ava/UI/Views/Input/InputView.axaml225
-rw-r--r--src/Ryujinx.Ava/UI/Views/Input/InputView.axaml.cs61
-rw-r--r--src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml675
-rw-r--r--src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml.cs210
-rw-r--r--src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml2
-rw-r--r--src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs8
-rw-r--r--src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml2
-rw-r--r--src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs8
-rw-r--r--src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml4
-rw-r--r--src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs2
-rw-r--r--src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs2
-rw-r--r--src/Ryujinx.Input/Assigner/GamepadButtonAssigner.cs6
-rw-r--r--src/Ryujinx.Input/Assigner/IButtonAssigner.cs2
-rw-r--r--src/Ryujinx.Input/Assigner/KeyboardKeyAssigner.cs10
-rw-r--r--src/Ryujinx.Input/ButtonValue.cs48
-rw-r--r--src/Ryujinx/Ui/Windows/ControllerWindow.cs2
30 files changed, 1140 insertions, 2904 deletions
diff --git a/src/Ryujinx.Ava/Assets/Locales/en_US.json b/src/Ryujinx.Ava/Assets/Locales/en_US.json
index fc65fe4a0..a67b796bd 100644
--- a/src/Ryujinx.Ava/Assets/Locales/en_US.json
+++ b/src/Ryujinx.Ava/Assets/Locales/en_US.json
@@ -263,105 +263,6 @@
263 "ControllerSettingsMotionGyroDeadzone": "Gyro Deadzone:", 263 "ControllerSettingsMotionGyroDeadzone": "Gyro Deadzone:",
264 "ControllerSettingsSave": "Save", 264 "ControllerSettingsSave": "Save",
265 "ControllerSettingsClose": "Close", 265 "ControllerSettingsClose": "Close",
266 "KeyUnknown": "Unknown",
267 "KeyShiftLeft": "Shift Left",
268 "KeyShiftRight": "Shift Right",
269 "KeyControlLeft": "Control Left",
270 "KeyControlRight": "Control Right",
271 "KeyAltLeft": "Alt Left",
272 "KeyAltRight": "Alt Right",
273 "KeyOptLeft": "⌥ Left",
274 "KeyOptRight": "⌥ Right",
275 "KeyWinLeft": "⊞ Left",
276 "KeyWinRight": "⊞ Right",
277 "KeyCmdLeft": "⌘ Left",
278 "KeyCmdRight": "⌘ Right",
279 "KeyMenu": "Menu",
280 "KeyUp": "Up",
281 "KeyDown": "Down",
282 "KeyLeft": "Left",
283 "KeyRight": "Right",
284 "KeyEnter": "Enter",
285 "KeyEscape": "Escape",
286 "KeySpace": "Space",
287 "KeyTab": "Tab",
288 "KeyBackSpace": "Backspace",
289 "KeyInsert": "Insert",
290 "KeyDelete": "Delete",
291 "KeyPageUp": "Page Up",
292 "KeyPageDown": "Page Down",
293 "KeyHome": "Home",
294 "KeyEnd": "End",
295 "KeyCapsLock": "Caps Lock",
296 "KeyScrollLock": "Scroll Lock",
297 "KeyPrintScreen": "Print Screen",
298 "KeyPause": "Pause",
299 "KeyNumLock": "Num Lock",
300 "KeyClear": "Clear",
301 "KeyKeypad0": "Keypad 0",
302 "KeyKeypad1": "Keypad 1",
303 "KeyKeypad2": "Keypad 2",
304 "KeyKeypad3": "Keypad 3",
305 "KeyKeypad4": "Keypad 4",
306 "KeyKeypad5": "Keypad 5",
307 "KeyKeypad6": "Keypad 6",
308 "KeyKeypad7": "Keypad 7",
309 "KeyKeypad8": "Keypad 8",
310 "KeyKeypad9": "Keypad 9",
311 "KeyKeypadDivide": "Keypad Divide",
312 "KeyKeypadMultiply": "Keypad Multiply",
313 "KeyKeypadSubtract": "Keypad Subtract",
314 "KeyKeypadAdd": "Keypad Add",
315 "KeyKeypadDecimal": "Keypad Decimal",
316 "KeyKeypadEnter": "Keypad Enter",
317 "KeyNumber0": "0",
318 "KeyNumber1": "1",
319 "KeyNumber2": "2",
320 "KeyNumber3": "3",
321 "KeyNumber4": "4",
322 "KeyNumber5": "5",
323 "KeyNumber6": "6",
324 "KeyNumber7": "7",
325 "KeyNumber8": "8",
326 "KeyNumber9": "9",
327 "KeyTilde": "~",
328 "KeyGrave": "`",
329 "KeyMinus": "-",
330 "KeyPlus": "+",
331 "KeyBracketLeft": "[",
332 "KeyBracketRight": "]",
333 "KeySemicolon": ";",
334 "KeyQuote": "\"",
335 "KeyComma": ",",
336 "KeyPeriod": ".",
337 "KeySlash": "/",
338 "KeyBackSlash": "\\",
339 "KeyUnbound": "Unbound",
340 "GamepadLeftStick": "Left Stick Button",
341 "GamepadRightStick": "Right Stick Button",
342 "GamepadLeftShoulder": "Left Shoulder",
343 "GamepadRightShoulder": "Right Shoulder",
344 "GamepadLeftTrigger": "Left Trigger",
345 "GamepadRightTrigger": "Right Trigger",
346 "GamepadDpadUp": "Up",
347 "GamepadDpadDown": "Down",
348 "GamepadDpadLeft": "Left",
349 "GamepadDpadRight": "Right",
350 "GamepadMinus": "-",
351 "GamepadPlus": "+",
352 "GamepadGuide": "Guide",
353 "GamepadMisc1": "Misc",
354 "GamepadPaddle1": "Paddle 1",
355 "GamepadPaddle2": "Paddle 2",
356 "GamepadPaddle3": "Paddle 3",
357 "GamepadPaddle4": "Paddle 4",
358 "GamepadTouchpad": "Touchpad",
359 "GamepadSingleLeftTrigger0": "Left Trigger 0",
360 "GamepadSingleRightTrigger0": "Right Trigger 0",
361 "GamepadSingleLeftTrigger1": "Left Trigger 1",
362 "GamepadSingleRightTrigger1": "Right Trigger 1",
363 "StickLeft": "Left Stick",
364 "StickRight": "Right Stick",
365 "UserProfilesSelectedUserProfile": "Selected User Profile:", 266 "UserProfilesSelectedUserProfile": "Selected User Profile:",
366 "UserProfilesSaveProfileName": "Save Profile Name", 267 "UserProfilesSaveProfileName": "Save Profile Name",
367 "UserProfilesChangeProfileImage": "Change Profile Image", 268 "UserProfilesChangeProfileImage": "Change Profile Image",
diff --git a/src/Ryujinx.Ava/Assets/Styles/Styles.xaml b/src/Ryujinx.Ava/Assets/Styles/Styles.xaml
index b3a6f59c8..f7f64be22 100644
--- a/src/Ryujinx.Ava/Assets/Styles/Styles.xaml
+++ b/src/Ryujinx.Ava/Assets/Styles/Styles.xaml
@@ -15,7 +15,8 @@
15 <MenuItem Header="Test 2" /> 15 <MenuItem Header="Test 2" />
16 <MenuItem Header="Test 3"> 16 <MenuItem Header="Test 3">
17 <MenuItem.Icon> 17 <MenuItem.Icon>
18 <CheckBox Margin="0" /> 18 <CheckBox Margin="0"
19 IsChecked="{ReflectionBinding Checkbox, Mode=TwoWay}" />
19 </MenuItem.Icon> 20 </MenuItem.Icon>
20 </MenuItem> 21 </MenuItem>
21 </MenuItem> 22 </MenuItem>
@@ -392,4 +393,4 @@
392 <x:Double x:Key="ContentDialogMaxWidth">600</x:Double> 393 <x:Double x:Key="ContentDialogMaxWidth">600</x:Double>
393 <x:Double x:Key="ContentDialogMaxHeight">756</x:Double> 394 <x:Double x:Key="ContentDialogMaxHeight">756</x:Double>
394 </Styles.Resources> 395 </Styles.Resources>
395</Styles> 396</Styles> \ No newline at end of file
diff --git a/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs b/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs
index 54e0918a5..7e8ba7342 100644
--- a/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs
+++ b/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs
@@ -1,8 +1,11 @@
1using Avalonia.Controls;
1using Avalonia.Controls.Primitives; 2using Avalonia.Controls.Primitives;
3using Avalonia.LogicalTree;
2using Avalonia.Threading; 4using Avalonia.Threading;
3using Ryujinx.Input; 5using Ryujinx.Input;
4using Ryujinx.Input.Assigner; 6using Ryujinx.Input.Assigner;
5using System; 7using System;
8using System.Linq;
6using System.Threading.Tasks; 9using System.Threading.Tasks;
7 10
8namespace Ryujinx.Ava.UI.Helpers 11namespace Ryujinx.Ava.UI.Helpers
@@ -12,12 +15,12 @@ namespace Ryujinx.Ava.UI.Helpers
12 internal class ButtonAssignedEventArgs : EventArgs 15 internal class ButtonAssignedEventArgs : EventArgs
13 { 16 {
14 public ToggleButton Button { get; } 17 public ToggleButton Button { get; }
15 public ButtonValue? ButtonValue { get; } 18 public bool IsAssigned { get; }
16 19
17 public ButtonAssignedEventArgs(ToggleButton button, ButtonValue? buttonValue) 20 public ButtonAssignedEventArgs(ToggleButton button, bool isAssigned)
18 { 21 {
19 Button = button; 22 Button = button;
20 ButtonValue = buttonValue; 23 IsAssigned = isAssigned;
21 } 24 }
22 } 25 }
23 26
@@ -75,11 +78,15 @@ namespace Ryujinx.Ava.UI.Helpers
75 78
76 await Dispatcher.UIThread.InvokeAsync(() => 79 await Dispatcher.UIThread.InvokeAsync(() =>
77 { 80 {
78 ButtonValue? pressedButton = assigner.GetPressedButton(); 81 string pressedButton = assigner.GetPressedButton();
79 82
80 if (_shouldUnbind) 83 if (_shouldUnbind)
81 { 84 {
82 pressedButton = null; 85 SetButtonText(ToggledButton, "Unbound");
86 }
87 else if (pressedButton != "")
88 {
89 SetButtonText(ToggledButton, pressedButton);
83 } 90 }
84 91
85 _shouldUnbind = false; 92 _shouldUnbind = false;
@@ -87,8 +94,17 @@ namespace Ryujinx.Ava.UI.Helpers
87 94
88 ToggledButton.IsChecked = false; 95 ToggledButton.IsChecked = false;
89 96
90 ButtonAssigned?.Invoke(this, new ButtonAssignedEventArgs(ToggledButton, pressedButton)); 97 ButtonAssigned?.Invoke(this, new ButtonAssignedEventArgs(ToggledButton, pressedButton != null));
98
99 static void SetButtonText(ToggleButton button, string text)
100 {
101 ILogical textBlock = button.GetLogicalDescendants().First(x => x is TextBlock);
91 102
103 if (textBlock != null && textBlock is TextBlock block)
104 {
105 block.Text = text;
106 }
107 }
92 }); 108 });
93 } 109 }
94 110
diff --git a/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs b/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs
index 1c4aa7b21..028ed6bf4 100644
--- a/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs
+++ b/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs
@@ -1,9 +1,7 @@
1using Avalonia.Data.Converters; 1using Avalonia.Data.Converters;
2using Ryujinx.Ava.Common.Locale;
3using Ryujinx.Common.Configuration.Hid; 2using Ryujinx.Common.Configuration.Hid;
4using Ryujinx.Common.Configuration.Hid.Controller; 3using Ryujinx.Common.Configuration.Hid.Controller;
5using System; 4using System;
6using System.Collections.Generic;
7using System.Globalization; 5using System.Globalization;
8 6
9namespace Ryujinx.Ava.UI.Helpers 7namespace Ryujinx.Ava.UI.Helpers
@@ -12,158 +10,37 @@ namespace Ryujinx.Ava.UI.Helpers
12 { 10 {
13 public static KeyValueConverter Instance = new(); 11 public static KeyValueConverter Instance = new();
14 12
15 private static readonly Dictionary<Key, LocaleKeys> _keysMap = new() 13 public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
16 {
17 { Key.Unknown, LocaleKeys.KeyUnknown },
18 { Key.ShiftLeft, LocaleKeys.KeyShiftLeft },
19 { Key.ShiftRight, LocaleKeys.KeyShiftRight },
20 { Key.ControlLeft, LocaleKeys.KeyControlLeft },
21 { Key.ControlRight, LocaleKeys.KeyControlRight },
22 { Key.AltLeft, OperatingSystem.IsMacOS() ? LocaleKeys.KeyOptLeft : LocaleKeys.KeyAltLeft },
23 { Key.AltRight, OperatingSystem.IsMacOS() ? LocaleKeys.KeyOptRight : LocaleKeys.KeyAltRight },
24 { Key.WinLeft, OperatingSystem.IsMacOS() ? LocaleKeys.KeyCmdLeft : LocaleKeys.KeyWinLeft },
25 { Key.WinRight, OperatingSystem.IsMacOS() ? LocaleKeys.KeyCmdRight : LocaleKeys.KeyWinRight },
26 { Key.Up, LocaleKeys.KeyUp },
27 { Key.Down, LocaleKeys.KeyDown },
28 { Key.Left, LocaleKeys.KeyLeft },
29 { Key.Right, LocaleKeys.KeyRight },
30 { Key.Enter, LocaleKeys.KeyEnter },
31 { Key.Escape, LocaleKeys.KeyEscape },
32 { Key.Space, LocaleKeys.KeySpace },
33 { Key.Tab, LocaleKeys.KeyTab },
34 { Key.BackSpace, LocaleKeys.KeyBackSpace },
35 { Key.Insert, LocaleKeys.KeyInsert },
36 { Key.Delete, LocaleKeys.KeyDelete },
37 { Key.PageUp, LocaleKeys.KeyPageUp },
38 { Key.PageDown, LocaleKeys.KeyPageDown },
39 { Key.Home, LocaleKeys.KeyHome },
40 { Key.End, LocaleKeys.KeyEnd },
41 { Key.CapsLock, LocaleKeys.KeyCapsLock },
42 { Key.ScrollLock, LocaleKeys.KeyScrollLock },
43 { Key.PrintScreen, LocaleKeys.KeyPrintScreen },
44 { Key.Pause, LocaleKeys.KeyPause },
45 { Key.NumLock, LocaleKeys.KeyNumLock },
46 { Key.Clear, LocaleKeys.KeyClear },
47 { Key.Keypad0, LocaleKeys.KeyKeypad0 },
48 { Key.Keypad1, LocaleKeys.KeyKeypad1 },
49 { Key.Keypad2, LocaleKeys.KeyKeypad2 },
50 { Key.Keypad3, LocaleKeys.KeyKeypad3 },
51 { Key.Keypad4, LocaleKeys.KeyKeypad4 },
52 { Key.Keypad5, LocaleKeys.KeyKeypad5 },
53 { Key.Keypad6, LocaleKeys.KeyKeypad6 },
54 { Key.Keypad7, LocaleKeys.KeyKeypad7 },
55 { Key.Keypad8, LocaleKeys.KeyKeypad8 },
56 { Key.Keypad9, LocaleKeys.KeyKeypad9 },
57 { Key.KeypadDivide, LocaleKeys.KeyKeypadDivide },
58 { Key.KeypadMultiply, LocaleKeys.KeyKeypadMultiply },
59 { Key.KeypadSubtract, LocaleKeys.KeyKeypadSubtract },
60 { Key.KeypadAdd, LocaleKeys.KeyKeypadAdd },
61 { Key.KeypadDecimal, LocaleKeys.KeyKeypadDecimal },
62 { Key.KeypadEnter, LocaleKeys.KeyKeypadEnter },
63 { Key.Number0, LocaleKeys.KeyNumber0 },
64 { Key.Number1, LocaleKeys.KeyNumber1 },
65 { Key.Number2, LocaleKeys.KeyNumber2 },
66 { Key.Number3, LocaleKeys.KeyNumber3 },
67 { Key.Number4, LocaleKeys.KeyNumber4 },
68 { Key.Number5, LocaleKeys.KeyNumber5 },
69 { Key.Number6, LocaleKeys.KeyNumber6 },
70 { Key.Number7, LocaleKeys.KeyNumber7 },
71 { Key.Number8, LocaleKeys.KeyNumber8 },
72 { Key.Number9, LocaleKeys.KeyNumber9 },
73 { Key.Tilde, LocaleKeys.KeyTilde },
74 { Key.Grave, LocaleKeys.KeyGrave },
75 { Key.Minus, LocaleKeys.KeyMinus },
76 { Key.Plus, LocaleKeys.KeyPlus },
77 { Key.BracketLeft, LocaleKeys.KeyBracketLeft },
78 { Key.BracketRight, LocaleKeys.KeyBracketRight },
79 { Key.Semicolon, LocaleKeys.KeySemicolon },
80 { Key.Quote, LocaleKeys.KeyQuote },
81 { Key.Comma, LocaleKeys.KeyComma },
82 { Key.Period, LocaleKeys.KeyPeriod },
83 { Key.Slash, LocaleKeys.KeySlash },
84 { Key.BackSlash, LocaleKeys.KeyBackSlash },
85 { Key.Unbound, LocaleKeys.KeyUnbound },
86 };
87
88 private static readonly Dictionary<GamepadInputId, LocaleKeys> _gamepadInputIdMap = new()
89 { 14 {
90 { GamepadInputId.LeftStick, LocaleKeys.GamepadLeftStick }, 15 if (value == null)
91 { GamepadInputId.RightStick, LocaleKeys.GamepadRightStick }, 16 {
92 { GamepadInputId.LeftShoulder, LocaleKeys.GamepadLeftShoulder }, 17 return null;
93 { GamepadInputId.RightShoulder, LocaleKeys.GamepadRightShoulder }, 18 }
94 { GamepadInputId.LeftTrigger, LocaleKeys.GamepadLeftTrigger },
95 { GamepadInputId.RightTrigger, LocaleKeys.GamepadRightTrigger },
96 { GamepadInputId.DpadUp, LocaleKeys.GamepadDpadUp},
97 { GamepadInputId.DpadDown, LocaleKeys.GamepadDpadDown},
98 { GamepadInputId.DpadLeft, LocaleKeys.GamepadDpadLeft},
99 { GamepadInputId.DpadRight, LocaleKeys.GamepadDpadRight},
100 { GamepadInputId.Minus, LocaleKeys.GamepadMinus},
101 { GamepadInputId.Plus, LocaleKeys.GamepadPlus},
102 { GamepadInputId.Guide, LocaleKeys.GamepadGuide},
103 { GamepadInputId.Misc1, LocaleKeys.GamepadMisc1},
104 { GamepadInputId.Paddle1, LocaleKeys.GamepadPaddle1},
105 { GamepadInputId.Paddle2, LocaleKeys.GamepadPaddle2},
106 { GamepadInputId.Paddle3, LocaleKeys.GamepadPaddle3},
107 { GamepadInputId.Paddle4, LocaleKeys.GamepadPaddle4},
108 { GamepadInputId.Touchpad, LocaleKeys.GamepadTouchpad},
109 { GamepadInputId.SingleLeftTrigger0, LocaleKeys.GamepadSingleLeftTrigger0},
110 { GamepadInputId.SingleRightTrigger0, LocaleKeys.GamepadSingleRightTrigger0},
111 { GamepadInputId.SingleLeftTrigger1, LocaleKeys.GamepadSingleLeftTrigger1},
112 { GamepadInputId.SingleRightTrigger1, LocaleKeys.GamepadSingleRightTrigger1},
113 { GamepadInputId.Unbound, LocaleKeys.KeyUnbound},
114 };
115 19
116 private static readonly Dictionary<StickInputId, LocaleKeys> _stickInputIdMap = new() 20 return value.ToString();
117 { 21 }
118 { StickInputId.Left, LocaleKeys.StickLeft},
119 { StickInputId.Right, LocaleKeys.StickRight},
120 { StickInputId.Unbound, LocaleKeys.KeyUnbound},
121 };
122 22
123 public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 23 public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
124 { 24 {
125 string keyString = ""; 25 object key = null;
126 26
127 if (value is Key key) 27 if (value != null)
128 { 28 {
129 if (_keysMap.TryGetValue(key, out LocaleKeys localeKey)) 29 if (targetType == typeof(Key))
130 { 30 {
131 keyString = LocaleManager.Instance[localeKey]; 31 key = Enum.Parse<Key>(value.ToString());
132 } 32 }
133 else 33 else if (targetType == typeof(GamepadInputId))
134 { 34 {
135 keyString = key.ToString(); 35 key = Enum.Parse<GamepadInputId>(value.ToString());
136 } 36 }
137 } 37 else if (targetType == typeof(StickInputId))
138 else if (value is GamepadInputId gamepadInputId)
139 {
140 if (_gamepadInputIdMap.TryGetValue(gamepadInputId, out LocaleKeys localeKey))
141 { 38 {
142 keyString = LocaleManager.Instance[localeKey]; 39 key = Enum.Parse<StickInputId>(value.ToString());
143 }
144 else
145 {
146 keyString = gamepadInputId.ToString();
147 } 40 }
148 } 41 }
149 else if (value is StickInputId stickInputId)
150 {
151 if (_stickInputIdMap.TryGetValue(stickInputId, out LocaleKeys localeKey))
152 {
153 keyString = LocaleManager.Instance[localeKey];
154 }
155 else
156 {
157 keyString = stickInputId.ToString();
158 }
159 }
160
161 return keyString;
162 }
163 42
164 public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 43 return key;
165 {
166 throw new NotSupportedException();
167 } 44 }
168 } 45 }
169} 46}
diff --git a/src/Ryujinx.Ava/UI/Models/Input/ControllerInputConfig.cs b/src/Ryujinx.Ava/UI/Models/Input/ControllerInputConfig.cs
deleted file mode 100644
index 4929e582e..000000000
--- a/src/Ryujinx.Ava/UI/Models/Input/ControllerInputConfig.cs
+++ /dev/null
@@ -1,580 +0,0 @@
1using Ryujinx.Ava.UI.ViewModels;
2using Ryujinx.Common.Configuration.Hid;
3using Ryujinx.Common.Configuration.Hid.Controller;
4using Ryujinx.Common.Configuration.Hid.Controller.Motion;
5using System;
6
7namespace Ryujinx.Ava.UI.Models.Input
8{
9 public class ControllerInputConfig : BaseModel
10 {
11 public bool EnableCemuHookMotion { get; set; }
12 public string DsuServerHost { get; set; }
13 public int DsuServerPort { get; set; }
14 public int Slot { get; set; }
15 public int AltSlot { get; set; }
16 public bool MirrorInput { get; set; }
17 public int Sensitivity { get; set; }
18 public double GyroDeadzone { get; set; }
19
20 public float WeakRumble { get; set; }
21 public float StrongRumble { get; set; }
22
23 public string Id { get; set; }
24 public ControllerType ControllerType { get; set; }
25 public PlayerIndex PlayerIndex { get; set; }
26
27 private StickInputId _leftJoystick;
28 public StickInputId LeftJoystick
29 {
30 get => _leftJoystick;
31 set
32 {
33 _leftJoystick = value;
34 OnPropertyChanged();
35 }
36 }
37
38 private bool _leftInvertStickX;
39 public bool LeftInvertStickX
40 {
41 get => _leftInvertStickX;
42 set
43 {
44 _leftInvertStickX = value;
45 OnPropertyChanged();
46 }
47 }
48
49 private bool _leftInvertStickY;
50 public bool LeftInvertStickY
51 {
52 get => _leftInvertStickY;
53 set
54 {
55 _leftInvertStickY = value;
56 OnPropertyChanged();
57 }
58 }
59
60 private bool _leftRotate90;
61 public bool LeftRotate90
62 {
63 get => _leftRotate90;
64 set
65 {
66 _leftRotate90 = value;
67 OnPropertyChanged();
68 }
69 }
70
71 private GamepadInputId _leftStickButton;
72 public GamepadInputId LeftStickButton
73 {
74 get => _leftStickButton;
75 set
76 {
77 _leftStickButton = value;
78 OnPropertyChanged();
79 }
80 }
81
82 private StickInputId _rightJoystick;
83 public StickInputId RightJoystick
84 {
85 get => _rightJoystick;
86 set
87 {
88 _rightJoystick = value;
89 OnPropertyChanged();
90 }
91 }
92
93 private bool _rightInvertStickX;
94 public bool RightInvertStickX
95 {
96 get => _rightInvertStickX;
97 set
98 {
99 _rightInvertStickX = value;
100 OnPropertyChanged();
101 }
102 }
103
104 private bool _rightInvertStickY;
105 public bool RightInvertStickY
106 {
107 get => _rightInvertStickY;
108 set
109 {
110 _rightInvertStickY = value;
111 OnPropertyChanged();
112 }
113 }
114
115 private bool _rightRotate90;
116 public bool RightRotate90
117 {
118 get => _rightRotate90;
119 set
120 {
121 _rightRotate90 = value;
122 OnPropertyChanged();
123 }
124 }
125
126 private GamepadInputId _rightStickButton;
127 public GamepadInputId RightStickButton
128 {
129 get => _rightStickButton;
130 set
131 {
132 _rightStickButton = value;
133 OnPropertyChanged();
134 }
135 }
136
137 private GamepadInputId _dpadUp;
138 public GamepadInputId DpadUp
139 {
140 get => _dpadUp;
141 set
142 {
143 _dpadUp = value;
144 OnPropertyChanged();
145 }
146 }
147
148 private GamepadInputId _dpadDown;
149 public GamepadInputId DpadDown
150 {
151 get => _dpadDown;
152 set
153 {
154 _dpadDown = value;
155 OnPropertyChanged();
156 }
157 }
158
159 private GamepadInputId _dpadLeft;
160 public GamepadInputId DpadLeft
161 {
162 get => _dpadLeft;
163 set
164 {
165 _dpadLeft = value;
166 OnPropertyChanged();
167 }
168 }
169
170 private GamepadInputId _dpadRight;
171 public GamepadInputId DpadRight
172 {
173 get => _dpadRight;
174 set
175 {
176 _dpadRight = value;
177 OnPropertyChanged();
178 }
179 }
180
181 private GamepadInputId _buttonL;
182 public GamepadInputId ButtonL
183 {
184 get => _buttonL;
185 set
186 {
187 _buttonL = value;
188 OnPropertyChanged();
189 }
190 }
191
192 private GamepadInputId _buttonMinus;
193 public GamepadInputId ButtonMinus
194 {
195 get => _buttonMinus;
196 set
197 {
198 _buttonMinus = value;
199 OnPropertyChanged();
200 }
201 }
202
203 private GamepadInputId _leftButtonSl;
204 public GamepadInputId LeftButtonSl
205 {
206 get => _leftButtonSl;
207 set
208 {
209 _leftButtonSl = value;
210 OnPropertyChanged();
211 }
212 }
213
214 private GamepadInputId _leftButtonSr;
215 public GamepadInputId LeftButtonSr
216 {
217 get => _leftButtonSr;
218 set
219 {
220 _leftButtonSr = value;
221 OnPropertyChanged();
222 }
223 }
224
225 private GamepadInputId _buttonZl;
226 public GamepadInputId ButtonZl
227 {
228 get => _buttonZl;
229 set
230 {
231 _buttonZl = value;
232 OnPropertyChanged();
233 }
234 }
235
236 private GamepadInputId _buttonA;
237 public GamepadInputId ButtonA
238 {
239 get => _buttonA;
240 set
241 {
242 _buttonA = value;
243 OnPropertyChanged();
244 }
245 }
246
247 private GamepadInputId _buttonB;
248 public GamepadInputId ButtonB
249 {
250 get => _buttonB;
251 set
252 {
253 _buttonB = value;
254 OnPropertyChanged();
255 }
256 }
257
258 private GamepadInputId _buttonX;
259 public GamepadInputId ButtonX
260 {
261 get => _buttonX;
262 set
263 {
264 _buttonX = value;
265 OnPropertyChanged();
266 }
267 }
268
269 private GamepadInputId _buttonY;
270 public GamepadInputId ButtonY
271 {
272 get => _buttonY;
273 set
274 {
275 _buttonY = value;
276 OnPropertyChanged();
277 }
278 }
279
280 private GamepadInputId _buttonR;
281 public GamepadInputId ButtonR
282 {
283 get => _buttonR;
284 set
285 {
286 _buttonR = value;
287 OnPropertyChanged();
288 }
289 }
290
291 private GamepadInputId _buttonPlus;
292 public GamepadInputId ButtonPlus
293 {
294 get => _buttonPlus;
295 set
296 {
297 _buttonPlus = value;
298 OnPropertyChanged();
299 }
300 }
301
302 private GamepadInputId _rightButtonSl;
303 public GamepadInputId RightButtonSl
304 {
305 get => _rightButtonSl;
306 set
307 {
308 _rightButtonSl = value;
309 OnPropertyChanged();
310 }
311 }
312
313 private GamepadInputId _rightButtonSr;
314 public GamepadInputId RightButtonSr
315 {
316 get => _rightButtonSr;
317 set
318 {
319 _rightButtonSr = value;
320 OnPropertyChanged();
321 }
322 }
323
324 private GamepadInputId _buttonZr;
325 public GamepadInputId ButtonZr
326 {
327 get => _buttonZr;
328 set
329 {
330 _buttonZr = value;
331 OnPropertyChanged();
332 }
333 }
334
335 private float _deadzoneLeft;
336 public float DeadzoneLeft
337 {
338 get => _deadzoneLeft;
339 set
340 {
341 _deadzoneLeft = MathF.Round(value, 3);
342 OnPropertyChanged();
343 }
344 }
345
346 private float _deadzoneRight;
347 public float DeadzoneRight
348 {
349 get => _deadzoneRight;
350 set
351 {
352 _deadzoneRight = MathF.Round(value, 3);
353 OnPropertyChanged();
354 }
355 }
356
357 private float _rangeLeft;
358 public float RangeLeft
359 {
360 get => _rangeLeft;
361 set
362 {
363 _rangeLeft = MathF.Round(value, 3);
364 OnPropertyChanged();
365 }
366 }
367
368 private float _rangeRight;
369 public float RangeRight
370 {
371 get => _rangeRight;
372 set
373 {
374 _rangeRight = MathF.Round(value, 3);
375 OnPropertyChanged();
376 }
377 }
378
379 private float _triggerThreshold;
380 public float TriggerThreshold
381 {
382 get => _triggerThreshold;
383 set
384 {
385 _triggerThreshold = MathF.Round(value, 3);
386 OnPropertyChanged();
387 }
388 }
389
390 private bool _enableMotion;
391 public bool EnableMotion
392 {
393 get => _enableMotion;
394 set
395 {
396 _enableMotion = value;
397 OnPropertyChanged();
398 }
399 }
400
401 private bool _enableRumble;
402 public bool EnableRumble
403 {
404 get => _enableRumble;
405 set
406 {
407 _enableRumble = value;
408 OnPropertyChanged();
409 }
410 }
411
412 public ControllerInputConfig(InputConfig config)
413 {
414 if (config != null)
415 {
416 Id = config.Id;
417 ControllerType = config.ControllerType;
418 PlayerIndex = config.PlayerIndex;
419
420 if (config is not StandardControllerInputConfig controllerInput)
421 {
422 return;
423 }
424
425 LeftJoystick = controllerInput.LeftJoyconStick.Joystick;
426 LeftInvertStickX = controllerInput.LeftJoyconStick.InvertStickX;
427 LeftInvertStickY = controllerInput.LeftJoyconStick.InvertStickY;
428 LeftRotate90 = controllerInput.LeftJoyconStick.Rotate90CW;
429 LeftStickButton = controllerInput.LeftJoyconStick.StickButton;
430
431 RightJoystick = controllerInput.RightJoyconStick.Joystick;
432 RightInvertStickX = controllerInput.RightJoyconStick.InvertStickX;
433 RightInvertStickY = controllerInput.RightJoyconStick.InvertStickY;
434 RightRotate90 = controllerInput.RightJoyconStick.Rotate90CW;
435 RightStickButton = controllerInput.RightJoyconStick.StickButton;
436
437 DpadUp = controllerInput.LeftJoycon.DpadUp;
438 DpadDown = controllerInput.LeftJoycon.DpadDown;
439 DpadLeft = controllerInput.LeftJoycon.DpadLeft;
440 DpadRight = controllerInput.LeftJoycon.DpadRight;
441 ButtonL = controllerInput.LeftJoycon.ButtonL;
442 ButtonMinus = controllerInput.LeftJoycon.ButtonMinus;
443 LeftButtonSl = controllerInput.LeftJoycon.ButtonSl;
444 LeftButtonSr = controllerInput.LeftJoycon.ButtonSr;
445 ButtonZl = controllerInput.LeftJoycon.ButtonZl;
446
447 ButtonA = controllerInput.RightJoycon.ButtonA;
448 ButtonB = controllerInput.RightJoycon.ButtonB;
449 ButtonX = controllerInput.RightJoycon.ButtonX;
450 ButtonY = controllerInput.RightJoycon.ButtonY;
451 ButtonR = controllerInput.RightJoycon.ButtonR;
452 ButtonPlus = controllerInput.RightJoycon.ButtonPlus;
453 RightButtonSl = controllerInput.RightJoycon.ButtonSl;
454 RightButtonSr = controllerInput.RightJoycon.ButtonSr;
455 ButtonZr = controllerInput.RightJoycon.ButtonZr;
456
457 DeadzoneLeft = controllerInput.DeadzoneLeft;
458 DeadzoneRight = controllerInput.DeadzoneRight;
459 RangeLeft = controllerInput.RangeLeft;
460 RangeRight = controllerInput.RangeRight;
461 TriggerThreshold = controllerInput.TriggerThreshold;
462
463 if (controllerInput.Motion != null)
464 {
465 EnableMotion = controllerInput.Motion.EnableMotion;
466 GyroDeadzone = controllerInput.Motion.GyroDeadzone;
467 Sensitivity = controllerInput.Motion.Sensitivity;
468
469 if (controllerInput.Motion is CemuHookMotionConfigController cemuHook)
470 {
471 EnableCemuHookMotion = true;
472 DsuServerHost = cemuHook.DsuServerHost;
473 DsuServerPort = cemuHook.DsuServerPort;
474 Slot = cemuHook.Slot;
475 AltSlot = cemuHook.AltSlot;
476 MirrorInput = cemuHook.MirrorInput;
477 }
478 }
479
480 if (controllerInput.Rumble != null)
481 {
482 EnableRumble = controllerInput.Rumble.EnableRumble;
483 WeakRumble = controllerInput.Rumble.WeakRumble;
484 StrongRumble = controllerInput.Rumble.StrongRumble;
485 }
486 }
487 }
488
489 public InputConfig GetConfig()
490 {
491 var config = new StandardControllerInputConfig
492 {
493 Id = Id,
494 Backend = InputBackendType.GamepadSDL2,
495 PlayerIndex = PlayerIndex,
496 ControllerType = ControllerType,
497 LeftJoycon = new LeftJoyconCommonConfig<GamepadInputId>
498 {
499 DpadUp = DpadUp,
500 DpadDown = DpadDown,
501 DpadLeft = DpadLeft,
502 DpadRight = DpadRight,
503 ButtonL = ButtonL,
504 ButtonMinus = ButtonMinus,
505 ButtonSl = LeftButtonSl,
506 ButtonSr = LeftButtonSr,
507 ButtonZl = ButtonZl
508 },
509 RightJoycon = new RightJoyconCommonConfig<GamepadInputId>
510 {
511 ButtonA = ButtonA,
512 ButtonB = ButtonB,
513 ButtonX = ButtonX,
514 ButtonY = ButtonY,
515 ButtonPlus = ButtonPlus,
516 ButtonSl = RightButtonSl,
517 ButtonSr = RightButtonSr,
518 ButtonR = ButtonR,
519 ButtonZr = ButtonZr
520 },
521 LeftJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
522 {
523 Joystick = LeftJoystick,
524 InvertStickX = LeftInvertStickX,
525 InvertStickY = LeftInvertStickY,
526 Rotate90CW = LeftRotate90,
527 StickButton = LeftStickButton
528 },
529 RightJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
530 {
531 Joystick = RightJoystick,
532 InvertStickX = RightInvertStickX,
533 InvertStickY = RightInvertStickY,
534 Rotate90CW = RightRotate90,
535 StickButton = RightStickButton
536 },
537 Rumble = new RumbleConfigController
538 {
539 EnableRumble = EnableRumble,
540 WeakRumble = WeakRumble,
541 StrongRumble = StrongRumble
542 },
543 Version = InputConfig.CurrentVersion,
544 DeadzoneLeft = DeadzoneLeft,
545 DeadzoneRight = DeadzoneRight,
546 RangeLeft = RangeLeft,
547 RangeRight = RangeRight,
548 TriggerThreshold = TriggerThreshold
549 };
550
551 if (EnableCemuHookMotion)
552 {
553 config.Motion = new CemuHookMotionConfigController
554 {
555 EnableMotion = EnableMotion,
556 MotionBackend = MotionInputBackendType.CemuHook,
557 GyroDeadzone = GyroDeadzone,
558 Sensitivity = Sensitivity,
559 DsuServerHost = DsuServerHost,
560 DsuServerPort = DsuServerPort,
561 Slot = Slot,
562 AltSlot = AltSlot,
563 MirrorInput = MirrorInput
564 };
565 }
566 else
567 {
568 config.Motion = new MotionConfigController
569 {
570 EnableMotion = EnableMotion,
571 MotionBackend = MotionInputBackendType.GamepadDriver,
572 GyroDeadzone = GyroDeadzone,
573 Sensitivity = Sensitivity
574 };
575 }
576
577 return config;
578 }
579 }
580}
diff --git a/src/Ryujinx.Ava/UI/Models/Input/KeyboardInputConfig.cs b/src/Ryujinx.Ava/UI/Models/Input/KeyboardInputConfig.cs
deleted file mode 100644
index 029565210..000000000
--- a/src/Ryujinx.Ava/UI/Models/Input/KeyboardInputConfig.cs
+++ /dev/null
@@ -1,422 +0,0 @@
1using Ryujinx.Ava.UI.ViewModels;
2using Ryujinx.Common.Configuration.Hid;
3using Ryujinx.Common.Configuration.Hid.Keyboard;
4
5namespace Ryujinx.Ava.UI.Models.Input
6{
7 public class KeyboardInputConfig : BaseModel
8 {
9 public string Id { get; set; }
10 public ControllerType ControllerType { get; set; }
11 public PlayerIndex PlayerIndex { get; set; }
12
13 private Key _leftStickUp;
14 public Key LeftStickUp
15 {
16 get => _leftStickUp;
17 set
18 {
19 _leftStickUp = value;
20 OnPropertyChanged();
21 }
22 }
23
24 private Key _leftStickDown;
25 public Key LeftStickDown
26 {
27 get => _leftStickDown;
28 set
29 {
30 _leftStickDown = value;
31 OnPropertyChanged();
32 }
33 }
34
35 private Key _leftStickLeft;
36 public Key LeftStickLeft
37 {
38 get => _leftStickLeft;
39 set
40 {
41 _leftStickLeft = value;
42 OnPropertyChanged();
43 }
44 }
45
46 private Key _leftStickRight;
47 public Key LeftStickRight
48 {
49 get => _leftStickRight;
50 set
51 {
52 _leftStickRight = value;
53 OnPropertyChanged();
54 }
55 }
56
57 private Key _leftStickButton;
58 public Key LeftStickButton
59 {
60 get => _leftStickButton;
61 set
62 {
63 _leftStickButton = value;
64 OnPropertyChanged();
65 }
66 }
67
68 private Key _rightStickUp;
69 public Key RightStickUp
70 {
71 get => _rightStickUp;
72 set
73 {
74 _rightStickUp = value;
75 OnPropertyChanged();
76 }
77 }
78
79 private Key _rightStickDown;
80 public Key RightStickDown
81 {
82 get => _rightStickDown;
83 set
84 {
85 _rightStickDown = value;
86 OnPropertyChanged();
87 }
88 }
89
90 private Key _rightStickLeft;
91 public Key RightStickLeft
92 {
93 get => _rightStickLeft;
94 set
95 {
96 _rightStickLeft = value;
97 OnPropertyChanged();
98 }
99 }
100
101 private Key _rightStickRight;
102 public Key RightStickRight
103 {
104 get => _rightStickRight;
105 set
106 {
107 _rightStickRight = value;
108 OnPropertyChanged();
109 }
110 }
111
112 private Key _rightStickButton;
113 public Key RightStickButton
114 {
115 get => _rightStickButton;
116 set
117 {
118 _rightStickButton = value;
119 OnPropertyChanged();
120 }
121 }
122
123 private Key _dpadUp;
124 public Key DpadUp
125 {
126 get => _dpadUp;
127 set
128 {
129 _dpadUp = value;
130 OnPropertyChanged();
131 }
132 }
133
134 private Key _dpadDown;
135 public Key DpadDown
136 {
137 get => _dpadDown;
138 set
139 {
140 _dpadDown = value;
141 OnPropertyChanged();
142 }
143 }
144
145 private Key _dpadLeft;
146 public Key DpadLeft
147 {
148 get => _dpadLeft;
149 set
150 {
151 _dpadLeft = value;
152 OnPropertyChanged();
153 }
154 }
155
156 private Key _dpadRight;
157 public Key DpadRight
158 {
159 get => _dpadRight;
160 set
161 {
162 _dpadRight = value;
163 OnPropertyChanged();
164 }
165 }
166
167 private Key _buttonL;
168 public Key ButtonL
169 {
170 get => _buttonL;
171 set
172 {
173 _buttonL = value;
174 OnPropertyChanged();
175 }
176 }
177
178 private Key _buttonMinus;
179 public Key ButtonMinus
180 {
181 get => _buttonMinus;
182 set
183 {
184 _buttonMinus = value;
185 OnPropertyChanged();
186 }
187 }
188
189 private Key _leftButtonSl;
190 public Key LeftButtonSl
191 {
192 get => _leftButtonSl;
193 set
194 {
195 _leftButtonSl = value;
196 OnPropertyChanged();
197 }
198 }
199
200 private Key _leftButtonSr;
201 public Key LeftButtonSr
202 {
203 get => _leftButtonSr;
204 set
205 {
206 _leftButtonSr = value;
207 OnPropertyChanged();
208 }
209 }
210
211 private Key _buttonZl;
212 public Key ButtonZl
213 {
214 get => _buttonZl;
215 set
216 {
217 _buttonZl = value;
218 OnPropertyChanged();
219 }
220 }
221
222 private Key _buttonA;
223 public Key ButtonA
224 {
225 get => _buttonA;
226 set
227 {
228 _buttonA = value;
229 OnPropertyChanged();
230 }
231 }
232
233 private Key _buttonB;
234 public Key ButtonB
235 {
236 get => _buttonB;
237 set
238 {
239 _buttonB = value;
240 OnPropertyChanged();
241 }
242 }
243
244 private Key _buttonX;
245 public Key ButtonX
246 {
247 get => _buttonX;
248 set
249 {
250 _buttonX = value;
251 OnPropertyChanged();
252 }
253 }
254
255 private Key _buttonY;
256 public Key ButtonY
257 {
258 get => _buttonY;
259 set
260 {
261 _buttonY = value;
262 OnPropertyChanged();
263 }
264 }
265
266 private Key _buttonR;
267 public Key ButtonR
268 {
269 get => _buttonR;
270 set
271 {
272 _buttonR = value;
273 OnPropertyChanged();
274 }
275 }
276
277 private Key _buttonPlus;
278 public Key ButtonPlus
279 {
280 get => _buttonPlus;
281 set
282 {
283 _buttonPlus = value;
284 OnPropertyChanged();
285 }
286 }
287
288 private Key _rightButtonSl;
289 public Key RightButtonSl
290 {
291 get => _rightButtonSl;
292 set
293 {
294 _rightButtonSl = value;
295 OnPropertyChanged();
296 }
297 }
298
299 private Key _rightButtonSr;
300 public Key RightButtonSr
301 {
302 get => _rightButtonSr;
303 set
304 {
305 _rightButtonSr = value;
306 OnPropertyChanged();
307 }
308 }
309
310 private Key _buttonZr;
311 public Key ButtonZr
312 {
313 get => _buttonZr;
314 set
315 {
316 _buttonZr = value;
317 OnPropertyChanged();
318 }
319 }
320
321 public KeyboardInputConfig(InputConfig config)
322 {
323 if (config != null)
324 {
325 Id = config.Id;
326 ControllerType = config.ControllerType;
327 PlayerIndex = config.PlayerIndex;
328
329 if (config is not StandardKeyboardInputConfig keyboardConfig)
330 {
331 return;
332 }
333
334 LeftStickUp = keyboardConfig.LeftJoyconStick.StickUp;
335 LeftStickDown = keyboardConfig.LeftJoyconStick.StickDown;
336 LeftStickLeft = keyboardConfig.LeftJoyconStick.StickLeft;
337 LeftStickRight = keyboardConfig.LeftJoyconStick.StickRight;
338 LeftStickButton = keyboardConfig.LeftJoyconStick.StickButton;
339
340 RightStickUp = keyboardConfig.RightJoyconStick.StickUp;
341 RightStickDown = keyboardConfig.RightJoyconStick.StickDown;
342 RightStickLeft = keyboardConfig.RightJoyconStick.StickLeft;
343 RightStickRight = keyboardConfig.RightJoyconStick.StickRight;
344 RightStickButton = keyboardConfig.RightJoyconStick.StickButton;
345
346 DpadUp = keyboardConfig.LeftJoycon.DpadUp;
347 DpadDown = keyboardConfig.LeftJoycon.DpadDown;
348 DpadLeft = keyboardConfig.LeftJoycon.DpadLeft;
349 DpadRight = keyboardConfig.LeftJoycon.DpadRight;
350 ButtonL = keyboardConfig.LeftJoycon.ButtonL;
351 ButtonMinus = keyboardConfig.LeftJoycon.ButtonMinus;
352 LeftButtonSl = keyboardConfig.LeftJoycon.ButtonSl;
353 LeftButtonSr = keyboardConfig.LeftJoycon.ButtonSr;
354 ButtonZl = keyboardConfig.LeftJoycon.ButtonZl;
355
356 ButtonA = keyboardConfig.RightJoycon.ButtonA;
357 ButtonB = keyboardConfig.RightJoycon.ButtonB;
358 ButtonX = keyboardConfig.RightJoycon.ButtonX;
359 ButtonY = keyboardConfig.RightJoycon.ButtonY;
360 ButtonR = keyboardConfig.RightJoycon.ButtonR;
361 ButtonPlus = keyboardConfig.RightJoycon.ButtonPlus;
362 RightButtonSl = keyboardConfig.RightJoycon.ButtonSl;
363 RightButtonSr = keyboardConfig.RightJoycon.ButtonSr;
364 ButtonZr = keyboardConfig.RightJoycon.ButtonZr;
365 }
366 }
367
368 public InputConfig GetConfig()
369 {
370 var config = new StandardKeyboardInputConfig
371 {
372 Id = Id,
373 Backend = InputBackendType.WindowKeyboard,
374 PlayerIndex = PlayerIndex,
375 ControllerType = ControllerType,
376 LeftJoycon = new LeftJoyconCommonConfig<Key>
377 {
378 DpadUp = DpadUp,
379 DpadDown = DpadDown,
380 DpadLeft = DpadLeft,
381 DpadRight = DpadRight,
382 ButtonL = ButtonL,
383 ButtonMinus = ButtonMinus,
384 ButtonZl = ButtonZl,
385 ButtonSl = LeftButtonSl,
386 ButtonSr = LeftButtonSr
387 },
388 RightJoycon = new RightJoyconCommonConfig<Key>
389 {
390 ButtonA = ButtonA,
391 ButtonB = ButtonB,
392 ButtonX = ButtonX,
393 ButtonY = ButtonY,
394 ButtonPlus = ButtonPlus,
395 ButtonSl = RightButtonSl,
396 ButtonSr = RightButtonSr,
397 ButtonR = ButtonR,
398 ButtonZr = ButtonZr
399 },
400 LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
401 {
402 StickUp = LeftStickUp,
403 StickDown = LeftStickDown,
404 StickRight = LeftStickRight,
405 StickLeft = LeftStickLeft,
406 StickButton = LeftStickButton
407 },
408 RightJoyconStick = new JoyconConfigKeyboardStick<Key>
409 {
410 StickUp = RightStickUp,
411 StickDown = RightStickDown,
412 StickLeft = RightStickLeft,
413 StickRight = RightStickRight,
414 StickButton = RightStickButton
415 },
416 Version = InputConfig.CurrentVersion
417 };
418
419 return config;
420 }
421 }
422}
diff --git a/src/Ryujinx.Ava/UI/Models/InputConfiguration.cs b/src/Ryujinx.Ava/UI/Models/InputConfiguration.cs
new file mode 100644
index 000000000..f1352c6d8
--- /dev/null
+++ b/src/Ryujinx.Ava/UI/Models/InputConfiguration.cs
@@ -0,0 +1,456 @@
1using Ryujinx.Ava.UI.ViewModels;
2using Ryujinx.Common.Configuration.Hid;
3using Ryujinx.Common.Configuration.Hid.Controller;
4using Ryujinx.Common.Configuration.Hid.Controller.Motion;
5using Ryujinx.Common.Configuration.Hid.Keyboard;
6using System;
7
8namespace Ryujinx.Ava.UI.Models
9{
10 internal class InputConfiguration<TKey, TStick> : BaseModel
11 {
12 private float _deadzoneRight;
13 private float _triggerThreshold;
14 private float _deadzoneLeft;
15 private double _gyroDeadzone;
16 private int _sensitivity;
17 private bool _enableMotion;
18 private float _weakRumble;
19 private float _strongRumble;
20 private float _rangeLeft;
21 private float _rangeRight;
22
23 public InputBackendType Backend { get; set; }
24
25 /// <summary>
26 /// Controller id
27 /// </summary>
28 public string Id { get; set; }
29
30 /// <summary>
31 /// Controller's Type
32 /// </summary>
33 public ControllerType ControllerType { get; set; }
34
35 /// <summary>
36 /// Player's Index for the controller
37 /// </summary>
38 public PlayerIndex PlayerIndex { get; set; }
39
40 public TStick LeftJoystick { get; set; }
41 public bool LeftInvertStickX { get; set; }
42 public bool LeftInvertStickY { get; set; }
43 public bool RightRotate90 { get; set; }
44 public TKey LeftControllerStickButton { get; set; }
45
46 public TStick RightJoystick { get; set; }
47 public bool RightInvertStickX { get; set; }
48 public bool RightInvertStickY { get; set; }
49 public bool LeftRotate90 { get; set; }
50 public TKey RightControllerStickButton { get; set; }
51
52 public float DeadzoneLeft
53 {
54 get => _deadzoneLeft;
55 set
56 {
57 _deadzoneLeft = MathF.Round(value, 3);
58
59 OnPropertyChanged();
60 }
61 }
62
63 public float RangeLeft
64 {
65 get => _rangeLeft;
66 set
67 {
68 _rangeLeft = MathF.Round(value, 3);
69
70 OnPropertyChanged();
71 }
72 }
73
74 public float DeadzoneRight
75 {
76 get => _deadzoneRight;
77 set
78 {
79 _deadzoneRight = MathF.Round(value, 3);
80
81 OnPropertyChanged();
82 }
83 }
84
85 public float RangeRight
86 {
87 get => _rangeRight;
88 set
89 {
90 _rangeRight = MathF.Round(value, 3);
91
92 OnPropertyChanged();
93 }
94 }
95
96 public float TriggerThreshold
97 {
98 get => _triggerThreshold;
99 set
100 {
101 _triggerThreshold = MathF.Round(value, 3);
102
103 OnPropertyChanged();
104 }
105 }
106
107 public MotionInputBackendType MotionBackend { get; set; }
108
109 public TKey ButtonMinus { get; set; }
110 public TKey ButtonL { get; set; }
111 public TKey ButtonZl { get; set; }
112 public TKey LeftButtonSl { get; set; }
113 public TKey LeftButtonSr { get; set; }
114 public TKey DpadUp { get; set; }
115 public TKey DpadDown { get; set; }
116 public TKey DpadLeft { get; set; }
117 public TKey DpadRight { get; set; }
118
119 public TKey ButtonPlus { get; set; }
120 public TKey ButtonR { get; set; }
121 public TKey ButtonZr { get; set; }
122 public TKey RightButtonSl { get; set; }
123 public TKey RightButtonSr { get; set; }
124 public TKey ButtonX { get; set; }
125 public TKey ButtonB { get; set; }
126 public TKey ButtonY { get; set; }
127 public TKey ButtonA { get; set; }
128
129 public TKey LeftStickUp { get; set; }
130 public TKey LeftStickDown { get; set; }
131 public TKey LeftStickLeft { get; set; }
132 public TKey LeftStickRight { get; set; }
133 public TKey LeftKeyboardStickButton { get; set; }
134
135 public TKey RightStickUp { get; set; }
136 public TKey RightStickDown { get; set; }
137 public TKey RightStickLeft { get; set; }
138 public TKey RightStickRight { get; set; }
139 public TKey RightKeyboardStickButton { get; set; }
140
141 public int Sensitivity
142 {
143 get => _sensitivity;
144 set
145 {
146 _sensitivity = value;
147
148 OnPropertyChanged();
149 }
150 }
151
152 public double GyroDeadzone
153 {
154 get => _gyroDeadzone;
155 set
156 {
157 _gyroDeadzone = Math.Round(value, 3);
158
159 OnPropertyChanged();
160 }
161 }
162
163 public bool EnableMotion
164 {
165 get => _enableMotion; set
166 {
167 _enableMotion = value;
168
169 OnPropertyChanged();
170 }
171 }
172
173 public bool EnableCemuHookMotion { get; set; }
174 public int Slot { get; set; }
175 public int AltSlot { get; set; }
176 public bool MirrorInput { get; set; }
177 public string DsuServerHost { get; set; }
178 public int DsuServerPort { get; set; }
179
180 public bool EnableRumble { get; set; }
181 public float WeakRumble
182 {
183 get => _weakRumble; set
184 {
185 _weakRumble = value;
186
187 OnPropertyChanged();
188 }
189 }
190 public float StrongRumble
191 {
192 get => _strongRumble; set
193 {
194 _strongRumble = value;
195
196 OnPropertyChanged();
197 }
198 }
199
200 public InputConfiguration(InputConfig config)
201 {
202 if (config != null)
203 {
204 Backend = config.Backend;
205 Id = config.Id;
206 ControllerType = config.ControllerType;
207 PlayerIndex = config.PlayerIndex;
208
209 if (config is StandardKeyboardInputConfig keyboardConfig)
210 {
211 LeftStickUp = (TKey)(object)keyboardConfig.LeftJoyconStick.StickUp;
212 LeftStickDown = (TKey)(object)keyboardConfig.LeftJoyconStick.StickDown;
213 LeftStickLeft = (TKey)(object)keyboardConfig.LeftJoyconStick.StickLeft;
214 LeftStickRight = (TKey)(object)keyboardConfig.LeftJoyconStick.StickRight;
215 LeftKeyboardStickButton = (TKey)(object)keyboardConfig.LeftJoyconStick.StickButton;
216
217 RightStickUp = (TKey)(object)keyboardConfig.RightJoyconStick.StickUp;
218 RightStickDown = (TKey)(object)keyboardConfig.RightJoyconStick.StickDown;
219 RightStickLeft = (TKey)(object)keyboardConfig.RightJoyconStick.StickLeft;
220 RightStickRight = (TKey)(object)keyboardConfig.RightJoyconStick.StickRight;
221 RightKeyboardStickButton = (TKey)(object)keyboardConfig.RightJoyconStick.StickButton;
222
223 ButtonA = (TKey)(object)keyboardConfig.RightJoycon.ButtonA;
224 ButtonB = (TKey)(object)keyboardConfig.RightJoycon.ButtonB;
225 ButtonX = (TKey)(object)keyboardConfig.RightJoycon.ButtonX;
226 ButtonY = (TKey)(object)keyboardConfig.RightJoycon.ButtonY;
227 ButtonR = (TKey)(object)keyboardConfig.RightJoycon.ButtonR;
228 RightButtonSl = (TKey)(object)keyboardConfig.RightJoycon.ButtonSl;
229 RightButtonSr = (TKey)(object)keyboardConfig.RightJoycon.ButtonSr;
230 ButtonZr = (TKey)(object)keyboardConfig.RightJoycon.ButtonZr;
231 ButtonPlus = (TKey)(object)keyboardConfig.RightJoycon.ButtonPlus;
232
233 DpadUp = (TKey)(object)keyboardConfig.LeftJoycon.DpadUp;
234 DpadDown = (TKey)(object)keyboardConfig.LeftJoycon.DpadDown;
235 DpadLeft = (TKey)(object)keyboardConfig.LeftJoycon.DpadLeft;
236 DpadRight = (TKey)(object)keyboardConfig.LeftJoycon.DpadRight;
237 ButtonMinus = (TKey)(object)keyboardConfig.LeftJoycon.ButtonMinus;
238 LeftButtonSl = (TKey)(object)keyboardConfig.LeftJoycon.ButtonSl;
239 LeftButtonSr = (TKey)(object)keyboardConfig.LeftJoycon.ButtonSr;
240 ButtonZl = (TKey)(object)keyboardConfig.LeftJoycon.ButtonZl;
241 ButtonL = (TKey)(object)keyboardConfig.LeftJoycon.ButtonL;
242 }
243 else if (config is StandardControllerInputConfig controllerConfig)
244 {
245 LeftJoystick = (TStick)(object)controllerConfig.LeftJoyconStick.Joystick;
246 LeftInvertStickX = controllerConfig.LeftJoyconStick.InvertStickX;
247 LeftInvertStickY = controllerConfig.LeftJoyconStick.InvertStickY;
248 LeftRotate90 = controllerConfig.LeftJoyconStick.Rotate90CW;
249 LeftControllerStickButton = (TKey)(object)controllerConfig.LeftJoyconStick.StickButton;
250
251 RightJoystick = (TStick)(object)controllerConfig.RightJoyconStick.Joystick;
252 RightInvertStickX = controllerConfig.RightJoyconStick.InvertStickX;
253 RightInvertStickY = controllerConfig.RightJoyconStick.InvertStickY;
254 RightRotate90 = controllerConfig.RightJoyconStick.Rotate90CW;
255 RightControllerStickButton = (TKey)(object)controllerConfig.RightJoyconStick.StickButton;
256
257 ButtonA = (TKey)(object)controllerConfig.RightJoycon.ButtonA;
258 ButtonB = (TKey)(object)controllerConfig.RightJoycon.ButtonB;
259 ButtonX = (TKey)(object)controllerConfig.RightJoycon.ButtonX;
260 ButtonY = (TKey)(object)controllerConfig.RightJoycon.ButtonY;
261 ButtonR = (TKey)(object)controllerConfig.RightJoycon.ButtonR;
262 RightButtonSl = (TKey)(object)controllerConfig.RightJoycon.ButtonSl;
263 RightButtonSr = (TKey)(object)controllerConfig.RightJoycon.ButtonSr;
264 ButtonZr = (TKey)(object)controllerConfig.RightJoycon.ButtonZr;
265 ButtonPlus = (TKey)(object)controllerConfig.RightJoycon.ButtonPlus;
266
267 DpadUp = (TKey)(object)controllerConfig.LeftJoycon.DpadUp;
268 DpadDown = (TKey)(object)controllerConfig.LeftJoycon.DpadDown;
269 DpadLeft = (TKey)(object)controllerConfig.LeftJoycon.DpadLeft;
270 DpadRight = (TKey)(object)controllerConfig.LeftJoycon.DpadRight;
271 ButtonMinus = (TKey)(object)controllerConfig.LeftJoycon.ButtonMinus;
272 LeftButtonSl = (TKey)(object)controllerConfig.LeftJoycon.ButtonSl;
273 LeftButtonSr = (TKey)(object)controllerConfig.LeftJoycon.ButtonSr;
274 ButtonZl = (TKey)(object)controllerConfig.LeftJoycon.ButtonZl;
275 ButtonL = (TKey)(object)controllerConfig.LeftJoycon.ButtonL;
276
277 DeadzoneLeft = controllerConfig.DeadzoneLeft;
278 DeadzoneRight = controllerConfig.DeadzoneRight;
279 RangeLeft = controllerConfig.RangeLeft;
280 RangeRight = controllerConfig.RangeRight;
281 TriggerThreshold = controllerConfig.TriggerThreshold;
282
283 if (controllerConfig.Motion != null)
284 {
285 EnableMotion = controllerConfig.Motion.EnableMotion;
286 MotionBackend = controllerConfig.Motion.MotionBackend;
287 GyroDeadzone = controllerConfig.Motion.GyroDeadzone;
288 Sensitivity = controllerConfig.Motion.Sensitivity;
289
290 if (controllerConfig.Motion is CemuHookMotionConfigController cemuHook)
291 {
292 EnableCemuHookMotion = true;
293 DsuServerHost = cemuHook.DsuServerHost;
294 DsuServerPort = cemuHook.DsuServerPort;
295 Slot = cemuHook.Slot;
296 AltSlot = cemuHook.AltSlot;
297 MirrorInput = cemuHook.MirrorInput;
298 }
299
300 if (controllerConfig.Rumble != null)
301 {
302 EnableRumble = controllerConfig.Rumble.EnableRumble;
303 WeakRumble = controllerConfig.Rumble.WeakRumble;
304 StrongRumble = controllerConfig.Rumble.StrongRumble;
305 }
306 }
307 }
308 }
309 }
310
311 public InputConfiguration()
312 {
313 }
314
315 public InputConfig GetConfig()
316 {
317 if (Backend == InputBackendType.WindowKeyboard)
318 {
319 return new StandardKeyboardInputConfig
320 {
321 Id = Id,
322 Backend = Backend,
323 PlayerIndex = PlayerIndex,
324 ControllerType = ControllerType,
325 LeftJoycon = new LeftJoyconCommonConfig<Key>
326 {
327 DpadUp = (Key)(object)DpadUp,
328 DpadDown = (Key)(object)DpadDown,
329 DpadLeft = (Key)(object)DpadLeft,
330 DpadRight = (Key)(object)DpadRight,
331 ButtonL = (Key)(object)ButtonL,
332 ButtonZl = (Key)(object)ButtonZl,
333 ButtonSl = (Key)(object)LeftButtonSl,
334 ButtonSr = (Key)(object)LeftButtonSr,
335 ButtonMinus = (Key)(object)ButtonMinus,
336 },
337 RightJoycon = new RightJoyconCommonConfig<Key>
338 {
339 ButtonA = (Key)(object)ButtonA,
340 ButtonB = (Key)(object)ButtonB,
341 ButtonX = (Key)(object)ButtonX,
342 ButtonY = (Key)(object)ButtonY,
343 ButtonPlus = (Key)(object)ButtonPlus,
344 ButtonSl = (Key)(object)RightButtonSl,
345 ButtonSr = (Key)(object)RightButtonSr,
346 ButtonR = (Key)(object)ButtonR,
347 ButtonZr = (Key)(object)ButtonZr,
348 },
349 LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
350 {
351 StickUp = (Key)(object)LeftStickUp,
352 StickDown = (Key)(object)LeftStickDown,
353 StickRight = (Key)(object)LeftStickRight,
354 StickLeft = (Key)(object)LeftStickLeft,
355 StickButton = (Key)(object)LeftKeyboardStickButton,
356 },
357 RightJoyconStick = new JoyconConfigKeyboardStick<Key>
358 {
359 StickUp = (Key)(object)RightStickUp,
360 StickDown = (Key)(object)RightStickDown,
361 StickLeft = (Key)(object)RightStickLeft,
362 StickRight = (Key)(object)RightStickRight,
363 StickButton = (Key)(object)RightKeyboardStickButton,
364 },
365 Version = InputConfig.CurrentVersion,
366 };
367
368 }
369
370 if (Backend == InputBackendType.GamepadSDL2)
371 {
372 var config = new StandardControllerInputConfig
373 {
374 Id = Id,
375 Backend = Backend,
376 PlayerIndex = PlayerIndex,
377 ControllerType = ControllerType,
378 LeftJoycon = new LeftJoyconCommonConfig<GamepadInputId>
379 {
380 DpadUp = (GamepadInputId)(object)DpadUp,
381 DpadDown = (GamepadInputId)(object)DpadDown,
382 DpadLeft = (GamepadInputId)(object)DpadLeft,
383 DpadRight = (GamepadInputId)(object)DpadRight,
384 ButtonL = (GamepadInputId)(object)ButtonL,
385 ButtonZl = (GamepadInputId)(object)ButtonZl,
386 ButtonSl = (GamepadInputId)(object)LeftButtonSl,
387 ButtonSr = (GamepadInputId)(object)LeftButtonSr,
388 ButtonMinus = (GamepadInputId)(object)ButtonMinus,
389 },
390 RightJoycon = new RightJoyconCommonConfig<GamepadInputId>
391 {
392 ButtonA = (GamepadInputId)(object)ButtonA,
393 ButtonB = (GamepadInputId)(object)ButtonB,
394 ButtonX = (GamepadInputId)(object)ButtonX,
395 ButtonY = (GamepadInputId)(object)ButtonY,
396 ButtonPlus = (GamepadInputId)(object)ButtonPlus,
397 ButtonSl = (GamepadInputId)(object)RightButtonSl,
398 ButtonSr = (GamepadInputId)(object)RightButtonSr,
399 ButtonR = (GamepadInputId)(object)ButtonR,
400 ButtonZr = (GamepadInputId)(object)ButtonZr,
401 },
402 LeftJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
403 {
404 Joystick = (StickInputId)(object)LeftJoystick,
405 InvertStickX = LeftInvertStickX,
406 InvertStickY = LeftInvertStickY,
407 Rotate90CW = LeftRotate90,
408 StickButton = (GamepadInputId)(object)LeftControllerStickButton,
409 },
410 RightJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
411 {
412 Joystick = (StickInputId)(object)RightJoystick,
413 InvertStickX = RightInvertStickX,
414 InvertStickY = RightInvertStickY,
415 Rotate90CW = RightRotate90,
416 StickButton = (GamepadInputId)(object)RightControllerStickButton,
417 },
418 Rumble = new RumbleConfigController
419 {
420 EnableRumble = EnableRumble,
421 WeakRumble = WeakRumble,
422 StrongRumble = StrongRumble,
423 },
424 Version = InputConfig.CurrentVersion,
425 DeadzoneLeft = DeadzoneLeft,
426 DeadzoneRight = DeadzoneRight,
427 RangeLeft = RangeLeft,
428 RangeRight = RangeRight,
429 TriggerThreshold = TriggerThreshold,
430 Motion = EnableCemuHookMotion
431 ? new CemuHookMotionConfigController
432 {
433 DsuServerHost = DsuServerHost,
434 DsuServerPort = DsuServerPort,
435 Slot = Slot,
436 AltSlot = AltSlot,
437 MirrorInput = MirrorInput,
438 MotionBackend = MotionInputBackendType.CemuHook,
439 }
440 : new StandardMotionConfigController
441 {
442 MotionBackend = MotionInputBackendType.GamepadDriver,
443 },
444 };
445
446 config.Motion.Sensitivity = Sensitivity;
447 config.Motion.EnableMotion = EnableMotion;
448 config.Motion.GyroDeadzone = GyroDeadzone;
449
450 return config;
451 }
452
453 return null;
454 }
455 }
456}
diff --git a/src/Ryujinx.Ava/UI/ViewModels/Input/InputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs
index ef8ffd50d..c0c625321 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/Input/InputViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs
@@ -8,7 +8,7 @@ using Ryujinx.Ava.Common.Locale;
8using Ryujinx.Ava.Input; 8using Ryujinx.Ava.Input;
9using Ryujinx.Ava.UI.Helpers; 9using Ryujinx.Ava.UI.Helpers;
10using Ryujinx.Ava.UI.Models; 10using Ryujinx.Ava.UI.Models;
11using Ryujinx.Ava.UI.Models.Input; 11using Ryujinx.Ava.UI.Views.Input;
12using Ryujinx.Ava.UI.Windows; 12using Ryujinx.Ava.UI.Windows;
13using Ryujinx.Common; 13using Ryujinx.Common;
14using Ryujinx.Common.Configuration; 14using Ryujinx.Common.Configuration;
@@ -30,9 +30,9 @@ using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.Gamepad
30using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId; 30using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
31using Key = Ryujinx.Common.Configuration.Hid.Key; 31using Key = Ryujinx.Common.Configuration.Hid.Key;
32 32
33namespace Ryujinx.Ava.UI.ViewModels.Input 33namespace Ryujinx.Ava.UI.ViewModels
34{ 34{
35 public class InputViewModel : BaseModel, IDisposable 35 public class ControllerInputViewModel : BaseModel, IDisposable
36 { 36 {
37 private const string Disabled = "disabled"; 37 private const string Disabled = "disabled";
38 private const string ProControllerResource = "Ryujinx.Ui.Common/Resources/Controller_ProCon.svg"; 38 private const string ProControllerResource = "Ryujinx.Ui.Common/Resources/Controller_ProCon.svg";
@@ -48,7 +48,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
48 private int _controllerNumber; 48 private int _controllerNumber;
49 private string _controllerImage; 49 private string _controllerImage;
50 private int _device; 50 private int _device;
51 private object _configViewModel; 51 private object _configuration;
52 private string _profileName; 52 private string _profileName;
53 private bool _isLoaded; 53 private bool _isLoaded;
54 54
@@ -71,14 +71,13 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
71 public bool IsLeft { get; set; } 71 public bool IsLeft { get; set; }
72 72
73 public bool IsModified { get; set; } 73 public bool IsModified { get; set; }
74 public event Action NotifyChangesEvent;
75 74
76 public object ConfigViewModel 75 public object Configuration
77 { 76 {
78 get => _configViewModel; 77 get => _configuration;
79 set 78 set
80 { 79 {
81 _configViewModel = value; 80 _configuration = value;
82 81
83 OnPropertyChanged(); 82 OnPropertyChanged();
84 } 83 }
@@ -233,7 +232,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
233 232
234 public InputConfig Config { get; set; } 233 public InputConfig Config { get; set; }
235 234
236 public InputViewModel(UserControl owner) : this() 235 public ControllerInputViewModel(UserControl owner) : this()
237 { 236 {
238 if (Program.PreviewerDetached) 237 if (Program.PreviewerDetached)
239 { 238 {
@@ -245,6 +244,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
245 244
246 _mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected; 245 _mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
247 _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected; 246 _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
247
248 _mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates(); 248 _mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates();
249 249
250 _isLoaded = false; 250 _isLoaded = false;
@@ -255,7 +255,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
255 } 255 }
256 } 256 }
257 257
258 public InputViewModel() 258 public ControllerInputViewModel()
259 { 259 {
260 PlayerIndexes = new ObservableCollection<PlayerModel>(); 260 PlayerIndexes = new ObservableCollection<PlayerModel>();
261 Controllers = new ObservableCollection<ControllerModel>(); 261 Controllers = new ObservableCollection<ControllerModel>();
@@ -282,12 +282,12 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
282 282
283 if (Config is StandardKeyboardInputConfig keyboardInputConfig) 283 if (Config is StandardKeyboardInputConfig keyboardInputConfig)
284 { 284 {
285 ConfigViewModel = new KeyboardInputViewModel(this, new KeyboardInputConfig(keyboardInputConfig)); 285 Configuration = new InputConfiguration<Key, ConfigStickInputId>(keyboardInputConfig);
286 } 286 }
287 287
288 if (Config is StandardControllerInputConfig controllerInputConfig) 288 if (Config is StandardControllerInputConfig controllerInputConfig)
289 { 289 {
290 ConfigViewModel = new ControllerInputViewModel(this, new ControllerInputConfig(controllerInputConfig)); 290 Configuration = new InputConfiguration<ConfigGamepadInputId, ConfigStickInputId>(controllerInputConfig);
291 } 291 }
292 } 292 }
293 293
@@ -323,6 +323,16 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
323 } 323 }
324 } 324 }
325 325
326 public async void ShowMotionConfig()
327 {
328 await MotionInputView.Show(this);
329 }
330
331 public async void ShowRumbleConfig()
332 {
333 await RumbleInputView.Show(this);
334 }
335
326 private void LoadInputDriver() 336 private void LoadInputDriver()
327 { 337 {
328 if (_device < 0) 338 if (_device < 0)
@@ -730,7 +740,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
730 return; 740 return;
731 } 741 }
732 742
733 if (ConfigViewModel == null) 743 if (Configuration == null)
734 { 744 {
735 return; 745 return;
736 } 746 }
@@ -741,37 +751,35 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
741 751
742 return; 752 return;
743 } 753 }
744 else
745 {
746 bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
747
748 if (validFileName)
749 {
750 string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
751
752 InputConfig config = null;
753 754
754 if (IsKeyboard) 755 bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
755 {
756 config = (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig();
757 }
758 else if (IsController)
759 {
760 config = (ConfigViewModel as ControllerInputViewModel).Config.GetConfig();
761 }
762 756
763 config.ControllerType = Controllers[_controller].Type; 757 if (validFileName)
764 758 {
765 string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig); 759 string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
766 760
767 await File.WriteAllTextAsync(path, jsonString); 761 InputConfig config = null;
768 762
769 LoadProfiles(); 763 if (IsKeyboard)
764 {
765 config = (Configuration as InputConfiguration<Key, ConfigStickInputId>).GetConfig();
770 } 766 }
771 else 767 else if (IsController)
772 { 768 {
773 await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]); 769 config = (Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>).GetConfig();
774 } 770 }
771
772 config.ControllerType = Controllers[_controller].Type;
773
774 string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig);
775
776 await File.WriteAllTextAsync(path, jsonString);
777
778 LoadProfiles();
779 }
780 else
781 {
782 await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]);
775 } 783 }
776 } 784 }
777 785
@@ -822,18 +830,18 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
822 830
823 if (device.Type == DeviceType.Keyboard) 831 if (device.Type == DeviceType.Keyboard)
824 { 832 {
825 var inputConfig = (ConfigViewModel as KeyboardInputViewModel).Config; 833 var inputConfig = Configuration as InputConfiguration<Key, ConfigStickInputId>;
826 inputConfig.Id = device.Id; 834 inputConfig.Id = device.Id;
827 } 835 }
828 else 836 else
829 { 837 {
830 var inputConfig = (ConfigViewModel as ControllerInputViewModel).Config; 838 var inputConfig = Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>;
831 inputConfig.Id = device.Id.Split(" ")[0]; 839 inputConfig.Id = device.Id.Split(" ")[0];
832 } 840 }
833 841
834 var config = !IsController 842 var config = !IsController
835 ? (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig() 843 ? (Configuration as InputConfiguration<Key, ConfigStickInputId>).GetConfig()
836 : (ConfigViewModel as ControllerInputViewModel).Config.GetConfig(); 844 : (Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>).GetConfig();
837 config.ControllerType = Controllers[_controller].Type; 845 config.ControllerType = Controllers[_controller].Type;
838 config.PlayerIndex = _playerId; 846 config.PlayerIndex = _playerId;
839 847
@@ -864,13 +872,12 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
864 872
865 public void NotifyChanges() 873 public void NotifyChanges()
866 { 874 {
867 OnPropertyChanged(nameof(ConfigViewModel)); 875 OnPropertyChanged(nameof(Configuration));
868 OnPropertyChanged(nameof(IsController)); 876 OnPropertyChanged(nameof(IsController));
869 OnPropertyChanged(nameof(ShowSettings)); 877 OnPropertyChanged(nameof(ShowSettings));
870 OnPropertyChanged(nameof(IsKeyboard)); 878 OnPropertyChanged(nameof(IsKeyboard));
871 OnPropertyChanged(nameof(IsRight)); 879 OnPropertyChanged(nameof(IsRight));
872 OnPropertyChanged(nameof(IsLeft)); 880 OnPropertyChanged(nameof(IsLeft));
873 NotifyChangesEvent?.Invoke();
874 } 881 }
875 882
876 public void Dispose() 883 public void Dispose()
diff --git a/src/Ryujinx.Ava/UI/ViewModels/Input/ControllerInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/Input/ControllerInputViewModel.cs
deleted file mode 100644
index 0e23dfa76..000000000
--- a/src/Ryujinx.Ava/UI/ViewModels/Input/ControllerInputViewModel.cs
+++ /dev/null
@@ -1,84 +0,0 @@
1using Avalonia.Svg.Skia;
2using Ryujinx.Ava.UI.Models.Input;
3using Ryujinx.Ava.UI.Views.Input;
4
5namespace Ryujinx.Ava.UI.ViewModels.Input
6{
7 public class ControllerInputViewModel : BaseModel
8 {
9 private ControllerInputConfig _config;
10 public ControllerInputConfig Config
11 {
12 get => _config;
13 set
14 {
15 _config = value;
16 OnPropertyChanged();
17 }
18 }
19
20 private bool _isLeft;
21 public bool IsLeft
22 {
23 get => _isLeft;
24 set
25 {
26 _isLeft = value;
27 OnPropertyChanged();
28 OnPropertyChanged(nameof(HasSides));
29 }
30 }
31
32 private bool _isRight;
33 public bool IsRight
34 {
35 get => _isRight;
36 set
37 {
38 _isRight = value;
39 OnPropertyChanged();
40 OnPropertyChanged(nameof(HasSides));
41 }
42 }
43
44 public bool HasSides => IsLeft ^ IsRight;
45
46 private SvgImage _image;
47 public SvgImage Image
48 {
49 get => _image;
50 set
51 {
52 _image = value;
53 OnPropertyChanged();
54 }
55 }
56
57 public InputViewModel parentModel;
58
59 public ControllerInputViewModel(InputViewModel model, ControllerInputConfig config)
60 {
61 parentModel = model;
62 model.NotifyChangesEvent += OnParentModelChanged;
63 OnParentModelChanged();
64 Config = config;
65 }
66
67 public async void ShowMotionConfig()
68 {
69 await MotionInputView.Show(this);
70 }
71
72 public async void ShowRumbleConfig()
73 {
74 await RumbleInputView.Show(this);
75 }
76
77 public void OnParentModelChanged()
78 {
79 IsLeft = parentModel.IsLeft;
80 IsRight = parentModel.IsRight;
81 Image = parentModel.Image;
82 }
83 }
84}
diff --git a/src/Ryujinx.Ava/UI/ViewModels/Input/KeyboardInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/Input/KeyboardInputViewModel.cs
deleted file mode 100644
index a93873063..000000000
--- a/src/Ryujinx.Ava/UI/ViewModels/Input/KeyboardInputViewModel.cs
+++ /dev/null
@@ -1,73 +0,0 @@
1using Avalonia.Svg.Skia;
2using Ryujinx.Ava.UI.Models.Input;
3
4namespace Ryujinx.Ava.UI.ViewModels.Input
5{
6 public class KeyboardInputViewModel : BaseModel
7 {
8 private KeyboardInputConfig _config;
9 public KeyboardInputConfig Config
10 {
11 get => _config;
12 set
13 {
14 _config = value;
15 OnPropertyChanged();
16 }
17 }
18
19 private bool _isLeft;
20 public bool IsLeft
21 {
22 get => _isLeft;
23 set
24 {
25 _isLeft = value;
26 OnPropertyChanged();
27 OnPropertyChanged(nameof(HasSides));
28 }
29 }
30
31 private bool _isRight;
32 public bool IsRight
33 {
34 get => _isRight;
35 set
36 {
37 _isRight = value;
38 OnPropertyChanged();
39 OnPropertyChanged(nameof(HasSides));
40 }
41 }
42
43 public bool HasSides => IsLeft ^ IsRight;
44
45 private SvgImage _image;
46 public SvgImage Image
47 {
48 get => _image;
49 set
50 {
51 _image = value;
52 OnPropertyChanged();
53 }
54 }
55
56 public InputViewModel parentModel;
57
58 public KeyboardInputViewModel(InputViewModel model, KeyboardInputConfig config)
59 {
60 parentModel = model;
61 model.NotifyChangesEvent += OnParentModelChanged;
62 OnParentModelChanged();
63 Config = config;
64 }
65
66 public void OnParentModelChanged()
67 {
68 IsLeft = parentModel.IsLeft;
69 IsRight = parentModel.IsRight;
70 Image = parentModel.Image;
71 }
72 }
73}
diff --git a/src/Ryujinx.Ava/UI/ViewModels/Input/MotionInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs
index c9ed8f2d4..0b12a51f6 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/Input/MotionInputViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs
@@ -1,4 +1,4 @@
1namespace Ryujinx.Ava.UI.ViewModels.Input 1namespace Ryujinx.Ava.UI.ViewModels
2{ 2{
3 public class MotionInputViewModel : BaseModel 3 public class MotionInputViewModel : BaseModel
4 { 4 {
diff --git a/src/Ryujinx.Ava/UI/ViewModels/Input/RumbleInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs
index 8ad33cf4c..49de19937 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/Input/RumbleInputViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs
@@ -1,4 +1,4 @@
1namespace Ryujinx.Ava.UI.ViewModels.Input 1namespace Ryujinx.Ava.UI.ViewModels
2{ 2{
3 public class RumbleInputViewModel : BaseModel 3 public class RumbleInputViewModel : BaseModel
4 { 4 {
diff --git a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml
index 08bdf90f4..d636873a3 100644
--- a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml
+++ b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml
@@ -1,11 +1,13 @@
1<UserControl 1<UserControl
2 xmlns="https://github.com/avaloniaui" 2 xmlns="https://github.com/avaloniaui"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
4 xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" 5 xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
7 xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls" 8 xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
8 xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input" 9 xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
10 xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
9 xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers" 11 xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
10 HorizontalAlignment="Stretch" 12 HorizontalAlignment="Stretch"
11 VerticalAlignment="Stretch" 13 VerticalAlignment="Stretch"
@@ -13,7 +15,6 @@
13 d:DesignWidth="800" 15 d:DesignWidth="800"
14 x:Class="Ryujinx.Ava.UI.Views.Input.ControllerInputView" 16 x:Class="Ryujinx.Ava.UI.Views.Input.ControllerInputView"
15 x:DataType="viewModels:ControllerInputViewModel" 17 x:DataType="viewModels:ControllerInputViewModel"
16 x:CompileBindings="True"
17 mc:Ignorable="d" 18 mc:Ignorable="d"
18 Focusable="True"> 19 Focusable="True">
19 <Design.DataContext> 20 <Design.DataContext>
@@ -33,10 +34,191 @@
33 HorizontalAlignment="Stretch" 34 HorizontalAlignment="Stretch"
34 VerticalAlignment="Stretch" 35 VerticalAlignment="Stretch"
35 Orientation="Vertical"> 36 Orientation="Vertical">
37 <StackPanel
38 Margin="0 0 0 5"
39 Orientation="Vertical"
40 Spacing="5">
41 <Grid>
42 <Grid.ColumnDefinitions>
43 <ColumnDefinition Width="*" />
44 <ColumnDefinition Width="10" />
45 <ColumnDefinition Width="*" />
46 </Grid.ColumnDefinitions>
47 <!-- Player Selection -->
48 <Grid
49 Grid.Column="0"
50 Margin="2"
51 HorizontalAlignment="Stretch"
52 VerticalAlignment="Center">
53 <Grid.ColumnDefinitions>
54 <ColumnDefinition Width="Auto"/>
55 <ColumnDefinition Width="*" />
56 </Grid.ColumnDefinitions>
57 <TextBlock
58 Margin="5,0,10,0"
59 Width="90"
60 HorizontalAlignment="Left"
61 VerticalAlignment="Center"
62 Text="{locale:Locale ControllerSettingsPlayer}" />
63 <ComboBox
64 Grid.Column="1"
65 Name="PlayerIndexBox"
66 HorizontalAlignment="Stretch"
67 VerticalAlignment="Center"
68 SelectionChanged="PlayerIndexBox_OnSelectionChanged"
69 ItemsSource="{Binding PlayerIndexes}"
70 SelectedIndex="{Binding PlayerId}">
71 <ComboBox.ItemTemplate>
72 <DataTemplate>
73 <TextBlock Text="{Binding Name}" />
74 </DataTemplate>
75 </ComboBox.ItemTemplate>
76 </ComboBox>
77 </Grid>
78 <!-- Profile Selection -->
79 <Grid
80 Grid.Column="2"
81 Margin="2"
82 HorizontalAlignment="Stretch"
83 VerticalAlignment="Center">
84 <Grid.ColumnDefinitions>
85 <ColumnDefinition Width="Auto"/>
86 <ColumnDefinition Width="*" />
87 <ColumnDefinition Width="Auto"/>
88 <ColumnDefinition Width="Auto"/>
89 <ColumnDefinition Width="Auto"/>
90 </Grid.ColumnDefinitions>
91 <TextBlock
92 Margin="5,0,10,0"
93 Width="90"
94 HorizontalAlignment="Left"
95 VerticalAlignment="Center"
96 Text="{locale:Locale ControllerSettingsProfile}" />
97 <ui:FAComboBox
98 Grid.Column="1"
99 IsEditable="True"
100 Name="ProfileBox"
101 HorizontalAlignment="Stretch"
102 VerticalAlignment="Center"
103 SelectedIndex="0"
104 ItemsSource="{Binding ProfilesList}"
105 Text="{Binding ProfileName, Mode=TwoWay}" />
106 <Button
107 Grid.Column="2"
108 MinWidth="0"
109 Margin="5,0,0,0"
110 VerticalAlignment="Center"
111 ToolTip.Tip="{locale:Locale ControllerSettingsLoadProfileToolTip}"
112 Command="{ReflectionBinding LoadProfile}">
113 <ui:SymbolIcon
114 Symbol="Upload"
115 FontSize="15"
116 Height="20" />
117 </Button>
118 <Button
119 Grid.Column="3"
120 MinWidth="0"
121 Margin="5,0,0,0"
122 VerticalAlignment="Center"
123 ToolTip.Tip="{locale:Locale ControllerSettingsSaveProfileToolTip}"
124 Command="{ReflectionBinding SaveProfile}">
125 <ui:SymbolIcon
126 Symbol="Save"
127 FontSize="15"
128 Height="20" />
129 </Button>
130 <Button
131 Grid.Column="4"
132 MinWidth="0"
133 Margin="5,0,0,0"
134 VerticalAlignment="Center"
135 ToolTip.Tip="{locale:Locale ControllerSettingsRemoveProfileToolTip}"
136 Command="{ReflectionBinding RemoveProfile}">
137 <ui:SymbolIcon
138 Symbol="Delete"
139 FontSize="15"
140 Height="20" />
141 </Button>
142 </Grid>
143 </Grid>
144 <Separator />
145 <Grid>
146 <Grid.ColumnDefinitions>
147 <ColumnDefinition Width="*" />
148 <ColumnDefinition Width="10" />
149 <ColumnDefinition Width="*" />
150 </Grid.ColumnDefinitions>
151 <!-- Input Device -->
152 <Grid
153 Grid.Column="0"
154 Margin="2"
155 HorizontalAlignment="Stretch">
156 <Grid.ColumnDefinitions>
157 <ColumnDefinition Width="Auto"/>
158 <ColumnDefinition Width="*"/>
159 <ColumnDefinition Width="Auto" />
160 </Grid.ColumnDefinitions>
161 <TextBlock
162 Grid.Column="0"
163 Margin="5,0,10,0"
164 Width="90"
165 HorizontalAlignment="Left"
166 VerticalAlignment="Center"
167 Text="{locale:Locale ControllerSettingsInputDevice}" />
168 <ComboBox
169 Grid.Column="1"
170 Name="DeviceBox"
171 HorizontalAlignment="Stretch"
172 VerticalAlignment="Center"
173 ItemsSource="{Binding DeviceList}"
174 SelectedIndex="{Binding Device}" />
175 <Button
176 Grid.Column="2"
177 MinWidth="0"
178 Margin="5,0,0,0"
179 VerticalAlignment="Center"
180 Command="{ReflectionBinding LoadDevices}">
181 <ui:SymbolIcon
182 Symbol="Refresh"
183 FontSize="15"
184 Height="20"/>
185 </Button>
186 </Grid>
187 <!-- Controller Type -->
188 <Grid
189 Grid.Column="2"
190 Margin="2"
191 HorizontalAlignment="Stretch"
192 VerticalAlignment="Center">
193 <Grid.ColumnDefinitions>
194 <ColumnDefinition Width="Auto"/>
195 <ColumnDefinition Width="*" />
196 </Grid.ColumnDefinitions>
197 <TextBlock
198 Margin="5,0,10,0"
199 Width="90"
200 HorizontalAlignment="Left"
201 VerticalAlignment="Center"
202 Text="{locale:Locale ControllerSettingsControllerType}" />
203 <ComboBox
204 Grid.Column="1"
205 HorizontalAlignment="Stretch"
206 ItemsSource="{Binding Controllers}"
207 SelectedIndex="{Binding Controller}">
208 <ComboBox.ItemTemplate>
209 <DataTemplate DataType="models:ControllerModel">
210 <TextBlock Text="{Binding Name}" />
211 </DataTemplate>
212 </ComboBox.ItemTemplate>
213 </ComboBox>
214 </Grid>
215 </Grid>
216 </StackPanel>
36 <!-- Button / JoyStick Settings --> 217 <!-- Button / JoyStick Settings -->
37 <Grid 218 <Grid
38 Name="SettingButtons" 219 Name="SettingButtons"
39 MinHeight="450"> 220 MinHeight="450"
221 IsVisible="{Binding ShowSettings}">
40 <Grid.ColumnDefinitions> 222 <Grid.ColumnDefinitions>
41 <ColumnDefinition Width="Auto" /> 223 <ColumnDefinition Width="Auto" />
42 <ColumnDefinition Width="*" /> 224 <ColumnDefinition Width="*" />
@@ -75,9 +257,9 @@
75 VerticalAlignment="Center" 257 VerticalAlignment="Center"
76 Text="{locale:Locale ControllerSettingsTriggerZL}" 258 Text="{locale:Locale ControllerSettingsTriggerZL}"
77 TextAlignment="Center" /> 259 TextAlignment="Center" />
78 <ToggleButton Name="ButtonZl"> 260 <ToggleButton>
79 <TextBlock 261 <TextBlock
80 Text="{Binding Config.ButtonZl, Converter={StaticResource Key}}" 262 Text="{ReflectionBinding Configuration.ButtonZl, Mode=TwoWay, Converter={StaticResource Key}}"
81 TextAlignment="Center" /> 263 TextAlignment="Center" />
82 </ToggleButton> 264 </ToggleButton>
83 </StackPanel> 265 </StackPanel>
@@ -91,9 +273,9 @@
91 VerticalAlignment="Center" 273 VerticalAlignment="Center"
92 Text="{locale:Locale ControllerSettingsTriggerL}" 274 Text="{locale:Locale ControllerSettingsTriggerL}"
93 TextAlignment="Center" /> 275 TextAlignment="Center" />
94 <ToggleButton Name="ButtonL"> 276 <ToggleButton>
95 <TextBlock 277 <TextBlock
96 Text="{Binding Config.ButtonL, Converter={StaticResource Key}}" 278 Text="{ReflectionBinding Configuration.ButtonL, Mode=TwoWay, Converter={StaticResource Key}}"
97 TextAlignment="Center" /> 279 TextAlignment="Center" />
98 </ToggleButton> 280 </ToggleButton>
99 </StackPanel> 281 </StackPanel>
@@ -107,9 +289,9 @@
107 VerticalAlignment="Center" 289 VerticalAlignment="Center"
108 Text="{locale:Locale ControllerSettingsButtonMinus}" 290 Text="{locale:Locale ControllerSettingsButtonMinus}"
109 TextAlignment="Center" /> 291 TextAlignment="Center" />
110 <ToggleButton Name="ButtonMinus"> 292 <ToggleButton>
111 <TextBlock 293 <TextBlock
112 Text="{Binding Config.ButtonMinus, Converter={StaticResource Key}}" 294 Text="{ReflectionBinding Configuration.ButtonMinus, Mode=TwoWay, Converter={StaticResource Key}}"
113 TextAlignment="Center" /> 295 TextAlignment="Center" />
114 </ToggleButton> 296 </ToggleButton>
115 </StackPanel> 297 </StackPanel>
@@ -129,8 +311,100 @@
129 Margin="0,0,0,10" 311 Margin="0,0,0,10"
130 HorizontalAlignment="Center" 312 HorizontalAlignment="Center"
131 Text="{locale:Locale ControllerSettingsLStick}" /> 313 Text="{locale:Locale ControllerSettingsLStick}" />
314 <!-- Left Joystick Keyboard -->
315 <StackPanel
316 IsVisible="{Binding !IsController}"
317 Orientation="Vertical">
318 <!-- Left Joystick Button -->
319 <StackPanel
320 Margin="0,0,0,4"
321 Orientation="Horizontal">
322 <TextBlock
323 Margin="0,0,10,0"
324 Width="120"
325 HorizontalAlignment="Center"
326 VerticalAlignment="Center"
327 Text="{locale:Locale ControllerSettingsStickButton}"
328 TextAlignment="Center" />
329 <ToggleButton>
330 <TextBlock
331 Text="{ReflectionBinding Configuration.LeftKeyboardStickButton, Mode=TwoWay, Converter={StaticResource Key}}"
332 TextAlignment="Center" />
333 </ToggleButton>
334 </StackPanel>
335 <!-- Left Joystick Up -->
336 <StackPanel
337 Margin="0,0,0,4"
338 Orientation="Horizontal">
339 <TextBlock
340 Margin="0,0,10,0"
341 Width="120"
342 HorizontalAlignment="Center"
343 VerticalAlignment="Center"
344 Text="{locale:Locale ControllerSettingsStickUp}"
345 TextAlignment="Center" />
346 <ToggleButton>
347 <TextBlock
348 Text="{ReflectionBinding Configuration.LeftStickUp, Mode=TwoWay, Converter={StaticResource Key}}"
349 TextAlignment="Center" />
350 </ToggleButton>
351 </StackPanel>
352 <!-- Left Joystick Down -->
353 <StackPanel
354 Margin="0,0,0,4"
355 Orientation="Horizontal">
356 <TextBlock
357 Margin="0,0,10,0"
358 Width="120"
359 HorizontalAlignment="Center"
360 VerticalAlignment="Center"
361 Text="{locale:Locale ControllerSettingsStickDown}"
362 TextAlignment="Center" />
363 <ToggleButton>
364 <TextBlock
365 Text="{ReflectionBinding Configuration.LeftStickDown, Mode=TwoWay, Converter={StaticResource Key}}"
366 TextAlignment="Center" />
367 </ToggleButton>
368 </StackPanel>
369 <!-- Left Joystick Left -->
370 <StackPanel
371 Margin="0,0,0,4"
372 Orientation="Horizontal">
373 <TextBlock
374 Margin="0,0,10,0"
375 Width="120"
376 HorizontalAlignment="Center"
377 VerticalAlignment="Center"
378 Text="{locale:Locale ControllerSettingsStickLeft}"
379 TextAlignment="Center" />
380 <ToggleButton>
381 <TextBlock
382 Text="{ReflectionBinding Configuration.LeftStickLeft, Mode=TwoWay, Converter={StaticResource Key}}"
383 TextAlignment="Center" />
384 </ToggleButton>
385 </StackPanel>
386 <!-- Left Joystick Right -->
387 <StackPanel
388 Margin="0,0,0,4"
389 Orientation="Horizontal">
390 <TextBlock
391 Margin="0,0,10,0"
392 Width="120"
393 HorizontalAlignment="Center"
394 VerticalAlignment="Center"
395 Text="{locale:Locale ControllerSettingsStickRight}"
396 TextAlignment="Center" />
397 <ToggleButton>
398 <TextBlock
399 Text="{ReflectionBinding Configuration.LeftStickRight, Mode=TwoWay, Converter={StaticResource Key}}"
400 TextAlignment="Center" />
401 </ToggleButton>
402 </StackPanel>
403 </StackPanel>
132 <!-- Left Joystick Controller --> 404 <!-- Left Joystick Controller -->
133 <StackPanel Orientation="Vertical"> 405 <StackPanel
406 IsVisible="{Binding IsController}"
407 Orientation="Vertical">
134 <!-- Left Joystick Button --> 408 <!-- Left Joystick Button -->
135 <StackPanel 409 <StackPanel
136 Orientation="Horizontal"> 410 Orientation="Horizontal">
@@ -141,9 +415,9 @@
141 VerticalAlignment="Center" 415 VerticalAlignment="Center"
142 Text="{locale:Locale ControllerSettingsStickButton}" 416 Text="{locale:Locale ControllerSettingsStickButton}"
143 TextAlignment="Center" /> 417 TextAlignment="Center" />
144 <ToggleButton Name="LeftStickButton"> 418 <ToggleButton>
145 <TextBlock 419 <TextBlock
146 Text="{Binding Config.LeftStickButton, Converter={StaticResource Key}}" 420 Text="{ReflectionBinding Configuration.LeftControllerStickButton, Mode=TwoWay, Converter={StaticResource Key}}"
147 TextAlignment="Center" /> 421 TextAlignment="Center" />
148 </ToggleButton> 422 </ToggleButton>
149 </StackPanel> 423 </StackPanel>
@@ -158,22 +432,22 @@
158 VerticalAlignment="Center" 432 VerticalAlignment="Center"
159 Text="{locale:Locale ControllerSettingsStickStick}" 433 Text="{locale:Locale ControllerSettingsStickStick}"
160 TextAlignment="Center" /> 434 TextAlignment="Center" />
161 <ToggleButton Name="LeftJoystick" Tag="stick"> 435 <ToggleButton Tag="stick">
162 <TextBlock 436 <TextBlock
163 Text="{Binding Config.LeftJoystick, Converter={StaticResource Key}}" 437 Text="{ReflectionBinding Configuration.LeftJoystick, Mode=TwoWay, Converter={StaticResource Key}}"
164 TextAlignment="Center" /> 438 TextAlignment="Center" />
165 </ToggleButton> 439 </ToggleButton>
166 </StackPanel> 440 </StackPanel>
167 <Separator 441 <Separator
168 Margin="0,8,0,8" 442 Margin="0,8,0,8"
169 Height="1" /> 443 Height="1" />
170 <CheckBox IsChecked="{Binding Config.LeftInvertStickX}"> 444 <CheckBox IsChecked="{ReflectionBinding Configuration.LeftInvertStickX}">
171 <TextBlock Text="{locale:Locale ControllerSettingsStickInvertXAxis}" /> 445 <TextBlock Text="{locale:Locale ControllerSettingsStickInvertXAxis}" />
172 </CheckBox> 446 </CheckBox>
173 <CheckBox IsChecked="{Binding Config.LeftInvertStickY}"> 447 <CheckBox IsChecked="{ReflectionBinding Configuration.LeftInvertStickY}">
174 <TextBlock Text="{locale:Locale ControllerSettingsStickInvertYAxis}" /> 448 <TextBlock Text="{locale:Locale ControllerSettingsStickInvertYAxis}" />
175 </CheckBox> 449 </CheckBox>
176 <CheckBox IsChecked="{Binding Config.LeftRotate90}"> 450 <CheckBox IsChecked="{ReflectionBinding Configuration.LeftRotate90}">
177 <TextBlock Text="{locale:Locale ControllerSettingsRotate90}" /> 451 <TextBlock Text="{locale:Locale ControllerSettingsRotate90}" />
178 </CheckBox> 452 </CheckBox>
179 <Separator 453 <Separator
@@ -194,11 +468,11 @@
194 IsSnapToTickEnabled="True" 468 IsSnapToTickEnabled="True"
195 SmallChange="0.01" 469 SmallChange="0.01"
196 Minimum="0" 470 Minimum="0"
197 Value="{Binding Config.DeadzoneLeft, Mode=TwoWay}" /> 471 Value="{ReflectionBinding Configuration.DeadzoneLeft, Mode=TwoWay}" />
198 <TextBlock 472 <TextBlock
199 VerticalAlignment="Center" 473 VerticalAlignment="Center"
200 Width="25" 474 Width="25"
201 Text="{Binding Config.DeadzoneLeft, StringFormat=\{0:0.00\}}" /> 475 Text="{ReflectionBinding Configuration.DeadzoneLeft, StringFormat=\{0:0.00\}}" />
202 </StackPanel> 476 </StackPanel>
203 <TextBlock 477 <TextBlock
204 HorizontalAlignment="Center" 478 HorizontalAlignment="Center"
@@ -214,11 +488,11 @@
214 IsSnapToTickEnabled="True" 488 IsSnapToTickEnabled="True"
215 SmallChange="0.01" 489 SmallChange="0.01"
216 Minimum="0" 490 Minimum="0"
217 Value="{Binding Config.RangeLeft, Mode=TwoWay}" /> 491 Value="{ReflectionBinding Configuration.RangeLeft, Mode=TwoWay}" />
218 <TextBlock 492 <TextBlock
219 VerticalAlignment="Center" 493 VerticalAlignment="Center"
220 Width="25" 494 Width="25"
221 Text="{Binding Config.RangeLeft, StringFormat=\{0:0.00\}}" /> 495 Text="{ReflectionBinding Configuration.RangeLeft, StringFormat=\{0:0.00\}}" />
222 </StackPanel> 496 </StackPanel>
223 </StackPanel> 497 </StackPanel>
224 </StackPanel> 498 </StackPanel>
@@ -251,9 +525,9 @@
251 VerticalAlignment="Center" 525 VerticalAlignment="Center"
252 Text="{locale:Locale ControllerSettingsDPadUp}" 526 Text="{locale:Locale ControllerSettingsDPadUp}"
253 TextAlignment="Center" /> 527 TextAlignment="Center" />
254 <ToggleButton Name="DpadUp"> 528 <ToggleButton>
255 <TextBlock 529 <TextBlock
256 Text="{Binding Config.DpadUp, Converter={StaticResource Key}}" 530 Text="{ReflectionBinding Configuration.DpadUp, Mode=TwoWay, Converter={StaticResource Key}}"
257 TextAlignment="Center" /> 531 TextAlignment="Center" />
258 </ToggleButton> 532 </ToggleButton>
259 </StackPanel> 533 </StackPanel>
@@ -268,9 +542,9 @@
268 VerticalAlignment="Center" 542 VerticalAlignment="Center"
269 Text="{locale:Locale ControllerSettingsDPadDown}" 543 Text="{locale:Locale ControllerSettingsDPadDown}"
270 TextAlignment="Center" /> 544 TextAlignment="Center" />
271 <ToggleButton Name="DpadDown"> 545 <ToggleButton>
272 <TextBlock 546 <TextBlock
273 Text="{Binding Config.DpadDown, Converter={StaticResource Key}}" 547 Text="{ReflectionBinding Configuration.DpadDown, Mode=TwoWay, Converter={StaticResource Key}}"
274 TextAlignment="Center" /> 548 TextAlignment="Center" />
275 </ToggleButton> 549 </ToggleButton>
276 </StackPanel> 550 </StackPanel>
@@ -285,9 +559,9 @@
285 VerticalAlignment="Center" 559 VerticalAlignment="Center"
286 Text="{locale:Locale ControllerSettingsDPadLeft}" 560 Text="{locale:Locale ControllerSettingsDPadLeft}"
287 TextAlignment="Center" /> 561 TextAlignment="Center" />
288 <ToggleButton Name="DpadLeft"> 562 <ToggleButton>
289 <TextBlock 563 <TextBlock
290 Text="{Binding Config.DpadLeft, Converter={StaticResource Key}}" 564 Text="{ReflectionBinding Configuration.DpadLeft, Mode=TwoWay, Converter={StaticResource Key}}"
291 TextAlignment="Center" /> 565 TextAlignment="Center" />
292 </ToggleButton> 566 </ToggleButton>
293 </StackPanel> 567 </StackPanel>
@@ -302,9 +576,9 @@
302 VerticalAlignment="Center" 576 VerticalAlignment="Center"
303 Text="{locale:Locale ControllerSettingsDPadRight}" 577 Text="{locale:Locale ControllerSettingsDPadRight}"
304 TextAlignment="Center" /> 578 TextAlignment="Center" />
305 <ToggleButton Name="DpadRight"> 579 <ToggleButton>
306 <TextBlock 580 <TextBlock
307 Text="{Binding Config.DpadRight, Converter={StaticResource Key}}" 581 Text="{ReflectionBinding Configuration.DpadRight, Mode=TwoWay, Converter={StaticResource Key}}"
308 TextAlignment="Center" /> 582 TextAlignment="Center" />
309 </ToggleButton> 583 </ToggleButton>
310 </StackPanel> 584 </StackPanel>
@@ -317,13 +591,6 @@
317 Grid.Column="1" 591 Grid.Column="1"
318 HorizontalAlignment="Stretch" 592 HorizontalAlignment="Stretch"
319 VerticalAlignment="Stretch"> 593 VerticalAlignment="Stretch">
320 <!-- Controller Picture -->
321 <Image
322 Margin="0,10"
323 MaxHeight="300"
324 HorizontalAlignment="Stretch"
325 VerticalAlignment="Stretch"
326 Source="{Binding Image}" />
327 <Border 594 <Border
328 BorderBrush="{DynamicResource ThemeControlBorderColor}" 595 BorderBrush="{DynamicResource ThemeControlBorderColor}"
329 BorderThickness="1" 596 BorderThickness="1"
@@ -345,89 +612,92 @@
345 IsSnapToTickEnabled="True" 612 IsSnapToTickEnabled="True"
346 SmallChange="0.01" 613 SmallChange="0.01"
347 Minimum="0" 614 Minimum="0"
348 Value="{Binding Config.TriggerThreshold, Mode=TwoWay}" /> 615 Value="{ReflectionBinding Configuration.TriggerThreshold, Mode=TwoWay}" />
349 <TextBlock 616 <TextBlock
350 Width="25" 617 Width="25"
351 Text="{Binding Config.TriggerThreshold, StringFormat=\{0:0.00\}}" /> 618 Text="{ReflectionBinding Configuration.TriggerThreshold, StringFormat=\{0:0.00\}}" />
352 </StackPanel> 619 </StackPanel>
353 <StackPanel 620 <StackPanel
354 Orientation="Vertical" 621 Margin="0,4,0,0"
355 IsVisible="{Binding HasSides}"> 622 HorizontalAlignment="Center"
356 <StackPanel 623 VerticalAlignment="Center"
357 Margin="0,4,0,0" 624 IsVisible="{Binding !IsRight}"
625 Orientation="Horizontal">
626 <TextBlock
627 Width="20"
358 HorizontalAlignment="Center" 628 HorizontalAlignment="Center"
359 VerticalAlignment="Center" 629 VerticalAlignment="Center"
360 IsVisible="{Binding IsLeft}" 630 Text="{locale:Locale ControllerSettingsLeftSR}"
361 Orientation="Horizontal"> 631 TextAlignment="Center" />
632 <ToggleButton>
362 <TextBlock 633 <TextBlock
363 Width="20" 634 Text="{ReflectionBinding Configuration.LeftButtonSr, Mode=TwoWay, Converter={StaticResource Key}}"
364 HorizontalAlignment="Center"
365 VerticalAlignment="Center"
366 Text="{locale:Locale ControllerSettingsLeftSR}"
367 TextAlignment="Center" /> 635 TextAlignment="Center" />
368 <ToggleButton Name="LeftButtonSr"> 636 </ToggleButton>
369 <TextBlock 637 </StackPanel>
370 Text="{Binding Config.LeftButtonSr, Converter={StaticResource Key}}" 638 <StackPanel
371 TextAlignment="Center" /> 639 Margin="0,4,0,0"
372 </ToggleButton> 640 HorizontalAlignment="Center"
373 </StackPanel> 641 VerticalAlignment="Center"
374 <StackPanel 642 IsVisible="{Binding !IsRight}"
375 Margin="0,4,0,0" 643 Orientation="Horizontal">
644 <TextBlock
645 Width="20"
376 HorizontalAlignment="Center" 646 HorizontalAlignment="Center"
377 VerticalAlignment="Center" 647 VerticalAlignment="Center"
378 IsVisible="{Binding IsLeft}" 648 Text="{locale:Locale ControllerSettingsLeftSL}"
379 Orientation="Horizontal"> 649 TextAlignment="Center" />
650 <ToggleButton>
380 <TextBlock 651 <TextBlock
381 Width="20" 652 Text="{ReflectionBinding Configuration.LeftButtonSl, Mode=TwoWay, Converter={StaticResource Key}}"
382 HorizontalAlignment="Center"
383 VerticalAlignment="Center"
384 Text="{locale:Locale ControllerSettingsLeftSL}"
385 TextAlignment="Center" /> 653 TextAlignment="Center" />
386 <ToggleButton Name="LeftButtonSl"> 654 </ToggleButton>
387 <TextBlock 655 </StackPanel>
388 Text="{Binding Config.LeftButtonSl, Converter={StaticResource Key}}" 656 <StackPanel
389 TextAlignment="Center" /> 657 Margin="0,4,0,0"
390 </ToggleButton> 658 HorizontalAlignment="Center"
391 </StackPanel> 659 VerticalAlignment="Center"
392 <StackPanel 660 IsVisible="{Binding !IsLeft}"
393 Margin="0,4,0,0" 661 Orientation="Horizontal">
662 <TextBlock
663 Width="20"
394 HorizontalAlignment="Center" 664 HorizontalAlignment="Center"
395 VerticalAlignment="Center" 665 VerticalAlignment="Center"
396 IsVisible="{Binding IsRight}" 666 Text="{locale:Locale ControllerSettingsRightSR}"
397 Orientation="Horizontal"> 667 TextAlignment="Center" />
668 <ToggleButton>
398 <TextBlock 669 <TextBlock
399 Width="20" 670 Text="{ReflectionBinding Configuration.RightButtonSr, Mode=TwoWay, Converter={StaticResource Key}}"
400 HorizontalAlignment="Center"
401 VerticalAlignment="Center"
402 Text="{locale:Locale ControllerSettingsRightSR}"
403 TextAlignment="Center" /> 671 TextAlignment="Center" />
404 <ToggleButton Name="RightButtonSr"> 672 </ToggleButton>
405 <TextBlock 673 </StackPanel>
406 Text="{Binding Config.RightButtonSr, Converter={StaticResource Key}}" 674 <StackPanel
407 TextAlignment="Center" /> 675 Margin="0,4,0,0"
408 </ToggleButton> 676 HorizontalAlignment="Center"
409 </StackPanel> 677 VerticalAlignment="Center"
410 <StackPanel 678 IsVisible="{Binding !IsLeft}"
411 Margin="0,4,0,0" 679 Orientation="Horizontal">
680 <TextBlock
681 Width="20"
412 HorizontalAlignment="Center" 682 HorizontalAlignment="Center"
413 VerticalAlignment="Center" 683 VerticalAlignment="Center"
414 IsVisible="{Binding IsRight}" 684 Text="{locale:Locale ControllerSettingsRightSL}"
415 Orientation="Horizontal"> 685 TextAlignment="Center" />
686 <ToggleButton>
416 <TextBlock 687 <TextBlock
417 Width="20" 688 Text="{ReflectionBinding Configuration.RightButtonSl, Mode=TwoWay, Converter={StaticResource Key}}"
418 HorizontalAlignment="Center"
419 VerticalAlignment="Center"
420 Text="{locale:Locale ControllerSettingsRightSL}"
421 TextAlignment="Center" /> 689 TextAlignment="Center" />
422 <ToggleButton Name="RightButtonSl"> 690 </ToggleButton>
423 <TextBlock
424 Text="{Binding Config.RightButtonSl, Converter={StaticResource Key}}"
425 TextAlignment="Center" />
426 </ToggleButton>
427 </StackPanel>
428 </StackPanel> 691 </StackPanel>
429 </StackPanel> 692 </StackPanel>
430 </Border> 693 </Border>
694 <!-- Controller Picture -->
695 <Image
696 Margin="0,10,0,0"
697 MaxHeight="300"
698 HorizontalAlignment="Stretch"
699 VerticalAlignment="Stretch"
700 Source="{Binding Image}" />
431 <!-- Motion + Rumble --> 701 <!-- Motion + Rumble -->
432 <StackPanel 702 <StackPanel
433 Margin="0,10,0,0" 703 Margin="0,10,0,0"
@@ -439,7 +709,8 @@
439 BorderThickness="1" 709 BorderThickness="1"
440 CornerRadius="5" 710 CornerRadius="5"
441 VerticalAlignment="Bottom" 711 VerticalAlignment="Bottom"
442 HorizontalAlignment="Stretch"> 712 HorizontalAlignment="Stretch"
713 IsVisible="{Binding IsController}">
443 <Grid> 714 <Grid>
444 <Grid.ColumnDefinitions> 715 <Grid.ColumnDefinitions>
445 <ColumnDefinition Width="*" /> 716 <ColumnDefinition Width="*" />
@@ -449,7 +720,7 @@
449 Margin="10" 720 Margin="10"
450 MinWidth="0" 721 MinWidth="0"
451 Grid.Column="0" 722 Grid.Column="0"
452 IsChecked="{Binding Config.EnableMotion, Mode=TwoWay}"> 723 IsChecked="{ReflectionBinding Configuration.EnableMotion, Mode=TwoWay}">
453 <TextBlock Text="{locale:Locale ControllerSettingsMotion}" /> 724 <TextBlock Text="{locale:Locale ControllerSettingsMotion}" />
454 </CheckBox> 725 </CheckBox>
455 <Button 726 <Button
@@ -465,6 +736,7 @@
465 BorderThickness="1" 736 BorderThickness="1"
466 CornerRadius="5" 737 CornerRadius="5"
467 HorizontalAlignment="Stretch" 738 HorizontalAlignment="Stretch"
739 IsVisible="{Binding IsController}"
468 Margin="0,-1,0,0"> 740 Margin="0,-1,0,0">
469 <Grid> 741 <Grid>
470 <Grid.ColumnDefinitions> 742 <Grid.ColumnDefinitions>
@@ -475,7 +747,7 @@
475 Margin="10" 747 Margin="10"
476 MinWidth="0" 748 MinWidth="0"
477 Grid.Column="0" 749 Grid.Column="0"
478 IsChecked="{Binding Config.EnableRumble, Mode=TwoWay}"> 750 IsChecked="{ReflectionBinding Configuration.EnableRumble, Mode=TwoWay}">
479 <TextBlock Text="{locale:Locale ControllerSettingsRumble}" /> 751 <TextBlock Text="{locale:Locale ControllerSettingsRumble}" />
480 </CheckBox> 752 </CheckBox>
481 <Button 753 <Button
@@ -521,9 +793,9 @@
521 VerticalAlignment="Center" 793 VerticalAlignment="Center"
522 Text="{locale:Locale ControllerSettingsTriggerZR}" 794 Text="{locale:Locale ControllerSettingsTriggerZR}"
523 TextAlignment="Center" /> 795 TextAlignment="Center" />
524 <ToggleButton Name="ButtonZr"> 796 <ToggleButton>
525 <TextBlock 797 <TextBlock
526 Text="{Binding Config.ButtonZr, Converter={StaticResource Key}}" 798 Text="{ReflectionBinding Configuration.ButtonZr, Mode=TwoWay, Converter={StaticResource Key}}"
527 TextAlignment="Center" /> 799 TextAlignment="Center" />
528 </ToggleButton> 800 </ToggleButton>
529 </StackPanel> 801 </StackPanel>
@@ -539,9 +811,9 @@
539 VerticalAlignment="Center" 811 VerticalAlignment="Center"
540 Text="{locale:Locale ControllerSettingsTriggerR}" 812 Text="{locale:Locale ControllerSettingsTriggerR}"
541 TextAlignment="Center" /> 813 TextAlignment="Center" />
542 <ToggleButton Name="ButtonR"> 814 <ToggleButton>
543 <TextBlock 815 <TextBlock
544 Text="{Binding Config.ButtonR, Converter={StaticResource Key}}" 816 Text="{ReflectionBinding Configuration.ButtonR, Mode=TwoWay, Converter={StaticResource Key}}"
545 TextAlignment="Center" /> 817 TextAlignment="Center" />
546 </ToggleButton> 818 </ToggleButton>
547 </StackPanel> 819 </StackPanel>
@@ -557,15 +829,15 @@
557 VerticalAlignment="Center" 829 VerticalAlignment="Center"
558 Text="{locale:Locale ControllerSettingsButtonPlus}" 830 Text="{locale:Locale ControllerSettingsButtonPlus}"
559 TextAlignment="Center" /> 831 TextAlignment="Center" />
560 <ToggleButton Name="ButtonPlus"> 832 <ToggleButton>
561 <TextBlock 833 <TextBlock
562 Text="{Binding Config.ButtonPlus, Converter={StaticResource Key}}" 834 Text="{ReflectionBinding Configuration.ButtonPlus, Mode=TwoWay, Converter={StaticResource Key}}"
563 TextAlignment="Center" /> 835 TextAlignment="Center" />
564 </ToggleButton> 836 </ToggleButton>
565 </StackPanel> 837 </StackPanel>
566 </Grid> 838 </Grid>
567 </Border> 839 </Border>
568 <!-- Right Buttons --> 840 <!-- Right Joystick -->
569 <Border 841 <Border
570 BorderBrush="{DynamicResource ThemeControlBorderColor}" 842 BorderBrush="{DynamicResource ThemeControlBorderColor}"
571 BorderThickness="1" 843 BorderThickness="1"
@@ -592,9 +864,9 @@
592 VerticalAlignment="Center" 864 VerticalAlignment="Center"
593 Text="{locale:Locale ControllerSettingsButtonA}" 865 Text="{locale:Locale ControllerSettingsButtonA}"
594 TextAlignment="Center" /> 866 TextAlignment="Center" />
595 <ToggleButton Name="ButtonA"> 867 <ToggleButton>
596 <TextBlock 868 <TextBlock
597 Text="{Binding Config.ButtonA, Converter={StaticResource Key}}" 869 Text="{ReflectionBinding Configuration.ButtonA, Mode=TwoWay, Converter={StaticResource Key}}"
598 TextAlignment="Center" /> 870 TextAlignment="Center" />
599 </ToggleButton> 871 </ToggleButton>
600 </StackPanel> 872 </StackPanel>
@@ -609,9 +881,9 @@
609 VerticalAlignment="Center" 881 VerticalAlignment="Center"
610 Text="{locale:Locale ControllerSettingsButtonB}" 882 Text="{locale:Locale ControllerSettingsButtonB}"
611 TextAlignment="Center" /> 883 TextAlignment="Center" />
612 <ToggleButton Name="ButtonB"> 884 <ToggleButton>
613 <TextBlock 885 <TextBlock
614 Text="{Binding Config.ButtonB, Converter={StaticResource Key}}" 886 Text="{ReflectionBinding Configuration.ButtonB, Mode=TwoWay, Converter={StaticResource Key}}"
615 TextAlignment="Center" /> 887 TextAlignment="Center" />
616 </ToggleButton> 888 </ToggleButton>
617 </StackPanel> 889 </StackPanel>
@@ -626,9 +898,9 @@
626 VerticalAlignment="Center" 898 VerticalAlignment="Center"
627 Text="{locale:Locale ControllerSettingsButtonX}" 899 Text="{locale:Locale ControllerSettingsButtonX}"
628 TextAlignment="Center" /> 900 TextAlignment="Center" />
629 <ToggleButton Name="ButtonX"> 901 <ToggleButton>
630 <TextBlock 902 <TextBlock
631 Text="{Binding Config.ButtonX, Converter={StaticResource Key}}" 903 Text="{ReflectionBinding Configuration.ButtonX, Mode=TwoWay, Converter={StaticResource Key}}"
632 TextAlignment="Center" /> 904 TextAlignment="Center" />
633 </ToggleButton> 905 </ToggleButton>
634 </StackPanel> 906 </StackPanel>
@@ -643,9 +915,9 @@
643 VerticalAlignment="Center" 915 VerticalAlignment="Center"
644 Text="{locale:Locale ControllerSettingsButtonY}" 916 Text="{locale:Locale ControllerSettingsButtonY}"
645 TextAlignment="Center" /> 917 TextAlignment="Center" />
646 <ToggleButton Name="ButtonY"> 918 <ToggleButton>
647 <TextBlock 919 <TextBlock
648 Text="{Binding Config.ButtonY, Converter={StaticResource Key}}" 920 Text="{ReflectionBinding Configuration.ButtonY, Mode=TwoWay, Converter={StaticResource Key}}"
649 TextAlignment="Center" /> 921 TextAlignment="Center" />
650 </ToggleButton> 922 </ToggleButton>
651 </StackPanel> 923 </StackPanel>
@@ -665,8 +937,100 @@
665 Margin="0,0,0,10" 937 Margin="0,0,0,10"
666 HorizontalAlignment="Center" 938 HorizontalAlignment="Center"
667 Text="{locale:Locale ControllerSettingsRStick}" /> 939 Text="{locale:Locale ControllerSettingsRStick}" />
940 <!-- Right Joystick Keyboard -->
941 <StackPanel
942 IsVisible="{Binding !IsController}"
943 Orientation="Vertical">
944 <!-- Right Joystick Button -->
945 <StackPanel
946 Margin="0,0,0,4"
947 Orientation="Horizontal">
948 <TextBlock
949 Margin="0,0,10,0"
950 Width="120"
951 HorizontalAlignment="Center"
952 VerticalAlignment="Center"
953 Text="{locale:Locale ControllerSettingsStickButton}"
954 TextAlignment="Center" />
955 <ToggleButton>
956 <TextBlock
957 Text="{ReflectionBinding Configuration.RightKeyboardStickButton, Mode=TwoWay, Converter={StaticResource Key}}"
958 TextAlignment="Center" />
959 </ToggleButton>
960 </StackPanel>
961 <!-- Right Joystick Up -->
962 <StackPanel
963 Margin="0,0,0,4"
964 Orientation="Horizontal">
965 <TextBlock
966 Margin="0,0,10,0"
967 Width="120"
968 HorizontalAlignment="Center"
969 VerticalAlignment="Center"
970 Text="{locale:Locale ControllerSettingsStickUp}"
971 TextAlignment="Center" />
972 <ToggleButton>
973 <TextBlock
974 Text="{ReflectionBinding Configuration.RightStickUp, Mode=TwoWay, Converter={StaticResource Key}}"
975 TextAlignment="Center" />
976 </ToggleButton>
977 </StackPanel>
978 <!-- Right Joystick Down -->
979 <StackPanel
980 Margin="0,0,0,4"
981 Orientation="Horizontal">
982 <TextBlock
983 Margin="0,0,10,0"
984 Width="120"
985 HorizontalAlignment="Center"
986 VerticalAlignment="Center"
987 Text="{locale:Locale ControllerSettingsStickDown}"
988 TextAlignment="Center" />
989 <ToggleButton>
990 <TextBlock
991 Text="{ReflectionBinding Configuration.RightStickDown, Mode=TwoWay, Converter={StaticResource Key}}"
992 TextAlignment="Center" />
993 </ToggleButton>
994 </StackPanel>
995 <!-- Right Joystick Left -->
996 <StackPanel
997 Margin="0,0,0,4"
998 Orientation="Horizontal">
999 <TextBlock
1000 Margin="0,0,10,0"
1001 Width="120"
1002 HorizontalAlignment="Center"
1003 VerticalAlignment="Center"
1004 Text="{locale:Locale ControllerSettingsStickLeft}"
1005 TextAlignment="Center" />
1006 <ToggleButton>
1007 <TextBlock
1008 Text="{ReflectionBinding Configuration.RightStickLeft, Mode=TwoWay, Converter={StaticResource Key}}"
1009 TextAlignment="Center" />
1010 </ToggleButton>
1011 </StackPanel>
1012 <!-- Right Joystick Right -->
1013 <StackPanel
1014 Margin="0,0,0,4"
1015 Orientation="Horizontal">
1016 <TextBlock
1017 Margin="0,0,10,0"
1018 Width="120"
1019 HorizontalAlignment="Center"
1020 VerticalAlignment="Center"
1021 Text="{locale:Locale ControllerSettingsStickRight}"
1022 TextAlignment="Center" />
1023 <ToggleButton>
1024 <TextBlock
1025 Text="{ReflectionBinding Configuration.RightStickRight, Mode=TwoWay, Converter={StaticResource Key}}"
1026 TextAlignment="Center" />
1027 </ToggleButton>
1028 </StackPanel>
1029 </StackPanel>
668 <!-- Right Joystick Controller --> 1030 <!-- Right Joystick Controller -->
669 <StackPanel Orientation="Vertical"> 1031 <StackPanel
1032 IsVisible="{Binding IsController}"
1033 Orientation="Vertical">
670 <!-- Right Joystick Button --> 1034 <!-- Right Joystick Button -->
671 <StackPanel 1035 <StackPanel
672 Orientation="Horizontal"> 1036 Orientation="Horizontal">
@@ -677,9 +1041,9 @@
677 VerticalAlignment="Center" 1041 VerticalAlignment="Center"
678 Text="{locale:Locale ControllerSettingsStickButton}" 1042 Text="{locale:Locale ControllerSettingsStickButton}"
679 TextAlignment="Center" /> 1043 TextAlignment="Center" />
680 <ToggleButton Name="RightStickButton"> 1044 <ToggleButton>
681 <TextBlock 1045 <TextBlock
682 Text="{Binding Config.RightStickButton, Converter={StaticResource Key}}" 1046 Text="{ReflectionBinding Configuration.RightControllerStickButton, Mode=TwoWay, Converter={StaticResource Key}}"
683 TextAlignment="Center" /> 1047 TextAlignment="Center" />
684 </ToggleButton> 1048 </ToggleButton>
685 </StackPanel> 1049 </StackPanel>
@@ -695,20 +1059,20 @@
695 VerticalAlignment="Center" 1059 VerticalAlignment="Center"
696 Text="{locale:Locale ControllerSettingsStickStick}" 1060 Text="{locale:Locale ControllerSettingsStickStick}"
697 TextAlignment="Center" /> 1061 TextAlignment="Center" />
698 <ToggleButton Name="RightJoystick" Tag="stick"> 1062 <ToggleButton Tag="stick">
699 <TextBlock 1063 <TextBlock
700 Text="{Binding Config.RightJoystick, Converter={StaticResource Key}}" 1064 Text="{ReflectionBinding Configuration.RightJoystick, Mode=TwoWay, Converter={StaticResource Key}}"
701 TextAlignment="Center" /> 1065 TextAlignment="Center" />
702 </ToggleButton> 1066 </ToggleButton>
703 </StackPanel> 1067 </StackPanel>
704 <Separator Margin="0,8,0,8" Height="1" /> 1068 <Separator Margin="0,8,0,8" Height="1" />
705 <CheckBox IsChecked="{Binding Config.RightInvertStickX}"> 1069 <CheckBox IsChecked="{ReflectionBinding Configuration.RightInvertStickX}">
706 <TextBlock Text="{locale:Locale ControllerSettingsStickInvertXAxis}" /> 1070 <TextBlock Text="{locale:Locale ControllerSettingsStickInvertXAxis}" />
707 </CheckBox> 1071 </CheckBox>
708 <CheckBox IsChecked="{Binding Config.RightInvertStickY}"> 1072 <CheckBox IsChecked="{ReflectionBinding Configuration.RightInvertStickY}">
709 <TextBlock Text="{locale:Locale ControllerSettingsStickInvertYAxis}" /> 1073 <TextBlock Text="{locale:Locale ControllerSettingsStickInvertYAxis}" />
710 </CheckBox> 1074 </CheckBox>
711 <CheckBox IsChecked="{Binding Config.RightRotate90}"> 1075 <CheckBox IsChecked="{ReflectionBinding Configuration.RightRotate90}">
712 <TextBlock Text="{locale:Locale ControllerSettingsRotate90}" /> 1076 <TextBlock Text="{locale:Locale ControllerSettingsRotate90}" />
713 </CheckBox> 1077 </CheckBox>
714 <Separator Margin="0,8,0,8" Height="1" /> 1078 <Separator Margin="0,8,0,8" Height="1" />
@@ -729,11 +1093,11 @@
729 Padding="0" 1093 Padding="0"
730 VerticalAlignment="Center" 1094 VerticalAlignment="Center"
731 Minimum="0" 1095 Minimum="0"
732 Value="{Binding Config.DeadzoneRight, Mode=TwoWay}" /> 1096 Value="{ReflectionBinding Configuration.DeadzoneRight, Mode=TwoWay}" />
733 <TextBlock 1097 <TextBlock
734 VerticalAlignment="Center" 1098 VerticalAlignment="Center"
735 Width="25" 1099 Width="25"
736 Text="{Binding Config.DeadzoneRight, StringFormat=\{0:0.00\}}" /> 1100 Text="{ReflectionBinding Configuration.DeadzoneRight, StringFormat=\{0:0.00\}}" />
737 </StackPanel> 1101 </StackPanel>
738 <TextBlock 1102 <TextBlock
739 HorizontalAlignment="Center" 1103 HorizontalAlignment="Center"
@@ -749,11 +1113,11 @@
749 IsSnapToTickEnabled="True" 1113 IsSnapToTickEnabled="True"
750 SmallChange="0.01" 1114 SmallChange="0.01"
751 Minimum="0" 1115 Minimum="0"
752 Value="{Binding Config.RangeRight, Mode=TwoWay}" /> 1116 Value="{ReflectionBinding Configuration.RangeRight, Mode=TwoWay}" />
753 <TextBlock 1117 <TextBlock
754 VerticalAlignment="Center" 1118 VerticalAlignment="Center"
755 Width="25" 1119 Width="25"
756 Text="{Binding Config.RangeRight, StringFormat=\{0:0.00\}}" /> 1120 Text="{ReflectionBinding Configuration.RangeRight, StringFormat=\{0:0.00\}}" />
757 </StackPanel> 1121 </StackPanel>
758 </StackPanel> 1122 </StackPanel>
759 </StackPanel> 1123 </StackPanel>
diff --git a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs
index 52fc62389..351297060 100644
--- a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs
@@ -1,28 +1,35 @@
1using Avalonia;
2using Avalonia.Controls; 1using Avalonia.Controls;
3using Avalonia.Controls.Primitives; 2using Avalonia.Controls.Primitives;
4using Avalonia.Input; 3using Avalonia.Input;
5using Avalonia.Interactivity; 4using Avalonia.Interactivity;
6using Avalonia.LogicalTree; 5using Avalonia.LogicalTree;
6using Ryujinx.Ava.Common.Locale;
7using Ryujinx.Ava.UI.Helpers; 7using Ryujinx.Ava.UI.Helpers;
8using Ryujinx.Ava.UI.ViewModels.Input; 8using Ryujinx.Ava.UI.Models;
9using Ryujinx.Ava.UI.ViewModels;
9using Ryujinx.Common.Configuration.Hid.Controller; 10using Ryujinx.Common.Configuration.Hid.Controller;
10using Ryujinx.Input; 11using Ryujinx.Input;
11using Ryujinx.Input.Assigner; 12using Ryujinx.Input.Assigner;
13using System;
12 14
13namespace Ryujinx.Ava.UI.Views.Input 15namespace Ryujinx.Ava.UI.Views.Input
14{ 16{
15 public partial class ControllerInputView : UserControl 17 public partial class ControllerInputView : UserControl
16 { 18 {
19 private bool _dialogOpen;
20
17 private ButtonKeyAssigner _currentAssigner; 21 private ButtonKeyAssigner _currentAssigner;
22 internal ControllerInputViewModel ViewModel { get; set; }
18 23
19 public ControllerInputView() 24 public ControllerInputView()
20 { 25 {
26 DataContext = ViewModel = new ControllerInputViewModel(this);
27
21 InitializeComponent(); 28 InitializeComponent();
22 29
23 foreach (ILogical visual in SettingButtons.GetLogicalDescendants()) 30 foreach (ILogical visual in SettingButtons.GetLogicalDescendants())
24 { 31 {
25 if (visual is ToggleButton button and not CheckBox) 32 if (visual is ToggleButton button && visual is not CheckBox)
26 { 33 {
27 button.IsCheckedChanged += Button_IsCheckedChanged; 34 button.IsCheckedChanged += Button_IsCheckedChanged;
28 } 35 }
@@ -52,7 +59,7 @@ namespace Ryujinx.Ava.UI.Views.Input
52 59
53 bool isStick = button.Tag != null && button.Tag.ToString() == "stick"; 60 bool isStick = button.Tag != null && button.Tag.ToString() == "stick";
54 61
55 if (_currentAssigner == null && (bool)button.IsChecked) 62 if (_currentAssigner == null)
56 { 63 {
57 _currentAssigner = new ButtonKeyAssigner(button); 64 _currentAssigner = new ButtonKeyAssigner(button);
58 65
@@ -60,86 +67,14 @@ namespace Ryujinx.Ava.UI.Views.Input
60 67
61 PointerPressed += MouseClick; 68 PointerPressed += MouseClick;
62 69
63 IKeyboard keyboard = (IKeyboard)(DataContext as ControllerInputViewModel).parentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations. 70 IKeyboard keyboard = (IKeyboard)ViewModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
64 IButtonAssigner assigner = CreateButtonAssigner(isStick); 71 IButtonAssigner assigner = CreateButtonAssigner(isStick);
65 72
66 _currentAssigner.ButtonAssigned += (sender, e) => 73 _currentAssigner.ButtonAssigned += (sender, e) =>
67 { 74 {
68 if (e.ButtonValue.HasValue) 75 if (e.IsAssigned)
69 { 76 {
70 var viewModel = (DataContext as ControllerInputViewModel); 77 ViewModel.IsModified = true;
71 var buttonValue = e.ButtonValue.Value;
72 viewModel.parentModel.IsModified = true;
73
74 switch (button.Name)
75 {
76 case "ButtonZl":
77 viewModel.Config.ButtonZl = buttonValue.AsGamepadButtonInputId();
78 break;
79 case "ButtonL":
80 viewModel.Config.ButtonL = buttonValue.AsGamepadButtonInputId();
81 break;
82 case "ButtonMinus":
83 viewModel.Config.ButtonMinus = buttonValue.AsGamepadButtonInputId();
84 break;
85 case "LeftStickButton":
86 viewModel.Config.LeftStickButton = buttonValue.AsGamepadButtonInputId();
87 break;
88 case "LeftJoystick":
89 viewModel.Config.LeftJoystick = buttonValue.AsGamepadStickId();
90 break;
91 case "DpadUp":
92 viewModel.Config.DpadUp = buttonValue.AsGamepadButtonInputId();
93 break;
94 case "DpadDown":
95 viewModel.Config.DpadDown = buttonValue.AsGamepadButtonInputId();
96 break;
97 case "DpadLeft":
98 viewModel.Config.DpadLeft = buttonValue.AsGamepadButtonInputId();
99 break;
100 case "DpadRight":
101 viewModel.Config.DpadRight = buttonValue.AsGamepadButtonInputId();
102 break;
103 case "LeftButtonSr":
104 viewModel.Config.LeftButtonSr = buttonValue.AsGamepadButtonInputId();
105 break;
106 case "LeftButtonSl":
107 viewModel.Config.LeftButtonSl = buttonValue.AsGamepadButtonInputId();
108 break;
109 case "RightButtonSr":
110 viewModel.Config.RightButtonSr = buttonValue.AsGamepadButtonInputId();
111 break;
112 case "RightButtonSl":
113 viewModel.Config.RightButtonSl = buttonValue.AsGamepadButtonInputId();
114 break;
115 case "ButtonZr":
116 viewModel.Config.ButtonZr = buttonValue.AsGamepadButtonInputId();
117 break;
118 case "ButtonR":
119 viewModel.Config.ButtonR = buttonValue.AsGamepadButtonInputId();
120 break;
121 case "ButtonPlus":
122 viewModel.Config.ButtonPlus = buttonValue.AsGamepadButtonInputId();
123 break;
124 case "ButtonA":
125 viewModel.Config.ButtonA = buttonValue.AsGamepadButtonInputId();
126 break;
127 case "ButtonB":
128 viewModel.Config.ButtonB = buttonValue.AsGamepadButtonInputId();
129 break;
130 case "ButtonX":
131 viewModel.Config.ButtonX = buttonValue.AsGamepadButtonInputId();
132 break;
133 case "ButtonY":
134 viewModel.Config.ButtonY = buttonValue.AsGamepadButtonInputId();
135 break;
136 case "RightStickButton":
137 viewModel.Config.RightStickButton = buttonValue.AsGamepadButtonInputId();
138 break;
139 case "RightJoystick":
140 viewModel.Config.RightJoystick = buttonValue.AsGamepadStickId();
141 break;
142 }
143 } 78 }
144 }; 79 };
145 80
@@ -165,29 +100,82 @@ namespace Ryujinx.Ava.UI.Views.Input
165 } 100 }
166 } 101 }
167 102
103 public void SaveCurrentProfile()
104 {
105 ViewModel.Save();
106 }
107
108 private IButtonAssigner CreateButtonAssigner(bool forStick)
109 {
110 IButtonAssigner assigner;
111
112 var device = ViewModel.Devices[ViewModel.Device];
113
114 if (device.Type == DeviceType.Keyboard)
115 {
116 assigner = new KeyboardKeyAssigner((IKeyboard)ViewModel.SelectedGamepad);
117 }
118 else if (device.Type == DeviceType.Controller)
119 {
120 assigner = new GamepadButtonAssigner(ViewModel.SelectedGamepad, (ViewModel.Config as StandardControllerInputConfig).TriggerThreshold, forStick);
121 }
122 else
123 {
124 throw new Exception("Controller not supported");
125 }
126
127 return assigner;
128 }
129
168 private void MouseClick(object sender, PointerPressedEventArgs e) 130 private void MouseClick(object sender, PointerPressedEventArgs e)
169 { 131 {
170 bool shouldUnbind = e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed; 132 bool shouldUnbind = false;
133
134 if (e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed)
135 {
136 shouldUnbind = true;
137 }
171 138
172 _currentAssigner?.Cancel(shouldUnbind); 139 _currentAssigner?.Cancel(shouldUnbind);
173 140
174 PointerPressed -= MouseClick; 141 PointerPressed -= MouseClick;
175 } 142 }
176 143
177 private IButtonAssigner CreateButtonAssigner(bool forStick) 144 private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
178 { 145 {
179 IButtonAssigner assigner; 146 if (ViewModel.IsModified && !_dialogOpen)
147 {
148 _dialogOpen = true;
180 149
181 assigner = new GamepadButtonAssigner((DataContext as ControllerInputViewModel).parentModel.SelectedGamepad, ((DataContext as ControllerInputViewModel).parentModel.Config as StandardControllerInputConfig).TriggerThreshold, forStick); 150 var result = await ContentDialogHelper.CreateConfirmationDialog(
151 LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmMessage],
152 LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmSubMessage],
153 LocaleManager.Instance[LocaleKeys.InputDialogYes],
154 LocaleManager.Instance[LocaleKeys.InputDialogNo],
155 LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
182 156
183 return assigner; 157 if (result == UserResult.Yes)
158 {
159 ViewModel.Save();
160 }
161
162 _dialogOpen = false;
163
164 ViewModel.IsModified = false;
165
166 if (e.AddedItems.Count > 0)
167 {
168 var player = (PlayerModel)e.AddedItems[0];
169 ViewModel.PlayerId = player.Id;
170 }
171 }
184 } 172 }
185 173
186 protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) 174 public void Dispose()
187 { 175 {
188 base.OnDetachedFromVisualTree(e);
189 _currentAssigner?.Cancel(); 176 _currentAssigner?.Cancel();
190 _currentAssigner = null; 177 _currentAssigner = null;
178 ViewModel.Dispose();
191 } 179 }
192 } 180 }
193} 181}
diff --git a/src/Ryujinx.Ava/UI/Views/Input/InputView.axaml b/src/Ryujinx.Ava/UI/Views/Input/InputView.axaml
deleted file mode 100644
index b4940941c..000000000
--- a/src/Ryujinx.Ava/UI/Views/Input/InputView.axaml
+++ /dev/null
@@ -1,225 +0,0 @@
1<UserControl
2 xmlns="https://github.com/avaloniaui"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
5 xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
6 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
8 xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
9 xmlns:views="clr-namespace:Ryujinx.Ava.UI.Views.Input"
10 xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
11 HorizontalAlignment="Stretch"
12 VerticalAlignment="Stretch"
13 d:DesignHeight="800"
14 d:DesignWidth="800"
15 x:Class="Ryujinx.Ava.UI.Views.Input.InputView"
16 x:DataType="viewModels:InputViewModel"
17 x:CompileBindings="True"
18 mc:Ignorable="d"
19 Focusable="True">
20 <Design.DataContext>
21 <viewModels:InputViewModel />
22 </Design.DataContext>
23 <UserControl.Styles>
24 <Style Selector="ToggleButton">
25 <Setter Property="Width" Value="90" />
26 <Setter Property="Height" Value="27" />
27 <Setter Property="HorizontalAlignment" Value="Stretch" />
28 </Style>
29 </UserControl.Styles>
30 <StackPanel
31 HorizontalAlignment="Stretch"
32 VerticalAlignment="Stretch"
33 Orientation="Vertical">
34 <StackPanel
35 Margin="0 0 0 5"
36 Orientation="Vertical"
37 Spacing="5">
38 <Grid>
39 <Grid.ColumnDefinitions>
40 <ColumnDefinition Width="*" />
41 <ColumnDefinition Width="10" />
42 <ColumnDefinition Width="*" />
43 </Grid.ColumnDefinitions>
44 <!-- Player Selection -->
45 <Grid
46 Grid.Column="0"
47 Margin="2"
48 HorizontalAlignment="Stretch"
49 VerticalAlignment="Center">
50 <Grid.ColumnDefinitions>
51 <ColumnDefinition Width="Auto"/>
52 <ColumnDefinition Width="*" />
53 </Grid.ColumnDefinitions>
54 <TextBlock
55 Margin="5,0,10,0"
56 Width="90"
57 HorizontalAlignment="Left"
58 VerticalAlignment="Center"
59 Text="{locale:Locale ControllerSettingsPlayer}" />
60 <ComboBox
61 Grid.Column="1"
62 Name="PlayerIndexBox"
63 HorizontalAlignment="Stretch"
64 VerticalAlignment="Center"
65 SelectionChanged="PlayerIndexBox_OnSelectionChanged"
66 ItemsSource="{Binding PlayerIndexes}"
67 SelectedIndex="{Binding PlayerId}">
68 <ComboBox.ItemTemplate>
69 <DataTemplate>
70 <TextBlock Text="{Binding Name}" />
71 </DataTemplate>
72 </ComboBox.ItemTemplate>
73 </ComboBox>
74 </Grid>
75 <!-- Profile Selection -->
76 <Grid
77 Grid.Column="2"
78 Margin="2"
79 HorizontalAlignment="Stretch"
80 VerticalAlignment="Center">
81 <Grid.ColumnDefinitions>
82 <ColumnDefinition Width="Auto"/>
83 <ColumnDefinition Width="*" />
84 <ColumnDefinition Width="Auto"/>
85 <ColumnDefinition Width="Auto"/>
86 <ColumnDefinition Width="Auto"/>
87 </Grid.ColumnDefinitions>
88 <TextBlock
89 Margin="5,0,10,0"
90 Width="90"
91 HorizontalAlignment="Left"
92 VerticalAlignment="Center"
93 Text="{locale:Locale ControllerSettingsProfile}" />
94 <ui:FAComboBox
95 Grid.Column="1"
96 IsEditable="True"
97 Name="ProfileBox"
98 HorizontalAlignment="Stretch"
99 VerticalAlignment="Center"
100 SelectedIndex="0"
101 ItemsSource="{Binding ProfilesList}"
102 Text="{Binding ProfileName, Mode=TwoWay}" />
103 <Button
104 Grid.Column="2"
105 MinWidth="0"
106 Margin="5,0,0,0"
107 VerticalAlignment="Center"
108 ToolTip.Tip="{locale:Locale ControllerSettingsLoadProfileToolTip}"
109 Command="{Binding LoadProfile}">
110 <ui:SymbolIcon
111 Symbol="Upload"
112 FontSize="15"
113 Height="20" />
114 </Button>
115 <Button
116 Grid.Column="3"
117 MinWidth="0"
118 Margin="5,0,0,0"
119 VerticalAlignment="Center"
120 ToolTip.Tip="{locale:Locale ControllerSettingsSaveProfileToolTip}"
121 Command="{Binding SaveProfile}">
122 <ui:SymbolIcon
123 Symbol="Save"
124 FontSize="15"
125 Height="20" />
126 </Button>
127 <Button
128 Grid.Column="4"
129 MinWidth="0"
130 Margin="5,0,0,0"
131 VerticalAlignment="Center"
132 ToolTip.Tip="{locale:Locale ControllerSettingsRemoveProfileToolTip}"
133 Command="{Binding RemoveProfile}">
134 <ui:SymbolIcon
135 Symbol="Delete"
136 FontSize="15"
137 Height="20" />
138 </Button>
139 </Grid>
140 </Grid>
141 <Separator />
142 <Grid>
143 <Grid.ColumnDefinitions>
144 <ColumnDefinition Width="*" />
145 <ColumnDefinition Width="10" />
146 <ColumnDefinition Width="*" />
147 </Grid.ColumnDefinitions>
148 <!-- Input Device -->
149 <Grid
150 Grid.Column="0"
151 Margin="2"
152 HorizontalAlignment="Stretch">
153 <Grid.ColumnDefinitions>
154 <ColumnDefinition Width="Auto"/>
155 <ColumnDefinition Width="*"/>
156 <ColumnDefinition Width="Auto" />
157 </Grid.ColumnDefinitions>
158 <TextBlock
159 Grid.Column="0"
160 Margin="5,0,10,0"
161 Width="90"
162 HorizontalAlignment="Left"
163 VerticalAlignment="Center"
164 Text="{locale:Locale ControllerSettingsInputDevice}" />
165 <ComboBox
166 Grid.Column="1"
167 Name="DeviceBox"
168 HorizontalAlignment="Stretch"
169 VerticalAlignment="Center"
170 ItemsSource="{Binding DeviceList}"
171 SelectedIndex="{Binding Device}" />
172 <Button
173 Grid.Column="2"
174 MinWidth="0"
175 Margin="5,0,0,0"
176 VerticalAlignment="Center"
177 Command="{Binding LoadDevices}">
178 <ui:SymbolIcon
179 Symbol="Refresh"
180 FontSize="15"
181 Height="20"/>
182 </Button>
183 </Grid>
184 <!-- Controller Type -->
185 <Grid
186 Grid.Column="2"
187 Margin="2"
188 HorizontalAlignment="Stretch"
189 VerticalAlignment="Center">
190 <Grid.ColumnDefinitions>
191 <ColumnDefinition Width="Auto"/>
192 <ColumnDefinition Width="*" />
193 </Grid.ColumnDefinitions>
194 <TextBlock
195 Margin="5,0,10,0"
196 Width="90"
197 HorizontalAlignment="Left"
198 VerticalAlignment="Center"
199 Text="{locale:Locale ControllerSettingsControllerType}" />
200 <ComboBox
201 Grid.Column="1"
202 HorizontalAlignment="Stretch"
203 ItemsSource="{Binding Controllers}"
204 SelectedIndex="{Binding Controller}">
205 <ComboBox.ItemTemplate>
206 <DataTemplate DataType="models:ControllerModel">
207 <TextBlock Text="{Binding Name}" />
208 </DataTemplate>
209 </ComboBox.ItemTemplate>
210 </ComboBox>
211 </Grid>
212 </Grid>
213 </StackPanel>
214 <ContentControl Content="{Binding ConfigViewModel}" IsVisible="{Binding ShowSettings}">
215 <ContentControl.DataTemplates>
216 <DataTemplate DataType="viewModels:ControllerInputViewModel">
217 <views:ControllerInputView />
218 </DataTemplate>
219 <DataTemplate DataType="viewModels:KeyboardInputViewModel">
220 <views:KeyboardInputView />
221 </DataTemplate>
222 </ContentControl.DataTemplates>
223 </ContentControl>
224 </StackPanel>
225</UserControl>
diff --git a/src/Ryujinx.Ava/UI/Views/Input/InputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/InputView.axaml.cs
deleted file mode 100644
index 356381a8a..000000000
--- a/src/Ryujinx.Ava/UI/Views/Input/InputView.axaml.cs
+++ /dev/null
@@ -1,61 +0,0 @@
1using Avalonia.Controls;
2using Ryujinx.Ava.Common.Locale;
3using Ryujinx.Ava.UI.Helpers;
4using Ryujinx.Ava.UI.Models;
5using Ryujinx.Ava.UI.ViewModels.Input;
6
7namespace Ryujinx.Ava.UI.Views.Input
8{
9 public partial class InputView : UserControl
10 {
11 private bool _dialogOpen;
12 private InputViewModel ViewModel { get; set; }
13
14 public InputView()
15 {
16 DataContext = ViewModel = new InputViewModel(this);
17
18 InitializeComponent();
19 }
20
21 public void SaveCurrentProfile()
22 {
23 ViewModel.Save();
24 }
25
26 private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
27 {
28 if (ViewModel.IsModified && !_dialogOpen)
29 {
30 _dialogOpen = true;
31
32 var result = await ContentDialogHelper.CreateConfirmationDialog(
33 LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmMessage],
34 LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmSubMessage],
35 LocaleManager.Instance[LocaleKeys.InputDialogYes],
36 LocaleManager.Instance[LocaleKeys.InputDialogNo],
37 LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
38
39 if (result == UserResult.Yes)
40 {
41 ViewModel.Save();
42 }
43
44 _dialogOpen = false;
45
46 ViewModel.IsModified = false;
47
48 if (e.AddedItems.Count > 0)
49 {
50 var player = (PlayerModel)e.AddedItems[0];
51 ViewModel.PlayerId = player.Id;
52 }
53 }
54 }
55
56 public void Dispose()
57 {
58 ViewModel.Dispose();
59 }
60 }
61}
diff --git a/src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml b/src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml
deleted file mode 100644
index e4566f463..000000000
--- a/src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml
+++ /dev/null
@@ -1,675 +0,0 @@
1<UserControl
2 xmlns="https://github.com/avaloniaui"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
7 xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
8 xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
9 HorizontalAlignment="Stretch"
10 VerticalAlignment="Stretch"
11 d:DesignHeight="800"
12 d:DesignWidth="800"
13 x:Class="Ryujinx.Ava.UI.Views.Input.KeyboardInputView"
14 x:DataType="viewModels:KeyboardInputViewModel"
15 x:CompileBindings="True"
16 mc:Ignorable="d"
17 Focusable="True">
18 <Design.DataContext>
19 <viewModels:KeyboardInputViewModel />
20 </Design.DataContext>
21 <UserControl.Resources>
22 <helpers:KeyValueConverter x:Key="Key" />
23 </UserControl.Resources>
24 <UserControl.Styles>
25 <Style Selector="ToggleButton">
26 <Setter Property="Width" Value="90" />
27 <Setter Property="Height" Value="27" />
28 <Setter Property="HorizontalAlignment" Value="Stretch" />
29 </Style>
30 </UserControl.Styles>
31 <StackPanel
32 HorizontalAlignment="Stretch"
33 VerticalAlignment="Stretch"
34 Orientation="Vertical">
35 <!-- Button / JoyStick Settings -->
36 <Grid
37 Name="SettingButtons"
38 MinHeight="450">
39 <Grid.ColumnDefinitions>
40 <ColumnDefinition Width="Auto" />
41 <ColumnDefinition Width="*" />
42 <ColumnDefinition Width="Auto" />
43 </Grid.ColumnDefinitions>
44 <!-- Left Controls -->
45 <StackPanel
46 Orientation="Vertical"
47 Margin="0,0,5,0"
48 Grid.Column="0">
49 <!-- Left Triggers -->
50 <Border
51 BorderBrush="{DynamicResource ThemeControlBorderColor}"
52 BorderThickness="1"
53 IsVisible="{Binding IsLeft}"
54 MinHeight="90"
55 CornerRadius="5">
56 <Grid
57 Margin="10"
58 HorizontalAlignment="Stretch">
59 <Grid.ColumnDefinitions>
60 <ColumnDefinition />
61 <ColumnDefinition />
62 </Grid.ColumnDefinitions>
63 <Grid.RowDefinitions>
64 <RowDefinition />
65 <RowDefinition />
66 </Grid.RowDefinitions>
67 <StackPanel
68 Grid.Column="0"
69 Grid.Row="0"
70 Orientation="Horizontal">
71 <TextBlock
72 Width="20"
73 HorizontalAlignment="Center"
74 VerticalAlignment="Center"
75 Text="{locale:Locale ControllerSettingsTriggerZL}"
76 TextAlignment="Center" />
77 <ToggleButton Name="ButtonZl">
78 <TextBlock
79 Text="{Binding Config.ButtonZl, Converter={StaticResource Key}}"
80 TextAlignment="Center" />
81 </ToggleButton>
82 </StackPanel>
83 <StackPanel
84 Grid.Column="0"
85 Grid.Row="1"
86 Orientation="Horizontal">
87 <TextBlock
88 Width="20"
89 HorizontalAlignment="Center"
90 VerticalAlignment="Center"
91 Text="{locale:Locale ControllerSettingsTriggerL}"
92 TextAlignment="Center" />
93 <ToggleButton Name="ButtonL">
94 <TextBlock
95 Text="{Binding Config.ButtonL, Converter={StaticResource Key}}"
96 TextAlignment="Center" />
97 </ToggleButton>
98 </StackPanel>
99 <StackPanel
100 Grid.Column="1"
101 Grid.Row="1"
102 Orientation="Horizontal">
103 <TextBlock
104 Width="20"
105 HorizontalAlignment="Center"
106 VerticalAlignment="Center"
107 Text="{locale:Locale ControllerSettingsButtonMinus}"
108 TextAlignment="Center" />
109 <ToggleButton Name="ButtonMinus">
110 <TextBlock
111 Text="{Binding Config.ButtonMinus, Converter={StaticResource Key}}"
112 TextAlignment="Center" />
113 </ToggleButton>
114 </StackPanel>
115 </Grid>
116 </Border>
117 <!-- Left Joystick -->
118 <Border
119 BorderBrush="{DynamicResource ThemeControlBorderColor}"
120 BorderThickness="1"
121 IsVisible="{Binding IsLeft}"
122 Margin="0,5,0,0"
123 CornerRadius="5">
124 <StackPanel
125 Margin="10"
126 Orientation="Vertical">
127 <TextBlock
128 Margin="0,0,0,10"
129 HorizontalAlignment="Center"
130 Text="{locale:Locale ControllerSettingsLStick}" />
131 <!-- Left Joystick Keyboard -->
132 <StackPanel Orientation="Vertical">
133 <!-- Left Joystick Button -->
134 <StackPanel
135 Margin="0,0,0,4"
136 Orientation="Horizontal">
137 <TextBlock
138 Margin="0,0,10,0"
139 Width="120"
140 HorizontalAlignment="Center"
141 VerticalAlignment="Center"
142 Text="{locale:Locale ControllerSettingsStickButton}"
143 TextAlignment="Center" />
144 <ToggleButton Name="LeftStickButton">
145 <TextBlock
146 Text="{Binding Config.LeftStickButton, Converter={StaticResource Key}}"
147 TextAlignment="Center" />
148 </ToggleButton>
149 </StackPanel>
150 <!-- Left Joystick Up -->
151 <StackPanel
152 Margin="0,0,0,4"
153 Orientation="Horizontal">
154 <TextBlock
155 Margin="0,0,10,0"
156 Width="120"
157 HorizontalAlignment="Center"
158 VerticalAlignment="Center"
159 Text="{locale:Locale ControllerSettingsStickUp}"
160 TextAlignment="Center" />
161 <ToggleButton Name="LeftStickUp">
162 <TextBlock
163 Text="{Binding Config.LeftStickUp, Converter={StaticResource Key}}"
164 TextAlignment="Center" />
165 </ToggleButton>
166 </StackPanel>
167 <!-- Left Joystick Down -->
168 <StackPanel
169 Margin="0,0,0,4"
170 Orientation="Horizontal">
171 <TextBlock
172 Margin="0,0,10,0"
173 Width="120"
174 HorizontalAlignment="Center"
175 VerticalAlignment="Center"
176 Text="{locale:Locale ControllerSettingsStickDown}"
177 TextAlignment="Center" />
178 <ToggleButton Name="LeftStickDown">
179 <TextBlock
180 Text="{Binding Config.LeftStickDown, Converter={StaticResource Key}}"
181 TextAlignment="Center" />
182 </ToggleButton>
183 </StackPanel>
184 <!-- Left Joystick Left -->
185 <StackPanel
186 Margin="0,0,0,4"
187 Orientation="Horizontal">
188 <TextBlock
189 Margin="0,0,10,0"
190 Width="120"
191 HorizontalAlignment="Center"
192 VerticalAlignment="Center"
193 Text="{locale:Locale ControllerSettingsStickLeft}"
194 TextAlignment="Center" />
195 <ToggleButton Name="LeftStickLeft">
196 <TextBlock
197 Text="{Binding Config.LeftStickLeft, Converter={StaticResource Key}}"
198 TextAlignment="Center" />
199 </ToggleButton>
200 </StackPanel>
201 <!-- Left Joystick Right -->
202 <StackPanel
203 Margin="0,0,0,4"
204 Orientation="Horizontal">
205 <TextBlock
206 Margin="0,0,10,0"
207 Width="120"
208 HorizontalAlignment="Center"
209 VerticalAlignment="Center"
210 Text="{locale:Locale ControllerSettingsStickRight}"
211 TextAlignment="Center" />
212 <ToggleButton Name="LeftStickRight">
213 <TextBlock
214 Text="{Binding Config.LeftStickRight, Converter={StaticResource Key}}"
215 TextAlignment="Center" />
216 </ToggleButton>
217 </StackPanel>
218 </StackPanel>
219 </StackPanel>
220 </Border>
221 <!-- Left DPad -->
222 <Border
223 BorderBrush="{DynamicResource ThemeControlBorderColor}"
224 BorderThickness="1"
225 VerticalAlignment="Top"
226 IsVisible="{Binding IsLeft}"
227 Margin="0,5,0,0"
228 CornerRadius="5">
229 <StackPanel
230 Margin="10"
231 Orientation="Vertical">
232 <TextBlock
233 Margin="0,0,0,10"
234 HorizontalAlignment="Center"
235 Text="{locale:Locale ControllerSettingsDPad}" />
236 <StackPanel Orientation="Vertical">
237 <!-- Left DPad Up -->
238 <StackPanel
239 Margin="0,0,0,4"
240 Orientation="Horizontal">
241 <TextBlock
242 Margin="0,0,10,0"
243 Width="120"
244 HorizontalAlignment="Center"
245 VerticalAlignment="Center"
246 Text="{locale:Locale ControllerSettingsDPadUp}"
247 TextAlignment="Center" />
248 <ToggleButton Name="DpadUp">
249 <TextBlock
250 Text="{Binding Config.DpadUp, Converter={StaticResource Key}}"
251 TextAlignment="Center" />
252 </ToggleButton>
253 </StackPanel>
254 <!-- Left DPad Down -->
255 <StackPanel
256 Margin="0,0,0,4"
257 Orientation="Horizontal">
258 <TextBlock
259 Margin="0,0,10,0"
260 Width="120"
261 HorizontalAlignment="Center"
262 VerticalAlignment="Center"
263 Text="{locale:Locale ControllerSettingsDPadDown}"
264 TextAlignment="Center" />
265 <ToggleButton Name="DpadDown">
266 <TextBlock
267 Text="{Binding Config.DpadDown, Converter={StaticResource Key}}"
268 TextAlignment="Center" />
269 </ToggleButton>
270 </StackPanel>
271 <!-- Left DPad Left -->
272 <StackPanel
273 Margin="0,0,0,4"
274 Orientation="Horizontal">
275 <TextBlock
276 Margin="0,0,10,0"
277 Width="120"
278 HorizontalAlignment="Center"
279 VerticalAlignment="Center"
280 Text="{locale:Locale ControllerSettingsDPadLeft}"
281 TextAlignment="Center" />
282 <ToggleButton Name="DpadLeft">
283 <TextBlock
284 Text="{Binding Config.DpadLeft, Converter={StaticResource Key}}"
285 TextAlignment="Center" />
286 </ToggleButton>
287 </StackPanel>
288 <!-- Left DPad Right -->
289 <StackPanel
290 Margin="0,0,0,4"
291 Orientation="Horizontal">
292 <TextBlock
293 Margin="0,0,10,0"
294 Width="120"
295 HorizontalAlignment="Center"
296 VerticalAlignment="Center"
297 Text="{locale:Locale ControllerSettingsDPadRight}"
298 TextAlignment="Center" />
299 <ToggleButton Name="DpadRight">
300 <TextBlock
301 Text="{Binding Config.DpadRight, Converter={StaticResource Key}}"
302 TextAlignment="Center" />
303 </ToggleButton>
304 </StackPanel>
305 </StackPanel>
306 </StackPanel>
307 </Border>
308 </StackPanel>
309 <!-- Triggers & Side Buttons -->
310 <StackPanel
311 Grid.Column="1"
312 HorizontalAlignment="Stretch"
313 VerticalAlignment="Stretch">
314 <!-- Controller Picture -->
315 <Image
316 Margin="0,10"
317 MaxHeight="300"
318 HorizontalAlignment="Stretch"
319 VerticalAlignment="Stretch"
320 Source="{Binding Image}" />
321 <Border
322 BorderBrush="{DynamicResource ThemeControlBorderColor}"
323 BorderThickness="1"
324 CornerRadius="5"
325 MinHeight="90"
326 IsVisible="{Binding HasSides}">
327 <StackPanel
328 Margin="8"
329 Orientation="Vertical">
330 <StackPanel
331 Margin="0,4,0,0"
332 HorizontalAlignment="Center"
333 VerticalAlignment="Center"
334 IsVisible="{Binding IsLeft}"
335 Orientation="Horizontal">
336 <TextBlock
337 Width="20"
338 HorizontalAlignment="Center"
339 VerticalAlignment="Center"
340 Text="{locale:Locale ControllerSettingsLeftSR}"
341 TextAlignment="Center" />
342 <ToggleButton Name="LeftButtonSr">
343 <TextBlock
344 Text="{Binding Config.LeftButtonSr, Converter={StaticResource Key}}"
345 TextAlignment="Center" />
346 </ToggleButton>
347 </StackPanel>
348 <StackPanel
349 Margin="0,4,0,0"
350 HorizontalAlignment="Center"
351 VerticalAlignment="Center"
352 IsVisible="{Binding IsLeft}"
353 Orientation="Horizontal">
354 <TextBlock
355 Width="20"
356 HorizontalAlignment="Center"
357 VerticalAlignment="Center"
358 Text="{locale:Locale ControllerSettingsLeftSL}"
359 TextAlignment="Center" />
360 <ToggleButton Name="LeftButtonSl">
361 <TextBlock
362 Text="{Binding Config.LeftButtonSl, Converter={StaticResource Key}}"
363 TextAlignment="Center" />
364 </ToggleButton>
365 </StackPanel>
366 <StackPanel
367 Margin="0,4,0,0"
368 HorizontalAlignment="Center"
369 VerticalAlignment="Center"
370 IsVisible="{Binding IsRight}"
371 Orientation="Horizontal">
372 <TextBlock
373 Width="20"
374 HorizontalAlignment="Center"
375 VerticalAlignment="Center"
376 Text="{locale:Locale ControllerSettingsRightSR}"
377 TextAlignment="Center" />
378 <ToggleButton Name="RightButtonSr">
379 <TextBlock
380 Text="{Binding Config.RightButtonSr, Converter={StaticResource Key}}"
381 TextAlignment="Center" />
382 </ToggleButton>
383 </StackPanel>
384 <StackPanel
385 Margin="0,4,0,0"
386 HorizontalAlignment="Center"
387 VerticalAlignment="Center"
388 IsVisible="{Binding IsRight}"
389 Orientation="Horizontal">
390 <TextBlock
391 Width="20"
392 HorizontalAlignment="Center"
393 VerticalAlignment="Center"
394 Text="{locale:Locale ControllerSettingsRightSL}"
395 TextAlignment="Center" />
396 <ToggleButton Name="RightButtonSl">
397 <TextBlock
398 Text="{Binding Config.RightButtonSl, Converter={StaticResource Key}}"
399 TextAlignment="Center" />
400 </ToggleButton>
401 </StackPanel>
402 </StackPanel>
403 </Border>
404 </StackPanel>
405 <!-- Right Controls -->
406 <StackPanel
407 Orientation="Vertical"
408 Margin="5,0,0,0"
409 Grid.Column="2">
410 <!-- Right Triggers -->
411 <Border
412 BorderBrush="{DynamicResource ThemeControlBorderColor}"
413 BorderThickness="1"
414 IsVisible="{Binding IsRight}"
415 MinHeight="90"
416 CornerRadius="5">
417 <Grid
418 Margin="10"
419 HorizontalAlignment="Stretch">
420 <Grid.ColumnDefinitions>
421 <ColumnDefinition />
422 <ColumnDefinition />
423 </Grid.ColumnDefinitions>
424 <Grid.RowDefinitions>
425 <RowDefinition />
426 <RowDefinition />
427 </Grid.RowDefinitions>
428 <StackPanel
429 Grid.Column="1"
430 Grid.Row="0"
431 Orientation="Horizontal">
432 <TextBlock
433 Width="20"
434 HorizontalAlignment="Center"
435 VerticalAlignment="Center"
436 Text="{locale:Locale ControllerSettingsTriggerZR}"
437 TextAlignment="Center" />
438 <ToggleButton Name="ButtonZr">
439 <TextBlock
440 Text="{Binding Config.ButtonZr, Converter={StaticResource Key}}"
441 TextAlignment="Center" />
442 </ToggleButton>
443 </StackPanel>
444 <StackPanel
445 Grid.Column="1"
446 Grid.Row="1"
447 HorizontalAlignment="Center"
448 VerticalAlignment="Center"
449 Orientation="Horizontal">
450 <TextBlock
451 Width="20"
452 HorizontalAlignment="Center"
453 VerticalAlignment="Center"
454 Text="{locale:Locale ControllerSettingsTriggerR}"
455 TextAlignment="Center" />
456 <ToggleButton Name="ButtonR">
457 <TextBlock
458 Text="{Binding Config.ButtonR, Converter={StaticResource Key}}"
459 TextAlignment="Center" />
460 </ToggleButton>
461 </StackPanel>
462 <StackPanel
463 Grid.Column="0"
464 Grid.Row="1"
465 HorizontalAlignment="Right"
466 VerticalAlignment="Center"
467 Orientation="Horizontal">
468 <TextBlock
469 Width="20"
470 HorizontalAlignment="Center"
471 VerticalAlignment="Center"
472 Text="{locale:Locale ControllerSettingsButtonPlus}"
473 TextAlignment="Center" />
474 <ToggleButton Name="ButtonPlus">
475 <TextBlock
476 Text="{Binding Config.ButtonPlus, Converter={StaticResource Key}}"
477 TextAlignment="Center" />
478 </ToggleButton>
479 </StackPanel>
480 </Grid>
481 </Border>
482 <!-- Right Buttons -->
483 <Border
484 BorderBrush="{DynamicResource ThemeControlBorderColor}"
485 BorderThickness="1"
486 IsVisible="{Binding IsRight}"
487 Margin="0,5,0,0"
488 CornerRadius="5">
489 <StackPanel
490 Margin="10"
491 Orientation="Vertical">
492 <TextBlock
493 Margin="0,0,0,10"
494 HorizontalAlignment="Center"
495 Text="{locale:Locale ControllerSettingsButtons}" />
496 <StackPanel
497 Orientation="Vertical">
498 <!-- Right Buttons A -->
499 <StackPanel
500 Margin="0,0,0,4"
501 Orientation="Horizontal">
502 <TextBlock
503 Width="120"
504 Margin="0,0,10,0"
505 HorizontalAlignment="Center"
506 VerticalAlignment="Center"
507 Text="{locale:Locale ControllerSettingsButtonA}"
508 TextAlignment="Center" />
509 <ToggleButton Name="ButtonA">
510 <TextBlock
511 Text="{Binding Config.ButtonA, Converter={StaticResource Key}}"
512 TextAlignment="Center" />
513 </ToggleButton>
514 </StackPanel>
515 <!-- Right Buttons B -->
516 <StackPanel
517 Margin="0,0,0,4"
518 Orientation="Horizontal">
519 <TextBlock
520 Width="120"
521 Margin="0,0,10,0"
522 HorizontalAlignment="Center"
523 VerticalAlignment="Center"
524 Text="{locale:Locale ControllerSettingsButtonB}"
525 TextAlignment="Center" />
526 <ToggleButton Name="ButtonB">
527 <TextBlock
528 Text="{Binding Config.ButtonB, Converter={StaticResource Key}}"
529 TextAlignment="Center" />
530 </ToggleButton>
531 </StackPanel>
532 <!-- Right Buttons X -->
533 <StackPanel
534 Margin="0,0,0,4"
535 Orientation="Horizontal">
536 <TextBlock
537 Width="120"
538 Margin="0,0,10,0"
539 HorizontalAlignment="Center"
540 VerticalAlignment="Center"
541 Text="{locale:Locale ControllerSettingsButtonX}"
542 TextAlignment="Center" />
543 <ToggleButton Name="ButtonX">
544 <TextBlock
545 Text="{Binding Config.ButtonX, Converter={StaticResource Key}}"
546 TextAlignment="Center" />
547 </ToggleButton>
548 </StackPanel>
549 <!-- Right Buttons Y -->
550 <StackPanel
551 Margin="0,0,0,4"
552 Orientation="Horizontal">
553 <TextBlock
554 Width="120"
555 Margin="0,0,10,0"
556 HorizontalAlignment="Center"
557 VerticalAlignment="Center"
558 Text="{locale:Locale ControllerSettingsButtonY}"
559 TextAlignment="Center" />
560 <ToggleButton Name="ButtonY">
561 <TextBlock
562 Text="{Binding Config.ButtonY, Converter={StaticResource Key}}"
563 TextAlignment="Center" />
564 </ToggleButton>
565 </StackPanel>
566 </StackPanel>
567 </StackPanel>
568 </Border>
569 <!-- Right DPad -->
570 <Border
571 Padding="10"
572 BorderBrush="{DynamicResource ThemeControlBorderColor}"
573 BorderThickness="1"
574 CornerRadius="5"
575 IsVisible="{Binding IsRight}"
576 Margin="0,5,0,0">
577 <StackPanel Orientation="Vertical">
578 <TextBlock
579 Margin="0,0,0,10"
580 HorizontalAlignment="Center"
581 Text="{locale:Locale ControllerSettingsRStick}" />
582 <!-- Right Joystick Keyboard -->
583 <StackPanel Orientation="Vertical">
584 <!-- Right Joystick Button -->
585 <StackPanel
586 Margin="0,0,0,4"
587 Orientation="Horizontal">
588 <TextBlock
589 Margin="0,0,10,0"
590 Width="120"
591 HorizontalAlignment="Center"
592 VerticalAlignment="Center"
593 Text="{locale:Locale ControllerSettingsStickButton}"
594 TextAlignment="Center" />
595 <ToggleButton Name="RightStickButton">
596 <TextBlock
597 Text="{Binding Config.RightStickButton, Converter={StaticResource Key}}"
598 TextAlignment="Center" />
599 </ToggleButton>
600 </StackPanel>
601 <!-- Right Joystick Up -->
602 <StackPanel
603 Margin="0,0,0,4"
604 Orientation="Horizontal">
605 <TextBlock
606 Margin="0,0,10,0"
607 Width="120"
608 HorizontalAlignment="Center"
609 VerticalAlignment="Center"
610 Text="{locale:Locale ControllerSettingsStickUp}"
611 TextAlignment="Center" />
612 <ToggleButton Name="RightStickUp">
613 <TextBlock
614 Text="{Binding Config.RightStickUp, Converter={StaticResource Key}}"
615 TextAlignment="Center" />
616 </ToggleButton>
617 </StackPanel>
618 <!-- Right Joystick Down -->
619 <StackPanel
620 Margin="0,0,0,4"
621 Orientation="Horizontal">
622 <TextBlock
623 Margin="0,0,10,0"
624 Width="120"
625 HorizontalAlignment="Center"
626 VerticalAlignment="Center"
627 Text="{locale:Locale ControllerSettingsStickDown}"
628 TextAlignment="Center" />
629 <ToggleButton Name="RightStickDown">
630 <TextBlock
631 Text="{Binding Config.RightStickDown, Converter={StaticResource Key}}"
632 TextAlignment="Center" />
633 </ToggleButton>
634 </StackPanel>
635 <!-- Right Joystick Left -->
636 <StackPanel
637 Margin="0,0,0,4"
638 Orientation="Horizontal">
639 <TextBlock
640 Margin="0,0,10,0"
641 Width="120"
642 HorizontalAlignment="Center"
643 VerticalAlignment="Center"
644 Text="{locale:Locale ControllerSettingsStickLeft}"
645 TextAlignment="Center" />
646 <ToggleButton Name="RightStickLeft">
647 <TextBlock
648 Text="{Binding Config.RightStickLeft, Converter={StaticResource Key}}"
649 TextAlignment="Center" />
650 </ToggleButton>
651 </StackPanel>
652 <!-- Right Joystick Right -->
653 <StackPanel
654 Margin="0,0,0,4"
655 Orientation="Horizontal">
656 <TextBlock
657 Margin="0,0,10,0"
658 Width="120"
659 HorizontalAlignment="Center"
660 VerticalAlignment="Center"
661 Text="{locale:Locale ControllerSettingsStickRight}"
662 TextAlignment="Center" />
663 <ToggleButton Name="RightStickRight">
664 <TextBlock
665 Text="{Binding Config.RightStickRight, Converter={StaticResource Key}}"
666 TextAlignment="Center" />
667 </ToggleButton>
668 </StackPanel>
669 </StackPanel>
670 </StackPanel>
671 </Border>
672 </StackPanel>
673 </Grid>
674 </StackPanel>
675</UserControl> \ No newline at end of file
diff --git a/src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml.cs
deleted file mode 100644
index f7024c5d1..000000000
--- a/src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml.cs
+++ /dev/null
@@ -1,210 +0,0 @@
1using Avalonia;
2using Avalonia.Controls;
3using Avalonia.Controls.Primitives;
4using Avalonia.Input;
5using Avalonia.Interactivity;
6using Avalonia.LogicalTree;
7using Ryujinx.Ava.UI.Helpers;
8using Ryujinx.Ava.UI.ViewModels.Input;
9using Ryujinx.Input;
10using Ryujinx.Input.Assigner;
11
12namespace Ryujinx.Ava.UI.Views.Input
13{
14 public partial class KeyboardInputView : UserControl
15 {
16 private ButtonKeyAssigner _currentAssigner;
17
18 public KeyboardInputView()
19 {
20 InitializeComponent();
21
22 foreach (ILogical visual in SettingButtons.GetLogicalDescendants())
23 {
24 if (visual is ToggleButton button and not CheckBox)
25 {
26 button.IsCheckedChanged += Button_IsCheckedChanged;
27 }
28 }
29 }
30
31 protected override void OnPointerReleased(PointerReleasedEventArgs e)
32 {
33 base.OnPointerReleased(e);
34
35 if (_currentAssigner != null && _currentAssigner.ToggledButton != null && !_currentAssigner.ToggledButton.IsPointerOver)
36 {
37 _currentAssigner.Cancel();
38 }
39 }
40
41 private void Button_IsCheckedChanged(object sender, RoutedEventArgs e)
42 {
43 if (sender is ToggleButton button)
44 {
45 if ((bool)button.IsChecked)
46 {
47 if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
48 {
49 return;
50 }
51
52 bool isStick = button.Tag != null && button.Tag.ToString() == "stick";
53
54 if (_currentAssigner == null && (bool)button.IsChecked)
55 {
56 _currentAssigner = new ButtonKeyAssigner(button);
57
58 this.Focus(NavigationMethod.Pointer);
59
60 PointerPressed += MouseClick;
61
62 IKeyboard keyboard = (IKeyboard)(DataContext as KeyboardInputViewModel).parentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
63 IButtonAssigner assigner = CreateButtonAssigner(isStick);
64
65 _currentAssigner.ButtonAssigned += (sender, e) =>
66 {
67 if (e.ButtonValue.HasValue)
68 {
69 var viewModel = (DataContext as KeyboardInputViewModel);
70 var buttonValue = e.ButtonValue.Value;
71 viewModel.parentModel.IsModified = true;
72
73 switch (button.Name)
74 {
75 case "ButtonZl":
76 viewModel.Config.ButtonZl = buttonValue.AsKey();
77 break;
78 case "ButtonL":
79 viewModel.Config.ButtonL = buttonValue.AsKey();
80 break;
81 case "ButtonMinus":
82 viewModel.Config.ButtonMinus = buttonValue.AsKey();
83 break;
84 case "LeftStickButton":
85 viewModel.Config.LeftStickButton = buttonValue.AsKey();
86 break;
87 case "LeftStickUp":
88 viewModel.Config.LeftStickUp = buttonValue.AsKey();
89 break;
90 case "LeftStickDown":
91 viewModel.Config.LeftStickDown = buttonValue.AsKey();
92 break;
93 case "LeftStickRight":
94 viewModel.Config.LeftStickRight = buttonValue.AsKey();
95 break;
96 case "LeftStickLeft":
97 viewModel.Config.LeftStickLeft = buttonValue.AsKey();
98 break;
99 case "DpadUp":
100 viewModel.Config.DpadUp = buttonValue.AsKey();
101 break;
102 case "DpadDown":
103 viewModel.Config.DpadDown = buttonValue.AsKey();
104 break;
105 case "DpadLeft":
106 viewModel.Config.DpadLeft = buttonValue.AsKey();
107 break;
108 case "DpadRight":
109 viewModel.Config.DpadRight = buttonValue.AsKey();
110 break;
111 case "LeftButtonSr":
112 viewModel.Config.LeftButtonSr = buttonValue.AsKey();
113 break;
114 case "LeftButtonSl":
115 viewModel.Config.LeftButtonSl = buttonValue.AsKey();
116 break;
117 case "RightButtonSr":
118 viewModel.Config.RightButtonSr = buttonValue.AsKey();
119 break;
120 case "RightButtonSl":
121 viewModel.Config.RightButtonSl = buttonValue.AsKey();
122 break;
123 case "ButtonZr":
124 viewModel.Config.ButtonZr = buttonValue.AsKey();
125 break;
126 case "ButtonR":
127 viewModel.Config.ButtonR = buttonValue.AsKey();
128 break;
129 case "ButtonPlus":
130 viewModel.Config.ButtonPlus = buttonValue.AsKey();
131 break;
132 case "ButtonA":
133 viewModel.Config.ButtonA = buttonValue.AsKey();
134 break;
135 case "ButtonB":
136 viewModel.Config.ButtonB = buttonValue.AsKey();
137 break;
138 case "ButtonX":
139 viewModel.Config.ButtonX = buttonValue.AsKey();
140 break;
141 case "ButtonY":
142 viewModel.Config.ButtonY = buttonValue.AsKey();
143 break;
144 case "RightStickButton":
145 viewModel.Config.RightStickButton = buttonValue.AsKey();
146 break;
147 case "RightStickUp":
148 viewModel.Config.RightStickUp = buttonValue.AsKey();
149 break;
150 case "RightStickDown":
151 viewModel.Config.RightStickDown = buttonValue.AsKey();
152 break;
153 case "RightStickRight":
154 viewModel.Config.RightStickRight = buttonValue.AsKey();
155 break;
156 case "RightStickLeft":
157 viewModel.Config.RightStickLeft = buttonValue.AsKey();
158 break;
159 }
160 }
161 };
162
163 _currentAssigner.GetInputAndAssign(assigner, keyboard);
164 }
165 else
166 {
167 if (_currentAssigner != null)
168 {
169 ToggleButton oldButton = _currentAssigner.ToggledButton;
170
171 _currentAssigner.Cancel();
172 _currentAssigner = null;
173 button.IsChecked = false;
174 }
175 }
176 }
177 else
178 {
179 _currentAssigner?.Cancel();
180 _currentAssigner = null;
181 }
182 }
183 }
184
185 private void MouseClick(object sender, PointerPressedEventArgs e)
186 {
187 bool shouldUnbind = e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed;
188
189 _currentAssigner?.Cancel(shouldUnbind);
190
191 PointerPressed -= MouseClick;
192 }
193
194 private IButtonAssigner CreateButtonAssigner(bool forStick)
195 {
196 IButtonAssigner assigner;
197
198 assigner = new KeyboardKeyAssigner((IKeyboard)(DataContext as KeyboardInputViewModel).parentModel.SelectedGamepad);
199
200 return assigner;
201 }
202
203 protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
204 {
205 base.OnDetachedFromVisualTree(e);
206 _currentAssigner?.Cancel();
207 _currentAssigner = null;
208 }
209 }
210}
diff --git a/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml b/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml
index 0d018e297..a6b587f67 100644
--- a/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml
+++ b/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml
@@ -6,7 +6,7 @@
6 xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls" 6 xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
7 xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" 7 xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
8 xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" 8 xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
9 xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input" 9 xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
10 mc:Ignorable="d" 10 mc:Ignorable="d"
11 x:Class="Ryujinx.Ava.UI.Views.Input.MotionInputView" 11 x:Class="Ryujinx.Ava.UI.Views.Input.MotionInputView"
12 x:DataType="viewModels:MotionInputViewModel" 12 x:DataType="viewModels:MotionInputViewModel"
diff --git a/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs
index 2304364b6..1b340752b 100644
--- a/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs
@@ -1,7 +1,9 @@
1using Avalonia.Controls; 1using Avalonia.Controls;
2using FluentAvalonia.UI.Controls; 2using FluentAvalonia.UI.Controls;
3using Ryujinx.Ava.Common.Locale; 3using Ryujinx.Ava.Common.Locale;
4using Ryujinx.Ava.UI.ViewModels.Input; 4using Ryujinx.Ava.UI.Models;
5using Ryujinx.Ava.UI.ViewModels;
6using Ryujinx.Common.Configuration.Hid.Controller;
5using System.Threading.Tasks; 7using System.Threading.Tasks;
6 8
7namespace Ryujinx.Ava.UI.Views.Input 9namespace Ryujinx.Ava.UI.Views.Input
@@ -17,7 +19,7 @@ namespace Ryujinx.Ava.UI.Views.Input
17 19
18 public MotionInputView(ControllerInputViewModel viewModel) 20 public MotionInputView(ControllerInputViewModel viewModel)
19 { 21 {
20 var config = viewModel.Config; 22 var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
21 23
22 _viewModel = new MotionInputViewModel 24 _viewModel = new MotionInputViewModel
23 { 25 {
@@ -49,7 +51,7 @@ namespace Ryujinx.Ava.UI.Views.Input
49 }; 51 };
50 contentDialog.PrimaryButtonClick += (sender, args) => 52 contentDialog.PrimaryButtonClick += (sender, args) =>
51 { 53 {
52 var config = viewModel.Config; 54 var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
53 config.Slot = content._viewModel.Slot; 55 config.Slot = content._viewModel.Slot;
54 config.Sensitivity = content._viewModel.Sensitivity; 56 config.Sensitivity = content._viewModel.Sensitivity;
55 config.GyroDeadzone = content._viewModel.GyroDeadzone; 57 config.GyroDeadzone = content._viewModel.GyroDeadzone;
diff --git a/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml b/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml
index 1beb1f06e..5b7087a47 100644
--- a/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml
+++ b/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml
@@ -5,7 +5,7 @@
5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
7 xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" 7 xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
8 xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input" 8 xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
9 mc:Ignorable="d" 9 mc:Ignorable="d"
10 x:Class="Ryujinx.Ava.UI.Views.Input.RumbleInputView" 10 x:Class="Ryujinx.Ava.UI.Views.Input.RumbleInputView"
11 x:DataType="viewModels:RumbleInputViewModel" 11 x:DataType="viewModels:RumbleInputViewModel"
diff --git a/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs
index 58a4b416b..9307f872c 100644
--- a/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs
@@ -1,7 +1,9 @@
1using Avalonia.Controls; 1using Avalonia.Controls;
2using FluentAvalonia.UI.Controls; 2using FluentAvalonia.UI.Controls;
3using Ryujinx.Ava.Common.Locale; 3using Ryujinx.Ava.Common.Locale;
4using Ryujinx.Ava.UI.ViewModels.Input; 4using Ryujinx.Ava.UI.Models;
5using Ryujinx.Ava.UI.ViewModels;
6using Ryujinx.Common.Configuration.Hid.Controller;
5using System.Threading.Tasks; 7using System.Threading.Tasks;
6 8
7namespace Ryujinx.Ava.UI.Views.Input 9namespace Ryujinx.Ava.UI.Views.Input
@@ -17,7 +19,7 @@ namespace Ryujinx.Ava.UI.Views.Input
17 19
18 public RumbleInputView(ControllerInputViewModel viewModel) 20 public RumbleInputView(ControllerInputViewModel viewModel)
19 { 21 {
20 var config = viewModel.Config; 22 var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
21 23
22 _viewModel = new RumbleInputViewModel 24 _viewModel = new RumbleInputViewModel
23 { 25 {
@@ -45,7 +47,7 @@ namespace Ryujinx.Ava.UI.Views.Input
45 47
46 contentDialog.PrimaryButtonClick += (sender, args) => 48 contentDialog.PrimaryButtonClick += (sender, args) =>
47 { 49 {
48 var config = viewModel.Config; 50 var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
49 config.StrongRumble = content._viewModel.StrongRumble; 51 config.StrongRumble = content._viewModel.StrongRumble;
50 config.WeakRumble = content._viewModel.WeakRumble; 52 config.WeakRumble = content._viewModel.WeakRumble;
51 }; 53 };
diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml b/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml
index 55c2ed6e3..81f4b68b7 100644
--- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml
+++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml
@@ -27,9 +27,9 @@
27 <RowDefinition Height="*" /> 27 <RowDefinition Height="*" />
28 <RowDefinition Height="Auto" /> 28 <RowDefinition Height="Auto" />
29 </Grid.RowDefinitions> 29 </Grid.RowDefinitions>
30 <views:InputView 30 <views:ControllerInputView
31 Grid.Row="0" 31 Grid.Row="0"
32 Name="InputView" /> 32 Name="ControllerSettings" />
33 <StackPanel 33 <StackPanel
34 Orientation="Vertical" 34 Orientation="Vertical"
35 Grid.Row="2"> 35 Grid.Row="2">
diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs
index 85ccffccd..8a0cb8ab9 100644
--- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs
@@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
11 11
12 public void Dispose() 12 public void Dispose()
13 { 13 {
14 InputView.Dispose(); 14 ControllerSettings.Dispose();
15 } 15 }
16 } 16 }
17} 17}
diff --git a/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs
index 314501c52..d7bb0b883 100644
--- a/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs
@@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.Windows
37 37
38 public void SaveSettings() 38 public void SaveSettings()
39 { 39 {
40 InputPage.InputView?.SaveCurrentProfile(); 40 InputPage.ControllerSettings?.SaveCurrentProfile();
41 41
42 if (Owner is MainWindow window && ViewModel.DirectoryChanged) 42 if (Owner is MainWindow window && ViewModel.DirectoryChanged)
43 { 43 {
diff --git a/src/Ryujinx.Input/Assigner/GamepadButtonAssigner.cs b/src/Ryujinx.Input/Assigner/GamepadButtonAssigner.cs
index bf8319a6a..388ebcc07 100644
--- a/src/Ryujinx.Input/Assigner/GamepadButtonAssigner.cs
+++ b/src/Ryujinx.Input/Assigner/GamepadButtonAssigner.cs
@@ -59,16 +59,16 @@ namespace Ryujinx.Input.Assigner
59 return _gamepad == null || !_gamepad.IsConnected; 59 return _gamepad == null || !_gamepad.IsConnected;
60 } 60 }
61 61
62 public ButtonValue? GetPressedButton() 62 public string GetPressedButton()
63 { 63 {
64 IEnumerable<GamepadButtonInputId> pressedButtons = _detector.GetPressedButtons(); 64 IEnumerable<GamepadButtonInputId> pressedButtons = _detector.GetPressedButtons();
65 65
66 if (pressedButtons.Any()) 66 if (pressedButtons.Any())
67 { 67 {
68 return !_forStick ? new(pressedButtons.First()) : new(((StickInputId)pressedButtons.First())); 68 return !_forStick ? pressedButtons.First().ToString() : ((StickInputId)pressedButtons.First()).ToString();
69 } 69 }
70 70
71 return null; 71 return "";
72 } 72 }
73 73
74 private void CollectButtonStats() 74 private void CollectButtonStats()
diff --git a/src/Ryujinx.Input/Assigner/IButtonAssigner.cs b/src/Ryujinx.Input/Assigner/IButtonAssigner.cs
index 653717133..76a9fece4 100644
--- a/src/Ryujinx.Input/Assigner/IButtonAssigner.cs
+++ b/src/Ryujinx.Input/Assigner/IButtonAssigner.cs
@@ -31,6 +31,6 @@ namespace Ryujinx.Input.Assigner
31 /// Get the pressed button that was read in <see cref="ReadInput"/> by the button assigner. 31 /// Get the pressed button that was read in <see cref="ReadInput"/> by the button assigner.
32 /// </summary> 32 /// </summary>
33 /// <returns>The pressed button that was read</returns> 33 /// <returns>The pressed button that was read</returns>
34 ButtonValue? GetPressedButton(); 34 string GetPressedButton();
35 } 35 }
36} 36}
diff --git a/src/Ryujinx.Input/Assigner/KeyboardKeyAssigner.cs b/src/Ryujinx.Input/Assigner/KeyboardKeyAssigner.cs
index c66812ba0..e52ef4a2c 100644
--- a/src/Ryujinx.Input/Assigner/KeyboardKeyAssigner.cs
+++ b/src/Ryujinx.Input/Assigner/KeyboardKeyAssigner.cs
@@ -23,7 +23,7 @@ namespace Ryujinx.Input.Assigner
23 23
24 public bool HasAnyButtonPressed() 24 public bool HasAnyButtonPressed()
25 { 25 {
26 return GetPressedButton() is not null; 26 return GetPressedButton().Length != 0;
27 } 27 }
28 28
29 public bool ShouldCancel() 29 public bool ShouldCancel()
@@ -31,20 +31,20 @@ namespace Ryujinx.Input.Assigner
31 return _keyboardState.IsPressed(Key.Escape); 31 return _keyboardState.IsPressed(Key.Escape);
32 } 32 }
33 33
34 public ButtonValue? GetPressedButton() 34 public string GetPressedButton()
35 { 35 {
36 ButtonValue? keyPressed = null; 36 string keyPressed = "";
37 37
38 for (Key key = Key.Unknown; key < Key.Count; key++) 38 for (Key key = Key.Unknown; key < Key.Count; key++)
39 { 39 {
40 if (_keyboardState.IsPressed(key)) 40 if (_keyboardState.IsPressed(key))
41 { 41 {
42 keyPressed = new(key); 42 keyPressed = key.ToString();
43 break; 43 break;
44 } 44 }
45 } 45 }
46 46
47 return !ShouldCancel() ? keyPressed : null; 47 return !ShouldCancel() ? keyPressed : "";
48 } 48 }
49 } 49 }
50} 50}
diff --git a/src/Ryujinx.Input/ButtonValue.cs b/src/Ryujinx.Input/ButtonValue.cs
deleted file mode 100644
index f037e6b60..000000000
--- a/src/Ryujinx.Input/ButtonValue.cs
+++ /dev/null
@@ -1,48 +0,0 @@
1using System.Diagnostics;
2
3namespace Ryujinx.Input
4{
5 public enum ButtonValueType { Key, GamepadButtonInputId, StickId }
6
7 public readonly struct ButtonValue
8 {
9 private readonly ButtonValueType _type;
10 private readonly uint _rawValue;
11
12 public ButtonValue(Key key)
13 {
14 _type = ButtonValueType.Key;
15 _rawValue = (uint)key;
16 }
17
18 public ButtonValue(GamepadButtonInputId gamepad)
19 {
20 _type = ButtonValueType.GamepadButtonInputId;
21 _rawValue = (uint)gamepad;
22 }
23
24 public ButtonValue(StickInputId stick)
25 {
26 _type = ButtonValueType.StickId;
27 _rawValue = (uint)stick;
28 }
29
30 public Common.Configuration.Hid.Key AsKey()
31 {
32 Debug.Assert(_type == ButtonValueType.Key);
33 return (Common.Configuration.Hid.Key)_rawValue;
34 }
35
36 public Common.Configuration.Hid.Controller.GamepadInputId AsGamepadButtonInputId()
37 {
38 Debug.Assert(_type == ButtonValueType.GamepadButtonInputId);
39 return (Common.Configuration.Hid.Controller.GamepadInputId)_rawValue;
40 }
41
42 public Common.Configuration.Hid.Controller.StickInputId AsGamepadStickId()
43 {
44 Debug.Assert(_type == ButtonValueType.StickId);
45 return (Common.Configuration.Hid.Controller.StickInputId)_rawValue;
46 }
47 }
48}
diff --git a/src/Ryujinx/Ui/Windows/ControllerWindow.cs b/src/Ryujinx/Ui/Windows/ControllerWindow.cs
index 52cad5c85..ebf22ab60 100644
--- a/src/Ryujinx/Ui/Windows/ControllerWindow.cs
+++ b/src/Ryujinx/Ui/Windows/ControllerWindow.cs
@@ -893,7 +893,7 @@ namespace Ryujinx.Ui.Windows
893 } 893 }
894 } 894 }
895 895
896 string pressedButton = assigner.GetPressedButton().ToString(); 896 string pressedButton = assigner.GetPressedButton();
897 897
898 Application.Invoke(delegate 898 Application.Invoke(delegate
899 { 899 {