added base UI

This commit is contained in:
emmaus 2018-04-19 18:21:16 +00:00
parent 81e74ebd86
commit c4c0ad5837
58 changed files with 3477 additions and 57 deletions

1
.gitignore vendored
View file

@ -121,6 +121,7 @@ ClientBin/
*.publishsettings
packages/*
*.config
*.glide~
# RIA/Silverlight projects
Generated_Code/

View file

@ -20,5 +20,7 @@ namespace Ryujinx.Audio
void Stop(int Track);
PlaybackState GetState(int Track);
void Close();
}
}

View file

@ -360,6 +360,10 @@ namespace Ryujinx.Audio.OpenAL
return PlaybackState.Stopped;
}
public void Close()
{
KeepPolling = false;
Context.Dispose();
}
}
}

View file

@ -1,4 +1,7 @@
//TODO: This is only used by Config, it doesn't belong to Core.
using System.ComponentModel;
using Newtonsoft.Json;
using OpenTK.Input;
namespace Ryujinx.Core.Input
{
public struct JoyConLeft

View file

@ -43,6 +43,16 @@ namespace Ryujinx.Core.Logging
EnabledClasses[(int)Class] = Enabled;
}
public bool IsEnabled(LogLevel Level)
{
return EnabledLevels[(int)Level];
}
public bool IsEnabled(LogClass Class)
{
return EnabledClasses[(int)Class];
}
internal void PrintDebug(LogClass Class, string Message, [CallerMemberName] string Caller = "")
{
Print(LogLevel.Debug, Class, GetFormattedMessage(Class, Message, Caller));

View file

@ -167,6 +167,19 @@ namespace Ryujinx.Core.OsHle
}
}
public void ShutDown()
{
foreach(var Process in Processes)
{
Process.Value.StopAllThreadsAsync();
Process.Value.Dispose();
}
Processes.Clear();
Ns.OnFinish(EventArgs.Empty);
Ns.Gpu.Close();
Ns.AudioOut.Close();
}
internal bool TryGetProcess(int ProcessId, out Process Process)
{
return Processes.TryGetValue(ProcessId, out Process);

View file

@ -12,6 +12,10 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ChocolArm64\ChocolArm64.csproj" />
<ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" />

View file

@ -70,5 +70,10 @@ namespace Ryujinx.Graphics.Gpu
Thread.Yield();
}
}
public void Close()
{
KeepRunning = false;
}
}
}

View file

@ -0,0 +1,25 @@
using Ryujinx.Core.Input;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Ryujinx.Core.Logging;
namespace Ryujinx.UI
{
public class Configuration
{
public bool EnableMemoryChecks { get; set; }
public bool LoggingEnableInfo { get; set; }
public bool LoggingEnableDebug { get; set; }
public bool LoggingEnableWarn { get; set; }
public bool LoggingEnableError { get; set; }
public bool LoggingEnableStub { get; set; }
public string LoggingFilteredClasses { get; set; }
public JoyCon EmulatedJoyCon { get; set; }
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Ryujinx.Graphics.Gal;
namespace Ryujinx.Core
{
public class EmutionController
{
private Thread EmulationThread;
private Switch Ns;
private IGalRenderer Renderer;
private bool IsPaused = false;
public EmutionController(Switch Ns, IGalRenderer Renderer)
{
this.Ns = Ns;
this.Renderer = Renderer;
}
public void Start()
{
EmulationThread = new Thread(new ThreadStart(() =>
{
using (GLScreen Screen = new GLScreen(Ns, Renderer))
{
Ns.Finish += (Sender, Args) =>
{
Screen?.Exit();
};
Screen.Closed += (Sender, Args) =>
{
Stop();
};
Screen.Run(60.0);
}
}));
EmulationThread.Start();
}
public void Stop()
{
IsPaused = false;
Ns.Os.ShutDown();
}
public async void Pause()
{
IsPaused = true;
lock (Ns)
{
while (IsPaused)
{
Thread.Sleep(1000);
}
}
}
public void Continue()
{
IsPaused = false;
}
}
}

237
Ryujinx.UI/MainWindow.cs Normal file
View file

@ -0,0 +1,237 @@
using System;
using System.Threading.Tasks;
using Gtk;
using GUI = Gtk.Builder.ObjectAttribute;
using Ryujinx.Audio;
using Ryujinx.Audio.OpenAL;
using Ryujinx.Core;
using System.Threading;
using Ryujinx.Graphics.Gal;
using Ryujinx.Graphics.Gal.OpenGL;
using System.IO;
using System.Reflection;
using Ryujinx.Core.Logging;
namespace Ryujinx.UI
{
class MainWindow : Window
{
//UI Controls
[GUI] MenuItem LoadFileMenuItem;
[GUI] MenuItem LoadFolderMenuItem;
[GUI] MenuItem ExitMenuItem;
[GUI] MenuItem OptionMenuItem;
[GUI] MenuItem ShowDebugMenuItem;
[GUI] MenuItem ContinueMenuItem;
[GUI] MenuItem PauseMenuItem;
[GUI] MenuItem StopMenuItem;
[GUI] MenuItem AboutMenuItem;
bool DebugWindowActive = false;
Core.Switch Ns;
IAalOutput AudioOut = new OpenALAudioOut();
IGalRenderer Renderer;
EmutionController EmulationController;
public MainWindow() : this(new Builder("MainWindow.glade")) { }
private MainWindow(Builder builder) : base(builder.GetObject("MainWindow").Handle)
{
builder.Autoconnect(this);
//Load Icon
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Ryujinx.UI.ryujinxicon.png"))
using (StreamReader reader = new StreamReader(stream))
{
Icon = new Gdk.Pixbuf(stream);
}
InitializeSwitch();
//Register Events
DeleteEvent += Window_DeleteEvent;
LoadFileMenuItem.Activated += LoadFileMenuItem_Activated;
LoadFolderMenuItem.Activated += LoadFolderMenuItem_Activated;
ExitMenuItem.Activated += ExitMenuItem_Activated;
OptionMenuItem.Activated += OptionMenuItem_Activated;
ShowDebugMenuItem.Activated += ShowDebugMenuItem_Activated;
ContinueMenuItem.Activated += ContinueMenuItem_Activated;
PauseMenuItem.Activated += PauseMenuItem_Activated;
StopMenuItem.Activated += StopMenuItem_Activated;
AboutMenuItem.Activated += AboutMenuItem_Activated;
PauseMenuItem.Sensitive = false;
ContinueMenuItem.Sensitive = false;
StopMenuItem.Sensitive = false;
//Initialize Ryujinx
Console.Title = "Ryujinx Console";
}
private void AboutMenuItem_Activated(object sender, EventArgs e)
{
AboutDialog AboutDialog = new AboutDialog
{
Title = "Ryujinx",
Logo = Icon,
Comments = "This is a free switch emulator",
Copyright = "2018 - Ryujinx Team"
};
AboutDialog.Run();
AboutDialog.Destroy();
}
private void LoadFolderMenuItem_Activated(object sender, EventArgs e)
{
FileChooserDialog ContentLoader = new FileChooserDialog("Open Game Folder", this, FileChooserAction.SelectFolder,
"Cancel", Gtk.ResponseType.Cancel,
"Open", Gtk.ResponseType.Accept
);
if (ContentLoader.Run() == (int)Gtk.ResponseType.Accept)
{
if (Directory.Exists(ContentLoader.Filename))
{
InitializeSwitch();
string FolderName = ContentLoader.Filename;
ContentLoader.Destroy();
string[] RomFsFiles = Directory.GetFiles(FolderName, "*.istorage");
if (RomFsFiles.Length == 0)
{
RomFsFiles = Directory.GetFiles(FolderName, "*.romfs");
}
if (RomFsFiles.Length > 0)
{
Console.WriteLine("Loading as cart with RomFS.");
Ns.LoadCart(FolderName, RomFsFiles[0]);
}
else
{
Console.WriteLine("Loading as cart WITHOUT RomFS.");
Ns.LoadCart(FolderName);
}
Start();
}
}
else
ContentLoader.Destroy();
}
void InitializeSwitch()
{
Renderer = new OpenGLRenderer();
IAalOutput AudioOut = new OpenALAudioOut();
Ns = new Core.Switch(Renderer, AudioOut);
Settings.Read(Ns.Log);
}
private void StopMenuItem_Activated(object sender, EventArgs e)
{
EmulationController?.Stop();
PauseMenuItem.Sensitive = false;
ContinueMenuItem.Sensitive = false;
StopMenuItem.Sensitive = false;
EmulationController = null;
}
private void PauseMenuItem_Activated(object sender, EventArgs e)
{
new Thread(()=>EmulationController?.Pause()).Start();
PauseMenuItem.Sensitive = false;
ContinueMenuItem.Sensitive = true;
StopMenuItem.Sensitive = true;
}
private void ContinueMenuItem_Activated(object sender, EventArgs e)
{
EmulationController?.Continue();
PauseMenuItem.Sensitive = true;
ContinueMenuItem.Sensitive = false;
StopMenuItem.Sensitive = true;
}
private void ShowDebugMenuItem_Activated(object sender, EventArgs e)
{
UI.Debugging.Debugger debugger = new UI.Debugging.Debugger();
debugger.DeleteEvent += Debugger_DeleteEvent;
DebugWindowActive = true;
debugger.Show();
}
private void Debugger_DeleteEvent(object o, DeleteEventArgs args)
{
DebugWindowActive = false;
}
private void OptionMenuItem_Activated(object sender, EventArgs e)
{
UI.ConfigurationWindow configurationWindow = new UI.ConfigurationWindow(Ns.Log);
if (configurationWindow.Run() == (int)ResponseType.Accept)
{
Settings.Write(Ns.Log);
}
else
Settings.Read(Ns.Log);
configurationWindow.Destroy();
}
private void ExitMenuItem_Activated(object sender, EventArgs e)
{
Environment.Exit(0);
}
private void LoadFileMenuItem_Activated(object sender, EventArgs e)
{
FileChooserDialog ContentLoader = new FileChooserDialog("Open Package", this, FileChooserAction.Open,
"Cancel", Gtk.ResponseType.Cancel,
"Open", Gtk.ResponseType.Accept
);
if (ContentLoader.Run() == (int)Gtk.ResponseType.Accept)
{
if (File.Exists(ContentLoader.Filename))
{
InitializeSwitch();
Ns.LoadProgram(ContentLoader.Filename);
ContentLoader.Destroy();
Start();
}
}
else
ContentLoader.Destroy();
}
private void Window_DeleteEvent(object sender, DeleteEventArgs a)
{
EmulationController?.Stop();
Environment.Exit(0);
}
void Start()
{
EmulationController = new EmutionController(Ns, Renderer);
EmulationController.Start();
PauseMenuItem.Sensitive = true;
ContinueMenuItem.Sensitive = false;
StopMenuItem.Sensitive = true;
}
}
}

35
Ryujinx.UI/Program.cs Normal file
View file

@ -0,0 +1,35 @@
using Gtk;
using System;
using System.Reflection;
using System.Linq;
using Ryujinx.Core;
using Ryujinx.Core.Logging;
namespace Ryujinx.UI
{
class Program
{
[STAThread]
public static void Main(string[] args)
{
Application.Init();
Console.Title = "Ryujinx Console";
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
AppDomain.CurrentDomain.AppendPrivatePath(@"Dependencies\");
Console.SetOut(UI.Debugging.LogPage.LogWriter);
var resourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();
var app = new Application("org.Ryujinx.UI.Ryujinx.UI", GLib.ApplicationFlags.None);
app.Register(GLib.Cancellable.Current);
var win = new MainWindow();
app.AddWindow(win);
win.Show();
Application.Run();
}
}
}

View file

@ -0,0 +1,131 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<None Remove="**\*.glade" />
<EmbeddedResource Include="**\*.glade">
<LogicalName>%(Filename)%(Extension)</LogicalName>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Remove="ryujinxicon.png" />
<None Remove="UI\style.css" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="ryujinxicon.png" />
<EmbeddedResource Include="UI\style.css">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<PackageReference Include="GtkSharp" Version="3.22.24.36" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="OpenTK.NETCore" Version="1.1.2749.6433" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ChocolArm64\ChocolArm64.csproj" />
<ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" />
<ProjectReference Include="..\Ryujinx.Core\Ryujinx.Core.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics\Ryujinx.Graphics.csproj" />
<ProjectReference Include="..\Ryujinx\Ryujinx.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="UI\GeneralPage.glade">
<LogicalName>%(Filename)%(Extension)</LogicalName>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Update="Dependencies\libbz2-1.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libcairo-2.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libepoxy-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libexpat-1.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libffi-6.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libfontconfig-1.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libfreetype-6.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libgcc_s_seh-1.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libgdk-3-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libgdk_pixbuf-2.0-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libglib-2.0-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libgobject-2.0-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libgraphite2.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libgthread-2.0-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libgtk-3-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libharfbuzz-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libiconv-2.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libintl-8.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libpango-1.0-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libpangocairo-1.0-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libpangoft2-1.0-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libpangowin32-1.0-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libpcre32-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libpixman-1-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libpng16-16.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libstdc++-6.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Dependencies\libwinpthread-1.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

164
Ryujinx.UI/Settings.cs Normal file
View file

@ -0,0 +1,164 @@
using System;
using System.Reflection;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Ryujinx.Core;
using Ryujinx.Core.Input;
using Newtonsoft.Json;
using Ryujinx.Core.Logging;
namespace Ryujinx.UI
{
public static class Settings
{
private static string ConfigPath;
static Settings()
{
var IniFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
ConfigPath = Path.Combine(IniFolder, "RyujinxUI.json");
}
public static void Read(Logger Log)
{
JsonParser JsonParser = new JsonParser(ConfigPath);
var Configuration = JsonParser.Load();
Config.FakeJoyCon = Configuration.EmulatedJoyCon;
AOptimizations.DisableMemoryChecks = !Configuration.EnableMemoryChecks;
Log.SetEnable(LogLevel.Info, Configuration.LoggingEnableInfo);
Log.SetEnable(LogLevel.Debug, Configuration.LoggingEnableDebug);
Log.SetEnable(LogLevel.Error, Configuration.LoggingEnableError);
Log.SetEnable(LogLevel.Warning, Configuration.LoggingEnableWarn);
Log.SetEnable(LogLevel.Stub, Configuration.LoggingEnableStub);
Configuration.LoggingFilteredClasses = Configuration.LoggingFilteredClasses != null ?
Configuration.LoggingFilteredClasses : string.Empty;
string[] FilteredLogClasses = Configuration.LoggingFilteredClasses.Split('\n');
//When the classes are specified on the list, we only
//enable the classes that are on the list.
//So, first disable everything, then enable
//the classes that the user added to the list.
if (FilteredLogClasses.Length > 0)
{
foreach (LogClass Class in Enum.GetValues(typeof(LogClass)))
{
Log.SetEnable(Class, false);
}
}
foreach (string LogClass in FilteredLogClasses)
{
if (!string.IsNullOrEmpty(LogClass.Trim()))
{
foreach (LogClass Class in Enum.GetValues(typeof(LogClass)))
{
if (Class.ToString().ToLower().Contains(LogClass.Trim().ToLower()))
{
Log.SetEnable(Class, true);
}
}
}
}
}
public static void Write(Logger Logger)
{
Configuration Configuration = new Configuration
{
EmulatedJoyCon = Config.FakeJoyCon,
EnableMemoryChecks = !AOptimizations.DisableMemoryChecks,
LoggingEnableDebug = (bool)Logger?.IsEnabled(LogLevel.Debug),
LoggingEnableInfo = (bool)Logger?.IsEnabled(LogLevel.Info),
LoggingEnableWarn = (bool)Logger?.IsEnabled(LogLevel.Warning),
LoggingEnableError = (bool)Logger?.IsEnabled(LogLevel.Error),
LoggingEnableStub = (bool)Logger?.IsEnabled(LogLevel.Stub)
};
lock (ConfigPath)
{
JsonParser JsonParser = new JsonParser(ConfigPath);
JsonParser.Save(Configuration);
}
}
public static void LoadDefault()
{
Configuration configuration = new Configuration();
Config.FakeJoyCon = new JoyCon();
var Joycon = configuration.EmulatedJoyCon;
Joycon.Left.StickUp = (int)OpenTK.Input.Key.W;
Joycon.Left.StickDown = (int)OpenTK.Input.Key.S;
Joycon.Left.StickLeft = (int)OpenTK.Input.Key.A;
Joycon.Left.StickRight = (int)OpenTK.Input.Key.D;
Joycon.Left.StickButton = (int)OpenTK.Input.Key.F;
Joycon.Left.DPadUp = (int)OpenTK.Input.Key.Up;
Joycon.Left.DPadDown = (int)OpenTK.Input.Key.Down;
Joycon.Left.DPadLeft = (int)OpenTK.Input.Key.Left;
Joycon.Left.DPadRight = (int)OpenTK.Input.Key.Right;
Joycon.Left.ButtonMinus = (int)OpenTK.Input.Key.Minus;
Joycon.Left.ButtonL = (int)OpenTK.Input.Key.E;
Joycon.Left.ButtonZL = (int)OpenTK.Input.Key.Q;
Joycon.Right.StickUp = (int)OpenTK.Input.Key.I;
Joycon.Right.StickDown = (int)OpenTK.Input.Key.K;
Joycon.Right.StickLeft = (int)OpenTK.Input.Key.J;
Joycon.Right.StickRight = (int)OpenTK.Input.Key.L;
Joycon.Right.StickButton = (int)OpenTK.Input.Key.H;
Joycon.Right.ButtonA = (int)OpenTK.Input.Key.Z;
Joycon.Right.ButtonB = (int)OpenTK.Input.Key.X;
Joycon.Right.ButtonX = (int)OpenTK.Input.Key.C;
Joycon.Right.ButtonY = (int)OpenTK.Input.Key.V;
Joycon.Right.ButtonPlus = (int)OpenTK.Input.Key.Plus;
Joycon.Right.ButtonR = (int)OpenTK.Input.Key.U;
Joycon.Right.ButtonZR = (int)OpenTK.Input.Key.O;
Config.FakeJoyCon = Joycon;
Write(null);
}
}
public class JsonParser
{
private string ConfigPath;
public JsonParser(string Path)
{
ConfigPath = Path;
if (!File.Exists(ConfigPath))
{
File.CreateText(ConfigPath).Close();
Settings.LoadDefault();
}
}
private string Serialize<T>(T obj)
{
return JsonConvert.SerializeObject(obj, typeof(T),Formatting.Indented ,null);
}
private T Deserialize<T>(string serialized_string)
{
return (T)JsonConvert.DeserializeObject<T>(serialized_string);
}
public void Save(Configuration Configuration)
{
string SerializeText = Serialize(Configuration);
File.WriteAllText(ConfigPath, SerializeText);
}
public Configuration Load()
{
if (!File.Exists(ConfigPath))
File.Create(ConfigPath).Close();
string Config = File.ReadAllText(ConfigPath);
return Deserialize<Configuration>(Config);
}
}
}

View file

@ -0,0 +1,56 @@
using Gtk;
using System;
using System.Reflection;
using Ryujinx.Core.Logging;
using GUI = Gtk.Builder.ObjectAttribute;
namespace Ryujinx.UI.UI
{
public class ConfigurationWindow : Dialog
{
Logger Log;
[GUI] Notebook OptionNotebook;
[GUI] Button OptionAcceptButton;
[GUI] Button OptionCancelButton;
public ConfigurationWindow(Logger Log) : this(new Builder("ConfigurationWindow.glade"))
{
this.Log = Log;
}
private ConfigurationWindow(Builder builder) : base(builder.GetObject("ConfigurationWindow").Handle)
{
builder.Autoconnect(this);
//Saves current configuration
Settings.Write(Log);
//Loads Parser
var iniFolder = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
var iniPath = System.IO.Path.Combine(iniFolder, "Ryujinx.conf");
//Add pages
Label GeneralLabel = new Label("General");
GeneralPage GeneralPage = new GeneralPage();
OptionNotebook.AppendPage(GeneralPage.GetWidget(), GeneralLabel);
Label InputLabel = new Label("Input");
InputPage InputPage = new InputPage();
OptionNotebook.AppendPage(InputPage.GetWidget(), InputLabel);
//Register Events
OptionAcceptButton.Clicked += OptionAcceptButton_Clicked;
OptionCancelButton.Clicked += OptionCancelButton_Clicked;
}
private void OptionCancelButton_Clicked(object sender, EventArgs e)
{
this.Respond(ResponseType.Cancel);
}
private void OptionAcceptButton_Clicked(object sender, EventArgs e)
{
this.Respond(ResponseType.Accept);
}
}
}

View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.21.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkDialog" id="ConfigurationWindow">
<property name="width_request">-1</property>
<property name="height_request">-1</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">Configuration</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="OptionAcceptButton">
<property name="label" translatable="yes">OK</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="OptionCancelButton">
<property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkNotebook" id="OptionNotebook">
<property name="width_request">-1</property>
<property name="height_request">-1</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child>
<placeholder/>
</child>
</object>
</interface>

View file

@ -0,0 +1,25 @@
using Gtk;
using System;
using System.Reflection;
using GUI = Gtk.Builder.ObjectAttribute;
namespace Ryujinx.UI.UI.Debugging
{
public class Debugger : Gtk.Window
{
[GUI] Notebook DebuggerNotebook;
public Debugger() : this(new Builder("Debugger.glade")) { }
public Debugger(Builder builder) : base(builder.GetObject("Debugger").Handle)
{
builder.Autoconnect(this);
//Add Pages
Label LogLabel = new Label("Log");
LogPage LogPage = new LogPage();
DebuggerNotebook.AppendPage(LogPage.Widget, LogLabel);
}
}
}

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.21.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="Debugger">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Debugger</property>
<child>
<object class="GtkNotebook" id="DebuggerNotebook">
<property name="height_request">500</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
</child>
<child type="titlebar">
<placeholder/>
</child>
</object>
</interface>

View file

@ -0,0 +1,200 @@
using Gtk;
using System;
using System.IO;
using System.Reflection;
using System.Text;
using Ryujinx.Core.Logging;
using GUI = Gtk.Builder.ObjectAttribute;
namespace Ryujinx.UI.UI.Debugging
{
public class LogPage : Box
{
Logger Log;
public static LogWriter LogWriter = new LogWriter();
Builder builder = new Builder("LogPage.glade");
Box LogBox;
//UI elements
[GUI] Button SaveButton;
[GUI] TextView LogTextView;
[GUI] TextView LogClassesBox;
[GUI] CheckButton InfoLogEnable;
[GUI] CheckButton DebugLogEnable;
[GUI] CheckButton ErrorLogEnable;
[GUI] CheckButton StubLogEnable;
[GUI] CheckButton WarnLogEnable;
public LogPage() : base(Orientation.Horizontal, 0)
{
//Load styles
CssProvider provider = new CssProvider();
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Ryujinx.UI.UI.style.css"))
using (StreamReader reader = new StreamReader(stream))
{
provider.LoadFromData(reader.ReadToEnd());
}
builder.Autoconnect(this);
LogBox = (Box)builder.GetObject("MainBox");
//Style the log text box
LogTextView.StyleContext.AddProvider(provider,1000);
//Register Events
InfoLogEnable.Toggled += InfoLogEnable_Toggled;
DebugLogEnable.Toggled += DebugLogEnable_Toggled;
ErrorLogEnable.Toggled += ErrorLogEnable_Toggled;
WarnLogEnable.Toggled += WarnLogEnable_Toggled;
StubLogEnable.Toggled += StubLogEnable_Toggled;
SaveButton.Clicked += SaveButton_Clicked;
LogClassesBox.Buffer.InsertText += Buffer_InsertText;
//Set values
LogTextView.Buffer = LogWriter.LogBuffer;
}
private void SaveButton_Clicked(object sender, EventArgs e)
{
if (Log != null)
Settings.Write(Log);
}
public void UpdateSettings(Logger Log)
{
this.Log = Log;
InfoLogEnable.Active = Log.IsEnabled(LogLevel.Info);
DebugLogEnable.Active = Log.IsEnabled(LogLevel.Debug);
ErrorLogEnable.Active = Log.IsEnabled(LogLevel.Error);
WarnLogEnable.Active = Log.IsEnabled(LogLevel.Warning);
StubLogEnable.Active = Log.IsEnabled(LogLevel.Stub);
string EnabledClasses = string.Empty;
foreach(var logClass in Enum.GetNames(typeof(LogClass)))
{
if (Log.IsEnabled(Enum.Parse<LogClass>(logClass)))
EnabledClasses += logClass + Environment.NewLine;
}
LogClassesBox.Buffer.Text = EnabledClasses;
}
private void Buffer_InsertText(object o, InsertTextArgs args)
{
string[] FilteredLogClasses = LogClassesBox.Buffer.Text.Split('\n');
if (FilteredLogClasses.Length > 0)
{
foreach (LogClass Class in Enum.GetValues(typeof(LogClass)))
{
Log.SetEnable(Class, false);
}
}
foreach (string LogClass in FilteredLogClasses)
{
if (!string.IsNullOrEmpty(LogClass.Trim()))
{
foreach (LogClass Class in Enum.GetValues(typeof(LogClass)))
{
if (Class.ToString().ToLower().Contains(LogClass.Trim().ToLower()))
{
Log.SetEnable(Class, true);
}
}
}
}
}
private void StubLogEnable_Toggled(object sender, EventArgs e)
{
if (sender is CheckButton LogCheckButton)
{
Log.SetEnable(LogLevel.Stub,LogCheckButton.Active);
}
}
private void WarnLogEnable_Toggled(object sender, EventArgs e)
{
if (sender is CheckButton LogCheckButton)
{
Log.SetEnable(LogLevel.Warning, LogCheckButton.Active);
}
}
private void ErrorLogEnable_Toggled(object sender, EventArgs e)
{
if (sender is CheckButton LogCheckButton)
{
Log.SetEnable(LogLevel.Error, LogCheckButton.Active);
}
}
private void DebugLogEnable_Toggled(object sender, EventArgs e)
{
if (sender is CheckButton LogCheckButton)
{
Log.SetEnable(LogLevel.Debug, LogCheckButton.Active);
}
}
private void InfoLogEnable_Toggled(object sender, EventArgs e)
{
if (sender is CheckButton LogCheckButton)
{
Log.SetEnable(LogLevel.Info, LogCheckButton.Active);
}
}
public Widget Widget
{
get => LogBox;
}
}
public class LogWriter : TextWriter
{
public override Encoding Encoding => Encoding.UTF8;
public TextBuffer LogBuffer { get; private set; }
private TextIter EndIter;
public LogWriter()
{
LogBuffer = new TextBuffer(null);
EndIter = LogBuffer.EndIter;
//Add color tags
LogBuffer.TagTable.Add(new TextTag("Red") { Foreground = "red" });
LogBuffer.TagTable.Add(new TextTag("Gray") { Foreground = "grey" });
LogBuffer.TagTable.Add(new TextTag("Yellow") { Foreground = "yellow" });
LogBuffer.TagTable.Add(new TextTag("Magenta") { Foreground = "magenta" });
LogBuffer.TagTable.Add(new TextTag("White") { Foreground = "white" });
LogBuffer.TagTable.Add(new TextTag("DarkYellow") { Foreground = "orange" });
LogBuffer.TagTable.Add(new TextTag("DarkGray") { Foreground = "darkgray" });
}
public override void Write(string value)
{
string consoleColor = Console.ForegroundColor.ToString();
Gtk.Application.Invoke(delegate
{
LogBuffer.InsertWithTagsByName(ref EndIter, value, consoleColor);
});
}
public override void WriteLine(string value)
{
string consoleColor = Console.ForegroundColor.ToString();
Gtk.Application.Invoke(delegate
{
LogBuffer.InsertWithTagsByName(ref EndIter, value + Environment.NewLine, consoleColor);
});
}
}
}

View file

@ -0,0 +1,254 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.21.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkBox" id="MainBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkScrolledWindow">
<property name="width_request">400</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<property name="shadow_type">in</property>
<property name="propagate_natural_width">True</property>
<property name="propagate_natural_height">True</property>
<child>
<object class="GtkTextView" id="LogTextView">
<property name="width_request">400</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="wrap_mode">word</property>
<style>
<class name="log_text_box"/>
</style>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="width_request">200</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="margin_bottom">5</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkFrame" id="LogLevelFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">5</property>
<property name="margin_right">10</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">20</property>
<property name="margin_bottom">5</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkCheckButton" id="InfoLogEnable">
<property name="label" translatable="yes">Info</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="DebugLogEnable">
<property name="label" translatable="yes">Debug</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="ErrorLogEnable">
<property name="label" translatable="yes">Error</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="TraceLogEnable">
<property name="label" translatable="yes">Trace</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="FatalLogEnable">
<property name="label" translatable="yes">Fatal</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="StubLogEnable">
<property name="label" translatable="yes">Stub</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="WarnLogEnable">
<property name="label" translatable="yes">Warn</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Log Levels</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">5</property>
<property name="margin_right">10</property>
<property name="hexpand">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="margin_right">5</property>
<property name="margin_bottom">5</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTextView" id="LogClassesBox">
<property name="width_request">200</property>
<property name="height_request">300</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Log Classes</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="SaveButton">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</interface>

View file

@ -0,0 +1,36 @@
using Gtk;
using System;
using GUI = Gtk.Builder.ObjectAttribute;
namespace Ryujinx.UI.UI
{
public class GeneralPage : Alignment
{
Alignment Alignment;
[GUI] CheckButton MemoryChecksToggle;
Builder builder = new Builder("GeneralPage.glade");
public GeneralPage(): base(0.5f, 0.5f, 1, 1)
{
builder.Autoconnect(this);
Alignment = (Alignment)builder.GetObject("GeneralLayout");
MemoryChecksToggle.Toggled += MemoryChecksToggle_Toggled;
MemoryChecksToggle.Active = !AOptimizations.DisableMemoryChecks;
}
private void MemoryChecksToggle_Toggled(object sender, EventArgs e)
{
AOptimizations.DisableMemoryChecks = !MemoryChecksToggle.Active;
}
public Widget GetWidget()
{
return Alignment;
}
}
}

View file

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.21.0 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkAlignment" id="GeneralLayout">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">10</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">10</property>
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkCheckButton" id="MemoryChecksToggle">
<property name="label" translatable="yes">Enable Memory Checks</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">CPU</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

495
Ryujinx.UI/UI/InputPage.cs Normal file
View file

@ -0,0 +1,495 @@
using Gtk;
using Ryujinx.Core;
using System;
using System.Threading.Tasks;
using System.Globalization;
using GUI = Gtk.Builder.ObjectAttribute;
namespace Ryujinx.UI.UI
{
public class InputPage : Notebook
{
Notebook Notebook;
//Buttons
[GUI] Button LeftAnalogUp;
[GUI] Button LeftAnalogDown;
[GUI] Button LeftAnalogLeft;
[GUI] Button LeftAnalogRight;
[GUI] Button LeftAnalogStick;
[GUI] Button RightAnalogUp;
[GUI] Button RightAnalogDown;
[GUI] Button RightAnalogLeft;
[GUI] Button RightAnalogRight;
[GUI] Button RightAnalogStick;
[GUI] Button DPadUp;
[GUI] Button DPadDown;
[GUI] Button DPadLeft;
[GUI] Button DPadRight;
[GUI] Button ButtonA;
[GUI] Button ButtonB;
[GUI] Button ButtonX;
[GUI] Button ButtonY;
[GUI] Button ButtonL;
[GUI] Button ButtonR;
[GUI] Button ButtonZL;
[GUI] Button ButtonZR;
[GUI] Button ButtonMinus;
[GUI] Button ButtonPlus;
Gdk.Key CurrentKeyPressed;
bool IsPressed;
bool CancelCurrentEvent;
Builder builder = new Builder("InputPage.glade");
public InputPage()
{
builder.Autoconnect(this);
Notebook = (Notebook)builder.GetObject("InputNotebook");
//Register Events
LeftAnalogUp.Clicked += LeftAnalogUp_Clicked;
LeftAnalogDown.Clicked += LeftAnalogDown_Clicked;
LeftAnalogLeft.Clicked += LeftAnalogLeft_Clicked;
LeftAnalogRight.Clicked += LeftAnalogRight_Clicked;
LeftAnalogStick.Clicked += LeftAnalogStick_Clicked;
RightAnalogUp.Clicked += RightAnalogUp_Clicked;
RightAnalogDown.Clicked += RightAnalogDown_Clicked;
RightAnalogLeft.Clicked += RightAnalogLeft_Clicked;
RightAnalogRight.Clicked += RightAnalogRight_Clicked;
RightAnalogStick.Clicked += RightAnalogStick_Clicked;
DPadUp.Clicked += DPadUp_Clicked;
DPadDown.Clicked += DPadDown_Clicked;
DPadLeft.Clicked += DPadLeft_Clicked;
DPadRight.Clicked += DPadRight_Clicked;
ButtonA.Clicked += ButtonA_Clicked;
ButtonB.Clicked += ButtonB_Clicked;
ButtonX.Clicked += ButtonX_Clicked;
ButtonY.Clicked += ButtonY_Clicked;
ButtonZL.Clicked += ButtonZL_Clicked;
ButtonZR.Clicked += ButtonZR_Clicked;
ButtonMinus.Clicked += ButtonMinus_Clicked;
ButtonPlus.Clicked += ButtonPlus_Clicked;
// Load Values
LeftAnalogUp.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Left.StickUp).ToString();
LeftAnalogDown.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Left.StickDown).ToString();
LeftAnalogLeft.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Left.StickLeft).ToString();
LeftAnalogRight.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Left.StickRight).ToString();
LeftAnalogStick.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Left.StickButton).ToString();
RightAnalogUp.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Right.StickUp).ToString();
RightAnalogDown.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Right.StickDown).ToString();
RightAnalogLeft.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Right.StickLeft).ToString();
RightAnalogRight.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Right.StickRight).ToString();
RightAnalogStick.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Right.StickButton).ToString();
DPadUp.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadUp).ToString();
DPadDown.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadDown).ToString();
DPadLeft.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadLeft).ToString();
DPadRight.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadRight).ToString();
ButtonA.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonA).ToString();
ButtonB.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonB).ToString();
ButtonX.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonX).ToString();
ButtonY.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonY).ToString();
ButtonL.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonL).ToString();
ButtonR.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonR).ToString();
ButtonZL.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonZL).ToString();
ButtonZR.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonZR).ToString();
ButtonMinus.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonMinus).ToString();
ButtonPlus.Label = ((OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonPlus).ToString();
}
private async void ButtonPlus_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Right.ButtonPlus = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void ButtonMinus_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Left.ButtonMinus = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void ButtonZR_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Right.ButtonZR = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void ButtonZL_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Left.ButtonZL = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void ButtonY_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Right.ButtonY = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void ButtonX_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Right.ButtonX = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void ButtonB_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Right.ButtonB = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void ButtonA_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Right.ButtonA = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void DPadRight_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Left.DPadRight = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void DPadLeft_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Left.DPadLeft = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void DPadDown_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Left.DPadDown = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void DPadUp_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Left.DPadUp = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void RightAnalogStick_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Right.StickButton = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void RightAnalogRight_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Right.StickRight = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void RightAnalogLeft_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Right.StickLeft = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void RightAnalogDown_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Right.StickDown = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void RightAnalogUp_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Right.StickUp = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void LeftAnalogStick_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Left.StickButton = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void LeftAnalogRight_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Left.StickRight = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void LeftAnalogLeft_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Left.StickLeft = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void LeftAnalogDown_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Left.StickDown = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private async void LeftAnalogUp_Clicked(object sender, EventArgs e)
{
if (sender is Button ClickedButton)
{
OpenTK.Input.Key key = await GetKeyPress(ClickedButton);
if (key != default(OpenTK.Input.Key))
{
var joycon = Config.FakeJoyCon;
joycon.Left.StickUp = (int)key;
Config.FakeJoyCon = joycon;
}
}
}
private void InputPage_KeyPressEvent(object o, KeyPressEventArgs args)
{
CurrentKeyPressed = args.Event.Key;
IsPressed = true;
}
public async Task<OpenTK.Input.Key> GetKeyPress(Button ClickedButton)
{
string oldLabel = ClickedButton.Label;
try
{
ClickedButton.IsFocus = true;
ClickedButton.Label = "Enter Key";
ClickedButton.KeyPressEvent += InputPage_KeyPressEvent;
ClickedButton.FocusOutEvent += ClickedButton_FocusOutEvent;
ClickedButton.KeyPressEvent -= InputPage_KeyPressEvent;
while (!IsPressed)
{
if (CancelCurrentEvent)
return default(OpenTK.Input.Key);
await Task.Delay(1);
}
IsPressed = false;
string KeyCode = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(CurrentKeyPressed.ToString());
//Convert certain GTK Keys to OpenTK
switch (CurrentKeyPressed)
{
case Gdk.Key.Shift_L:
KeyCode = "LShift";
break;
case Gdk.Key.Shift_R:
KeyCode = "RShift";
break;
case Gdk.Key.Alt_L:
KeyCode = "LAlt";
break;
case Gdk.Key.Alt_R:
KeyCode = "RAlt";
break;
case Gdk.Key.Control_L:
KeyCode = "LControl";
break;
case Gdk.Key.Control_R:
KeyCode = "RControl";
break;
case Gdk.Key.dead_tilde:
KeyCode = "Tilde";
break;
}
return (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), KeyCode, true);
}
finally
{
CancelCurrentEvent = false;
Gtk.Application.Invoke(delegate
{
ClickedButton.FocusOutEvent -= ClickedButton_FocusOutEvent;
ClickedButton.KeyPressEvent -= InputPage_KeyPressEvent;
ClickedButton.Label = ClickedButton.Label.Equals("Enter Key") ? oldLabel : ClickedButton.Label;
});
}
}
private void ClickedButton_FocusOutEvent(object o, FocusOutEventArgs args)
{
CancelCurrentEvent = true;
IsPressed = false;
}
public Widget GetWidget()
{
return Notebook;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,196 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.21.0 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<object class="GtkImage" id="AboutImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-about</property>
</object>
<object class="GtkImage" id="FileImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-file</property>
</object>
<object class="GtkImage" id="FolderImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-open</property>
</object>
<object class="GtkWindow" id="MainWindow">
<property name="width_request">1027</property>
<property name="height_request">640</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">RyujinxUI</property>
<property name="destroy_with_parent">True</property>
<child>
<object class="GtkBox" id="MainBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkMenuBar" id="MainMenu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
<child>
<object class="GtkMenuItem" id="FileMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Game</property>
<child type="submenu">
<object class="GtkMenu" id="menu1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="LoadFileMenuItem">
<property name="label">Load Package</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="image">FileImage</property>
<property name="use_stock">False</property>
<property name="always_show_image">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="LoadFolderMenuItem">
<property name="label" translatable="yes">Load Game Folder</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="image">FolderImage</property>
<property name="use_stock">False</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="ExitMenuItem">
<property name="label">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Emulation</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="ContinueMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Continue</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="PauseMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Pause</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="StopMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Stop</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="OptionMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Configuration</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">View</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="ShowDebugMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Show Debug Window</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="HelpMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Help</property>
<child type="submenu">
<object class="GtkMenu" id="menu3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="AboutMenuItem">
<property name="label">About Ryujinx</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="image">AboutImage</property>
<property name="use_stock">False</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
<child type="titlebar">
<placeholder/>
</child>
</object>
</interface>

View file

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.21.0 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkNotebook">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<placeholder/>
</child>
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">page 1</property>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">page 2</property>
</object>
<packing>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">page 3</property>
</object>
<packing>
<property name="position">2</property>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
</interface>

5
Ryujinx.UI/UI/style.css Normal file
View file

@ -0,0 +1,5 @@
*
{
background-color:black;
color:blue;
}

BIN
Ryujinx.UI/ryujinxicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.8
VisualStudioVersion = 15.0.27130.2036
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "Ryujinx\Ryujinx.csproj", "{074045D4-3ED2-4711-9169-E385F2BFB5A0}"
EndProject
@ -15,6 +15,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics", "Ryujinx
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio", "Ryujinx.Audio\Ryujinx.Audio.csproj", "{5C1D818E-682A-46A5-9D54-30006E26C270}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI", "Ryujinx.UI\Ryujinx.UI.csproj", "{367E79AF-9A28-4E34-8589-A0F2CF32E2BF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -45,6 +47,10 @@ Global
{5C1D818E-682A-46A5-9D54-30006E26C270}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5C1D818E-682A-46A5-9D54-30006E26C270}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5C1D818E-682A-46A5-9D54-30006E26C270}.Release|Any CPU.Build.0 = Release|Any CPU
{367E79AF-9A28-4E34-8589-A0F2CF32E2BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{367E79AF-9A28-4E34-8589-A0F2CF32E2BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{367E79AF-9A28-4E34-8589-A0F2CF32E2BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{367E79AF-9A28-4E34-8589-A0F2CF32E2BF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE