Added GUI to Ryujinx (#695)

* Added GUI to Ryujinx

* Updated to use Glade

Also added scrollbar and default dark theme

* Added support for loading icon from .nro files and cleaned up the code a bit

* Added General Settings Menu (read-only for now) and moved some functionality from MainMenu.cs to ApplicationLibrary.cs

* Added custom GUI theme support and changed the defualt theme to one I just wrote

* Added GTK to process path, fixed a bug and minor edits

* some more edits and a bug fix

* general settings menu is now fully functional. also fixed the bug where ryujinx crashes when it trys to load an invalid gamedir

* big rewrite

* aesthetic changes to General Settings menu

* Added Control Settings

one day done feature :P

* minor changes

* 1st wave of changes

* 2nd wave of changes

* 3rd wave of changes

* Cleanup settings ui

* minor edits

* new about window added, still needs styling

* added spin button for new option and tooltips to settings

* Game icons and names are now shown in the games list

* add nuget package which contains gtk dependencies

* requested changes have been changed

* put CreateGameWindow on a new thread and stopped destroying the main menu when a game loads

* fixed bug that allowed a user to attempt to load multiple games at a time which causes a crash

* Added LastPlayed and TimePlayed columns to the game list

* Did some testing and fixed some bugs

Im not happy with one of the fixes so i will do it properly an upcoming commit

* did some more bug testing and fixed another 2 bugs

* caught an exception when ryujinx tries to load non-homebrew as homebrew

* Large changes

Rewrote ApplicationLibrary.cs (added comments too) so any devs reading it wont get eye cancer, also its probably more efficient now. Added 2 new columns (Developer name and application version) to the game list and wrote the logic for it. Ryujinx now loads NRO's TitleName and TitleID from the NACP file instead of the default NPDM. I also killed a lot of bugs

* Moved Files

moved ApplicationLibrary.cs to Ryujinx.HLE as that is a better place for it. Moved contents of GUI folder to Ui folder and changed the namespaces of the gui files from Ryujinx to Ryujinx.Ui

* Added 'Open Ryujinx Folder' button to the file menu and did some small fixes

* New features

* updated nuget package with missing dlls and changed emmauss' requested changes

* fixed some minor issues

* all requested changes marked as resolved have been changed

* gdkchan's requested changes

* fixed an issue with settings window getting chopped on small res

* fixed 2 problems caused by rebase

* changed the default theme

* applied Thog's patch to fix issue on linux

* fixed issue caused by rebase

* added update check button that runs ryujinx-updater

* reads version info from installer and displays it in about menu

* changes completed

* requested changes changed

* fixed issue with default theme

* fixed a bug and completed requested changes

* added more tooltips and changed some text
This commit is contained in:
Xpl0itR 2019-09-02 17:03:57 +01:00 committed by gdkchan
parent c00c638ecc
commit edafce57be
40 changed files with 8807 additions and 319 deletions

View file

@ -1,4 +1,4 @@
using ARMeilleure;
using JsonPrettyPrinterPlus;
using LibHac.Fs;
using OpenTK.Input;
using Ryujinx.Common;
@ -7,9 +7,12 @@ using Ryujinx.HLE;
using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.HOS.Services;
using Ryujinx.HLE.Input;
using Ryujinx.UI;
using Ryujinx.UI.Input;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Utf8Json;
using Utf8Json.Resolvers;
@ -26,112 +29,132 @@ namespace Ryujinx
/// <summary>
/// Dumps shaders in this local directory
/// </summary>
public string GraphicsShadersDumpPath { get; private set; }
public string GraphicsShadersDumpPath { get; set; }
/// <summary>
/// Enables printing debug log messages
/// </summary>
public bool LoggingEnableDebug { get; private set; }
public bool LoggingEnableDebug { get; set; }
/// <summary>
/// Enables printing stub log messages
/// </summary>
public bool LoggingEnableStub { get; private set; }
public bool LoggingEnableStub { get; set; }
/// <summary>
/// Enables printing info log messages
/// </summary>
public bool LoggingEnableInfo { get; private set; }
public bool LoggingEnableInfo { get; set; }
/// <summary>
/// Enables printing warning log messages
/// </summary>
public bool LoggingEnableWarn { get; private set; }
public bool LoggingEnableWarn { get; set; }
/// <summary>
/// Enables printing error log messages
/// </summary>
public bool LoggingEnableError { get; private set; }
public bool LoggingEnableError { get; set; }
/// <summary>
/// Enables printing guest log messages
/// </summary>
public bool LoggingEnableGuest { get; private set; }
public bool LoggingEnableGuest { get; set; }
/// <summary>
/// Enables printing FS access log messages
/// </summary>
public bool LoggingEnableFsAccessLog { get; private set; }
public bool LoggingEnableFsAccessLog { get; set; }
/// <summary>
/// Controls which log messages are written to the log targets
/// </summary>
public LogClass[] LoggingFilteredClasses { get; private set; }
public LogClass[] LoggingFilteredClasses { get; set; }
/// <summary>
/// Enables or disables logging to a file on disk
/// </summary>
public bool EnableFileLog { get; private set; }
public bool EnableFileLog { get; set; }
/// <summary>
/// Change System Language
/// </summary>
public SystemLanguage SystemLanguage { get; private set; }
public SystemLanguage SystemLanguage { get; set; }
/// <summary>
/// Enables or disables Docked Mode
/// </summary>
public bool DockedMode { get; private set; }
public bool DockedMode { get; set; }
/// <summary>
/// Enables or disables Discord Rich Presence
/// </summary>
public bool EnableDiscordIntegration { get; private set; }
public bool EnableDiscordIntegration { get; set; }
/// <summary>
/// Enables or disables Vertical Sync
/// </summary>
public bool EnableVsync { get; private set; }
public bool EnableVsync { get; set; }
/// <summary>
/// Enables or disables multi-core scheduling of threads
/// </summary>
public bool EnableMulticoreScheduling { get; private set; }
public bool EnableMulticoreScheduling { get; set; }
/// <summary>
/// Enables integrity checks on Game content files
/// </summary>
public bool EnableFsIntegrityChecks { get; private set; }
public bool EnableFsIntegrityChecks { get; set; }
/// <summary>
/// Enables FS access log output to the console. Possible modes are 0-3
/// </summary>
public int FsGlobalAccessLogMode { get; private set; }
public int FsGlobalAccessLogMode { get; set; }
/// <summary>
/// Use old ChocolArm64 ARM emulator
/// </summary>
public bool EnableLegacyJit { get; private set; }
public bool EnableLegacyJit { get; set; }
/// <summary>
/// Enable or disable ignoring missing services
/// </summary>
public bool IgnoreMissingServices { get; private set; }
public bool IgnoreMissingServices { get; set; }
/// <summary>
/// The primary controller's type
/// </summary>
public ControllerStatus ControllerType { get; private set; }
public ControllerStatus ControllerType { get; set; }
/// <summary>
/// Used to toggle columns in the GUI
/// </summary>
public List<bool> GuiColumns { get; set; }
/// <summary>
/// A list of directories containing games to be used to load games into the games list
/// </summary>
public List<string> GameDirs { get; set; }
/// <summary>
/// Enable or disable custom themes in the GUI
/// </summary>
public bool EnableCustomTheme { get; set; }
/// <summary>
/// Path to custom GUI theme
/// </summary>
public string CustomThemePath { get; set; }
/// <summary>
/// Enable or disable keyboard support (Independent from controllers binding)
/// </summary>
public bool EnableKeyboard { get; private set; }
public bool EnableKeyboard { get; set; }
/// <summary>
/// Keyboard control bindings
/// </summary>
public NpadKeyboard KeyboardControls { get; private set; }
public NpadKeyboard KeyboardControls { get; set; }
/// <summary>
/// Controller control bindings
@ -161,8 +184,8 @@ namespace Ryujinx
/// <param name="path">The path to the JSON configuration file</param>
public static async Task LoadAsync(string path)
{
var resolver = CompositeResolver.Create(
new[] { new ConfigurationEnumFormatter<Key>() },
IJsonFormatterResolver resolver = CompositeResolver.Create(
new[] { new ConfigurationEnumFormatter<Key>() },
new[] { StandardResolver.AllowPrivateSnakeCase }
);
@ -172,18 +195,33 @@ namespace Ryujinx
}
}
/// <summary>
/// Save a configuration file to disk
/// </summary>
/// <param name="path">The path to the JSON configuration file</param>
public static void SaveConfig(Configuration config, string path)
{
IJsonFormatterResolver resolver = CompositeResolver.Create(
new[] { new ConfigurationEnumFormatter<Key>() },
new[] { StandardResolver.AllowPrivateSnakeCase }
);
byte[] data = JsonSerializer.Serialize(config, resolver);
File.WriteAllText(path, Encoding.UTF8.GetString(data, 0, data.Length).PrettyPrintJson());
}
/// <summary>
/// Configures a <see cref="Switch"/> instance
/// </summary>
/// <param name="device">The instance to configure</param>
public static void Configure(Switch device)
public static void InitialConfigure(Switch device)
{
if (Instance == null)
{
throw new InvalidOperationException("Configuration has not been loaded yet.");
}
GraphicsConfig.ShadersDumpPath = Instance.GraphicsShadersDumpPath;
SwitchSettings.ConfigureSettings(Instance);
Logger.AddTarget(new AsyncLogTargetWrapper(
new ConsoleLogTarget(),
@ -194,65 +232,74 @@ namespace Ryujinx
if (Instance.EnableFileLog)
{
Logger.AddTarget(new AsyncLogTargetWrapper(
new FileLogTarget(Path.Combine(Program.ApplicationDirectory, "Ryujinx.log")),
new FileLogTarget(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.log")),
1000,
AsyncLogTargetOverflowAction.Block
));
}
Logger.SetEnable(LogLevel.Debug, Instance.LoggingEnableDebug);
Logger.SetEnable(LogLevel.Stub, Instance.LoggingEnableStub);
Logger.SetEnable(LogLevel.Info, Instance.LoggingEnableInfo);
Logger.SetEnable(LogLevel.Warning, Instance.LoggingEnableWarn);
Logger.SetEnable(LogLevel.Error, Instance.LoggingEnableError);
Logger.SetEnable(LogLevel.Guest, Instance.LoggingEnableGuest);
Logger.SetEnable(LogLevel.AccessLog, Instance.LoggingEnableFsAccessLog);
Configure(device, Instance);
}
if (Instance.LoggingFilteredClasses.Length > 0)
public static void Configure(Switch device, Configuration SwitchConfig)
{
GraphicsConfig.ShadersDumpPath = SwitchConfig.GraphicsShadersDumpPath;
Logger.SetEnable(LogLevel.Debug, SwitchConfig.LoggingEnableDebug );
Logger.SetEnable(LogLevel.Stub, SwitchConfig.LoggingEnableStub );
Logger.SetEnable(LogLevel.Info, SwitchConfig.LoggingEnableInfo );
Logger.SetEnable(LogLevel.Warning, SwitchConfig.LoggingEnableWarn );
Logger.SetEnable(LogLevel.Error, SwitchConfig.LoggingEnableError );
Logger.SetEnable(LogLevel.Guest, SwitchConfig.LoggingEnableGuest );
Logger.SetEnable(LogLevel.AccessLog, SwitchConfig.LoggingEnableFsAccessLog);
if (SwitchConfig.LoggingFilteredClasses.Length > 0)
{
foreach (var logClass in EnumExtensions.GetValues<LogClass>())
{
Logger.SetEnable(logClass, false);
}
foreach (var logClass in Instance.LoggingFilteredClasses)
foreach (var logClass in SwitchConfig.LoggingFilteredClasses)
{
Logger.SetEnable(logClass, true);
}
}
device.System.State.DiscordIntegrationEnabled = Instance.EnableDiscordIntegration;
MainWindow.DiscordIntegrationEnabled = SwitchConfig.EnableDiscordIntegration;
device.EnableDeviceVsync = Instance.EnableVsync;
device.EnableDeviceVsync = SwitchConfig.EnableVsync;
device.System.State.DockedMode = Instance.DockedMode;
device.System.State.DockedMode = SwitchConfig.DockedMode;
device.System.State.SetLanguage(Instance.SystemLanguage);
device.System.State.SetLanguage(SwitchConfig.SystemLanguage);
if (Instance.EnableMulticoreScheduling)
if (SwitchConfig.EnableMulticoreScheduling)
{
device.System.EnableMultiCoreScheduling();
}
device.System.FsIntegrityCheckLevel = Instance.EnableFsIntegrityChecks
device.System.FsIntegrityCheckLevel = SwitchConfig.EnableFsIntegrityChecks
? IntegrityCheckLevel.ErrorOnInvalid
: IntegrityCheckLevel.None;
device.System.GlobalAccessLogMode = Instance.FsGlobalAccessLogMode;
device.System.GlobalAccessLogMode = SwitchConfig.FsGlobalAccessLogMode;
device.System.UseLegacyJit = Instance.EnableLegacyJit;
device.System.UseLegacyJit = SwitchConfig.EnableLegacyJit;
ServiceConfiguration.IgnoreMissingServices = Instance.IgnoreMissingServices;
if (Instance.JoystickControls.Enabled)
ServiceConfiguration.IgnoreMissingServices = SwitchConfig.IgnoreMissingServices;
}
public static void ConfigureHid(Switch device, Configuration SwitchConfig)
{
if (SwitchConfig.JoystickControls.Enabled)
{
if (!Joystick.GetState(Instance.JoystickControls.Index).IsConnected)
if (!Joystick.GetState(SwitchConfig.JoystickControls.Index).IsConnected)
{
Instance.JoystickControls.SetEnabled(false);
SwitchConfig.JoystickControls.SetEnabled(false);
}
}
device.Hid.InitializePrimaryController(Instance.ControllerType);
device.Hid.InitializePrimaryController(SwitchConfig.ControllerType);
device.Hid.InitializeKeyboard();
}