Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
49b37550ca | ||
|
a42f0bbb87 | ||
|
b4bb22ba06 | ||
|
6fdf774845 |
@@ -3,13 +3,13 @@
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia" Version="11.0.4" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.4" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.4" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.4" />
|
||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.4" />
|
||||
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.2" />
|
||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.2" />
|
||||
<PackageVersion Include="Avalonia" Version="11.0.5" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.5" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.5" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.5" />
|
||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.5" />
|
||||
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.3" />
|
||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.3" />
|
||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageVersion Include="Concentus" Version="1.1.7" />
|
||||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||
@@ -35,6 +35,7 @@
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||
<PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.28.1-build28" />
|
||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.16.0" />
|
||||
|
@@ -141,3 +141,4 @@ See [LICENSE.txt](LICENSE.txt) and [THIRDPARTY.md](distribution/legal/THIRDPARTY
|
||||
|
||||
- [LibHac](https://github.com/Thealexbarney/LibHac) is used for our file-system.
|
||||
- [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation.
|
||||
- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation.
|
||||
|
@@ -682,3 +682,32 @@
|
||||
END OF TERMS AND CONDITIONS
|
||||
```
|
||||
</details>
|
||||
|
||||
# ShellLink (MIT)
|
||||
<details>
|
||||
<summary>See License</summary>
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Yorick Koster, Securify B.V.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
</details>
|
@@ -3,8 +3,8 @@ Version=1.0
|
||||
Name=Ryujinx
|
||||
Type=Application
|
||||
Icon=Ryujinx
|
||||
Exec=env DOTNET_EnableAlternateStackCheck=1 Ryujinx %f
|
||||
Comment=A Nintendo Switch Emulator
|
||||
Exec=Ryujinx.sh %f
|
||||
Comment=Plays Nintendo Switch applications
|
||||
GenericName=Nintendo Switch Emulator
|
||||
Terminal=false
|
||||
Categories=Game;Emulator;
|
||||
|
13
distribution/linux/shortcut-template.desktop
Normal file
13
distribution/linux/shortcut-template.desktop
Normal file
@@ -0,0 +1,13 @@
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Name={0}
|
||||
Type=Application
|
||||
Icon={1}
|
||||
Exec={2} %f
|
||||
Comment=Nintendo Switch application
|
||||
GenericName=Nintendo Switch Emulator
|
||||
Terminal=false
|
||||
Categories=Game;Emulator;
|
||||
Keywords=Switch;Nintendo;Emulator;
|
||||
StartupWMClass=Ryujinx
|
||||
PrefersNonDefaultGPU=true
|
35
distribution/macos/shortcut-template.plist
Normal file
35
distribution/macos/shortcut-template.plist
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>{0}</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>{1}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>{2}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2018 - 2023 Ryujinx Team and Contributors.</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.games</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>11.0</string>
|
||||
<key>UIPrerenderedIcon</key>
|
||||
<true/>
|
||||
<key>LSEnvironment</key>
|
||||
<dict>
|
||||
<key>DOTNET_DefaultStackSize</key>
|
||||
<string>200000</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
@@ -72,6 +72,8 @@
|
||||
"GameListContextMenuExtractDataRomFSToolTip": "Extract the RomFS section from Application's current config (including updates)",
|
||||
"GameListContextMenuExtractDataLogo": "Logo",
|
||||
"GameListContextMenuExtractDataLogoToolTip": "Extract the Logo section from Application's current config (including updates)",
|
||||
"GameListContextMenuCreateShortcut": "Create Application Shortcut",
|
||||
"GameListContextMenuCreateShortcutToolTip": "Create a Desktop Shortcut that launches the selected Application",
|
||||
"StatusBarGamesLoaded": "{0}/{1} Games Loaded",
|
||||
"StatusBarSystemVersion": "System Version: {0}",
|
||||
"LinuxVmMaxMapCountDialogTitle": "Low limit for memory mappings detected",
|
||||
@@ -261,6 +263,105 @@
|
||||
"ControllerSettingsMotionGyroDeadzone": "Gyro Deadzone:",
|
||||
"ControllerSettingsSave": "Save",
|
||||
"ControllerSettingsClose": "Close",
|
||||
"KeyUnknown": "Unknown",
|
||||
"KeyShiftLeft": "Shift Left",
|
||||
"KeyShiftRight": "Shift Right",
|
||||
"KeyControlLeft": "Control Left",
|
||||
"KeyControlRight": "Control Right",
|
||||
"KeyAltLeft": "Alt Left",
|
||||
"KeyAltRight": "Alt Right",
|
||||
"KeyOptLeft": "⌥ Left",
|
||||
"KeyOptRight": "⌥ Right",
|
||||
"KeyWinLeft": "⊞ Left",
|
||||
"KeyWinRight": "⊞ Right",
|
||||
"KeyCmdLeft": "⌘ Left",
|
||||
"KeyCmdRight": "⌘ Right",
|
||||
"KeyMenu": "Menu",
|
||||
"KeyUp": "Up",
|
||||
"KeyDown": "Down",
|
||||
"KeyLeft": "Left",
|
||||
"KeyRight": "Right",
|
||||
"KeyEnter": "Enter",
|
||||
"KeyEscape": "Escape",
|
||||
"KeySpace": "Space",
|
||||
"KeyTab": "Tab",
|
||||
"KeyBackSpace": "Backspace",
|
||||
"KeyInsert": "Insert",
|
||||
"KeyDelete": "Delete",
|
||||
"KeyPageUp": "Page Up",
|
||||
"KeyPageDown": "Page Down",
|
||||
"KeyHome": "Home",
|
||||
"KeyEnd": "End",
|
||||
"KeyCapsLock": "Caps Lock",
|
||||
"KeyScrollLock": "Scroll Lock",
|
||||
"KeyPrintScreen": "Print Screen",
|
||||
"KeyPause": "Pause",
|
||||
"KeyNumLock": "Num Lock",
|
||||
"KeyClear": "Clear",
|
||||
"KeyKeypad0": "Keypad 0",
|
||||
"KeyKeypad1": "Keypad 1",
|
||||
"KeyKeypad2": "Keypad 2",
|
||||
"KeyKeypad3": "Keypad 3",
|
||||
"KeyKeypad4": "Keypad 4",
|
||||
"KeyKeypad5": "Keypad 5",
|
||||
"KeyKeypad6": "Keypad 6",
|
||||
"KeyKeypad7": "Keypad 7",
|
||||
"KeyKeypad8": "Keypad 8",
|
||||
"KeyKeypad9": "Keypad 9",
|
||||
"KeyKeypadDivide": "Keypad Divide",
|
||||
"KeyKeypadMultiply": "Keypad Multiply",
|
||||
"KeyKeypadSubtract": "Keypad Subtract",
|
||||
"KeyKeypadAdd": "Keypad Add",
|
||||
"KeyKeypadDecimal": "Keypad Decimal",
|
||||
"KeyKeypadEnter": "Keypad Enter",
|
||||
"KeyNumber0": "0",
|
||||
"KeyNumber1": "1",
|
||||
"KeyNumber2": "2",
|
||||
"KeyNumber3": "3",
|
||||
"KeyNumber4": "4",
|
||||
"KeyNumber5": "5",
|
||||
"KeyNumber6": "6",
|
||||
"KeyNumber7": "7",
|
||||
"KeyNumber8": "8",
|
||||
"KeyNumber9": "9",
|
||||
"KeyTilde": "~",
|
||||
"KeyGrave": "`",
|
||||
"KeyMinus": "-",
|
||||
"KeyPlus": "+",
|
||||
"KeyBracketLeft": "[",
|
||||
"KeyBracketRight": "]",
|
||||
"KeySemicolon": ";",
|
||||
"KeyQuote": "\"",
|
||||
"KeyComma": ",",
|
||||
"KeyPeriod": ".",
|
||||
"KeySlash": "/",
|
||||
"KeyBackSlash": "\\",
|
||||
"KeyUnbound": "Unbound",
|
||||
"GamepadLeftStick": "Left Stick Button",
|
||||
"GamepadRightStick": "Right Stick Button",
|
||||
"GamepadLeftShoulder": "Left Shoulder",
|
||||
"GamepadRightShoulder": "Right Shoulder",
|
||||
"GamepadLeftTrigger": "Left Trigger",
|
||||
"GamepadRightTrigger": "Right Trigger",
|
||||
"GamepadDpadUp": "Up",
|
||||
"GamepadDpadDown": "Down",
|
||||
"GamepadDpadLeft": "Left",
|
||||
"GamepadDpadRight": "Right",
|
||||
"GamepadMinus": "-",
|
||||
"GamepadPlus": "+",
|
||||
"GamepadGuide": "Guide",
|
||||
"GamepadMisc1": "Misc",
|
||||
"GamepadPaddle1": "Paddle 1",
|
||||
"GamepadPaddle2": "Paddle 2",
|
||||
"GamepadPaddle3": "Paddle 3",
|
||||
"GamepadPaddle4": "Paddle 4",
|
||||
"GamepadTouchpad": "Touchpad",
|
||||
"GamepadSingleLeftTrigger0": "Left Trigger 0",
|
||||
"GamepadSingleRightTrigger0": "Right Trigger 0",
|
||||
"GamepadSingleLeftTrigger1": "Left Trigger 1",
|
||||
"GamepadSingleRightTrigger1": "Right Trigger 1",
|
||||
"StickLeft": "Left Stick",
|
||||
"StickRight": "Right Stick",
|
||||
"UserProfilesSelectedUserProfile": "Selected User Profile:",
|
||||
"UserProfilesSaveProfileName": "Save Profile Name",
|
||||
"UserProfilesChangeProfileImage": "Change Profile Image",
|
||||
|
@@ -15,8 +15,7 @@
|
||||
<MenuItem Header="Test 2" />
|
||||
<MenuItem Header="Test 3">
|
||||
<MenuItem.Icon>
|
||||
<CheckBox Margin="0"
|
||||
IsChecked="{ReflectionBinding Checkbox, Mode=TwoWay}" />
|
||||
<CheckBox Margin="0" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
|
@@ -82,4 +82,9 @@
|
||||
Header="{locale:Locale GameListContextMenuExtractDataLogo}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuExtractDataLogoToolTip}" />
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
Click="CreateApplicationShortcut_Click"
|
||||
Header="{locale:Locale GameListContextMenuCreateShortcut}"
|
||||
IsEnabled="{Binding CreateShortcutEnabled}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuCreateShortcutToolTip}" />
|
||||
</MenuFlyout>
|
@@ -337,6 +337,17 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateApplicationShortcut_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
|
||||
|
||||
if (viewModel?.SelectedApplication != null)
|
||||
{
|
||||
ApplicationData selectedApplication = viewModel.SelectedApplication;
|
||||
ShortcutHelper.CreateAppShortcut(selectedApplication.Path, selectedApplication.TitleName, selectedApplication.TitleId, selectedApplication.Icon);
|
||||
}
|
||||
}
|
||||
|
||||
public async void RunApplication_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
|
||||
|
31
src/Ryujinx.Ava/UI/Controls/SliderScroll.axaml.cs
Normal file
31
src/Ryujinx.Ava/UI/Controls/SliderScroll.axaml.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Controls
|
||||
{
|
||||
public class SliderScroll : Slider
|
||||
{
|
||||
protected override Type StyleKeyOverride => typeof(Slider);
|
||||
|
||||
protected override void OnPointerWheelChanged(PointerWheelEventArgs e)
|
||||
{
|
||||
var newValue = Value + e.Delta.Y * TickFrequency;
|
||||
|
||||
if (newValue < Minimum)
|
||||
{
|
||||
Value = Minimum;
|
||||
}
|
||||
else if (newValue > Maximum)
|
||||
{
|
||||
Value = Maximum;
|
||||
}
|
||||
else
|
||||
{
|
||||
Value = newValue;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +1,8 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Threading;
|
||||
using Ryujinx.Input;
|
||||
using Ryujinx.Input.Assigner;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Helpers
|
||||
@@ -15,12 +12,12 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
internal class ButtonAssignedEventArgs : EventArgs
|
||||
{
|
||||
public ToggleButton Button { get; }
|
||||
public bool IsAssigned { get; }
|
||||
public ButtonValue? ButtonValue { get; }
|
||||
|
||||
public ButtonAssignedEventArgs(ToggleButton button, bool isAssigned)
|
||||
public ButtonAssignedEventArgs(ToggleButton button, ButtonValue? buttonValue)
|
||||
{
|
||||
Button = button;
|
||||
IsAssigned = isAssigned;
|
||||
ButtonValue = buttonValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,15 +75,11 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
|
||||
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
string pressedButton = assigner.GetPressedButton();
|
||||
ButtonValue? pressedButton = assigner.GetPressedButton();
|
||||
|
||||
if (_shouldUnbind)
|
||||
{
|
||||
SetButtonText(ToggledButton, "Unbound");
|
||||
}
|
||||
else if (pressedButton != "")
|
||||
{
|
||||
SetButtonText(ToggledButton, pressedButton);
|
||||
pressedButton = null;
|
||||
}
|
||||
|
||||
_shouldUnbind = false;
|
||||
@@ -94,17 +87,8 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
|
||||
ToggledButton.IsChecked = false;
|
||||
|
||||
ButtonAssigned?.Invoke(this, new ButtonAssignedEventArgs(ToggledButton, pressedButton != null));
|
||||
ButtonAssigned?.Invoke(this, new ButtonAssignedEventArgs(ToggledButton, pressedButton));
|
||||
|
||||
static void SetButtonText(ToggleButton button, string text)
|
||||
{
|
||||
ILogical textBlock = button.GetLogicalDescendants().First(x => x is TextBlock);
|
||||
|
||||
if (textBlock != null && textBlock is TextBlock block)
|
||||
{
|
||||
block.Text = text;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using Avalonia.Data.Converters;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Helpers
|
||||
@@ -10,37 +12,158 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
{
|
||||
public static KeyValueConverter Instance = new();
|
||||
|
||||
private static readonly Dictionary<Key, LocaleKeys> _keysMap = new()
|
||||
{
|
||||
{ Key.Unknown, LocaleKeys.KeyUnknown },
|
||||
{ Key.ShiftLeft, LocaleKeys.KeyShiftLeft },
|
||||
{ Key.ShiftRight, LocaleKeys.KeyShiftRight },
|
||||
{ Key.ControlLeft, LocaleKeys.KeyControlLeft },
|
||||
{ Key.ControlRight, LocaleKeys.KeyControlRight },
|
||||
{ Key.AltLeft, OperatingSystem.IsMacOS() ? LocaleKeys.KeyOptLeft : LocaleKeys.KeyAltLeft },
|
||||
{ Key.AltRight, OperatingSystem.IsMacOS() ? LocaleKeys.KeyOptRight : LocaleKeys.KeyAltRight },
|
||||
{ Key.WinLeft, OperatingSystem.IsMacOS() ? LocaleKeys.KeyCmdLeft : LocaleKeys.KeyWinLeft },
|
||||
{ Key.WinRight, OperatingSystem.IsMacOS() ? LocaleKeys.KeyCmdRight : LocaleKeys.KeyWinRight },
|
||||
{ Key.Up, LocaleKeys.KeyUp },
|
||||
{ Key.Down, LocaleKeys.KeyDown },
|
||||
{ Key.Left, LocaleKeys.KeyLeft },
|
||||
{ Key.Right, LocaleKeys.KeyRight },
|
||||
{ Key.Enter, LocaleKeys.KeyEnter },
|
||||
{ Key.Escape, LocaleKeys.KeyEscape },
|
||||
{ Key.Space, LocaleKeys.KeySpace },
|
||||
{ Key.Tab, LocaleKeys.KeyTab },
|
||||
{ Key.BackSpace, LocaleKeys.KeyBackSpace },
|
||||
{ Key.Insert, LocaleKeys.KeyInsert },
|
||||
{ Key.Delete, LocaleKeys.KeyDelete },
|
||||
{ Key.PageUp, LocaleKeys.KeyPageUp },
|
||||
{ Key.PageDown, LocaleKeys.KeyPageDown },
|
||||
{ Key.Home, LocaleKeys.KeyHome },
|
||||
{ Key.End, LocaleKeys.KeyEnd },
|
||||
{ Key.CapsLock, LocaleKeys.KeyCapsLock },
|
||||
{ Key.ScrollLock, LocaleKeys.KeyScrollLock },
|
||||
{ Key.PrintScreen, LocaleKeys.KeyPrintScreen },
|
||||
{ Key.Pause, LocaleKeys.KeyPause },
|
||||
{ Key.NumLock, LocaleKeys.KeyNumLock },
|
||||
{ Key.Clear, LocaleKeys.KeyClear },
|
||||
{ Key.Keypad0, LocaleKeys.KeyKeypad0 },
|
||||
{ Key.Keypad1, LocaleKeys.KeyKeypad1 },
|
||||
{ Key.Keypad2, LocaleKeys.KeyKeypad2 },
|
||||
{ Key.Keypad3, LocaleKeys.KeyKeypad3 },
|
||||
{ Key.Keypad4, LocaleKeys.KeyKeypad4 },
|
||||
{ Key.Keypad5, LocaleKeys.KeyKeypad5 },
|
||||
{ Key.Keypad6, LocaleKeys.KeyKeypad6 },
|
||||
{ Key.Keypad7, LocaleKeys.KeyKeypad7 },
|
||||
{ Key.Keypad8, LocaleKeys.KeyKeypad8 },
|
||||
{ Key.Keypad9, LocaleKeys.KeyKeypad9 },
|
||||
{ Key.KeypadDivide, LocaleKeys.KeyKeypadDivide },
|
||||
{ Key.KeypadMultiply, LocaleKeys.KeyKeypadMultiply },
|
||||
{ Key.KeypadSubtract, LocaleKeys.KeyKeypadSubtract },
|
||||
{ Key.KeypadAdd, LocaleKeys.KeyKeypadAdd },
|
||||
{ Key.KeypadDecimal, LocaleKeys.KeyKeypadDecimal },
|
||||
{ Key.KeypadEnter, LocaleKeys.KeyKeypadEnter },
|
||||
{ Key.Number0, LocaleKeys.KeyNumber0 },
|
||||
{ Key.Number1, LocaleKeys.KeyNumber1 },
|
||||
{ Key.Number2, LocaleKeys.KeyNumber2 },
|
||||
{ Key.Number3, LocaleKeys.KeyNumber3 },
|
||||
{ Key.Number4, LocaleKeys.KeyNumber4 },
|
||||
{ Key.Number5, LocaleKeys.KeyNumber5 },
|
||||
{ Key.Number6, LocaleKeys.KeyNumber6 },
|
||||
{ Key.Number7, LocaleKeys.KeyNumber7 },
|
||||
{ Key.Number8, LocaleKeys.KeyNumber8 },
|
||||
{ Key.Number9, LocaleKeys.KeyNumber9 },
|
||||
{ Key.Tilde, LocaleKeys.KeyTilde },
|
||||
{ Key.Grave, LocaleKeys.KeyGrave },
|
||||
{ Key.Minus, LocaleKeys.KeyMinus },
|
||||
{ Key.Plus, LocaleKeys.KeyPlus },
|
||||
{ Key.BracketLeft, LocaleKeys.KeyBracketLeft },
|
||||
{ Key.BracketRight, LocaleKeys.KeyBracketRight },
|
||||
{ Key.Semicolon, LocaleKeys.KeySemicolon },
|
||||
{ Key.Quote, LocaleKeys.KeyQuote },
|
||||
{ Key.Comma, LocaleKeys.KeyComma },
|
||||
{ Key.Period, LocaleKeys.KeyPeriod },
|
||||
{ Key.Slash, LocaleKeys.KeySlash },
|
||||
{ Key.BackSlash, LocaleKeys.KeyBackSlash },
|
||||
{ Key.Unbound, LocaleKeys.KeyUnbound },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<GamepadInputId, LocaleKeys> _gamepadInputIdMap = new()
|
||||
{
|
||||
{ GamepadInputId.LeftStick, LocaleKeys.GamepadLeftStick },
|
||||
{ GamepadInputId.RightStick, LocaleKeys.GamepadRightStick },
|
||||
{ GamepadInputId.LeftShoulder, LocaleKeys.GamepadLeftShoulder },
|
||||
{ GamepadInputId.RightShoulder, LocaleKeys.GamepadRightShoulder },
|
||||
{ GamepadInputId.LeftTrigger, LocaleKeys.GamepadLeftTrigger },
|
||||
{ GamepadInputId.RightTrigger, LocaleKeys.GamepadRightTrigger },
|
||||
{ GamepadInputId.DpadUp, LocaleKeys.GamepadDpadUp},
|
||||
{ GamepadInputId.DpadDown, LocaleKeys.GamepadDpadDown},
|
||||
{ GamepadInputId.DpadLeft, LocaleKeys.GamepadDpadLeft},
|
||||
{ GamepadInputId.DpadRight, LocaleKeys.GamepadDpadRight},
|
||||
{ GamepadInputId.Minus, LocaleKeys.GamepadMinus},
|
||||
{ GamepadInputId.Plus, LocaleKeys.GamepadPlus},
|
||||
{ GamepadInputId.Guide, LocaleKeys.GamepadGuide},
|
||||
{ GamepadInputId.Misc1, LocaleKeys.GamepadMisc1},
|
||||
{ GamepadInputId.Paddle1, LocaleKeys.GamepadPaddle1},
|
||||
{ GamepadInputId.Paddle2, LocaleKeys.GamepadPaddle2},
|
||||
{ GamepadInputId.Paddle3, LocaleKeys.GamepadPaddle3},
|
||||
{ GamepadInputId.Paddle4, LocaleKeys.GamepadPaddle4},
|
||||
{ GamepadInputId.Touchpad, LocaleKeys.GamepadTouchpad},
|
||||
{ GamepadInputId.SingleLeftTrigger0, LocaleKeys.GamepadSingleLeftTrigger0},
|
||||
{ GamepadInputId.SingleRightTrigger0, LocaleKeys.GamepadSingleRightTrigger0},
|
||||
{ GamepadInputId.SingleLeftTrigger1, LocaleKeys.GamepadSingleLeftTrigger1},
|
||||
{ GamepadInputId.SingleRightTrigger1, LocaleKeys.GamepadSingleRightTrigger1},
|
||||
{ GamepadInputId.Unbound, LocaleKeys.KeyUnbound},
|
||||
};
|
||||
|
||||
private static readonly Dictionary<StickInputId, LocaleKeys> _stickInputIdMap = new()
|
||||
{
|
||||
{ StickInputId.Left, LocaleKeys.StickLeft},
|
||||
{ StickInputId.Right, LocaleKeys.StickRight},
|
||||
{ StickInputId.Unbound, LocaleKeys.KeyUnbound},
|
||||
};
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value == null)
|
||||
string keyString = "";
|
||||
|
||||
if (value is Key key)
|
||||
{
|
||||
return null;
|
||||
if (_keysMap.TryGetValue(key, out LocaleKeys localeKey))
|
||||
{
|
||||
keyString = LocaleManager.Instance[localeKey];
|
||||
}
|
||||
else
|
||||
{
|
||||
keyString = key.ToString();
|
||||
}
|
||||
}
|
||||
else if (value is GamepadInputId gamepadInputId)
|
||||
{
|
||||
if (_gamepadInputIdMap.TryGetValue(gamepadInputId, out LocaleKeys localeKey))
|
||||
{
|
||||
keyString = LocaleManager.Instance[localeKey];
|
||||
}
|
||||
else
|
||||
{
|
||||
keyString = gamepadInputId.ToString();
|
||||
}
|
||||
}
|
||||
else if (value is StickInputId stickInputId)
|
||||
{
|
||||
if (_stickInputIdMap.TryGetValue(stickInputId, out LocaleKeys localeKey))
|
||||
{
|
||||
keyString = LocaleManager.Instance[localeKey];
|
||||
}
|
||||
else
|
||||
{
|
||||
keyString = stickInputId.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
return value.ToString();
|
||||
return keyString;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
object key = null;
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
if (targetType == typeof(Key))
|
||||
{
|
||||
key = Enum.Parse<Key>(value.ToString());
|
||||
}
|
||||
else if (targetType == typeof(GamepadInputId))
|
||||
{
|
||||
key = Enum.Parse<GamepadInputId>(value.ToString());
|
||||
}
|
||||
else if (targetType == typeof(StickInputId))
|
||||
{
|
||||
key = Enum.Parse<StickInputId>(value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
580
src/Ryujinx.Ava/UI/Models/Input/ControllerInputConfig.cs
Normal file
580
src/Ryujinx.Ava/UI/Models/Input/ControllerInputConfig.cs
Normal file
@@ -0,0 +1,580 @@
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models.Input
|
||||
{
|
||||
public class ControllerInputConfig : BaseModel
|
||||
{
|
||||
public bool EnableCemuHookMotion { get; set; }
|
||||
public string DsuServerHost { get; set; }
|
||||
public int DsuServerPort { get; set; }
|
||||
public int Slot { get; set; }
|
||||
public int AltSlot { get; set; }
|
||||
public bool MirrorInput { get; set; }
|
||||
public int Sensitivity { get; set; }
|
||||
public double GyroDeadzone { get; set; }
|
||||
|
||||
public float WeakRumble { get; set; }
|
||||
public float StrongRumble { get; set; }
|
||||
|
||||
public string Id { get; set; }
|
||||
public ControllerType ControllerType { get; set; }
|
||||
public PlayerIndex PlayerIndex { get; set; }
|
||||
|
||||
private StickInputId _leftJoystick;
|
||||
public StickInputId LeftJoystick
|
||||
{
|
||||
get => _leftJoystick;
|
||||
set
|
||||
{
|
||||
_leftJoystick = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _leftInvertStickX;
|
||||
public bool LeftInvertStickX
|
||||
{
|
||||
get => _leftInvertStickX;
|
||||
set
|
||||
{
|
||||
_leftInvertStickX = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _leftInvertStickY;
|
||||
public bool LeftInvertStickY
|
||||
{
|
||||
get => _leftInvertStickY;
|
||||
set
|
||||
{
|
||||
_leftInvertStickY = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _leftRotate90;
|
||||
public bool LeftRotate90
|
||||
{
|
||||
get => _leftRotate90;
|
||||
set
|
||||
{
|
||||
_leftRotate90 = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _leftStickButton;
|
||||
public GamepadInputId LeftStickButton
|
||||
{
|
||||
get => _leftStickButton;
|
||||
set
|
||||
{
|
||||
_leftStickButton = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private StickInputId _rightJoystick;
|
||||
public StickInputId RightJoystick
|
||||
{
|
||||
get => _rightJoystick;
|
||||
set
|
||||
{
|
||||
_rightJoystick = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _rightInvertStickX;
|
||||
public bool RightInvertStickX
|
||||
{
|
||||
get => _rightInvertStickX;
|
||||
set
|
||||
{
|
||||
_rightInvertStickX = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _rightInvertStickY;
|
||||
public bool RightInvertStickY
|
||||
{
|
||||
get => _rightInvertStickY;
|
||||
set
|
||||
{
|
||||
_rightInvertStickY = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _rightRotate90;
|
||||
public bool RightRotate90
|
||||
{
|
||||
get => _rightRotate90;
|
||||
set
|
||||
{
|
||||
_rightRotate90 = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _rightStickButton;
|
||||
public GamepadInputId RightStickButton
|
||||
{
|
||||
get => _rightStickButton;
|
||||
set
|
||||
{
|
||||
_rightStickButton = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _dpadUp;
|
||||
public GamepadInputId DpadUp
|
||||
{
|
||||
get => _dpadUp;
|
||||
set
|
||||
{
|
||||
_dpadUp = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _dpadDown;
|
||||
public GamepadInputId DpadDown
|
||||
{
|
||||
get => _dpadDown;
|
||||
set
|
||||
{
|
||||
_dpadDown = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _dpadLeft;
|
||||
public GamepadInputId DpadLeft
|
||||
{
|
||||
get => _dpadLeft;
|
||||
set
|
||||
{
|
||||
_dpadLeft = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _dpadRight;
|
||||
public GamepadInputId DpadRight
|
||||
{
|
||||
get => _dpadRight;
|
||||
set
|
||||
{
|
||||
_dpadRight = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonL;
|
||||
public GamepadInputId ButtonL
|
||||
{
|
||||
get => _buttonL;
|
||||
set
|
||||
{
|
||||
_buttonL = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonMinus;
|
||||
public GamepadInputId ButtonMinus
|
||||
{
|
||||
get => _buttonMinus;
|
||||
set
|
||||
{
|
||||
_buttonMinus = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _leftButtonSl;
|
||||
public GamepadInputId LeftButtonSl
|
||||
{
|
||||
get => _leftButtonSl;
|
||||
set
|
||||
{
|
||||
_leftButtonSl = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _leftButtonSr;
|
||||
public GamepadInputId LeftButtonSr
|
||||
{
|
||||
get => _leftButtonSr;
|
||||
set
|
||||
{
|
||||
_leftButtonSr = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonZl;
|
||||
public GamepadInputId ButtonZl
|
||||
{
|
||||
get => _buttonZl;
|
||||
set
|
||||
{
|
||||
_buttonZl = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonA;
|
||||
public GamepadInputId ButtonA
|
||||
{
|
||||
get => _buttonA;
|
||||
set
|
||||
{
|
||||
_buttonA = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonB;
|
||||
public GamepadInputId ButtonB
|
||||
{
|
||||
get => _buttonB;
|
||||
set
|
||||
{
|
||||
_buttonB = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonX;
|
||||
public GamepadInputId ButtonX
|
||||
{
|
||||
get => _buttonX;
|
||||
set
|
||||
{
|
||||
_buttonX = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonY;
|
||||
public GamepadInputId ButtonY
|
||||
{
|
||||
get => _buttonY;
|
||||
set
|
||||
{
|
||||
_buttonY = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonR;
|
||||
public GamepadInputId ButtonR
|
||||
{
|
||||
get => _buttonR;
|
||||
set
|
||||
{
|
||||
_buttonR = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonPlus;
|
||||
public GamepadInputId ButtonPlus
|
||||
{
|
||||
get => _buttonPlus;
|
||||
set
|
||||
{
|
||||
_buttonPlus = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _rightButtonSl;
|
||||
public GamepadInputId RightButtonSl
|
||||
{
|
||||
get => _rightButtonSl;
|
||||
set
|
||||
{
|
||||
_rightButtonSl = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _rightButtonSr;
|
||||
public GamepadInputId RightButtonSr
|
||||
{
|
||||
get => _rightButtonSr;
|
||||
set
|
||||
{
|
||||
_rightButtonSr = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GamepadInputId _buttonZr;
|
||||
public GamepadInputId ButtonZr
|
||||
{
|
||||
get => _buttonZr;
|
||||
set
|
||||
{
|
||||
_buttonZr = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private float _deadzoneLeft;
|
||||
public float DeadzoneLeft
|
||||
{
|
||||
get => _deadzoneLeft;
|
||||
set
|
||||
{
|
||||
_deadzoneLeft = MathF.Round(value, 3);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private float _deadzoneRight;
|
||||
public float DeadzoneRight
|
||||
{
|
||||
get => _deadzoneRight;
|
||||
set
|
||||
{
|
||||
_deadzoneRight = MathF.Round(value, 3);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private float _rangeLeft;
|
||||
public float RangeLeft
|
||||
{
|
||||
get => _rangeLeft;
|
||||
set
|
||||
{
|
||||
_rangeLeft = MathF.Round(value, 3);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private float _rangeRight;
|
||||
public float RangeRight
|
||||
{
|
||||
get => _rangeRight;
|
||||
set
|
||||
{
|
||||
_rangeRight = MathF.Round(value, 3);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private float _triggerThreshold;
|
||||
public float TriggerThreshold
|
||||
{
|
||||
get => _triggerThreshold;
|
||||
set
|
||||
{
|
||||
_triggerThreshold = MathF.Round(value, 3);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _enableMotion;
|
||||
public bool EnableMotion
|
||||
{
|
||||
get => _enableMotion;
|
||||
set
|
||||
{
|
||||
_enableMotion = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _enableRumble;
|
||||
public bool EnableRumble
|
||||
{
|
||||
get => _enableRumble;
|
||||
set
|
||||
{
|
||||
_enableRumble = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public ControllerInputConfig(InputConfig config)
|
||||
{
|
||||
if (config != null)
|
||||
{
|
||||
Id = config.Id;
|
||||
ControllerType = config.ControllerType;
|
||||
PlayerIndex = config.PlayerIndex;
|
||||
|
||||
if (config is not StandardControllerInputConfig controllerInput)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LeftJoystick = controllerInput.LeftJoyconStick.Joystick;
|
||||
LeftInvertStickX = controllerInput.LeftJoyconStick.InvertStickX;
|
||||
LeftInvertStickY = controllerInput.LeftJoyconStick.InvertStickY;
|
||||
LeftRotate90 = controllerInput.LeftJoyconStick.Rotate90CW;
|
||||
LeftStickButton = controllerInput.LeftJoyconStick.StickButton;
|
||||
|
||||
RightJoystick = controllerInput.RightJoyconStick.Joystick;
|
||||
RightInvertStickX = controllerInput.RightJoyconStick.InvertStickX;
|
||||
RightInvertStickY = controllerInput.RightJoyconStick.InvertStickY;
|
||||
RightRotate90 = controllerInput.RightJoyconStick.Rotate90CW;
|
||||
RightStickButton = controllerInput.RightJoyconStick.StickButton;
|
||||
|
||||
DpadUp = controllerInput.LeftJoycon.DpadUp;
|
||||
DpadDown = controllerInput.LeftJoycon.DpadDown;
|
||||
DpadLeft = controllerInput.LeftJoycon.DpadLeft;
|
||||
DpadRight = controllerInput.LeftJoycon.DpadRight;
|
||||
ButtonL = controllerInput.LeftJoycon.ButtonL;
|
||||
ButtonMinus = controllerInput.LeftJoycon.ButtonMinus;
|
||||
LeftButtonSl = controllerInput.LeftJoycon.ButtonSl;
|
||||
LeftButtonSr = controllerInput.LeftJoycon.ButtonSr;
|
||||
ButtonZl = controllerInput.LeftJoycon.ButtonZl;
|
||||
|
||||
ButtonA = controllerInput.RightJoycon.ButtonA;
|
||||
ButtonB = controllerInput.RightJoycon.ButtonB;
|
||||
ButtonX = controllerInput.RightJoycon.ButtonX;
|
||||
ButtonY = controllerInput.RightJoycon.ButtonY;
|
||||
ButtonR = controllerInput.RightJoycon.ButtonR;
|
||||
ButtonPlus = controllerInput.RightJoycon.ButtonPlus;
|
||||
RightButtonSl = controllerInput.RightJoycon.ButtonSl;
|
||||
RightButtonSr = controllerInput.RightJoycon.ButtonSr;
|
||||
ButtonZr = controllerInput.RightJoycon.ButtonZr;
|
||||
|
||||
DeadzoneLeft = controllerInput.DeadzoneLeft;
|
||||
DeadzoneRight = controllerInput.DeadzoneRight;
|
||||
RangeLeft = controllerInput.RangeLeft;
|
||||
RangeRight = controllerInput.RangeRight;
|
||||
TriggerThreshold = controllerInput.TriggerThreshold;
|
||||
|
||||
if (controllerInput.Motion != null)
|
||||
{
|
||||
EnableMotion = controllerInput.Motion.EnableMotion;
|
||||
GyroDeadzone = controllerInput.Motion.GyroDeadzone;
|
||||
Sensitivity = controllerInput.Motion.Sensitivity;
|
||||
|
||||
if (controllerInput.Motion is CemuHookMotionConfigController cemuHook)
|
||||
{
|
||||
EnableCemuHookMotion = true;
|
||||
DsuServerHost = cemuHook.DsuServerHost;
|
||||
DsuServerPort = cemuHook.DsuServerPort;
|
||||
Slot = cemuHook.Slot;
|
||||
AltSlot = cemuHook.AltSlot;
|
||||
MirrorInput = cemuHook.MirrorInput;
|
||||
}
|
||||
}
|
||||
|
||||
if (controllerInput.Rumble != null)
|
||||
{
|
||||
EnableRumble = controllerInput.Rumble.EnableRumble;
|
||||
WeakRumble = controllerInput.Rumble.WeakRumble;
|
||||
StrongRumble = controllerInput.Rumble.StrongRumble;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public InputConfig GetConfig()
|
||||
{
|
||||
var config = new StandardControllerInputConfig
|
||||
{
|
||||
Id = Id,
|
||||
Backend = InputBackendType.GamepadSDL2,
|
||||
PlayerIndex = PlayerIndex,
|
||||
ControllerType = ControllerType,
|
||||
LeftJoycon = new LeftJoyconCommonConfig<GamepadInputId>
|
||||
{
|
||||
DpadUp = DpadUp,
|
||||
DpadDown = DpadDown,
|
||||
DpadLeft = DpadLeft,
|
||||
DpadRight = DpadRight,
|
||||
ButtonL = ButtonL,
|
||||
ButtonMinus = ButtonMinus,
|
||||
ButtonSl = LeftButtonSl,
|
||||
ButtonSr = LeftButtonSr,
|
||||
ButtonZl = ButtonZl
|
||||
},
|
||||
RightJoycon = new RightJoyconCommonConfig<GamepadInputId>
|
||||
{
|
||||
ButtonA = ButtonA,
|
||||
ButtonB = ButtonB,
|
||||
ButtonX = ButtonX,
|
||||
ButtonY = ButtonY,
|
||||
ButtonPlus = ButtonPlus,
|
||||
ButtonSl = RightButtonSl,
|
||||
ButtonSr = RightButtonSr,
|
||||
ButtonR = ButtonR,
|
||||
ButtonZr = ButtonZr
|
||||
},
|
||||
LeftJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
|
||||
{
|
||||
Joystick = LeftJoystick,
|
||||
InvertStickX = LeftInvertStickX,
|
||||
InvertStickY = LeftInvertStickY,
|
||||
Rotate90CW = LeftRotate90,
|
||||
StickButton = LeftStickButton
|
||||
},
|
||||
RightJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
|
||||
{
|
||||
Joystick = RightJoystick,
|
||||
InvertStickX = RightInvertStickX,
|
||||
InvertStickY = RightInvertStickY,
|
||||
Rotate90CW = RightRotate90,
|
||||
StickButton = RightStickButton
|
||||
},
|
||||
Rumble = new RumbleConfigController
|
||||
{
|
||||
EnableRumble = EnableRumble,
|
||||
WeakRumble = WeakRumble,
|
||||
StrongRumble = StrongRumble
|
||||
},
|
||||
Version = InputConfig.CurrentVersion,
|
||||
DeadzoneLeft = DeadzoneLeft,
|
||||
DeadzoneRight = DeadzoneRight,
|
||||
RangeLeft = RangeLeft,
|
||||
RangeRight = RangeRight,
|
||||
TriggerThreshold = TriggerThreshold
|
||||
};
|
||||
|
||||
if (EnableCemuHookMotion)
|
||||
{
|
||||
config.Motion = new CemuHookMotionConfigController
|
||||
{
|
||||
EnableMotion = EnableMotion,
|
||||
MotionBackend = MotionInputBackendType.CemuHook,
|
||||
GyroDeadzone = GyroDeadzone,
|
||||
Sensitivity = Sensitivity,
|
||||
DsuServerHost = DsuServerHost,
|
||||
DsuServerPort = DsuServerPort,
|
||||
Slot = Slot,
|
||||
AltSlot = AltSlot,
|
||||
MirrorInput = MirrorInput
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
config.Motion = new MotionConfigController
|
||||
{
|
||||
EnableMotion = EnableMotion,
|
||||
MotionBackend = MotionInputBackendType.GamepadDriver,
|
||||
GyroDeadzone = GyroDeadzone,
|
||||
Sensitivity = Sensitivity
|
||||
};
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
}
|
422
src/Ryujinx.Ava/UI/Models/Input/KeyboardInputConfig.cs
Normal file
422
src/Ryujinx.Ava/UI/Models/Input/KeyboardInputConfig.cs
Normal file
@@ -0,0 +1,422 @@
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models.Input
|
||||
{
|
||||
public class KeyboardInputConfig : BaseModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public ControllerType ControllerType { get; set; }
|
||||
public PlayerIndex PlayerIndex { get; set; }
|
||||
|
||||
private Key _leftStickUp;
|
||||
public Key LeftStickUp
|
||||
{
|
||||
get => _leftStickUp;
|
||||
set
|
||||
{
|
||||
_leftStickUp = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _leftStickDown;
|
||||
public Key LeftStickDown
|
||||
{
|
||||
get => _leftStickDown;
|
||||
set
|
||||
{
|
||||
_leftStickDown = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _leftStickLeft;
|
||||
public Key LeftStickLeft
|
||||
{
|
||||
get => _leftStickLeft;
|
||||
set
|
||||
{
|
||||
_leftStickLeft = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _leftStickRight;
|
||||
public Key LeftStickRight
|
||||
{
|
||||
get => _leftStickRight;
|
||||
set
|
||||
{
|
||||
_leftStickRight = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _leftStickButton;
|
||||
public Key LeftStickButton
|
||||
{
|
||||
get => _leftStickButton;
|
||||
set
|
||||
{
|
||||
_leftStickButton = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightStickUp;
|
||||
public Key RightStickUp
|
||||
{
|
||||
get => _rightStickUp;
|
||||
set
|
||||
{
|
||||
_rightStickUp = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightStickDown;
|
||||
public Key RightStickDown
|
||||
{
|
||||
get => _rightStickDown;
|
||||
set
|
||||
{
|
||||
_rightStickDown = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightStickLeft;
|
||||
public Key RightStickLeft
|
||||
{
|
||||
get => _rightStickLeft;
|
||||
set
|
||||
{
|
||||
_rightStickLeft = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightStickRight;
|
||||
public Key RightStickRight
|
||||
{
|
||||
get => _rightStickRight;
|
||||
set
|
||||
{
|
||||
_rightStickRight = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightStickButton;
|
||||
public Key RightStickButton
|
||||
{
|
||||
get => _rightStickButton;
|
||||
set
|
||||
{
|
||||
_rightStickButton = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _dpadUp;
|
||||
public Key DpadUp
|
||||
{
|
||||
get => _dpadUp;
|
||||
set
|
||||
{
|
||||
_dpadUp = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _dpadDown;
|
||||
public Key DpadDown
|
||||
{
|
||||
get => _dpadDown;
|
||||
set
|
||||
{
|
||||
_dpadDown = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _dpadLeft;
|
||||
public Key DpadLeft
|
||||
{
|
||||
get => _dpadLeft;
|
||||
set
|
||||
{
|
||||
_dpadLeft = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _dpadRight;
|
||||
public Key DpadRight
|
||||
{
|
||||
get => _dpadRight;
|
||||
set
|
||||
{
|
||||
_dpadRight = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonL;
|
||||
public Key ButtonL
|
||||
{
|
||||
get => _buttonL;
|
||||
set
|
||||
{
|
||||
_buttonL = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonMinus;
|
||||
public Key ButtonMinus
|
||||
{
|
||||
get => _buttonMinus;
|
||||
set
|
||||
{
|
||||
_buttonMinus = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _leftButtonSl;
|
||||
public Key LeftButtonSl
|
||||
{
|
||||
get => _leftButtonSl;
|
||||
set
|
||||
{
|
||||
_leftButtonSl = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _leftButtonSr;
|
||||
public Key LeftButtonSr
|
||||
{
|
||||
get => _leftButtonSr;
|
||||
set
|
||||
{
|
||||
_leftButtonSr = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonZl;
|
||||
public Key ButtonZl
|
||||
{
|
||||
get => _buttonZl;
|
||||
set
|
||||
{
|
||||
_buttonZl = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonA;
|
||||
public Key ButtonA
|
||||
{
|
||||
get => _buttonA;
|
||||
set
|
||||
{
|
||||
_buttonA = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonB;
|
||||
public Key ButtonB
|
||||
{
|
||||
get => _buttonB;
|
||||
set
|
||||
{
|
||||
_buttonB = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonX;
|
||||
public Key ButtonX
|
||||
{
|
||||
get => _buttonX;
|
||||
set
|
||||
{
|
||||
_buttonX = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonY;
|
||||
public Key ButtonY
|
||||
{
|
||||
get => _buttonY;
|
||||
set
|
||||
{
|
||||
_buttonY = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonR;
|
||||
public Key ButtonR
|
||||
{
|
||||
get => _buttonR;
|
||||
set
|
||||
{
|
||||
_buttonR = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonPlus;
|
||||
public Key ButtonPlus
|
||||
{
|
||||
get => _buttonPlus;
|
||||
set
|
||||
{
|
||||
_buttonPlus = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightButtonSl;
|
||||
public Key RightButtonSl
|
||||
{
|
||||
get => _rightButtonSl;
|
||||
set
|
||||
{
|
||||
_rightButtonSl = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _rightButtonSr;
|
||||
public Key RightButtonSr
|
||||
{
|
||||
get => _rightButtonSr;
|
||||
set
|
||||
{
|
||||
_rightButtonSr = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Key _buttonZr;
|
||||
public Key ButtonZr
|
||||
{
|
||||
get => _buttonZr;
|
||||
set
|
||||
{
|
||||
_buttonZr = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public KeyboardInputConfig(InputConfig config)
|
||||
{
|
||||
if (config != null)
|
||||
{
|
||||
Id = config.Id;
|
||||
ControllerType = config.ControllerType;
|
||||
PlayerIndex = config.PlayerIndex;
|
||||
|
||||
if (config is not StandardKeyboardInputConfig keyboardConfig)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LeftStickUp = keyboardConfig.LeftJoyconStick.StickUp;
|
||||
LeftStickDown = keyboardConfig.LeftJoyconStick.StickDown;
|
||||
LeftStickLeft = keyboardConfig.LeftJoyconStick.StickLeft;
|
||||
LeftStickRight = keyboardConfig.LeftJoyconStick.StickRight;
|
||||
LeftStickButton = keyboardConfig.LeftJoyconStick.StickButton;
|
||||
|
||||
RightStickUp = keyboardConfig.RightJoyconStick.StickUp;
|
||||
RightStickDown = keyboardConfig.RightJoyconStick.StickDown;
|
||||
RightStickLeft = keyboardConfig.RightJoyconStick.StickLeft;
|
||||
RightStickRight = keyboardConfig.RightJoyconStick.StickRight;
|
||||
RightStickButton = keyboardConfig.RightJoyconStick.StickButton;
|
||||
|
||||
DpadUp = keyboardConfig.LeftJoycon.DpadUp;
|
||||
DpadDown = keyboardConfig.LeftJoycon.DpadDown;
|
||||
DpadLeft = keyboardConfig.LeftJoycon.DpadLeft;
|
||||
DpadRight = keyboardConfig.LeftJoycon.DpadRight;
|
||||
ButtonL = keyboardConfig.LeftJoycon.ButtonL;
|
||||
ButtonMinus = keyboardConfig.LeftJoycon.ButtonMinus;
|
||||
LeftButtonSl = keyboardConfig.LeftJoycon.ButtonSl;
|
||||
LeftButtonSr = keyboardConfig.LeftJoycon.ButtonSr;
|
||||
ButtonZl = keyboardConfig.LeftJoycon.ButtonZl;
|
||||
|
||||
ButtonA = keyboardConfig.RightJoycon.ButtonA;
|
||||
ButtonB = keyboardConfig.RightJoycon.ButtonB;
|
||||
ButtonX = keyboardConfig.RightJoycon.ButtonX;
|
||||
ButtonY = keyboardConfig.RightJoycon.ButtonY;
|
||||
ButtonR = keyboardConfig.RightJoycon.ButtonR;
|
||||
ButtonPlus = keyboardConfig.RightJoycon.ButtonPlus;
|
||||
RightButtonSl = keyboardConfig.RightJoycon.ButtonSl;
|
||||
RightButtonSr = keyboardConfig.RightJoycon.ButtonSr;
|
||||
ButtonZr = keyboardConfig.RightJoycon.ButtonZr;
|
||||
}
|
||||
}
|
||||
|
||||
public InputConfig GetConfig()
|
||||
{
|
||||
var config = new StandardKeyboardInputConfig
|
||||
{
|
||||
Id = Id,
|
||||
Backend = InputBackendType.WindowKeyboard,
|
||||
PlayerIndex = PlayerIndex,
|
||||
ControllerType = ControllerType,
|
||||
LeftJoycon = new LeftJoyconCommonConfig<Key>
|
||||
{
|
||||
DpadUp = DpadUp,
|
||||
DpadDown = DpadDown,
|
||||
DpadLeft = DpadLeft,
|
||||
DpadRight = DpadRight,
|
||||
ButtonL = ButtonL,
|
||||
ButtonMinus = ButtonMinus,
|
||||
ButtonZl = ButtonZl,
|
||||
ButtonSl = LeftButtonSl,
|
||||
ButtonSr = LeftButtonSr
|
||||
},
|
||||
RightJoycon = new RightJoyconCommonConfig<Key>
|
||||
{
|
||||
ButtonA = ButtonA,
|
||||
ButtonB = ButtonB,
|
||||
ButtonX = ButtonX,
|
||||
ButtonY = ButtonY,
|
||||
ButtonPlus = ButtonPlus,
|
||||
ButtonSl = RightButtonSl,
|
||||
ButtonSr = RightButtonSr,
|
||||
ButtonR = ButtonR,
|
||||
ButtonZr = ButtonZr
|
||||
},
|
||||
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||
{
|
||||
StickUp = LeftStickUp,
|
||||
StickDown = LeftStickDown,
|
||||
StickRight = LeftStickRight,
|
||||
StickLeft = LeftStickLeft,
|
||||
StickButton = LeftStickButton
|
||||
},
|
||||
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||
{
|
||||
StickUp = RightStickUp,
|
||||
StickDown = RightStickDown,
|
||||
StickLeft = RightStickLeft,
|
||||
StickRight = RightStickRight,
|
||||
StickButton = RightStickButton
|
||||
},
|
||||
Version = InputConfig.CurrentVersion
|
||||
};
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,456 +0,0 @@
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models
|
||||
{
|
||||
internal class InputConfiguration<TKey, TStick> : BaseModel
|
||||
{
|
||||
private float _deadzoneRight;
|
||||
private float _triggerThreshold;
|
||||
private float _deadzoneLeft;
|
||||
private double _gyroDeadzone;
|
||||
private int _sensitivity;
|
||||
private bool _enableMotion;
|
||||
private float _weakRumble;
|
||||
private float _strongRumble;
|
||||
private float _rangeLeft;
|
||||
private float _rangeRight;
|
||||
|
||||
public InputBackendType Backend { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Controller id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Controller's Type
|
||||
/// </summary>
|
||||
public ControllerType ControllerType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Player's Index for the controller
|
||||
/// </summary>
|
||||
public PlayerIndex PlayerIndex { get; set; }
|
||||
|
||||
public TStick LeftJoystick { get; set; }
|
||||
public bool LeftInvertStickX { get; set; }
|
||||
public bool LeftInvertStickY { get; set; }
|
||||
public bool RightRotate90 { get; set; }
|
||||
public TKey LeftControllerStickButton { get; set; }
|
||||
|
||||
public TStick RightJoystick { get; set; }
|
||||
public bool RightInvertStickX { get; set; }
|
||||
public bool RightInvertStickY { get; set; }
|
||||
public bool LeftRotate90 { get; set; }
|
||||
public TKey RightControllerStickButton { get; set; }
|
||||
|
||||
public float DeadzoneLeft
|
||||
{
|
||||
get => _deadzoneLeft;
|
||||
set
|
||||
{
|
||||
_deadzoneLeft = MathF.Round(value, 3);
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public float RangeLeft
|
||||
{
|
||||
get => _rangeLeft;
|
||||
set
|
||||
{
|
||||
_rangeLeft = MathF.Round(value, 3);
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public float DeadzoneRight
|
||||
{
|
||||
get => _deadzoneRight;
|
||||
set
|
||||
{
|
||||
_deadzoneRight = MathF.Round(value, 3);
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public float RangeRight
|
||||
{
|
||||
get => _rangeRight;
|
||||
set
|
||||
{
|
||||
_rangeRight = MathF.Round(value, 3);
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public float TriggerThreshold
|
||||
{
|
||||
get => _triggerThreshold;
|
||||
set
|
||||
{
|
||||
_triggerThreshold = MathF.Round(value, 3);
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public MotionInputBackendType MotionBackend { get; set; }
|
||||
|
||||
public TKey ButtonMinus { get; set; }
|
||||
public TKey ButtonL { get; set; }
|
||||
public TKey ButtonZl { get; set; }
|
||||
public TKey LeftButtonSl { get; set; }
|
||||
public TKey LeftButtonSr { get; set; }
|
||||
public TKey DpadUp { get; set; }
|
||||
public TKey DpadDown { get; set; }
|
||||
public TKey DpadLeft { get; set; }
|
||||
public TKey DpadRight { get; set; }
|
||||
|
||||
public TKey ButtonPlus { get; set; }
|
||||
public TKey ButtonR { get; set; }
|
||||
public TKey ButtonZr { get; set; }
|
||||
public TKey RightButtonSl { get; set; }
|
||||
public TKey RightButtonSr { get; set; }
|
||||
public TKey ButtonX { get; set; }
|
||||
public TKey ButtonB { get; set; }
|
||||
public TKey ButtonY { get; set; }
|
||||
public TKey ButtonA { get; set; }
|
||||
|
||||
public TKey LeftStickUp { get; set; }
|
||||
public TKey LeftStickDown { get; set; }
|
||||
public TKey LeftStickLeft { get; set; }
|
||||
public TKey LeftStickRight { get; set; }
|
||||
public TKey LeftKeyboardStickButton { get; set; }
|
||||
|
||||
public TKey RightStickUp { get; set; }
|
||||
public TKey RightStickDown { get; set; }
|
||||
public TKey RightStickLeft { get; set; }
|
||||
public TKey RightStickRight { get; set; }
|
||||
public TKey RightKeyboardStickButton { get; set; }
|
||||
|
||||
public int Sensitivity
|
||||
{
|
||||
get => _sensitivity;
|
||||
set
|
||||
{
|
||||
_sensitivity = value;
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public double GyroDeadzone
|
||||
{
|
||||
get => _gyroDeadzone;
|
||||
set
|
||||
{
|
||||
_gyroDeadzone = Math.Round(value, 3);
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool EnableMotion
|
||||
{
|
||||
get => _enableMotion; set
|
||||
{
|
||||
_enableMotion = value;
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool EnableCemuHookMotion { get; set; }
|
||||
public int Slot { get; set; }
|
||||
public int AltSlot { get; set; }
|
||||
public bool MirrorInput { get; set; }
|
||||
public string DsuServerHost { get; set; }
|
||||
public int DsuServerPort { get; set; }
|
||||
|
||||
public bool EnableRumble { get; set; }
|
||||
public float WeakRumble
|
||||
{
|
||||
get => _weakRumble; set
|
||||
{
|
||||
_weakRumble = value;
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
public float StrongRumble
|
||||
{
|
||||
get => _strongRumble; set
|
||||
{
|
||||
_strongRumble = value;
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public InputConfiguration(InputConfig config)
|
||||
{
|
||||
if (config != null)
|
||||
{
|
||||
Backend = config.Backend;
|
||||
Id = config.Id;
|
||||
ControllerType = config.ControllerType;
|
||||
PlayerIndex = config.PlayerIndex;
|
||||
|
||||
if (config is StandardKeyboardInputConfig keyboardConfig)
|
||||
{
|
||||
LeftStickUp = (TKey)(object)keyboardConfig.LeftJoyconStick.StickUp;
|
||||
LeftStickDown = (TKey)(object)keyboardConfig.LeftJoyconStick.StickDown;
|
||||
LeftStickLeft = (TKey)(object)keyboardConfig.LeftJoyconStick.StickLeft;
|
||||
LeftStickRight = (TKey)(object)keyboardConfig.LeftJoyconStick.StickRight;
|
||||
LeftKeyboardStickButton = (TKey)(object)keyboardConfig.LeftJoyconStick.StickButton;
|
||||
|
||||
RightStickUp = (TKey)(object)keyboardConfig.RightJoyconStick.StickUp;
|
||||
RightStickDown = (TKey)(object)keyboardConfig.RightJoyconStick.StickDown;
|
||||
RightStickLeft = (TKey)(object)keyboardConfig.RightJoyconStick.StickLeft;
|
||||
RightStickRight = (TKey)(object)keyboardConfig.RightJoyconStick.StickRight;
|
||||
RightKeyboardStickButton = (TKey)(object)keyboardConfig.RightJoyconStick.StickButton;
|
||||
|
||||
ButtonA = (TKey)(object)keyboardConfig.RightJoycon.ButtonA;
|
||||
ButtonB = (TKey)(object)keyboardConfig.RightJoycon.ButtonB;
|
||||
ButtonX = (TKey)(object)keyboardConfig.RightJoycon.ButtonX;
|
||||
ButtonY = (TKey)(object)keyboardConfig.RightJoycon.ButtonY;
|
||||
ButtonR = (TKey)(object)keyboardConfig.RightJoycon.ButtonR;
|
||||
RightButtonSl = (TKey)(object)keyboardConfig.RightJoycon.ButtonSl;
|
||||
RightButtonSr = (TKey)(object)keyboardConfig.RightJoycon.ButtonSr;
|
||||
ButtonZr = (TKey)(object)keyboardConfig.RightJoycon.ButtonZr;
|
||||
ButtonPlus = (TKey)(object)keyboardConfig.RightJoycon.ButtonPlus;
|
||||
|
||||
DpadUp = (TKey)(object)keyboardConfig.LeftJoycon.DpadUp;
|
||||
DpadDown = (TKey)(object)keyboardConfig.LeftJoycon.DpadDown;
|
||||
DpadLeft = (TKey)(object)keyboardConfig.LeftJoycon.DpadLeft;
|
||||
DpadRight = (TKey)(object)keyboardConfig.LeftJoycon.DpadRight;
|
||||
ButtonMinus = (TKey)(object)keyboardConfig.LeftJoycon.ButtonMinus;
|
||||
LeftButtonSl = (TKey)(object)keyboardConfig.LeftJoycon.ButtonSl;
|
||||
LeftButtonSr = (TKey)(object)keyboardConfig.LeftJoycon.ButtonSr;
|
||||
ButtonZl = (TKey)(object)keyboardConfig.LeftJoycon.ButtonZl;
|
||||
ButtonL = (TKey)(object)keyboardConfig.LeftJoycon.ButtonL;
|
||||
}
|
||||
else if (config is StandardControllerInputConfig controllerConfig)
|
||||
{
|
||||
LeftJoystick = (TStick)(object)controllerConfig.LeftJoyconStick.Joystick;
|
||||
LeftInvertStickX = controllerConfig.LeftJoyconStick.InvertStickX;
|
||||
LeftInvertStickY = controllerConfig.LeftJoyconStick.InvertStickY;
|
||||
LeftRotate90 = controllerConfig.LeftJoyconStick.Rotate90CW;
|
||||
LeftControllerStickButton = (TKey)(object)controllerConfig.LeftJoyconStick.StickButton;
|
||||
|
||||
RightJoystick = (TStick)(object)controllerConfig.RightJoyconStick.Joystick;
|
||||
RightInvertStickX = controllerConfig.RightJoyconStick.InvertStickX;
|
||||
RightInvertStickY = controllerConfig.RightJoyconStick.InvertStickY;
|
||||
RightRotate90 = controllerConfig.RightJoyconStick.Rotate90CW;
|
||||
RightControllerStickButton = (TKey)(object)controllerConfig.RightJoyconStick.StickButton;
|
||||
|
||||
ButtonA = (TKey)(object)controllerConfig.RightJoycon.ButtonA;
|
||||
ButtonB = (TKey)(object)controllerConfig.RightJoycon.ButtonB;
|
||||
ButtonX = (TKey)(object)controllerConfig.RightJoycon.ButtonX;
|
||||
ButtonY = (TKey)(object)controllerConfig.RightJoycon.ButtonY;
|
||||
ButtonR = (TKey)(object)controllerConfig.RightJoycon.ButtonR;
|
||||
RightButtonSl = (TKey)(object)controllerConfig.RightJoycon.ButtonSl;
|
||||
RightButtonSr = (TKey)(object)controllerConfig.RightJoycon.ButtonSr;
|
||||
ButtonZr = (TKey)(object)controllerConfig.RightJoycon.ButtonZr;
|
||||
ButtonPlus = (TKey)(object)controllerConfig.RightJoycon.ButtonPlus;
|
||||
|
||||
DpadUp = (TKey)(object)controllerConfig.LeftJoycon.DpadUp;
|
||||
DpadDown = (TKey)(object)controllerConfig.LeftJoycon.DpadDown;
|
||||
DpadLeft = (TKey)(object)controllerConfig.LeftJoycon.DpadLeft;
|
||||
DpadRight = (TKey)(object)controllerConfig.LeftJoycon.DpadRight;
|
||||
ButtonMinus = (TKey)(object)controllerConfig.LeftJoycon.ButtonMinus;
|
||||
LeftButtonSl = (TKey)(object)controllerConfig.LeftJoycon.ButtonSl;
|
||||
LeftButtonSr = (TKey)(object)controllerConfig.LeftJoycon.ButtonSr;
|
||||
ButtonZl = (TKey)(object)controllerConfig.LeftJoycon.ButtonZl;
|
||||
ButtonL = (TKey)(object)controllerConfig.LeftJoycon.ButtonL;
|
||||
|
||||
DeadzoneLeft = controllerConfig.DeadzoneLeft;
|
||||
DeadzoneRight = controllerConfig.DeadzoneRight;
|
||||
RangeLeft = controllerConfig.RangeLeft;
|
||||
RangeRight = controllerConfig.RangeRight;
|
||||
TriggerThreshold = controllerConfig.TriggerThreshold;
|
||||
|
||||
if (controllerConfig.Motion != null)
|
||||
{
|
||||
EnableMotion = controllerConfig.Motion.EnableMotion;
|
||||
MotionBackend = controllerConfig.Motion.MotionBackend;
|
||||
GyroDeadzone = controllerConfig.Motion.GyroDeadzone;
|
||||
Sensitivity = controllerConfig.Motion.Sensitivity;
|
||||
|
||||
if (controllerConfig.Motion is CemuHookMotionConfigController cemuHook)
|
||||
{
|
||||
EnableCemuHookMotion = true;
|
||||
DsuServerHost = cemuHook.DsuServerHost;
|
||||
DsuServerPort = cemuHook.DsuServerPort;
|
||||
Slot = cemuHook.Slot;
|
||||
AltSlot = cemuHook.AltSlot;
|
||||
MirrorInput = cemuHook.MirrorInput;
|
||||
}
|
||||
|
||||
if (controllerConfig.Rumble != null)
|
||||
{
|
||||
EnableRumble = controllerConfig.Rumble.EnableRumble;
|
||||
WeakRumble = controllerConfig.Rumble.WeakRumble;
|
||||
StrongRumble = controllerConfig.Rumble.StrongRumble;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public InputConfiguration()
|
||||
{
|
||||
}
|
||||
|
||||
public InputConfig GetConfig()
|
||||
{
|
||||
if (Backend == InputBackendType.WindowKeyboard)
|
||||
{
|
||||
return new StandardKeyboardInputConfig
|
||||
{
|
||||
Id = Id,
|
||||
Backend = Backend,
|
||||
PlayerIndex = PlayerIndex,
|
||||
ControllerType = ControllerType,
|
||||
LeftJoycon = new LeftJoyconCommonConfig<Key>
|
||||
{
|
||||
DpadUp = (Key)(object)DpadUp,
|
||||
DpadDown = (Key)(object)DpadDown,
|
||||
DpadLeft = (Key)(object)DpadLeft,
|
||||
DpadRight = (Key)(object)DpadRight,
|
||||
ButtonL = (Key)(object)ButtonL,
|
||||
ButtonZl = (Key)(object)ButtonZl,
|
||||
ButtonSl = (Key)(object)LeftButtonSl,
|
||||
ButtonSr = (Key)(object)LeftButtonSr,
|
||||
ButtonMinus = (Key)(object)ButtonMinus,
|
||||
},
|
||||
RightJoycon = new RightJoyconCommonConfig<Key>
|
||||
{
|
||||
ButtonA = (Key)(object)ButtonA,
|
||||
ButtonB = (Key)(object)ButtonB,
|
||||
ButtonX = (Key)(object)ButtonX,
|
||||
ButtonY = (Key)(object)ButtonY,
|
||||
ButtonPlus = (Key)(object)ButtonPlus,
|
||||
ButtonSl = (Key)(object)RightButtonSl,
|
||||
ButtonSr = (Key)(object)RightButtonSr,
|
||||
ButtonR = (Key)(object)ButtonR,
|
||||
ButtonZr = (Key)(object)ButtonZr,
|
||||
},
|
||||
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||
{
|
||||
StickUp = (Key)(object)LeftStickUp,
|
||||
StickDown = (Key)(object)LeftStickDown,
|
||||
StickRight = (Key)(object)LeftStickRight,
|
||||
StickLeft = (Key)(object)LeftStickLeft,
|
||||
StickButton = (Key)(object)LeftKeyboardStickButton,
|
||||
},
|
||||
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||
{
|
||||
StickUp = (Key)(object)RightStickUp,
|
||||
StickDown = (Key)(object)RightStickDown,
|
||||
StickLeft = (Key)(object)RightStickLeft,
|
||||
StickRight = (Key)(object)RightStickRight,
|
||||
StickButton = (Key)(object)RightKeyboardStickButton,
|
||||
},
|
||||
Version = InputConfig.CurrentVersion,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
if (Backend == InputBackendType.GamepadSDL2)
|
||||
{
|
||||
var config = new StandardControllerInputConfig
|
||||
{
|
||||
Id = Id,
|
||||
Backend = Backend,
|
||||
PlayerIndex = PlayerIndex,
|
||||
ControllerType = ControllerType,
|
||||
LeftJoycon = new LeftJoyconCommonConfig<GamepadInputId>
|
||||
{
|
||||
DpadUp = (GamepadInputId)(object)DpadUp,
|
||||
DpadDown = (GamepadInputId)(object)DpadDown,
|
||||
DpadLeft = (GamepadInputId)(object)DpadLeft,
|
||||
DpadRight = (GamepadInputId)(object)DpadRight,
|
||||
ButtonL = (GamepadInputId)(object)ButtonL,
|
||||
ButtonZl = (GamepadInputId)(object)ButtonZl,
|
||||
ButtonSl = (GamepadInputId)(object)LeftButtonSl,
|
||||
ButtonSr = (GamepadInputId)(object)LeftButtonSr,
|
||||
ButtonMinus = (GamepadInputId)(object)ButtonMinus,
|
||||
},
|
||||
RightJoycon = new RightJoyconCommonConfig<GamepadInputId>
|
||||
{
|
||||
ButtonA = (GamepadInputId)(object)ButtonA,
|
||||
ButtonB = (GamepadInputId)(object)ButtonB,
|
||||
ButtonX = (GamepadInputId)(object)ButtonX,
|
||||
ButtonY = (GamepadInputId)(object)ButtonY,
|
||||
ButtonPlus = (GamepadInputId)(object)ButtonPlus,
|
||||
ButtonSl = (GamepadInputId)(object)RightButtonSl,
|
||||
ButtonSr = (GamepadInputId)(object)RightButtonSr,
|
||||
ButtonR = (GamepadInputId)(object)ButtonR,
|
||||
ButtonZr = (GamepadInputId)(object)ButtonZr,
|
||||
},
|
||||
LeftJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
|
||||
{
|
||||
Joystick = (StickInputId)(object)LeftJoystick,
|
||||
InvertStickX = LeftInvertStickX,
|
||||
InvertStickY = LeftInvertStickY,
|
||||
Rotate90CW = LeftRotate90,
|
||||
StickButton = (GamepadInputId)(object)LeftControllerStickButton,
|
||||
},
|
||||
RightJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
|
||||
{
|
||||
Joystick = (StickInputId)(object)RightJoystick,
|
||||
InvertStickX = RightInvertStickX,
|
||||
InvertStickY = RightInvertStickY,
|
||||
Rotate90CW = RightRotate90,
|
||||
StickButton = (GamepadInputId)(object)RightControllerStickButton,
|
||||
},
|
||||
Rumble = new RumbleConfigController
|
||||
{
|
||||
EnableRumble = EnableRumble,
|
||||
WeakRumble = WeakRumble,
|
||||
StrongRumble = StrongRumble,
|
||||
},
|
||||
Version = InputConfig.CurrentVersion,
|
||||
DeadzoneLeft = DeadzoneLeft,
|
||||
DeadzoneRight = DeadzoneRight,
|
||||
RangeLeft = RangeLeft,
|
||||
RangeRight = RangeRight,
|
||||
TriggerThreshold = TriggerThreshold,
|
||||
Motion = EnableCemuHookMotion
|
||||
? new CemuHookMotionConfigController
|
||||
{
|
||||
DsuServerHost = DsuServerHost,
|
||||
DsuServerPort = DsuServerPort,
|
||||
Slot = Slot,
|
||||
AltSlot = AltSlot,
|
||||
MirrorInput = MirrorInput,
|
||||
MotionBackend = MotionInputBackendType.CemuHook,
|
||||
}
|
||||
: new StandardMotionConfigController
|
||||
{
|
||||
MotionBackend = MotionInputBackendType.GamepadDriver,
|
||||
},
|
||||
};
|
||||
|
||||
config.Motion.Sensitivity = Sensitivity;
|
||||
config.Motion.EnableMotion = EnableMotion;
|
||||
config.Motion.GyroDeadzone = GyroDeadzone;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
using Avalonia.Svg.Skia;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Views.Input;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
public class ControllerInputViewModel : BaseModel
|
||||
{
|
||||
private ControllerInputConfig _config;
|
||||
public ControllerInputConfig Config
|
||||
{
|
||||
get => _config;
|
||||
set
|
||||
{
|
||||
_config = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isLeft;
|
||||
public bool IsLeft
|
||||
{
|
||||
get => _isLeft;
|
||||
set
|
||||
{
|
||||
_isLeft = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(HasSides));
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isRight;
|
||||
public bool IsRight
|
||||
{
|
||||
get => _isRight;
|
||||
set
|
||||
{
|
||||
_isRight = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(HasSides));
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasSides => IsLeft ^ IsRight;
|
||||
|
||||
private SvgImage _image;
|
||||
public SvgImage Image
|
||||
{
|
||||
get => _image;
|
||||
set
|
||||
{
|
||||
_image = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public InputViewModel parentModel;
|
||||
|
||||
public ControllerInputViewModel(InputViewModel model, ControllerInputConfig config)
|
||||
{
|
||||
parentModel = model;
|
||||
model.NotifyChangesEvent += OnParentModelChanged;
|
||||
OnParentModelChanged();
|
||||
Config = config;
|
||||
}
|
||||
|
||||
public async void ShowMotionConfig()
|
||||
{
|
||||
await MotionInputView.Show(this);
|
||||
}
|
||||
|
||||
public async void ShowRumbleConfig()
|
||||
{
|
||||
await RumbleInputView.Show(this);
|
||||
}
|
||||
|
||||
public void OnParentModelChanged()
|
||||
{
|
||||
IsLeft = parentModel.IsLeft;
|
||||
IsRight = parentModel.IsRight;
|
||||
Image = parentModel.Image;
|
||||
}
|
||||
}
|
||||
}
|
@@ -8,7 +8,7 @@ using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.Views.Input;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
@@ -30,9 +30,9 @@ using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.Gamepad
|
||||
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||
using Key = Ryujinx.Common.Configuration.Hid.Key;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
public class ControllerInputViewModel : BaseModel, IDisposable
|
||||
public class InputViewModel : BaseModel, IDisposable
|
||||
{
|
||||
private const string Disabled = "disabled";
|
||||
private const string ProControllerResource = "Ryujinx.Ui.Common/Resources/Controller_ProCon.svg";
|
||||
@@ -48,7 +48,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private int _controllerNumber;
|
||||
private string _controllerImage;
|
||||
private int _device;
|
||||
private object _configuration;
|
||||
private object _configViewModel;
|
||||
private string _profileName;
|
||||
private bool _isLoaded;
|
||||
|
||||
@@ -71,13 +71,14 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public bool IsLeft { get; set; }
|
||||
|
||||
public bool IsModified { get; set; }
|
||||
public event Action NotifyChangesEvent;
|
||||
|
||||
public object Configuration
|
||||
public object ConfigViewModel
|
||||
{
|
||||
get => _configuration;
|
||||
get => _configViewModel;
|
||||
set
|
||||
{
|
||||
_configuration = value;
|
||||
_configViewModel = value;
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
@@ -232,7 +233,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public InputConfig Config { get; set; }
|
||||
|
||||
public ControllerInputViewModel(UserControl owner) : this()
|
||||
public InputViewModel(UserControl owner) : this()
|
||||
{
|
||||
if (Program.PreviewerDetached)
|
||||
{
|
||||
@@ -244,7 +245,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
||||
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
||||
|
||||
_mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates();
|
||||
|
||||
_isLoaded = false;
|
||||
@@ -255,7 +255,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public ControllerInputViewModel()
|
||||
public InputViewModel()
|
||||
{
|
||||
PlayerIndexes = new ObservableCollection<PlayerModel>();
|
||||
Controllers = new ObservableCollection<ControllerModel>();
|
||||
@@ -282,12 +282,12 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
if (Config is StandardKeyboardInputConfig keyboardInputConfig)
|
||||
{
|
||||
Configuration = new InputConfiguration<Key, ConfigStickInputId>(keyboardInputConfig);
|
||||
ConfigViewModel = new KeyboardInputViewModel(this, new KeyboardInputConfig(keyboardInputConfig));
|
||||
}
|
||||
|
||||
if (Config is StandardControllerInputConfig controllerInputConfig)
|
||||
{
|
||||
Configuration = new InputConfiguration<ConfigGamepadInputId, ConfigStickInputId>(controllerInputConfig);
|
||||
ConfigViewModel = new ControllerInputViewModel(this, new ControllerInputConfig(controllerInputConfig));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,16 +323,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public async void ShowMotionConfig()
|
||||
{
|
||||
await MotionInputView.Show(this);
|
||||
}
|
||||
|
||||
public async void ShowRumbleConfig()
|
||||
{
|
||||
await RumbleInputView.Show(this);
|
||||
}
|
||||
|
||||
private void LoadInputDriver()
|
||||
{
|
||||
if (_device < 0)
|
||||
@@ -740,7 +730,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
if (Configuration == null)
|
||||
if (ConfigViewModel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -751,7 +741,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
|
||||
|
||||
if (validFileName)
|
||||
@@ -762,11 +753,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
if (IsKeyboard)
|
||||
{
|
||||
config = (Configuration as InputConfiguration<Key, ConfigStickInputId>).GetConfig();
|
||||
config = (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig();
|
||||
}
|
||||
else if (IsController)
|
||||
{
|
||||
config = (Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>).GetConfig();
|
||||
config = (ConfigViewModel as ControllerInputViewModel).Config.GetConfig();
|
||||
}
|
||||
|
||||
config.ControllerType = Controllers[_controller].Type;
|
||||
@@ -782,6 +773,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async void RemoveProfile()
|
||||
{
|
||||
@@ -830,18 +822,18 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
if (device.Type == DeviceType.Keyboard)
|
||||
{
|
||||
var inputConfig = Configuration as InputConfiguration<Key, ConfigStickInputId>;
|
||||
var inputConfig = (ConfigViewModel as KeyboardInputViewModel).Config;
|
||||
inputConfig.Id = device.Id;
|
||||
}
|
||||
else
|
||||
{
|
||||
var inputConfig = Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>;
|
||||
var inputConfig = (ConfigViewModel as ControllerInputViewModel).Config;
|
||||
inputConfig.Id = device.Id.Split(" ")[0];
|
||||
}
|
||||
|
||||
var config = !IsController
|
||||
? (Configuration as InputConfiguration<Key, ConfigStickInputId>).GetConfig()
|
||||
: (Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>).GetConfig();
|
||||
? (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig()
|
||||
: (ConfigViewModel as ControllerInputViewModel).Config.GetConfig();
|
||||
config.ControllerType = Controllers[_controller].Type;
|
||||
config.PlayerIndex = _playerId;
|
||||
|
||||
@@ -872,12 +864,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public void NotifyChanges()
|
||||
{
|
||||
OnPropertyChanged(nameof(Configuration));
|
||||
OnPropertyChanged(nameof(ConfigViewModel));
|
||||
OnPropertyChanged(nameof(IsController));
|
||||
OnPropertyChanged(nameof(ShowSettings));
|
||||
OnPropertyChanged(nameof(IsKeyboard));
|
||||
OnPropertyChanged(nameof(IsRight));
|
||||
OnPropertyChanged(nameof(IsLeft));
|
||||
NotifyChangesEvent?.Invoke();
|
||||
}
|
||||
|
||||
public void Dispose()
|
@@ -0,0 +1,73 @@
|
||||
using Avalonia.Svg.Skia;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
public class KeyboardInputViewModel : BaseModel
|
||||
{
|
||||
private KeyboardInputConfig _config;
|
||||
public KeyboardInputConfig Config
|
||||
{
|
||||
get => _config;
|
||||
set
|
||||
{
|
||||
_config = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isLeft;
|
||||
public bool IsLeft
|
||||
{
|
||||
get => _isLeft;
|
||||
set
|
||||
{
|
||||
_isLeft = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(HasSides));
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isRight;
|
||||
public bool IsRight
|
||||
{
|
||||
get => _isRight;
|
||||
set
|
||||
{
|
||||
_isRight = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(HasSides));
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasSides => IsLeft ^ IsRight;
|
||||
|
||||
private SvgImage _image;
|
||||
public SvgImage Image
|
||||
{
|
||||
get => _image;
|
||||
set
|
||||
{
|
||||
_image = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public InputViewModel parentModel;
|
||||
|
||||
public KeyboardInputViewModel(InputViewModel model, KeyboardInputConfig config)
|
||||
{
|
||||
parentModel = model;
|
||||
model.NotifyChangesEvent += OnParentModelChanged;
|
||||
OnParentModelChanged();
|
||||
Config = config;
|
||||
}
|
||||
|
||||
public void OnParentModelChanged()
|
||||
{
|
||||
IsLeft = parentModel.IsLeft;
|
||||
IsRight = parentModel.IsRight;
|
||||
Image = parentModel.Image;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
public class MotionInputViewModel : BaseModel
|
||||
{
|
@@ -1,4 +1,4 @@
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
public class RumbleInputViewModel : BaseModel
|
||||
{
|
@@ -356,6 +356,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public bool OpenBcatSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
|
||||
|
||||
public bool CreateShortcutEnabled => !ReleaseInformation.IsFlatHubBuild();
|
||||
|
||||
public string LoadHeading
|
||||
{
|
||||
get => _loadHeading;
|
||||
@@ -1488,7 +1490,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
Logger.RestartTime();
|
||||
|
||||
SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(path);
|
||||
SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(path, ConfigurationState.Instance.System.Language);
|
||||
|
||||
PrepareLoadScreen();
|
||||
|
||||
@@ -1696,7 +1698,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@@ -1,12 +1,11 @@
|
||||
<UserControl
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
|
||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
@@ -14,6 +13,7 @@
|
||||
d:DesignWidth="800"
|
||||
x:Class="Ryujinx.Ava.UI.Views.Input.ControllerInputView"
|
||||
x:DataType="viewModels:ControllerInputViewModel"
|
||||
x:CompileBindings="True"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
<Design.DataContext>
|
||||
@@ -33,191 +33,10 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Orientation="Vertical">
|
||||
<StackPanel
|
||||
Margin="0 0 0 5"
|
||||
Orientation="Vertical"
|
||||
Spacing="5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="10" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<!-- Player Selection -->
|
||||
<Grid
|
||||
Grid.Column="0"
|
||||
Margin="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="5,0,10,0"
|
||||
Width="90"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsPlayer}" />
|
||||
<ComboBox
|
||||
Grid.Column="1"
|
||||
Name="PlayerIndexBox"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
SelectionChanged="PlayerIndexBox_OnSelectionChanged"
|
||||
ItemsSource="{Binding PlayerIndexes}"
|
||||
SelectedIndex="{Binding PlayerId}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
<!-- Profile Selection -->
|
||||
<Grid
|
||||
Grid.Column="2"
|
||||
Margin="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="5,0,10,0"
|
||||
Width="90"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsProfile}" />
|
||||
<ui:FAComboBox
|
||||
Grid.Column="1"
|
||||
IsEditable="True"
|
||||
Name="ProfileBox"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
SelectedIndex="0"
|
||||
ItemsSource="{Binding ProfilesList}"
|
||||
Text="{Binding ProfileName, Mode=TwoWay}" />
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
MinWidth="0"
|
||||
Margin="5,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="{locale:Locale ControllerSettingsLoadProfileToolTip}"
|
||||
Command="{ReflectionBinding LoadProfile}">
|
||||
<ui:SymbolIcon
|
||||
Symbol="Upload"
|
||||
FontSize="15"
|
||||
Height="20" />
|
||||
</Button>
|
||||
<Button
|
||||
Grid.Column="3"
|
||||
MinWidth="0"
|
||||
Margin="5,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="{locale:Locale ControllerSettingsSaveProfileToolTip}"
|
||||
Command="{ReflectionBinding SaveProfile}">
|
||||
<ui:SymbolIcon
|
||||
Symbol="Save"
|
||||
FontSize="15"
|
||||
Height="20" />
|
||||
</Button>
|
||||
<Button
|
||||
Grid.Column="4"
|
||||
MinWidth="0"
|
||||
Margin="5,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="{locale:Locale ControllerSettingsRemoveProfileToolTip}"
|
||||
Command="{ReflectionBinding RemoveProfile}">
|
||||
<ui:SymbolIcon
|
||||
Symbol="Delete"
|
||||
FontSize="15"
|
||||
Height="20" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Separator />
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="10" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<!-- Input Device -->
|
||||
<Grid
|
||||
Grid.Column="0"
|
||||
Margin="2"
|
||||
HorizontalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Margin="5,0,10,0"
|
||||
Width="90"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsInputDevice}" />
|
||||
<ComboBox
|
||||
Grid.Column="1"
|
||||
Name="DeviceBox"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
ItemsSource="{Binding DeviceList}"
|
||||
SelectedIndex="{Binding Device}" />
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
MinWidth="0"
|
||||
Margin="5,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Command="{ReflectionBinding LoadDevices}">
|
||||
<ui:SymbolIcon
|
||||
Symbol="Refresh"
|
||||
FontSize="15"
|
||||
Height="20"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
<!-- Controller Type -->
|
||||
<Grid
|
||||
Grid.Column="2"
|
||||
Margin="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="5,0,10,0"
|
||||
Width="90"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsControllerType}" />
|
||||
<ComboBox
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding Controllers}"
|
||||
SelectedIndex="{Binding Controller}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate DataType="models:ControllerModel">
|
||||
<TextBlock Text="{Binding Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
<!-- Button / JoyStick Settings -->
|
||||
<Grid
|
||||
Name="SettingButtons"
|
||||
MinHeight="450"
|
||||
IsVisible="{Binding ShowSettings}">
|
||||
MinHeight="450">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
@@ -256,9 +75,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsTriggerZL}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="ButtonZl">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.ButtonZl, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.ButtonZl, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -272,9 +91,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsTriggerL}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="ButtonL">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.ButtonL, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.ButtonL, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -288,9 +107,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsButtonMinus}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="ButtonMinus">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.ButtonMinus, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.ButtonMinus, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -310,100 +129,8 @@
|
||||
Margin="0,0,0,10"
|
||||
HorizontalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsLStick}" />
|
||||
<!-- Left Joystick Keyboard -->
|
||||
<StackPanel
|
||||
IsVisible="{Binding !IsController}"
|
||||
Orientation="Vertical">
|
||||
<!-- Left Joystick Button -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickButton}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.LeftKeyboardStickButton, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Left Joystick Up -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickUp}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.LeftStickUp, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Left Joystick Down -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickDown}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.LeftStickDown, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Left Joystick Left -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickLeft}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.LeftStickLeft, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Left Joystick Right -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickRight}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.LeftStickRight, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<!-- Left Joystick Controller -->
|
||||
<StackPanel
|
||||
IsVisible="{Binding IsController}"
|
||||
Orientation="Vertical">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<!-- Left Joystick Button -->
|
||||
<StackPanel
|
||||
Orientation="Horizontal">
|
||||
@@ -414,9 +141,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickButton}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="LeftStickButton">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.LeftControllerStickButton, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.LeftStickButton, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -431,22 +158,22 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickStick}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Tag="stick">
|
||||
<ToggleButton Name="LeftJoystick" Tag="stick">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.LeftJoystick, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.LeftJoystick, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<Separator
|
||||
Margin="0,8,0,8"
|
||||
Height="1" />
|
||||
<CheckBox IsChecked="{ReflectionBinding Configuration.LeftInvertStickX}">
|
||||
<CheckBox IsChecked="{Binding Config.LeftInvertStickX}">
|
||||
<TextBlock Text="{locale:Locale ControllerSettingsStickInvertXAxis}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{ReflectionBinding Configuration.LeftInvertStickY}">
|
||||
<CheckBox IsChecked="{Binding Config.LeftInvertStickY}">
|
||||
<TextBlock Text="{locale:Locale ControllerSettingsStickInvertYAxis}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{ReflectionBinding Configuration.LeftRotate90}">
|
||||
<CheckBox IsChecked="{Binding Config.LeftRotate90}">
|
||||
<TextBlock Text="{locale:Locale ControllerSettingsRotate90}" />
|
||||
</CheckBox>
|
||||
<Separator
|
||||
@@ -460,18 +187,18 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<Slider
|
||||
<controls:SliderScroll
|
||||
Width="130"
|
||||
Maximum="1"
|
||||
TickFrequency="0.01"
|
||||
IsSnapToTickEnabled="True"
|
||||
SmallChange="0.01"
|
||||
Minimum="0"
|
||||
Value="{ReflectionBinding Configuration.DeadzoneLeft, Mode=TwoWay}" />
|
||||
Value="{Binding Config.DeadzoneLeft, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Width="25"
|
||||
Text="{ReflectionBinding Configuration.DeadzoneLeft, StringFormat=\{0:0.00\}}" />
|
||||
Text="{Binding Config.DeadzoneLeft, StringFormat=\{0:0.00\}}" />
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
@@ -480,18 +207,18 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<Slider
|
||||
<controls:SliderScroll
|
||||
Width="130"
|
||||
Maximum="2"
|
||||
TickFrequency="0.01"
|
||||
IsSnapToTickEnabled="True"
|
||||
SmallChange="0.01"
|
||||
Minimum="0"
|
||||
Value="{ReflectionBinding Configuration.RangeLeft, Mode=TwoWay}" />
|
||||
Value="{Binding Config.RangeLeft, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Width="25"
|
||||
Text="{ReflectionBinding Configuration.RangeLeft, StringFormat=\{0:0.00\}}" />
|
||||
Text="{Binding Config.RangeLeft, StringFormat=\{0:0.00\}}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
@@ -524,9 +251,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsDPadUp}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="DpadUp">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.DpadUp, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.DpadUp, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -541,9 +268,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsDPadDown}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="DpadDown">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.DpadDown, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.DpadDown, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -558,9 +285,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsDPadLeft}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="DpadLeft">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.DpadLeft, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.DpadLeft, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -575,9 +302,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsDPadRight}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="DpadRight">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.DpadRight, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.DpadRight, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -590,6 +317,13 @@
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<!-- Controller Picture -->
|
||||
<Image
|
||||
Margin="0,10"
|
||||
MaxHeight="300"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Source="{Binding Image}" />
|
||||
<Border
|
||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||
BorderThickness="1"
|
||||
@@ -604,23 +338,26 @@
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<Slider
|
||||
<controls:SliderScroll
|
||||
Width="130"
|
||||
Maximum="1"
|
||||
TickFrequency="0.01"
|
||||
IsSnapToTickEnabled="True"
|
||||
SmallChange="0.01"
|
||||
Minimum="0"
|
||||
Value="{ReflectionBinding Configuration.TriggerThreshold, Mode=TwoWay}" />
|
||||
Value="{Binding Config.TriggerThreshold, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Width="25"
|
||||
Text="{ReflectionBinding Configuration.TriggerThreshold, StringFormat=\{0:0.00\}}" />
|
||||
Text="{Binding Config.TriggerThreshold, StringFormat=\{0:0.00\}}" />
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Orientation="Vertical"
|
||||
IsVisible="{Binding HasSides}">
|
||||
<StackPanel
|
||||
Margin="0,4,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding !IsRight}"
|
||||
IsVisible="{Binding IsLeft}"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
@@ -628,9 +365,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsLeftSR}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="LeftButtonSr">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.LeftButtonSr, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.LeftButtonSr, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -638,7 +375,7 @@
|
||||
Margin="0,4,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding !IsRight}"
|
||||
IsVisible="{Binding IsLeft}"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
@@ -646,9 +383,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsLeftSL}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="LeftButtonSl">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.LeftButtonSl, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.LeftButtonSl, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -656,7 +393,7 @@
|
||||
Margin="0,4,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding !IsLeft}"
|
||||
IsVisible="{Binding IsRight}"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
@@ -664,9 +401,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsRightSR}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="RightButtonSr">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.RightButtonSr, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.RightButtonSr, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -674,7 +411,7 @@
|
||||
Margin="0,4,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding !IsLeft}"
|
||||
IsVisible="{Binding IsRight}"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
@@ -682,21 +419,15 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsRightSL}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="RightButtonSl">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.RightButtonSl, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.RightButtonSl, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<!-- Controller Picture -->
|
||||
<Image
|
||||
Margin="0,10,0,0"
|
||||
MaxHeight="300"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Source="{Binding Image}" />
|
||||
<!-- Motion + Rumble -->
|
||||
<StackPanel
|
||||
Margin="0,10,0,0"
|
||||
@@ -708,8 +439,7 @@
|
||||
BorderThickness="1"
|
||||
CornerRadius="5"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Stretch"
|
||||
IsVisible="{Binding IsController}">
|
||||
HorizontalAlignment="Stretch">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
@@ -719,7 +449,7 @@
|
||||
Margin="10"
|
||||
MinWidth="0"
|
||||
Grid.Column="0"
|
||||
IsChecked="{ReflectionBinding Configuration.EnableMotion, Mode=TwoWay}">
|
||||
IsChecked="{Binding Config.EnableMotion, Mode=TwoWay}">
|
||||
<TextBlock Text="{locale:Locale ControllerSettingsMotion}" />
|
||||
</CheckBox>
|
||||
<Button
|
||||
@@ -735,7 +465,6 @@
|
||||
BorderThickness="1"
|
||||
CornerRadius="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
IsVisible="{Binding IsController}"
|
||||
Margin="0,-1,0,0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -746,7 +475,7 @@
|
||||
Margin="10"
|
||||
MinWidth="0"
|
||||
Grid.Column="0"
|
||||
IsChecked="{ReflectionBinding Configuration.EnableRumble, Mode=TwoWay}">
|
||||
IsChecked="{Binding Config.EnableRumble, Mode=TwoWay}">
|
||||
<TextBlock Text="{locale:Locale ControllerSettingsRumble}" />
|
||||
</CheckBox>
|
||||
<Button
|
||||
@@ -792,9 +521,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsTriggerZR}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="ButtonZr">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.ButtonZr, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.ButtonZr, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -810,9 +539,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsTriggerR}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="ButtonR">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.ButtonR, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.ButtonR, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -828,15 +557,15 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsButtonPlus}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="ButtonPlus">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.ButtonPlus, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.ButtonPlus, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
<!-- Right Joystick -->
|
||||
<!-- Right Buttons -->
|
||||
<Border
|
||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||
BorderThickness="1"
|
||||
@@ -863,9 +592,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsButtonA}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="ButtonA">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.ButtonA, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.ButtonA, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -880,9 +609,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsButtonB}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="ButtonB">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.ButtonB, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.ButtonB, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -897,9 +626,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsButtonX}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="ButtonX">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.ButtonX, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.ButtonX, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -914,9 +643,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsButtonY}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="ButtonY">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.ButtonY, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.ButtonY, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -936,100 +665,8 @@
|
||||
Margin="0,0,0,10"
|
||||
HorizontalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsRStick}" />
|
||||
<!-- Right Joystick Keyboard -->
|
||||
<StackPanel
|
||||
IsVisible="{Binding !IsController}"
|
||||
Orientation="Vertical">
|
||||
<!-- Right Joystick Button -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickButton}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.RightKeyboardStickButton, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Right Joystick Up -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickUp}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.RightStickUp, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Right Joystick Down -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickDown}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.RightStickDown, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Right Joystick Left -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickLeft}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.RightStickLeft, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Right Joystick Right -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickRight}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.RightStickRight, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<!-- Right Joystick Controller -->
|
||||
<StackPanel
|
||||
IsVisible="{Binding IsController}"
|
||||
Orientation="Vertical">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<!-- Right Joystick Button -->
|
||||
<StackPanel
|
||||
Orientation="Horizontal">
|
||||
@@ -1040,9 +677,9 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickButton}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton>
|
||||
<ToggleButton Name="RightStickButton">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.RightControllerStickButton, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.RightStickButton, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
@@ -1058,20 +695,20 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickStick}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Tag="stick">
|
||||
<ToggleButton Name="RightJoystick" Tag="stick">
|
||||
<TextBlock
|
||||
Text="{ReflectionBinding Configuration.RightJoystick, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding Config.RightJoystick, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<Separator Margin="0,8,0,8" Height="1" />
|
||||
<CheckBox IsChecked="{ReflectionBinding Configuration.RightInvertStickX}">
|
||||
<CheckBox IsChecked="{Binding Config.RightInvertStickX}">
|
||||
<TextBlock Text="{locale:Locale ControllerSettingsStickInvertXAxis}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{ReflectionBinding Configuration.RightInvertStickY}">
|
||||
<CheckBox IsChecked="{Binding Config.RightInvertStickY}">
|
||||
<TextBlock Text="{locale:Locale ControllerSettingsStickInvertYAxis}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{ReflectionBinding Configuration.RightRotate90}">
|
||||
<CheckBox IsChecked="{Binding Config.RightRotate90}">
|
||||
<TextBlock Text="{locale:Locale ControllerSettingsRotate90}" />
|
||||
</CheckBox>
|
||||
<Separator Margin="0,8,0,8" Height="1" />
|
||||
@@ -1083,7 +720,7 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<Slider
|
||||
<controls:SliderScroll
|
||||
Width="130"
|
||||
Maximum="1"
|
||||
TickFrequency="0.01"
|
||||
@@ -1092,11 +729,11 @@
|
||||
Padding="0"
|
||||
VerticalAlignment="Center"
|
||||
Minimum="0"
|
||||
Value="{ReflectionBinding Configuration.DeadzoneRight, Mode=TwoWay}" />
|
||||
Value="{Binding Config.DeadzoneRight, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Width="25"
|
||||
Text="{ReflectionBinding Configuration.DeadzoneRight, StringFormat=\{0:0.00\}}" />
|
||||
Text="{Binding Config.DeadzoneRight, StringFormat=\{0:0.00\}}" />
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
@@ -1105,18 +742,18 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<Slider
|
||||
<controls:SliderScroll
|
||||
Width="130"
|
||||
Maximum="2"
|
||||
TickFrequency="0.01"
|
||||
IsSnapToTickEnabled="True"
|
||||
SmallChange="0.01"
|
||||
Minimum="0"
|
||||
Value="{ReflectionBinding Configuration.RangeRight, Mode=TwoWay}" />
|
||||
Value="{Binding Config.RangeRight, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Width="25"
|
||||
Text="{ReflectionBinding Configuration.RangeRight, StringFormat=\{0:0.00\}}" />
|
||||
Text="{Binding Config.RangeRight, StringFormat=\{0:0.00\}}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
@@ -1,35 +1,28 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.LogicalTree;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Input;
|
||||
using Ryujinx.Input.Assigner;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Views.Input
|
||||
{
|
||||
public partial class ControllerInputView : UserControl
|
||||
{
|
||||
private bool _dialogOpen;
|
||||
|
||||
private ButtonKeyAssigner _currentAssigner;
|
||||
internal ControllerInputViewModel ViewModel { get; set; }
|
||||
|
||||
public ControllerInputView()
|
||||
{
|
||||
DataContext = ViewModel = new ControllerInputViewModel(this);
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
foreach (ILogical visual in SettingButtons.GetLogicalDescendants())
|
||||
{
|
||||
if (visual is ToggleButton button && visual is not CheckBox)
|
||||
if (visual is ToggleButton button and not CheckBox)
|
||||
{
|
||||
button.IsCheckedChanged += Button_IsCheckedChanged;
|
||||
}
|
||||
@@ -59,7 +52,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||
|
||||
bool isStick = button.Tag != null && button.Tag.ToString() == "stick";
|
||||
|
||||
if (_currentAssigner == null)
|
||||
if (_currentAssigner == null && (bool)button.IsChecked)
|
||||
{
|
||||
_currentAssigner = new ButtonKeyAssigner(button);
|
||||
|
||||
@@ -67,14 +60,86 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||
|
||||
PointerPressed += MouseClick;
|
||||
|
||||
IKeyboard keyboard = (IKeyboard)ViewModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
|
||||
IKeyboard keyboard = (IKeyboard)(DataContext as ControllerInputViewModel).parentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
|
||||
IButtonAssigner assigner = CreateButtonAssigner(isStick);
|
||||
|
||||
_currentAssigner.ButtonAssigned += (sender, e) =>
|
||||
{
|
||||
if (e.IsAssigned)
|
||||
if (e.ButtonValue.HasValue)
|
||||
{
|
||||
ViewModel.IsModified = true;
|
||||
var viewModel = (DataContext as ControllerInputViewModel);
|
||||
var buttonValue = e.ButtonValue.Value;
|
||||
viewModel.parentModel.IsModified = true;
|
||||
|
||||
switch (button.Name)
|
||||
{
|
||||
case "ButtonZl":
|
||||
viewModel.Config.ButtonZl = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "ButtonL":
|
||||
viewModel.Config.ButtonL = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "ButtonMinus":
|
||||
viewModel.Config.ButtonMinus = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "LeftStickButton":
|
||||
viewModel.Config.LeftStickButton = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "LeftJoystick":
|
||||
viewModel.Config.LeftJoystick = buttonValue.AsGamepadStickId();
|
||||
break;
|
||||
case "DpadUp":
|
||||
viewModel.Config.DpadUp = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "DpadDown":
|
||||
viewModel.Config.DpadDown = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "DpadLeft":
|
||||
viewModel.Config.DpadLeft = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "DpadRight":
|
||||
viewModel.Config.DpadRight = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "LeftButtonSr":
|
||||
viewModel.Config.LeftButtonSr = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "LeftButtonSl":
|
||||
viewModel.Config.LeftButtonSl = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "RightButtonSr":
|
||||
viewModel.Config.RightButtonSr = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "RightButtonSl":
|
||||
viewModel.Config.RightButtonSl = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "ButtonZr":
|
||||
viewModel.Config.ButtonZr = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "ButtonR":
|
||||
viewModel.Config.ButtonR = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "ButtonPlus":
|
||||
viewModel.Config.ButtonPlus = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "ButtonA":
|
||||
viewModel.Config.ButtonA = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "ButtonB":
|
||||
viewModel.Config.ButtonB = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "ButtonX":
|
||||
viewModel.Config.ButtonX = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "ButtonY":
|
||||
viewModel.Config.ButtonY = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "RightStickButton":
|
||||
viewModel.Config.RightStickButton = buttonValue.AsGamepadButtonInputId();
|
||||
break;
|
||||
case "RightJoystick":
|
||||
viewModel.Config.RightJoystick = buttonValue.AsGamepadStickId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -100,82 +165,29 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveCurrentProfile()
|
||||
{
|
||||
ViewModel.Save();
|
||||
}
|
||||
|
||||
private IButtonAssigner CreateButtonAssigner(bool forStick)
|
||||
{
|
||||
IButtonAssigner assigner;
|
||||
|
||||
var device = ViewModel.Devices[ViewModel.Device];
|
||||
|
||||
if (device.Type == DeviceType.Keyboard)
|
||||
{
|
||||
assigner = new KeyboardKeyAssigner((IKeyboard)ViewModel.SelectedGamepad);
|
||||
}
|
||||
else if (device.Type == DeviceType.Controller)
|
||||
{
|
||||
assigner = new GamepadButtonAssigner(ViewModel.SelectedGamepad, (ViewModel.Config as StandardControllerInputConfig).TriggerThreshold, forStick);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Controller not supported");
|
||||
}
|
||||
|
||||
return assigner;
|
||||
}
|
||||
|
||||
private void MouseClick(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
bool shouldUnbind = false;
|
||||
|
||||
if (e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed)
|
||||
{
|
||||
shouldUnbind = true;
|
||||
}
|
||||
bool shouldUnbind = e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed;
|
||||
|
||||
_currentAssigner?.Cancel(shouldUnbind);
|
||||
|
||||
PointerPressed -= MouseClick;
|
||||
}
|
||||
|
||||
private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
private IButtonAssigner CreateButtonAssigner(bool forStick)
|
||||
{
|
||||
if (ViewModel.IsModified && !_dialogOpen)
|
||||
{
|
||||
_dialogOpen = true;
|
||||
IButtonAssigner assigner;
|
||||
|
||||
var result = await ContentDialogHelper.CreateConfirmationDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmMessage],
|
||||
LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmSubMessage],
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogYes],
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogNo],
|
||||
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
|
||||
assigner = new GamepadButtonAssigner((DataContext as ControllerInputViewModel).parentModel.SelectedGamepad, ((DataContext as ControllerInputViewModel).parentModel.Config as StandardControllerInputConfig).TriggerThreshold, forStick);
|
||||
|
||||
if (result == UserResult.Yes)
|
||||
{
|
||||
ViewModel.Save();
|
||||
return assigner;
|
||||
}
|
||||
|
||||
_dialogOpen = false;
|
||||
|
||||
ViewModel.IsModified = false;
|
||||
|
||||
if (e.AddedItems.Count > 0)
|
||||
{
|
||||
var player = (PlayerModel)e.AddedItems[0];
|
||||
ViewModel.PlayerId = player.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
_currentAssigner?.Cancel();
|
||||
_currentAssigner = null;
|
||||
ViewModel.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
225
src/Ryujinx.Ava/UI/Views/Input/InputView.axaml
Normal file
225
src/Ryujinx.Ava/UI/Views/Input/InputView.axaml
Normal file
@@ -0,0 +1,225 @@
|
||||
<UserControl
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
|
||||
xmlns:views="clr-namespace:Ryujinx.Ava.UI.Views.Input"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
d:DesignHeight="800"
|
||||
d:DesignWidth="800"
|
||||
x:Class="Ryujinx.Ava.UI.Views.Input.InputView"
|
||||
x:DataType="viewModels:InputViewModel"
|
||||
x:CompileBindings="True"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
<Design.DataContext>
|
||||
<viewModels:InputViewModel />
|
||||
</Design.DataContext>
|
||||
<UserControl.Styles>
|
||||
<Style Selector="ToggleButton">
|
||||
<Setter Property="Width" Value="90" />
|
||||
<Setter Property="Height" Value="27" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
<StackPanel
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Orientation="Vertical">
|
||||
<StackPanel
|
||||
Margin="0 0 0 5"
|
||||
Orientation="Vertical"
|
||||
Spacing="5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="10" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<!-- Player Selection -->
|
||||
<Grid
|
||||
Grid.Column="0"
|
||||
Margin="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="5,0,10,0"
|
||||
Width="90"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsPlayer}" />
|
||||
<ComboBox
|
||||
Grid.Column="1"
|
||||
Name="PlayerIndexBox"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
SelectionChanged="PlayerIndexBox_OnSelectionChanged"
|
||||
ItemsSource="{Binding PlayerIndexes}"
|
||||
SelectedIndex="{Binding PlayerId}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
<!-- Profile Selection -->
|
||||
<Grid
|
||||
Grid.Column="2"
|
||||
Margin="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="5,0,10,0"
|
||||
Width="90"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsProfile}" />
|
||||
<ui:FAComboBox
|
||||
Grid.Column="1"
|
||||
IsEditable="True"
|
||||
Name="ProfileBox"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
SelectedIndex="0"
|
||||
ItemsSource="{Binding ProfilesList}"
|
||||
Text="{Binding ProfileName, Mode=TwoWay}" />
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
MinWidth="0"
|
||||
Margin="5,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="{locale:Locale ControllerSettingsLoadProfileToolTip}"
|
||||
Command="{Binding LoadProfile}">
|
||||
<ui:SymbolIcon
|
||||
Symbol="Upload"
|
||||
FontSize="15"
|
||||
Height="20" />
|
||||
</Button>
|
||||
<Button
|
||||
Grid.Column="3"
|
||||
MinWidth="0"
|
||||
Margin="5,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="{locale:Locale ControllerSettingsSaveProfileToolTip}"
|
||||
Command="{Binding SaveProfile}">
|
||||
<ui:SymbolIcon
|
||||
Symbol="Save"
|
||||
FontSize="15"
|
||||
Height="20" />
|
||||
</Button>
|
||||
<Button
|
||||
Grid.Column="4"
|
||||
MinWidth="0"
|
||||
Margin="5,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="{locale:Locale ControllerSettingsRemoveProfileToolTip}"
|
||||
Command="{Binding RemoveProfile}">
|
||||
<ui:SymbolIcon
|
||||
Symbol="Delete"
|
||||
FontSize="15"
|
||||
Height="20" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Separator />
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="10" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<!-- Input Device -->
|
||||
<Grid
|
||||
Grid.Column="0"
|
||||
Margin="2"
|
||||
HorizontalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Margin="5,0,10,0"
|
||||
Width="90"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsInputDevice}" />
|
||||
<ComboBox
|
||||
Grid.Column="1"
|
||||
Name="DeviceBox"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
ItemsSource="{Binding DeviceList}"
|
||||
SelectedIndex="{Binding Device}" />
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
MinWidth="0"
|
||||
Margin="5,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding LoadDevices}">
|
||||
<ui:SymbolIcon
|
||||
Symbol="Refresh"
|
||||
FontSize="15"
|
||||
Height="20"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
<!-- Controller Type -->
|
||||
<Grid
|
||||
Grid.Column="2"
|
||||
Margin="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="5,0,10,0"
|
||||
Width="90"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsControllerType}" />
|
||||
<ComboBox
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding Controllers}"
|
||||
SelectedIndex="{Binding Controller}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate DataType="models:ControllerModel">
|
||||
<TextBlock Text="{Binding Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
<ContentControl Content="{Binding ConfigViewModel}" IsVisible="{Binding ShowSettings}">
|
||||
<ContentControl.DataTemplates>
|
||||
<DataTemplate DataType="viewModels:ControllerInputViewModel">
|
||||
<views:ControllerInputView />
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="viewModels:KeyboardInputViewModel">
|
||||
<views:KeyboardInputView />
|
||||
</DataTemplate>
|
||||
</ContentControl.DataTemplates>
|
||||
</ContentControl>
|
||||
</StackPanel>
|
||||
</UserControl>
|
61
src/Ryujinx.Ava/UI/Views/Input/InputView.axaml.cs
Normal file
61
src/Ryujinx.Ava/UI/Views/Input/InputView.axaml.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using Avalonia.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Views.Input
|
||||
{
|
||||
public partial class InputView : UserControl
|
||||
{
|
||||
private bool _dialogOpen;
|
||||
private InputViewModel ViewModel { get; set; }
|
||||
|
||||
public InputView()
|
||||
{
|
||||
DataContext = ViewModel = new InputViewModel(this);
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void SaveCurrentProfile()
|
||||
{
|
||||
ViewModel.Save();
|
||||
}
|
||||
|
||||
private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (ViewModel.IsModified && !_dialogOpen)
|
||||
{
|
||||
_dialogOpen = true;
|
||||
|
||||
var result = await ContentDialogHelper.CreateConfirmationDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmMessage],
|
||||
LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmSubMessage],
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogYes],
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogNo],
|
||||
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
|
||||
|
||||
if (result == UserResult.Yes)
|
||||
{
|
||||
ViewModel.Save();
|
||||
}
|
||||
|
||||
_dialogOpen = false;
|
||||
|
||||
ViewModel.IsModified = false;
|
||||
|
||||
if (e.AddedItems.Count > 0)
|
||||
{
|
||||
var player = (PlayerModel)e.AddedItems[0];
|
||||
ViewModel.PlayerId = player.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ViewModel.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
675
src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml
Normal file
675
src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml
Normal file
@@ -0,0 +1,675 @@
|
||||
<UserControl
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
|
||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
d:DesignHeight="800"
|
||||
d:DesignWidth="800"
|
||||
x:Class="Ryujinx.Ava.UI.Views.Input.KeyboardInputView"
|
||||
x:DataType="viewModels:KeyboardInputViewModel"
|
||||
x:CompileBindings="True"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
<Design.DataContext>
|
||||
<viewModels:KeyboardInputViewModel />
|
||||
</Design.DataContext>
|
||||
<UserControl.Resources>
|
||||
<helpers:KeyValueConverter x:Key="Key" />
|
||||
</UserControl.Resources>
|
||||
<UserControl.Styles>
|
||||
<Style Selector="ToggleButton">
|
||||
<Setter Property="Width" Value="90" />
|
||||
<Setter Property="Height" Value="27" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
<StackPanel
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Orientation="Vertical">
|
||||
<!-- Button / JoyStick Settings -->
|
||||
<Grid
|
||||
Name="SettingButtons"
|
||||
MinHeight="450">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<!-- Left Controls -->
|
||||
<StackPanel
|
||||
Orientation="Vertical"
|
||||
Margin="0,0,5,0"
|
||||
Grid.Column="0">
|
||||
<!-- Left Triggers -->
|
||||
<Border
|
||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||
BorderThickness="1"
|
||||
IsVisible="{Binding IsLeft}"
|
||||
MinHeight="90"
|
||||
CornerRadius="5">
|
||||
<Grid
|
||||
Margin="10"
|
||||
HorizontalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel
|
||||
Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsTriggerZL}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="ButtonZl">
|
||||
<TextBlock
|
||||
Text="{Binding Config.ButtonZl, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="0"
|
||||
Grid.Row="1"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsTriggerL}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="ButtonL">
|
||||
<TextBlock
|
||||
Text="{Binding Config.ButtonL, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
Grid.Row="1"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsButtonMinus}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="ButtonMinus">
|
||||
<TextBlock
|
||||
Text="{Binding Config.ButtonMinus, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
<!-- Left Joystick -->
|
||||
<Border
|
||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||
BorderThickness="1"
|
||||
IsVisible="{Binding IsLeft}"
|
||||
Margin="0,5,0,0"
|
||||
CornerRadius="5">
|
||||
<StackPanel
|
||||
Margin="10"
|
||||
Orientation="Vertical">
|
||||
<TextBlock
|
||||
Margin="0,0,0,10"
|
||||
HorizontalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsLStick}" />
|
||||
<!-- Left Joystick Keyboard -->
|
||||
<StackPanel Orientation="Vertical">
|
||||
<!-- Left Joystick Button -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickButton}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="LeftStickButton">
|
||||
<TextBlock
|
||||
Text="{Binding Config.LeftStickButton, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Left Joystick Up -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickUp}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="LeftStickUp">
|
||||
<TextBlock
|
||||
Text="{Binding Config.LeftStickUp, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Left Joystick Down -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickDown}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="LeftStickDown">
|
||||
<TextBlock
|
||||
Text="{Binding Config.LeftStickDown, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Left Joystick Left -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickLeft}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="LeftStickLeft">
|
||||
<TextBlock
|
||||
Text="{Binding Config.LeftStickLeft, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Left Joystick Right -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickRight}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="LeftStickRight">
|
||||
<TextBlock
|
||||
Text="{Binding Config.LeftStickRight, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<!-- Left DPad -->
|
||||
<Border
|
||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||
BorderThickness="1"
|
||||
VerticalAlignment="Top"
|
||||
IsVisible="{Binding IsLeft}"
|
||||
Margin="0,5,0,0"
|
||||
CornerRadius="5">
|
||||
<StackPanel
|
||||
Margin="10"
|
||||
Orientation="Vertical">
|
||||
<TextBlock
|
||||
Margin="0,0,0,10"
|
||||
HorizontalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsDPad}" />
|
||||
<StackPanel Orientation="Vertical">
|
||||
<!-- Left DPad Up -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsDPadUp}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="DpadUp">
|
||||
<TextBlock
|
||||
Text="{Binding Config.DpadUp, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Left DPad Down -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsDPadDown}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="DpadDown">
|
||||
<TextBlock
|
||||
Text="{Binding Config.DpadDown, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Left DPad Left -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsDPadLeft}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="DpadLeft">
|
||||
<TextBlock
|
||||
Text="{Binding Config.DpadLeft, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Left DPad Right -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsDPadRight}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="DpadRight">
|
||||
<TextBlock
|
||||
Text="{Binding Config.DpadRight, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
<!-- Triggers & Side Buttons -->
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<!-- Controller Picture -->
|
||||
<Image
|
||||
Margin="0,10"
|
||||
MaxHeight="300"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Source="{Binding Image}" />
|
||||
<Border
|
||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="5"
|
||||
MinHeight="90"
|
||||
IsVisible="{Binding HasSides}">
|
||||
<StackPanel
|
||||
Margin="8"
|
||||
Orientation="Vertical">
|
||||
<StackPanel
|
||||
Margin="0,4,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding IsLeft}"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsLeftSR}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="LeftButtonSr">
|
||||
<TextBlock
|
||||
Text="{Binding Config.LeftButtonSr, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Margin="0,4,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding IsLeft}"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsLeftSL}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="LeftButtonSl">
|
||||
<TextBlock
|
||||
Text="{Binding Config.LeftButtonSl, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Margin="0,4,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding IsRight}"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsRightSR}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="RightButtonSr">
|
||||
<TextBlock
|
||||
Text="{Binding Config.RightButtonSr, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Margin="0,4,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding IsRight}"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsRightSL}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="RightButtonSl">
|
||||
<TextBlock
|
||||
Text="{Binding Config.RightButtonSl, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
<!-- Right Controls -->
|
||||
<StackPanel
|
||||
Orientation="Vertical"
|
||||
Margin="5,0,0,0"
|
||||
Grid.Column="2">
|
||||
<!-- Right Triggers -->
|
||||
<Border
|
||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||
BorderThickness="1"
|
||||
IsVisible="{Binding IsRight}"
|
||||
MinHeight="90"
|
||||
CornerRadius="5">
|
||||
<Grid
|
||||
Margin="10"
|
||||
HorizontalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
Grid.Row="0"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsTriggerZR}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="ButtonZr">
|
||||
<TextBlock
|
||||
Text="{Binding Config.ButtonZr, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsTriggerR}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="ButtonR">
|
||||
<TextBlock
|
||||
Text="{Binding Config.ButtonR, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="0"
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsButtonPlus}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="ButtonPlus">
|
||||
<TextBlock
|
||||
Text="{Binding Config.ButtonPlus, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
<!-- Right Buttons -->
|
||||
<Border
|
||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||
BorderThickness="1"
|
||||
IsVisible="{Binding IsRight}"
|
||||
Margin="0,5,0,0"
|
||||
CornerRadius="5">
|
||||
<StackPanel
|
||||
Margin="10"
|
||||
Orientation="Vertical">
|
||||
<TextBlock
|
||||
Margin="0,0,0,10"
|
||||
HorizontalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsButtons}" />
|
||||
<StackPanel
|
||||
Orientation="Vertical">
|
||||
<!-- Right Buttons A -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="120"
|
||||
Margin="0,0,10,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsButtonA}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="ButtonA">
|
||||
<TextBlock
|
||||
Text="{Binding Config.ButtonA, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Right Buttons B -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="120"
|
||||
Margin="0,0,10,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsButtonB}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="ButtonB">
|
||||
<TextBlock
|
||||
Text="{Binding Config.ButtonB, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Right Buttons X -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="120"
|
||||
Margin="0,0,10,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsButtonX}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="ButtonX">
|
||||
<TextBlock
|
||||
Text="{Binding Config.ButtonX, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Right Buttons Y -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="120"
|
||||
Margin="0,0,10,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsButtonY}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="ButtonY">
|
||||
<TextBlock
|
||||
Text="{Binding Config.ButtonY, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<!-- Right DPad -->
|
||||
<Border
|
||||
Padding="10"
|
||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="5"
|
||||
IsVisible="{Binding IsRight}"
|
||||
Margin="0,5,0,0">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock
|
||||
Margin="0,0,0,10"
|
||||
HorizontalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsRStick}" />
|
||||
<!-- Right Joystick Keyboard -->
|
||||
<StackPanel Orientation="Vertical">
|
||||
<!-- Right Joystick Button -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickButton}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="RightStickButton">
|
||||
<TextBlock
|
||||
Text="{Binding Config.RightStickButton, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Right Joystick Up -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickUp}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="RightStickUp">
|
||||
<TextBlock
|
||||
Text="{Binding Config.RightStickUp, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Right Joystick Down -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickDown}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="RightStickDown">
|
||||
<TextBlock
|
||||
Text="{Binding Config.RightStickDown, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Right Joystick Left -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickLeft}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="RightStickLeft">
|
||||
<TextBlock
|
||||
Text="{Binding Config.RightStickLeft, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<!-- Right Joystick Right -->
|
||||
<StackPanel
|
||||
Margin="0,0,0,4"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Width="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsStickRight}"
|
||||
TextAlignment="Center" />
|
||||
<ToggleButton Name="RightStickRight">
|
||||
<TextBlock
|
||||
Text="{Binding Config.RightStickRight, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
210
src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml.cs
Normal file
210
src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml.cs
Normal file
@@ -0,0 +1,210 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.LogicalTree;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using Ryujinx.Input;
|
||||
using Ryujinx.Input.Assigner;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Views.Input
|
||||
{
|
||||
public partial class KeyboardInputView : UserControl
|
||||
{
|
||||
private ButtonKeyAssigner _currentAssigner;
|
||||
|
||||
public KeyboardInputView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
foreach (ILogical visual in SettingButtons.GetLogicalDescendants())
|
||||
{
|
||||
if (visual is ToggleButton button and not CheckBox)
|
||||
{
|
||||
button.IsCheckedChanged += Button_IsCheckedChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||
{
|
||||
base.OnPointerReleased(e);
|
||||
|
||||
if (_currentAssigner != null && _currentAssigner.ToggledButton != null && !_currentAssigner.ToggledButton.IsPointerOver)
|
||||
{
|
||||
_currentAssigner.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void Button_IsCheckedChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is ToggleButton button)
|
||||
{
|
||||
if ((bool)button.IsChecked)
|
||||
{
|
||||
if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool isStick = button.Tag != null && button.Tag.ToString() == "stick";
|
||||
|
||||
if (_currentAssigner == null && (bool)button.IsChecked)
|
||||
{
|
||||
_currentAssigner = new ButtonKeyAssigner(button);
|
||||
|
||||
this.Focus(NavigationMethod.Pointer);
|
||||
|
||||
PointerPressed += MouseClick;
|
||||
|
||||
IKeyboard keyboard = (IKeyboard)(DataContext as KeyboardInputViewModel).parentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
|
||||
IButtonAssigner assigner = CreateButtonAssigner(isStick);
|
||||
|
||||
_currentAssigner.ButtonAssigned += (sender, e) =>
|
||||
{
|
||||
if (e.ButtonValue.HasValue)
|
||||
{
|
||||
var viewModel = (DataContext as KeyboardInputViewModel);
|
||||
var buttonValue = e.ButtonValue.Value;
|
||||
viewModel.parentModel.IsModified = true;
|
||||
|
||||
switch (button.Name)
|
||||
{
|
||||
case "ButtonZl":
|
||||
viewModel.Config.ButtonZl = buttonValue.AsKey();
|
||||
break;
|
||||
case "ButtonL":
|
||||
viewModel.Config.ButtonL = buttonValue.AsKey();
|
||||
break;
|
||||
case "ButtonMinus":
|
||||
viewModel.Config.ButtonMinus = buttonValue.AsKey();
|
||||
break;
|
||||
case "LeftStickButton":
|
||||
viewModel.Config.LeftStickButton = buttonValue.AsKey();
|
||||
break;
|
||||
case "LeftStickUp":
|
||||
viewModel.Config.LeftStickUp = buttonValue.AsKey();
|
||||
break;
|
||||
case "LeftStickDown":
|
||||
viewModel.Config.LeftStickDown = buttonValue.AsKey();
|
||||
break;
|
||||
case "LeftStickRight":
|
||||
viewModel.Config.LeftStickRight = buttonValue.AsKey();
|
||||
break;
|
||||
case "LeftStickLeft":
|
||||
viewModel.Config.LeftStickLeft = buttonValue.AsKey();
|
||||
break;
|
||||
case "DpadUp":
|
||||
viewModel.Config.DpadUp = buttonValue.AsKey();
|
||||
break;
|
||||
case "DpadDown":
|
||||
viewModel.Config.DpadDown = buttonValue.AsKey();
|
||||
break;
|
||||
case "DpadLeft":
|
||||
viewModel.Config.DpadLeft = buttonValue.AsKey();
|
||||
break;
|
||||
case "DpadRight":
|
||||
viewModel.Config.DpadRight = buttonValue.AsKey();
|
||||
break;
|
||||
case "LeftButtonSr":
|
||||
viewModel.Config.LeftButtonSr = buttonValue.AsKey();
|
||||
break;
|
||||
case "LeftButtonSl":
|
||||
viewModel.Config.LeftButtonSl = buttonValue.AsKey();
|
||||
break;
|
||||
case "RightButtonSr":
|
||||
viewModel.Config.RightButtonSr = buttonValue.AsKey();
|
||||
break;
|
||||
case "RightButtonSl":
|
||||
viewModel.Config.RightButtonSl = buttonValue.AsKey();
|
||||
break;
|
||||
case "ButtonZr":
|
||||
viewModel.Config.ButtonZr = buttonValue.AsKey();
|
||||
break;
|
||||
case "ButtonR":
|
||||
viewModel.Config.ButtonR = buttonValue.AsKey();
|
||||
break;
|
||||
case "ButtonPlus":
|
||||
viewModel.Config.ButtonPlus = buttonValue.AsKey();
|
||||
break;
|
||||
case "ButtonA":
|
||||
viewModel.Config.ButtonA = buttonValue.AsKey();
|
||||
break;
|
||||
case "ButtonB":
|
||||
viewModel.Config.ButtonB = buttonValue.AsKey();
|
||||
break;
|
||||
case "ButtonX":
|
||||
viewModel.Config.ButtonX = buttonValue.AsKey();
|
||||
break;
|
||||
case "ButtonY":
|
||||
viewModel.Config.ButtonY = buttonValue.AsKey();
|
||||
break;
|
||||
case "RightStickButton":
|
||||
viewModel.Config.RightStickButton = buttonValue.AsKey();
|
||||
break;
|
||||
case "RightStickUp":
|
||||
viewModel.Config.RightStickUp = buttonValue.AsKey();
|
||||
break;
|
||||
case "RightStickDown":
|
||||
viewModel.Config.RightStickDown = buttonValue.AsKey();
|
||||
break;
|
||||
case "RightStickRight":
|
||||
viewModel.Config.RightStickRight = buttonValue.AsKey();
|
||||
break;
|
||||
case "RightStickLeft":
|
||||
viewModel.Config.RightStickLeft = buttonValue.AsKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_currentAssigner.GetInputAndAssign(assigner, keyboard);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_currentAssigner != null)
|
||||
{
|
||||
ToggleButton oldButton = _currentAssigner.ToggledButton;
|
||||
|
||||
_currentAssigner.Cancel();
|
||||
_currentAssigner = null;
|
||||
button.IsChecked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentAssigner?.Cancel();
|
||||
_currentAssigner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MouseClick(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
bool shouldUnbind = e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed;
|
||||
|
||||
_currentAssigner?.Cancel(shouldUnbind);
|
||||
|
||||
PointerPressed -= MouseClick;
|
||||
}
|
||||
|
||||
private IButtonAssigner CreateButtonAssigner(bool forStick)
|
||||
{
|
||||
IButtonAssigner assigner;
|
||||
|
||||
assigner = new KeyboardKeyAssigner((IKeyboard)(DataContext as KeyboardInputViewModel).parentModel.SelectedGamepad);
|
||||
|
||||
return assigner;
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
_currentAssigner?.Cancel();
|
||||
_currentAssigner = null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,9 +3,10 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
|
||||
mc:Ignorable="d"
|
||||
x:Class="Ryujinx.Ava.UI.Views.Input.MotionInputView"
|
||||
x:DataType="viewModels:MotionInputViewModel"
|
||||
@@ -23,11 +24,11 @@
|
||||
Margin="0"
|
||||
HorizontalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsMotionGyroSensitivity}" />
|
||||
<Slider
|
||||
<controls:SliderScroll
|
||||
Margin="0,-5,0,-5"
|
||||
Width="150"
|
||||
MaxWidth="150"
|
||||
TickFrequency="0.01"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
SmallChange="0.01"
|
||||
Maximum="100"
|
||||
@@ -45,11 +46,11 @@
|
||||
Margin="0"
|
||||
HorizontalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsMotionGyroDeadzone}" />
|
||||
<Slider
|
||||
<controls:SliderScroll
|
||||
Margin="0,-5,0,-5"
|
||||
Width="150"
|
||||
MaxWidth="150"
|
||||
TickFrequency="0.01"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
SmallChange="0.01"
|
||||
Maximum="100"
|
||||
|
@@ -1,9 +1,7 @@
|
||||
using Avalonia.Controls;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Views.Input
|
||||
@@ -19,7 +17,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||
|
||||
public MotionInputView(ControllerInputViewModel viewModel)
|
||||
{
|
||||
var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
var config = viewModel.Config;
|
||||
|
||||
_viewModel = new MotionInputViewModel
|
||||
{
|
||||
@@ -51,7 +49,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||
};
|
||||
contentDialog.PrimaryButtonClick += (sender, args) =>
|
||||
{
|
||||
var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
var config = viewModel.Config;
|
||||
config.Slot = content._viewModel.Slot;
|
||||
config.Sensitivity = content._viewModel.Sensitivity;
|
||||
config.GyroDeadzone = content._viewModel.GyroDeadzone;
|
||||
|
@@ -1,10 +1,11 @@
|
||||
<UserControl
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
|
||||
mc:Ignorable="d"
|
||||
x:Class="Ryujinx.Ava.UI.Views.Input.RumbleInputView"
|
||||
x:DataType="viewModels:RumbleInputViewModel"
|
||||
@@ -21,7 +22,7 @@
|
||||
TextWrapping="WrapWithOverflow"
|
||||
HorizontalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsRumbleStrongMultiplier}" />
|
||||
<Slider
|
||||
<controls:SliderScroll
|
||||
Margin="0,-5,0,-5"
|
||||
Width="200"
|
||||
TickFrequency="0.01"
|
||||
@@ -41,7 +42,7 @@
|
||||
TextWrapping="WrapWithOverflow"
|
||||
HorizontalAlignment="Center"
|
||||
Text="{locale:Locale ControllerSettingsRumbleWeakMultiplier}" />
|
||||
<Slider
|
||||
<controls:SliderScroll
|
||||
Margin="0,-5,0,-5"
|
||||
Width="200"
|
||||
MaxWidth="200"
|
||||
|
@@ -1,9 +1,7 @@
|
||||
using Avalonia.Controls;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Views.Input
|
||||
@@ -19,7 +17,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||
|
||||
public RumbleInputView(ControllerInputViewModel viewModel)
|
||||
{
|
||||
var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
var config = viewModel.Config;
|
||||
|
||||
_viewModel = new RumbleInputViewModel
|
||||
{
|
||||
@@ -47,7 +45,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||
|
||||
contentDialog.PrimaryButtonClick += (sender, args) =>
|
||||
{
|
||||
var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
var config = viewModel.Config;
|
||||
config.StrongRumble = content._viewModel.StrongRumble;
|
||||
config.WeakRumble = content._viewModel.WeakRumble;
|
||||
};
|
||||
|
@@ -3,6 +3,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
@@ -176,6 +177,7 @@
|
||||
Content="{Binding VolumeStatusText}"
|
||||
IsChecked="{Binding VolumeMuted}"
|
||||
IsVisible="{Binding !ShowLoadProgress}"
|
||||
PointerWheelChanged="VolumeStatus_OnPointerWheelChanged"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
CornerRadius="0">
|
||||
@@ -192,7 +194,7 @@
|
||||
<ToggleSplitButton.Flyout>
|
||||
<Flyout Placement="Bottom" ShowMode="TransientWithDismissOnPointerMoveAway">
|
||||
<Grid Margin="0">
|
||||
<Slider
|
||||
<controls:SliderScroll
|
||||
MaxHeight="40"
|
||||
Width="150"
|
||||
Margin="0"
|
||||
|
@@ -53,5 +53,20 @@ namespace Ryujinx.Ava.UI.Views.Main
|
||||
{
|
||||
Window.LoadApplications();
|
||||
}
|
||||
|
||||
private void VolumeStatus_OnPointerWheelChanged(object sender, PointerWheelEventArgs e)
|
||||
{
|
||||
// Change the volume by 5% at a time
|
||||
float newValue = Window.ViewModel.Volume + (float)e.Delta.Y * 0.05f;
|
||||
|
||||
Window.ViewModel.Volume = newValue switch
|
||||
{
|
||||
< 0 => 0,
|
||||
> 1 => 1,
|
||||
_ => newValue,
|
||||
};
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
@@ -50,7 +51,7 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{locale:Locale IconSize}"
|
||||
ToolTip.Tip="{locale:Locale IconSizeTooltip}" />
|
||||
<Slider
|
||||
<controls:SliderScroll
|
||||
Width="150"
|
||||
Height="35"
|
||||
Margin="5,-10,5,0"
|
||||
|
@@ -4,6 +4,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
@@ -63,13 +64,13 @@
|
||||
Maximum="100" />
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<Slider Value="{Binding Volume}"
|
||||
<controls:SliderScroll Value="{Binding Volume}"
|
||||
Margin="250,0,0,0"
|
||||
ToolTip.Tip="{locale:Locale AudioVolumeTooltip}"
|
||||
Minimum="0"
|
||||
Maximum="100"
|
||||
SmallChange="5"
|
||||
TickFrequency="5"
|
||||
SmallChange="1"
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True"
|
||||
LargeChange="10"
|
||||
Width="350" />
|
||||
|
@@ -4,6 +4,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
@@ -173,7 +174,7 @@
|
||||
<TextBlock Text="FSR" />
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
<Slider Value="{Binding ScalingFilterLevel}"
|
||||
<controls:SliderScroll Value="{Binding ScalingFilterLevel}"
|
||||
ToolTip.Tip="{locale:Locale GraphicsScalingFilterLevelTooltip}"
|
||||
MinWidth="150"
|
||||
Margin="10,-3,0,0"
|
||||
|
@@ -27,9 +27,9 @@
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<views:ControllerInputView
|
||||
<views:InputView
|
||||
Grid.Row="0"
|
||||
Name="ControllerSettings" />
|
||||
Name="InputView" />
|
||||
<StackPanel
|
||||
Orientation="Vertical"
|
||||
Grid.Row="2">
|
||||
|
@@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ControllerSettings.Dispose();
|
||||
InputView.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
public void SaveSettings()
|
||||
{
|
||||
InputPage.ControllerSettings?.SaveCurrentProfile();
|
||||
InputPage.InputView?.SaveCurrentProfile();
|
||||
|
||||
if (Owner is MainWindow window && ViewModel.DirectoryChanged)
|
||||
{
|
||||
|
@@ -59,16 +59,16 @@ namespace Ryujinx.Input.Assigner
|
||||
return _gamepad == null || !_gamepad.IsConnected;
|
||||
}
|
||||
|
||||
public string GetPressedButton()
|
||||
public ButtonValue? GetPressedButton()
|
||||
{
|
||||
IEnumerable<GamepadButtonInputId> pressedButtons = _detector.GetPressedButtons();
|
||||
|
||||
if (pressedButtons.Any())
|
||||
{
|
||||
return !_forStick ? pressedButtons.First().ToString() : ((StickInputId)pressedButtons.First()).ToString();
|
||||
return !_forStick ? new(pressedButtons.First()) : new(((StickInputId)pressedButtons.First()));
|
||||
}
|
||||
|
||||
return "";
|
||||
return null;
|
||||
}
|
||||
|
||||
private void CollectButtonStats()
|
||||
|
@@ -31,6 +31,6 @@ namespace Ryujinx.Input.Assigner
|
||||
/// Get the pressed button that was read in <see cref="ReadInput"/> by the button assigner.
|
||||
/// </summary>
|
||||
/// <returns>The pressed button that was read</returns>
|
||||
string GetPressedButton();
|
||||
ButtonValue? GetPressedButton();
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@ namespace Ryujinx.Input.Assigner
|
||||
|
||||
public bool HasAnyButtonPressed()
|
||||
{
|
||||
return GetPressedButton().Length != 0;
|
||||
return GetPressedButton() is not null;
|
||||
}
|
||||
|
||||
public bool ShouldCancel()
|
||||
@@ -31,20 +31,20 @@ namespace Ryujinx.Input.Assigner
|
||||
return _keyboardState.IsPressed(Key.Escape);
|
||||
}
|
||||
|
||||
public string GetPressedButton()
|
||||
public ButtonValue? GetPressedButton()
|
||||
{
|
||||
string keyPressed = "";
|
||||
ButtonValue? keyPressed = null;
|
||||
|
||||
for (Key key = Key.Unknown; key < Key.Count; key++)
|
||||
{
|
||||
if (_keyboardState.IsPressed(key))
|
||||
{
|
||||
keyPressed = key.ToString();
|
||||
keyPressed = new(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return !ShouldCancel() ? keyPressed : "";
|
||||
return !ShouldCancel() ? keyPressed : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
48
src/Ryujinx.Input/ButtonValue.cs
Normal file
48
src/Ryujinx.Input/ButtonValue.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Input
|
||||
{
|
||||
public enum ButtonValueType { Key, GamepadButtonInputId, StickId }
|
||||
|
||||
public readonly struct ButtonValue
|
||||
{
|
||||
private readonly ButtonValueType _type;
|
||||
private readonly uint _rawValue;
|
||||
|
||||
public ButtonValue(Key key)
|
||||
{
|
||||
_type = ButtonValueType.Key;
|
||||
_rawValue = (uint)key;
|
||||
}
|
||||
|
||||
public ButtonValue(GamepadButtonInputId gamepad)
|
||||
{
|
||||
_type = ButtonValueType.GamepadButtonInputId;
|
||||
_rawValue = (uint)gamepad;
|
||||
}
|
||||
|
||||
public ButtonValue(StickInputId stick)
|
||||
{
|
||||
_type = ButtonValueType.StickId;
|
||||
_rawValue = (uint)stick;
|
||||
}
|
||||
|
||||
public Common.Configuration.Hid.Key AsKey()
|
||||
{
|
||||
Debug.Assert(_type == ButtonValueType.Key);
|
||||
return (Common.Configuration.Hid.Key)_rawValue;
|
||||
}
|
||||
|
||||
public Common.Configuration.Hid.Controller.GamepadInputId AsGamepadButtonInputId()
|
||||
{
|
||||
Debug.Assert(_type == ButtonValueType.GamepadButtonInputId);
|
||||
return (Common.Configuration.Hid.Controller.GamepadInputId)_rawValue;
|
||||
}
|
||||
|
||||
public Common.Configuration.Hid.Controller.StickInputId AsGamepadStickId()
|
||||
{
|
||||
Debug.Assert(_type == ButtonValueType.StickId);
|
||||
return (Common.Configuration.Hid.Controller.StickInputId)_rawValue;
|
||||
}
|
||||
}
|
||||
}
|
@@ -546,7 +546,7 @@ namespace Ryujinx.Ui.App.Common
|
||||
return appMetadata;
|
||||
}
|
||||
|
||||
public byte[] GetApplicationIcon(string applicationPath)
|
||||
public byte[] GetApplicationIcon(string applicationPath, Language desiredTitleLanguage)
|
||||
{
|
||||
byte[] applicationIcon = null;
|
||||
|
||||
@@ -600,7 +600,7 @@ namespace Ryujinx.Ui.App.Common
|
||||
{
|
||||
using var icon = new UniqueRef<IFile>();
|
||||
|
||||
controlFs.OpenFile(ref icon.Ref, $"/icon_{_desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
controlFs.OpenFile(ref icon.Ref, $"/icon_{desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
|
||||
|
171
src/Ryujinx.Ui.Common/Helper/ShortcutHelper.cs
Normal file
171
src/Ryujinx.Ui.Common/Helper/ShortcutHelper.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using ShellLink;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Runtime.Versioning;
|
||||
using Image = System.Drawing.Image;
|
||||
|
||||
namespace Ryujinx.Ui.Common.Helper
|
||||
{
|
||||
public static class ShortcutHelper
|
||||
{
|
||||
[SupportedOSPlatform("windows")]
|
||||
private static void CreateShortcutWindows(string applicationFilePath, byte[] iconData, string iconPath, string cleanedAppName, string desktopPath)
|
||||
{
|
||||
string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.FriendlyName + ".exe");
|
||||
iconPath += ".ico";
|
||||
|
||||
MemoryStream iconDataStream = new(iconData);
|
||||
using Image image = Image.FromStream(iconDataStream);
|
||||
using Bitmap bitmap = new(128, 128);
|
||||
using System.Drawing.Graphics graphic = System.Drawing.Graphics.FromImage(bitmap);
|
||||
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphic.DrawImage(image, 0, 0, 128, 128);
|
||||
SaveBitmapAsIcon(bitmap, iconPath);
|
||||
|
||||
var shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(basePath, applicationFilePath), iconPath, 0);
|
||||
shortcut.StringData.NameString = cleanedAppName;
|
||||
shortcut.WriteToFile(Path.Combine(desktopPath, cleanedAppName + ".lnk"));
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("linux")]
|
||||
private static void CreateShortcutLinux(string applicationFilePath, byte[] iconData, string iconPath, string desktopPath, string cleanedAppName)
|
||||
{
|
||||
string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.sh");
|
||||
var desktopFile = EmbeddedResources.ReadAllText("Ryujinx.Ui.Common/shortcut-template.desktop");
|
||||
iconPath += ".png";
|
||||
|
||||
var image = SixLabors.ImageSharp.Image.Load<Rgba32>(iconData);
|
||||
image.SaveAsPng(iconPath);
|
||||
|
||||
using StreamWriter outputFile = new(Path.Combine(desktopPath, cleanedAppName + ".desktop"));
|
||||
outputFile.Write(desktopFile, cleanedAppName, iconPath, GetArgsString(basePath, applicationFilePath));
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
private static void CreateShortcutMacos(string appFilePath, byte[] iconData, string desktopPath, string cleanedAppName)
|
||||
{
|
||||
string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.FriendlyName);
|
||||
var plistFile = EmbeddedResources.ReadAllText("Ryujinx.Ui.Common/shortcut-template.plist");
|
||||
// Macos .App folder
|
||||
string contentFolderPath = Path.Combine(desktopPath, cleanedAppName + ".app", "Contents");
|
||||
string scriptFolderPath = Path.Combine(contentFolderPath, "MacOS");
|
||||
|
||||
if (!Directory.Exists(scriptFolderPath))
|
||||
{
|
||||
Directory.CreateDirectory(scriptFolderPath);
|
||||
}
|
||||
|
||||
// Runner script
|
||||
const string ScriptName = "runner.sh";
|
||||
string scriptPath = Path.Combine(scriptFolderPath, ScriptName);
|
||||
using StreamWriter scriptFile = new(scriptPath);
|
||||
|
||||
scriptFile.WriteLine("#!/bin/sh");
|
||||
scriptFile.WriteLine(GetArgsString(basePath, appFilePath));
|
||||
|
||||
// Set execute permission
|
||||
FileInfo fileInfo = new(scriptPath);
|
||||
fileInfo.UnixFileMode |= UnixFileMode.UserExecute;
|
||||
|
||||
// img
|
||||
string resourceFolderPath = Path.Combine(contentFolderPath, "Resources");
|
||||
if (!Directory.Exists(resourceFolderPath))
|
||||
{
|
||||
Directory.CreateDirectory(resourceFolderPath);
|
||||
}
|
||||
|
||||
const string IconName = "icon.png";
|
||||
var image = SixLabors.ImageSharp.Image.Load<Rgba32>(iconData);
|
||||
image.SaveAsPng(Path.Combine(resourceFolderPath, IconName));
|
||||
|
||||
// plist file
|
||||
using StreamWriter outputFile = new(Path.Combine(contentFolderPath, "Info.plist"));
|
||||
outputFile.Write(plistFile, ScriptName, cleanedAppName, IconName);
|
||||
}
|
||||
|
||||
public static void CreateAppShortcut(string applicationFilePath, string applicationName, string applicationId, byte[] iconData)
|
||||
{
|
||||
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
|
||||
string cleanedAppName = string.Join("_", applicationName.Split(Path.GetInvalidFileNameChars()));
|
||||
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
string iconPath = Path.Combine(AppDataManager.BaseDirPath, "games", applicationId, "app");
|
||||
|
||||
CreateShortcutWindows(applicationFilePath, iconData, iconPath, cleanedAppName, desktopPath);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
string iconPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "icons", "Ryujinx");
|
||||
|
||||
Directory.CreateDirectory(iconPath);
|
||||
CreateShortcutLinux(applicationFilePath, iconData, Path.Combine(iconPath, applicationId), desktopPath, cleanedAppName);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
CreateShortcutMacos(applicationFilePath, iconData, desktopPath, cleanedAppName);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new NotImplementedException("Shortcut support has not been implemented yet for this OS.");
|
||||
}
|
||||
|
||||
private static string GetArgsString(string basePath, string appFilePath)
|
||||
{
|
||||
// args are first defined as a list, for easier adjustments in the future
|
||||
var argsList = new List<string>
|
||||
{
|
||||
basePath,
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(CommandLineState.BaseDirPathArg))
|
||||
{
|
||||
argsList.Add("--root-data-dir");
|
||||
argsList.Add($"\"{CommandLineState.BaseDirPathArg}\"");
|
||||
}
|
||||
|
||||
argsList.Add($"\"{appFilePath}\"");
|
||||
|
||||
|
||||
return String.Join(" ", argsList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Icon (.ico) file using the source bitmap image at the specified file path.
|
||||
/// </summary>
|
||||
/// <param name="source">The source bitmap image that will be saved as an .ico file</param>
|
||||
/// <param name="filePath">The location that the new .ico file will be saved too (Make sure to include '.ico' in the path).</param>
|
||||
[SupportedOSPlatform("windows")]
|
||||
private static void SaveBitmapAsIcon(Bitmap source, string filePath)
|
||||
{
|
||||
// Code Modified From https://stackoverflow.com/a/11448060/368354 by Benlitz
|
||||
byte[] header = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 32, 0, 0, 0, 0, 0, 22, 0, 0, 0 };
|
||||
using FileStream fs = new(filePath, FileMode.Create);
|
||||
|
||||
fs.Write(header);
|
||||
// Writing actual data
|
||||
source.Save(fs, ImageFormat.Png);
|
||||
// Getting data length (file length minus header)
|
||||
long dataLength = fs.Length - header.Length;
|
||||
// Write it in the correct place
|
||||
fs.Seek(14, SeekOrigin.Begin);
|
||||
fs.WriteByte((byte)dataLength);
|
||||
fs.WriteByte((byte)(dataLength >> 8));
|
||||
}
|
||||
}
|
||||
}
|
@@ -45,8 +45,18 @@
|
||||
<EmbeddedResource Include="Resources\Logo_Twitter_Light.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == ''">
|
||||
<EmbeddedResource Include="..\..\distribution\linux\shortcut-template.desktop" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64' OR '$(RuntimeIdentifier)' == ''">
|
||||
<EmbeddedResource Include="..\..\distribution\macos\shortcut-template.plist" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DiscordRichPresence" />
|
||||
<PackageReference Include="securifybv.ShellLink" />
|
||||
<PackageReference Include="System.Drawing.Common" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -23,6 +23,7 @@ namespace Ryujinx.Ui.Widgets
|
||||
private MenuItem _purgeShaderCacheMenuItem;
|
||||
private MenuItem _openPtcDirMenuItem;
|
||||
private MenuItem _openShaderCacheDirMenuItem;
|
||||
private MenuItem _createShortcutMenuItem;
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
@@ -187,6 +188,15 @@ namespace Ryujinx.Ui.Widgets
|
||||
};
|
||||
_openShaderCacheDirMenuItem.Activated += OpenShaderCacheDir_Clicked;
|
||||
|
||||
//
|
||||
// _createShortcutMenuItem
|
||||
//
|
||||
_createShortcutMenuItem = new MenuItem("Create Application Shortcut")
|
||||
{
|
||||
TooltipText = "Create a Desktop Shortcut that launches the selected Application."
|
||||
};
|
||||
_createShortcutMenuItem.Activated += CreateShortcut_Clicked;
|
||||
|
||||
ShowComponent();
|
||||
}
|
||||
|
||||
@@ -213,6 +223,7 @@ namespace Ryujinx.Ui.Widgets
|
||||
Add(new SeparatorMenuItem());
|
||||
Add(_manageCacheMenuItem);
|
||||
Add(_extractMenuItem);
|
||||
Add(_createShortcutMenuItem);
|
||||
|
||||
ShowAll();
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@ using LibHac.Ns;
|
||||
using LibHac.Tools.Fs;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
@@ -77,6 +78,8 @@ namespace Ryujinx.Ui.Widgets
|
||||
_extractExeFsMenuItem.Sensitive = hasNca;
|
||||
_extractLogoMenuItem.Sensitive = hasNca;
|
||||
|
||||
_createShortcutMenuItem.Sensitive = !ReleaseInformation.IsFlatHubBuild();
|
||||
|
||||
PopupAtPointer(null);
|
||||
}
|
||||
|
||||
@@ -629,5 +632,11 @@ namespace Ryujinx.Ui.Widgets
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateShortcut_Clicked(object sender, EventArgs args)
|
||||
{
|
||||
byte[] appIcon = new ApplicationLibrary(_virtualFileSystem).GetApplicationIcon(_titleFilePath, ConfigurationState.Instance.System.Language);
|
||||
ShortcutHelper.CreateAppShortcut(_titleFilePath, _titleName, _titleIdText, appIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -893,7 +893,7 @@ namespace Ryujinx.Ui.Windows
|
||||
}
|
||||
}
|
||||
|
||||
string pressedButton = assigner.GetPressedButton();
|
||||
string pressedButton = assigner.GetPressedButton().ToString();
|
||||
|
||||
Application.Invoke(delegate
|
||||
{
|
||||
|
Reference in New Issue
Block a user