diff --git a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs index ff5a67c4e7..09252b7739 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 /// /// The current version of the file format /// - public const int CurrentVersion = 5; + public const int CurrentVersion = 6; public int Version { get; set; } @@ -129,11 +127,6 @@ namespace Ryujinx.Configuration /// public bool IgnoreMissingServices { get; set; } - /// - /// The primary controller's type - /// - public ControllerType ControllerType { get; set; } - /// /// Used to toggle columns in the GUI /// @@ -162,12 +155,12 @@ namespace Ryujinx.Configuration /// /// Keyboard control bindings /// - public NpadKeyboard KeyboardControls { get; set; } + public List KeyboardConfig { get; set; } /// /// Controller control bindings /// - public NpadController JoystickControls { get; set; } + public List ControllerConfig { get; set; } /// /// Loads a configuration file from disk diff --git a/Ryujinx.Common/Configuration/ConfigurationState.cs b/Ryujinx.Common/Configuration/ConfigurationState.cs index d2826d3675..a994e6d57e 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 TimeZone { get; private set; } /// - /// System Time Offset in seconds + /// System Time Offset in Seconds /// public ReactiveObject SystemTimeOffset { get; private set; } @@ -207,32 +206,22 @@ namespace Ryujinx.Configuration /// public class HidSection { - /// - /// The primary controller's type - /// - public ReactiveObject ControllerType { get; private set; } - /// /// Enable or disable keyboard support (Independent from controllers binding) /// public ReactiveObject EnableKeyboard { get; private set; } /// - /// 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. /// - public ReactiveObject KeyboardControls { get; private set; } - - /// - /// Controller control bindings - /// - public ReactiveObject JoystickControls { get; private set; } + public ReactiveObject> InputConfig { get; private set; } public HidSection() { - ControllerType = new ReactiveObject(); - EnableKeyboard = new ReactiveObject(); - KeyboardControls = new ReactiveObject(); - JoystickControls = new ReactiveObject(); + EnableKeyboard = new ReactiveObject(); + InputConfig = new ReactiveObject>(); } } @@ -311,6 +300,21 @@ namespace Ryujinx.Configuration public ConfigurationFileFormat ToFileFormat() { + List controllerConfigList = new List(); + List keyboardConfigList = new List(); + + 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 { - LeftJoycon = new NpadKeyboardLeft + new KeyboardConfig { - 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 - { - 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(); + configurationFileFormat.KeyboardConfig = new List{ + 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 = new List(); + 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 similarity index 63% rename from Ryujinx.Common/Configuration/Hid/NpadController.cs rename to Ryujinx.Common/Configuration/Hid/ControllerConfig.cs index 94b985d55c..3e414055cb 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 { /// - /// Enables or disables controller support + /// Controller Left Analog Stick Deadzone /// - public bool Enabled { get; set; } + public float DeadzoneLeft { get; set; } /// - /// Controller Device Index + /// Controller Right Analog Stick Deadzone /// - public int Index { get; set; } - - /// - /// Controller Analog Stick Deadzone - /// - public float Deadzone { get; set; } + public float DeadzoneRight { get; set; } /// /// Controller Trigger Threshold @@ -32,4 +27,4 @@ /// 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 8969b6a4b8..606a1b0cd4 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 b0613b2d66..0ad01bbb69 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 0000000000..540506d5e0 --- /dev/null +++ b/Ryujinx.Common/Configuration/Hid/InputConfig.cs @@ -0,0 +1,20 @@ +namespace Ryujinx.Common.Configuration.Hid +{ + public class InputConfig + { + /// + /// Controller Device Index + /// + public int Index { get; set; } + + /// + /// Controller's Type + /// + public ControllerType ControllerType { get; set; } + + /// + /// Player's Index for the controller + /// + 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 b658396b9b..67177eecb6 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 0000000000..664fdff082 --- /dev/null +++ b/Ryujinx.Common/Configuration/Hid/KeyboardConfig.cs @@ -0,0 +1,20 @@ +namespace Ryujinx.Common.Configuration.Hid +{ + public class KeyboardConfig : InputConfig + { + /// + /// Left JoyCon Keyboard Bindings + /// + public NpadKeyboardLeft LeftJoycon { get; set; } + + /// + /// Right JoyCon Keyboard Bindings + /// + public NpadKeyboardRight RightJoycon { get; set; } + + /// + /// Hotkey Keyboard Bindings + /// + 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 30cc8d8449..19cc0487d5 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 c221b5e8a0..00816e56f2 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 f52f6f16df..b7b289cc92 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 5ae82756b7..0000000000 --- a/Ryujinx.Common/Configuration/Hid/NpadKeyboard.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Ryujinx.UI.Input -{ - public class NpadKeyboard - { - /// - /// Left JoyCon Keyboard Bindings - /// - public Configuration.Hid.NpadKeyboardLeft LeftJoycon { get; set; } - - /// - /// Right JoyCon Keyboard Bindings - /// - public Configuration.Hid.NpadKeyboardRight RightJoycon { get; set; } - - /// - /// Hotkey Keyboard Bindings - /// - public Configuration.Hid.KeyboardHotkeys Hotkeys { get; set; } - } -} diff --git a/Ryujinx.Common/Configuration/Hid/NpadKeyboardLeft.cs b/Ryujinx.Common/Configuration/Hid/NpadKeyboardLeft.cs index 4a61d93233..6b78f5b61b 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 0677b57327..e210990245 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 0000000000..2e34cb96ca --- /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 e07577eda1..c4935a6451 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(_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 ff33031276..c4c9d095e2 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 _fullBattery; + private static readonly Array3 _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 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 e59ba312d5..477e1a8404 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 2488057ed7..633671df84 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 db0319edaa..c91636b2c9 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 f65c307995..b2d34e8e26 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 29eb8d3d5e..c44193369d 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 7eaf4ac866..3ff3489bbe 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 8df901e226..c5d08f9fbc 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 28a0b60178..b8258f58a4 100644 --- a/Ryujinx/Ryujinx.csproj +++ b/Ryujinx/Ryujinx.csproj @@ -31,9 +31,10 @@ - - - + + + + @@ -41,21 +42,23 @@ - + - + + - - - + + + + @@ -63,13 +66,14 @@ - + - + + diff --git a/Ryujinx/Ui/AboutWindow.cs b/Ryujinx/Ui/AboutWindow.cs index 6a18058a5a..5f1645da5c 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 02b6541f95..2dd88196b4 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 0000000000..581c7d5613 --- /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.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.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(stream); + } + catch (ArgumentException) + { + try + { + config = JsonHelper.Deserialize(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 0000000000..2b780f13ba --- /dev/null +++ b/Ryujinx/Ui/ControllerWindow.glade @@ -0,0 +1,1732 @@ + + + + + + 1 + 0.050000000000000003 + 0.01 + 0.10000000000000001 + + + 1 + 0.050000000000000003 + 0.01 + 0.10000000000000001 + + + 1 + 0.5 + 0.01 + 0.10000000000000001 + + + False + Ryujinx - Controller Settings + True + center + 1100 + 600 + + + + + + True + False + vertical + + + True + True + in + + + True + False + + + True + False + vertical + + + True + False + 10 + 10 + 10 + + + True + False + + + True + False + 5 + Input Device + + + False + True + 0 + + + + + True + False + 0 + disabled + + Disabled + + + + + True + True + 1 + + + + + Refresh + True + True + True + 5 + + + + False + True + 2 + + + + + False + True + 0 + + + + + True + False + 20 + + + True + False + The controller's type + center + 5 + Controller Type: + + + False + True + 0 + + + + + True + False + The controller's type + 0 + + Handheld + Pro Controller + Paired Joycons + Left Joycon + Right Joycon + + + + + False + True + 1 + + + + + False + True + 1 + + + + + True + False + 20 + + + True + False + 5 + Profile: + + + False + True + 0 + + + + + True + False + 5 + 0 + default + + + False + True + 1 + + + + + Load + 60 + True + True + True + 5 + + + + False + True + 2 + + + + + Add + 60 + True + True + True + 5 + + + + False + True + 3 + + + + + Remove + 60 + True + True + True + + + + False + True + 4 + + + + + False + True + 2 + + + + + False + True + 0 + + + + + True + False + + + True + False + vertical + + + True + False + 10 + 5 + + + 156 + True + False + 10 + vertical + + + True + False + 5 + 5 + Buttons + + + + + + False + True + 0 + + + + + True + False + 3 + 10 + + + 80 + True + False + A + + + 0 + 0 + + + + + 80 + True + False + B + + + 0 + 1 + + + + + 80 + True + False + X + + + 0 + 2 + + + + + 80 + True + False + Y + + + 0 + 3 + + + + + + 70 + True + True + True + + + 1 + 0 + + + + + + 70 + True + True + True + + + 1 + 1 + + + + + + 70 + True + True + True + + + 1 + 2 + + + + + + 70 + True + True + True + + + 1 + 3 + + + + + 80 + True + False + + + + + 0 + 4 + + + + + 80 + True + False + - + + + 0 + 5 + + + + + + 70 + True + True + True + + + 1 + 5 + + + + + + 70 + True + True + True + + + 1 + 4 + + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + + + False + True + 1 + + + + + 160 + True + False + 10 + 10 + vertical + + + True + False + 5 + 5 + Left Stick + + + + + + False + True + 0 + + + + + True + False + 5 + 3 + 10 + + + 80 + True + False + LStick Button + 0 + + + 0 + 0 + + + + + + 65 + True + True + True + + + 1 + 0 + + + + + False + True + 1 + + + + + True + False + 3 + 10 + + + + 65 + True + True + True + + + 1 + 1 + + + + + + 65 + True + True + True + + + 1 + 0 + + + + + + 65 + True + True + True + + + 1 + 2 + + + + + + 65 + True + True + True + + + 1 + 3 + + + + + 80 + True + False + LStick Down + 0 + + + 0 + 1 + + + + + 80 + True + False + LStick Up + 0 + + + 0 + 0 + + + + + 80 + True + False + LStick Right + 0 + + + 0 + 3 + + + + + 80 + True + False + LStick Left + 0 + + + 0 + 2 + + + + + False + True + 2 + + + + + True + False + 3 + 10 + + + 80 + True + False + LStick Lt/Rt + 0 + + + 0 + 0 + + + + + 80 + True + False + LStick Up/Dn + 0 + + + 0 + 1 + + + + + + 65 + True + True + True + + + 1 + 0 + + + + + + 65 + True + True + True + + + 1 + 1 + + + + + Invert + True + True + False + True + + + 2 + 0 + + + + + Invert + True + True + False + True + + + 2 + 1 + + + + + False + True + 3 + + + + + True + False + 10 + vertical + + + True + False + start + Deadzone Left + + + False + True + 0 + + + + + True + True + _controllerDeadzoneLeft + 2 + 2 + + + True + True + 1 + + + + + False + True + 4 + + + + + False + True + 2 + + + + + True + False + + + False + True + 3 + + + + + 150 + True + False + 10 + 10 + vertical + + + True + False + 5 + 5 + Triggers + + + + + + False + True + 0 + + + + + True + False + 3 + 10 + + + 80 + True + False + L + + + 0 + 0 + + + + + 80 + True + False + R + + + 0 + 1 + + + + + + 65 + True + True + True + + + 1 + 0 + + + + + + 65 + True + True + True + + + 1 + 1 + + + + + 80 + True + False + ZL + + + 0 + 2 + + + + + 80 + True + False + ZR + + + 0 + 3 + + + + + + 65 + True + True + True + + + 1 + 2 + + + + + + 65 + True + True + True + + + 1 + 3 + + + + + False + True + 1 + + + + + _sideTriggerBox + True + False + 5 + 3 + 10 + + + 80 + True + False + Left SL + + + 0 + 0 + + + + + 80 + True + False + Left SR + + + 0 + 1 + + + + + + 65 + True + True + True + + + 1 + 0 + + + + + + 65 + True + True + True + + + 1 + 1 + + + + + False + True + 2 + + + + + _sideTriggerBox + True + False + 5 + 3 + 10 + + + 80 + True + False + Right SL + + + 0 + 0 + + + + + 80 + True + False + Right SR + + + 0 + 1 + + + + + + 65 + True + True + True + + + 1 + 0 + + + + + + 65 + True + True + True + + + 1 + 1 + + + + + False + True + 3 + + + + + True + False + 10 + vertical + + + True + False + start + 10 + Trigger Threshold + + + False + True + 0 + + + + + True + True + _controllerTriggerThreshold + 2 + 2 + + + True + True + 1 + + + + + False + True + 4 + + + + + False + True + 4 + + + + + False + True + 0 + + + + + True + False + 10 + + + 156 + True + False + 10 + 10 + vertical + + + True + False + 5 + 5 + Directional Pad + + + + + + False + True + 0 + + + + + True + False + 3 + 10 + + + 80 + True + False + Dpad Up + 0 + + + 0 + 0 + + + + + 80 + True + False + Dpad Down + 0 + + + 0 + 1 + + + + + 80 + True + False + Dpad Left + 0 + + + 0 + 2 + + + + + 80 + True + False + Dpad Right + 0 + + + 0 + 3 + + + + + + 70 + True + True + True + + + 1 + 0 + + + + + + 70 + True + True + True + + + 1 + 1 + + + + + + 70 + True + True + True + + + 1 + 2 + + + + + + 70 + True + True + True + + + 1 + 3 + + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + + + False + True + 1 + + + + + 160 + True + False + 10 + 10 + vertical + + + True + False + 5 + 5 + Right Stick + + + + + + False + True + 0 + + + + + True + False + 5 + 3 + 10 + + + 80 + True + False + RStick Button + 0 + + + 0 + 0 + + + + + + 65 + True + True + True + + + 1 + 0 + + + + + False + True + 1 + + + + + True + False + 3 + 10 + + + 80 + True + False + RStick Up + 0 + + + 0 + 0 + + + + + 80 + True + False + RStick Down + 0 + + + 0 + 1 + + + + + 80 + True + False + RStick Left + 0 + + + 0 + 2 + + + + + 80 + True + False + RStick Right + 0 + + + 0 + 3 + + + + + + 65 + True + True + True + + + 1 + 0 + + + + + + 65 + True + True + True + + + 1 + 1 + + + + + + 65 + True + True + True + + + 1 + 2 + + + + + + 65 + True + True + True + + + 1 + 3 + + + + + False + True + 2 + + + + + True + False + 3 + 10 + + + 80 + True + False + RStick Lt/Rt + 0 + + + 0 + 0 + + + + + 80 + True + False + RStick Up/Dn + 0 + + + 0 + 1 + + + + + + 65 + True + True + True + + + 1 + 0 + + + + + + 65 + True + True + True + + + 1 + 1 + + + + + Invert + True + True + False + True + + + 2 + 0 + + + + + Invert + True + True + False + True + + + 2 + 1 + + + + + False + True + 3 + + + + + True + False + 10 + vertical + + + True + False + start + Deadzone Right + + + False + True + 0 + + + + + True + True + _controllerDeadzoneRight + 2 + 2 + + + True + True + 1 + + + + + False + True + 4 + + + + + False + True + 2 + + + + + True + False + + + False + True + 3 + + + + + True + False + + + True + True + 4 + + + + + False + True + 1 + + + + + True + True + 0 + + + + + True + False + 10 + 20 + 5 + 5 + + + True + True + 1 + + + + + True + True + 1 + + + + + + + + + True + True + 0 + + + + + True + False + 5 + 3 + 3 + end + + + Save + True + True + True + + + + False + True + 0 + + + + + Close + True + True + True + 4 + + + + False + True + 5 + 1 + + + + + False + False + 1 + + + + + + diff --git a/Ryujinx/Ui/GLRenderer.cs b/Ryujinx/Ui/GLRenderer.cs index d266eefcde..b37ab44810 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 gamepadInputs = new List(); - 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); + + currentButton = keyboardController.GetButtons(); + + (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) + { + // Controller Input + JoystickController joystickController = new JoystickController(controllerConfig); + + currentButton |= joystickController.GetButtons(); + + (leftJoystickDx, leftJoystickDy) = joystickController.GetLeftStick(); + (rightJoystickDx, rightJoystickDy) = joystickController.GetRightStick(); + + leftJoystick = new JoystickPosition + { + Dx = controllerConfig.LeftJoycon.InvertStickX ? -leftJoystickDx : leftJoystickDx, + Dy = controllerConfig.LeftJoycon.InvertStickY ? -leftJoystickDy : leftJoystickDy + }; + + rightJoystick = new JoystickPosition + { + Dx = controllerConfig.RightJoycon.InvertStickX ? -rightJoystickDx : rightJoystickDx, + Dy = controllerConfig.RightJoycon.InvertStickY ? -rightJoystickDy : rightJoystickDy + }; } - (leftJoystickDx, leftJoystickDy) = KeyboardControls.GetLeftStick(ConfigurationState.Instance.Hid.KeyboardControls, keyboard); - (rightJoystickDx, rightJoystickDy) = KeyboardControls.GetRightStick(ConfigurationState.Instance.Hid.KeyboardControls, keyboard); - } + currentButton |= _device.Hid.UpdateStickButtons(leftJoystick, rightJoystick); - if (!hidKeyboard.HasValue) - { - hidKeyboard = new KeyboardInput + gamepadInputs.Add(new GamepadInput { - Modifier = 0, - Keys = new int[0x8] - }; + PlayerId = (HLE.HOS.Services.Hid.PlayerIndex)inputConfig.PlayerIndex, + Buttons = currentButton, + LStick = leftJoystick, + RStick = rightJoystick + }); } - currentButton |= _primaryController.GetButtons(); - - // Keyboard has priority stick-wise - if (leftJoystickDx == 0 && leftJoystickDy == 0) - { - (leftJoystickDx, leftJoystickDy) = _primaryController.GetLeftStick(); - } - - if (rightJoystickDx == 0 && rightJoystickDy == 0) - { - (rightJoystickDx, rightJoystickDy) = _primaryController.GetRightStick(); - } - - leftJoystick = new JoystickPosition - { - Dx = leftJoystickDx, - Dy = leftJoystickDy - }; - - rightJoystick = new JoystickPosition - { - Dx = rightJoystickDx, - Dy = rightJoystickDy - }; - - 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 698b8b7e2e..9a14f63d3e 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); } - internal static void CreateWarningDialog(string text, string secondaryText) + private void GtkDialog_Response(object sender, ResponseArgs args) { - CreateDialog("Ryujinx - Warning", text, secondaryText); + Dispose(); + } + + internal static void CreateInfoDialog(string title, string mainText, string 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 0000000000..f5d7450ab6 --- /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 similarity index 74% rename from Ryujinx/Ui/KeyboardControls.cs rename to Ryujinx/Ui/KeyboardController.cs index 1f19fe32e6..ed4a4b3fe9 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 eb8077e52f..756ca23173 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 bool _debuggerOpened; + + 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 b92f687cdd..0000000000 --- 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 0000000000..2b26cbef93 --- /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 0000000000..adaf6608fc --- /dev/null +++ b/Ryujinx/Ui/ProfileDialog.glade @@ -0,0 +1,124 @@ + + + + + + False + Ryujinx - Profile Dialog + True + center + 400 + dialog + + + + + + False + vertical + 2 + + + False + end + + + OK + True + True + True + + + + False + True + 0 + + + + + Cancel + True + True + True + + + + False + True + 5 + 1 + + + + + False + False + 0 + + + + + True + False + vertical + + + True + False + 10 + 10 + 20 + 10 + Enter a name for the new profile: + + + True + True + 0 + + + + + True + True + 20 + 20 + 20 + + + True + True + 1 + + + + + True + False + start + 20 + 10 + 10 + 10 + + + + + + False + True + 2 + + + + + True + True + 1 + + + + + + diff --git a/Ryujinx/Ui/SettingsWindow.cs b/Ryujinx/Ui/SettingsWindow.cs new file mode 100644 index 0000000000..1b24e72bf6 --- /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 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 gameDirs = new List(); + + _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(_systemLanguageSelect.ActiveId); + ConfigurationState.Instance.System.Region.Value = Enum.Parse(_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 similarity index 65% rename from Ryujinx/Ui/SwitchSettings.glade rename to Ryujinx/Ui/SettingsWindow.glade index 7415e76e44..ea662de09b 100644 --- a/Ryujinx/Ui/SwitchSettings.glade +++ b/Ryujinx/Ui/SettingsWindow.glade @@ -7,95 +7,21 @@ 1 10 - - 2000 - 2060 - 1 - 10 - - - 1 - 12 - 1 - 5 - - - 1 - 31 - 1 - 5 - - - 0 - 23 - 1 - 5 - - - 0 - 59 - 1 - 5 - - + False Ryujinx - Settings True center - 910 - 790 - dialog + 650 + 520 - + + True False vertical - 2 - - - False - 5 - 3 - 3 - end - - - Save - True - True - True - - - - False - True - 0 - - - - - Close - True - True - True - - - - False - True - 5 - 1 - - - - - False - False - 0 - - True @@ -142,303 +68,19 @@ - + True False + 10 + 10 vertical - - - True - False - - - True - False - Change System Language - end - System Language: - - - False - True - 0 - - - - - True - False - Change System Language - 5 - - American English - British English - Canadian French - Chinese - Dutch - French - German - Italian - Japanese - Korean - Latin American Spanish - Portuguese - Russian - Simplified Chinese - Spanish - Taiwanese - Traditional Chinese - - - - False - True - 1 - - - - - True - False - Change System Region - end - System Region: - - - False - True - 5 - 2 - - - - - True - False - Change System Region - 5 - - Japan - USA - Europe - Australia - China - Korea - Taiwan - - - - False - True - 3 - - - - - False - True - 0 - - - - - True - False - vertical - - - True - False - - - True - False - Change System TimeZone - end - System TimeZone: - - - False - True - 1 - - - - - True - False - Change System TimeZone - 5 - - - False - True - 2 - - - - - False - True - 0 - - - - - False - True - 1 - - - - - True - False - - - True - False - end - System Time: - - - False - True - 5 - 0 - - - - - True - False - 5 - vertical - _systemTimeYearSpinAdjustment - True - - - False - True - 1 - - - - - True - False - end - - - - - False - True - 5 - 2 - - - - - True - False - 0 - vertical - _systemTimeMonthSpinAdjustment - True - - - False - True - 3 - - - - - True - False - end - - - - - False - True - 5 - 4 - - - - - True - False - 0 - vertical - _systemTimeDaySpinAdjustment - True - - - False - True - 5 - - - - - True - False - 25 - vertical - _systemTimeHourSpinAdjustment - True - - - False - True - 6 - - - - - True - False - end - : - - - False - True - 5 - 7 - - - - - True - False - 0 - vertical - _systemTimeMinuteSpinAdjustment - True - - - False - True - 8 - - - - - False - True - 2 - - Enable Discord Rich Presence True True False - Enables or disables Discord Rich Presense + Enables or disables Discord Rich Presence start True @@ -446,7 +88,7 @@ False True 5 - 3 + 2 @@ -569,23 +211,6 @@ 1 - - - Browse... - 80 - True - True - True - Browse for a game directory - 5 - - - - False - True - 2 - - Remove @@ -775,6 +400,9 @@ True False + 5 + 10 + 5 vertical @@ -834,653 +462,553 @@ - + True False - 10 - 10 - 5 + center + center + 20 True False vertical - + True False - - - True - False - The primary controller's type - center - 5 - 5 - Controller Type: - - - False - True - 0 - - - - - True - False - The primary controller's type - 5 - 0 - - Handheld - Pro Controller - Paired Joycons - Left Joycon - Right Joycon - - - - True - True - 1 - - + 20 + 20 + Player 1 False True - 10 0 - + + Configure True - False - 2 - 5 - - - True - False - LStick Up - - - 0 - 0 - - - - - True - False - LStick Down - - - 0 - 1 - - - - - True - False - LStick Left - - - 0 - 2 - - - - - True - False - LStick Right - - - 0 - 3 - - - - - True - False - LStick Button - - - 0 - 4 - - - - - True - False - Dpad Up - - - 0 - 5 - - - - - True - False - Dpad Down - - - 0 - 6 - - - - - True - False - Dpad Left - - - 0 - 7 - - - - - True - False - Dpad Right - - - 0 - 8 - - - - - True - False - - - - - 0 - 9 - - - - - True - False - L - - - 0 - 10 - - - - - True - False - ZL - - - 0 - 11 - - - - - True - False - ZR - - - 2 - 11 - - - - - True - False - R - - - 2 - 10 - - - - - True - False - + - - - 2 - 9 - - - - - True - False - Y - - - 2 - 8 - - - - - True - False - X - - - 2 - 7 - - - - - True - False - B - - - 2 - 6 - - - - - True - False - A - - - 2 - 5 - - - - - True - False - RStick Button - - - 2 - 4 - - - - - True - False - RStick Right - - - 2 - 3 - - - - - True - False - RStick Left - - - 2 - 2 - - - - - True - False - RStick Down - - - 2 - 1 - - - - - True - False - RStick Up - - - 2 - 0 - - - - - - True - True - True - - - 1 - 0 - - - - - - True - True - True - - - 1 - 1 - - - - - - True - True - True - - - 1 - 2 - - - - - - True - True - True - - - 1 - 3 - - - - - - True - True - True - - - 1 - 4 - - - - - - True - True - True - - - 1 - 5 - - - - - - True - True - True - - - 1 - 6 - - - - - - True - True - True - - - 1 - 7 - - - - - - True - True - True - - - 1 - 8 - - - - - - True - True - True - - - 1 - 9 - - - - - - True - True - True - - - 1 - 10 - - - - - - True - True - True - - - 1 - 11 - - - - - - True - True - True - - - 3 - 0 - - - - - - True - True - True - - - 3 - 1 - - - - - - True - True - True - - - 3 - 2 - - - - - - True - True - True - - - 3 - 3 - - - - - - True - True - True - - - 3 - 4 - - - - - - True - True - True - - - 3 - 5 - - - - - - True - True - True - - - 3 - 6 - - - - - - True - True - True - - - 3 - 7 - - - - - - True - True - True - - - 3 - 8 - - - - - - True - True - True - - - 3 - 9 - - - - - - True - True - True - - - 3 - 10 - - - - - - True - True - True - - - 3 - 11 - - + True + True + 20 + 20 + 20 + 20 False True - 10 1 - False - True - 0 + 0 + 0 - + + True + False + vertical + + + True + False + 20 + 20 + Player 3 + + + False + True + 0 + + + + + Configure + True + True + True + 20 + 20 + 20 + 20 + + + False + True + 1 + + + + + 4 + 0 + + + + + True + False + vertical + + + True + False + 20 + 20 + Player 2 + + + False + True + 0 + + + + + Configure + True + True + True + 20 + 20 + 20 + 20 + + + False + True + 1 + + + + + 2 + 0 + + + + + True + False + vertical + + + True + False + 20 + 20 + Handheld + + + False + True + 0 + + + + + Configure + True + True + True + 20 + 20 + 20 + 20 + + + False + True + 1 + + + + + 4 + 4 + + + + + True + False + vertical + + + True + False + 20 + 20 + Player 6 + + + False + True + 0 + + + + + Configure + True + True + True + 20 + 20 + 20 + 20 + + + False + True + 1 + + + + + 4 + 2 + + + + + True + False + vertical + + + True + False + 20 + 20 + Player 5 + + + False + True + 0 + + + + + Configure + True + True + True + 20 + 20 + 20 + 20 + + + False + True + 1 + + + + + 2 + 2 + + + + + True + False + vertical + + + True + False + 20 + 20 + Player 7 + + + False + True + 0 + + + + + Configure + True + True + True + 20 + 20 + 20 + 20 + + + False + True + 1 + + + + + 0 + 4 + + + + + True + False + vertical + + + True + False + 20 + 20 + Player 4 + + + False + True + 0 + + + + + Configure + True + True + True + 20 + 20 + 20 + 20 + + + False + True + 1 + + + + + 0 + 2 + + + + + True + False + vertical + + + True + False + 20 + 20 + Player 8 + + + False + True + 0 + + + + + Configure + True + True + True + 20 + 20 + 20 + 20 + + + False + True + 1 + + + + + 2 + 4 + + + + True False - True - True - 1 + 1 + 0 + + + + + True + False + + + 3 + 0 + + + + + True + False + + + 3 + 2 + + + + + True + False + + + 3 + 4 + + + + + True + False + + + 1 + 2 + + + + + True + False + + + 1 + 4 + + + + + True + False + + + 1 + 1 + + + + + True + False + + + 1 + 3 + + + + + True + False + + + 3 + 1 + + + + + True + False + + + 3 + 3 + + + + + True + False + + + 0 + 1 + + + + + True + False + + + 2 + 1 + + + + + True + False + + + 4 + 1 + + + + + True + False + + + 0 + 3 + + + + + True + False + + + 2 + 3 + + + + + True + False + + + 4 + 3 - False + True True 2 @@ -1522,7 +1050,6 @@ True False start - 5 5 Core @@ -1542,6 +1069,299 @@ 10 10 vertical + + + True + False + + + True + False + Change System Region + end + System Region: + + + False + True + 5 + 2 + + + + + True + False + Change System Region + 5 + + Japan + USA + Europe + Australia + China + Korea + Taiwan + + + + False + True + 3 + + + + + False + True + 5 + 0 + + + + + True + False + + + True + False + Change System Language + end + System Language: + + + False + True + 5 + 0 + + + + + True + False + Change System Language + + American English + British English + Canadian French + Chinese + Dutch + French + German + Italian + Japanese + Korean + Latin American Spanish + Portuguese + Russian + Simplified Chinese + Spanish + Taiwanese + Traditional Chinese + + + + False + True + 1 + + + + + False + True + 5 + 1 + + + + + True + False + + + True + False + Change System TimeZone + end + System TimeZone: + + + False + True + 5 + 1 + + + + + True + False + Change System TimeZone + 5 + + + False + True + 2 + + + + + False + True + 5 + 2 + + + + + True + False + + + True + False + end + System Time: + + + False + True + 5 + 0 + + + + + True + True + 2000 + vertical + _systemTimeYearSpinAdjustment + True + 2000 + + + False + True + 1 + + + + + True + False + end + - + + + False + True + 5 + 2 + + + + + True + True + 1 + vertical + _systemTimeMonthSpinAdjustment + True + 1 + + + False + True + 3 + + + + + True + False + end + - + + + False + True + 5 + 4 + + + + + True + True + 1 + vertical + _systemTimeDaySpinAdjustment + True + 1 + + + False + True + 5 + + + + + True + True + 0 + vertical + _systemTimeHourSpinAdjustment + True + + + False + True + 6 + + + + + True + False + end + : + + + False + True + 5 + 7 + + + + + True + True + 0 + vertical + _systemTimeMinuteSpinAdjustment + True + + + False + True + 8 + + + + + False + True + 5 + 3 + + Enable VSync @@ -1557,7 +1377,7 @@ False True - 0 + 4 @@ -1575,7 +1395,7 @@ False True - 1 + 5 @@ -1593,53 +1413,190 @@ False True - 2 + 6 + + + True + True + 1 + + + + + False + True + 5 + 0 + + + + + True + False + 5 + 5 + + + False + True + 5 + 1 + + + + + True + False + start + 5 + 5 + vertical + + + True + False - + True False - - - True - False - Graphics Shaders Dump Path - Graphics Shaders Dump Path: - - - False - True - 5 - 0 - - - - - True - True - Graphics Shaders Dump Path - center - False - - - True - True - 1 - - + start + 5 + Hacks + + + False True - 5 - 3 + 0 + + + True + False + start + 5 + - These may cause instability + + + False + True + 1 + + + + + False + True + 1 + + + + + True + False + 10 + 10 + vertical + + + Ignore Missing Services + True + True + False + Enable or disable ignoring missing services + start + 5 + 5 + True + + + False + True + 0 + + + + + True + True + 2 + + + + + False + True + 5 + 4 + + + + + 2 + + + + + True + False + end + System + + + 2 + False + + + + + True + False + 5 + vertical + + + True + False + 5 + 5 + vertical + + + True + False + start + 5 + 5 + 5 + Enhancements + + + + + + False + True + 0 + + + + + True + False + 10 + 10 + vertical True False + 5 + 5 True @@ -1679,12 +1636,12 @@ False True 5 - 4 + 0 - True + False True 1 @@ -1701,8 +1658,6 @@ True False - 5 - 5 False @@ -1712,7 +1667,121 @@ - + + True + False + 5 + 5 + vertical + + + True + False + start + 5 + 5 + 5 + Developer Options + + + + + + False + True + 0 + + + + + True + False + 10 + 10 + vertical + + + True + False + 5 + 5 + + + True + False + Graphics Shaders Dump Path + Graphics Shaders Dump Path: + + + False + True + 5 + 0 + + + + + True + True + Graphics Shaders Dump Path + center + False + + + True + True + 1 + + + + + False + True + 5 + 0 + + + + + False + True + 1 + + + + + False + True + 5 + 4 + + + + + 3 + + + + + True + False + Graphics + + + 3 + False + + + + + True + False + 5 + 10 + 5 + vertical + + True False 5 @@ -1736,52 +1805,24 @@ - + True False + start 10 10 vertical - + + Enable Logging to File True - False - - - Enable Logging to File - True - True - False - Enables or disables logging to a file on disk - start - 5 - 5 - True - - - False - True - 0 - - - - - Open Logs Folder - True - True - True - Opens the folder where logs are written to. - 5 - 5 - 5 - - - - False - True - 1 - - + True + False + Enables or disables logging to a file on disk + start + 5 + 5 + True False @@ -1789,6 +1830,23 @@ 0 + + + Open Logs Folder + True + True + True + Opens the folder where logs are written to. + start + 10 + + + + False + True + 1 + + Enable Debug Logs @@ -1938,6 +1996,7 @@ True True Enables FS access log output to the console. Possible modes are 0-3 + 0 _fsLogSpinAdjustment @@ -1966,126 +2025,22 @@ False True 5 - 2 - - - - - True - False - 5 - 5 - - - False - True - 5 - 3 - - - - - True - False - 5 - 5 - vertical - - - True - False - - - True - False - start - 5 - Hacks - - - - - - False - True - 0 - - - - - True - False - start - 5 - - These may cause instability - - - False - True - 1 - - - - - False - True - 1 - - - - - True - False - 10 - 10 - vertical - - - Ignore Missing Services - True - True - False - Enable or disable ignoring missing services - start - 5 - 5 - True - - - False - True - 0 - - - - - True - True - 2 - - - - - False - True - 5 - 4 + 0 - 2 + 4 True False - end - System + Logging - 2 + 4 False @@ -2097,10 +2052,83 @@ True True + 0 + + + + + True + False + 5 + 3 + 3 + end + + + Save + True + True + True + + + + False + True + 0 + + + + + Close + True + True + True + 4 + + + + False + True + 5 + 1 + + + + + False + False 1 + + 1 + 31 + 1 + 5 + + + 23 + 1 + 5 + + + 59 + 1 + 5 + + + 1 + 12 + 1 + 5 + + + 2000 + 2060 + 1 + 10 + diff --git a/Ryujinx/Ui/SwitchSettings.cs b/Ryujinx/Ui/SwitchSettings.cs deleted file mode 100644 index 2843557277..0000000000 --- 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 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 gameDirs = new List(); - - _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 GdkToOpenTkInput = new Dictionary() - { - { "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 6808b4da62..06d0dcdb80 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 deleted file mode 100644 index 25691957eb..0000000000 Binary files a/Ryujinx/Ui/assets/BlueCon.png and /dev/null differ diff --git a/Ryujinx/Ui/assets/JoyCon.png b/Ryujinx/Ui/assets/JoyCon.png deleted file mode 100644 index ec74586376..0000000000 Binary files a/Ryujinx/Ui/assets/JoyCon.png and /dev/null differ diff --git a/Ryujinx/Ui/assets/JoyConLeft.svg b/Ryujinx/Ui/assets/JoyConLeft.svg new file mode 100644 index 0000000000..40d06136b1 --- /dev/null +++ b/Ryujinx/Ui/assets/JoyConLeft.svg @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ryujinx/Ui/assets/JoyConPair.svg b/Ryujinx/Ui/assets/JoyConPair.svg new file mode 100644 index 0000000000..fca94d18f6 --- /dev/null +++ b/Ryujinx/Ui/assets/JoyConPair.svg @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ryujinx/Ui/assets/JoyConRight.svg b/Ryujinx/Ui/assets/JoyConRight.svg new file mode 100644 index 0000000000..014c0ae3df --- /dev/null +++ b/Ryujinx/Ui/assets/JoyConRight.svg @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ryujinx/Ui/assets/ProCon.png b/Ryujinx/Ui/assets/ProCon.png deleted file mode 100644 index 8563622616..0000000000 Binary files a/Ryujinx/Ui/assets/ProCon.png and /dev/null differ diff --git a/Ryujinx/Ui/assets/ProCon.svg b/Ryujinx/Ui/assets/ProCon.svg new file mode 100644 index 0000000000..8c2b879fa3 --- /dev/null +++ b/Ryujinx/Ui/assets/ProCon.svg @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ryujinx/Ui/assets/RedCon.png b/Ryujinx/Ui/assets/RedCon.png deleted file mode 100644 index 6094b2e812..0000000000 Binary files a/Ryujinx/Ui/assets/RedCon.png and /dev/null differ diff --git a/Ryujinx/_schema.json b/Ryujinx/_schema.json index f075b608f9..e89e2bf7d4 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 ]