diff options
| author | Xpl0itR <xpl0itr@outlook.com> | 2020-05-03 03:00:53 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-03 04:00:53 +0200 |
| commit | 538fba826b75cdd2feffaeac684044246590cb29 (patch) | |
| tree | 4f9b09aaaeec6249b49d665012dd4e585f3e67f0 | |
| parent | 5f3558fd51a0920966e5341101c4233a02c98307 (diff) | |
Improvements to input and input configuration in the GUI. (#849)
* Improvements to input and input configuration in the GUI
* Requested changes
* nits
* more nits
50 files changed, 5810 insertions, 2438 deletions
diff --git a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs index ff5a67c4..09252b77 100644 --- a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs +++ b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs @@ -4,9 +4,7 @@ using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Logging; using Ryujinx.Common.Utilities; using Ryujinx.Configuration.System; -using Ryujinx.Configuration.Hid; using Ryujinx.Configuration.Ui; -using Ryujinx.UI.Input; namespace Ryujinx.Configuration { @@ -15,7 +13,7 @@ namespace Ryujinx.Configuration /// <summary> /// The current version of the file format /// </summary> - public const int CurrentVersion = 5; + public const int CurrentVersion = 6; public int Version { get; set; } @@ -130,11 +128,6 @@ namespace Ryujinx.Configuration public bool IgnoreMissingServices { get; set; } /// <summary> - /// The primary controller's type - /// </summary> - public ControllerType ControllerType { get; set; } - - /// <summary> /// Used to toggle columns in the GUI /// </summary> public GuiColumns GuiColumns { get; set; } @@ -162,12 +155,12 @@ namespace Ryujinx.Configuration /// <summary> /// Keyboard control bindings /// </summary> - public NpadKeyboard KeyboardControls { get; set; } + public List<KeyboardConfig> KeyboardConfig { get; set; } /// <summary> /// Controller control bindings /// </summary> - public NpadController JoystickControls { get; set; } + public List<ControllerConfig> ControllerConfig { get; set; } /// <summary> /// Loads a configuration file from disk diff --git a/Ryujinx.Common/Configuration/ConfigurationState.cs b/Ryujinx.Common/Configuration/ConfigurationState.cs index d2826d36..a994e6d5 100644 --- a/Ryujinx.Common/Configuration/ConfigurationState.cs +++ b/Ryujinx.Common/Configuration/ConfigurationState.cs @@ -1,10 +1,9 @@ -using Ryujinx.Common; +using Ryujinx.Common; using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Logging; using Ryujinx.Configuration.Hid; using Ryujinx.Configuration.System; using Ryujinx.Configuration.Ui; -using Ryujinx.UI.Input; using System; using System.Collections.Generic; @@ -159,7 +158,7 @@ namespace Ryujinx.Configuration public ReactiveObject<string> TimeZone { get; private set; } /// <summary> - /// System Time Offset in seconds + /// System Time Offset in Seconds /// </summary> public ReactiveObject<long> SystemTimeOffset { get; private set; } @@ -208,31 +207,21 @@ namespace Ryujinx.Configuration public class HidSection { /// <summary> - /// The primary controller's type - /// </summary> - public ReactiveObject<ControllerType> ControllerType { get; private set; } - - /// <summary> /// Enable or disable keyboard support (Independent from controllers binding) /// </summary> public ReactiveObject<bool> EnableKeyboard { get; private set; } /// <summary> - /// Keyboard control bindings + /// Input device configuration. + /// NOTE: This ReactiveObject won't issue an event when the List has elements added or removed. + /// TODO: Implement a ReactiveList class. /// </summary> - public ReactiveObject<NpadKeyboard> KeyboardControls { get; private set; } - - /// <summary> - /// Controller control bindings - /// </summary> - public ReactiveObject<NpadController> JoystickControls { get; private set; } + public ReactiveObject<List<InputConfig>> InputConfig { get; private set; } public HidSection() { - ControllerType = new ReactiveObject<ControllerType>(); - EnableKeyboard = new ReactiveObject<bool>(); - KeyboardControls = new ReactiveObject<NpadKeyboard>(); - JoystickControls = new ReactiveObject<NpadController>(); + EnableKeyboard = new ReactiveObject<bool>(); + InputConfig = new ReactiveObject<List<InputConfig>>(); } } @@ -311,6 +300,21 @@ namespace Ryujinx.Configuration public ConfigurationFileFormat ToFileFormat() { + List<ControllerConfig> controllerConfigList = new List<ControllerConfig>(); + List<KeyboardConfig> keyboardConfigList = new List<KeyboardConfig>(); + + foreach (InputConfig inputConfig in Hid.InputConfig.Value) + { + if (inputConfig is ControllerConfig controllerConfig) + { + controllerConfigList.Add(controllerConfig); + } + else if (inputConfig is KeyboardConfig keyboardConfig) + { + keyboardConfigList.Add(keyboardConfig); + } + } + ConfigurationFileFormat configurationFile = new ConfigurationFileFormat { Version = ConfigurationFileFormat.CurrentVersion, @@ -336,7 +340,6 @@ namespace Ryujinx.Configuration EnableFsIntegrityChecks = System.EnableFsIntegrityChecks, FsGlobalAccessLogMode = System.FsGlobalAccessLogMode, IgnoreMissingServices = System.IgnoreMissingServices, - ControllerType = Hid.ControllerType, GuiColumns = new GuiColumns() { FavColumn = Ui.GuiColumns.FavColumn, @@ -354,8 +357,8 @@ namespace Ryujinx.Configuration EnableCustomTheme = Ui.EnableCustomTheme, CustomThemePath = Ui.CustomThemePath, EnableKeyboard = Hid.EnableKeyboard, - KeyboardControls = Hid.KeyboardControls, - JoystickControls = Hid.JoystickControls + KeyboardConfig = keyboardConfigList, + ControllerConfig = controllerConfigList }; return configurationFile; @@ -385,7 +388,6 @@ namespace Ryujinx.Configuration System.EnableFsIntegrityChecks.Value = true; System.FsGlobalAccessLogMode.Value = 0; System.IgnoreMissingServices.Value = false; - Hid.ControllerType.Value = ControllerType.Handheld; Ui.GuiColumns.FavColumn.Value = true; Ui.GuiColumns.IconColumn.Value = true; Ui.GuiColumns.AppColumn.Value = true; @@ -401,73 +403,51 @@ namespace Ryujinx.Configuration Ui.CustomThemePath.Value = ""; Hid.EnableKeyboard.Value = false; - Hid.KeyboardControls.Value = new NpadKeyboard + Hid.InputConfig.Value = new List<InputConfig> { - LeftJoycon = new NpadKeyboardLeft - { - StickUp = Key.W, - StickDown = Key.S, - StickLeft = Key.A, - StickRight = Key.D, - StickButton = Key.F, - DPadUp = Key.Up, - DPadDown = Key.Down, - DPadLeft = Key.Left, - DPadRight = Key.Right, - ButtonMinus = Key.Minus, - ButtonL = Key.E, - ButtonZl = Key.Q, - }, - RightJoycon = new NpadKeyboardRight - { - StickUp = Key.I, - StickDown = Key.K, - StickLeft = Key.J, - StickRight = Key.L, - StickButton = Key.H, - ButtonA = Key.Z, - ButtonB = Key.X, - ButtonX = Key.C, - ButtonY = Key.V, - ButtonPlus = Key.Plus, - ButtonR = Key.U, - ButtonZr = Key.O, - }, - Hotkeys = new KeyboardHotkeys + new KeyboardConfig { - ToggleVsync = Key.Tab - } - }; - - Hid.JoystickControls.Value = new NpadController - { - Enabled = true, - Index = 0, - Deadzone = 0.05f, - TriggerThreshold = 0.5f, - LeftJoycon = new NpadControllerLeft - { - Stick = ControllerInputId.Axis0, - StickButton = ControllerInputId.Button8, - DPadUp = ControllerInputId.Hat0Up, - DPadDown = ControllerInputId.Hat0Down, - DPadLeft = ControllerInputId.Hat0Left, - DPadRight = ControllerInputId.Hat0Right, - ButtonMinus = ControllerInputId.Button6, - ButtonL = ControllerInputId.Button4, - ButtonZl = ControllerInputId.Axis2, - }, - RightJoycon = new NpadControllerRight - { - Stick = ControllerInputId.Axis3, - StickButton = ControllerInputId.Button9, - ButtonA = ControllerInputId.Button1, - ButtonB = ControllerInputId.Button0, - ButtonX = ControllerInputId.Button3, - ButtonY = ControllerInputId.Button2, - ButtonPlus = ControllerInputId.Button7, - ButtonR = ControllerInputId.Button5, - ButtonZr = ControllerInputId.Axis5, + Index = 0, + ControllerType = ControllerType.JoyconPair, + PlayerIndex = PlayerIndex.Player1, + LeftJoycon = new NpadKeyboardLeft + { + StickUp = Key.W, + StickDown = Key.S, + StickLeft = Key.A, + StickRight = Key.D, + StickButton = Key.F, + DPadUp = Key.Up, + DPadDown = Key.Down, + DPadLeft = Key.Left, + DPadRight = Key.Right, + ButtonMinus = Key.Minus, + ButtonL = Key.E, + ButtonZl = Key.Q, + ButtonSl = Key.Home, + ButtonSr = Key.End + }, + RightJoycon = new NpadKeyboardRight + { + StickUp = Key.I, + StickDown = Key.K, + StickLeft = Key.J, + StickRight = Key.L, + StickButton = Key.H, + ButtonA = Key.Z, + ButtonB = Key.X, + ButtonX = Key.C, + ButtonY = Key.V, + ButtonPlus = Key.Plus, + ButtonR = Key.U, + ButtonZr = Key.O, + ButtonSl = Key.PageUp, + ButtonSr = Key.PageDown + }, + Hotkeys = new KeyboardHotkeys + { + ToggleVsync = Key.Tab + } } }; } @@ -521,6 +501,71 @@ namespace Ryujinx.Configuration configurationFileUpdated = true; } + if (configurationFileFormat.Version < 6) + { + Common.Logging.Logger.PrintWarning(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 6."); + + configurationFileFormat.ControllerConfig = new List<ControllerConfig>(); + configurationFileFormat.KeyboardConfig = new List<KeyboardConfig>{ + new KeyboardConfig + { + Index = 0, + ControllerType = ControllerType.JoyconPair, + PlayerIndex = PlayerIndex.Player1, + LeftJoycon = new NpadKeyboardLeft + { + StickUp = Key.W, + StickDown = Key.S, + StickLeft = Key.A, + StickRight = Key.D, + StickButton = Key.F, + DPadUp = Key.Up, + DPadDown = Key.Down, + DPadLeft = Key.Left, + DPadRight = Key.Right, + ButtonMinus = Key.Minus, + ButtonL = Key.E, + ButtonZl = Key.Q, + ButtonSl = Key.Unbound, + ButtonSr = Key.Unbound + }, + RightJoycon = new NpadKeyboardRight + { + StickUp = Key.I, + StickDown = Key.K, + StickLeft = Key.J, + StickRight = Key.L, + StickButton = Key.H, + ButtonA = Key.Z, + ButtonB = Key.X, + ButtonX = Key.C, + ButtonY = Key.V, + ButtonPlus = Key.Plus, + ButtonR = Key.U, + ButtonZr = Key.O, + ButtonSl = Key.Unbound, + ButtonSr = Key.Unbound + }, + Hotkeys = new KeyboardHotkeys + { + ToggleVsync = Key.Tab + } + } + }; + + configurationFileUpdated = true; + } + + List<InputConfig> inputConfig = new List<InputConfig>(); + foreach (ControllerConfig controllerConfig in configurationFileFormat.ControllerConfig) + { + inputConfig.Add(controllerConfig); + } + foreach (KeyboardConfig keyboardConfig in configurationFileFormat.KeyboardConfig) + { + inputConfig.Add(keyboardConfig); + } + Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy; Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath; Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug; @@ -544,7 +589,6 @@ namespace Ryujinx.Configuration System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks; System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode; System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices; - Hid.ControllerType.Value = configurationFileFormat.ControllerType; Ui.GuiColumns.FavColumn.Value = configurationFileFormat.GuiColumns.FavColumn; Ui.GuiColumns.IconColumn.Value = configurationFileFormat.GuiColumns.IconColumn; Ui.GuiColumns.AppColumn.Value = configurationFileFormat.GuiColumns.AppColumn; @@ -559,14 +603,13 @@ namespace Ryujinx.Configuration Ui.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme; Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath; Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard; - Hid.KeyboardControls.Value = configurationFileFormat.KeyboardControls; - Hid.JoystickControls.Value = configurationFileFormat.JoystickControls; + Hid.InputConfig.Value = inputConfig; if (configurationFileUpdated) { ToFileFormat().SaveConfig(configurationFilePath); - Common.Logging.Logger.PrintWarning(LogClass.Application, "Configuration file is updated!"); + Common.Logging.Logger.PrintWarning(LogClass.Application, "Configuration file has been updated!"); } } diff --git a/Ryujinx.Common/Configuration/Hid/NpadController.cs b/Ryujinx.Common/Configuration/Hid/ControllerConfig.cs index 94b985d5..3e414055 100644 --- a/Ryujinx.Common/Configuration/Hid/NpadController.cs +++ b/Ryujinx.Common/Configuration/Hid/ControllerConfig.cs @@ -1,21 +1,16 @@ namespace Ryujinx.Common.Configuration.Hid { - public class NpadController + public class ControllerConfig : InputConfig { /// <summary> - /// Enables or disables controller support + /// Controller Left Analog Stick Deadzone /// </summary> - public bool Enabled { get; set; } + public float DeadzoneLeft { get; set; } /// <summary> - /// Controller Device Index + /// Controller Right Analog Stick Deadzone /// </summary> - public int Index { get; set; } - - /// <summary> - /// Controller Analog Stick Deadzone - /// </summary> - public float Deadzone { get; set; } + public float DeadzoneRight { get; set; } /// <summary> /// Controller Trigger Threshold @@ -32,4 +27,4 @@ /// </summary> public NpadControllerRight RightJoycon { get; set; } } -} +}
\ No newline at end of file diff --git a/Ryujinx.Common/Configuration/Hid/ControllerInputId.cs b/Ryujinx.Common/Configuration/Hid/ControllerInputId.cs index 8969b6a4..606a1b0c 100644 --- a/Ryujinx.Common/Configuration/Hid/ControllerInputId.cs +++ b/Ryujinx.Common/Configuration/Hid/ControllerInputId.cs @@ -40,6 +40,7 @@ Hat2Up, Hat2Down, Hat2Left, - Hat2Right + Hat2Right, + Unbound } } diff --git a/Ryujinx.Common/Configuration/Hid/ControllerType.cs b/Ryujinx.Common/Configuration/Hid/ControllerType.cs index b0613b2d..0ad01bbb 100644 --- a/Ryujinx.Common/Configuration/Hid/ControllerType.cs +++ b/Ryujinx.Common/Configuration/Hid/ControllerType.cs @@ -1,11 +1,20 @@ -namespace Ryujinx.Configuration.Hid +using System; + +namespace Ryujinx.Common.Configuration.Hid { - public enum ControllerType + [Flags] + // This enum was duplicated from Ryujinx.HLE.HOS.Services.Hid.PlayerIndex and should be kept identical + public enum ControllerType : int { - ProController, - Handheld, - NpadPair, - NpadLeft, - NpadRight + None, + ProController = 1 << 0, + Handheld = 1 << 1, + JoyconPair = 1 << 2, + JoyconLeft = 1 << 3, + JoyconRight = 1 << 4, + Invalid = 1 << 5, + Pokeball = 1 << 6, + SystemExternal = 1 << 29, + System = 1 << 30 } -} +}
\ No newline at end of file diff --git a/Ryujinx.Common/Configuration/Hid/InputConfig.cs b/Ryujinx.Common/Configuration/Hid/InputConfig.cs new file mode 100644 index 00000000..540506d5 --- /dev/null +++ b/Ryujinx.Common/Configuration/Hid/InputConfig.cs @@ -0,0 +1,20 @@ +namespace Ryujinx.Common.Configuration.Hid +{ + public class InputConfig + { + /// <summary> + /// Controller Device Index + /// </summary> + public int Index { 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; } + } +}
\ No newline at end of file diff --git a/Ryujinx.Common/Configuration/Hid/Key.cs b/Ryujinx.Common/Configuration/Hid/Key.cs index b658396b..67177eec 100644 --- a/Ryujinx.Common/Configuration/Hid/Key.cs +++ b/Ryujinx.Common/Configuration/Hid/Key.cs @@ -148,6 +148,7 @@ Slash = 128, BackSlash = 129, NonUSBackSlash = 130, - LastKey = 131 + LastKey = 131, + Unbound } } diff --git a/Ryujinx.Common/Configuration/Hid/KeyboardConfig.cs b/Ryujinx.Common/Configuration/Hid/KeyboardConfig.cs new file mode 100644 index 00000000..664fdff0 --- /dev/null +++ b/Ryujinx.Common/Configuration/Hid/KeyboardConfig.cs @@ -0,0 +1,20 @@ +namespace Ryujinx.Common.Configuration.Hid +{ + public class KeyboardConfig : InputConfig + { + /// <summary> + /// Left JoyCon Keyboard Bindings + /// </summary> + public NpadKeyboardLeft LeftJoycon { get; set; } + + /// <summary> + /// Right JoyCon Keyboard Bindings + /// </summary> + public NpadKeyboardRight RightJoycon { get; set; } + + /// <summary> + /// Hotkey Keyboard Bindings + /// </summary> + public KeyboardHotkeys Hotkeys { get; set; } + } +}
\ No newline at end of file diff --git a/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs b/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs index 30cc8d84..19cc0487 100644 --- a/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs +++ b/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs @@ -1,7 +1,9 @@ -namespace Ryujinx.Configuration.Hid +using Ryujinx.Configuration.Hid; + +namespace Ryujinx.Common.Configuration.Hid { public struct KeyboardHotkeys { public Key ToggleVsync { get; set; } } -} +}
\ No newline at end of file diff --git a/Ryujinx.Common/Configuration/Hid/NpadControllerLeft.cs b/Ryujinx.Common/Configuration/Hid/NpadControllerLeft.cs index c221b5e8..00816e56 100644 --- a/Ryujinx.Common/Configuration/Hid/NpadControllerLeft.cs +++ b/Ryujinx.Common/Configuration/Hid/NpadControllerLeft.cs @@ -2,14 +2,19 @@ { public struct NpadControllerLeft { - public ControllerInputId Stick { get; set; } + public ControllerInputId StickX { get; set; } + public bool InvertStickX { get; set; } + public ControllerInputId StickY { get; set; } + public bool InvertStickY { get; set; } public ControllerInputId StickButton { get; set; } public ControllerInputId ButtonMinus { get; set; } public ControllerInputId ButtonL { get; set; } public ControllerInputId ButtonZl { get; set; } + public ControllerInputId ButtonSl { get; set; } + public ControllerInputId ButtonSr { get; set; } public ControllerInputId DPadUp { get; set; } public ControllerInputId DPadDown { get; set; } public ControllerInputId DPadLeft { get; set; } public ControllerInputId DPadRight { get; set; } } -} +}
\ No newline at end of file diff --git a/Ryujinx.Common/Configuration/Hid/NpadControllerRight.cs b/Ryujinx.Common/Configuration/Hid/NpadControllerRight.cs index f52f6f16..b7b289cc 100644 --- a/Ryujinx.Common/Configuration/Hid/NpadControllerRight.cs +++ b/Ryujinx.Common/Configuration/Hid/NpadControllerRight.cs @@ -2,7 +2,10 @@ { public struct NpadControllerRight { - public ControllerInputId Stick { get; set; } + public ControllerInputId StickX { get; set; } + public bool InvertStickX { get; set; } + public ControllerInputId StickY { get; set; } + public bool InvertStickY { get; set; } public ControllerInputId StickButton { get; set; } public ControllerInputId ButtonA { get; set; } public ControllerInputId ButtonB { get; set; } @@ -11,5 +14,7 @@ public ControllerInputId ButtonPlus { get; set; } public ControllerInputId ButtonR { get; set; } public ControllerInputId ButtonZr { get; set; } + public ControllerInputId ButtonSl { get; set; } + public ControllerInputId ButtonSr { get; set; } } -} +}
\ No newline at end of file diff --git a/Ryujinx.Common/Configuration/Hid/NpadKeyboard.cs b/Ryujinx.Common/Configuration/Hid/NpadKeyboard.cs deleted file mode 100644 index 5ae82756..00000000 --- a/Ryujinx.Common/Configuration/Hid/NpadKeyboard.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Ryujinx.UI.Input -{ - public class NpadKeyboard - { - /// <summary> - /// Left JoyCon Keyboard Bindings - /// </summary> - public Configuration.Hid.NpadKeyboardLeft LeftJoycon { get; set; } - - /// <summary> - /// Right JoyCon Keyboard Bindings - /// </summary> - public Configuration.Hid.NpadKeyboardRight RightJoycon { get; set; } - - /// <summary> - /// Hotkey Keyboard Bindings - /// </summary> - public Configuration.Hid.KeyboardHotkeys Hotkeys { get; set; } - } -} diff --git a/Ryujinx.Common/Configuration/Hid/NpadKeyboardLeft.cs b/Ryujinx.Common/Configuration/Hid/NpadKeyboardLeft.cs index 4a61d932..6b78f5b6 100644 --- a/Ryujinx.Common/Configuration/Hid/NpadKeyboardLeft.cs +++ b/Ryujinx.Common/Configuration/Hid/NpadKeyboardLeft.cs @@ -1,4 +1,6 @@ -namespace Ryujinx.Configuration.Hid +using Ryujinx.Configuration.Hid; + +namespace Ryujinx.Common.Configuration.Hid { public struct NpadKeyboardLeft { @@ -14,5 +16,7 @@ public Key ButtonMinus { get; set; } public Key ButtonL { get; set; } public Key ButtonZl { get; set; } + public Key ButtonSl { get; set; } + public Key ButtonSr { get; set; } } -} +}
\ No newline at end of file diff --git a/Ryujinx.Common/Configuration/Hid/NpadKeyboardRight.cs b/Ryujinx.Common/Configuration/Hid/NpadKeyboardRight.cs index 0677b573..e2109902 100644 --- a/Ryujinx.Common/Configuration/Hid/NpadKeyboardRight.cs +++ b/Ryujinx.Common/Configuration/Hid/NpadKeyboardRight.cs @@ -1,4 +1,6 @@ -namespace Ryujinx.Configuration.Hid +using Ryujinx.Configuration.Hid; + +namespace Ryujinx.Common.Configuration.Hid { public struct NpadKeyboardRight { @@ -14,5 +16,7 @@ public Key ButtonPlus { get; set; } public Key ButtonR { get; set; } public Key ButtonZr { get; set; } + public Key ButtonSl { get; set; } + public Key ButtonSr { get; set; } } -} +}
\ No newline at end of file diff --git a/Ryujinx.Common/Configuration/Hid/PlayerIndex.cs b/Ryujinx.Common/Configuration/Hid/PlayerIndex.cs new file mode 100644 index 00000000..2e34cb96 --- /dev/null +++ b/Ryujinx.Common/Configuration/Hid/PlayerIndex.cs @@ -0,0 +1,18 @@ +namespace Ryujinx.Common.Configuration.Hid +{ + // This enum was duplicated from Ryujinx.HLE.HOS.Services.Hid.PlayerIndex and should be kept identical + public enum PlayerIndex : int + { + Player1 = 0, + Player2 = 1, + Player3 = 2, + Player4 = 3, + Player5 = 4, + Player6 = 5, + Player7 = 6, + Player8 = 7, + Handheld = 8, + Unknown = 9, + Auto = 10 // Shouldn't be used directly + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Hid/Hid.cs b/Ryujinx.HLE/HOS/Services/Hid/Hid.cs index e07577ed..c4935a64 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/Hid.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/Hid.cs @@ -7,16 +7,16 @@ namespace Ryujinx.HLE.HOS.Services.Hid public class Hid { private readonly Switch _device; - private long _hidMemoryAddress; + private readonly long _hidMemoryAddress; internal ref HidSharedMemory SharedMemory => ref _device.Memory.GetStructRef<HidSharedMemory>(_hidMemoryAddress); internal const int SharedMemEntryCount = 17; public DebugPadDevice DebugPad; - public TouchDevice Touchscreen; - public MouseDevice Mouse; + public TouchDevice Touchscreen; + public MouseDevice Mouse; public KeyboardDevice Keyboard; - public NpadDevices Npads; + public NpadDevices Npads; static Hid() { @@ -48,7 +48,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid public Hid(in Switch device, long sharedHidMemoryAddress) { - _device = device; + _device = device; _hidMemoryAddress = sharedHidMemoryAddress; device.Memory.FillWithZeros(sharedHidMemoryAddress, Horizon.HidSize); @@ -56,26 +56,26 @@ namespace Ryujinx.HLE.HOS.Services.Hid public void InitDevices() { - DebugPad = new DebugPadDevice(_device, true); + DebugPad = new DebugPadDevice(_device, true); Touchscreen = new TouchDevice(_device, true); - Mouse = new MouseDevice(_device, false); - Keyboard = new KeyboardDevice(_device, false); - Npads = new NpadDevices(_device, true); + Mouse = new MouseDevice(_device, false); + Keyboard = new KeyboardDevice(_device, false); + Npads = new NpadDevices(_device, true); } public ControllerKeys UpdateStickButtons(JoystickPosition leftStick, JoystickPosition rightStick) { ControllerKeys result = 0; - result |= (leftStick.Dx < 0) ? ControllerKeys.LStickLeft : result; + result |= (leftStick.Dx < 0) ? ControllerKeys.LStickLeft : result; result |= (leftStick.Dx > 0) ? ControllerKeys.LStickRight : result; - result |= (leftStick.Dy < 0) ? ControllerKeys.LStickDown : result; - result |= (leftStick.Dy > 0) ? ControllerKeys.LStickUp : result; + result |= (leftStick.Dy < 0) ? ControllerKeys.LStickDown : result; + result |= (leftStick.Dy > 0) ? ControllerKeys.LStickUp : result; - result |= (rightStick.Dx < 0) ? ControllerKeys.RStickLeft : result; + result |= (rightStick.Dx < 0) ? ControllerKeys.RStickLeft : result; result |= (rightStick.Dx > 0) ? ControllerKeys.RStickRight : result; - result |= (rightStick.Dy < 0) ? ControllerKeys.RStickDown : result; - result |= (rightStick.Dy > 0) ? ControllerKeys.RStickUp : result; + result |= (rightStick.Dy < 0) ? ControllerKeys.RStickDown : result; + result |= (rightStick.Dy > 0) ? ControllerKeys.RStickUp : result; return result; } diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs index ff330312..c4c9d095 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs @@ -1,6 +1,6 @@ using System; -using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Kernel.Threading; namespace Ryujinx.HLE.HOS.Services.Hid { @@ -9,14 +9,14 @@ namespace Ryujinx.HLE.HOS.Services.Hid internal NpadJoyHoldType JoyHold = NpadJoyHoldType.Vertical; internal bool SixAxisActive = false; // TODO: link to hidserver when implemented - enum FilterState + private enum FilterState { Unconfigured = 0, - Configured = 1, - Accepted = 2 + Configured = 1, + Accepted = 2 } - struct NpadConfig + private struct NpadConfig { public ControllerType ConfiguredType; public FilterState State; @@ -33,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid public ControllerType SupportedStyleSets { - get { return _supportedStyleSets; } + get => _supportedStyleSets; set { if (_supportedStyleSets != value) // Deal with spamming @@ -46,9 +46,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid public PlayerIndex PrimaryController { get; set; } = PlayerIndex.Unknown; - KEvent[] _styleSetUpdateEvents; + private KEvent[] _styleSetUpdateEvents; - static readonly Array3<BatteryCharge> _fullBattery; + private static readonly Array3<BatteryCharge> _fullBattery; public NpadDevices(Switch device, bool active = true) : base(device, active) { @@ -68,7 +68,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid { for (int i = 0; i < configs.Length; ++i) { - PlayerIndex player = configs[i].Player; + PlayerIndex player = configs[i].Player; ControllerType controllerType = configs[i].Type; if (player > PlayerIndex.Handheld) @@ -87,7 +87,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid MatchControllers(); } - void MatchControllers() + private void MatchControllers() { PrimaryController = PlayerIndex.Unknown; @@ -141,7 +141,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid return ref _styleSetUpdateEvents[(int)player]; } - void InitController(PlayerIndex player, ControllerType type) + private void InitController(PlayerIndex player, ControllerType type) { if (type == ControllerType.Handheld) { @@ -155,13 +155,13 @@ namespace Ryujinx.HLE.HOS.Services.Hid // TODO: Allow customizing colors at config NpadStateHeader defaultHeader = new NpadStateHeader { - IsHalf = false, - SingleColorBody = NpadColor.BodyGray, + IsHalf = false, + SingleColorBody = NpadColor.BodyGray, SingleColorButtons = NpadColor.ButtonGray, - LeftColorBody = NpadColor.BodyNeonBlue, - LeftColorButtons = NpadColor.ButtonGray, - RightColorBody = NpadColor.BodyNeonRed, - RightColorButtons = NpadColor.ButtonGray + LeftColorBody = NpadColor.BodyNeonBlue, + LeftColorButtons = NpadColor.ButtonGray, + RightColorBody = NpadColor.BodyNeonRed, + RightColorButtons = NpadColor.ButtonGray }; controller.SystemProperties = NpadSystemProperties.PowerInfo0Connected | @@ -173,44 +173,44 @@ namespace Ryujinx.HLE.HOS.Services.Hid switch (type) { case ControllerType.ProController: - defaultHeader.Type = ControllerType.ProController; - controller.DeviceType = DeviceType.FullKey; + defaultHeader.Type = ControllerType.ProController; + controller.DeviceType = DeviceType.FullKey; controller.SystemProperties |= NpadSystemProperties.AbxyButtonOriented | NpadSystemProperties.PlusButtonCapability | NpadSystemProperties.MinusButtonCapability; break; case ControllerType.Handheld: - defaultHeader.Type = ControllerType.Handheld; - controller.DeviceType = DeviceType.HandheldLeft | + defaultHeader.Type = ControllerType.Handheld; + controller.DeviceType = DeviceType.HandheldLeft | DeviceType.HandheldRight; controller.SystemProperties |= NpadSystemProperties.AbxyButtonOriented | NpadSystemProperties.PlusButtonCapability | NpadSystemProperties.MinusButtonCapability; break; case ControllerType.JoyconPair: - defaultHeader.Type = ControllerType.JoyconPair; - controller.DeviceType = DeviceType.JoyLeft | + defaultHeader.Type = ControllerType.JoyconPair; + controller.DeviceType = DeviceType.JoyLeft | DeviceType.JoyRight; controller.SystemProperties |= NpadSystemProperties.AbxyButtonOriented | NpadSystemProperties.PlusButtonCapability | NpadSystemProperties.MinusButtonCapability; break; case ControllerType.JoyconLeft: - defaultHeader.Type = ControllerType.JoyconLeft; - defaultHeader.IsHalf = true; - controller.DeviceType = DeviceType.JoyLeft; + defaultHeader.Type = ControllerType.JoyconLeft; + defaultHeader.IsHalf = true; + controller.DeviceType = DeviceType.JoyLeft; controller.SystemProperties |= NpadSystemProperties.SlSrButtonOriented | NpadSystemProperties.MinusButtonCapability; break; case ControllerType.JoyconRight: - defaultHeader.Type = ControllerType.JoyconRight; - defaultHeader.IsHalf = true; - controller.DeviceType = DeviceType.JoyRight; + defaultHeader.Type = ControllerType.JoyconRight; + defaultHeader.IsHalf = true; + controller.DeviceType = DeviceType.JoyRight; controller.SystemProperties |= NpadSystemProperties.SlSrButtonOriented | NpadSystemProperties.PlusButtonCapability; break; case ControllerType.Pokeball: - defaultHeader.Type = ControllerType.Pokeball; + defaultHeader.Type = ControllerType.Pokeball; controller.DeviceType = DeviceType.Palma; break; } @@ -229,16 +229,16 @@ namespace Ryujinx.HLE.HOS.Services.Hid Logger.PrintInfo(LogClass.Hid, $"Connected ControllerType {type} to PlayerIndex {player}"); } - static NpadLayoutsIndex ControllerTypeToLayout(ControllerType controllerType) + private static NpadLayoutsIndex ControllerTypeToLayout(ControllerType controllerType) => controllerType switch { ControllerType.ProController => NpadLayoutsIndex.ProController, - ControllerType.Handheld => NpadLayoutsIndex.Handheld, - ControllerType.JoyconPair => NpadLayoutsIndex.JoyDual, - ControllerType.JoyconLeft => NpadLayoutsIndex.JoyLeft, - ControllerType.JoyconRight => NpadLayoutsIndex.JoyRight, - ControllerType.Pokeball => NpadLayoutsIndex.Pokeball, - _ => NpadLayoutsIndex.SystemExternal + ControllerType.Handheld => NpadLayoutsIndex.Handheld, + ControllerType.JoyconPair => NpadLayoutsIndex.JoyDual, + ControllerType.JoyconLeft => NpadLayoutsIndex.JoyLeft, + ControllerType.JoyconRight => NpadLayoutsIndex.JoyRight, + ControllerType.Pokeball => NpadLayoutsIndex.Pokeball, + _ => NpadLayoutsIndex.SystemExternal }; public void SetGamepadsInput(params GamepadInput[] states) @@ -251,8 +251,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid } } - void SetGamepadState(PlayerIndex player, ControllerKeys buttons, - JoystickPosition leftJoystick, JoystickPosition rightJoystick) + private void SetGamepadState(PlayerIndex player, ControllerKeys buttons, + JoystickPosition leftJoystick, JoystickPosition rightJoystick) { if (player == PlayerIndex.Auto) { @@ -269,9 +269,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid return; } - ref ShMemNpad currentNpad = ref _device.Hid.SharedMemory.Npads[(int)player]; + ref ShMemNpad currentNpad = ref _device.Hid.SharedMemory.Npads[(int)player]; ref NpadLayout currentLayout = ref currentNpad.Layouts[(int)ControllerTypeToLayout(currentNpad.Header.Type)]; - ref NpadState currentEntry = ref currentLayout.Entries[(int)currentLayout.Header.LatestEntry]; + ref NpadState currentEntry = ref currentLayout.Entries[(int)currentLayout.Header.LatestEntry]; currentEntry.Buttons = buttons; currentEntry.LStickX = leftJoystick.Dx; @@ -284,7 +284,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid mainLayout.Entries[(int)mainLayout.Header.LatestEntry] = currentEntry; } - void UpdateAllEntries() + private void UpdateAllEntries() { ref Array10<ShMemNpad> controllers = ref _device.Hid.SharedMemory.Npads; for (int i = 0; i < controllers.Length; ++i) @@ -296,9 +296,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid int currentIndex = UpdateEntriesHeader(ref currentLayout.Header, out int previousIndex); ref NpadState currentEntry = ref currentLayout.Entries[currentIndex]; - NpadState previousEntry = currentLayout.Entries[previousIndex]; + NpadState previousEntry = currentLayout.Entries[previousIndex]; - currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1; + currentEntry.SampleTimestamp = previousEntry.SampleTimestamp + 1; currentEntry.SampleTimestamp2 = previousEntry.SampleTimestamp2 + 1; if (controllers[i].Header.Type == ControllerType.None) diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/ControllerConfig.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/ControllerConfig.cs index e59ba312..477e1a84 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/ControllerConfig.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/ControllerConfig.cs @@ -2,7 +2,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid { public struct ControllerConfig { - public PlayerIndex Player; + public PlayerIndex Player; public ControllerType Type; } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/GamepadInput.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/GamepadInput.cs index 2488057e..633671df 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/GamepadInput.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/Types/GamepadInput.cs @@ -2,8 +2,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid { public struct GamepadInput { - public PlayerIndex PlayerId; - public ControllerKeys Buttons; + public PlayerIndex PlayerId; + public ControllerKeys Buttons; public JoystickPosition LStick; public JoystickPosition RStick; } diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/ControllerKeys.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/ControllerKeys.cs index db0319ed..c91636b2 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/ControllerKeys.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/ControllerKeys.cs @@ -5,41 +5,41 @@ namespace Ryujinx.HLE.HOS.Services.Hid [Flags] public enum ControllerKeys : long { - A = 1 << 0, - B = 1 << 1, - X = 1 << 2, - Y = 1 << 3, - LStick = 1 << 4, - RStick = 1 << 5, - L = 1 << 6, - R = 1 << 7, - Zl = 1 << 8, - Zr = 1 << 9, - Plus = 1 << 10, - Minus = 1 << 11, - DpadLeft = 1 << 12, - DpadUp = 1 << 13, - DpadRight = 1 << 14, - DpadDown = 1 << 15, - LStickLeft = 1 << 16, - LStickUp = 1 << 17, + A = 1 << 0, + B = 1 << 1, + X = 1 << 2, + Y = 1 << 3, + LStick = 1 << 4, + RStick = 1 << 5, + L = 1 << 6, + R = 1 << 7, + Zl = 1 << 8, + Zr = 1 << 9, + Plus = 1 << 10, + Minus = 1 << 11, + DpadLeft = 1 << 12, + DpadUp = 1 << 13, + DpadRight = 1 << 14, + DpadDown = 1 << 15, + LStickLeft = 1 << 16, + LStickUp = 1 << 17, LStickRight = 1 << 18, - LStickDown = 1 << 19, - RStickLeft = 1 << 20, - RStickUp = 1 << 21, + LStickDown = 1 << 19, + RStickLeft = 1 << 20, + RStickUp = 1 << 21, RStickRight = 1 << 22, - RStickDown = 1 << 23, - SlLeft = 1 << 24, - SrLeft = 1 << 25, - SlRight = 1 << 26, - SrRight = 1 << 27, + RStickDown = 1 << 23, + SlLeft = 1 << 24, + SrLeft = 1 << 25, + SlRight = 1 << 26, + SrRight = 1 << 27, // Generic Catch-all - Up = DpadUp | LStickUp | RStickUp, - Down = DpadDown | LStickDown | RStickDown, - Left = DpadLeft | LStickLeft | RStickLeft, + Up = DpadUp | LStickUp | RStickUp, + Down = DpadDown | LStickDown | RStickDown, + Left = DpadLeft | LStickLeft | RStickLeft, Right = DpadRight | LStickRight | RStickRight, - Sl = SlLeft | SlRight, - Sr = SrLeft | SrRight + Sl = SlLeft | SlRight, + Sr = SrLeft | SrRight } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/ControllerType.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/ControllerType.cs index f65c3079..b2d34e8e 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/ControllerType.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/Types/Npad/ControllerType.cs @@ -6,14 +6,14 @@ namespace Ryujinx.HLE.HOS.Services.Hid public enum ControllerType : int { None, - ProController = 1 << 0, - Handheld = 1 << 1, - JoyconPair = 1 << 2, - JoyconLeft = 1 << 3, - JoyconRight = 1 << 4, - Invalid = 1 << 5, - Pokeball = 1 << 6, + ProController = 1 << 0, + Handheld = 1 << 1, + JoyconPair = 1 << 2, + JoyconLeft = 1 << 3, + JoyconRight = 1 << 4, + Invalid = 1 << 5, + Pokeball = 1 << 6, SystemExternal = 1 << 29, - System = 1 << 30 + System = 1 << 30 } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayoutsIndex.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayoutsIndex.cs index 29eb8d3d..c4419336 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayoutsIndex.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMem/Npad/NpadLayoutsIndex.cs @@ -2,12 +2,12 @@ namespace Ryujinx.HLE.HOS.Services.Hid { enum NpadLayoutsIndex : int { - ProController = 0, - Handheld = 1, - JoyDual = 2, - JoyLeft = 3, - JoyRight = 4, - Pokeball = 5, + ProController = 0, + Handheld = 1, + JoyDual = 2, + JoyLeft = 3, + JoyRight = 4, + Pokeball = 5, SystemExternal = 6 } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/Types/Device.cs b/Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/Types/Device.cs index 7eaf4ac8..3ff3489b 100644 --- a/Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/Types/Device.cs +++ b/Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/Types/Device.cs @@ -14,6 +14,6 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp.UserManager public DeviceState State = DeviceState.Unavailable; public PlayerIndex Handle; - public NpadIdType NpadIdType; + public NpadIdType NpadIdType; } }
\ No newline at end of file diff --git a/Ryujinx/Config.json b/Ryujinx/Config.json index 8df901e2..c5d08f9f 100644 --- a/Ryujinx/Config.json +++ b/Ryujinx/Config.json @@ -1,5 +1,5 @@ { - "version": 5, + "version": 6, "max_anisotropy": -1, "graphics_shaders_dump_path": "", "logging_enable_debug": false, @@ -22,7 +22,6 @@ "enable_fs_integrity_checks": true, "fs_global_access_log_mode": 0, "ignore_missing_services": false, - "controller_type": "Handheld", "gui_columns": { "fav_column": true, "icon_column": true, @@ -39,65 +38,47 @@ "enable_custom_theme": false, "custom_theme_path": "", "enable_keyboard": false, - "keyboard_controls": { - "left_joycon": { - "stick_up": "W", - "stick_down": "S", - "stick_left": "A", - "stick_right": "D", - "stick_button": "F", - "dpad_up": "Up", - "dpad_down": "Down", - "dpad_left": "Left", - "dpad_right": "Right", - "button_minus": "Minus", - "button_l": "E", - "button_zl": "Q" - }, - "right_joycon": { - "stick_up": "I", - "stick_down": "K", - "stick_left": "J", - "stick_right": "L", - "stick_button": "H", - "button_a": "Z", - "button_b": "X", - "button_x": "C", - "button_y": "V", - "button_plus": "Plus", - "button_r": "U", - "button_zr": "O" - }, - "hotkeys": { - "toggle_vsync": "Tab" + "keyboard_config": [ + { + "index": 0, + "controller_type": "JoyconPair", + "player_index": "Player1", + "left_joycon": { + "stick_up": "W", + "stick_down": "S", + "stick_left": "A", + "stick_right": "D", + "stick_button": "F", + "dpad_up": "Up", + "dpad_down": "Down", + "dpad_left": "Left", + "dpad_right": "Right", + "button_minus": "Minus", + "button_l": "E", + "button_zl": "Q", + "button_sl": "Unbound", + "button_sr": "Unbound" + }, + "right_joycon": { + "stick_up": "I", + "stick_down": "K", + "stick_left": "J", + "stick_right": "L", + "stick_button": "H", + "button_a": "Z", + "button_b": "X", + "button_x": "C", + "button_y": "V", + "button_plus": "Plus", + "button_r": "U", + "button_zr": "O", + "button_sl": "Unbound", + "button_sr": "Unbound" + }, + "hotkeys": { + "toggle_vsync": "Tab" + } } - }, - "joystick_controls": { - "enabled": true, - "index": 0, - "deadzone": 0.05, - "trigger_threshold": 0.5, - "left_joycon": { - "stick": "Axis0", - "stick_button": "Button8", - "button_minus": "Button6", - "button_l": "Button4", - "button_zl": "Axis2", - "dpad_up": "Hat0Up", - "dpad_down": "Hat0Down", - "dpad_left": "Hat0Left", - "dpad_right": "Hat0Right" - }, - "right_joycon": { - "stick": "Axis3", - "stick_button": "Button9", - "button_a": "Button1", - "button_b": "Button0", - "button_x": "Button3", - "button_y": "Button2", - "button_plus": "Button7", - "button_r": "Button5", - "button_zr": "Axis5" - } - } + ], + "controller_config": [] }
\ No newline at end of file diff --git a/Ryujinx/Ryujinx.csproj b/Ryujinx/Ryujinx.csproj index 28a0b601..b8258f58 100644 --- a/Ryujinx/Ryujinx.csproj +++ b/Ryujinx/Ryujinx.csproj @@ -31,9 +31,10 @@ <ItemGroup> <None Remove="Ui\AboutWindow.glade" /> - <None Remove="Ui\assets\BlueCon.png" /> - <None Remove="Ui\assets\ProCon.png" /> - <None Remove="Ui\assets\RedCon.png" /> + <None Remove="Ui\assets\JoyConLeft.svg" /> + <None Remove="Ui\assets\JoyConPair.svg" /> + <None Remove="Ui\assets\JoyConRight.svg" /> + <None Remove="Ui\assets\ProCon.svg" /> <None Remove="Ui\assets\NCAIcon.png" /> <None Remove="Ui\assets\NROIcon.png" /> <None Remove="Ui\assets\NSOIcon.png" /> @@ -41,21 +42,23 @@ <None Remove="Ui\assets\XCIIcon.png" /> <None Remove="Ui\assets\DiscordLogo.png" /> <None Remove="Ui\assets\GitHubLogo.png" /> - <None Remove="Ui\assets\JoyCon.png" /> <None Remove="Ui\assets\PatreonLogo.png" /> <None Remove="Ui\assets\Icon.png" /> <None Remove="Ui\assets\TwitterLogo.png" /> + <None Remove="Ui\ControllerWindow.glade" /> <None Remove="Ui\GameTableContextMenu.glade" /> <None Remove="Ui\MainWindow.glade" /> - <None Remove="Ui\SwitchSettings.glade" /> + <None Remove="Ui\ProfileDialog.glade" /> + <None Remove="Ui\SettingsWindow.glade" /> <None Remove="Ui\TitleUpdateWindow.glade" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="Ui\AboutWindow.glade" /> - <EmbeddedResource Include="Ui\assets\BlueCon.png" /> - <EmbeddedResource Include="Ui\assets\ProCon.png" /> - <EmbeddedResource Include="Ui\assets\RedCon.png" /> + <EmbeddedResource Include="Ui\assets\JoyConLeft.svg" /> + <EmbeddedResource Include="Ui\assets\JoyConPair.svg" /> + <EmbeddedResource Include="Ui\assets\JoyConRight.svg" /> + <EmbeddedResource Include="Ui\assets\ProCon.svg" /> <EmbeddedResource Include="Ui\assets\NCAIcon.png" /> <EmbeddedResource Include="Ui\assets\NROIcon.png" /> <EmbeddedResource Include="Ui\assets\NSOIcon.png" /> @@ -63,13 +66,14 @@ <EmbeddedResource Include="Ui\assets\XCIIcon.png" /> <EmbeddedResource Include="Ui\assets\DiscordLogo.png" /> <EmbeddedResource Include="Ui\assets\GitHubLogo.png" /> - <EmbeddedResource Include="Ui\assets\JoyCon.png" /> <EmbeddedResource Include="Ui\assets\PatreonLogo.png" /> <EmbeddedResource Include="Ui\assets\Icon.png" /> <EmbeddedResource Include="Ui\assets\TwitterLogo.png" /> + <EmbeddedResource Include="Ui\ControllerWindow.glade" /> <EmbeddedResource Include="Ui\GameTableContextMenu.glade" /> <EmbeddedResource Include="Ui\MainWindow.glade" /> - <EmbeddedResource Include="Ui\SwitchSettings.glade" /> + <EmbeddedResource Include="Ui\ProfileDialog.glade" /> + <EmbeddedResource Include="Ui\SettingsWindow.glade" /> <EmbeddedResource Include="Ui\TitleUpdateWindow.glade" /> </ItemGroup> diff --git a/Ryujinx/Ui/AboutWindow.cs b/Ryujinx/Ui/AboutWindow.cs index 6a18058a..5f1645da 100644 --- a/Ryujinx/Ui/AboutWindow.cs +++ b/Ryujinx/Ui/AboutWindow.cs @@ -12,7 +12,6 @@ namespace Ryujinx.Ui { #pragma warning disable CS0649 #pragma warning disable IDE0044 - [GUI] Window _aboutWin; [GUI] Label _versionText; [GUI] Image _ryujinxLogo; [GUI] Image _patreonLogo; @@ -28,7 +27,7 @@ namespace Ryujinx.Ui { builder.Autoconnect(this); - _aboutWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"); + this.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"); _ryujinxLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png" , 100, 100); _patreonLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.PatreonLogo.png", 30 , 30 ); _gitHubLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.GitHubLogo.png" , 30 , 30 ); diff --git a/Ryujinx/Ui/ApplicationLibrary.cs b/Ryujinx/Ui/ApplicationLibrary.cs index 02b6541f..2dd88196 100644 --- a/Ryujinx/Ui/ApplicationLibrary.cs +++ b/Ryujinx/Ui/ApplicationLibrary.cs @@ -413,7 +413,7 @@ namespace Ryujinx.Ui Version = version, TimePlayed = ConvertSecondsToReadableString(appMetadata.TimePlayed), LastPlayed = appMetadata.LastPlayed, - FileExtension = Path.GetExtension(applicationPath).ToUpper().Remove(0 ,1), + FileExtension = Path.GetExtension(applicationPath).ToUpper().Remove(0, 1), FileSize = (fileSize < 1) ? (fileSize * 1024).ToString("0.##") + "MB" : fileSize.ToString("0.##") + "GB", Path = applicationPath, SaveDataPath = saveDataPath, diff --git a/Ryujinx/Ui/ControllerWindow.cs b/Ryujinx/Ui/ControllerWindow.cs new file mode 100644 index 00000000..581c7d56 --- /dev/null +++ b/Ryujinx/Ui/ControllerWindow.cs @@ -0,0 +1,925 @@ +using Gtk; +using OpenTK.Input; +using System; +using System.IO; +using System.Reflection; +using System.Threading; +using Ryujinx.Configuration; +using Ryujinx.Common.Configuration.Hid; +using Ryujinx.Common.Utilities; +using Ryujinx.HLE.FileSystem; + +using GUI = Gtk.Builder.ObjectAttribute; +using Key = Ryujinx.Configuration.Hid.Key; + +namespace Ryujinx.Ui +{ + public class ControllerWindow : Window + { + private PlayerIndex _playerIndex; + private InputConfig _inputConfig; + private bool _isWaitingForInput; + private VirtualFileSystem _virtualFileSystem; + +#pragma warning disable CS0649, IDE0044 + [GUI] Adjustment _controllerDeadzoneLeft; + [GUI] Adjustment _controllerDeadzoneRight; + [GUI] Adjustment _controllerTriggerThreshold; + [GUI] ComboBoxText _inputDevice; + [GUI] ComboBoxText _profile; + [GUI] ToggleButton _refreshInputDevicesButton; + [GUI] Box _settingsBox; + [GUI] Grid _leftStickKeyboard; + [GUI] Grid _leftStickController; + [GUI] Box _deadZoneLeftBox; + [GUI] Grid _rightStickKeyboard; + [GUI] Grid _rightStickController; + [GUI] Box _deadZoneRightBox; + [GUI] Grid _leftSideTriggerBox; + [GUI] Grid _rightSideTriggerBox; + [GUI] Box _triggerThresholdBox; + [GUI] ComboBoxText _controllerType; + [GUI] ToggleButton _lStickX; + [GUI] CheckButton _invertLStickX; + [GUI] ToggleButton _lStickY; + [GUI] CheckButton _invertLStickY; + [GUI] ToggleButton _lStickUp; + [GUI] ToggleButton _lStickDown; + [GUI] ToggleButton _lStickLeft; + [GUI] ToggleButton _lStickRight; + [GUI] ToggleButton _lStickButton; + [GUI] ToggleButton _dpadUp; + [GUI] ToggleButton _dpadDown; + [GUI] ToggleButton _dpadLeft; + [GUI] ToggleButton _dpadRight; + [GUI] ToggleButton _minus; + [GUI] ToggleButton _l; + [GUI] ToggleButton _zL; + [GUI] ToggleButton _rStickX; + [GUI] CheckButton _invertRStickX; + [GUI] ToggleButton _rStickY; + [GUI] CheckButton _invertRStickY; + [GUI] ToggleButton _rStickUp; + [GUI] ToggleButton _rStickDown; + [GUI] ToggleButton _rStickLeft; + [GUI] ToggleButton _rStickRight; + [GUI] ToggleButton _rStickButton; + [GUI] ToggleButton _a; + [GUI] ToggleButton _b; + [GUI] ToggleButton _x; + [GUI] ToggleButton _y; + [GUI] ToggleButton _plus; + [GUI] ToggleButton _r; + [GUI] ToggleButton _zR; + [GUI] ToggleButton _lSl; + [GUI] ToggleButton _lSr; + [GUI] ToggleButton _rSl; + [GUI] ToggleButton _rSr; + [GUI] Image _controllerImage; +#pragma warning restore CS0649, IDE0044 + + public ControllerWindow(PlayerIndex controllerId, VirtualFileSystem virtualFileSystem) : this(new Builder("Ryujinx.Ui.ControllerWindow.glade"), controllerId, virtualFileSystem) { } + + private ControllerWindow(Builder builder, PlayerIndex controllerId, VirtualFileSystem virtualFileSystem) : base(builder.GetObject("_controllerWin").Handle) + { + builder.Autoconnect(this); + + this.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"); + + _playerIndex = controllerId; + _virtualFileSystem = virtualFileSystem; + _inputConfig = ConfigurationState.Instance.Hid.InputConfig.Value.Find(inputConfig => inputConfig.PlayerIndex == _playerIndex); + + //Bind Events + _lStickX.Clicked += Button_Pressed; + _lStickY.Clicked += Button_Pressed; + _lStickUp.Clicked += Button_Pressed; + _lStickDown.Clicked += Button_Pressed; + _lStickLeft.Clicked += Button_Pressed; + _lStickRight.Clicked += Button_Pressed; + _lStickButton.Clicked += Button_Pressed; + _dpadUp.Clicked += Button_Pressed; + _dpadDown.Clicked += Button_Pressed; + _dpadLeft.Clicked += Button_Pressed; + _dpadRight.Clicked += Button_Pressed; + _minus.Clicked += Button_Pressed; + _l.Clicked += Button_Pressed; + _zL.Clicked += Button_Pressed; + _lSl.Clicked += Button_Pressed; + _lSr.Clicked += Button_Pressed; + _rStickX.Clicked += Button_Pressed; + _rStickY.Clicked += Button_Pressed; + _rStickUp.Clicked += Button_Pressed; + _rStickDown.Clicked += Button_Pressed; + _rStickLeft.Clicked += Button_Pressed; + _rStickRight.Clicked += Button_Pressed; + _rStickButton.Clicked += Button_Pressed; + _a.Clicked += Button_Pressed; + _b.Clicked += Button_Pressed; + _x.Clicked += Button_Pressed; + _y.Clicked += Button_Pressed; + _plus.Clicked += Button_Pressed; + _r.Clicked += Button_Pressed; + _zR.Clicked += Button_Pressed; + _rSl.Clicked += Button_Pressed; + _rSr.Clicked += Button_Pressed; + + // Setup current values + UpdateInputDeviceList(); + SetAvailableOptions(); + + ClearValues(); + if (_inputDevice.ActiveId != null) SetCurrentValues(); + } + + private void UpdateInputDeviceList() + { + _inputDevice.RemoveAll(); + _inputDevice.Append("disabled", "Disabled"); + _inputDevice.SetActiveId("disabled"); + + for (int i = 0; i < 20; i++) + { + if (Keyboard.GetState(i).IsConnected) + _inputDevice.Append($"keyboard/{i}", $"Keyboard/{i}"); + + if (GamePad.GetState(i).IsConnected) + _inputDevice.Append($"controller/{i}", $"Controller/{i} ({GamePad.GetName(i)})"); + } + + switch (_inputConfig) + { + case KeyboardConfig keyboard: + _inputDevice.SetActiveId($"keyboard/{keyboard.Index}"); + break; + case ControllerConfig controller: + _inputDevice.SetActiveId($"controller/{controller.Index}"); + break; + } + } + + private void SetAvailableOptions() + { + if (_inputDevice.ActiveId != null && _inputDevice.ActiveId.StartsWith("keyboard")) + { + this.ShowAll(); + _leftStickController.Hide(); + _rightStickController.Hide(); + _deadZoneLeftBox.Hide(); + _deadZoneRightBox.Hide(); + _triggerThresholdBox.Hide(); + } + else if (_inputDevice.ActiveId != null && _inputDevice.ActiveId.StartsWith("controller")) + { + this.ShowAll(); + _leftStickKeyboard.Hide(); + _rightStickKeyboard.Hide(); + } + else + { + _settingsBox.Hide(); + } + + ClearValues(); + } + + private void SetCurrentValues() + { + SetControllerSpecificFields(); + + SetProfiles(); + + if (_inputDevice.ActiveId.StartsWith("keyboard") && _inputConfig is KeyboardConfig) + { + SetValues(_inputConfig); + } + else if (_inputDevice.ActiveId.StartsWith("controller") && _inputConfig is ControllerConfig) + { + SetValues(_inputConfig); + } + } + + private void SetControllerSpecificFields() + { + _leftSideTriggerBox.Hide(); + _rightSideTriggerBox.Hide(); + + switch (_controllerType.ActiveId) + { + case "JoyconLeft": + _leftSideTriggerBox.Show(); + break; + case "JoyconRight": + _rightSideTriggerBox.Show(); + break; + } + + switch (_controllerType.ActiveId) + { + case "ProController": + _controllerImage.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.ProCon.svg", 400, 400); + break; + case "JoyconLeft": + _controllerImage.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.JoyConLeft.svg", 400, 400); + break; + case "JoyconRight": + _controllerImage.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.JoyConRight.svg", 400, 400); + break; + default: + _controllerImage.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.JoyConPair.svg", 400, 400); + break; + } + } + + private void ClearValues() + { + _lStickX.Label = "Unbound"; + _lStickY.Label = "Unbound"; + _lStickUp.Label = "Unbound"; + _lStickDown.Label = "Unbound"; + _lStickLeft.Label = "Unbound"; + _lStickRight.Label = "Unbound"; + _lStickButton.Label = "Unbound"; + _dpadUp.Label = "Unbound"; + _dpadDown.Label = "Unbound"; + _dpadLeft.Label = "Unbound"; + _dpadRight.Label = "Unbound"; + _minus.Label = "Unbound"; + _l.Label = "Unbound"; + _zL.Label = "Unbound"; + _lSl.Label = "Unbound"; + _lSr.Label = "Unbound"; + _rStickX.Label = "Unbound"; + _rStickY.Label = "Unbound"; + _rStickUp.Label = "Unbound"; + _rStickDown.Label = "Unbound"; + _rStickLeft.Label = "Unbound"; + _rStickRight.Label = "Unbound"; + _rStickButton.Label = "Unbound"; + _a.Label = "Unbound"; + _b.Label = "Unbound"; + _x.Label = "Unbound"; + _y.Label = "Unbound"; + _plus.Label = "Unbound"; + _r.Label = "Unbound"; + _zR.Label = "Unbound"; + _rSl.Label = "Unbound"; + _rSr.Label = "Unbound"; + _controllerDeadzoneLeft.Value = 0; + _controllerDeadzoneRight.Value = 0; + _controllerTriggerThreshold.Value = 0; + } + + private void SetValues(InputConfig config) + { + switch (config) + { + case KeyboardConfig keyboardConfig: + _controllerType.SetActiveId(keyboardConfig.ControllerType.ToString()); + + _lStickUp.Label = keyboardConfig.LeftJoycon.StickUp.ToString(); + _lStickDown.Label = keyboardConfig.LeftJoycon.StickDown.ToString(); + _lStickLeft.Label = keyboardConfig.LeftJoycon.StickLeft.ToString(); + _lStickRight.Label = keyboardConfig.LeftJoycon.StickRight.ToString(); + _lStickButton.Label = keyboardConfig.LeftJoycon.StickButton.ToString(); + _dpadUp.Label = keyboardConfig.LeftJoycon.DPadUp.ToString(); + _dpadDown.Label = keyboardConfig.LeftJoycon.DPadDown.ToString(); + _dpadLeft.Label = keyboardConfig.LeftJoycon.DPadLeft.ToString(); + _dpadRight.Label = keyboardConfig.LeftJoycon.DPadRight.ToString(); + _minus.Label = keyboardConfig.LeftJoycon.ButtonMinus.ToString(); + _l.Label = keyboardConfig.LeftJoycon.ButtonL.ToString(); + _zL.Label = keyboardConfig.LeftJoycon.ButtonZl.ToString(); + _lSl.Label = keyboardConfig.LeftJoycon.ButtonSl.ToString(); + _lSr.Label = keyboardConfig.LeftJoycon.ButtonSr.ToString(); + _rStickUp.Label = keyboardConfig.RightJoycon.StickUp.ToString(); + _rStickDown.Label = keyboardConfig.RightJoycon.StickDown.ToString(); + _rStickLeft.Label = keyboardConfig.RightJoycon.StickLeft.ToString(); + _rStickRight.Label = keyboardConfig.RightJoycon.StickRight.ToString(); + _rStickButton.Label = keyboardConfig.RightJoycon.StickButton.ToString(); + _a.Label = keyboardConfig.RightJoycon.ButtonA.ToString(); + _b.Label = keyboardConfig.RightJoycon.ButtonB.ToString(); + _x.Label = keyboardConfig.RightJoycon.ButtonX.ToString(); + _y.Label = keyboardConfig.RightJoycon.ButtonY.ToString(); + _plus.Label = keyboardConfig.RightJoycon.ButtonPlus.ToString(); + _r.Label = keyboardConfig.RightJoycon.ButtonR.ToString(); + _zR.Label = keyboardConfig.RightJoycon.ButtonZr.ToString(); + _rSl.Label = keyboardConfig.RightJoycon.ButtonSl.ToString(); + _rSr.Label = keyboardConfig.RightJoycon.ButtonSr.ToString(); + break; + case ControllerConfig controllerConfig: + _controllerType.SetActiveId(controllerConfig.ControllerType.ToString()); + + _lStickX.Label = controllerConfig.LeftJoycon.StickX.ToString(); + _invertLStickX.Active = controllerConfig.LeftJoycon.InvertStickX; + _lStickY.Label = controllerConfig.LeftJoycon.StickY.ToString(); + _invertLStickY.Active = controllerConfig.LeftJoycon.InvertStickY; + _lStickButton.Label = controllerConfig.LeftJoycon.StickButton.ToString(); + _dpadUp.Label = controllerConfig.LeftJoycon.DPadUp.ToString(); + _dpadDown.Label = controllerConfig.LeftJoycon.DPadDown.ToString(); + _dpadLeft.Label = controllerConfig.LeftJoycon.DPadLeft.ToString(); + _dpadRight.Label = controllerConfig.LeftJoycon.DPadRight.ToString(); + _minus.Label = controllerConfig.LeftJoycon.ButtonMinus.ToString(); + _l.Label = controllerConfig.LeftJoycon.ButtonL.ToString(); + _zL.Label = controllerConfig.LeftJoycon.ButtonZl.ToString(); + _lSl.Label = controllerConfig.LeftJoycon.ButtonSl.ToString(); + _lSr.Label = controllerConfig.LeftJoycon.ButtonSr.ToString(); + _rStickX.Label = controllerConfig.RightJoycon.StickX.ToString(); + _invertRStickX.Active = controllerConfig.RightJoycon.InvertStickX; + _rStickY.Label = controllerConfig.RightJoycon.StickY.ToString(); + _invertRStickY.Active = controllerConfig.RightJoycon.InvertStickY; + _rStickButton.Label = controllerConfig.RightJoycon.StickButton.ToString(); + _a.Label = controllerConfig.RightJoycon.ButtonA.ToString(); + _b.Label = controllerConfig.RightJoycon.ButtonB.ToString(); + _x.Label = controllerConfig.RightJoycon.ButtonX.ToString(); + _y.Label = controllerConfig.RightJoycon.ButtonY.ToString(); + _plus.Label = controllerConfig.RightJoycon.ButtonPlus.ToString(); + _r.Label = controllerConfig.RightJoycon.ButtonR.ToString(); + _zR.Label = controllerConfig.RightJoycon.ButtonZr.ToString(); + _rSl.Label = controllerConfig.RightJoycon.ButtonSl.ToString(); + _rSr.Label = controllerConfig.RightJoycon.ButtonSr.ToString(); + _controllerDeadzoneLeft.Value = controllerConfig.DeadzoneLeft; + _controllerDeadzoneRight.Value = controllerConfig.DeadzoneRight; + _controllerTriggerThreshold.Value = controllerConfig.TriggerThreshold; + break; + } + } + + private InputConfig GetValues() + { + if (_inputDevice.ActiveId.StartsWith("keyboard")) + { + Enum.TryParse(_lStickUp.Label, out Key lStickUp); + Enum.TryParse(_lStickDown.Label, out Key lStickDown); + Enum.TryParse(_lStickLeft.Label, out Key lStickLeft); + Enum.TryParse(_lStickRight.Label, out Key lStickRight); + Enum.TryParse(_lStickButton.Label, out Key lStickButton); + Enum.TryParse(_dpadUp.Label, out Key lDPadUp); + Enum.TryParse(_dpadDown.Label, out Key lDPadDown); + Enum.TryParse(_dpadLeft.Label, out Key lDPadLeft); + Enum.TryParse(_dpadRight.Label, out Key lDPadRight); + Enum.TryParse(_minus.Label, out Key lButtonMinus); + Enum.TryParse(_l.Label, out Key lButtonL); + Enum.TryParse(_zL.Label, out Key lButtonZl); + Enum.TryParse(_lSl.Label, out Key lButtonSl); + Enum.TryParse(_lSr.Label, out Key lButtonSr); + + Enum.TryParse(_rStickUp.Label, out Key rStickUp); + Enum.TryParse(_rStickDown.Label, out Key rStickDown); + Enum.TryParse(_rStickLeft.Label, out Key rStickLeft); + Enum.TryParse(_rStickRight.Label, out Key rStickRight); + Enum.TryParse(_rStickButton.Label, out Key rStickButton); + Enum.TryParse(_a.Label, out Key rButtonA); + Enum.TryParse(_b.Label, out Key rButtonB); + Enum.TryParse(_x.Label, out Key rButtonX); + Enum.TryParse(_y.Label, out Key rButtonY); + Enum.TryParse(_plus.Label, out Key rButtonPlus); + Enum.TryParse(_r.Label, out Key rButtonR); + Enum.TryParse(_zR.Label, out Key rButtonZr); + Enum.TryParse(_rSl.Label, out Key rButtonSl); + Enum.TryParse(_rSr.Label, out Key rButtonSr); + + return new KeyboardConfig + { + Index = int.Parse(_inputDevice.ActiveId.Split("/")[1]), + ControllerType = Enum.Parse<ControllerType>(_controllerType.ActiveId), + PlayerIndex = _playerIndex, + LeftJoycon = new NpadKeyboardLeft + { + StickUp = lStickUp, + StickDown = lStickDown, + StickLeft = lStickLeft, + StickRight = lStickRight, + StickButton = lStickButton, + DPadUp = lDPadUp, + DPadDown = lDPadDown, + DPadLeft = lDPadLeft, + DPadRight = lDPadRight, + ButtonMinus = lButtonMinus, + ButtonL = lButtonL, + ButtonZl = lButtonZl, + ButtonSl = lButtonSl, + ButtonSr = lButtonSr + }, + RightJoycon = new NpadKeyboardRight + { + StickUp = rStickUp, + StickDown = rStickDown, + StickLeft = rStickLeft, + StickRight = rStickRight, + StickButton = rStickButton, + ButtonA = rButtonA, + ButtonB = rButtonB, + ButtonX = rButtonX, + ButtonY = rButtonY, + ButtonPlus = rButtonPlus, + ButtonR = rButtonR, + ButtonZr = rButtonZr, + ButtonSl = rButtonSl, + ButtonSr = rButtonSr + }, + Hotkeys = new KeyboardHotkeys + { + ToggleVsync = Key.Tab //TODO: Make this an option in the GUI + } + }; + } + + if (_inputDevice.ActiveId.StartsWith("controller")) + { + Enum.TryParse(_lStickX.Label, out ControllerInputId lStickX); + Enum.TryParse(_lStickY.Label, out ControllerInputId lStickY); + Enum.TryParse(_lStickButton.Label, out ControllerInputId lStickButton); + Enum.TryParse(_minus.Label, out ControllerInputId lButtonMinus); + Enum.TryParse(_l.Label, out ControllerInputId lButtonL); + Enum.TryParse(_zL.Label, out ControllerInputId lButtonZl); + Enum.TryParse(_lSl.Label, out ControllerInputId lButtonSl); + Enum.TryParse(_lSr.Label, out ControllerInputId lButtonSr); + Enum.TryParse(_dpadUp.Label, out ControllerInputId lDPadUp); + Enum.TryParse(_dpadDown.Label, out ControllerInputId lDPadDown); + Enum.TryParse(_dpadLeft.Label, out ControllerInputId lDPadLeft); + Enum.TryParse(_dpadRight.Label, out ControllerInputId lDPadRight); + + Enum.TryParse(_rStickX.Label, out ControllerInputId rStickX); + Enum.TryParse(_rStickY.Label, out ControllerInputId rStickY); + Enum.TryParse(_rStickButton.Label, out ControllerInputId rStickButton); + Enum.TryParse(_a.Label, out ControllerInputId rButtonA); + Enum.TryParse(_b.Label, out ControllerInputId rButtonB); + Enum.TryParse(_x.Label, out ControllerInputId rButtonX); + Enum.TryParse(_y.Label, out ControllerInputId rButtonY); + Enum.TryParse(_plus.Label, out ControllerInputId rButtonPlus); + Enum.TryParse(_r.Label, out ControllerInputId rButtonR); + Enum.TryParse(_zR.Label, out ControllerInputId rButtonZr); + Enum.TryParse(_rSl.Label, out ControllerInputId rButtonSl); + Enum.TryParse(_rSr.Label, out ControllerInputId rButtonSr); + + return new ControllerConfig + { + Index = int.Parse(_inputDevice.ActiveId.Split("/")[1]), + ControllerType = Enum.Parse<ControllerType>(_controllerType.ActiveId), + PlayerIndex = _playerIndex, + DeadzoneLeft = (float)_controllerDeadzoneLeft.Value, + DeadzoneRight = (float)_controllerDeadzoneRight.Value, + TriggerThreshold = (float)_controllerTriggerThreshold.Value, + LeftJoycon = new NpadControllerLeft + { + InvertStickX = _invertLStickX.Active, + StickX = lStickX, + InvertStickY = _invertLStickY.Active, + StickY = lStickY, + StickButton = lStickButton, + ButtonMinus = lButtonMinus, + ButtonL = lButtonL, + ButtonZl = lButtonZl, + ButtonSl = lButtonSl, + ButtonSr = lButtonSr, + DPadUp = lDPadUp, + DPadDown = lDPadDown, + DPadLeft = lDPadLeft, + DPadRight = lDPadRight + }, + RightJoycon = new NpadControllerRight + { + InvertStickX = _invertRStickX.Active, + StickX = rStickX, + InvertStickY = _invertRStickY.Active, + StickY = rStickY, + StickButton = rStickButton, + ButtonA = rButtonA, + ButtonB = rButtonB, + ButtonX = rButtonX, + ButtonY = rButtonY, + ButtonPlus = rButtonPlus, + ButtonR = rButtonR, + ButtonZr = rButtonZr, + ButtonSl = rButtonSl, + ButtonSr = rButtonSr + } + }; + } + + if (!_inputDevice.ActiveId.StartsWith("disabled")) + { + GtkDialog.CreateErrorDialog("Some fields entered where invalid and therefore your config was not saved."); + } + + return null; + } + + private static bool IsAnyKeyPressed(out Key pressedKey, int index = 0) + { + KeyboardState keyboardState = Keyboard.GetState(index); + + foreach (Key key in Enum.GetValues(typeof(Key))) + { + if (keyboardState.IsKeyDown((OpenTK.Input.Key)key)) + { + pressedKey = key; + + return true; + } + } + + pressedKey = Key.Unbound; + + return false; + } + + private static bool IsAnyButtonPressed(out ControllerInputId pressedButton, int index, double triggerThreshold) + { + JoystickState joystickState = Joystick.GetState(index); + JoystickCapabilities joystickCapabilities = Joystick.GetCapabilities(index); + + //Buttons + for (int i = 0; i != joystickCapabilities.ButtonCount; i++) + { + if (joystickState.IsButtonDown(i)) + { + Enum.TryParse($"Button{i}", out pressedButton); + + return true; + } + } + + //Axis + for (int i = 0; i != joystickCapabilities.AxisCount; i++) + { + if (joystickState.GetAxis(i) > 0.5f && joystickState.GetAxis(i) > triggerThreshold) + { + Enum.TryParse($"Axis{i}", out pressedButton); + + return true; + } + } + + //Hats + for (int i = 0; i != joystickCapabilities.HatCount; i++) + { + JoystickHatState hatState = joystickState.GetHat((JoystickHat)i); + string pos = null; + + if (hatState.IsUp) pos = "Up"; + if (hatState.IsDown) pos = "Down"; + if (hatState.IsLeft) pos = "Left"; + if (hatState.IsRight) pos = "Right"; + if (pos == null) continue; + + Enum.TryParse($"Hat{i}{pos}", out pressedButton); + + return true; + } + + pressedButton = ControllerInputId.Unbound; + + return false; + } + + private string GetProfileBasePath() + { + string path = System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "profiles"); + + if (_inputDevice.ActiveId.StartsWith("keyboard")) + { + path = System.IO.Path.Combine(path, "keyboard"); + } + else if (_inputDevice.ActiveId.StartsWith("controller")) + { + path = System.IO.Path.Combine(path, "controller"); + } + + return path; + } + + //Events + private void InputDevice_Changed(object sender, EventArgs args) + { + SetAvailableOptions(); + SetControllerSpecificFields(); + + if (_inputDevice.ActiveId != null) SetProfiles(); + } + + private void Controller_Changed(object sender, EventArgs args) + { + SetControllerSpecificFields(); + } + + private void RefreshInputDevicesButton_Pressed(object sender, EventArgs args) + { + UpdateInputDeviceList(); + + _refreshInputDevicesButton.SetStateFlags(0, true); + } + + private void Button_Pressed(object sender, EventArgs args) + { + if (_isWaitingForInput) + { + return; + } + + _isWaitingForInput = true; + + Thread inputThread = new Thread(() => + { + Button button = (ToggleButton)sender; + + if (_inputDevice.ActiveId.StartsWith("keyboard")) + { + Key pressedKey; + + int index = int.Parse(_inputDevice.ActiveId.Split("/")[1]); + while (!IsAnyKeyPressed(out pressedKey, index)) + { + if (Mouse.GetState().IsAnyButtonDown || Keyboard.GetState().IsKeyDown(OpenTK.Input.Key.Escape)) + { + Application.Invoke(delegate + { + button.SetStateFlags(0, true); + }); + + _isWaitingForInput = false; + + return; + } + } + + Application.Invoke(delegate + { + button.Label = pressedKey.ToString(); + button.SetStateFlags(0, true); + }); + } + else if (_inputDevice.ActiveId.StartsWith("controller")) + { + ControllerInputId pressedButton; + + int index = int.Parse(_inputDevice.ActiveId.Split("/")[1]); + while (!IsAnyButtonPressed(out pressedButton, index, _controllerTriggerThreshold.Value)) + { + if (Mouse.GetState().IsAnyButtonDown || Keyboard.GetState().IsAnyKeyDown) + { + Application.Invoke(delegate + { + button.SetStateFlags(0, true); + }); + + _isWaitingForInput = false; + + return; + } + } + + Application.Invoke(delegate + { + button.Label = pressedButton.ToString(); + button.SetStateFlags(0, true); + }); + } + + _isWaitingForInput = false; + }); + inputThread.Name = "GUI.InputThread"; + inputThread.IsBackground = true; + inputThread.Start(); + } + + private void SetProfiles() + { + string basePath = GetProfileBasePath(); + + if (!Directory.Exists(basePath)) + { + Directory.CreateDirectory(basePath); + } + + _profile.RemoveAll(); + _profile.Append("default", "Default"); + + foreach (string profile in Directory.GetFiles(basePath, "*.*", SearchOption.AllDirectories)) + { + _profile.Append(System.IO.Path.GetFileName(profile), System.IO.Path.GetFileNameWithoutExtension(profile)); + } + } + + private void ProfileLoad_Activated(object sender, EventArgs args) + { + ((ToggleButton)sender).SetStateFlags(0, true); + + if (_inputDevice.ActiveId == "disabled" || _profile.ActiveId == null) return; + + InputConfig config = null; + int pos = _profile.Active; + + if (_profile.ActiveId == "default") + { + if (_inputDevice.ActiveId.StartsWith("keyboard")) + { + config = new KeyboardConfig + { + Index = 0, + ControllerType = ControllerType.JoyconPair, + LeftJoycon = new NpadKeyboardLeft + { + StickUp = Key.W, + StickDown = Key.S, + StickLeft = Key.A, + StickRight = Key.D, + StickButton = Key.F, + DPadUp = Key.Up, + DPadDown = Key.Down, + DPadLeft = Key.Left, + DPadRight = Key.Right, + ButtonMinus = Key.Minus, + ButtonL = Key.E, + ButtonZl = Key.Q, + ButtonSl = Key.Unbound, + ButtonSr = Key.Unbound + }, + RightJoycon = new NpadKeyboardRight + { + StickUp = Key.I, + StickDown = Key.K, + StickLeft = Key.J, + StickRight = Key.L, + StickButton = Key.H, + ButtonA = Key.Z, + ButtonB = Key.X, + ButtonX = Key.C, + ButtonY = Key.V, + ButtonPlus = Key.Plus, + ButtonR = Key.U, + ButtonZr = Key.O, + ButtonSl = Key.Unbound, + ButtonSr = Key.Unbound + }, + Hotkeys = new KeyboardHotkeys + { + ToggleVsync = Key.Tab + } + }; + } + else if (_inputDevice.ActiveId.StartsWith("controller")) + { + config = new ControllerConfig + { + Index = 0, + ControllerType = ControllerType.ProController, + DeadzoneLeft = 0.1f, + DeadzoneRight = 0.1f, + TriggerThreshold = 0.5f, + LeftJoycon = new NpadControllerLeft + { + StickX = ControllerInputId.Axis0, + StickY = ControllerInputId.Axis1, + StickButton = ControllerInputId.Button8, + DPadUp = ControllerInputId.Hat0Up, + DPadDown = ControllerInputId.Hat0Down, + DPadLeft = ControllerInputId.Hat0Left, + DPadRight = ControllerInputId.Hat0Right, + ButtonMinus = ControllerInputId.Button6, + ButtonL = ControllerInputId.Button4, + ButtonZl = ControllerInputId.Axis2, + ButtonSl = ControllerInputId.Unbound, + ButtonSr = ControllerInputId.Unbound, + InvertStickX = false, + InvertStickY = false + }, + RightJoycon = new NpadControllerRight + { + StickX = ControllerInputId.Axis3, + StickY = ControllerInputId.Axis4, + StickButton = ControllerInputId.Button9, + ButtonA = ControllerInputId.Button1, + ButtonB = ControllerInputId.Button0, + ButtonX = ControllerInputId.Button3, + ButtonY = ControllerInputId.Button2, + ButtonPlus = ControllerInputId.Button7, + ButtonR = ControllerInputId.Button5, + ButtonZr = ControllerInputId.Axis5, + ButtonSl = ControllerInputId.Unbound, + ButtonSr = ControllerInputId.Unbound, + InvertStickX = false, + InvertStickY = false + } + }; + } + } + else + { + string path = System.IO.Path.Combine(GetProfileBasePath(), _profile.ActiveId); + + if (!File.Exists(path)) + { + if (pos >= 0) + { + _profile.Remove(pos); + } + + return; + } + + using (Stream stream = File.OpenRead(path)) + { + try + { + config = JsonHelper.Deserialize<ControllerConfig>(stream); + } + catch (ArgumentException) + { + try + { + config = JsonHelper.Deserialize<KeyboardConfig>(stream); + } + catch { } + } + } + } + + SetValues(config); + } + + private void ProfileAdd_Activated(object sender, EventArgs args) + { + ((ToggleButton)sender).SetStateFlags(0, true); + + if (_inputDevice.ActiveId == "disabled") return; + + InputConfig inputConfig = GetValues(); + ProfileDialog profileDialog = new ProfileDialog(); + + if (inputConfig == null) return; + + if (profileDialog.Run() == (int)ResponseType.Ok) + { + string path = System.IO.Path.Combine(GetProfileBasePath(), profileDialog.FileName); + string jsonString; + + if (inputConfig is KeyboardConfig keyboardConfig) + { + jsonString = JsonHelper.Serialize(keyboardConfig, true); + } + else + { + jsonString = JsonHelper.Serialize(inputConfig as ControllerConfig, true); + } + + File.WriteAllText(path, jsonString); + } + + profileDialog.Dispose(); + + SetProfiles(); + } + + private void ProfileRemove_Activated(object sender, EventArgs args) + { + ((ToggleButton) sender).SetStateFlags(0, true); + + if (_inputDevice.ActiveId == "disabled" || _profile.ActiveId == "default" || _profile.ActiveId == null) return; + + MessageDialog confirmDialog = GtkDialog.CreateConfirmationDialog("Deleting Profile", "This action is irreversible, are your sure you want to continue?"); + + if (confirmDialog.Run() == (int)ResponseType.Yes) + { + string path = System.IO.Path.Combine(GetProfileBasePath(), _profile.ActiveId); + + if (File.Exists(path)) + { + File.Delete(path); + } + + SetProfiles(); + } + } + + private void SaveToggle_Activated(object sender, EventArgs args) + { + InputConfig inputConfig = GetValues(); + + if (_inputConfig == null && inputConfig != null) + { + ConfigurationState.Instance.Hid.InputConfig.Value.Add(inputConfig); + } + else + { + if (_inputDevice.ActiveId == "disabled") + { + ConfigurationState.Instance.Hid.InputConfig.Value.Remove(_inputConfig); + } + else if (inputConfig != null) + { + int index = ConfigurationState.Instance.Hid.InputConfig.Value.IndexOf(_inputConfig); + + ConfigurationState.Instance.Hid.InputConfig.Value[index] = inputConfig; + } + } + + Dispose(); + } + + private void CloseToggle_Activated(object sender, EventArgs args) + { + Dispose(); + } + } +}
\ No newline at end of file diff --git a/Ryujinx/Ui/ControllerWindow.glade b/Ryujinx/Ui/ControllerWindow.glade new file mode 100644 index 00000000..2b780f13 --- /dev/null +++ b/Ryujinx/Ui/ControllerWindow.glade @@ -0,0 +1,1732 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.22.1 --> +<interface> + <requires lib="gtk+" version="3.20"/> + <object class="GtkAdjustment" id="_controllerDeadzoneLeft"> + <property name="upper">1</property> + <property name="value">0.050000000000000003</property> + <property name="step_increment">0.01</property> + <property name="page_increment">0.10000000000000001</property> + </object> + <object class="GtkAdjustment" id="_controllerDeadzoneRight"> + <property name="upper">1</property> + <property name="value">0.050000000000000003</property> + <property name="step_increment">0.01</property> + <property name="page_increment">0.10000000000000001</property> + </object> + <object class="GtkAdjustment" id="_controllerTriggerThreshold"> + <property name="upper">1</property> + <property name="value">0.5</property> + <property name="step_increment">0.01</property> + <property name="page_increment">0.10000000000000001</property> + </object> + <object class="GtkWindow" id="_controllerWin"> + <property name="can_focus">False</property> + <property name="title" translatable="yes">Ryujinx - Controller Settings</property> + <property name="modal">True</property> + <property name="window_position">center</property> + <property name="default_width">1100</property> + <property name="default_height">600</property> + <child> + <placeholder/> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkBox" id="HeadBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">10</property> + <property name="margin_top">10</property> + <property name="margin_bottom">10</property> + <child> + <object class="GtkBox" id="DeviceBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_right">5</property> + <property name="label" translatable="yes">Input Device</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="_inputDevice"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="active">0</property> + <property name="active_id">disabled</property> + <items> + <item id="disabled" translatable="yes">Disabled</item> + </items> + <signal name="changed" handler="InputDevice_Changed" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_refreshInputDevicesButton"> + <property name="label" translatable="yes">Refresh</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">5</property> + <signal name="toggled" handler="RefreshInputDevicesButton_Pressed" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="ControllerTypeBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">20</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="tooltip_text" translatable="yes">The controller's type</property> + <property name="halign">center</property> + <property name="margin_right">5</property> + <property name="label" translatable="yes">Controller Type:</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="_controllerType"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="tooltip_text" translatable="yes">The controller's type</property> + <property name="active">0</property> + <items> + <item id="Handheld" translatable="yes">Handheld</item> + <item id="ProController" translatable="yes">Pro Controller</item> + <item id="JoyconPair" translatable="yes">Paired Joycons</item> + <item id="JoyconLeft" translatable="yes">Left Joycon</item> + <item id="JoyconRight" translatable="yes">Right Joycon</item> + </items> + <signal name="changed" handler="Controller_Changed" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="ProfileBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">20</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_right">5</property> + <property name="label" translatable="yes">Profile:</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="_profile"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_right">5</property> + <property name="active">0</property> + <property name="active_id">default</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkToggleButton"> + <property name="label" translatable="yes">Load</property> + <property name="width_request">60</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_right">5</property> + <signal name="toggled" handler="ProfileLoad_Activated" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkToggleButton"> + <property name="label" translatable="yes">Add</property> + <property name="width_request">60</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_right">5</property> + <signal name="toggled" handler="ProfileAdd_Activated" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkToggleButton"> + <property name="label" translatable="yes">Remove</property> + <property name="width_request">60</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="toggled" handler="ProfileRemove_Activated" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="_settingsBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">10</property> + <property name="margin_top">5</property> + <child> + <object class="GtkBox" id="ButtonsBox"> + <property name="width_request">156</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_right">10</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">5</property> + <property name="margin_bottom">5</property> + <property name="label" translatable="yes">Buttons</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">3</property> + <property name="column_spacing">10</property> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">A</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">B</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">X</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Y</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_a"> + <property name="label" translatable="yes"> </property> + <property name="width_request">70</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_b"> + <property name="label" translatable="yes"> </property> + <property name="width_request">70</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_x"> + <property name="label" translatable="yes"> </property> + <property name="width_request">70</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_y"> + <property name="label" translatable="yes"> </property> + <property name="width_request">70</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">+</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">4</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">-</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">5</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_minus"> + <property name="label" translatable="yes"> </property> + <property name="width_request">70</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">5</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_plus"> + <property name="label" translatable="yes"> </property> + <property name="width_request">70</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">4</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="LeftStickBox"> + <property name="width_request">160</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">10</property> + <property name="margin_right">10</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">5</property> + <property name="margin_bottom">5</property> + <property name="label" translatable="yes">Left Stick</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_bottom">5</property> + <property name="row_spacing">3</property> + <property name="column_spacing">10</property> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">LStick Button</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_lStickButton"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="_leftStickKeyboard"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">3</property> + <property name="column_spacing">10</property> + <child> + <object class="GtkToggleButton" id="_lStickDown"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_lStickUp"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_lStickLeft"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_lStickRight"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">LStick Down</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">LStick Up</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">LStick Right</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">LStick Left</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="_leftStickController"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">3</property> + <property name="column_spacing">10</property> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">LStick Lt/Rt</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">LStick Up/Dn</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_lStickX"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_lStickY"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="_invertLStickX"> + <property name="label" translatable="yes">Invert</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="_invertLStickY"> + <property name="label" translatable="yes">Invert</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkBox" id="_deadZoneLeftBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">10</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="label" translatable="yes">Deadzone Left</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkScale"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="adjustment">_controllerDeadzoneLeft</property> + <property name="round_digits">2</property> + <property name="digits">2</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkBox" id="TriggerBox"> + <property name="width_request">150</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">10</property> + <property name="margin_right">10</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">5</property> + <property name="margin_bottom">5</property> + <property name="label" translatable="yes">Triggers</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">3</property> + <property name="column_spacing">10</property> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">L</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">R</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_l"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_r"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">ZL</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">ZR</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_zL"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_zR"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="_leftSideTriggerBox"> + <property name="name">_sideTriggerBox</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">5</property> + <property name="row_spacing">3</property> + <property name="column_spacing">10</property> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Left SL</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Left SR</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_lSl"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_lSr"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="_rightSideTriggerBox"> + <property name="name">_sideTriggerBox</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">5</property> + <property name="row_spacing">3</property> + <property name="column_spacing">10</property> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Right SL</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Right SR</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_rSl"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_rSr"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkBox" id="_triggerThresholdBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">10</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="margin_left">10</property> + <property name="label" translatable="yes">Trigger Threshold</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkScale"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="adjustment">_controllerTriggerThreshold</property> + <property name="round_digits">2</property> + <property name="digits">2</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">10</property> + <child> + <object class="GtkBox" id="DPadBox"> + <property name="width_request">156</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_right">10</property> + <property name="margin_top">10</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">5</property> + <property name="margin_bottom">5</property> + <property name="label" translatable="yes">Directional Pad</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">3</property> + <property name="column_spacing">10</property> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Dpad Up</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Dpad Down</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Dpad Left</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Dpad Right</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_dpadUp"> + <property name="label" translatable="yes"> </property> + <property name="width_request">70</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_dpadDown"> + <property name="label" translatable="yes"> </property> + <property name="width_request">70</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_dpadLeft"> + <property name="label" translatable="yes"> </property> + <property name="width_request">70</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_dpadRight"> + <property name="label" translatable="yes"> </property> + <property name="width_request">70</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="RightStickBox"> + <property name="width_request">160</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">10</property> + <property name="margin_right">10</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">5</property> + <property name="margin_bottom">5</property> + <property name="label" translatable="yes">Right Stick</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_bottom">5</property> + <property name="row_spacing">3</property> + <property name="column_spacing">10</property> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">RStick Button</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_rStickButton"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="_rightStickKeyboard"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">3</property> + <property name="column_spacing">10</property> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">RStick Up</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">RStick Down</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">RStick Left</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">RStick Right</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_rStickUp"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_rStickDown"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_rStickLeft"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_rStickRight"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="_rightStickController"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">3</property> + <property name="column_spacing">10</property> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">RStick Lt/Rt</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="width_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">RStick Up/Dn</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_rStickX"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_rStickY"> + <property name="label" translatable="yes"> </property> + <property name="width_request">65</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="_invertRStickX"> + <property name="label" translatable="yes">Invert</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="_invertRStickY"> + <property name="label" translatable="yes">Invert</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkBox" id="_deadZoneRightBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">10</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="label" translatable="yes">Deadzone Right</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkScale"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="adjustment">_controllerDeadzoneRight</property> + <property name="round_digits">2</property> + <property name="digits">2</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkImage" id="_controllerImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">10</property> + <property name="margin_right">20</property> + <property name="margin_top">5</property> + <property name="margin_bottom">5</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButtonBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_right">5</property> + <property name="margin_top">3</property> + <property name="margin_bottom">3</property> + <property name="layout_style">end</property> + <child> + <object class="GtkToggleButton" id="SaveToggle"> + <property name="label" translatable="yes">Save</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="toggled" handler="SaveToggle_Activated" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="CloseToggle"> + <property name="label" translatable="yes">Close</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">4</property> + <signal name="toggled" handler="CloseToggle_Activated" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> +</interface> diff --git a/Ryujinx/Ui/GLRenderer.cs b/Ryujinx/Ui/GLRenderer.cs index d266eefc..b37ab448 100644 --- a/Ryujinx/Ui/GLRenderer.cs +++ b/Ryujinx/Ui/GLRenderer.cs @@ -1,26 +1,24 @@ -using Gdk; +using Gdk; using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; using OpenTK.Input; -using OpenTK.Platform; using Ryujinx.Configuration; +using Ryujinx.Common.Configuration.Hid; using Ryujinx.Graphics.OpenGL; using Ryujinx.HLE; using Ryujinx.HLE.HOS.Services.Hid; -using Ryujinx.Ui; using System; using System.Collections.Generic; -using System.Text; using System.Threading; namespace Ryujinx.Ui { - public class GLRenderer : GLWidget + public class GlRenderer : GLWidget { - private const int SwitchPanelWidth = 1280; + private const int SwitchPanelWidth = 1280; private const int SwitchPanelHeight = 720; - private const int TargetFps = 60; + private const int TargetFps = 60; public ManualResetEvent WaitEvent { get; set; } @@ -32,7 +30,7 @@ namespace Ryujinx.Ui private double _mouseX; private double _mouseY; - private bool _mousePressed; + private bool _mousePressed; private bool _toggleFullscreen; @@ -46,11 +44,9 @@ namespace Ryujinx.Ui private Renderer _renderer; - private HotkeyButtons _prevHotkeyButtons = 0; + private HotkeyButtons _prevHotkeyButtons; - private Input.NpadController _primaryController; - - public GLRenderer(Switch device) + public GlRenderer(Switch device) : base (GetGraphicsMode(), 3, 3, GraphicsContextFlags.ForwardCompatible) @@ -59,8 +55,8 @@ namespace Ryujinx.Ui _device = device; - this.Initialized += GLRenderer_Initialized; - this.Destroyed += GLRenderer_Destroyed; + this.Initialized += GLRenderer_Initialized; + this.Destroyed += GLRenderer_Destroyed; this.ShuttingDown += GLRenderer_ShuttingDown; Initialize(); @@ -69,25 +65,18 @@ namespace Ryujinx.Ui _ticksPerFrame = System.Diagnostics.Stopwatch.Frequency / TargetFps; - _primaryController = new Input.NpadController(ConfigurationState.Instance.Hid.JoystickControls); - - AddEvents((int)(Gdk.EventMask.ButtonPressMask - | Gdk.EventMask.ButtonReleaseMask - | Gdk.EventMask.PointerMotionMask - | Gdk.EventMask.KeyPressMask - | Gdk.EventMask.KeyReleaseMask)); + AddEvents((int)(EventMask.ButtonPressMask + | EventMask.ButtonReleaseMask + | EventMask.PointerMotionMask + | EventMask.KeyPressMask + | EventMask.KeyReleaseMask)); this.Shown += Renderer_Shown; } private static GraphicsMode GetGraphicsMode() { - if (Environment.OSVersion.Platform == PlatformID.Unix) - { - return new GraphicsMode(new ColorFormat(24)); - } - - return new GraphicsMode(new ColorFormat()); + return Environment.OSVersion.Platform == PlatformID.Unix ? new GraphicsMode(new ColorFormat(24)) : new GraphicsMode(new ColorFormat()); } private void GLRenderer_ShuttingDown(object sender, EventArgs args) @@ -117,11 +106,11 @@ namespace Ryujinx.Ui public void HandleScreenState(KeyboardState keyboard) { - bool toggleFullscreen = keyboard.IsKeyDown(OpenTK.Input.Key.F11) + bool toggleFullscreen = keyboard.IsKeyDown(OpenTK.Input.Key.F11) || ((keyboard.IsKeyDown(OpenTK.Input.Key.AltLeft) || keyboard.IsKeyDown(OpenTK.Input.Key.AltRight)) && keyboard.IsKeyDown(OpenTK.Input.Key.Enter)) - || keyboard.IsKeyDown(OpenTK.Input.Key.Escape); + || keyboard.IsKeyDown(OpenTK.Input.Key.Escape); bool fullScreenToggled = ParentWindow.State.HasFlag(Gdk.WindowState.Fullscreen); @@ -165,7 +154,7 @@ namespace Ryujinx.Ui protected override bool OnConfigureEvent(EventConfigure evnt) { - var result = base.OnConfigureEvent(evnt); + bool result = base.OnConfigureEvent(evnt); Gdk.Monitor monitor = Display.GetMonitorAtWindow(Window); @@ -184,7 +173,7 @@ namespace Ryujinx.Ui Gtk.Window parent = this.Toplevel as Gtk.Window; - parent.FocusInEvent += Parent_FocusInEvent; + parent.FocusInEvent += Parent_FocusInEvent; parent.FocusOutEvent += Parent_FocusOutEvent; Gtk.Application.Invoke(delegate @@ -347,7 +336,7 @@ namespace Ryujinx.Ui _device.EnableDeviceVsync, $"Host: {_device.Statistics.GetSystemFrameRate():00.00} FPS", $"Game: {_device.Statistics.GetGameFrameRate():00.00} FPS", - $"GPU: {_renderer.GpuVendor}")); + $"GPU: {_renderer.GpuVendor}")); _ticks = Math.Min(_ticks - _ticksPerFrame, _ticksPerFrame); } @@ -382,83 +371,127 @@ namespace Ryujinx.Ui return false; } - HotkeyButtons currentHotkeyButtons = 0; - ControllerKeys currentButton = 0; - JoystickPosition leftJoystick; - JoystickPosition rightJoystick; - KeyboardInput? hidKeyboard = null; - - int leftJoystickDx = 0; - int leftJoystickDy = 0; - int rightJoystickDx = 0; - int rightJoystickDy = 0; - - // OpenTK always captures keyboard events, even if out of focus, so check if window is focused. if (IsFocused) { - KeyboardState keyboard = OpenTK.Input.Keyboard.GetState(); - Gtk.Application.Invoke(delegate { - HandleScreenState(keyboard); + HandleScreenState(OpenTK.Input.Keyboard.GetState()); }); + } - // Normal Input - currentHotkeyButtons = KeyboardControls.GetHotkeyButtons(ConfigurationState.Instance.Hid.KeyboardControls, keyboard); - currentButton = KeyboardControls.GetButtons(ConfigurationState.Instance.Hid.KeyboardControls, keyboard); + List<GamepadInput> gamepadInputs = new List<GamepadInput>(); - if (ConfigurationState.Instance.Hid.EnableKeyboard) + foreach (InputConfig inputConfig in ConfigurationState.Instance.Hid.InputConfig.Value) + { + ControllerKeys currentButton = 0; + JoystickPosition leftJoystick = new JoystickPosition(); + JoystickPosition rightJoystick = new JoystickPosition(); + KeyboardInput? hidKeyboard = null; + + int leftJoystickDx = 0; + int leftJoystickDy = 0; + int rightJoystickDx = 0; + int rightJoystickDy = 0; + + if (inputConfig is KeyboardConfig keyboardConfig) { - hidKeyboard = KeyboardControls.GetKeysDown(ConfigurationState.Instance.Hid.KeyboardControls, keyboard); - } + if (IsFocused) + { + // Keyboard Input + KeyboardController keyboardController = new KeyboardController(keyboardConfig); - (leftJoystickDx, leftJoystickDy) = KeyboardControls.GetLeftStick(ConfigurationState.Instance.Hid.KeyboardControls, keyboard); - (rightJoystickDx, rightJoystickDy) = KeyboardControls.GetRightStick(ConfigurationState.Instance.Hid.KeyboardControls, keyboard); - } + currentButton = keyboardController.GetButtons(); - if (!hidKeyboard.HasValue) - { - hidKeyboard = new KeyboardInput + (leftJoystickDx, leftJoystickDy) = keyboardController.GetLeftStick(); + (rightJoystickDx, rightJoystickDy) = keyboardController.GetRightStick(); + + leftJoystick = new JoystickPosition + { + Dx = leftJoystickDx, + Dy = leftJoystickDy + }; + + rightJoystick = new JoystickPosition + { + Dx = rightJoystickDx, + Dy = rightJoystickDy + }; + + if (ConfigurationState.Instance.Hid.EnableKeyboard) + { + hidKeyboard = keyboardController.GetKeysDown(); + } + + if (!hidKeyboard.HasValue) + { + hidKeyboard = new KeyboardInput + { + Modifier = 0, + Keys = new int[0x8] + }; + } + + if (ConfigurationState.Instance.Hid.EnableKeyboard) + { + _device.Hid.Keyboard.Update(hidKeyboard.Value); + } + + // Toggle vsync + HotkeyButtons currentHotkeyButtons = keyboardController.GetHotkeyButtons(); + + if (currentHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync) && + !_prevHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync)) + { + _device.EnableDeviceVsync = !_device.EnableDeviceVsync; + } + + _prevHotkeyButtons = currentHotkeyButtons; + } + } + else if (inputConfig is Common.Configuration.Hid.ControllerConfig controllerConfig) { - Modifier = 0, - Keys = new int[0x8] - }; - } + // Controller Input + JoystickController joystickController = new JoystickController(controllerConfig); - currentButton |= _primaryController.GetButtons(); + currentButton |= joystickController.GetButtons(); - // Keyboard has priority stick-wise - if (leftJoystickDx == 0 && leftJoystickDy == 0) - { - (leftJoystickDx, leftJoystickDy) = _primaryController.GetLeftStick(); - } + (leftJoystickDx, leftJoystickDy) = joystickController.GetLeftStick(); + (rightJoystickDx, rightJoystickDy) = joystickController.GetRightStick(); - if (rightJoystickDx == 0 && rightJoystickDy == 0) - { - (rightJoystickDx, rightJoystickDy) = _primaryController.GetRightStick(); - } + leftJoystick = new JoystickPosition + { + Dx = controllerConfig.LeftJoycon.InvertStickX ? -leftJoystickDx : leftJoystickDx, + Dy = controllerConfig.LeftJoycon.InvertStickY ? -leftJoystickDy : leftJoystickDy + }; - leftJoystick = new JoystickPosition - { - Dx = leftJoystickDx, - Dy = leftJoystickDy - }; + rightJoystick = new JoystickPosition + { + Dx = controllerConfig.RightJoycon.InvertStickX ? -rightJoystickDx : rightJoystickDx, + Dy = controllerConfig.RightJoycon.InvertStickY ? -rightJoystickDy : rightJoystickDy + }; + } - rightJoystick = new JoystickPosition - { - Dx = rightJoystickDx, - Dy = rightJoystickDy - }; + currentButton |= _device.Hid.UpdateStickButtons(leftJoystick, rightJoystick); + + gamepadInputs.Add(new GamepadInput + { + PlayerId = (HLE.HOS.Services.Hid.PlayerIndex)inputConfig.PlayerIndex, + Buttons = currentButton, + LStick = leftJoystick, + RStick = rightJoystick + }); + } - currentButton |= _device.Hid.UpdateStickButtons(leftJoystick, rightJoystick); + _device.Hid.Npads.SetGamepadsInput(gamepadInputs.ToArray()); + //Touchscreen bool hasTouch = false; // Get screen touch position from left mouse click // OpenTK always captures mouse events, even if out of focus, so check if window is focused. if (IsFocused && _mousePressed) { - int screenWidth = AllocatedWidth; + int screenWidth = AllocatedWidth; int screenHeight = AllocatedHeight; if (AllocatedWidth > (AllocatedHeight * SwitchPanelWidth) / SwitchPanelHeight) @@ -470,7 +503,7 @@ namespace Ryujinx.Ui screenHeight = (AllocatedWidth * SwitchPanelHeight) / SwitchPanelWidth; } - int startX = (AllocatedWidth - screenWidth) >> 1; + int startX = (AllocatedWidth - screenWidth) >> 1; int startY = (AllocatedHeight - screenHeight) >> 1; int endX = startX + screenWidth; @@ -496,7 +529,7 @@ namespace Ryujinx.Ui // Placeholder values till more data is acquired DiameterX = 10, DiameterY = 10, - Angle = 90 + Angle = 90 }; hasTouch = true; @@ -510,30 +543,8 @@ namespace Ryujinx.Ui _device.Hid.Touchscreen.Update(); } - if (ConfigurationState.Instance.Hid.EnableKeyboard && hidKeyboard.HasValue) - { - _device.Hid.Keyboard.Update(hidKeyboard.Value); - } - _device.Hid.DebugPad.Update(); - _device.Hid.Npads.SetGamepadsInput(new GamepadInput - { - PlayerId = PlayerIndex.Auto, - Buttons = currentButton, - LStick = leftJoystick, - RStick = rightJoystick - }); - - // Toggle vsync - if (currentHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync) && - !_prevHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync)) - { - _device.EnableDeviceVsync = !_device.EnableDeviceVsync; - } - - _prevHotkeyButtons = currentHotkeyButtons; - return true; } } diff --git a/Ryujinx/Ui/GtkDialog.cs b/Ryujinx/Ui/GtkDialog.cs index 698b8b7e..9a14f63d 100644 --- a/Ryujinx/Ui/GtkDialog.cs +++ b/Ryujinx/Ui/GtkDialog.cs @@ -3,33 +3,46 @@ using System.Reflection; namespace Ryujinx.Ui { - internal class GtkDialog + internal class GtkDialog : MessageDialog { internal static bool _isExitDialogOpen = false; - internal static void CreateDialog(string title, string text, string secondaryText) + private GtkDialog(string title, string mainText, string secondaryText, + MessageType messageType = MessageType.Other, ButtonsType buttonsType = ButtonsType.Ok) : base(null, DialogFlags.Modal, messageType, buttonsType, null) { - MessageDialog errorDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, null) - { - Title = title, - Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"), - Text = text, - SecondaryText = secondaryText, - WindowPosition = WindowPosition.Center - }; - errorDialog.SetSizeRequest(100, 20); - errorDialog.Run(); - errorDialog.Dispose(); + Title = title; + Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"); + Text = mainText; + SecondaryText = secondaryText; + WindowPosition = WindowPosition.Center; + Response += GtkDialog_Response; + + SetSizeRequest(100, 20); + } + + private void GtkDialog_Response(object sender, ResponseArgs args) + { + Dispose(); } - internal static void CreateWarningDialog(string text, string secondaryText) + internal static void CreateInfoDialog(string title, string mainText, string secondaryText) { - CreateDialog("Ryujinx - Warning", text, secondaryText); + new GtkDialog(title, mainText, secondaryText, MessageType.Info).Run(); + } + + internal static void CreateWarningDialog(string mainText, string secondaryText) + { + new GtkDialog("Ryujinx - Warning", mainText, secondaryText, MessageType.Warning).Run(); } internal static void CreateErrorDialog(string errorMessage) { - CreateDialog("Ryujinx - Error", "Ryujinx has encountered an error", errorMessage); + new GtkDialog("Ryujinx - Error", "Ryujinx has encountered an error", errorMessage, MessageType.Error).Run(); + } + + internal static MessageDialog CreateConfirmationDialog(string mainText, string secondaryText = "") + { + return new GtkDialog("Ryujinx - Confirmation", mainText, secondaryText, MessageType.Question, ButtonsType.YesNo); } internal static bool CreateExitDialog() @@ -40,27 +53,11 @@ namespace Ryujinx.Ui } _isExitDialogOpen = true; - - MessageDialog messageDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Question, ButtonsType.OkCancel, null) - { - Title = "Ryujinx - Exit", - Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"), - Text = "Are you sure you want to stop emulation?", - SecondaryText = "All unsaved data will be lost", - WindowPosition = WindowPosition.Center - }; - - messageDialog.SetSizeRequest(100, 20); - ResponseType res = (ResponseType)messageDialog.Run(); - messageDialog.Dispose(); + ResponseType res = (ResponseType)new GtkDialog("Ryujinx - Exit", "Are you sure you want to stop emulation?", + "All unsaved data will be lost", MessageType.Question, ButtonsType.YesNo).Run(); _isExitDialogOpen = false; - if (res == ResponseType.Ok) - { - return true; - } - - return false; + return res == ResponseType.Yes; } } -} +}
\ No newline at end of file diff --git a/Ryujinx/Ui/JoystickController.cs b/Ryujinx/Ui/JoystickController.cs new file mode 100644 index 00000000..f5d7450a --- /dev/null +++ b/Ryujinx/Ui/JoystickController.cs @@ -0,0 +1,149 @@ +using OpenTK; +using OpenTK.Input; +using Ryujinx.Common.Configuration.Hid; +using Ryujinx.HLE.HOS.Services.Hid; +using System; + +using ControllerConfig = Ryujinx.Common.Configuration.Hid.ControllerConfig; + +namespace Ryujinx.Ui +{ + public class JoystickController + { + private readonly ControllerConfig _config; + + // NOTE: This should be initialized AFTER GTK for compat reasons with OpenTK SDL2 backend and GTK on Linux. + // BODY: Usage of Joystick.GetState must be defer to after GTK full initialization. Otherwise, GTK will segfault because SDL2 was already init *sighs* + public JoystickController(ControllerConfig config) + { + _config = config; + } + + private bool IsEnabled() + { + return Joystick.GetState(_config.Index).IsConnected; + } + + public ControllerKeys GetButtons() + { + if (!IsEnabled()) + { + return 0; + } + + JoystickState joystickState = Joystick.GetState(_config.Index); + + ControllerKeys buttons = 0; + + if (IsActivated(joystickState, _config.LeftJoycon.DPadUp)) buttons |= ControllerKeys.DpadUp; + if (IsActivated(joystickState, _config.LeftJoycon.DPadDown)) buttons |= ControllerKeys.DpadDown; + if (IsActivated(joystickState, _config.LeftJoycon.DPadLeft)) buttons |= ControllerKeys.DpadLeft; + if (IsActivated(joystickState, _config.LeftJoycon.DPadRight)) buttons |= ControllerKeys.DpadRight; + if (IsActivated(joystickState, _config.LeftJoycon.StickButton)) buttons |= ControllerKeys.LStick; + if (IsActivated(joystickState, _config.LeftJoycon.ButtonMinus)) buttons |= ControllerKeys.Minus; + if (IsActivated(joystickState, _config.LeftJoycon.ButtonL)) buttons |= ControllerKeys.L; + if (IsActivated(joystickState, _config.LeftJoycon.ButtonZl)) buttons |= ControllerKeys.Zl; + if (IsActivated(joystickState, _config.LeftJoycon.ButtonSl)) buttons |= ControllerKeys.SlLeft; + if (IsActivated(joystickState, _config.LeftJoycon.ButtonSr)) buttons |= ControllerKeys.SrLeft; + + if (IsActivated(joystickState, _config.RightJoycon.ButtonA)) buttons |= ControllerKeys.A; + if (IsActivated(joystickState, _config.RightJoycon.ButtonB)) buttons |= ControllerKeys.B; + if (IsActivated(joystickState, _config.RightJoycon.ButtonX)) buttons |= ControllerKeys.X; + if (IsActivated(joystickState, _config.RightJoycon.ButtonY)) buttons |= ControllerKeys.Y; + if (IsActivated(joystickState, _config.RightJoycon.StickButton)) buttons |= ControllerKeys.RStick; + if (IsActivated(joystickState, _config.RightJoycon.ButtonPlus)) buttons |= ControllerKeys.Plus; + if (IsActivated(joystickState, _config.RightJoycon.ButtonR)) buttons |= ControllerKeys.R; + if (IsActivated(joystickState, _config.RightJoycon.ButtonZr)) buttons |= ControllerKeys.Zr; + if (IsActivated(joystickState, _config.RightJoycon.ButtonSl)) buttons |= ControllerKeys.SlRight; + if (IsActivated(joystickState, _config.RightJoycon.ButtonSr)) buttons |= ControllerKeys.SrRight; + + return buttons; + } + + private bool IsActivated(JoystickState joystickState, ControllerInputId controllerInputId) + { + if (controllerInputId <= ControllerInputId.Button20) + { + return joystickState.IsButtonDown((int)controllerInputId); + } + else if (controllerInputId <= ControllerInputId.Axis5) + { + int axis = controllerInputId - ControllerInputId.Axis0; + + return joystickState.GetAxis(axis) > _config.TriggerThreshold; + } + else if (controllerInputId <= ControllerInputId.Hat2Right) + { + int hat = (controllerInputId - ControllerInputId.Hat0Up) / 4; + + int baseHatId = (int)ControllerInputId.Hat0Up + (hat * 4); + + JoystickHatState hatState = joystickState.GetHat((JoystickHat)hat); + + if (hatState.IsUp && ((int)controllerInputId % baseHatId == 0)) return true; + if (hatState.IsDown && ((int)controllerInputId % baseHatId == 1)) return true; + if (hatState.IsLeft && ((int)controllerInputId % baseHatId == 2)) return true; + if (hatState.IsRight && ((int)controllerInputId % baseHatId == 3)) return true; + } + + return false; + } + + public (short, short) GetLeftStick() + { + if (!IsEnabled()) + { + return (0, 0); + } + + return GetStick(_config.LeftJoycon.StickX, _config.LeftJoycon.StickY, _config.DeadzoneLeft); + } + + public (short, short) GetRightStick() + { + if (!IsEnabled()) + { + return (0, 0); + } + + return GetStick(_config.RightJoycon.StickX, _config.RightJoycon.StickY, _config.DeadzoneRight); + } + + private (short, short) GetStick(ControllerInputId stickXInputId, ControllerInputId stickYInputId, float deadzone) + { + if (stickXInputId < ControllerInputId.Axis0 || stickXInputId > ControllerInputId.Axis5 || + stickYInputId < ControllerInputId.Axis0 || stickYInputId > ControllerInputId.Axis5) + { + return (0, 0); + } + + JoystickState jsState = Joystick.GetState(_config.Index); + + int xAxis = stickXInputId - ControllerInputId.Axis0; + int yAxis = stickYInputId - ControllerInputId.Axis0; + + float xValue = jsState.GetAxis(xAxis); + float yValue = -jsState.GetAxis(yAxis); // Invert Y-axis + + return ApplyDeadzone(new Vector2(xValue, yValue), deadzone); + } + + private (short, short) ApplyDeadzone(Vector2 axis, float deadzone) + { + return (ClampAxis(MathF.Abs(axis.X) > deadzone ? axis.X : 0f), + ClampAxis(MathF.Abs(axis.Y) > deadzone ? axis.Y : 0f)); + } + + private static short ClampAxis(float value) + { + if (value <= -short.MaxValue) + { + return -short.MaxValue; + } + else + { + return (short)(value * short.MaxValue); + } + } + } +} diff --git a/Ryujinx/Ui/KeyboardControls.cs b/Ryujinx/Ui/KeyboardController.cs index 1f19fe32..ed4a4b3f 100644 --- a/Ryujinx/Ui/KeyboardControls.cs +++ b/Ryujinx/Ui/KeyboardController.cs @@ -1,7 +1,7 @@ using System; using OpenTK.Input; +using Ryujinx.Common.Configuration.Hid; using Ryujinx.HLE.HOS.Services.Hid; -using Ryujinx.UI.Input; namespace Ryujinx.Ui { @@ -11,64 +11,85 @@ namespace Ryujinx.Ui ToggleVSync = 1 << 0, } - public static class KeyboardControls + public class KeyboardController { - public static ControllerKeys GetButtons(NpadKeyboard npad, KeyboardState keyboard) + private readonly KeyboardConfig _config; + + // NOTE: This should be initialized AFTER GTK for compat reasons with OpenTK SDL2 backend and GTK on Linux. + // BODY: Usage of Joystick.GetState must be defer to after GTK full initialization. Otherwise, GTK will segfault because SDL2 was already init *sighs* + public KeyboardController(KeyboardConfig config) { + _config = config; + } + + public ControllerKeys GetButtons() + { + KeyboardState keyboard = Keyboard.GetState(_config.Index); + ControllerKeys buttons = 0; - if (keyboard[(Key)npad.LeftJoycon.StickButton]) buttons |= ControllerKeys.LStick; - if (keyboard[(Key)npad.LeftJoycon.DPadUp]) buttons |= ControllerKeys.DpadUp; - if (keyboard[(Key)npad.LeftJoycon.DPadDown]) buttons |= ControllerKeys.DpadDown; - if (keyboard[(Key)npad.LeftJoycon.DPadLeft]) buttons |= ControllerKeys.DpadLeft; - if (keyboard[(Key)npad.LeftJoycon.DPadRight]) buttons |= ControllerKeys.DpadRight; - if (keyboard[(Key)npad.LeftJoycon.ButtonMinus]) buttons |= ControllerKeys.Minus; - if (keyboard[(Key)npad.LeftJoycon.ButtonL]) buttons |= ControllerKeys.L | ControllerKeys.Sl; - if (keyboard[(Key)npad.LeftJoycon.ButtonZl]) buttons |= ControllerKeys.Zl; + if (keyboard[(Key)_config.LeftJoycon.StickButton]) buttons |= ControllerKeys.LStick; + if (keyboard[(Key)_config.LeftJoycon.DPadUp]) buttons |= ControllerKeys.DpadUp; + if (keyboard[(Key)_config.LeftJoycon.DPadDown]) buttons |= ControllerKeys.DpadDown; + if (keyboard[(Key)_config.LeftJoycon.DPadLeft]) buttons |= ControllerKeys.DpadLeft; + if (keyboard[(Key)_config.LeftJoycon.DPadRight]) buttons |= ControllerKeys.DpadRight; + if (keyboard[(Key)_config.LeftJoycon.ButtonMinus]) buttons |= ControllerKeys.Minus; + if (keyboard[(Key)_config.LeftJoycon.ButtonL]) buttons |= ControllerKeys.L; + if (keyboard[(Key)_config.LeftJoycon.ButtonZl]) buttons |= ControllerKeys.Zl; + if (keyboard[(Key)_config.LeftJoycon.ButtonSl]) buttons |= ControllerKeys.SlLeft; + if (keyboard[(Key)_config.LeftJoycon.ButtonSr]) buttons |= ControllerKeys.SlRight; - if (keyboard[(Key)npad.RightJoycon.StickButton]) buttons |= ControllerKeys.RStick; - if (keyboard[(Key)npad.RightJoycon.ButtonA]) buttons |= ControllerKeys.A; - if (keyboard[(Key)npad.RightJoycon.ButtonB]) buttons |= ControllerKeys.B; - if (keyboard[(Key)npad.RightJoycon.ButtonX]) buttons |= ControllerKeys.X; - if (keyboard[(Key)npad.RightJoycon.ButtonY]) buttons |= ControllerKeys.Y; - if (keyboard[(Key)npad.RightJoycon.ButtonPlus]) buttons |= ControllerKeys.Plus; - if (keyboard[(Key)npad.RightJoycon.ButtonR]) buttons |= ControllerKeys.R | ControllerKeys.Sr; - if (keyboard[(Key)npad.RightJoycon.ButtonZr]) buttons |= ControllerKeys.Zr; + if (keyboard[(Key)_config.RightJoycon.StickButton]) buttons |= ControllerKeys.RStick; + if (keyboard[(Key)_config.RightJoycon.ButtonA]) buttons |= ControllerKeys.A; + if (keyboard[(Key)_config.RightJoycon.ButtonB]) buttons |= ControllerKeys.B; + if (keyboard[(Key)_config.RightJoycon.ButtonX]) buttons |= ControllerKeys.X; + if (keyboard[(Key)_config.RightJoycon.ButtonY]) buttons |= ControllerKeys.Y; + if (keyboard[(Key)_config.RightJoycon.ButtonPlus]) buttons |= ControllerKeys.Plus; + if (keyboard[(Key)_config.RightJoycon.ButtonR]) buttons |= ControllerKeys.R; + if (keyboard[(Key)_config.RightJoycon.ButtonZr]) buttons |= ControllerKeys.Zr; + if (keyboard[(Key)_config.RightJoycon.ButtonSl]) buttons |= ControllerKeys.SrLeft; + if (keyboard[(Key)_config.RightJoycon.ButtonSr]) buttons |= ControllerKeys.SrRight; return buttons; } - public static (short, short) GetLeftStick(NpadKeyboard npad, KeyboardState keyboard) + public (short, short) GetLeftStick() { + KeyboardState keyboard = Keyboard.GetState(_config.Index); + short dx = 0; short dy = 0; - if (keyboard[(Key)npad.LeftJoycon.StickUp]) dy = short.MaxValue; - if (keyboard[(Key)npad.LeftJoycon.StickDown]) dy = -short.MaxValue; - if (keyboard[(Key)npad.LeftJoycon.StickLeft]) dx = -short.MaxValue; - if (keyboard[(Key)npad.LeftJoycon.StickRight]) dx = short.MaxValue; + if (keyboard[(Key)_config.LeftJoycon.StickUp]) dy = short.MaxValue; + if (keyboard[(Key)_config.LeftJoycon.StickDown]) dy = -short.MaxValue; + if (keyboard[(Key)_config.LeftJoycon.StickLeft]) dx = -short.MaxValue; + if (keyboard[(Key)_config.LeftJoycon.StickRight]) dx = short.MaxValue; return (dx, dy); } - public static (short, short) GetRightStick(NpadKeyboard npad, KeyboardState keyboard) + public (short, short) GetRightStick() { + KeyboardState keyboard = Keyboard.GetState(_config.Index); + short dx = 0; short dy = 0; - if (keyboard[(Key)npad.RightJoycon.StickUp]) dy = short.MaxValue; - if (keyboard[(Key)npad.RightJoycon.StickDown]) dy = -short.MaxValue; - if (keyboard[(Key)npad.RightJoycon.StickLeft]) dx = -short.MaxValue; - if (keyboard[(Key)npad.RightJoycon.StickRight]) dx = short.MaxValue; + if (keyboard[(Key)_config.RightJoycon.StickUp]) dy = short.MaxValue; + if (keyboard[(Key)_config.RightJoycon.StickDown]) dy = -short.MaxValue; + if (keyboard[(Key)_config.RightJoycon.StickLeft]) dx = -short.MaxValue; + if (keyboard[(Key)_config.RightJoycon.StickRight]) dx = short.MaxValue; return (dx, dy); } - public static HotkeyButtons GetHotkeyButtons(NpadKeyboard npad, KeyboardState keyboard) + public HotkeyButtons GetHotkeyButtons() { + KeyboardState keyboard = Keyboard.GetState(_config.Index); + HotkeyButtons buttons = 0; - if (keyboard[(Key)npad.Hotkeys.ToggleVsync]) buttons |= HotkeyButtons.ToggleVSync; + if (keyboard[(Key)_config.Hotkeys.ToggleVsync]) buttons |= HotkeyButtons.ToggleVSync; return buttons; } @@ -223,12 +244,14 @@ namespace Ryujinx.Ui new KeyMappingEntry { TargetKey = Key.NumLock, Target = 10 }, }; - public static KeyboardInput GetKeysDown(NpadKeyboard npad, KeyboardState keyboard) + public KeyboardInput GetKeysDown() { + KeyboardState keyboard = Keyboard.GetState(_config.Index); + KeyboardInput hidKeyboard = new KeyboardInput { - Modifier = 0, - Keys = new int[0x8] + Modifier = 0, + Keys = new int[0x8] }; foreach (KeyMappingEntry entry in KeyMapping) diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs index eb8077e5..756ca231 100644 --- a/Ryujinx/Ui/MainWindow.cs +++ b/Ryujinx/Ui/MainWindow.cs @@ -13,6 +13,7 @@ using Ryujinx.HLE.HOS.Services.Hid; using System; using System.Diagnostics; using System.IO; +using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; @@ -28,7 +29,7 @@ namespace Ryujinx.Ui private static HLE.Switch _emulationContext; - private static GLRenderer _gLWidget; + private static GlRenderer _glWidget; private static AutoResetEvent _deviceExitStatus = new AutoResetEvent(false); @@ -37,40 +38,38 @@ namespace Ryujinx.Ui private static bool _updatingGameTable; private static bool _gameLoaded; private static bool _ending; + #pragma warning disable CS0169 private static bool _debuggerOpened; -#pragma warning restore CS0169 -#pragma warning disable CS0169 - private static Ryujinx.Debugger.Debugger _debugger; + private static Debugger.Debugger _debugger; #pragma warning restore CS0169 #pragma warning disable CS0169, CS0649, IDE0044 - [GUI] Window _mainWin; [GUI] MenuBar _menuBar; [GUI] Box _footerBox; - [GUI] MenuItem _fullScreen; [GUI] Box _statusBar; [GUI] MenuItem _stopEmulation; + [GUI] MenuItem _fullScreen; [GUI] CheckMenuItem _favToggle; - [GUI] MenuItem _firmwareInstallFile; [GUI] MenuItem _firmwareInstallDirectory; + [GUI] MenuItem _firmwareInstallFile; [GUI] Label _hostStatus; [GUI] MenuItem _openDebugger; [GUI] CheckMenuItem _iconToggle; - [GUI] CheckMenuItem _appToggle; [GUI] CheckMenuItem _developerToggle; - [GUI] CheckMenuItem _versionToggle; + [GUI] CheckMenuItem _appToggle; [GUI] CheckMenuItem _timePlayedToggle; + [GUI] CheckMenuItem _versionToggle; [GUI] CheckMenuItem _lastPlayedToggle; [GUI] CheckMenuItem _fileExtToggle; - [GUI] CheckMenuItem _fileSizeToggle; [GUI] CheckMenuItem _pathToggle; + [GUI] CheckMenuItem _fileSizeToggle; [GUI] Label _gameStatus; [GUI] TreeView _gameTable; - [GUI] ScrolledWindow _gameTableWindow; [GUI] TreeSelection _gameTableSelection; + [GUI] ScrolledWindow _gameTableWindow; [GUI] Label _gpuName; [GUI] Label _progressLabel; [GUI] Label _firmwareVersionLabel; @@ -96,9 +95,12 @@ namespace Ryujinx.Ui this.DeleteEvent += Window_Close; _fullScreen.Activated += FullScreen_Toggled; + this.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"); + this.Title = $"Ryujinx {Program.Version}"; + ApplicationLibrary.ApplicationAdded += Application_Added; ApplicationLibrary.ApplicationCountUpdated += ApplicationCount_Updated; - GLRenderer.StatusUpdatedEvent += Update_StatusBar; + GlRenderer.StatusUpdatedEvent += Update_StatusBar; _gameTable.ButtonReleaseEvent += Row_Clicked; @@ -127,8 +129,6 @@ namespace Ryujinx.Ui ApplyTheme(); - _mainWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"); - _mainWin.Title = $"Ryujinx {Program.Version}"; _stopEmulation.Sensitive = false; if (ConfigurationState.Instance.Ui.GuiColumns.FavColumn) _favToggle.Active = true; @@ -302,7 +302,7 @@ namespace Ryujinx.Ui { if (_gameLoaded) { - GtkDialog.CreateDialog("Ryujinx", "A game has already been loaded", "Please close it first and try again."); + GtkDialog.CreateInfoDialog("Ryujinx", "A game has already been loaded", "Please close it first and try again."); } else { @@ -415,7 +415,7 @@ namespace Ryujinx.Ui #if MACOS_BUILD CreateGameWindow(device); #else - var windowThread = new Thread(() => + Thread windowThread = new Thread(() => { CreateGameWindow(device); }) @@ -443,35 +443,29 @@ namespace Ryujinx.Ui private void CreateGameWindow(HLE.Switch device) { - ControllerType type = (Ryujinx.Configuration.Hid.ControllerType)ConfigurationState.Instance.Hid.ControllerType switch { - Ryujinx.Configuration.Hid.ControllerType.ProController => ControllerType.ProController, - Ryujinx.Configuration.Hid.ControllerType.Handheld => ControllerType.Handheld, - Ryujinx.Configuration.Hid.ControllerType.NpadPair => ControllerType.JoyconPair, - Ryujinx.Configuration.Hid.ControllerType.NpadLeft => ControllerType.JoyconLeft, - Ryujinx.Configuration.Hid.ControllerType.NpadRight => ControllerType.JoyconRight, - _ => ControllerType.Handheld - }; - - device.Hid.Npads.AddControllers(new ControllerConfig { - Player = PlayerIndex.Player1, - Type = type - }); + device.Hid.Npads.AddControllers(ConfigurationState.Instance.Hid.InputConfig.Value.Select(inputConfig => + new HLE.HOS.Services.Hid.ControllerConfig + { + Player = (PlayerIndex)inputConfig.PlayerIndex, + Type = (ControllerType)inputConfig.ControllerType + } + ).ToArray()); - _gLWidget = new GLRenderer(_emulationContext); + _glWidget = new GlRenderer(_emulationContext); Application.Invoke(delegate { _viewBox.Remove(_gameTableWindow); - _gLWidget.Expand = true; - _viewBox.Child = _gLWidget; + _glWidget.Expand = true; + _viewBox.Child = _glWidget; - _gLWidget.ShowAll(); + _glWidget.ShowAll(); EditFooterForGameRender(); }); - _gLWidget.WaitEvent.WaitOne(); + _glWidget.WaitEvent.WaitOne(); - _gLWidget.Start(); + _glWidget.Start(); device.Dispose(); _deviceExitStatus.Set(); @@ -479,15 +473,15 @@ namespace Ryujinx.Ui // NOTE: Everything that is here will not be executed when you close the UI. Application.Invoke(delegate { - _viewBox.Remove(_gLWidget); - _gLWidget.Exit(); + _viewBox.Remove(_glWidget); + _glWidget.Exit(); - if(_gLWidget.Window != this.Window && _gLWidget.Window != null) + if(_glWidget.Window != this.Window && _glWidget.Window != null) { - _gLWidget.Window.Dispose(); + _glWidget.Window.Dispose(); } - _gLWidget.Dispose(); + _glWidget.Dispose(); _viewBox.Add(_gameTableWindow); @@ -497,7 +491,7 @@ namespace Ryujinx.Ui _emulationContext = null; _gameLoaded = false; - _gLWidget = null; + _glWidget = null; DiscordIntegrationModule.SwitchToMainMenu(); @@ -528,7 +522,7 @@ namespace Ryujinx.Ui public void ToggleExtraWidgets(bool show) { - if (_gLWidget != null) + if (_glWidget != null) { if (show) { @@ -562,6 +556,11 @@ namespace Ryujinx.Ui } } + public static void SaveConfig() + { + ConfigurationState.Instance.ToFileFormat().SaveConfig(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json")); + } + private void End(HLE.Switch device) { @@ -580,10 +579,10 @@ namespace Ryujinx.Ui { UpdateGameMetadata(device.System.TitleIdText); - if (_gLWidget != null) + if (_glWidget != null) { // We tell the widget that we are exiting - _gLWidget.Exit(); + _glWidget.Exit(); // Wait for the other thread to dispose the HLE context before exiting. _deviceExitStatus.WaitOne(); @@ -773,7 +772,7 @@ namespace Ryujinx.Ui private void StopEmulation_Pressed(object sender, EventArgs args) { - _gLWidget?.Exit(); + _glWidget?.Exit(); } private void Installer_File_Pressed(object o, EventArgs args) @@ -808,7 +807,7 @@ namespace Ryujinx.Ui private void RefreshFirmwareLabel() { - var currentFirmware = _contentManager.GetCurrentFirmwareVersion(); + SystemVersion currentFirmware = _contentManager.GetCurrentFirmwareVersion(); GLib.Idle.Add(new GLib.IdleHandler(() => { @@ -830,7 +829,7 @@ namespace Ryujinx.Ui fileChooser.Dispose(); - var firmwareVersion = _contentManager.VerifyFirmwarePackage(filename); + SystemVersion firmwareVersion = _contentManager.VerifyFirmwarePackage(filename); if (firmwareVersion == null) { @@ -849,7 +848,7 @@ namespace Ryujinx.Ui return; } - var currentVersion = _contentManager.GetCurrentFirmwareVersion(); + SystemVersion currentVersion = _contentManager.GetCurrentFirmwareVersion(); string dialogMessage = $"System version {firmwareVersion.VersionString} will be installed."; @@ -989,7 +988,7 @@ namespace Ryujinx.Ui private void Settings_Pressed(object sender, EventArgs args) { - SwitchSettings settingsWin = new SwitchSettings(_virtualFileSystem, _contentManager); + SettingsWindow settingsWin = new SettingsWindow(_virtualFileSystem, _contentManager); settingsWin.Show(); } @@ -1205,10 +1204,5 @@ namespace Ryujinx.Ui return 0; } } - - public static void SaveConfig() - { - ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath); - } } } diff --git a/Ryujinx/Ui/NpadController.cs b/Ryujinx/Ui/NpadController.cs deleted file mode 100644 index b92f687c..00000000 --- a/Ryujinx/Ui/NpadController.cs +++ /dev/null @@ -1,143 +0,0 @@ -using OpenTK; -using OpenTK.Input; -using Ryujinx.Common.Configuration.Hid; -using Ryujinx.HLE.HOS.Services.Hid; -using System; - -using InnerNpadController = Ryujinx.Common.Configuration.Hid.NpadController; - -namespace Ryujinx.Ui.Input -{ - public class NpadController - { - private InnerNpadController _inner; - - // NOTE: This should be initialized AFTER GTK for compat reasons with OpenTK SDL2 backend and GTK on Linux. - // BODY: Usage of Joystick.GetState must be defer to after GTK full initialization. Otherwise, GTK will segfault because SDL2 was already init *sighs* - public NpadController(InnerNpadController inner) - { - _inner = inner; - } - - private bool IsEnabled() - { - return _inner.Enabled && Joystick.GetState(_inner.Index).IsConnected; - } - - public ControllerKeys GetButtons() - { - if (!IsEnabled()) - { - return 0; - } - - JoystickState joystickState = Joystick.GetState(_inner.Index); - - ControllerKeys buttons = 0; - - if (IsActivated(joystickState, _inner.LeftJoycon.DPadUp)) buttons |= ControllerKeys.DpadUp; - if (IsActivated(joystickState, _inner.LeftJoycon.DPadDown)) buttons |= ControllerKeys.DpadDown; - if (IsActivated(joystickState, _inner.LeftJoycon.DPadLeft)) buttons |= ControllerKeys.DpadLeft; - if (IsActivated(joystickState, _inner.LeftJoycon.DPadRight)) buttons |= ControllerKeys.DpadRight; - if (IsActivated(joystickState, _inner.LeftJoycon.StickButton)) buttons |= ControllerKeys.LStick; - if (IsActivated(joystickState, _inner.LeftJoycon.ButtonMinus)) buttons |= ControllerKeys.Minus; - if (IsActivated(joystickState, _inner.LeftJoycon.ButtonL)) buttons |= ControllerKeys.L | ControllerKeys.Sl; - if (IsActivated(joystickState, _inner.LeftJoycon.ButtonZl)) buttons |= ControllerKeys.Zl; - - if (IsActivated(joystickState, _inner.RightJoycon.ButtonA)) buttons |= ControllerKeys.A; - if (IsActivated(joystickState, _inner.RightJoycon.ButtonB)) buttons |= ControllerKeys.B; - if (IsActivated(joystickState, _inner.RightJoycon.ButtonX)) buttons |= ControllerKeys.X; - if (IsActivated(joystickState, _inner.RightJoycon.ButtonY)) buttons |= ControllerKeys.Y; - if (IsActivated(joystickState, _inner.RightJoycon.StickButton)) buttons |= ControllerKeys.RStick; - if (IsActivated(joystickState, _inner.RightJoycon.ButtonPlus)) buttons |= ControllerKeys.Plus; - if (IsActivated(joystickState, _inner.RightJoycon.ButtonR)) buttons |= ControllerKeys.R | ControllerKeys.Sr; - if (IsActivated(joystickState, _inner.RightJoycon.ButtonZr)) buttons |= ControllerKeys.Zr; - - return buttons; - } - - private bool IsActivated(JoystickState joystickState, ControllerInputId controllerInputId) - { - if (controllerInputId <= ControllerInputId.Button20) - { - return joystickState.IsButtonDown((int)controllerInputId); - } - else if (controllerInputId <= ControllerInputId.Axis5) - { - int axis = controllerInputId - ControllerInputId.Axis0; - - return joystickState.GetAxis(axis) > _inner.TriggerThreshold; - } - else if (controllerInputId <= ControllerInputId.Hat2Right) - { - int hat = (controllerInputId - ControllerInputId.Hat0Up) / 4; - - int baseHatId = (int)ControllerInputId.Hat0Up + (hat * 4); - - JoystickHatState hatState = joystickState.GetHat((JoystickHat)hat); - - if (hatState.IsUp && ((int)controllerInputId % baseHatId == 0)) return true; - if (hatState.IsDown && ((int)controllerInputId % baseHatId == 1)) return true; - if (hatState.IsLeft && ((int)controllerInputId % baseHatId == 2)) return true; - if (hatState.IsRight && ((int)controllerInputId % baseHatId == 3)) return true; - } - - return false; - } - - public (short, short) GetLeftStick() - { - if (!IsEnabled()) - { - return (0, 0); - } - - return GetStick(_inner.LeftJoycon.Stick); - } - - public (short, short) GetRightStick() - { - if (!IsEnabled()) - { - return (0, 0); - } - - return GetStick(_inner.RightJoycon.Stick); - } - - private (short, short) GetStick(ControllerInputId stickInputId) - { - if (stickInputId < ControllerInputId.Axis0 || stickInputId > ControllerInputId.Axis5) - { - return (0, 0); - } - - JoystickState jsState = Joystick.GetState(_inner.Index); - - int xAxis = stickInputId - ControllerInputId.Axis0; - - float xValue = jsState.GetAxis(xAxis); - float yValue = 0 - jsState.GetAxis(xAxis + 1); // Invert Y-axis - - return ApplyDeadzone(new Vector2(xValue, yValue)); - } - - private (short, short) ApplyDeadzone(Vector2 axis) - { - return (ClampAxis(MathF.Abs(axis.X) > _inner.Deadzone ? axis.X : 0f), - ClampAxis(MathF.Abs(axis.Y) > _inner.Deadzone ? axis.Y : 0f)); - } - - private static short ClampAxis(float value) - { - if (value <= -short.MaxValue) - { - return -short.MaxValue; - } - else - { - return (short)(value * short.MaxValue); - } - } - } -} diff --git a/Ryujinx/Ui/ProfileDialog.cs b/Ryujinx/Ui/ProfileDialog.cs new file mode 100644 index 00000000..2b26cbef --- /dev/null +++ b/Ryujinx/Ui/ProfileDialog.cs @@ -0,0 +1,58 @@ +using Gtk; +using System; +using System.Reflection; + +using GUI = Gtk.Builder.ObjectAttribute; + +namespace Ryujinx.Ui +{ + public class ProfileDialog : Dialog + { + public string FileName { get; private set; } + +#pragma warning disable CS0649, IDE0044 + [GUI] Entry _profileEntry; + [GUI] Label _errorMessage; +#pragma warning restore CS0649, IDE0044 + + public ProfileDialog() : this(new Builder("Ryujinx.Ui.ProfileDialog.glade")) { } + + private ProfileDialog(Builder builder) : base(builder.GetObject("_profileDialog").Handle) + { + builder.Autoconnect(this); + + Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"); + } + + private void OkToggle_Activated(object sender, EventArgs args) + { + ((ToggleButton)sender).SetStateFlags(0, true); + + bool validFileName = true; + + foreach (char invalidChar in System.IO.Path.GetInvalidFileNameChars()) + { + if (_profileEntry.Text.Contains(invalidChar)) + { + validFileName = false; + } + } + + if (validFileName && !string.IsNullOrEmpty(_profileEntry.Text)) + { + FileName = $"{_profileEntry.Text}.json"; + + Respond(ResponseType.Ok); + } + else + { + _errorMessage.Text = "The file name contains invalid characters. Please try again."; + } + } + + private void CancelToggle_Activated(object sender, EventArgs args) + { + Respond(ResponseType.Cancel); + } + } +}
\ No newline at end of file diff --git a/Ryujinx/Ui/ProfileDialog.glade b/Ryujinx/Ui/ProfileDialog.glade new file mode 100644 index 00000000..adaf6608 --- /dev/null +++ b/Ryujinx/Ui/ProfileDialog.glade @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.22.1 --> +<interface> + <requires lib="gtk+" version="3.20"/> + <object class="GtkDialog" id="_profileDialog"> + <property name="can_focus">False</property> + <property name="title" translatable="yes">Ryujinx - Profile Dialog</property> + <property name="modal">True</property> + <property name="window_position">center</property> + <property name="default_width">400</property> + <property name="type_hint">dialog</property> + <child> + <placeholder/> + </child> + <child internal-child="vbox"> + <object class="GtkBox"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child internal-child="action_area"> + <object class="GtkButtonBox"> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkToggleButton" id="OkToggle"> + <property name="label" translatable="yes">OK</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="toggled" handler="OkToggle_Activated" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="CancelToggle"> + <property name="label" translatable="yes">Cancel</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="toggled" handler="CancelToggle_Activated" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">10</property> + <property name="margin_right">10</property> + <property name="margin_top">20</property> + <property name="margin_bottom">10</property> + <property name="label" translatable="yes">Enter a name for the new profile:</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="_profileEntry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="margin_left">20</property> + <property name="margin_right">20</property> + <property name="margin_top">20</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="_errorMessage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="margin_left">20</property> + <property name="margin_right">10</property> + <property name="margin_top">10</property> + <property name="margin_bottom">10</property> + <attributes> + <attribute name="foreground" value="#ffff00000000"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> +</interface> diff --git a/Ryujinx/Ui/SettingsWindow.cs b/Ryujinx/Ui/SettingsWindow.cs new file mode 100644 index 00000000..1b24e72b --- /dev/null +++ b/Ryujinx/Ui/SettingsWindow.cs @@ -0,0 +1,409 @@ +using Gtk; +using Ryujinx.Configuration; +using Ryujinx.Configuration.System; +using Ryujinx.HLE.HOS.Services.Time.TimeZone; +using Ryujinx.HLE.FileSystem; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using Ryujinx.Common.Configuration.Hid; +using GUI = Gtk.Builder.ObjectAttribute; + +namespace Ryujinx.Ui +{ + public class SettingsWindow : Window + { + private static ListStore _gameDirsBoxStore; + private static VirtualFileSystem _virtualFileSystem; + + private long _systemTimeOffset; + +#pragma warning disable CS0649, IDE0044 + [GUI] CheckButton _errorLogToggle; + [GUI] CheckButton _warningLogToggle; + [GUI] CheckButton _infoLogToggle; + [GUI] CheckButton _stubLogToggle; + [GUI] CheckButton _debugLogToggle; + [GUI] CheckButton _fileLogToggle; + [GUI] CheckButton _guestLogToggle; + [GUI] CheckButton _fsAccessLogToggle; + [GUI] Adjustment _fsLogSpinAdjustment; + [GUI] CheckButton _dockedModeToggle; + [GUI] CheckButton _discordToggle; + [GUI] CheckButton _vSyncToggle; + [GUI] CheckButton _multiSchedToggle; + [GUI] CheckButton _fsicToggle; + [GUI] CheckButton _ignoreToggle; + [GUI] CheckButton _directKeyboardAccess; + [GUI] ComboBoxText _systemLanguageSelect; + [GUI] ComboBoxText _systemRegionSelect; + [GUI] ComboBoxText _systemTimeZoneSelect; + [GUI] SpinButton _systemTimeYearSpin; + [GUI] SpinButton _systemTimeMonthSpin; + [GUI] SpinButton _systemTimeDaySpin; + [GUI] SpinButton _systemTimeHourSpin; + [GUI] SpinButton _systemTimeMinuteSpin; + [GUI] Adjustment _systemTimeYearSpinAdjustment; + [GUI] Adjustment _systemTimeMonthSpinAdjustment; + [GUI] Adjustment _systemTimeDaySpinAdjustment; + [GUI] Adjustment _systemTimeHourSpinAdjustment; + [GUI] Adjustment _systemTimeMinuteSpinAdjustment; + [GUI] CheckButton _custThemeToggle; + [GUI] Entry _custThemePath; + [GUI] ToggleButton _browseThemePath; + [GUI] Label _custThemePathLabel; + [GUI] TreeView _gameDirsBox; + [GUI] Entry _addGameDirBox; + [GUI] Entry _graphicsShadersDumpPath; + [GUI] ComboBoxText _anisotropy; + [GUI] ToggleButton _configureController1; + [GUI] ToggleButton _configureController2; + [GUI] ToggleButton _configureController3; + [GUI] ToggleButton _configureController4; + [GUI] ToggleButton _configureController5; + [GUI] ToggleButton _configureController6; + [GUI] ToggleButton _configureController7; + [GUI] ToggleButton _configureController8; + [GUI] ToggleButton _configureControllerH; +#pragma warning restore CS0649, IDE0044 + + public SettingsWindow(VirtualFileSystem virtualFileSystem, HLE.FileSystem.Content.ContentManager contentManager) : this(new Builder("Ryujinx.Ui.SettingsWindow.glade"), virtualFileSystem, contentManager) { } + + private SettingsWindow(Builder builder, VirtualFileSystem virtualFileSystem, HLE.FileSystem.Content.ContentManager contentManager) : base(builder.GetObject("_settingsWin").Handle) + { + builder.Autoconnect(this); + + this.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"); + + _virtualFileSystem = virtualFileSystem; + + //Bind Events + _configureController1.Pressed += (sender, args) => ConfigureController_Pressed(sender, args, PlayerIndex.Player1); + _configureController2.Pressed += (sender, args) => ConfigureController_Pressed(sender, args, PlayerIndex.Player2); + _configureController3.Pressed += (sender, args) => ConfigureController_Pressed(sender, args, PlayerIndex.Player3); + _configureController4.Pressed += (sender, args) => ConfigureController_Pressed(sender, args, PlayerIndex.Player4); + _configureController5.Pressed += (sender, args) => ConfigureController_Pressed(sender, args, PlayerIndex.Player5); + _configureController6.Pressed += (sender, args) => ConfigureController_Pressed(sender, args, PlayerIndex.Player6); + _configureController7.Pressed += (sender, args) => ConfigureController_Pressed(sender, args, PlayerIndex.Player7); + _configureController8.Pressed += (sender, args) => ConfigureController_Pressed(sender, args, PlayerIndex.Player8); + _configureControllerH.Pressed += (sender, args) => ConfigureController_Pressed(sender, args, PlayerIndex.Handheld); + + //Setup Currents + if (ConfigurationState.Instance.Logger.EnableFileLog) + { + _fileLogToggle.Click(); + } + + if (ConfigurationState.Instance.Logger.EnableError) + { + _errorLogToggle.Click(); + } + + if (ConfigurationState.Instance.Logger.EnableWarn) + { + _warningLogToggle.Click(); + } + + if (ConfigurationState.Instance.Logger.EnableInfo) + { + _infoLogToggle.Click(); + } + + if (ConfigurationState.Instance.Logger.EnableStub) + { + _stubLogToggle.Click(); + } + + if (ConfigurationState.Instance.Logger.EnableDebug) + { + _debugLogToggle.Click(); + } + + if (ConfigurationState.Instance.Logger.EnableGuest) + { + _guestLogToggle.Click(); + } + + if (ConfigurationState.Instance.Logger.EnableFsAccessLog) + { + _fsAccessLogToggle.Click(); + } + + if (ConfigurationState.Instance.System.EnableDockedMode) + { + _dockedModeToggle.Click(); + } + + if (ConfigurationState.Instance.EnableDiscordIntegration) + { + _discordToggle.Click(); + } + + if (ConfigurationState.Instance.Graphics.EnableVsync) + { + _vSyncToggle.Click(); + } + + if (ConfigurationState.Instance.System.EnableMulticoreScheduling) + { + _multiSchedToggle.Click(); + } + + if (ConfigurationState.Instance.System.EnableFsIntegrityChecks) + { + _fsicToggle.Click(); + } + + if (ConfigurationState.Instance.System.IgnoreMissingServices) + { + _ignoreToggle.Click(); + } + + if (ConfigurationState.Instance.Hid.EnableKeyboard) + { + _directKeyboardAccess.Click(); + } + + if (ConfigurationState.Instance.Ui.EnableCustomTheme) + { + _custThemeToggle.Click(); + } + + TimeZoneContentManager timeZoneContentManager = new TimeZoneContentManager(); + + timeZoneContentManager.InitializeInstance(virtualFileSystem, contentManager, LibHac.FsSystem.IntegrityCheckLevel.None); + + List<string> locationNames = timeZoneContentManager.LocationNameCache.ToList(); + + locationNames.Sort(); + + foreach (string locationName in locationNames) + { + _systemTimeZoneSelect.Append(locationName, locationName); + } + + _systemLanguageSelect.SetActiveId(ConfigurationState.Instance.System.Language.Value.ToString()); + _systemRegionSelect.SetActiveId(ConfigurationState.Instance.System.Region.Value.ToString()); + _systemTimeZoneSelect.SetActiveId(timeZoneContentManager.SanityCheckDeviceLocationName()); + _anisotropy.SetActiveId(ConfigurationState.Instance.Graphics.MaxAnisotropy.Value.ToString()); + + _custThemePath.Buffer.Text = ConfigurationState.Instance.Ui.CustomThemePath; + _graphicsShadersDumpPath.Buffer.Text = ConfigurationState.Instance.Graphics.ShadersDumpPath; + _fsLogSpinAdjustment.Value = ConfigurationState.Instance.System.FsGlobalAccessLogMode; + _systemTimeOffset = ConfigurationState.Instance.System.SystemTimeOffset; + + _gameDirsBox.AppendColumn("", new CellRendererText(), "text", 0); + _gameDirsBoxStore = new ListStore(typeof(string)); + _gameDirsBox.Model = _gameDirsBoxStore; + + foreach (string gameDir in ConfigurationState.Instance.Ui.GameDirs.Value) + { + _gameDirsBoxStore.AppendValues(gameDir); + } + + if (_custThemeToggle.Active == false) + { + _custThemePath.Sensitive = false; + _custThemePathLabel.Sensitive = false; + _browseThemePath.Sensitive = false; + } + + //Setup system time spinners + UpdateSystemTimeSpinners(); + } + + private void UpdateSystemTimeSpinners() + { + //Bind system time events + _systemTimeYearSpin.ValueChanged -= SystemTimeSpin_ValueChanged; + _systemTimeMonthSpin.ValueChanged -= SystemTimeSpin_ValueChanged; + _systemTimeDaySpin.ValueChanged -= SystemTimeSpin_ValueChanged; + _systemTimeHourSpin.ValueChanged -= SystemTimeSpin_ValueChanged; + _systemTimeMinuteSpin.ValueChanged -= SystemTimeSpin_ValueChanged; + + //Apply actual system time + SystemTimeOffset to system time spin buttons + DateTime systemTime = DateTime.Now.AddSeconds(_systemTimeOffset); + + _systemTimeYearSpinAdjustment.Value = systemTime.Year; + _systemTimeMonthSpinAdjustment.Value = systemTime.Month; + _systemTimeDaySpinAdjustment.Value = systemTime.Day; + _systemTimeHourSpinAdjustment.Value = systemTime.Hour; + _systemTimeMinuteSpinAdjustment.Value = systemTime.Minute; + + //Format spin buttons text to include leading zeros + _systemTimeYearSpin.Text = systemTime.Year.ToString("0000"); + _systemTimeMonthSpin.Text = systemTime.Month.ToString("00"); + _systemTimeDaySpin.Text = systemTime.Day.ToString("00"); + _systemTimeHourSpin.Text = systemTime.Hour.ToString("00"); + _systemTimeMinuteSpin.Text = systemTime.Minute.ToString("00"); + + //Bind system time events + _systemTimeYearSpin.ValueChanged += SystemTimeSpin_ValueChanged; + _systemTimeMonthSpin.ValueChanged += SystemTimeSpin_ValueChanged; + _systemTimeDaySpin.ValueChanged += SystemTimeSpin_ValueChanged; + _systemTimeHourSpin.ValueChanged += SystemTimeSpin_ValueChanged; + _systemTimeMinuteSpin.ValueChanged += SystemTimeSpin_ValueChanged; + } + + //Events + private void SystemTimeSpin_ValueChanged(Object sender, EventArgs e) + { + int year = _systemTimeYearSpin.ValueAsInt; + int month = _systemTimeMonthSpin.ValueAsInt; + int day = _systemTimeDaySpin.ValueAsInt; + int hour = _systemTimeHourSpin.ValueAsInt; + int minute = _systemTimeMinuteSpin.ValueAsInt; + + if (!DateTime.TryParse(year + "-" + month + "-" + day + " " + hour + ":" + minute, out DateTime newTime)) + { + UpdateSystemTimeSpinners(); + + return; + } + + newTime = newTime.AddSeconds(DateTime.Now.Second).AddMilliseconds(DateTime.Now.Millisecond); + + long systemTimeOffset = (long)Math.Ceiling((newTime - DateTime.Now).TotalMinutes) * 60L; + + if (_systemTimeOffset != systemTimeOffset) + { + _systemTimeOffset = systemTimeOffset; + UpdateSystemTimeSpinners(); + } + } + + private void AddDir_Pressed(object sender, EventArgs args) + { + if (Directory.Exists(_addGameDirBox.Buffer.Text)) + { + _gameDirsBoxStore.AppendValues(_addGameDirBox.Buffer.Text); + } + else + { + FileChooserDialog fileChooser = new FileChooserDialog("Choose the game directory to add to the list", this, FileChooserAction.SelectFolder, "Cancel", ResponseType.Cancel, "Add", ResponseType.Accept); + + if (fileChooser.Run() == (int)ResponseType.Accept) + { + _gameDirsBoxStore.AppendValues(fileChooser.Filename); + } + + fileChooser.Dispose(); + } + + _addGameDirBox.Buffer.Text = ""; + + ((ToggleButton)sender).SetStateFlags(0, true); + } + + private void RemoveDir_Pressed(object sender, EventArgs args) + { + TreeSelection selection = _gameDirsBox.Selection; + + if (selection.GetSelected(out TreeIter treeIter)) + { + _gameDirsBoxStore.Remove(ref treeIter); + } + + ((ToggleButton)sender).SetStateFlags(0, true); + } + + private void CustThemeToggle_Activated(object sender, EventArgs args) + { + _custThemePath.Sensitive = _custThemeToggle.Active; + _custThemePathLabel.Sensitive = _custThemeToggle.Active; + _browseThemePath.Sensitive = _custThemeToggle.Active; + } + + private void BrowseThemeDir_Pressed(object sender, EventArgs args) + { + FileChooserDialog fileChooser = new FileChooserDialog("Choose the theme to load", this, FileChooserAction.Open, "Cancel", ResponseType.Cancel, "Select", ResponseType.Accept); + + fileChooser.Filter = new FileFilter(); + fileChooser.Filter.AddPattern("*.css"); + + if (fileChooser.Run() == (int)ResponseType.Accept) + { + _custThemePath.Buffer.Text = fileChooser.Filename; + } + + fileChooser.Dispose(); + + _browseThemePath.SetStateFlags(0, true); + } + + private void OpenLogsFolder_Pressed(object sender, EventArgs args) + { + string logPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"); + + DirectoryInfo directory = new DirectoryInfo(logPath); + directory.Create(); + + Process.Start(new ProcessStartInfo() + { + FileName = logPath, + UseShellExecute = true, + Verb = "open" + }); + } + + private void ConfigureController_Pressed(object sender, EventArgs args, PlayerIndex playerIndex) + { + ((ToggleButton)sender).SetStateFlags(0, true); + + ControllerWindow controllerWin = new ControllerWindow(playerIndex, _virtualFileSystem); + controllerWin.Show(); + } + + private void SaveToggle_Activated(object sender, EventArgs args) + { + List<string> gameDirs = new List<string>(); + + _gameDirsBoxStore.GetIterFirst(out TreeIter treeIter); + for (int i = 0; i < _gameDirsBoxStore.IterNChildren(); i++) + { + gameDirs.Add((string)_gameDirsBoxStore.GetValue(treeIter, 0)); + + _gameDirsBoxStore.IterNext(ref treeIter); + } + + ConfigurationState.Instance.Logger.EnableError.Value = _errorLogToggle.Active; + ConfigurationState.Instance.Logger.EnableWarn.Value = _warningLogToggle.Active; + ConfigurationState.Instance.Logger.EnableInfo.Value = _infoLogToggle.Active; + ConfigurationState.Instance.Logger.EnableStub.Value = _stubLogToggle.Active; + ConfigurationState.Instance.Logger.EnableDebug.Value = _debugLogToggle.Active; + ConfigurationState.Instance.Logger.EnableGuest.Value = _guestLogToggle.Active; + ConfigurationState.Instance.Logger.EnableFsAccessLog.Value = _fsAccessLogToggle.Active; + ConfigurationState.Instance.Logger.EnableFileLog.Value = _fileLogToggle.Active; + ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active; + ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active; + ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active; + ConfigurationState.Instance.System.EnableMulticoreScheduling.Value = _multiSchedToggle.Active; + ConfigurationState.Instance.System.EnableFsIntegrityChecks.Value = _fsicToggle.Active; + ConfigurationState.Instance.System.IgnoreMissingServices.Value = _ignoreToggle.Active; + ConfigurationState.Instance.Hid.EnableKeyboard.Value = _directKeyboardAccess.Active; + ConfigurationState.Instance.Ui.EnableCustomTheme.Value = _custThemeToggle.Active; + ConfigurationState.Instance.System.Language.Value = Enum.Parse<Language>(_systemLanguageSelect.ActiveId); + ConfigurationState.Instance.System.Region.Value = Enum.Parse<Configuration.System.Region>(_systemRegionSelect.ActiveId); + ConfigurationState.Instance.System.TimeZone.Value = _systemTimeZoneSelect.ActiveId; + ConfigurationState.Instance.System.SystemTimeOffset.Value = _systemTimeOffset; + ConfigurationState.Instance.Ui.CustomThemePath.Value = _custThemePath.Buffer.Text; + ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = _graphicsShadersDumpPath.Buffer.Text; + ConfigurationState.Instance.Ui.GameDirs.Value = gameDirs; + ConfigurationState.Instance.System.FsGlobalAccessLogMode.Value = (int)_fsLogSpinAdjustment.Value; + ConfigurationState.Instance.Graphics.MaxAnisotropy.Value = float.Parse(_anisotropy.ActiveId); + + MainWindow.SaveConfig(); + MainWindow.ApplyTheme(); + MainWindow.UpdateGameTable(); + Dispose(); + } + + private void CloseToggle_Activated(object sender, EventArgs args) + { + Dispose(); + } + } +}
\ No newline at end of file diff --git a/Ryujinx/Ui/SwitchSettings.glade b/Ryujinx/Ui/SettingsWindow.glade index 7415e76e..ea662de0 100644 --- a/Ryujinx/Ui/SwitchSettings.glade +++ b/Ryujinx/Ui/SettingsWindow.glade @@ -7,95 +7,21 @@ <property name="step_increment">1</property> <property name="page_increment">10</property> </object> - <object class="GtkAdjustment" id="_systemTimeYearSpinAdjustment"> - <property name="lower">2000</property> - <property name="upper">2060</property> - <property name="step_increment">1</property> - <property name="page_increment">10</property> - </object> - <object class="GtkAdjustment" id="_systemTimeMonthSpinAdjustment"> - <property name="lower">1</property> - <property name="upper">12</property> - <property name="step_increment">1</property> - <property name="page_increment">5</property> - </object> - <object class="GtkAdjustment" id="_systemTimeDaySpinAdjustment"> - <property name="lower">1</property> - <property name="upper">31</property> - <property name="step_increment">1</property> - <property name="page_increment">5</property> - </object> - <object class="GtkAdjustment" id="_systemTimeHourSpinAdjustment"> - <property name="lower">0</property> - <property name="upper">23</property> - <property name="step_increment">1</property> - <property name="page_increment">5</property> - </object> - <object class="GtkAdjustment" id="_systemTimeMinuteSpinAdjustment"> - <property name="lower">0</property> - <property name="upper">59</property> - <property name="step_increment">1</property> - <property name="page_increment">5</property> - </object> - <object class="GtkDialog" id="_settingsWin"> + <object class="GtkWindow" id="_settingsWin"> <property name="can_focus">False</property> <property name="title" translatable="yes">Ryujinx - Settings</property> <property name="modal">True</property> <property name="window_position">center</property> - <property name="default_width">910</property> - <property name="default_height">790</property> - <property name="type_hint">dialog</property> + <property name="default_width">650</property> + <property name="default_height">520</property> <child> <placeholder/> </child> - <child internal-child="vbox"> + <child> <object class="GtkBox"> + <property name="visible">True</property> <property name="can_focus">False</property> <property name="orientation">vertical</property> - <property name="spacing">2</property> - <child internal-child="action_area"> - <object class="GtkButtonBox"> - <property name="can_focus">False</property> - <property name="margin_right">5</property> - <property name="margin_top">3</property> - <property name="margin_bottom">3</property> - <property name="layout_style">end</property> - <child> - <object class="GtkToggleButton" id="SaveToggle"> - <property name="label" translatable="yes">Save</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <signal name="toggled" handler="SaveToggle_Activated" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="CloseToggle"> - <property name="label" translatable="yes">Close</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <signal name="toggled" handler="CloseToggle_Activated" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="padding">5</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> <child> <object class="GtkScrolledWindow"> <property name="visible">True</property> @@ -142,303 +68,19 @@ </packing> </child> <child> - <object class="GtkBox" id="box1"> + <object class="GtkBox" id="General"> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="margin_left">10</property> + <property name="margin_right">10</property> <property name="orientation">vertical</property> <child> - <object class="GtkBox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Change System Language</property> - <property name="halign">end</property> - <property name="label" translatable="yes">System Language:</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkComboBoxText" id="_systemLanguageSelect"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Change System Language</property> - <property name="margin_left">5</property> - <items> - <item id="AmericanEnglish" translatable="yes">American English</item> - <item id="BritishEnglish" translatable="yes">British English</item> - <item id="CanadianFrench" translatable="yes">Canadian French</item> - <item id="Chinese" translatable="yes">Chinese</item> - <item id="Dutch" translatable="yes">Dutch</item> - <item id="French" translatable="yes">French</item> - <item id="German" translatable="yes">German</item> - <item id="Italian" translatable="yes">Italian</item> - <item id="Japanese" translatable="yes">Japanese</item> - <item id="Korean" translatable="yes">Korean</item> - <item id="LatinAmericanSpanish" translatable="yes">Latin American Spanish</item> - <item id="Portuguese" translatable="yes">Portuguese</item> - <item id="Russian" translatable="yes">Russian</item> - <item id="SimplifiedChinese" translatable="yes">Simplified Chinese</item> - <item id="Spanish" translatable="yes">Spanish</item> - <item id="Taiwanese" translatable="yes">Taiwanese</item> - <item id="TraditionalChinese" translatable="yes">Traditional Chinese</item> - </items> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Change System Region</property> - <property name="halign">end</property> - <property name="label" translatable="yes">System Region:</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="padding">5</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkComboBoxText" id="_systemRegionSelect"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Change System Region</property> - <property name="margin_left">5</property> - <items> - <item id="Japan" translatable="yes">Japan</item> - <item id="USA" translatable="yes">USA</item> - <item id="Europe" translatable="yes">Europe</item> - <item id="Australia" translatable="yes">Australia</item> - <item id="China" translatable="yes">China</item> - <item id="Korea" translatable="yes">Korea</item> - <item id="Taiwan" translatable="yes">Taiwan</item> - </items> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="box2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <child> - <object class="GtkBox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Change System TimeZone</property> - <property name="halign">end</property> - <property name="label" translatable="yes">System TimeZone:</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkComboBoxText" id="_systemTimeZoneSelect"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Change System TimeZone</property> - <property name="margin_left">5</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkBox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="halign">end</property> - <property name="label" translatable="yes">System Time:</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="padding">5</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkSpinButton" id="_systemTimeYearSpin"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_left">5</property> - <property name="orientation">vertical</property> - <property name="adjustment">_systemTimeYearSpinAdjustment</property> - <property name="wrap">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="halign">end</property> - <property name="label" translatable="no">-</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="padding">5</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkSpinButton" id="_systemTimeMonthSpin"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_left">0</property> - <property name="orientation">vertical</property> - <property name="adjustment">_systemTimeMonthSpinAdjustment</property> - <property name="wrap">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="halign">end</property> - <property name="label" translatable="no">-</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="padding">5</property> - <property name="position">4</property> - </packing> - </child> - <child> - <object class="GtkSpinButton" id="_systemTimeDaySpin"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_left">0</property> - <property name="orientation">vertical</property> - <property name="adjustment">_systemTimeDaySpinAdjustment</property> - <property name="wrap">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">5</property> - </packing> - </child> - <child> - <object class="GtkSpinButton" id="_systemTimeHourSpin"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_left">25</property> - <property name="orientation">vertical</property> - <property name="adjustment">_systemTimeHourSpinAdjustment</property> - <property name="wrap">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">6</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="halign">end</property> - <property name="label" translatable="no">:</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="padding">5</property> - <property name="position">7</property> - </packing> - </child> - <child> - <object class="GtkSpinButton" id="_systemTimeMinuteSpin"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_left">0</property> - <property name="orientation">vertical</property> - <property name="adjustment">_systemTimeMinuteSpinAdjustment</property> - <property name="wrap">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">8</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - <child> <object class="GtkCheckButton" id="_discordToggle"> <property name="label" translatable="yes">Enable Discord Rich Presence</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> - <property name="tooltip_text" translatable="yes">Enables or disables Discord Rich Presense</property> + <property name="tooltip_text" translatable="yes">Enables or disables Discord Rich Presence</property> <property name="halign">start</property> <property name="draw_indicator">True</property> </object> @@ -446,7 +88,7 @@ <property name="expand">False</property> <property name="fill">True</property> <property name="padding">5</property> - <property name="position">3</property> + <property name="position">2</property> </packing> </child> </object> @@ -570,23 +212,6 @@ </packing> </child> <child> - <object class="GtkToggleButton" id="_browseDir"> - <property name="label" translatable="yes">Browse...</property> - <property name="width_request">80</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_text" translatable="yes">Browse for a game directory</property> - <property name="margin_left">5</property> - <signal name="toggled" handler="BrowseDir_Pressed" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - <child> <object class="GtkToggleButton" id="_removeDir"> <property name="label" translatable="yes">Remove</property> <property name="width_request">80</property> @@ -775,6 +400,9 @@ <object class="GtkBox" id="TabInput"> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="margin_left">5</property> + <property name="margin_right">10</property> + <property name="margin_top">5</property> <property name="orientation">vertical</property> <child> <object class="GtkBox"> @@ -834,629 +462,1029 @@ </packing> </child> <child> - <object class="GtkBox" id="Controller1Box"> + <object class="GtkGrid" id="ControllerGrid"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="margin_left">10</property> - <property name="margin_right">10</property> - <property name="margin_bottom">5</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="column_spacing">20</property> <child> <object class="GtkBox"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="orientation">vertical</property> <child> - <object class="GtkBox"> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + <property name="label" translatable="yes">Player 1</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_configureController1"> + <property name="label" translatable="yes">Configure</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">20</property> + <property name="margin_right">20</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + <property name="label" translatable="yes">Player 3</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_configureController3"> + <property name="label" translatable="yes">Configure</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">20</property> + <property name="margin_right">20</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">4</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + <property name="label" translatable="yes">Player 2</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_configureController2"> + <property name="label" translatable="yes">Configure</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">20</property> + <property name="margin_right">20</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + <property name="label" translatable="yes">Handheld</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_configureControllerH"> + <property name="label" translatable="yes">Configure</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">20</property> + <property name="margin_right">20</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">4</property> + <property name="top_attach">4</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + <property name="label" translatable="yes">Player 6</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_configureController6"> + <property name="label" translatable="yes">Configure</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">20</property> + <property name="margin_right">20</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">4</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + <property name="label" translatable="yes">Player 5</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_configureController5"> + <property name="label" translatable="yes">Configure</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">20</property> + <property name="margin_right">20</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + <property name="label" translatable="yes">Player 7</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_configureController7"> + <property name="label" translatable="yes">Configure</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">20</property> + <property name="margin_right">20</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">4</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + <property name="label" translatable="yes">Player 4</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_configureController4"> + <property name="label" translatable="yes">Configure</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">20</property> + <property name="margin_right">20</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + <property name="label" translatable="yes">Player 8</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="_configureController8"> + <property name="label" translatable="yes">Configure</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">20</property> + <property name="margin_right">20</property> + <property name="margin_top">20</property> + <property name="margin_bottom">20</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">4</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">3</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">3</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">3</property> + <property name="top_attach">4</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">4</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">3</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">3</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">4</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="left_attach">4</property> + <property name="top_attach">3</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child type="tab"> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Input</property> + </object> + <packing> + <property name="position">1</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <object class="GtkBox" id="TabSystem"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">5</property> + <property name="margin_right">10</property> + <property name="margin_top">5</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkBox" id="CatCore"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">start</property> + <property name="margin_left">5</property> + <property name="margin_right">5</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="margin_bottom">5</property> + <property name="label" translatable="yes">Core</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">10</property> + <property name="margin_right">10</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkBox" id="RegionBox"> <property name="visible">True</property> <property name="can_focus">False</property> <child> <object class="GtkLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">The primary controller's type</property> - <property name="halign">center</property> - <property name="margin_top">5</property> - <property name="margin_bottom">5</property> - <property name="label" translatable="yes">Controller Type:</property> + <property name="tooltip_text" translatable="yes">Change System Region</property> + <property name="halign">end</property> + <property name="label" translatable="yes">System Region:</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">0</property> + <property name="padding">5</property> + <property name="position">2</property> </packing> </child> <child> - <object class="GtkComboBoxText" id="_controller1Type"> + <object class="GtkComboBoxText" id="_systemRegionSelect"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">The primary controller's type</property> + <property name="tooltip_text" translatable="yes">Change System Region</property> <property name="margin_left">5</property> - <property name="active">0</property> <items> - <item id="Handheld" translatable="yes">Handheld</item> - <item id="ProController" translatable="yes">Pro Controller</item> - <item id="NpadPair" translatable="yes">Paired Joycons</item> - <item id="NpadLeft" translatable="yes">Left Joycon</item> - <item id="NpadRight" translatable="yes">Right Joycon</item> + <item id="Japan" translatable="yes">Japan</item> + <item id="USA" translatable="yes">USA</item> + <item id="Europe" translatable="yes">Europe</item> + <item id="Australia" translatable="yes">Australia</item> + <item id="China" translatable="yes">China</item> + <item id="Korea" translatable="yes">Korea</item> + <item id="Taiwan" translatable="yes">Taiwan</item> </items> </object> <packing> - <property name="expand">True</property> + <property name="expand">False</property> <property name="fill">True</property> - <property name="position">1</property> + <property name="position">3</property> </packing> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="padding">10</property> + <property name="padding">5</property> <property name="position">0</property> </packing> </child> <child> - <object class="GtkGrid"> + <object class="GtkBox" id="LanguageBox"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">5</property> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">LStick Up</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">0</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">LStick Down</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">1</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">LStick Left</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">2</property> - </packing> - </child> <child> <object class="GtkLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">LStick Right</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">3</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">LStick Button</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">4</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Dpad Up</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">5</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Dpad Down</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">6</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Dpad Left</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">7</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Dpad Right</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">8</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">-</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">9</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">L</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">10</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">ZL</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">11</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">ZR</property> - </object> - <packing> - <property name="left_attach">2</property> - <property name="top_attach">11</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">R</property> - </object> - <packing> - <property name="left_attach">2</property> - <property name="top_attach">10</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">+</property> - </object> - <packing> - <property name="left_attach">2</property> - <property name="top_attach">9</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Y</property> + <property name="tooltip_text" translatable="yes">Change System Language</property> + <property name="halign">end</property> + <property name="label" translatable="yes">System Language:</property> </object> <packing> - <property name="left_attach">2</property> - <property name="top_attach">8</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">0</property> </packing> </child> <child> - <object class="GtkLabel"> + <object class="GtkComboBoxText" id="_systemLanguageSelect"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">X</property> + <property name="tooltip_text" translatable="yes">Change System Language</property> + <items> + <item id="AmericanEnglish" translatable="yes">American English</item> + <item id="BritishEnglish" translatable="yes">British English</item> + <item id="CanadianFrench" translatable="yes">Canadian French</item> + <item id="Chinese" translatable="yes">Chinese</item> + <item id="Dutch" translatable="yes">Dutch</item> + <item id="French" translatable="yes">French</item> + <item id="German" translatable="yes">German</item> + <item id="Italian" translatable="yes">Italian</item> + <item id="Japanese" translatable="yes">Japanese</item> + <item id="Korean" translatable="yes">Korean</item> + <item id="LatinAmericanSpanish" translatable="yes">Latin American Spanish</item> + <item id="Portuguese" translatable="yes">Portuguese</item> + <item id="Russian" translatable="yes">Russian</item> + <item id="SimplifiedChinese" translatable="yes">Simplified Chinese</item> + <item id="Spanish" translatable="yes">Spanish</item> + <item id="Taiwanese" translatable="yes">Taiwanese</item> + <item id="TraditionalChinese" translatable="yes">Traditional Chinese</item> + </items> </object> <packing> - <property name="left_attach">2</property> - <property name="top_attach">7</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> </packing> </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="TimeZoneBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> <child> <object class="GtkLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">B</property> + <property name="tooltip_text" translatable="yes">Change System TimeZone</property> + <property name="halign">end</property> + <property name="label" translatable="yes">System TimeZone:</property> </object> <packing> - <property name="left_attach">2</property> - <property name="top_attach">6</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">1</property> </packing> </child> <child> - <object class="GtkLabel"> + <object class="GtkComboBoxText" id="_systemTimeZoneSelect"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">A</property> + <property name="tooltip_text" translatable="yes">Change System TimeZone</property> + <property name="margin_left">5</property> </object> <packing> - <property name="left_attach">2</property> - <property name="top_attach">5</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> </packing> </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkBox" id="TimeBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> <child> <object class="GtkLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">RStick Button</property> + <property name="halign">end</property> + <property name="label" translatable="yes">System Time:</property> </object> <packing> - <property name="left_attach">2</property> - <property name="top_attach">4</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">0</property> </packing> </child> <child> - <object class="GtkLabel"> + <object class="GtkSpinButton" id="_systemTimeYearSpin"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">RStick Right</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">2000</property> + <property name="orientation">vertical</property> + <property name="adjustment">_systemTimeYearSpinAdjustment</property> + <property name="wrap">True</property> + <property name="value">2000</property> </object> <packing> - <property name="left_attach">2</property> - <property name="top_attach">3</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> </packing> </child> <child> <object class="GtkLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">RStick Left</property> + <property name="halign">end</property> + <property name="label">-</property> </object> <packing> - <property name="left_attach">2</property> - <property name="top_attach">2</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">2</property> </packing> </child> <child> - <object class="GtkLabel"> + <object class="GtkSpinButton" id="_systemTimeMonthSpin"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">RStick Down</property> + <property name="can_focus">True</property> + <property name="text" translatable="yes">1</property> + <property name="orientation">vertical</property> + <property name="adjustment">_systemTimeMonthSpinAdjustment</property> + <property name="wrap">True</property> + <property name="value">1</property> </object> <packing> - <property name="left_attach">2</property> - <property name="top_attach">1</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> </packing> </child> <child> <object class="GtkLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">RStick Up</property> - </object> - <packing> - <property name="left_attach">2</property> - <property name="top_attach">0</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_lStickUp1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">0</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_lStickDown1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">1</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_lStickLeft1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">2</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_lStickRight1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">3</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_lStickButton1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">4</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_dpadUp1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">5</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_dpadDown1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">6</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_dpadLeft1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">7</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_dpadRight1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">8</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_minus1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">9</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_l1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">10</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_zL1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">11</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_rStickUp1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">3</property> - <property name="top_attach">0</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_rStickDown1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">3</property> - <property name="top_attach">1</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_rStickLeft1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">3</property> - <property name="top_attach">2</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_rStickRight1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">3</property> - <property name="top_attach">3</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_rStickButton1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">3</property> - <property name="top_attach">4</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_a1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">3</property> - <property name="top_attach">5</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_b1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - </object> - <packing> - <property name="left_attach">3</property> - <property name="top_attach">6</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="_x1"> - <property name="label" translatable="yes"> </property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> + <property name="halign">end</property> + <property name="label">-</property> </object> <packing> - <property name="left_attach">3</property> - <property name="top_attach">7</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">4</property> </packing> </child> <child> - <object class="GtkToggleButton" id="_y1"> - <property name="label" translatable="yes"> </property> + <object class="GtkSpinButton" id="_systemTimeDaySpin"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="receives_default">True</property> + <property name="text" translatable="yes">1</property> + <property name="orientation">vertical</property> + <property name="adjustment">_systemTimeDaySpinAdjustment</property> + <property name="wrap">True</property> + <property name="value">1</property> </object> <packing> - <property name="left_attach">3</property> - <property name="top_attach">8</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">5</property> </packing> </child> <child> - <object class="GtkToggleButton" id="_plus1"> - <property name="label" translatable="yes"> </property> + <object class="GtkSpinButton" id="_systemTimeHourSpin"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="receives_default">True</property> + <property name="text" translatable="yes">0</property> + <property name="orientation">vertical</property> + <property name="adjustment">_systemTimeHourSpinAdjustment</property> + <property name="wrap">True</property> </object> <packing> - <property name="left_attach">3</property> - <property name="top_attach">9</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">6</property> </packing> </child> <child> - <object class="GtkToggleButton" id="_r1"> - <property name="label" translatable="yes"> </property> + <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> + <property name="can_focus">False</property> + <property name="halign">end</property> + <property name="label">:</property> </object> <packing> - <property name="left_attach">3</property> - <property name="top_attach">10</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">7</property> </packing> </child> <child> - <object class="GtkToggleButton" id="_zR1"> - <property name="label" translatable="yes"> </property> + <object class="GtkSpinButton" id="_systemTimeMinuteSpin"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="receives_default">True</property> + <property name="text" translatable="yes">0</property> + <property name="orientation">vertical</property> + <property name="adjustment">_systemTimeMinuteSpinAdjustment</property> + <property name="wrap">True</property> </object> <packing> - <property name="left_attach">3</property> - <property name="top_attach">11</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">8</property> </packing> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="padding">10</property> + <property name="padding">5</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="_vSyncToggle"> + <property name="label" translatable="yes">Enable VSync</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="tooltip_text" translatable="yes">Enables or disables Vertical Sync</property> + <property name="halign">start</property> + <property name="margin_top">5</property> + <property name="margin_bottom">5</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="_multiSchedToggle"> + <property name="label" translatable="yes">Enable Multicore Scheduling</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="tooltip_text" translatable="yes">Enables or disables multi-core scheduling of threads</property> + <property name="halign">start</property> + <property name="margin_top">5</property> + <property name="margin_bottom">5</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">5</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="_fsicToggle"> + <property name="label" translatable="yes">Enable FS Integrity Checks</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="tooltip_text" translatable="yes">Enables integrity checks on Game content files</property> + <property name="halign">start</property> + <property name="margin_top">5</property> + <property name="margin_bottom">5</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">6</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">5</property> + <property name="margin_right">5</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="CatHacks"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">start</property> + <property name="margin_left">5</property> + <property name="margin_right">5</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="margin_bottom">5</property> + <property name="label" translatable="yes">Hacks</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="margin_bottom">5</property> + <property name="label" translatable="yes"> - These may cause instability</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> @@ -1464,56 +1492,76 @@ <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">0</property> + <property name="position">1</property> </packing> </child> <child> - <object class="GtkImage" id="_controller1Image"> + <object class="GtkBox"> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="margin_left">10</property> + <property name="margin_right">10</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkCheckButton" id="_ignoreToggle"> + <property name="label" translatable="yes">Ignore Missing Services</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="tooltip_text" translatable="yes">Enable or disable ignoring missing services</property> + <property name="halign">start</property> + <property name="margin_top">5</property> + <property name="margin_bottom">5</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> </object> <packing> <property name="expand">True</property> <property name="fill">True</property> - <property name="position">1</property> + <property name="position">2</property> </packing> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">2</property> + <property name="padding">5</property> + <property name="position">4</property> </packing> </child> </object> <packing> - <property name="position">1</property> + <property name="position">2</property> </packing> </child> <child type="tab"> <object class="GtkLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">Input</property> + <property name="halign">end</property> + <property name="label" translatable="yes">System</property> </object> <packing> - <property name="position">1</property> + <property name="position">2</property> <property name="tab_fill">False</property> </packing> </child> <child> - <object class="GtkBox" id="TabSystem"> + <object class="GtkBox" id="TabGraphics"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="margin_left">5</property> - <property name="margin_right">10</property> <property name="margin_top">5</property> <property name="orientation">vertical</property> <child> - <object class="GtkBox" id="CatCore"> + <object class="GtkBox" id="CatEnhancements"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="valign">start</property> <property name="margin_left">5</property> <property name="margin_right">5</property> <property name="orientation">vertical</property> @@ -1523,8 +1571,9 @@ <property name="can_focus">False</property> <property name="halign">start</property> <property name="margin_left">5</property> + <property name="margin_right">5</property> <property name="margin_bottom">5</property> - <property name="label" translatable="yes">Core</property> + <property name="label" translatable="yes">Enhancements</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -1536,110 +1585,18 @@ </packing> </child> <child> - <object class="GtkBox"> + <object class="GtkBox" id="EnhancementOptions"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="margin_left">10</property> <property name="margin_right">10</property> <property name="orientation">vertical</property> <child> - <object class="GtkCheckButton" id="_vSyncToggle"> - <property name="label" translatable="yes">Enable VSync</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_text" translatable="yes">Enables or disables Vertical Sync</property> - <property name="halign">start</property> - <property name="margin_top">5</property> - <property name="margin_bottom">5</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="_multiSchedToggle"> - <property name="label" translatable="yes">Enable Multicore Scheduling</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_text" translatable="yes">Enables or disables multi-core scheduling of threads</property> - <property name="halign">start</property> - <property name="margin_top">5</property> - <property name="margin_bottom">5</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="_fsicToggle"> - <property name="label" translatable="yes">Enable FS Integrity Checks</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_text" translatable="yes">Enables integrity checks on Game content files</property> - <property name="halign">start</property> - <property name="margin_top">5</property> - <property name="margin_bottom">5</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkBox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Graphics Shaders Dump Path</property> - <property name="label" translatable="yes">Graphics Shaders Dump Path:</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="padding">5</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkEntry" id="_graphicsShadersDumpPath"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="tooltip_text" translatable="yes">Graphics Shaders Dump Path</property> - <property name="valign">center</property> - <property name="caps_lock_warning">False</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="padding">5</property> - <property name="position">3</property> - </packing> - </child> - <child> <object class="GtkBox"> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="margin_top">5</property> + <property name="margin_bottom">5</property> <child> <object class="GtkLabel"> <property name="visible">True</property> @@ -1679,12 +1636,12 @@ <property name="expand">False</property> <property name="fill">True</property> <property name="padding">5</property> - <property name="position">4</property> + <property name="position">0</property> </packing> </child> </object> <packing> - <property name="expand">True</property> + <property name="expand">False</property> <property name="fill">True</property> <property name="position">1</property> </packing> @@ -1701,8 +1658,6 @@ <object class="GtkSeparator"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="margin_left">5</property> - <property name="margin_right">5</property> </object> <packing> <property name="expand">False</property> @@ -1712,7 +1667,7 @@ </packing> </child> <child> - <object class="GtkBox" id="CatLog"> + <object class="GtkBox" id="CatDev"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="margin_left">5</property> @@ -1723,8 +1678,10 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="halign">start</property> + <property name="margin_left">5</property> + <property name="margin_right">5</property> <property name="margin_bottom">5</property> - <property name="label" translatable="yes">Logging</property> + <property name="label" translatable="yes">Developer Options</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -1736,7 +1693,7 @@ </packing> </child> <child> - <object class="GtkBox"> + <object class="GtkBox" id="DevOptions"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="margin_left">10</property> @@ -1746,38 +1703,32 @@ <object class="GtkBox"> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="margin_top">5</property> + <property name="margin_bottom">5</property> <child> - <object class="GtkCheckButton" id="_fileLogToggle"> - <property name="label" translatable="yes">Enable Logging to File</property> + <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_text" translatable="yes">Enables or disables logging to a file on disk</property> - <property name="halign">start</property> - <property name="margin_top">5</property> - <property name="margin_bottom">5</property> - <property name="draw_indicator">True</property> + <property name="can_focus">False</property> + <property name="tooltip_text" translatable="yes">Graphics Shaders Dump Path</property> + <property name="label" translatable="yes">Graphics Shaders Dump Path:</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> + <property name="padding">5</property> <property name="position">0</property> </packing> </child> <child> - <object class="GtkButton" id="_openLogsFolderButton"> - <property name="label" translatable="yes">Open Logs Folder</property> + <object class="GtkEntry" id="_graphicsShadersDumpPath"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_text" translatable="yes">Opens the folder where logs are written to.</property> - <property name="margin_left">5</property> - <property name="margin_top">5</property> - <property name="margin_bottom">5</property> - <signal name="clicked" handler="OpenLogsFolder_Pressed" swapped="no"/> + <property name="tooltip_text" translatable="yes">Graphics Shaders Dump Path</property> + <property name="valign">center</property> + <property name="caps_lock_warning">False</property> </object> <packing> - <property name="expand">False</property> + <property name="expand">True</property> <property name="fill">True</property> <property name="position">1</property> </packing> @@ -1786,9 +1737,116 @@ <packing> <property name="expand">False</property> <property name="fill">True</property> + <property name="padding">5</property> <property name="position">0</property> </packing> </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">4</property> + </packing> + </child> + </object> + <packing> + <property name="position">3</property> + </packing> + </child> + <child type="tab"> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Graphics</property> + </object> + <packing> + <property name="position">3</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <object class="GtkBox" id="TabLogging"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">5</property> + <property name="margin_right">10</property> + <property name="margin_top">5</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkBox" id="CatLogging"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">5</property> + <property name="margin_right">5</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="margin_bottom">5</property> + <property name="label" translatable="yes">Logging</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="LogggingOptions"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">start</property> + <property name="margin_left">10</property> + <property name="margin_right">10</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkCheckButton" id="_fileLogToggle"> + <property name="label" translatable="yes">Enable Logging to File</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="tooltip_text" translatable="yes">Enables or disables logging to a file on disk</property> + <property name="halign">start</property> + <property name="margin_top">5</property> + <property name="margin_bottom">5</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="_openLogsFolderButton"> + <property name="label" translatable="yes">Open Logs Folder</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="tooltip_text" translatable="yes">Opens the folder where logs are written to.</property> + <property name="halign">start</property> + <property name="margin_bottom">10</property> + <signal name="clicked" handler="OpenLogsFolder_Pressed" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> <child> <object class="GtkCheckButton" id="_debugLogToggle"> <property name="label" translatable="yes">Enable Debug Logs</property> @@ -1938,6 +1996,7 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="tooltip_text" translatable="yes">Enables FS access log output to the console. Possible modes are 0-3</property> + <property name="text" translatable="yes">0</property> <property name="adjustment">_fsLogSpinAdjustment</property> </object> <packing> @@ -1966,126 +2025,22 @@ <property name="expand">False</property> <property name="fill">True</property> <property name="padding">5</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkSeparator"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_left">5</property> - <property name="margin_right">5</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="padding">5</property> - <property name="position">3</property> - </packing> - </child> - <child> - <object class="GtkBox" id="CatHacks"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_left">5</property> - <property name="margin_right">5</property> - <property name="orientation">vertical</property> - <child> - <object class="GtkBox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="halign">start</property> - <property name="margin_bottom">5</property> - <property name="label" translatable="yes">Hacks</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="halign">start</property> - <property name="margin_bottom">5</property> - <property name="label" translatable="yes"> - These may cause instability</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkBox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_left">10</property> - <property name="margin_right">10</property> - <property name="orientation">vertical</property> - <child> - <object class="GtkCheckButton" id="_ignoreToggle"> - <property name="label" translatable="yes">Ignore Missing Services</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_text" translatable="yes">Enable or disable ignoring missing services</property> - <property name="halign">start</property> - <property name="margin_top">5</property> - <property name="margin_bottom">5</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="padding">5</property> - <property name="position">4</property> + <property name="position">0</property> </packing> </child> </object> <packing> - <property name="position">2</property> + <property name="position">4</property> </packing> </child> <child type="tab"> <object class="GtkLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="halign">end</property> - <property name="label" translatable="yes">System</property> + <property name="label" translatable="yes">Logging</property> </object> <packing> - <property name="position">2</property> + <property name="position">4</property> <property name="tab_fill">False</property> </packing> </child> @@ -2097,10 +2052,83 @@ <packing> <property name="expand">True</property> <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButtonBox" id="_buttonBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_right">5</property> + <property name="margin_top">3</property> + <property name="margin_bottom">3</property> + <property name="layout_style">end</property> + <child> + <object class="GtkToggleButton" id="SaveToggle"> + <property name="label" translatable="yes">Save</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="toggled" handler="SaveToggle_Activated" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="CloseToggle"> + <property name="label" translatable="yes">Close</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">4</property> + <signal name="toggled" handler="CloseToggle_Activated" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">5</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> <property name="position">1</property> </packing> </child> </object> </child> </object> + <object class="GtkAdjustment" id="_systemTimeDaySpinAdjustment"> + <property name="lower">1</property> + <property name="upper">31</property> + <property name="step_increment">1</property> + <property name="page_increment">5</property> + </object> + <object class="GtkAdjustment" id="_systemTimeHourSpinAdjustment"> + <property name="upper">23</property> + <property name="step_increment">1</property> + <property name="page_increment">5</property> + </object> + <object class="GtkAdjustment" id="_systemTimeMinuteSpinAdjustment"> + <property name="upper">59</property> + <property name="step_increment">1</property> + <property name="page_increment">5</property> + </object> + <object class="GtkAdjustment" id="_systemTimeMonthSpinAdjustment"> + <property name="lower">1</property> + <property name="upper">12</property> + <property name="step_increment">1</property> + <property name="page_increment">5</property> + </object> + <object class="GtkAdjustment" id="_systemTimeYearSpinAdjustment"> + <property name="lower">2000</property> + <property name="upper">2060</property> + <property name="step_increment">1</property> + <property name="page_increment">10</property> + </object> </interface> diff --git a/Ryujinx/Ui/SwitchSettings.cs b/Ryujinx/Ui/SwitchSettings.cs deleted file mode 100644 index 28435572..00000000 --- a/Ryujinx/Ui/SwitchSettings.cs +++ /dev/null @@ -1,611 +0,0 @@ -using Gtk; -using Ryujinx.Configuration; -using Ryujinx.Configuration.Hid; -using Ryujinx.Configuration.System; -using Ryujinx.HLE.HOS.Services.Time.TimeZone; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; - -using GUI = Gtk.Builder.ObjectAttribute; - -namespace Ryujinx.Ui -{ - public class SwitchSettings : Window - { - private static ListStore _gameDirsBoxStore; - - private static bool _listeningForKeypress; - - private long _systemTimeOffset; - -#pragma warning disable CS0649 -#pragma warning disable IDE0044 - [GUI] Window _settingsWin; - [GUI] CheckButton _errorLogToggle; - [GUI] CheckButton _warningLogToggle; - [GUI] CheckButton _infoLogToggle; - [GUI] CheckButton _stubLogToggle; - [GUI] CheckButton _debugLogToggle; - [GUI] CheckButton _fileLogToggle; - [GUI] CheckButton _guestLogToggle; - [GUI] CheckButton _fsAccessLogToggle; - [GUI] Adjustment _fsLogSpinAdjustment; - [GUI] CheckButton _dockedModeToggle; - [GUI] CheckButton _discordToggle; - [GUI] CheckButton _vSyncToggle; - [GUI] CheckButton _multiSchedToggle; - [GUI] CheckButton _fsicToggle; - [GUI] CheckButton _ignoreToggle; - [GUI] CheckButton _directKeyboardAccess; - [GUI] ComboBoxText _systemLanguageSelect; - [GUI] ComboBoxText _systemRegionSelect; - [GUI] ComboBoxText _systemTimeZoneSelect; - [GUI] SpinButton _systemTimeYearSpin; - [GUI] SpinButton _systemTimeMonthSpin; - [GUI] SpinButton _systemTimeDaySpin; - [GUI] SpinButton _systemTimeHourSpin; - [GUI] SpinButton _systemTimeMinuteSpin; - [GUI] Adjustment _systemTimeYearSpinAdjustment; - [GUI] Adjustment _systemTimeMonthSpinAdjustment; - [GUI] Adjustment _systemTimeDaySpinAdjustment; - [GUI] Adjustment _systemTimeHourSpinAdjustment; - [GUI] Adjustment _systemTimeMinuteSpinAdjustment; - [GUI] CheckButton _custThemeToggle; - [GUI] Entry _custThemePath; - [GUI] ToggleButton _browseThemePath; - [GUI] Label _custThemePathLabel; - [GUI] TreeView _gameDirsBox; - [GUI] Entry _addGameDirBox; - [GUI] ToggleButton _addDir; - [GUI] ToggleButton _browseDir; - [GUI] ToggleButton _removeDir; - [GUI] Entry _graphicsShadersDumpPath; - [GUI] ComboBoxText _anisotropy; - [GUI] Image _controller1Image; - - [GUI] ComboBoxText _controller1Type; - [GUI] ToggleButton _lStickUp1; - [GUI] ToggleButton _lStickDown1; - [GUI] ToggleButton _lStickLeft1; - [GUI] ToggleButton _lStickRight1; - [GUI] ToggleButton _lStickButton1; - [GUI] ToggleButton _dpadUp1; - [GUI] ToggleButton _dpadDown1; - [GUI] ToggleButton _dpadLeft1; - [GUI] ToggleButton _dpadRight1; - [GUI] ToggleButton _minus1; - [GUI] ToggleButton _l1; - [GUI] ToggleButton _zL1; - [GUI] ToggleButton _rStickUp1; - [GUI] ToggleButton _rStickDown1; - [GUI] ToggleButton _rStickLeft1; - [GUI] ToggleButton _rStickRight1; - [GUI] ToggleButton _rStickButton1; - [GUI] ToggleButton _a1; - [GUI] ToggleButton _b1; - [GUI] ToggleButton _x1; - [GUI] ToggleButton _y1; - [GUI] ToggleButton _plus1; - [GUI] ToggleButton _r1; - [GUI] ToggleButton _zR1; -#pragma warning restore CS0649 -#pragma warning restore IDE0044 - - public SwitchSettings(HLE.FileSystem.VirtualFileSystem virtualFileSystem, HLE.FileSystem.Content.ContentManager contentManager) : this(new Builder("Ryujinx.Ui.SwitchSettings.glade"), virtualFileSystem, contentManager) { } - - private SwitchSettings(Builder builder, HLE.FileSystem.VirtualFileSystem virtualFileSystem, HLE.FileSystem.Content.ContentManager contentManager) : base(builder.GetObject("_settingsWin").Handle) - { - builder.Autoconnect(this); - - _settingsWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"); - _controller1Image.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.JoyCon.png", 500, 500); - - //Bind Events - _lStickUp1.Clicked += (sender, args) => Button_Pressed(sender, args, _lStickUp1); - _lStickDown1.Clicked += (sender, args) => Button_Pressed(sender, args, _lStickDown1); - _lStickLeft1.Clicked += (sender, args) => Button_Pressed(sender, args, _lStickLeft1); - _lStickRight1.Clicked += (sender, args) => Button_Pressed(sender, args, _lStickRight1); - _lStickButton1.Clicked += (sender, args) => Button_Pressed(sender, args, _lStickButton1); - _dpadUp1.Clicked += (sender, args) => Button_Pressed(sender, args, _dpadUp1); - _dpadDown1.Clicked += (sender, args) => Button_Pressed(sender, args, _dpadDown1); - _dpadLeft1.Clicked += (sender, args) => Button_Pressed(sender, args, _dpadLeft1); - _dpadRight1.Clicked += (sender, args) => Button_Pressed(sender, args, _dpadRight1); - _minus1.Clicked += (sender, args) => Button_Pressed(sender, args, _minus1); - _l1.Clicked += (sender, args) => Button_Pressed(sender, args, _l1); - _zL1.Clicked += (sender, args) => Button_Pressed(sender, args, _zL1); - _rStickUp1.Clicked += (sender, args) => Button_Pressed(sender, args, _rStickUp1); - _rStickDown1.Clicked += (sender, args) => Button_Pressed(sender, args, _rStickDown1); - _rStickLeft1.Clicked += (sender, args) => Button_Pressed(sender, args, _rStickLeft1); - _rStickRight1.Clicked += (sender, args) => Button_Pressed(sender, args, _rStickRight1); - _rStickButton1.Clicked += (sender, args) => Button_Pressed(sender, args, _rStickButton1); - _a1.Clicked += (sender, args) => Button_Pressed(sender, args, _a1); - _b1.Clicked += (sender, args) => Button_Pressed(sender, args, _b1); - _x1.Clicked += (sender, args) => Button_Pressed(sender, args, _x1); - _y1.Clicked += (sender, args) => Button_Pressed(sender, args, _y1); - _plus1.Clicked += (sender, args) => Button_Pressed(sender, args, _plus1); - _r1.Clicked += (sender, args) => Button_Pressed(sender, args, _r1); - _zR1.Clicked += (sender, args) => Button_Pressed(sender, args, _zR1); - _controller1Type.Changed += (sender, args) => Controller_Changed(sender, args, _controller1Type.ActiveId, _controller1Image); - - //Setup Currents - if (ConfigurationState.Instance.Logger.EnableFileLog) - { - _fileLogToggle.Click(); - } - - if (ConfigurationState.Instance.Logger.EnableError) - { - _errorLogToggle.Click(); - } - - if (ConfigurationState.Instance.Logger.EnableWarn) - { - _warningLogToggle.Click(); - } - - if (ConfigurationState.Instance.Logger.EnableInfo) - { - _infoLogToggle.Click(); - } - - if (ConfigurationState.Instance.Logger.EnableStub) - { - _stubLogToggle.Click(); - } - - if (ConfigurationState.Instance.Logger.EnableDebug) - { - _debugLogToggle.Click(); - } - - if (ConfigurationState.Instance.Logger.EnableGuest) - { - _guestLogToggle.Click(); - } - - if (ConfigurationState.Instance.Logger.EnableFsAccessLog) - { - _fsAccessLogToggle.Click(); - } - - if (ConfigurationState.Instance.System.EnableDockedMode) - { - _dockedModeToggle.Click(); - } - - if (ConfigurationState.Instance.EnableDiscordIntegration) - { - _discordToggle.Click(); - } - - if (ConfigurationState.Instance.Graphics.EnableVsync) - { - _vSyncToggle.Click(); - } - - if (ConfigurationState.Instance.System.EnableMulticoreScheduling) - { - _multiSchedToggle.Click(); - } - - if (ConfigurationState.Instance.System.EnableFsIntegrityChecks) - { - _fsicToggle.Click(); - } - - if (ConfigurationState.Instance.System.IgnoreMissingServices) - { - _ignoreToggle.Click(); - } - - if (ConfigurationState.Instance.Hid.EnableKeyboard) - { - _directKeyboardAccess.Click(); - } - - if (ConfigurationState.Instance.Ui.EnableCustomTheme) - { - _custThemeToggle.Click(); - } - - TimeZoneContentManager timeZoneContentManager = new TimeZoneContentManager(); - - timeZoneContentManager.InitializeInstance(virtualFileSystem, contentManager, LibHac.FsSystem.IntegrityCheckLevel.None); - - List<string> locationNames = timeZoneContentManager.LocationNameCache.ToList(); - - locationNames.Sort(); - - foreach (string locationName in locationNames) - { - _systemTimeZoneSelect.Append(locationName, locationName); - } - - _systemLanguageSelect.SetActiveId(ConfigurationState.Instance.System.Language.Value.ToString()); - _systemRegionSelect .SetActiveId(ConfigurationState.Instance.System.Region.Value.ToString()); - _systemTimeZoneSelect.SetActiveId(timeZoneContentManager.SanityCheckDeviceLocationName()); - _anisotropy .SetActiveId(ConfigurationState.Instance.Graphics.MaxAnisotropy.Value.ToString()); - _controller1Type .SetActiveId(ConfigurationState.Instance.Hid.ControllerType.Value.ToString()); - Controller_Changed(null, null, _controller1Type.ActiveId, _controller1Image); - - _lStickUp1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.StickUp.ToString(); - _lStickDown1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.StickDown.ToString(); - _lStickLeft1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.StickLeft.ToString(); - _lStickRight1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.StickRight.ToString(); - _lStickButton1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.StickButton.ToString(); - _dpadUp1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.DPadUp.ToString(); - _dpadDown1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.DPadDown.ToString(); - _dpadLeft1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.DPadLeft.ToString(); - _dpadRight1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.DPadRight.ToString(); - _minus1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.ButtonMinus.ToString(); - _l1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.ButtonL.ToString(); - _zL1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.ButtonZl.ToString(); - _rStickUp1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.StickUp.ToString(); - _rStickDown1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.StickDown.ToString(); - _rStickLeft1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.StickLeft.ToString(); - _rStickRight1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.StickRight.ToString(); - _rStickButton1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.StickButton.ToString(); - _a1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonA.ToString(); - _b1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonB.ToString(); - _x1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonX.ToString(); - _y1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonY.ToString(); - _plus1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonPlus.ToString(); - _r1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonR.ToString(); - _zR1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonZr.ToString(); - - _custThemePath.Buffer.Text = ConfigurationState.Instance.Ui.CustomThemePath; - _graphicsShadersDumpPath.Buffer.Text = ConfigurationState.Instance.Graphics.ShadersDumpPath; - _fsLogSpinAdjustment.Value = ConfigurationState.Instance.System.FsGlobalAccessLogMode; - _systemTimeOffset = ConfigurationState.Instance.System.SystemTimeOffset; - - _gameDirsBox.AppendColumn("", new CellRendererText(), "text", 0); - _gameDirsBoxStore = new ListStore(typeof(string)); - _gameDirsBox.Model = _gameDirsBoxStore; - - foreach (string gameDir in ConfigurationState.Instance.Ui.GameDirs.Value) - { - _gameDirsBoxStore.AppendValues(gameDir); - } - - if (_custThemeToggle.Active == false) - { - _custThemePath.Sensitive = false; - _custThemePathLabel.Sensitive = false; - _browseThemePath.Sensitive = false; - } - - _listeningForKeypress = false; - - //Setup system time spinners - UpdateSystemTimeSpinners(); - } - - private void UpdateSystemTimeSpinners() - { - //Unbind system time spin events - _systemTimeYearSpin.ValueChanged -= SystemTimeSpin_ValueChanged; - _systemTimeMonthSpin.ValueChanged -= SystemTimeSpin_ValueChanged; - _systemTimeDaySpin.ValueChanged -= SystemTimeSpin_ValueChanged; - _systemTimeHourSpin.ValueChanged -= SystemTimeSpin_ValueChanged; - _systemTimeMinuteSpin.ValueChanged -= SystemTimeSpin_ValueChanged; - - //Apply actual system time + SystemTimeOffset to system time spin buttons - DateTime systemTime = DateTime.Now.AddSeconds(_systemTimeOffset); - - _systemTimeYearSpinAdjustment.Value = systemTime.Year; - _systemTimeMonthSpinAdjustment.Value = systemTime.Month; - _systemTimeDaySpinAdjustment.Value = systemTime.Day; - _systemTimeHourSpinAdjustment.Value = systemTime.Hour; - _systemTimeMinuteSpinAdjustment.Value = systemTime.Minute; - - //Format spin buttons text to include leading zeros - _systemTimeYearSpin.Text = systemTime.Year.ToString("0000"); - _systemTimeMonthSpin.Text = systemTime.Month.ToString("00"); - _systemTimeDaySpin.Text = systemTime.Day.ToString("00"); - _systemTimeHourSpin.Text = systemTime.Hour.ToString("00"); - _systemTimeMinuteSpin.Text = systemTime.Minute.ToString("00"); - - //Bind system time spin button events - _systemTimeYearSpin.ValueChanged += SystemTimeSpin_ValueChanged; - _systemTimeMonthSpin.ValueChanged += SystemTimeSpin_ValueChanged; - _systemTimeDaySpin.ValueChanged += SystemTimeSpin_ValueChanged; - _systemTimeHourSpin.ValueChanged += SystemTimeSpin_ValueChanged; - _systemTimeMinuteSpin.ValueChanged += SystemTimeSpin_ValueChanged; - } - - //Events - private void SystemTimeSpin_ValueChanged(Object sender, EventArgs e) - { - int year = _systemTimeYearSpin.ValueAsInt; - int month = _systemTimeMonthSpin.ValueAsInt; - int day = _systemTimeDaySpin.ValueAsInt; - int hour = _systemTimeHourSpin.ValueAsInt; - int minute = _systemTimeMinuteSpin.ValueAsInt; - - if (!DateTime.TryParse(year + "-" + month + "-" + day + " " + hour + ":" + minute, out DateTime newTime)) - { - UpdateSystemTimeSpinners(); - - return; - } - - newTime = newTime.AddSeconds(DateTime.Now.Second).AddMilliseconds(DateTime.Now.Millisecond); - - long systemTimeOffset = (long)Math.Ceiling((newTime - DateTime.Now).TotalMinutes) * 60L; - - if (_systemTimeOffset != systemTimeOffset) - { - _systemTimeOffset = systemTimeOffset; - UpdateSystemTimeSpinners(); - } - } - - private void Button_Pressed(object sender, EventArgs args, ToggleButton button) - { - if (_listeningForKeypress == false) - { - KeyPressEvent += On_KeyPress; - - _listeningForKeypress = true; - - void On_KeyPress(object o, KeyPressEventArgs keyPressed) - { - string key = keyPressed.Event.Key.ToString(); - string capKey = key.First().ToString().ToUpper() + key.Substring(1); - - if (Enum.IsDefined(typeof(Configuration.Hid.Key), capKey)) - { - button.Label = capKey; - } - else if (GdkToOpenTkInput.ContainsKey(key)) - { - button.Label = GdkToOpenTkInput[key]; - } - else - { - button.Label = "Space"; - } - - button.SetStateFlags(0, true); - - KeyPressEvent -= On_KeyPress; - - _listeningForKeypress = false; - } - } - else - { - button.SetStateFlags(0, true); - } - } - - private void Controller_Changed(object sender, EventArgs args, string controllerType, Image controllerImage) - { - switch (controllerType) - { - case "ProController": - controllerImage.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.ProCon.png", 500, 500); - break; - case "NpadLeft": - controllerImage.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.BlueCon.png", 500, 500); - break; - case "NpadRight": - controllerImage.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.RedCon.png", 500, 500); - break; - default: - controllerImage.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.JoyCon.png", 500, 500); - break; - } - } - - private void AddDir_Pressed(object sender, EventArgs args) - { - if (Directory.Exists(_addGameDirBox.Buffer.Text)) - { - _gameDirsBoxStore.AppendValues(_addGameDirBox.Buffer.Text); - } - - _addDir.SetStateFlags(0, true); - } - - private void BrowseDir_Pressed(object sender, EventArgs args) - { - FileChooserDialog fileChooser = new FileChooserDialog("Choose the game directory to add to the list", this, FileChooserAction.SelectFolder, "Cancel", ResponseType.Cancel, "Add", ResponseType.Accept); - - if (fileChooser.Run() == (int)ResponseType.Accept) - { - _gameDirsBoxStore.AppendValues(fileChooser.Filename); - } - - fileChooser.Dispose(); - - _browseDir.SetStateFlags(0, true); - } - - private void RemoveDir_Pressed(object sender, EventArgs args) - { - TreeSelection selection = _gameDirsBox.Selection; - - selection.GetSelected(out TreeIter treeIter); - _gameDirsBoxStore.Remove(ref treeIter); - - _removeDir.SetStateFlags(0, true); - } - - private void CustThemeToggle_Activated(object sender, EventArgs args) - { - _custThemePath.Sensitive = _custThemeToggle.Active; - _custThemePathLabel.Sensitive = _custThemeToggle.Active; - _browseThemePath.Sensitive = _custThemeToggle.Active; - } - - private void BrowseThemeDir_Pressed(object sender, EventArgs args) - { - FileChooserDialog fileChooser = new FileChooserDialog("Choose the theme to load", this, FileChooserAction.Open, "Cancel", ResponseType.Cancel, "Select", ResponseType.Accept); - - fileChooser.Filter = new FileFilter(); - fileChooser.Filter.AddPattern("*.css"); - - if (fileChooser.Run() == (int)ResponseType.Accept) - { - _custThemePath.Buffer.Text = fileChooser.Filename; - } - - fileChooser.Dispose(); - - _browseThemePath.SetStateFlags(0, true); - } - - private void OpenLogsFolder_Pressed(object sender, EventArgs args) - { - string logPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"); - - DirectoryInfo directory = new DirectoryInfo(logPath); - directory.Create(); - - Process.Start(new ProcessStartInfo() - { - FileName = logPath, - UseShellExecute = true, - Verb = "open" - }); - } - - private void SaveToggle_Activated(object sender, EventArgs args) - { - List<string> gameDirs = new List<string>(); - - _gameDirsBoxStore.GetIterFirst(out TreeIter treeIter); - for (int i = 0; i < _gameDirsBoxStore.IterNChildren(); i++) - { - _gameDirsBoxStore.GetValue(treeIter, i); - - gameDirs.Add((string)_gameDirsBoxStore.GetValue(treeIter, 0)); - - _gameDirsBoxStore.IterNext(ref treeIter); - } - - ConfigurationState.Instance.Logger.EnableError.Value = _errorLogToggle.Active; - ConfigurationState.Instance.Logger.EnableWarn.Value = _warningLogToggle.Active; - ConfigurationState.Instance.Logger.EnableInfo.Value = _infoLogToggle.Active; - ConfigurationState.Instance.Logger.EnableStub.Value = _stubLogToggle.Active; - ConfigurationState.Instance.Logger.EnableDebug.Value = _debugLogToggle.Active; - ConfigurationState.Instance.Logger.EnableGuest.Value = _guestLogToggle.Active; - ConfigurationState.Instance.Logger.EnableFsAccessLog.Value = _fsAccessLogToggle.Active; - ConfigurationState.Instance.Logger.EnableFileLog.Value = _fileLogToggle.Active; - ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active; - ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active; - ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active; - ConfigurationState.Instance.System.EnableMulticoreScheduling.Value = _multiSchedToggle.Active; - ConfigurationState.Instance.System.EnableFsIntegrityChecks.Value = _fsicToggle.Active; - ConfigurationState.Instance.System.IgnoreMissingServices.Value = _ignoreToggle.Active; - ConfigurationState.Instance.Hid.EnableKeyboard.Value = _directKeyboardAccess.Active; - ConfigurationState.Instance.Ui.EnableCustomTheme.Value = _custThemeToggle.Active; - - ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon = new NpadKeyboardLeft() - { - StickUp = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _lStickUp1.Label), - StickDown = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _lStickDown1.Label), - StickLeft = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _lStickLeft1.Label), - StickRight = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _lStickRight1.Label), - StickButton = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _lStickButton1.Label), - DPadUp = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _dpadUp1.Label), - DPadDown = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _dpadDown1.Label), - DPadLeft = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _dpadLeft1.Label), - DPadRight = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _dpadRight1.Label), - ButtonMinus = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _minus1.Label), - ButtonL = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _l1.Label), - ButtonZl = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _zL1.Label), - }; - - ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon = new NpadKeyboardRight() - { - StickUp = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _rStickUp1.Label), - StickDown = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _rStickDown1.Label), - StickLeft = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _rStickLeft1.Label), - StickRight = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _rStickRight1.Label), - StickButton = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _rStickButton1.Label), - ButtonA = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _a1.Label), - ButtonB = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _b1.Label), - ButtonX = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _x1.Label), - ButtonY = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _y1.Label), - ButtonPlus = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _plus1.Label), - ButtonR = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _r1.Label), - ButtonZr = (Configuration.Hid.Key)Enum.Parse(typeof(Configuration.Hid.Key), _zR1.Label), - }; - - ConfigurationState.Instance.System.Language.Value = (Language)Enum.Parse(typeof(Language), _systemLanguageSelect.ActiveId); - ConfigurationState.Instance.System.Region.Value = (Configuration.System.Region)Enum.Parse(typeof(Configuration.System.Region), _systemRegionSelect.ActiveId); - ConfigurationState.Instance.Graphics.MaxAnisotropy.Value = float.Parse(_anisotropy.ActiveId); - ConfigurationState.Instance.Hid.ControllerType.Value = (ControllerType)Enum.Parse(typeof(ControllerType), _controller1Type.ActiveId); - ConfigurationState.Instance.Ui.CustomThemePath.Value = _custThemePath.Buffer.Text; - ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = _graphicsShadersDumpPath.Buffer.Text; - ConfigurationState.Instance.Ui.GameDirs.Value = gameDirs; - ConfigurationState.Instance.System.FsGlobalAccessLogMode.Value = (int)_fsLogSpinAdjustment.Value; - - ConfigurationState.Instance.System.TimeZone.Value = _systemTimeZoneSelect.ActiveId; - ConfigurationState.Instance.System.SystemTimeOffset.Value = _systemTimeOffset; - - MainWindow.SaveConfig(); - MainWindow.ApplyTheme(); - MainWindow.UpdateGameTable(); - Dispose(); - } - - private void CloseToggle_Activated(object sender, EventArgs args) - { - Dispose(); - } - - public readonly Dictionary<string, string> GdkToOpenTkInput = new Dictionary<string, string>() - { - { "Key_0", "Number0" }, - { "Key_1", "Number1" }, - { "Key_2", "Number2" }, - { "Key_3", "Number3" }, - { "Key_4", "Number4" }, - { "Key_5", "Number5" }, - { "Key_6", "Number6" }, - { "Key_7", "Number7" }, - { "Key_8", "Number8" }, - { "Key_9", "Number9" }, - { "equal", "Plus" }, - { "uparrow", "Up" }, - { "downarrow", "Down" }, - { "leftarrow", "Left" }, - { "rightarrow", "Right" }, - { "Control_L", "ControlLeft" }, - { "Control_R", "ControlRight" }, - { "Shift_L", "ShiftLeft" }, - { "Shift_R", "ShiftRight" }, - { "Alt_L", "AltLeft" }, - { "Alt_R", "AltRight" }, - { "Page_Up", "PageUp" }, - { "Page_Down", "PageDown" }, - { "KP_Enter", "KeypadEnter" }, - { "KP_Up", "Up" }, - { "KP_Down", "Down" }, - { "KP_Left", "Left" }, - { "KP_Right", "Right" }, - { "KP_Divide", "KeypadDivide" }, - { "KP_Multiply", "KeypadMultiply" }, - { "KP_Subtract", "KeypadSubtract" }, - { "KP_Add", "KeypadAdd" }, - { "KP_Decimal", "KeypadDecimal" }, - { "KP_0", "Keypad0" }, - { "KP_1", "Keypad1" }, - { "KP_2", "Keypad2" }, - { "KP_3", "Keypad3" }, - { "KP_4", "Keypad4" }, - { "KP_5", "Keypad5" }, - { "KP_6", "Keypad6" }, - { "KP_7", "Keypad7" }, - { "KP_8", "Keypad8" }, - { "KP_9", "Keypad9" }, - }; - } -} diff --git a/Ryujinx/Ui/TitleUpdateWindow.cs b/Ryujinx/Ui/TitleUpdateWindow.cs index 6808b4da..06d0dcdb 100644 --- a/Ryujinx/Ui/TitleUpdateWindow.cs +++ b/Ryujinx/Ui/TitleUpdateWindow.cs @@ -133,7 +133,7 @@ namespace Ryujinx.Ui if (showErrorDialog) { - GtkDialog.CreateDialog("Ryujinx - Error", "Add Update Failed!", "The NCA header content type check has failed. This is usually because the header key is incorrect or missing."); + GtkDialog.CreateInfoDialog("Ryujinx - Error", "Add Update Failed!", "The NCA header content type check has failed. This is usually because the header key is incorrect or missing."); } break; @@ -144,7 +144,7 @@ namespace Ryujinx.Ui if (showErrorDialog) { - GtkDialog.CreateDialog("Ryujinx - Error", "Add Update Failed!", $"Your key set is missing a key with the name: {exception.Name}"); + GtkDialog.CreateInfoDialog("Ryujinx - Error", "Add Update Failed!", $"Your key set is missing a key with the name: {exception.Name}"); } break; diff --git a/Ryujinx/Ui/assets/BlueCon.png b/Ryujinx/Ui/assets/BlueCon.png Binary files differdeleted file mode 100644 index 25691957..00000000 --- a/Ryujinx/Ui/assets/BlueCon.png +++ /dev/null diff --git a/Ryujinx/Ui/assets/JoyCon.png b/Ryujinx/Ui/assets/JoyCon.png Binary files differdeleted file mode 100644 index ec745863..00000000 --- a/Ryujinx/Ui/assets/JoyCon.png +++ /dev/null diff --git a/Ryujinx/Ui/assets/JoyConLeft.svg b/Ryujinx/Ui/assets/JoyConLeft.svg new file mode 100644 index 00000000..40d06136 --- /dev/null +++ b/Ryujinx/Ui/assets/JoyConLeft.svg @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 1000.8 1000" style="enable-background:new 0 0 1000.8 1000;" xml:space="preserve"> +<style type="text/css"> + .st0{opacity:0.1;} + .st1{fill:#02C5E5;} + .st2{fill:#FFFFFF;} +</style> +<g class="st0"> + <path class="st1" d="M419.1,642.6v67.6c0,3.3-2.7,6-6,6h-4.2v-79.5h4.2C416.4,636.6,419.1,639.3,419.1,642.6z"/> + <path class="st1" d="M419.1,239.8v67.6c0,3.3-2.7,6-6,6h-4.2v-79.5h4.2C416.4,233.9,419.1,236.5,419.1,239.8z"/> + <path class="st1" d="M330.1,7v2.6h-54.2c-84.8,0-161.4,50.7-194.6,128.7l-3.4-3.4c-1.8-1.7-2.3-4.4-1.3-6.6 + C111.2,50.8,188.1,1,272.9,1h51.2C327.4,1,330.1,3.7,330.1,7z"/> + <path class="st1" d="M359.6,115.1h-46.9c-1.6,0-3-1.3-3-3v-11.7c0-1.6,1.3-3,3-3h46.9c1.6,0,3,1.3,3,3v11.7 + C362.6,113.8,361.3,115.1,359.6,115.1z"/> + <circle class="st1" cx="237.9" cy="464.4" r="37.5"/> + <circle class="st1" cx="237.9" cy="611.3" r="37.5"/> + <circle class="st1" cx="311.4" cy="537.9" r="37.5"/> + <ellipse class="st1" cx="164.5" cy="537.9" rx="37.5" ry="37.5"/> + <path class="st1" d="M269.1,689.9h45c4.9,0,8.9,4,8.9,8.9v45c0,4.9-4,8.9-8.9,8.9h-45c-4.9,0-8.9-4-8.9-8.9v-45 + C260.2,693.9,264.2,689.9,269.1,689.9z"/> + <circle class="st1" cx="291.6" cy="721.3" r="19.4"/> + <path class="st1" d="M234.6,187.1v12.3c0,3-2.2,5.5-5.2,5.9c-25.2,3.7-45,23.5-48.7,48.7c-0.4,2.9-2.9,5.1-5.9,5.2h-12.3 + C164.3,220.1,195.5,188.9,234.6,187.1z"/> + <path class="st1" d="M234.6,325.6v12.3c-39.1-1.7-70.3-33-72.1-72h12.3c3,0,5.5,2.2,5.9,5.2c3.7,25.2,23.5,45,48.7,48.7 + C232.4,320.1,234.6,322.6,234.6,325.6z"/> + <path class="st1" d="M313.3,265.9c-1.7,39.1-33,70.3-72.1,72v-12.3c0-3,2.2-5.5,5.2-5.9c25.2-3.7,45-23.5,48.7-48.7 + c0.4-2.9,2.9-5.1,5.9-5.2L313.3,265.9z"/> + <path class="st1" d="M313.3,259.2H301c-3,0-5.5-2.2-5.9-5.2c-3.7-25.2-23.5-45-48.7-48.7c-2.9-0.4-5.1-2.9-5.2-5.9v-12.3 + C280.3,188.9,311.6,220.1,313.3,259.2z"/> + <path class="st1" d="M313.4,262.5c0,1.1,0,2.2-0.1,3.3H301c-3,0-5.5,2.2-5.9,5.2c-3.7,25.2-23.5,45-48.7,48.7 + c-2.9,0.4-5.1,2.9-5.2,5.9v12.3c-1.1,0.1-2.2,0.1-3.3,0.1s-2.2,0-3.3-0.1v-12.3c0-3-2.2-5.5-5.2-5.9c-25.2-3.7-45-23.5-48.7-48.7 + c-0.4-2.9-2.9-5.1-5.9-5.2h-12.3c-0.1-1.1-0.1-2.2-0.1-3.3s0-2.2,0.1-3.3h12.3c3,0,5.5-2.2,5.9-5.2c3.7-25.2,23.5-45,48.7-48.7 + c2.9-0.4,5.1-2.9,5.2-5.9v-12.3c1.1-0.1,2.2-0.1,3.3-0.1s2.2,0,3.3,0.1v12.3c0,3,2.2,5.5,5.2,5.9c25.2,3.7,45,23.5,48.7,48.7 + c0.4,2.9,2.9,5.1,5.9,5.2h12.3C313.4,260.3,313.4,261.4,313.4,262.5z"/> +</g> +<path class="st2" d="M413.1,906.6h-7.9c-3.6,0-6.4-2.9-6.5-6.5V71.2c0-3.6,2.9-6.4,6.5-6.5h7.9c3.6,0,6.4,2.9,6.5,6.5V207 + c0,4.9-1.2,9.6-3.4,14l-6.7,13v79.2l6.7,13c2.2,4.3,3.4,9.1,3.4,13.9v269.7c0,4.9-1.2,9.6-3.4,14l-6.7,13V716l6.7,13 + c2.2,4.3,3.4,9.1,3.4,13.9v157.2C419.6,903.7,416.7,906.6,413.1,906.6z M405.2,65.7c-3,0-5.5,2.4-5.5,5.5v828.9c0,3,2.4,5.5,5.5,5.5 + h7.9c3,0,5.5-2.4,5.5-5.5V742.9c0-4.7-1.1-9.3-3.3-13.5l-6.8-13.1c0-0.1-0.1-0.2-0.1-0.2v-79.5c0-0.1,0-0.2,0.1-0.2l6.8-13.1 + c2.2-4.2,3.3-8.8,3.3-13.5V340.1c0-4.7-1.1-9.3-3.3-13.5l-6.8-13.1c0-0.1-0.1-0.2-0.1-0.2v-79.5c0-0.1,0-0.2,0.1-0.2l6.8-13.1 + c2.2-4.2,3.3-8.8,3.3-13.5V71.2c0-3-2.4-5.5-5.5-5.5H405.2z"/> +<path class="st2" d="M399.3,858.9h-11.2c-0.3,0-0.5-0.2-0.5-0.5V72c0-0.3,0.2-0.5,0.5-0.5h11.2c0.3,0,0.5,0.2,0.5,0.5v786.4 + C399.8,858.7,399.6,858.9,399.3,858.9z M388.6,857.9h10.2V72.5h-10.2V857.9z"/> +<path class="st2" d="M382.1,1000H275.9C158.9,1000,64,905.2,64,788.1l0,0V220.9C64,104.1,159.1,9.1,275.9,9.1h106.2 + c3.6,0,6.5,2.9,6.5,6.5v978C388.6,997.1,385.7,1000,382.1,1000z M275.9,10.1C159.6,10.1,65,104.7,65,220.9v567.2 + C65,904.4,159.6,999,275.9,999h106.2c3,0,5.5-2.4,5.5-5.5v-978c0-3-2.4-5.5-5.5-5.5H275.9V10.1z"/> +<polygon class="st1" points="237.9,448.9 225.8,469.9 250,469.9 "/> +<polygon class="st1" points="237.9,626.9 225.8,605.9 250,605.9 "/> +<polygon class="st1" points="148.9,537.9 169.9,550 169.9,525.8 "/> +<polygon class="st1" points="326.9,537.9 305.9,550 305.9,525.8 "/> +<path class="st1" d="M413.1,717.1h-4.2c-0.6,0-1-0.4-1-1l0,0v-79.5c0-0.6,0.4-1,1-1l0,0h4.2c3.8,0,6.9,3.1,7,7v67.6 + C420.1,714,417,717.1,413.1,717.1z M409.9,715.1h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V715.1z"/> +<path class="st1" d="M413.1,314.3h-4.2c-0.6,0-1-0.4-1-1v-79.5c0-0.6,0.4-1,1-1h4.2c3.8,0,6.9,3.1,7,7v67.6 + C420.1,311.2,417,314.3,413.1,314.3z M409.9,312.3h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V312.3z"/> +<path class="st1" d="M81.3,139.3c-0.3,0-0.5-0.1-0.7-0.3l-3.4-3.4c-2-2-2.6-5.1-1.5-7.8C110.5,50.1,187.7,0.1,272.9,0h51.2 + c3.8,0,6.9,3.1,7,7v2.6c0,0.6-0.4,1-1,1h-54.2C191.4,10.5,115.1,61,82.2,138.7c-0.1,0.3-0.4,0.5-0.7,0.6 + C81.4,139.3,81.3,139.3,81.3,139.3z M272.9,2C188.5,2.1,112,51.7,77.5,128.7c-0.8,1.9-0.4,4.1,1.1,5.5l2.4,2.4 + C114.6,58.8,191.3,8.5,276,8.6h53.2V7c0-2.7-2.2-5-5-5H272.9z"/> +<path class="st1" d="M359.6,116.1h-46.9c-2.2,0-4-1.8-4-4v-11.7c0-2.2,1.8-4,4-4h46.9c2.2,0,4,1.8,4,4v11.7 + C363.6,114.3,361.8,116.1,359.6,116.1z M312.7,98.5c-1.1,0-2,0.9-2,2v11.7c0,1.1,0.9,2,2,2h46.9c1.1,0,2-0.9,2-2v-11.7 + c0-1.1-0.9-2-2-2H312.7z"/> +<path class="st1" d="M237.9,502.9c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 + C276.4,485.7,259.2,502.9,237.9,502.9z M237.9,428c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 + c20.1,0,36.5-16.3,36.5-36.5S258.1,428,237.9,428z"/> +<path class="st1" d="M237.9,649.8c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 + S259.2,649.8,237.9,649.8z M237.9,574.9c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5l0,0 + C274.4,591.2,258.1,574.9,237.9,574.9z"/> +<path class="st1" d="M311.4,576.3c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5l0,0 + C349.8,559.1,332.6,576.3,311.4,576.3z M311.4,501.4c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5c20.1,0,36.5-16.3,36.5-36.5 + l0,0C347.8,517.7,331.5,501.4,311.4,501.4L311.4,501.4z"/> +<path class="st1" d="M164.5,576.3c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5l0,0 + C202.9,559.1,185.7,576.3,164.5,576.3z M164.5,501.4c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 + c20.1,0,36.5-16.3,36.5-36.5l0,0C200.9,517.7,184.6,501.4,164.5,501.4L164.5,501.4z"/> +<path class="st1" d="M314.1,753.7h-45c-5.5,0-9.9-4.4-9.9-9.9v-45c0-5.5,4.4-9.9,9.9-9.9h45c5.5,0,9.9,4.4,9.9,9.9v45 + C324,749.3,319.5,753.7,314.1,753.7z M269.1,690.9c-4.4,0-7.9,3.6-7.9,7.9v45c0,4.4,3.6,7.9,7.9,7.9h45c4.4,0,7.9-3.6,7.9-7.9v-45 + c0-4.4-3.6-7.9-7.9-7.9H269.1z"/> +<path class="st1" d="M291.6,741.7c-11.3,0-20.4-9.2-20.4-20.4c0-11.3,9.2-20.4,20.4-20.4c11.3,0,20.4,9.2,20.4,20.4l0,0 + C312,732.6,302.9,741.7,291.6,741.7z M291.6,702.8c-10.2,0-18.4,8.3-18.4,18.4s8.3,18.4,18.4,18.4c10.2,0,18.4-8.3,18.4-18.4 + S301.8,702.9,291.6,702.8z"/> +<path class="st1" d="M174.8,260.2h-12.3c-0.6,0-1-0.4-1-1l0,0c1.7-39.6,33.4-71.3,73-73c0.3,0,0.5,0.1,0.7,0.3s0.3,0.4,0.3,0.7v12.3 + c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9C181.2,257.6,178.3,260.2,174.8,260.2z M163.6,258.2h11.2c2.5,0,4.6-1.8,4.9-4.3 + c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-11.2C196.2,190.3,165.7,220.8,163.6,258.2L163.6,258.2z"/> +<path class="st1" d="M234.6,338.9L234.6,338.9c-39.6-1.7-71.3-33.4-73-73c0-0.6,0.4-1,1-1l0,0h12.3c3.5,0,6.4,2.6,6.9,6 + c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9V338C235.6,338.5,235.1,338.9,234.6,338.9L234.6,338.9z M163.6,266.9 + c2.2,37.4,32.6,67.8,70,70v-11.2c0-2.5-1.8-4.6-4.3-4.9c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3H163.6z"/> +<path class="st1" d="M241.3,338.9c-0.6,0-1-0.4-1-1v-12.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6 + h12.3c0.6,0,1,0.4,1,1l0,0C312.6,305.5,280.9,337.2,241.3,338.9L241.3,338.9z M301,266.9c-2.5,0-4.6,1.8-4.9,4.3 + c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v11.2c37.4-2.2,67.8-32.6,70-70H301z"/> +<path class="st1" d="M313.3,260.2H301c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-12.3 + c0-0.3,0.1-0.5,0.3-0.7s0.5-0.3,0.7-0.3c39.6,1.7,71.3,33.4,73,73C314.3,259.7,313.9,260.2,313.3,260.2L313.3,260.2L313.3,260.2z + M242.3,188.2v11.2c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h11.2 + C310.1,220.8,279.6,190.3,242.3,188.2L242.3,188.2z"/> +<path class="st1" d="M237.9,339c-1.2,0-2.3,0-3.4-0.1c-0.5,0-0.9-0.5-0.9-1v-12.3c0-2.5-1.8-4.6-4.3-4.9 + c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-12.3c-0.5,0-1-0.4-1-0.9c-0.1-1.1-0.1-2.2-0.1-3.4s0-2.3,0.1-3.4 + c0-0.5,0.5-0.9,1-0.9h12.3c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-12.3c0-0.5,0.4-1,0.9-1 + c2.3-0.1,4.5-0.1,6.8,0c0.5,0,0.9,0.5,0.9,1v12.3c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h12.3 + c0.5,0,1,0.4,1,0.9c0.1,1.1,0.1,2.2,0.1,3.4s0,2.3-0.1,3.4c0,0.5-0.5,0.9-1,0.9H301c-2.5,0-4.6,1.8-4.9,4.3 + c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v12.3c0,0.5-0.4,1-0.9,1C240.2,339,239.1,339,237.9,339z M235.6,337 + c1.5,0.1,3.1,0.1,4.7,0v-11.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6h11.3c0-0.8,0-1.5,0-2.3 + s0-1.6,0-2.3H301c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-11.3c-1.5-0.1-3.1-0.1-4.7,0v11.3 + c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-11.3c0,0.8,0,1.5,0,2.3s0,1.6,0,2.3h11.3 + c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9L235.6,337z"/> +</svg> diff --git a/Ryujinx/Ui/assets/JoyConPair.svg b/Ryujinx/Ui/assets/JoyConPair.svg new file mode 100644 index 00000000..fca94d18 --- /dev/null +++ b/Ryujinx/Ui/assets/JoyConPair.svg @@ -0,0 +1,218 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 1000.8 1000" style="enable-background:new 0 0 1000.8 1000;" xml:space="preserve"> +<style type="text/css"> + .st0{opacity:0.1;} + .st1{fill:#02C5E5;} + .st2{fill:#FF5F55;} + .st3{fill:#FFFFFF;} +</style> +<g class="st0"> + <path class="st1" d="M419.1,642.6v67.6c0,3.3-2.7,6-6,6h-4.2v-79.5h4.2C416.4,636.6,419.1,639.3,419.1,642.6z"/> + <path class="st1" d="M419.1,239.8v67.6c0,3.3-2.7,6-6,6h-4.2v-79.5h4.2C416.4,233.9,419.1,236.5,419.1,239.8z"/> + <path class="st1" d="M330.1,7v2.6h-54.2c-84.8,0-161.4,50.7-194.6,128.7l-3.4-3.4c-1.8-1.7-2.3-4.4-1.3-6.6 + C111.2,50.8,188.1,1,272.9,1h51.2C327.4,1,330.1,3.7,330.1,7z"/> + <path class="st1" d="M359.6,115.1h-46.9c-1.6,0-3-1.3-3-3v-11.7c0-1.6,1.3-3,3-3h46.9c1.6,0,3,1.3,3,3v11.7 + C362.6,113.8,361.3,115.1,359.6,115.1z"/> + <circle class="st1" cx="237.9" cy="464.4" r="37.5"/> + <circle class="st1" cx="237.9" cy="611.3" r="37.5"/> + <circle class="st1" cx="311.4" cy="537.9" r="37.5"/> + + <ellipse transform="matrix(0.9951 -9.853756e-02 9.853756e-02 0.9951 -52.201 18.8252)" class="st1" cx="164.5" cy="537.9" rx="37.5" ry="37.5"/> + <path class="st1" d="M269.1,689.9h45c4.9,0,8.9,4,8.9,8.9v45c0,4.9-4,8.9-8.9,8.9h-45c-4.9,0-8.9-4-8.9-8.9v-45 + C260.2,693.9,264.2,689.9,269.1,689.9z"/> + <circle class="st1" cx="291.6" cy="721.3" r="19.4"/> + <path class="st1" d="M234.6,187.1v12.3c0,3-2.2,5.5-5.2,5.9c-25.2,3.7-45,23.5-48.7,48.7c-0.4,2.9-2.9,5.1-5.9,5.2h-12.3 + C164.3,220.1,195.5,188.9,234.6,187.1z"/> + <path class="st1" d="M234.6,325.6v12.3c-39.1-1.7-70.3-33-72.1-72h12.3c3,0,5.5,2.2,5.9,5.2c3.7,25.2,23.5,45,48.7,48.7 + C232.4,320.1,234.6,322.6,234.6,325.6z"/> + <path class="st1" d="M313.3,265.9c-1.7,39.1-33,70.3-72.1,72v-12.3c0-3,2.2-5.5,5.2-5.9c25.2-3.7,45-23.5,48.7-48.7 + c0.4-2.9,2.9-5.1,5.9-5.2L313.3,265.9z"/> + <path class="st1" d="M313.3,259.2H301c-3,0-5.5-2.2-5.9-5.2c-3.7-25.2-23.5-45-48.7-48.7c-2.9-0.4-5.1-2.9-5.2-5.9v-12.3 + C280.3,188.9,311.6,220.1,313.3,259.2z"/> + <path class="st1" d="M313.4,262.5c0,1.1,0,2.2-0.1,3.3H301c-3,0-5.5,2.2-5.9,5.2c-3.7,25.2-23.5,45-48.7,48.7 + c-2.9,0.4-5.1,2.9-5.2,5.9v12.3c-1.1,0.1-2.2,0.1-3.3,0.1s-2.2,0-3.3-0.1v-12.3c0-3-2.2-5.5-5.2-5.9c-25.2-3.7-45-23.5-48.7-48.7 + c-0.4-2.9-2.9-5.1-5.9-5.2h-12.3c-0.1-1.1-0.1-2.2-0.1-3.3s0-2.2,0.1-3.3h12.3c3,0,5.5-2.2,5.9-5.2c3.7-25.2,23.5-45,48.7-48.7 + c2.9-0.4,5.1-2.9,5.2-5.9v-12.3c1.1-0.1,2.2-0.1,3.3-0.1s2.2,0,3.3,0.1v12.3c0,3,2.2,5.5,5.2,5.9c25.2,3.7,45,23.5,48.7,48.7 + c0.4,2.9,2.9,5.1,5.9,5.2h12.3C313.4,260.3,313.4,261.4,313.4,262.5z"/> +</g> +<g class="st0"> + <path class="st2" d="M597.9,233.9v79.5h-4.2c-3.3,0-6-2.7-6-6v-67.6c0-3.3,2.7-6,6-6H597.9z"/> + <path class="st2" d="M597.9,636.6v79.5h-4.2c-3.3,0-6-2.7-6-6v-67.6c0-3.3,2.7-6,6-6H597.9z"/> + <path class="st2" d="M929,134.9l-3.4,3.4C892.4,60.3,815.8,9.6,730.9,9.6h-54.2V7c0-3.3,2.7-6,6-6c0,0,0,0,0,0h51.2 + c84.8,0,161.7,49.8,196.4,127.2C931.3,130.5,930.8,133.1,929,134.9z"/> + <path class="st2" d="M679.5,94.5V82.8c0-1.6-1.3-3-3-3l0,0h-11.7c-1.6,0-3,1.3-3,3c0,0,0,0,0,0v11.7c0,1.6-1.3,3-3,3l0,0h-11.7 + c-1.6,0-3,1.3-3,3c0,0,0,0,0,0v11.7c0,1.6,1.3,3,3,3l0,0h11.7c1.6,0,3,1.3,3,3c0,0,0,0,0,0v11.7c0,1.6,1.3,3,3,3l0,0h11.7 + c1.6,0,3-1.3,3-3v0v-11.7c0-1.6,1.3-3,3-3l0,0h11.7c1.6,0,3-1.3,3-3c0,0,0,0,0,0v-11.7c0-1.6-1.3-3-3-3l0,0h-11.7 + C680.8,97.5,679.5,96.1,679.5,94.5C679.5,94.5,679.5,94.5,679.5,94.5z"/> + <circle class="st2" cx="768.9" cy="333.9" r="37.5"/> + <circle class="st2" cx="768.9" cy="187.1" r="37.5"/> + <circle class="st2" cx="842.3" cy="260.5" r="37.5"/> + <circle class="st2" cx="695.5" cy="260.5" r="37.5"/> + <circle class="st2" cx="715" cy="721.3" r="27.9"/> + <path class="st2" d="M765.6,460.3v12.3c0,3-2.2,5.5-5.2,5.9c-25.2,3.7-45,23.5-48.7,48.7c-0.4,2.9-2.9,5.1-5.9,5.2h-12.3 + C695.2,493.3,726.5,462,765.6,460.3z"/> + <path class="st2" d="M765.6,598.8v12.3c-39.1-1.7-70.3-33-72.1-72h12.3c3,0,5.5,2.2,5.9,5.2c3.7,25.2,23.5,45,48.7,48.7 + C763.4,593.3,765.6,595.8,765.6,598.8z"/> + <path class="st2" d="M844.3,539c-1.7,39.1-33,70.3-72.1,72v-12.3c0-3,2.2-5.5,5.2-5.9c25.2-3.7,45-23.5,48.7-48.7 + c0.4-2.9,2.9-5.1,5.9-5.2L844.3,539z"/> + <path class="st2" d="M844.3,532.4H832c-3,0-5.5-2.2-5.9-5.2c-3.7-25.2-23.5-45-48.7-48.7c-2.9-0.4-5.1-2.9-5.2-5.9v-12.3 + C811.3,462,842.6,493.3,844.3,532.4z"/> + <path class="st2" d="M844.4,535.7c0,1.1,0,2.2-0.1,3.3H832c-3,0-5.5,2.2-5.9,5.2c-3.7,25.2-23.5,45-48.7,48.7 + c-2.9,0.4-5.1,2.9-5.2,5.9v12.3c-1.1,0.1-2.2,0.1-3.3,0.1s-2.2,0-3.3-0.1v-12.3c0-3-2.2-5.5-5.2-5.9c-25.2-3.7-45-23.5-48.7-48.7 + c-0.4-2.9-2.9-5.1-5.9-5.2h-12.3c-0.1-1.1-0.1-2.2-0.1-3.3s0-2.2,0.1-3.3h12.3c3,0,5.5-2.2,5.9-5.2c3.7-25.2,23.5-45,48.7-48.7 + c2.9-0.4,5.1-2.9,5.2-5.9v-12.3c1.1-0.1,2.2-0.1,3.3-0.1s2.2,0,3.3,0.1v12.3c0,3,2.2,5.5,5.2,5.9c25.2,3.7,45,23.5,48.7,48.7 + c0.4,2.9,2.9,5.1,5.9,5.2h12.3C844.3,533.5,844.4,534.6,844.4,535.7z"/> +</g> +<path class="st3" d="M413.1,906.6h-7.9c-3.6,0-6.4-2.9-6.5-6.5V71.2c0-3.6,2.9-6.4,6.5-6.5h7.9c3.6,0,6.4,2.9,6.5,6.5V207 + c0,4.9-1.2,9.6-3.4,14l-6.7,13v79.2l6.7,13c2.2,4.3,3.4,9.1,3.4,13.9v269.7c0,4.9-1.2,9.6-3.4,14l-6.7,13V716l6.7,13 + c2.2,4.3,3.4,9.1,3.4,13.9v157.2C419.6,903.7,416.7,906.6,413.1,906.6z M405.2,65.7c-3,0-5.5,2.4-5.5,5.5v828.9c0,3,2.4,5.5,5.5,5.5 + h7.9c3,0,5.5-2.4,5.5-5.5V742.9c0-4.7-1.1-9.3-3.3-13.5l-6.8-13.1c0-0.1-0.1-0.2-0.1-0.2v-79.5c0-0.1,0-0.2,0.1-0.2l6.8-13.1 + c2.2-4.2,3.3-8.8,3.3-13.5V340.1c0-4.7-1.1-9.3-3.3-13.5l-6.8-13.1c0-0.1-0.1-0.2-0.1-0.2v-79.5c0-0.1,0-0.2,0.1-0.2l6.8-13.1 + c2.2-4.2,3.3-8.8,3.3-13.5V71.2c0-3-2.4-5.5-5.5-5.5L405.2,65.7z"/> +<path class="st3" d="M399.3,858.9h-11.2c-0.3,0-0.5-0.2-0.5-0.5V72c0-0.3,0.2-0.5,0.5-0.5h11.2c0.3,0,0.5,0.2,0.5,0.5v786.4 + C399.8,858.7,399.6,858.9,399.3,858.9z M388.6,857.9h10.2V72.5h-10.2V857.9z"/> +<path class="st3" d="M382.1,1000H275.9C158.9,1000,64,905.2,64,788.1c0,0,0,0,0,0V220.9C64,104.1,159.1,9.1,275.9,9.1h106.2 + c3.6,0,6.5,2.9,6.5,6.5v978C388.6,997.1,385.7,1000,382.1,1000z M275.9,10.1C159.6,10.1,65,104.7,65,220.9v567.2 + C65,904.4,159.6,999,275.9,999h106.2c3,0,5.5-2.4,5.5-5.5v-978c0-3-2.4-5.5-5.5-5.5H275.9z"/> +<path class="st3" d="M601.6,906.6h-7.9c-3.6,0-6.4-2.9-6.5-6.5V742.9c0-4.9,1.2-9.6,3.4-13.9l6.7-13v-79.2l-6.7-13 + c-2.2-4.3-3.4-9.1-3.4-14V340.1c0-4.9,1.2-9.6,3.4-13.9l6.7-13V234l-6.7-13c-2.2-4.3-3.4-9.1-3.4-14V71.2c0-3.6,2.9-6.4,6.5-6.5h7.9 + c3.6,0,6.4,2.9,6.5,6.5v828.9C608,903.7,605.1,906.6,601.6,906.6z M593.7,65.7c-3,0-5.5,2.4-5.5,5.5V207c0,4.7,1.1,9.3,3.3,13.5 + l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2l-6.8,13.1c-2.2,4.2-3.3,8.8-3.3,13.5v269.7c0,4.7,1.1,9.3,3.3,13.5 + l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2l-6.8,13.1c-2.2,4.2-3.3,8.8-3.3,13.5v157.2c0,3,2.4,5.5,5.5,5.5h7.9 + c3,0,5.5-2.4,5.5-5.5V71.2c0-3-2.4-5.5-5.5-5.5L593.7,65.7z"/> +<path class="st3" d="M618.8,858.9h-11.3c-0.3,0-0.5-0.2-0.5-0.5c0,0,0,0,0,0V72c0-0.3,0.2-0.5,0.5-0.5h11.3c0.3,0,0.5,0.2,0.5,0.5 + v786.4C619.3,858.7,619.1,858.9,618.8,858.9C618.8,858.9,618.8,858.9,618.8,858.9z M608,857.9h10.3V72.5H608V857.9z"/> +<path class="st3" d="M730.9,1000H624.7c-3.6,0-6.5-2.9-6.5-6.5v-978c0-3.6,2.9-6.5,6.5-6.5h106.2c116.8,0,211.9,95.1,211.9,211.9 + v567.2C942.8,905.1,848,1000,730.9,1000C730.9,1000,730.9,1000,730.9,1000z M624.7,10.1c-3,0-5.5,2.4-5.5,5.5v978 + c0,3,2.4,5.5,5.5,5.5h106.2c116.3,0,210.9-94.6,210.9-210.9V220.9c0-116.3-94.6-210.9-210.9-210.9L624.7,10.1z"/> +<path class="st3" d="M715,763.2c-23.1,0-41.9-18.7-41.9-41.9s18.7-41.9,41.9-41.9s41.9,18.7,41.9,41.9l0,0 + C756.8,744.4,738.1,763.1,715,763.2z M715,680.4c-22.6,0-40.9,18.3-40.9,40.9c0,22.6,18.3,40.9,40.9,40.9 + c22.6,0,40.9-18.3,40.9-40.9v0C755.8,698.7,737.6,680.4,715,680.4z"/> +<polygon class="st1" points="237.9,448.9 225.8,469.9 250,469.9 "/> +<polygon class="st1" points="237.9,626.9 225.8,605.9 250,605.9 "/> +<polygon class="st1" points="148.9,537.9 169.9,550 169.9,525.8 "/> +<polygon class="st1" points="326.9,537.9 305.9,550 305.9,525.8 "/> +<path class="st2" d="M782.2,203.2h-5.5l-7.8-12.9l-7.8,12.9h-5.4l10.6-16.3l-9.8-15.6h5.2l7.3,12l7.4-12h5l-9.8,15.4L782.2,203.2z" + /> +<path class="st2" d="M709.2,244.5l-11.6,20.6v11.4h-4.4V265l-11.6-20.5h5.3l6.4,11.7l2.3,4.7l2.2-4.3l6.4-12.1L709.2,244.5z"/> +<path class="st2" d="M855.9,276.5h-4.7l-2.2-7h-13.3l-2.3,7h-4.5l10.6-32h6L855.9,276.5z M847.7,265.6l-5.4-17.1l-5.4,17.1 + L847.7,265.6z"/> +<path class="st2" d="M779.4,340.4c0,1.4-0.3,2.8-0.9,4.1c-0.6,1.2-1.5,2.2-2.5,3c-1.2,0.9-2.6,1.5-4,1.9c-1.7,0.4-3.4,0.7-5.2,0.6 + h-8.4v-32h9.2c7.1,0,10.7,2.6,10.7,7.8c0,1.6-0.4,3.1-1.2,4.5c-1,1.4-2.4,2.3-4,2.8c0.9,0.2,1.7,0.4,2.5,0.8c0.8,0.4,1.5,0.9,2,1.5 + c0.6,0.6,1.1,1.4,1.4,2.2C779.2,338.4,779.4,339.4,779.4,340.4z M773.7,326.3c0-0.6-0.1-1.3-0.3-1.8c-0.2-0.6-0.6-1.1-1-1.5 + c-0.6-0.5-1.3-0.8-2-1c-1-0.3-2.1-0.4-3.2-0.4h-4.5v10h4.4c0.9,0,1.8-0.1,2.7-0.3c0.8-0.2,1.5-0.5,2.1-1c0.6-0.4,1-1,1.3-1.7 + C773.6,327.9,773.7,327.1,773.7,326.3L773.7,326.3z M774.8,340.5c0-0.8-0.2-1.5-0.5-2.2c-0.4-0.7-0.9-1.2-1.5-1.7 + c-0.7-0.5-1.5-0.8-2.4-1c-1-0.3-2.1-0.4-3.2-0.4h-4.5v11h4.6c2.5,0,4.4-0.5,5.6-1.4C774.2,343.8,774.9,342.2,774.8,340.5 + L774.8,340.5z"/> +<path class="st2" d="M715,701.3L695.4,721h5.6v16.8h28.2V721h5.3L715,701.3z M720.7,731.8h-11.1V721h11.1V731.8z"/> +<path class="st1" d="M413.1,717.1h-4.2c-0.6,0-1-0.4-1-1c0,0,0,0,0,0v-79.5c0-0.6,0.4-1,1-1c0,0,0,0,0,0h4.2c3.8,0,6.9,3.1,7,7v67.6 + C420.1,714,417,717.1,413.1,717.1z M409.9,715.1h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V715.1z"/> +<path class="st1" d="M413.1,314.3h-4.2c-0.6,0-1-0.4-1-1v-79.5c0-0.6,0.4-1,1-1h4.2c3.8,0,6.9,3.1,7,7v67.6 + C420.1,311.2,417,314.3,413.1,314.3z M409.9,312.3h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V312.3z"/> +<path class="st1" d="M81.3,139.3c-0.3,0-0.5-0.1-0.7-0.3l-3.4-3.4c-2-2-2.6-5.1-1.5-7.8C110.5,50.1,187.7,0.1,272.9,0h51.2 + c3.8,0,6.9,3.1,7,7v2.6c0,0.6-0.4,1-1,1h-54.2C191.4,10.5,115.1,61,82.2,138.7c-0.1,0.3-0.4,0.5-0.7,0.6 + C81.4,139.3,81.3,139.3,81.3,139.3z M272.9,2C188.5,2.1,112,51.7,77.5,128.7c-0.8,1.9-0.4,4.1,1.1,5.5l2.4,2.4 + c33.6-77.8,110.3-128.1,195-128h53.2V7c0-2.7-2.2-5-5-5L272.9,2z"/> +<path class="st1" d="M359.6,116.1h-46.9c-2.2,0-4-1.8-4-4v-11.7c0-2.2,1.8-4,4-4h46.9c2.2,0,4,1.8,4,4v11.7 + C363.6,114.3,361.8,116.1,359.6,116.1z M312.7,98.5c-1.1,0-2,0.9-2,2v11.7c0,1.1,0.9,2,2,2h46.9c1.1,0,2-0.9,2-2v-11.7 + c0-1.1-0.9-2-2-2H312.7z"/> +<path class="st1" d="M237.9,502.9c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 + C276.4,485.7,259.2,502.9,237.9,502.9z M237.9,428c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 + c20.1,0,36.5-16.3,36.5-36.5C274.4,444.3,258.1,428,237.9,428z"/> +<path class="st1" d="M237.9,649.8c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 + C276.4,632.6,259.2,649.8,237.9,649.8z M237.9,574.9c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5 + c0,0,0,0,0,0C274.4,591.2,258.1,574.9,237.9,574.9z"/> +<path class="st1" d="M311.4,576.3c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5l0,0 + C349.8,559.1,332.6,576.3,311.4,576.3z M311.4,501.4c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5c20.1,0,36.5-16.3,36.5-36.5 + c0,0,0,0,0,0C347.8,517.7,331.5,501.4,311.4,501.4L311.4,501.4z"/> +<path class="st1" d="M164.5,576.3c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5l0,0 + C202.9,559.1,185.7,576.3,164.5,576.3z M164.5,501.4c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 + c20.1,0,36.5-16.3,36.5-36.5c0,0,0,0,0,0C200.9,517.7,184.6,501.4,164.5,501.4L164.5,501.4z"/> +<path class="st1" d="M314.1,753.7h-45c-5.5,0-9.9-4.4-9.9-9.9v-45c0-5.5,4.4-9.9,9.9-9.9h45c5.5,0,9.9,4.4,9.9,9.9v45 + C324,749.3,319.5,753.7,314.1,753.7z M269.1,690.9c-4.4,0-7.9,3.6-7.9,7.9v45c0,4.4,3.6,7.9,7.9,7.9h45c4.4,0,7.9-3.6,7.9-7.9v-45 + c0-4.4-3.6-7.9-7.9-7.9H269.1z"/> +<path class="st1" d="M291.6,741.7c-11.3,0-20.4-9.2-20.4-20.4c0-11.3,9.2-20.4,20.4-20.4c11.3,0,20.4,9.2,20.4,20.4c0,0,0,0,0,0 + C312,732.6,302.9,741.7,291.6,741.7z M291.6,702.8c-10.2,0-18.4,8.3-18.4,18.4s8.3,18.4,18.4,18.4c10.2,0,18.4-8.3,18.4-18.4 + C310,711.1,301.8,702.9,291.6,702.8z"/> +<path class="st1" d="M174.8,260.2h-12.3c-0.6,0-1-0.4-1-1c0,0,0,0,0,0c1.7-39.6,33.4-71.3,73-73c0.3,0,0.5,0.1,0.7,0.3 + c0.2,0.2,0.3,0.4,0.3,0.7v12.3c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9C181.2,257.6,178.3,260.2,174.8,260.2z + M163.6,258.2h11.2c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-11.2 + C196.2,190.3,165.7,220.8,163.6,258.2L163.6,258.2z"/> +<path class="st1" d="M234.6,338.9L234.6,338.9c-39.6-1.7-71.3-33.4-73-73c0-0.6,0.4-1,1-1c0,0,0,0,0,0h12.3c3.5,0,6.4,2.6,6.9,6 + c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9v12.3C235.6,338.5,235.1,338.9,234.6,338.9L234.6,338.9z M163.6,266.9 + c2.2,37.4,32.6,67.8,70,70v-11.2c0-2.5-1.8-4.6-4.3-4.9c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3L163.6,266.9z"/> +<path class="st1" d="M241.3,338.9c-0.6,0-1-0.4-1-1v-12.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6 + h12.3c0.6,0,1,0.4,1,1c0,0,0,0,0,0C312.6,305.5,280.9,337.2,241.3,338.9L241.3,338.9z M301,266.9c-2.5,0-4.6,1.8-4.9,4.3 + c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v11.2c37.4-2.2,67.8-32.6,70-70L301,266.9z"/> +<path class="st1" d="M313.3,260.2H301c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-12.3 + c0-0.3,0.1-0.5,0.3-0.7c0.2-0.2,0.5-0.3,0.7-0.3c39.6,1.7,71.3,33.4,73,73C314.3,259.7,313.9,260.2,313.3,260.2 + C313.3,260.2,313.3,260.2,313.3,260.2L313.3,260.2z M242.3,188.2v11.2c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6 + c0.3,2.5,2.4,4.3,4.9,4.3h11.2C310.1,220.8,279.6,190.3,242.3,188.2L242.3,188.2z"/> +<path class="st1" d="M237.9,339c-1.2,0-2.3,0-3.4-0.1c-0.5,0-0.9-0.5-0.9-1v-12.3c0-2.5-1.8-4.6-4.3-4.9 + c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-12.3c-0.5,0-1-0.4-1-0.9c-0.1-1.1-0.1-2.2-0.1-3.4s0-2.3,0.1-3.4 + c0-0.5,0.5-0.9,1-0.9h12.3c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-12.3c0-0.5,0.4-1,0.9-1 + c2.3-0.1,4.5-0.1,6.8,0c0.5,0,0.9,0.5,0.9,1v12.3c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h12.3 + c0.5,0,1,0.4,1,0.9c0.1,1.1,0.1,2.2,0.1,3.4s0,2.3-0.1,3.4c0,0.5-0.5,0.9-1,0.9H301c-2.5,0-4.6,1.8-4.9,4.3 + c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v12.3c0,0.5-0.4,1-0.9,1C240.2,339,239.1,339,237.9,339z M235.6,337 + c1.5,0.1,3.1,0.1,4.7,0v-11.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6h11.3c0-0.8,0-1.5,0-2.3 + s0-1.6,0-2.3H301c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-11.3c-1.5-0.1-3.1-0.1-4.7,0v11.3 + c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-11.3c0,0.8,0,1.5,0,2.3s0,1.6,0,2.3h11.3 + c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9L235.6,337z"/> +<path class="st2" d="M597.9,314.3h-4.2c-3.8,0-6.9-3.1-7-7v-67.6c0-3.8,3.1-6.9,7-7h4.2c0.6,0,1,0.4,1,1c0,0,0,0,0,0v79.5 + C598.9,313.9,598.4,314.3,597.9,314.3C597.9,314.3,597.9,314.3,597.9,314.3z M593.7,234.8c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5 + h3.2v-77.5H593.7z"/> +<path class="st2" d="M597.9,717.1h-4.2c-3.8,0-6.9-3.1-7-7v-67.6c0-3.8,3.1-6.9,7-7h4.2c0.6,0,1,0.4,1,1c0,0,0,0,0,0v79.5 + C598.9,716.6,598.4,717.1,597.9,717.1C597.9,717.1,597.9,717.1,597.9,717.1z M593.7,637.6c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5 + h3.2v-77.5H593.7z"/> +<path class="st2" d="M925.6,139.3c-0.1,0-0.1,0-0.2,0c-0.3-0.1-0.6-0.3-0.7-0.6C891.7,61,815.4,10.5,730.9,10.6h-54.2 + c-0.6,0-1-0.4-1-1c0,0,0,0,0,0V7c0-3.8,3.1-6.9,7-7h51.2c85.2,0.1,162.4,50.1,197.3,127.8c1.2,2.6,0.6,5.7-1.5,7.8l-3.4,3.4 + C926.1,139.2,925.8,139.3,925.6,139.3z M677.7,8.6h53.2c84.7-0.1,161.3,50.2,195,128l2.4-2.4l0,0c1.5-1.4,1.9-3.6,1.1-5.5 + C894.8,51.7,818.3,2.1,733.9,2h-51.2c-2.7,0-5,2.2-5,5V8.6z"/> +<path class="st2" d="M676.5,133.7h-11.7c-2.2,0-4-1.8-4-4v-11.7c0-1.1-0.9-2-2-2h-11.7c-2.2,0-4-1.8-4-4v-11.7c0-2.2,1.8-4,4-4h11.7 + c1.1,0,2-0.9,2-2V82.8c0-2.2,1.8-4,4-4h11.7c2.2,0,4,1.8,4,4v11.7c0,1.1,0.9,2,2,2h11.7c2.2,0,4,1.8,4,4v11.7c0,2.2-1.8,4-4,4h-11.7 + c-1.1,0-2,0.9-2,2v11.7C680.5,131.9,678.7,133.7,676.5,133.7z M647.2,98.5c-1.1,0-2,0.9-2,2v11.7c0,1.1,0.9,2,2,2h11.7 + c2.2,0,4,1.8,4,4v11.7c0,1.1,0.9,2,2,2h11.7c1.1,0,2-0.9,2-2v-11.7c0-2.2,1.8-4,4-4h11.7c1.1,0,2-0.9,2-2v-11.7c0-1.1-0.9-2-2-2 + h-11.7c-2.2,0-4-1.8-4-4V82.8c0-1.1-0.9-2-2-2h-11.7c-1.1,0-2,0.9-2,2v11.7c0,2.2-1.8,4-4,4L647.2,98.5z"/> +<path class="st2" d="M768.9,372.4c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 + C807.3,355.2,790.1,372.4,768.9,372.4z M768.9,297.5c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 + c20.1,0,36.5-16.3,36.5-36.5C805.3,313.8,789,297.5,768.9,297.5L768.9,297.5z"/> +<path class="st2" d="M768.9,225.5c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 + C807.3,208.3,790.1,225.5,768.9,225.5z M768.9,150.6c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 + c20.1,0,36.5-16.3,36.5-36.5C805.3,166.9,789,150.6,768.9,150.6L768.9,150.6z"/> +<path class="st2" d="M842.3,299c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 + C880.8,281.7,863.6,298.9,842.3,299z M842.3,224c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 + c20.1,0,36.5-16.3,36.5-36.5C878.8,240.4,862.5,224,842.3,224L842.3,224z"/> +<path class="st2" d="M695.5,299c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 + C733.9,281.7,716.7,298.9,695.5,299z M695.5,224c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 + c20.1,0,36.5-16.3,36.5-36.5C731.9,240.4,715.6,224,695.5,224L695.5,224z"/> +<path class="st2" d="M715,750.2c-16,0-28.9-13-28.9-28.9s13-28.9,28.9-28.9c16,0,28.9,13,28.9,28.9c0,0,0,0,0,0 + C743.9,737.3,731,750.2,715,750.2z M715,694.3c-14.9,0-26.9,12.1-26.9,26.9s12.1,26.9,26.9,26.9c14.9,0,26.9-12.1,26.9-26.9 + C741.9,706.4,729.9,694.4,715,694.3z"/> +<path class="st2" d="M705.8,533.4h-12.3c-0.6,0-1-0.4-1-1c0,0,0,0,0,0c1.7-39.6,33.4-71.3,73-73c0.3,0,0.5,0.1,0.7,0.3 + c0.2,0.2,0.3,0.4,0.3,0.7v12.3c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9C712.2,530.8,709.3,533.4,705.8,533.4z + M694.6,531.4h11.2c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-11.2 + C727.2,463.5,696.7,494,694.6,531.4z"/> +<path class="st2" d="M765.6,612.1C765.6,612.1,765.5,612.1,765.6,612.1c-39.6-1.7-71.3-33.4-73-73c0-0.6,0.4-1,1-1c0,0,0,0,0,0h12.3 + c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9v12.3C766.6,611.6,766.1,612.1,765.6,612.1 + C765.6,612.1,765.6,612.1,765.6,612.1L765.6,612.1z M694.6,540c2.2,37.4,32.6,67.8,70,70v-11.2c0-2.5-1.8-4.6-4.3-4.9 + c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3H694.6z"/> +<path class="st2" d="M772.2,612.1c-0.6,0-1-0.4-1-1c0,0,0,0,0,0v-12.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9 + c0.5-3.4,3.4-6,6.9-6h12.3c0.6,0,1,0.4,1,1c0,0,0,0,0,0C843.5,578.7,811.9,610.3,772.2,612.1C772.3,612.1,772.3,612.1,772.2,612.1z + M832,540c-2.5,0-4.6,1.8-4.9,4.3c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9V610c37.4-2.2,67.8-32.6,70-70H832z"/> +<path class="st2" d="M844.3,533.4H832c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-12.3 + c0-0.3,0.1-0.5,0.3-0.7c0.2-0.2,0.5-0.3,0.7-0.3c39.6,1.7,71.3,33.4,73,73C845.3,532.9,844.9,533.3,844.3,533.4 + C844.3,533.4,844.3,533.4,844.3,533.4L844.3,533.4z M773.2,461.4v11.2c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6 + c0.3,2.5,2.4,4.3,4.9,4.3h11.2C841.1,494,810.6,463.5,773.2,461.4z"/> +<path class="st2" d="M768.9,612.2c-1.2,0-2.3,0-3.4-0.1c-0.5,0-0.9-0.5-0.9-1v-12.3c0-2.5-1.8-4.6-4.3-4.9 + c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-12.3c-0.5,0-1-0.4-1-0.9c-0.1-1.1-0.1-2.2-0.1-3.4s0-2.3,0.1-3.4 + c0-0.5,0.5-0.9,1-0.9h12.3c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-12.3c0-0.5,0.4-1,0.9-1 + c2.3-0.1,4.5-0.1,6.8,0c0.5,0,0.9,0.5,0.9,1v12.3c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h12.3 + c0.5,0,1,0.4,1,0.9c0.1,1.1,0.1,2.2,0.1,3.4s0,2.3-0.1,3.4c0,0.5-0.5,0.9-1,0.9H832c-2.5,0-4.6,1.8-4.9,4.3 + c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v12.3c0,0.5-0.4,1-0.9,1C771.2,612.1,770.1,612.2,768.9,612.2z M766.6,610.1 + c1.5,0.1,3.1,0.1,4.7,0v-11.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6h11.3c0-0.8,0-1.5,0-2.3 + s0-1.6,0-2.3H832c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-11.3c-1.5-0.1-3.1-0.1-4.7,0v11.3 + c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-11.3c0,0.8,0,1.5,0,2.3s0,1.6,0,2.3h11.3 + c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9V610.1z"/> +</svg> diff --git a/Ryujinx/Ui/assets/JoyConRight.svg b/Ryujinx/Ui/assets/JoyConRight.svg new file mode 100644 index 00000000..014c0ae3 --- /dev/null +++ b/Ryujinx/Ui/assets/JoyConRight.svg @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 1000.8 1000" style="enable-background:new 0 0 1000.8 1000;" xml:space="preserve"> +<style type="text/css"> + .st0{opacity:0.1;} + .st1{fill:#FF5F55;} + .st2{fill:#FFFFFF;} +</style> +<g class="st0"> + <path class="st1" d="M597.9,233.9v79.5h-4.2c-3.3,0-6-2.7-6-6v-67.6c0-3.3,2.7-6,6-6h4.2V233.9z"/> + <path class="st1" d="M597.9,636.6v79.5h-4.2c-3.3,0-6-2.7-6-6v-67.6c0-3.3,2.7-6,6-6L597.9,636.6L597.9,636.6z"/> + <path class="st1" d="M929,134.9l-3.4,3.4C892.4,60.3,815.8,9.6,730.9,9.6h-54.2V7c0-3.3,2.7-6,6-6l0,0h51.2 + c84.8,0,161.7,49.8,196.4,127.2C931.3,130.5,930.8,133.1,929,134.9z"/> + <path class="st1" d="M679.5,94.5V82.8c0-1.6-1.3-3-3-3l0,0h-11.7c-1.6,0-3,1.3-3,3l0,0v11.7c0,1.6-1.3,3-3,3l0,0h-11.7 + c-1.6,0-3,1.3-3,3l0,0v11.7c0,1.6,1.3,3,3,3l0,0h11.7c1.6,0,3,1.3,3,3l0,0v11.7c0,1.6,1.3,3,3,3l0,0h11.7c1.6,0,3-1.3,3-3l0,0 + v-11.7c0-1.6,1.3-3,3-3l0,0h11.7c1.6,0,3-1.3,3-3l0,0v-11.7c0-1.6-1.3-3-3-3l0,0h-11.7C680.8,97.5,679.5,96.1,679.5,94.5 + L679.5,94.5z"/> + <circle class="st1" cx="768.9" cy="333.9" r="37.5"/> + <circle class="st1" cx="768.9" cy="187.1" r="37.5"/> + <circle class="st1" cx="842.3" cy="260.5" r="37.5"/> + <circle class="st1" cx="695.5" cy="260.5" r="37.5"/> + <circle class="st1" cx="715" cy="721.3" r="27.9"/> + <path class="st1" d="M765.6,460.3v12.3c0,3-2.2,5.5-5.2,5.9c-25.2,3.7-45,23.5-48.7,48.7c-0.4,2.9-2.9,5.1-5.9,5.2h-12.3 + C695.2,493.3,726.5,462,765.6,460.3z"/> + <path class="st1" d="M765.6,598.8v12.3c-39.1-1.7-70.3-33-72.1-72h12.3c3,0,5.5,2.2,5.9,5.2c3.7,25.2,23.5,45,48.7,48.7 + C763.4,593.3,765.6,595.8,765.6,598.8z"/> + <path class="st1" d="M844.3,539c-1.7,39.1-33,70.3-72.1,72v-12.3c0-3,2.2-5.5,5.2-5.9c25.2-3.7,45-23.5,48.7-48.7 + c0.4-2.9,2.9-5.1,5.9-5.2L844.3,539z"/> + <path class="st1" d="M844.3,532.4H832c-3,0-5.5-2.2-5.9-5.2c-3.7-25.2-23.5-45-48.7-48.7c-2.9-0.4-5.1-2.9-5.2-5.9v-12.3 + C811.3,462,842.6,493.3,844.3,532.4z"/> + <path class="st1" d="M844.4,535.7c0,1.1,0,2.2-0.1,3.3H832c-3,0-5.5,2.2-5.9,5.2c-3.7,25.2-23.5,45-48.7,48.7 + c-2.9,0.4-5.1,2.9-5.2,5.9v12.3c-1.1,0.1-2.2,0.1-3.3,0.1s-2.2,0-3.3-0.1v-12.3c0-3-2.2-5.5-5.2-5.9c-25.2-3.7-45-23.5-48.7-48.7 + c-0.4-2.9-2.9-5.1-5.9-5.2h-12.3c-0.1-1.1-0.1-2.2-0.1-3.3s0-2.2,0.1-3.3h12.3c3,0,5.5-2.2,5.9-5.2c3.7-25.2,23.5-45,48.7-48.7 + c2.9-0.4,5.1-2.9,5.2-5.9v-12.3c1.1-0.1,2.2-0.1,3.3-0.1s2.2,0,3.3,0.1v12.3c0,3,2.2,5.5,5.2,5.9c25.2,3.7,45,23.5,48.7,48.7 + c0.4,2.9,2.9,5.1,5.9,5.2h12.3C844.3,533.5,844.4,534.6,844.4,535.7z"/> +</g> +<path class="st2" d="M601.6,906.6h-7.9c-3.6,0-6.4-2.9-6.5-6.5V742.9c0-4.9,1.2-9.6,3.4-13.9l6.7-13v-79.2l-6.7-13 + c-2.2-4.3-3.4-9.1-3.4-14V340.1c0-4.9,1.2-9.6,3.4-13.9l6.7-13V234l-6.7-13c-2.2-4.3-3.4-9.1-3.4-14V71.2c0-3.6,2.9-6.4,6.5-6.5h7.9 + c3.6,0,6.4,2.9,6.5,6.5v828.9C608,903.7,605.1,906.6,601.6,906.6z M593.7,65.7c-3,0-5.5,2.4-5.5,5.5V207c0,4.7,1.1,9.3,3.3,13.5 + l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2l-6.8,13.1c-2.2,4.2-3.3,8.8-3.3,13.5v269.7c0,4.7,1.1,9.3,3.3,13.5 + l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2l-6.8,13.1c-2.2,4.2-3.3,8.8-3.3,13.5v157.2c0,3,2.4,5.5,5.5,5.5h7.9 + c3,0,5.5-2.4,5.5-5.5V71.2c0-3-2.4-5.5-5.5-5.5H593.7z"/> +<path class="st2" d="M618.8,858.9h-11.3c-0.3,0-0.5-0.2-0.5-0.5l0,0V72c0-0.3,0.2-0.5,0.5-0.5h11.3c0.3,0,0.5,0.2,0.5,0.5v786.4 + C619.3,858.7,619.1,858.9,618.8,858.9L618.8,858.9z M608,857.9h10.3V72.5H608V857.9z"/> +<path class="st2" d="M730.9,1000H624.7c-3.6,0-6.5-2.9-6.5-6.5v-978c0-3.6,2.9-6.5,6.5-6.5h106.2c116.8,0,211.9,95.1,211.9,211.9 + v567.2C942.8,905.1,848,1000,730.9,1000L730.9,1000z M624.7,10.1c-3,0-5.5,2.4-5.5,5.5v978c0,3,2.4,5.5,5.5,5.5h106.2 + c116.3,0,210.9-94.6,210.9-210.9V220.9C941.8,104.6,847.2,10,730.9,10L624.7,10.1z"/> +<path class="st2" d="M715,763.2c-23.1,0-41.9-18.7-41.9-41.9s18.7-41.9,41.9-41.9s41.9,18.7,41.9,41.9l0,0 + C756.8,744.4,738.1,763.1,715,763.2z M715,680.4c-22.6,0-40.9,18.3-40.9,40.9c0,22.6,18.3,40.9,40.9,40.9 + c22.6,0,40.9-18.3,40.9-40.9l0,0C755.8,698.7,737.6,680.4,715,680.4z"/> +<path class="st1" d="M782.2,203.2h-5.5l-7.8-12.9l-7.8,12.9h-5.4l10.6-16.3l-9.8-15.6h5.2l7.3,12l7.4-12h5l-9.8,15.4L782.2,203.2z" + /> +<path class="st1" d="M709.2,244.5l-11.6,20.6v11.4h-4.4V265l-11.6-20.5h5.3l6.4,11.7l2.3,4.7l2.2-4.3l6.4-12.1L709.2,244.5z"/> +<path class="st1" d="M855.9,276.5h-4.7l-2.2-7h-13.3l-2.3,7h-4.5l10.6-32h6L855.9,276.5z M847.7,265.6l-5.4-17.1l-5.4,17.1H847.7z" + /> +<path class="st1" d="M779.4,340.4c0,1.4-0.3,2.8-0.9,4.1c-0.6,1.2-1.5,2.2-2.5,3c-1.2,0.9-2.6,1.5-4,1.9c-1.7,0.4-3.4,0.7-5.2,0.6 + h-8.4v-32h9.2c7.1,0,10.7,2.6,10.7,7.8c0,1.6-0.4,3.1-1.2,4.5c-1,1.4-2.4,2.3-4,2.8c0.9,0.2,1.7,0.4,2.5,0.8s1.5,0.9,2,1.5 + c0.6,0.6,1.1,1.4,1.4,2.2C779.2,338.4,779.4,339.4,779.4,340.4z M773.7,326.3c0-0.6-0.1-1.3-0.3-1.8c-0.2-0.6-0.6-1.1-1-1.5 + c-0.6-0.5-1.3-0.8-2-1c-1-0.3-2.1-0.4-3.2-0.4h-4.5v10h4.4c0.9,0,1.8-0.1,2.7-0.3c0.8-0.2,1.5-0.5,2.1-1c0.6-0.4,1-1,1.3-1.7 + C773.6,327.9,773.7,327.1,773.7,326.3L773.7,326.3z M774.8,340.5c0-0.8-0.2-1.5-0.5-2.2c-0.4-0.7-0.9-1.2-1.5-1.7 + c-0.7-0.5-1.5-0.8-2.4-1c-1-0.3-2.1-0.4-3.2-0.4h-4.5v11h4.6c2.5,0,4.4-0.5,5.6-1.4C774.2,343.8,774.9,342.2,774.8,340.5 + L774.8,340.5z"/> +<path class="st1" d="M715,701.3L695.4,721h5.6v16.8h28.2V721h5.3L715,701.3z M720.7,731.8h-11.1V721h11.1V731.8z"/> +<path class="st1" d="M597.9,314.3h-4.2c-3.8,0-6.9-3.1-7-7v-67.6c0-3.8,3.1-6.9,7-7h4.2c0.6,0,1,0.4,1,1l0,0v79.5 + C598.9,313.9,598.4,314.3,597.9,314.3L597.9,314.3z M593.7,234.8c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5h3.2v-77.5L593.7,234.8 + L593.7,234.8z"/> +<path class="st1" d="M597.9,717.1h-4.2c-3.8,0-6.9-3.1-7-7v-67.6c0-3.8,3.1-6.9,7-7h4.2c0.6,0,1,0.4,1,1l0,0V716 + C598.9,716.6,598.4,717.1,597.9,717.1L597.9,717.1z M593.7,637.6c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5h3.2v-77.5L593.7,637.6 + L593.7,637.6z"/> +<path class="st1" d="M925.6,139.3c-0.1,0-0.1,0-0.2,0c-0.3-0.1-0.6-0.3-0.7-0.6C891.7,61,815.4,10.5,730.9,10.6h-54.2 + c-0.6,0-1-0.4-1-1l0,0V7c0-3.8,3.1-6.9,7-7h51.2c85.2,0.1,162.4,50.1,197.3,127.8c1.2,2.6,0.6,5.7-1.5,7.8l-3.4,3.4 + C926.1,139.2,925.8,139.3,925.6,139.3z M677.7,8.6h53.2c84.7-0.1,161.3,50.2,195,128l2.4-2.4l0,0c1.5-1.4,1.9-3.6,1.1-5.5 + C894.8,51.7,818.3,2.1,733.9,2h-51.2c-2.7,0-5,2.2-5,5V8.6z"/> +<path class="st1" d="M676.5,133.7h-11.7c-2.2,0-4-1.8-4-4V118c0-1.1-0.9-2-2-2h-11.7c-2.2,0-4-1.8-4-4v-11.7c0-2.2,1.8-4,4-4h11.7 + c1.1,0,2-0.9,2-2V82.8c0-2.2,1.8-4,4-4h11.7c2.2,0,4,1.8,4,4v11.7c0,1.1,0.9,2,2,2h11.7c2.2,0,4,1.8,4,4v11.7c0,2.2-1.8,4-4,4h-11.7 + c-1.1,0-2,0.9-2,2v11.7C680.5,131.9,678.7,133.7,676.5,133.7z M647.2,98.5c-1.1,0-2,0.9-2,2v11.7c0,1.1,0.9,2,2,2h11.7 + c2.2,0,4,1.8,4,4v11.7c0,1.1,0.9,2,2,2h11.7c1.1,0,2-0.9,2-2v-11.7c0-2.2,1.8-4,4-4h11.7c1.1,0,2-0.9,2-2v-11.7c0-1.1-0.9-2-2-2 + h-11.7c-2.2,0-4-1.8-4-4V82.8c0-1.1-0.9-2-2-2h-11.7c-1.1,0-2,0.9-2,2v11.7c0,2.2-1.8,4-4,4H647.2z"/> +<path class="st1" d="M768.9,372.4c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 + C807.3,355.2,790.1,372.4,768.9,372.4z M768.9,297.5c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 + c20.1,0,36.5-16.3,36.5-36.5C805.3,313.8,789,297.5,768.9,297.5L768.9,297.5z"/> +<path class="st1" d="M768.9,225.5c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 + C807.3,208.3,790.1,225.5,768.9,225.5z M768.9,150.6c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 + c20.1,0,36.5-16.3,36.5-36.5C805.3,166.9,789,150.6,768.9,150.6L768.9,150.6z"/> +<path class="st1" d="M842.3,299c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 + C880.8,281.7,863.6,298.9,842.3,299z M842.3,224c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 + c20.1,0,36.5-16.3,36.5-36.5C878.8,240.4,862.5,224,842.3,224L842.3,224z"/> +<path class="st1" d="M695.5,299c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 + C733.9,281.7,716.7,298.9,695.5,299z M695.5,224c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 + c20.1,0,36.5-16.3,36.5-36.5C731.9,240.4,715.6,224,695.5,224L695.5,224z"/> +<path class="st1" d="M715,750.2c-16,0-28.9-13-28.9-28.9s13-28.9,28.9-28.9c16,0,28.9,13,28.9,28.9l0,0 + C743.9,737.3,731,750.2,715,750.2z M715,694.3c-14.9,0-26.9,12.1-26.9,26.9s12.1,26.9,26.9,26.9c14.9,0,26.9-12.1,26.9-26.9 + C741.9,706.4,729.9,694.4,715,694.3z"/> +<path class="st1" d="M705.8,533.4h-12.3c-0.6,0-1-0.4-1-1l0,0c1.7-39.6,33.4-71.3,73-73c0.3,0,0.5,0.1,0.7,0.3 + c0.2,0.2,0.3,0.4,0.3,0.7v12.3c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9C712.2,530.8,709.3,533.4,705.8,533.4z + M694.6,531.4h11.2c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-11.2 + C727.2,463.5,696.7,494,694.6,531.4z"/> +<path class="st1" d="M765.6,612.1C765.6,612.1,765.5,612.1,765.6,612.1c-39.6-1.7-71.3-33.4-73-73c0-0.6,0.4-1,1-1l0,0h12.3 + c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9v12.3C766.6,611.6,766.1,612.1,765.6,612.1L765.6,612.1 + L765.6,612.1z M694.6,540c2.2,37.4,32.6,67.8,70,70v-11.2c0-2.5-1.8-4.6-4.3-4.9c-25.6-3.9-45.7-24-49.6-49.6 + c-0.3-2.5-2.4-4.3-4.9-4.3H694.6z"/> +<path class="st1" d="M772.2,612.1c-0.6,0-1-0.4-1-1l0,0v-12.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9 + c0.5-3.4,3.4-6,6.9-6h12.3c0.6,0,1,0.4,1,1l0,0C843.5,578.7,811.9,610.3,772.2,612.1C772.3,612.1,772.3,612.1,772.2,612.1z M832,540 + c-2.5,0-4.6,1.8-4.9,4.3c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9V610c37.4-2.2,67.8-32.6,70-70H832z"/> +<path class="st1" d="M844.3,533.4H832c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-12.3 + c0-0.3,0.1-0.5,0.3-0.7s0.5-0.3,0.7-0.3c39.6,1.7,71.3,33.4,73,73C845.3,532.9,844.9,533.3,844.3,533.4L844.3,533.4L844.3,533.4z + M773.2,461.4v11.2c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h11.2 + C841.1,494,810.6,463.5,773.2,461.4z"/> +<path class="st1" d="M768.9,612.2c-1.2,0-2.3,0-3.4-0.1c-0.5,0-0.9-0.5-0.9-1v-12.3c0-2.5-1.8-4.6-4.3-4.9 + c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-12.3c-0.5,0-1-0.4-1-0.9c-0.1-1.1-0.1-2.2-0.1-3.4s0-2.3,0.1-3.4 + c0-0.5,0.5-0.9,1-0.9h12.3c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-12.3c0-0.5,0.4-1,0.9-1 + c2.3-0.1,4.5-0.1,6.8,0c0.5,0,0.9,0.5,0.9,1v12.3c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h12.3 + c0.5,0,1,0.4,1,0.9c0.1,1.1,0.1,2.2,0.1,3.4s0,2.3-0.1,3.4c0,0.5-0.5,0.9-1,0.9H832c-2.5,0-4.6,1.8-4.9,4.3 + c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v12.3c0,0.5-0.4,1-0.9,1C771.2,612.1,770.1,612.2,768.9,612.2z M766.6,610.1 + c1.5,0.1,3.1,0.1,4.7,0v-11.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6h11.3c0-0.8,0-1.5,0-2.3 + s0-1.6,0-2.3H832c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-11.3c-1.5-0.1-3.1-0.1-4.7,0v11.3 + c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-11.3c0,0.8,0,1.5,0,2.3s0,1.6,0,2.3h11.3 + c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9v11.3H766.6z"/> +</svg> diff --git a/Ryujinx/Ui/assets/ProCon.png b/Ryujinx/Ui/assets/ProCon.png Binary files differdeleted file mode 100644 index 85636226..00000000 --- a/Ryujinx/Ui/assets/ProCon.png +++ /dev/null diff --git a/Ryujinx/Ui/assets/ProCon.svg b/Ryujinx/Ui/assets/ProCon.svg new file mode 100644 index 00000000..8c2b879f --- /dev/null +++ b/Ryujinx/Ui/assets/ProCon.svg @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 1000 1000.5" style="enable-background:new 0 0 1000 1000.5;" xml:space="preserve"> +<style type="text/css"> + .st0{opacity:0.1;} + .st1{fill:#1ABC9C;} + .st2{fill:#CCCCCC;} + .st3{fill:#FFFFFF;} +</style> +<g class="st0"> + <path class="st1" d="M259.4,630.9c-22.4,12.5-32.3,39.7-49,69.8c-35.7,64.1-50.5,128.9-116.6,128.9C40.8,829.5,1,776.1,1,705.8 + c0-48.3,29.9-226.9,55.6-347.6C113.4,453.9,219.5,604.4,259.4,630.9z"/> + <path class="st1" d="M999,705.8c0,70.4-39.9,123.8-92.7,123.8c-66.1,0-80.9-64.8-116.6-128.9c-16.7-30-26.7-57.3-49-69.8 + c39.8-26.5,146-177,202.7-272.7C969.1,478.9,999,657.5,999,705.8z"/> + <circle class="st1" cx="630.3" cy="482.7" r="56.2"/> + <circle class="st1" cx="630.3" cy="482.7" r="40.5"/> + <circle class="st1" cx="764.9" cy="276.6" r="36.6"/> + <circle class="st1" cx="764.9" cy="412.6" r="36.6"/> + <circle class="st1" cx="223.9" cy="344.8" r="56.2"/> + <circle class="st1" cx="223.9" cy="344.8" r="40.5"/> + <circle class="st1" cx="843.1" cy="344.6" r="36.6"/> + <circle class="st1" cx="686.7" cy="344.6" r="36.6"/> + <circle class="st1" cx="624.1" cy="269.3" r="22.1"/> + <circle class="st1" cx="571.3" cy="344.6" r="22.1"/> + <circle class="st1" cx="375.9" cy="269.3" r="22.1"/> + <circle class="st1" cx="428.7" cy="344.6" r="14"/> + <path class="st1" d="M414.6,326.5h28.2c2.2,0,4.1,1.8,4.1,4.1v28.2c0,2.2-1.8,4.1-4.1,4.1h-28.2c-2.2,0-4.1-1.8-4.1-4.1v-28.2 + C410.6,328.3,412.4,326.5,414.6,326.5z"/> + <path class="st1" d="M351.6,158.8c-88.4,3.8-169.6,13.7-207,39.4c-14.9,10.2-26.4,16.9-32.9,20.5C142.6,135.9,282,138,299,138 + c6.5,0,26.6,8.7,39.9,14.8h0C346.3,156.2,351.6,158.8,351.6,158.8z"/> + <path class="st1" d="M888.3,218.7c-6.5-3.6-18-10.3-32.9-20.6c-37.4-25.7-118.7-35.6-207-39.4c0,0,5.3-2.6,12.6-6 + c13.4-6.1,33.4-14.8,40-14.8C717.9,138,857.4,135.9,888.3,218.7z"/> + <path class="st1" d="M414.6,461.1H373c-2.2,0-4.1-1.8-4.1-4.1v-41.6c0-2.2-1.8-4.1-4.1-4.1c0,0,0,0,0,0h-36.4 + c-2.2,0-4.1,1.8-4.1,4.1c0,0,0,0,0,0v41.6c0,2.2-1.8,4.1-4.1,4.1h-41.6c-2.2,0-4.1,1.8-4.1,4.1v36.4c0,2.2,1.8,4.1,4.1,4.1h41.6 + c2.2,0,4.1,1.8,4.1,4.1l0,0v41.6c0,2.2,1.8,4.1,4.1,4.1c0,0,0,0,0,0h36.4c2.2,0,4.1-1.8,4.1-4.1l0,0v-41.6c0-2.2,1.8-4.1,4.1-4.1 + l0,0h41.6c2.2,0,4.1-1.8,4.1-4.1v-36.4C418.6,462.9,416.8,461.1,414.6,461.1z"/> +</g> +<path class="st2" d="M661,153.1L661,153.1c-0.2,0-0.3-0.1-0.3-0.3c0-0.1,0.1-0.2,0.2-0.2c0.1,0,0.3,0.1,0.3,0.2 + C661.3,153,661.2,153.1,661,153.1C661,153.1,661,153.1,661,153.1z"/> +<path class="st3" d="M630.3,560.6c-43,0-77.9-34.9-77.9-77.9s34.9-77.9,77.9-77.9c43,0,77.9,34.9,77.9,77.9 + C708.2,525.7,673.3,560.6,630.3,560.6z M630.3,405.8c-42.5,0-76.9,34.4-76.9,76.9s34.4,76.9,76.9,76.9c42.5,0,76.9-34.4,76.9-76.9 + C707.2,440.3,672.8,405.9,630.3,405.8L630.3,405.8z"/> +<path class="st3" d="M223.9,422.7c-43,0-77.9-34.9-77.9-77.9c0-43,34.9-77.9,77.9-77.9s77.9,34.9,77.9,77.9l0,0 + C301.7,387.8,266.9,422.7,223.9,422.7z M223.9,267.9c-42.5,0-76.9,34.4-76.9,76.9c0,42.5,34.4,76.9,76.9,76.9s76.9-34.4,76.9-76.9 + l0,0C300.7,302.4,266.3,268,223.9,267.9z"/> +<path class="st3" d="M648.4,159.3L648.4,159.3c-49.9-2.1-102.8-2.3-148.4-2.3c-45.6,0-98.4,0.2-148.4,2.3c-0.1,0-0.2,0-0.2-0.1 + c-0.1,0-5.4-2.6-12.6-6c-0.3-0.1-0.4-0.4-0.2-0.7c0.1-0.2,0.2-0.3,0.4-0.3c2-0.2,50-4.9,161.1-4.9c111.7,0,159.1,4.7,161,4.9 + c0.3,0,0.5,0.3,0.4,0.5c0,0.2-0.1,0.3-0.3,0.4c-7.2,3.3-12.6,5.9-12.6,6C648.5,159.3,648.4,159.3,648.4,159.3z M340.9,153.2 + c5.8,2.7,10.1,4.8,10.8,5.1c49.9-2.1,102.7-2.3,148.3-2.3c45.6,0,98.4,0.2,148.3,2.3c0.7-0.4,5-2.4,10.8-5.1 + c-9.8-0.9-58.2-4.7-159.1-4.7C399.6,148.5,350.7,152.3,340.9,153.2L340.9,153.2z"/> +<path class="st3" d="M740.6,631.4c-0.1,0-0.2,0-0.2-0.1c-8.6-4.8-18.6-7.2-30.7-7.2H290.3c-12,0-22.1,2.4-30.7,7.2 + c-0.2,0.1-0.4,0.1-0.5,0C218.3,604.2,110,449.1,56.2,358.4c-0.1-0.1-0.1-0.2-0.1-0.4c11.3-53.3,20.7-90,27.1-106.1 + c1.2-3.1,2.9-5.9,4.9-8.5l12.7-16.2c2.9-3.7,6.5-6.8,10.6-9c0,0,0,0,0,0l0,0c7.1-3.9,18.5-10.6,32.8-20.5 + c32-22,99.8-34.9,207.3-39.4c49.5-2.1,100.5-2.3,148.4-2.3c47.9,0,98.8,0.2,148.4,2.3c107.5,4.6,175.3,17.5,207.3,39.4 + c14.4,9.9,25.8,16.6,32.9,20.5c4.1,2.2,7.7,5.3,10.6,9l12.7,16.2c2.1,2.6,3.7,5.5,4.9,8.6c6.4,16.1,15.7,52.8,27.1,106.1 + c0,0.1,0,0.3-0.1,0.4C890,449.1,781.7,604.2,740.9,631.3C740.8,631.4,740.7,631.4,740.6,631.4z M57.2,358.1 + c53.6,90.4,161.4,244.7,202.2,272.2c8.7-4.8,18.8-7.2,30.9-7.2h419.4c12.1,0,22.2,2.3,30.9,7.2c40.8-27.5,148.6-181.8,202.2-272.2 + c-11.3-53.1-20.6-89.7-27-105.7c-1.2-3-2.8-5.8-4.8-8.3l-12.7-16.2c-2.8-3.6-6.3-6.5-10.3-8.7c-7.1-3.9-18.5-10.7-33-20.6 + c-31.8-21.9-99.4-34.7-206.8-39.3c-49.5-2.1-100.4-2.3-148.3-2.3c-47.9,0-98.8,0.2-148.4,2.3c-107.3,4.6-174.9,17.4-206.7,39.3 + c-14.4,9.9-25.8,16.6-32.9,20.5c0,0-0.1,0-0.1,0.1c-4,2.2-7.5,5.2-10.3,8.7l-12.7,16.2c-2,2.5-3.6,5.3-4.8,8.3 + C77.8,268.4,68.5,305,57.2,358.1z"/> +<path class="st1" d="M93.7,830.5C40.3,830.5,0,776.9,0,705.8C0,657.1,29.9,478.8,55.6,358c0.1-0.5,0.6-0.9,1.2-0.8 + c0.3,0.1,0.5,0.2,0.7,0.5c53.7,90.5,161.9,245.4,202.4,272.4c0.5,0.3,0.6,0.9,0.3,1.4c-0.1,0.1-0.2,0.2-0.3,0.3 + c-17.4,9.7-27.3,28.8-38.8,50.9c-3.1,6-6.3,12.1-9.8,18.4c-7.3,13.1-13.7,26.1-19.8,38.7C167.5,788.5,146.9,830.5,93.7,830.5z + M57.1,360.9C31.5,481.6,2,657.5,2,705.8c0,70,39.4,122.8,91.7,122.8c52,0,72.3-41.5,95.9-89.6c6.2-12.6,12.6-25.7,19.9-38.8 + c3.5-6.3,6.7-12.4,9.8-18.4c11.3-21.8,21.2-40.7,38.2-51C216.1,601.5,110.7,450.9,57.1,360.9z"/> +<path class="st1" d="M906.3,830.5c-53.3,0-73.9-42-97.7-90.7c-6.2-12.6-12.5-25.6-19.8-38.7c-3.5-6.3-6.7-12.5-9.8-18.4 + c-11.5-22.1-21.4-41.2-38.8-50.9c-0.5-0.3-0.7-0.9-0.4-1.4c0.1-0.1,0.2-0.3,0.3-0.3c40.6-27,148.7-181.8,202.4-272.4 + c0.3-0.5,0.9-0.6,1.4-0.3c0.2,0.1,0.4,0.4,0.5,0.7c25.7,120.9,55.6,299.1,55.6,347.8C1000,776.9,959.7,830.5,906.3,830.5z + M742.5,630.8c17.1,10.2,26.9,29.2,38.2,51c3.1,6,6.3,12.1,9.8,18.4c7.3,13.1,13.7,26.1,19.9,38.7c23.5,48.1,43.9,89.6,95.9,89.6 + c52.3,0,91.7-52.8,91.7-122.8c0-48.2-29.5-224.2-55.1-344.9C889.3,450.9,783.9,601.5,742.5,630.8z"/> +<path class="st1" d="M630.3,539.9c-31.6,0-57.2-25.6-57.2-57.2c0-31.6,25.6-57.2,57.2-57.2c31.6,0,57.2,25.6,57.2,57.2l0,0 + C687.5,514.3,661.9,539.9,630.3,539.9z M630.3,427.5c-30.5,0-55.2,24.7-55.2,55.2c0,30.5,24.7,55.2,55.2,55.2 + c30.5,0,55.2-24.7,55.2-55.2C685.5,452.2,660.8,427.5,630.3,427.5L630.3,427.5z"/> +<path class="st1" d="M630.3,524.2c-22.9,0-41.5-18.6-41.5-41.5s18.6-41.5,41.5-41.5c22.9,0,41.5,18.6,41.5,41.5 + C671.8,505.6,653.2,524.2,630.3,524.2z M630.3,443.2c-21.8,0-39.5,17.7-39.5,39.5c0,21.8,17.7,39.5,39.5,39.5 + c21.8,0,39.5-17.7,39.5-39.5C669.8,460.9,652.1,443.2,630.3,443.2z"/> +<path class="st1" d="M764.9,314.2c-20.7,0-37.6-16.8-37.5-37.6c0-20.7,16.8-37.6,37.6-37.5c20.7,0,37.5,16.8,37.5,37.6 + C802.4,297.4,785.6,314.1,764.9,314.2z M764.9,241.1c-19.6,0-35.6,15.9-35.6,35.6c0,19.6,15.9,35.6,35.6,35.6 + c19.6,0,35.6-15.9,35.6-35.6C800.4,257,784.5,241.1,764.9,241.1L764.9,241.1z"/> +<path class="st1" d="M764.9,450.2c-20.7,0-37.6-16.8-37.5-37.6c0-20.7,16.8-37.6,37.6-37.5c20.7,0,37.5,16.8,37.5,37.6 + C802.4,433.4,785.6,450.2,764.9,450.2z M764.9,377.1c-19.6,0-35.6,15.9-35.6,35.6c0,19.6,15.9,35.6,35.6,35.6 + c19.6,0,35.6-15.9,35.6-35.6C800.4,393,784.5,377.1,764.9,377.1z"/> +<path class="st1" d="M223.9,402.1c-31.6,0-57.2-25.6-57.2-57.2c0-31.6,25.6-57.2,57.2-57.2s57.2,25.6,57.2,57.2 + C281.1,376.4,255.5,402,223.9,402.1z M223.9,289.6c-30.5,0-55.2,24.7-55.2,55.2c0,30.5,24.7,55.2,55.2,55.2 + c30.5,0,55.2-24.7,55.2-55.2c0,0,0,0,0,0C279.1,314.4,254.4,289.7,223.9,289.6L223.9,289.6z"/> +<path class="st1" d="M223.9,386.4c-22.9,0-41.5-18.6-41.5-41.5c0-22.9,18.6-41.5,41.5-41.5s41.5,18.6,41.5,41.5 + C265.4,367.8,246.8,386.3,223.9,386.4z M223.9,305.3c-21.8,0-39.5,17.7-39.5,39.5c0,21.8,17.7,39.5,39.5,39.5s39.5-17.7,39.5-39.5 + l0,0C263.4,323,245.7,305.3,223.9,305.3L223.9,305.3z"/> +<path class="st1" d="M843.1,382.2c-20.7,0-37.6-16.8-37.6-37.5s16.8-37.6,37.5-37.6c20.7,0,37.6,16.8,37.6,37.5c0,0,0,0,0,0 + C880.6,365.4,863.8,382.2,843.1,382.2z M843.1,309.1c-19.6,0-35.6,15.9-35.6,35.6s15.9,35.6,35.6,35.6c19.6,0,35.6-15.9,35.6-35.6 + c0,0,0,0,0,0C878.6,325,862.7,309.1,843.1,309.1z"/> +<path class="st1" d="M686.7,382.2c-20.7,0-37.6-16.8-37.6-37.6s16.8-37.6,37.6-37.6c20.7,0,37.6,16.8,37.6,37.6 + C724.2,365.4,707.4,382.2,686.7,382.2z M686.7,309.1c-19.6,0-35.6,15.9-35.6,35.6s15.9,35.6,35.6,35.6c19.6,0,35.6-15.9,35.6-35.6 + l0,0C722.2,325,706.3,309.1,686.7,309.1z"/> +<path class="st1" d="M624.1,292.4c-12.8,0-23.1-10.3-23.1-23.1c0-12.8,10.3-23.1,23.1-23.1c12.8,0,23.1,10.3,23.1,23.1 + C647.2,282,636.8,292.4,624.1,292.4z M624.1,248.2c-11.7,0-21.1,9.5-21.1,21.1c0,11.7,9.5,21.1,21.1,21.1c11.7,0,21.1-9.5,21.1-21.1 + C645.2,257.6,635.7,248.2,624.1,248.2z"/> +<path class="st1" d="M571.3,367.7c-12.8,0-23.1-10.3-23.1-23.1c0-12.8,10.3-23.1,23.1-23.1c12.8,0,23.1,10.3,23.1,23.1 + C594.3,357.4,584,367.7,571.3,367.7z M571.3,323.5c-11.7,0-21.1,9.5-21.1,21.1c0,11.7,9.5,21.1,21.1,21.1c11.7,0,21.1-9.5,21.1-21.1 + C592.3,333,582.9,323.5,571.3,323.5L571.3,323.5z"/> +<path class="st1" d="M375.9,292.4c-12.8,0-23.1-10.3-23.1-23.1c0-12.8,10.3-23.1,23.1-23.1c12.8,0,23.1,10.3,23.1,23.1 + C399,282,388.7,292.4,375.9,292.4z M375.9,248.2c-11.7,0-21.1,9.5-21.1,21.1c0,11.7,9.5,21.1,21.1,21.1c11.7,0,21.1-9.5,21.1-21.1 + C397,257.6,387.6,248.2,375.9,248.2z"/> +<path class="st1" d="M428.7,359.6c-8.3,0-15-6.7-15-15s6.7-15,15-15s15,6.7,15,15l0,0C443.7,352.9,437,359.6,428.7,359.6z + M428.7,331.7c-7.2,0-13,5.8-13,13c0,7.2,5.8,13,13,13c7.2,0,13-5.8,13-13c0,0,0,0,0,0C441.7,337.5,435.9,331.7,428.7,331.7 + L428.7,331.7z"/> +<path class="st1" d="M442.8,363.8h-28.2c-2.8,0-5.1-2.3-5.1-5.1v-28.2c0-2.8,2.3-5.1,5.1-5.1h28.2c2.8,0,5.1,2.3,5.1,5.1v28.2 + C447.9,361.5,445.6,363.8,442.8,363.8z M414.6,327.5c-1.7,0-3.1,1.4-3.1,3.1v28.2c0,1.7,1.4,3.1,3.1,3.1h28.2c1.7,0,3.1-1.4,3.1-3.1 + v-28.2c0-1.7-1.4-3.1-3.1-3.1H414.6z"/> +<path class="st1" d="M111.7,219.7c-0.6,0-1-0.4-1-1c0-0.1,0-0.2,0.1-0.3c27.3-73.2,138.4-81.3,186-81.3c0.3,0,0.6,0,1,0l1.2,0 + c6.6,0,25.5,8.1,40.3,14.9c0,0,0.1,0,0.1,0c7.2,3.3,12.6,6,12.7,6c0.5,0.2,0.7,0.8,0.5,1.3c-0.2,0.3-0.5,0.5-0.9,0.6 + c-107.2,4.6-174.8,17.4-206.5,39.2c-14.6,10-26,16.7-33,20.6C112.1,219.6,111.9,219.7,111.7,219.7z M296.8,139 + c-46.6,0-154.6,7.8-183.1,77.5c7-4,17.5-10.3,30.4-19.1c31.6-21.7,98.2-34.6,203.6-39.4c-2.2-1.1-5.4-2.5-8.9-4.2c0,0-0.1,0-0.1,0 + c-20.6-9.5-34.7-14.7-39.5-14.7l-1.2,0C297.5,139,297.1,139,296.8,139L296.8,139z"/> +<path class="st1" d="M888.3,219.7c-0.2,0-0.3,0-0.5-0.1c-7-3.9-18.5-10.7-33-20.6c-31.7-21.8-99.3-34.6-206.5-39.2c-0.6,0-1-0.5-1-1 + c0-0.4,0.2-0.7,0.6-0.9c0.1,0,5.4-2.6,12.7-6C682.2,142,695.8,137,701,137l1.2,0c0.3,0,0.6,0,1,0c47.6,0,158.7,8.1,186.1,81.4 + c0.2,0.5-0.1,1.1-0.6,1.3C888.5,219.7,888.4,219.7,888.3,219.7L888.3,219.7z M652.4,158c105.3,4.7,171.9,17.6,203.6,39.4 + c12.9,8.8,23.3,15.1,30.4,19.1C857.8,146.8,749.8,139,703.2,139c-0.3,0-0.6,0-1,0l-1.2,0c-4.8,0-18.8,5.2-39.5,14.7 + C657.8,155.4,654.6,156.9,652.4,158z"/> +<path class="st1" d="M364.9,556.4h-36.4c-2.8,0-5.1-2.3-5.1-5.1v-41.6c0-1.7-1.4-3.1-3.1-3.1h-41.6c-2.8,0-5.1-2.3-5.1-5.1v-36.4 + c0-2.8,2.3-5.1,5.1-5.1h41.6c1.7,0,3.1-1.4,3.1-3.1v-41.6c0-2.8,2.3-5.1,5.1-5.1h36.4c2.8,0,5.1,2.3,5.1,5.1v41.6 + c0,1.7,1.4,3.1,3.1,3.1h41.6c2.8,0,5.1,2.3,5.1,5.1v36.4c0,2.8-2.3,5.1-5.1,5.1H373c-1.7,0-3.1,1.4-3.1,3.1v41.6 + C369.9,554.1,367.7,556.4,364.9,556.4z M278.8,462.1c-1.7,0-3.1,1.4-3.1,3.1v36.4c0,1.7,1.4,3.1,3.1,3.1h41.6c2.8,0,5.1,2.3,5.1,5.1 + v41.6c0,1.7,1.4,3.1,3.1,3.1h36.4c1.7,0,3.1-1.4,3.1-3.1v-41.6c0-2.8,2.3-5.1,5.1-5.1h41.6c1.7,0,3.1-1.4,3.1-3.1v-36.4 + c0-1.7-1.4-3.1-3.1-3.1H373c-2.8,0-5.1-2.3-5.1-5.1v-41.6c0-1.7-1.4-3.1-3.1-3.1h-36.4c-1.7,0-3.1,1.4-3.1,3.1v41.6 + c0,2.8-2.3,5.1-5.1,5.1H278.8z"/> +<rect x="363.7" y="267.5" class="st1" width="24.4" height="3.5"/> +<polygon class="st1" points="636.3,267.5 625.8,267.5 625.8,257.1 622.3,257.1 622.3,267.5 611.9,267.5 611.9,271 622.3,271 + 622.3,281.4 625.8,281.4 625.8,271 636.3,271 "/> +<path class="st1" d="M775.5,289.9H771l-6.3-10.4l-6.3,10.4h-4.4l8.6-13.2l-7.9-12.6h4.2l5.9,9.7l5.9-9.7h4l-7.9,12.4L775.5,289.9z" + /> +<path class="st1" d="M697.8,331.8l-9.3,16.5v9.2h-3.5v-9.3l-9.3-16.5h4.2l5.1,9.4l1.9,3.8l1.7-3.4l5.2-9.8L697.8,331.8z"/> +<path class="st1" d="M854,357.5h-3.8l-1.8-5.6h-10.7l-1.8,5.6h-3.6l8.5-25.7h4.8L854,357.5z M847.4,348.8L843,335l-4.4,13.8H847.4z" + /> +<path class="st1" d="M773.3,417.8c0,1.1-0.2,2.3-0.7,3.3c-0.5,1-1.2,1.8-2,2.4c-1,0.7-2.1,1.2-3.2,1.5c-1.4,0.4-2.8,0.5-4.2,0.5 + h-6.7v-25.7h7.4c5.7,0,8.6,2.1,8.6,6.3c0,1.3-0.3,2.5-1,3.6c-0.8,1.1-1.9,1.9-3.2,2.2c0.7,0.1,1.4,0.4,2,0.7 + c0.6,0.3,1.2,0.7,1.6,1.2c0.5,0.5,0.9,1.1,1.1,1.8C773.2,416.2,773.4,417,773.3,417.8z M768.8,406.5c0-0.5-0.1-1-0.2-1.5 + c-0.2-0.5-0.4-0.9-0.8-1.2c-0.5-0.4-1-0.6-1.6-0.8c-0.8-0.2-1.7-0.3-2.5-0.3H760v8.1h3.5c0.7,0,1.5-0.1,2.2-0.3 + c0.6-0.1,1.2-0.4,1.7-0.8c0.5-0.3,0.8-0.8,1.1-1.3C768.7,407.8,768.8,407.2,768.8,406.5L768.8,406.5z M769.6,417.9 + c0-0.6-0.1-1.2-0.4-1.8c-0.3-0.5-0.7-1-1.2-1.3c-0.6-0.4-1.2-0.7-1.9-0.8c-0.8-0.2-1.7-0.3-2.5-0.3H760v8.9h3.7 + c1.6,0.1,3.2-0.3,4.5-1.1C769.2,420.6,769.7,419.3,769.6,417.9L769.6,417.9z"/> +<path class="st1" d="M571.3,329.3L557.7,343h3.9v11.6h19.5V343h3.7L571.3,329.3z M575.2,350.4h-7.7V343h7.7L575.2,350.4z"/> +<polygon class="st1" points="346.7,426.4 339.2,439.4 354.2,439.4 "/> +<polygon class="st1" points="346.7,540.4 339.2,527.4 354.2,527.4 "/> +<polygon class="st1" points="403.7,483.4 390.7,475.9 390.7,490.9 "/> +<polygon class="st1" points="289.6,483.4 302.6,475.9 302.6,490.9 "/> +</svg> diff --git a/Ryujinx/Ui/assets/RedCon.png b/Ryujinx/Ui/assets/RedCon.png Binary files differdeleted file mode 100644 index 6094b2e8..00000000 --- a/Ryujinx/Ui/assets/RedCon.png +++ /dev/null diff --git a/Ryujinx/_schema.json b/Ryujinx/_schema.json index f075b608..e89e2bf7 100644 --- a/Ryujinx/_schema.json +++ b/Ryujinx/_schema.json @@ -840,8 +840,8 @@ "title": "Joystick Deadzone", "description": "Controller Analog Stick Deadzone", "default": 0.05, - "minimum": -32768.0, - "maximum": 32767.0, + "minimum": 0.00, + "maximum": 1.00, "examples": [ 0.05 ] |
