cleanup, refactoring, style changes, fixes
This commit is contained in:
parent
f1ffb129d6
commit
b9d2039995
21 changed files with 634 additions and 417 deletions
|
@ -22,11 +22,7 @@ namespace ChocolArm64
|
|||
|
||||
public bool EnableCpuTrace { get; set; }
|
||||
|
||||
public static long CyclesExecuted { get; set; }
|
||||
|
||||
public static bool Pause { get; set; } = false;
|
||||
|
||||
public static ManualResetEvent PauseResetEvent = new ManualResetEvent(false);
|
||||
public static ManualResetEvent PauseResetEvent = new ManualResetEvent(true);
|
||||
|
||||
public ATranslator(IReadOnlyDictionary<long, string> SymbolTable = null)
|
||||
{
|
||||
|
@ -68,10 +64,7 @@ namespace ChocolArm64
|
|||
|
||||
OpCode.Interpreter(State, Memory, OpCode);
|
||||
|
||||
CyclesExecuted++;
|
||||
|
||||
while (Pause)
|
||||
PauseResetEvent.WaitOne(1000);
|
||||
PauseResetEvent.WaitOne(1000);
|
||||
}
|
||||
while (State.R15 != 0 && State.Running);
|
||||
}
|
||||
|
@ -102,10 +95,7 @@ namespace ChocolArm64
|
|||
|
||||
Position = Sub.Execute(State, Memory);
|
||||
|
||||
CyclesExecuted++;
|
||||
|
||||
while (Pause)
|
||||
PauseResetEvent.WaitOne(1000);
|
||||
PauseResetEvent.WaitOne();
|
||||
}
|
||||
while (Position != 0 && State.Running);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ namespace Ryujinx.HLE.OsHle
|
|||
|
||||
private ConcurrentDictionary<int, Process> Processes;
|
||||
|
||||
private bool IsDisposing;
|
||||
|
||||
public SystemStateMgr SystemState { get; private set; }
|
||||
|
||||
internal MemoryAllocator Allocator { get; private set; }
|
||||
|
@ -170,7 +172,7 @@ namespace Ryujinx.HLE.OsHle
|
|||
|
||||
internal void ExitProcess(int ProcessId)
|
||||
{
|
||||
if (Processes.TryGetValue(ProcessId, out Process Process) && Process.NeedsHbAbi)
|
||||
if (Processes.TryGetValue(ProcessId, out Process Process) && Process.NeedsHbAbi && !IsDisposing)
|
||||
{
|
||||
string NextNro = Homebrew.ReadHbAbiNextLoadPath(Process.Memory, Process.HbAbiDataPosition);
|
||||
|
||||
|
@ -193,8 +195,15 @@ namespace Ryujinx.HLE.OsHle
|
|||
|
||||
if (Processes.TryRemove(ProcessId, out Process))
|
||||
{
|
||||
Process.StopAllThreadsAsync();
|
||||
Process.Dispose();
|
||||
try
|
||||
{
|
||||
Process.StopAllThreadsAsync();
|
||||
Process.Dispose();
|
||||
}
|
||||
catch (ObjectDisposedException Ex)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (Processes.Count == 0)
|
||||
{
|
||||
|
@ -215,6 +224,8 @@ namespace Ryujinx.HLE.OsHle
|
|||
|
||||
protected virtual void Dispose(bool Disposing)
|
||||
{
|
||||
IsDisposing = Disposing;
|
||||
|
||||
if (Disposing)
|
||||
{
|
||||
foreach (Process Process in Processes.Values)
|
||||
|
|
|
@ -176,7 +176,7 @@ namespace Ryujinx.HLE.OsHle
|
|||
throw new ObjectDisposedException(nameof(Process));
|
||||
}
|
||||
|
||||
ATranslator.Pause = true;
|
||||
ATranslator.PauseResetEvent.Reset();
|
||||
}
|
||||
|
||||
public void Resume()
|
||||
|
@ -186,7 +186,6 @@ namespace Ryujinx.HLE.OsHle
|
|||
throw new ObjectDisposedException(nameof(Process));
|
||||
}
|
||||
|
||||
ATranslator.Pause = false;
|
||||
ATranslator.PauseResetEvent.Set();
|
||||
}
|
||||
|
||||
|
@ -424,6 +423,8 @@ namespace Ryujinx.HLE.OsHle
|
|||
{
|
||||
if (Disposing && !Disposed)
|
||||
{
|
||||
ATranslator.PauseResetEvent.Set();
|
||||
|
||||
//If there is still some thread running, disposing the objects is not
|
||||
//safe as the thread may try to access those resources. Instead, we set
|
||||
//the flag to have the Process disposed when all threads finishes.
|
||||
|
|
|
@ -98,7 +98,8 @@ namespace Ryujinx.HLE
|
|||
{
|
||||
Os.Dispose();
|
||||
VFs.Dispose();
|
||||
Gpu.Dispose();
|
||||
Gpu.Dispose();
|
||||
AudioOut.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,11 +98,21 @@ namespace Ryujinx
|
|||
|
||||
DefaultGameDirectory = Parser.GetValue("Default_Game_Directory");
|
||||
|
||||
VirtualFileSystem FS = new HLE.VirtualFileSystem();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(DefaultGameDirectory))
|
||||
{
|
||||
VirtualFileSystem FS = new HLE.VirtualFileSystem();
|
||||
{
|
||||
DefaultGameDirectory = Path.Combine(FS.GetSdCardPath(), "switch");
|
||||
}
|
||||
|
||||
if (!Directory.Exists(DefaultGameDirectory))
|
||||
{
|
||||
if (!Directory.CreateDirectory(DefaultGameDirectory).Exists)
|
||||
{
|
||||
DefaultGameDirectory = Path.Combine(FS.GetSdCardPath(), "switch");
|
||||
Directory.CreateDirectory(DefaultGameDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Save(Logger Log)
|
||||
|
@ -165,7 +175,7 @@ namespace Ryujinx
|
|||
{
|
||||
private readonly Dictionary<string, string> Values;
|
||||
private readonly Dictionary<string, string> Comments;
|
||||
private string Path;
|
||||
private readonly string Path;
|
||||
|
||||
public IniParser(string Path)
|
||||
{
|
||||
|
@ -214,20 +224,25 @@ namespace Ryujinx
|
|||
{
|
||||
bool result = false;
|
||||
List<string> Records = new List<string>();
|
||||
|
||||
foreach (var Record in Values)
|
||||
{
|
||||
if (Comments.ContainsKey(Record.Key))
|
||||
{
|
||||
string Comment = Comments[Record.Key];
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Comment))
|
||||
{
|
||||
Records.Add(Environment.NewLine);
|
||||
Records.Add(Comments[Record.Key]);
|
||||
}
|
||||
}
|
||||
|
||||
Records.Add(string.Format("{0} = {1}", Record.Key, Record.Value));
|
||||
}
|
||||
|
||||
File.WriteAllLines(Path, Records);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Ryujinx.HLE;
|
||||
using Ryujinx.HLE;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.UI
|
||||
{
|
||||
class EmulationController
|
||||
{
|
||||
public bool IsLoaded = false;
|
||||
|
||||
private Switch Ns;
|
||||
|
||||
public event EventHandler IsShutDown;
|
||||
|
||||
public EmulationController(Switch Ns)
|
||||
{
|
||||
this.Ns = Ns;
|
||||
|
@ -17,21 +19,56 @@ namespace Ryujinx.UI
|
|||
|
||||
public void Resume()
|
||||
{
|
||||
lock(Ns)
|
||||
Ns.Os.ResumeAllProcesses();
|
||||
lock (Ns)
|
||||
Ns.Os.ResumeAllProcesses();
|
||||
}
|
||||
|
||||
public void Pause()
|
||||
{
|
||||
lock(Ns)
|
||||
Ns.Os.PauseAllProcesses();
|
||||
lock (Ns)
|
||||
Ns.Os.PauseAllProcesses();
|
||||
}
|
||||
|
||||
public void ShutDown()
|
||||
{
|
||||
lock (Ns)
|
||||
Ns.Dispose();
|
||||
Ns = null;
|
||||
IsLoaded = false;
|
||||
IsShutDown.Invoke(null,null);
|
||||
}
|
||||
|
||||
public void Load(string Path)
|
||||
{
|
||||
if (Directory.Exists(Path))
|
||||
{
|
||||
string[] RomFsFiles = Directory.GetFiles(Path, "*.istorage");
|
||||
|
||||
if (RomFsFiles.Length == 0)
|
||||
{
|
||||
RomFsFiles = Directory.GetFiles(Path, "*.romfs");
|
||||
}
|
||||
|
||||
if (RomFsFiles.Length > 0)
|
||||
{
|
||||
Console.WriteLine("Loading as cart with RomFS.");
|
||||
|
||||
Ns.LoadCart(Path, RomFsFiles[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Loading as cart WITHOUT RomFS.");
|
||||
|
||||
Ns.LoadCart(Path);
|
||||
}
|
||||
}
|
||||
else if (File.Exists(Path))
|
||||
{
|
||||
Console.WriteLine("Loading as homebrew.");
|
||||
|
||||
Ns.LoadProgram(Path);
|
||||
}
|
||||
IsLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace Ryujinx.UI
|
|||
byte[] LanguageEntryData = Reader.ReadBytes(0x3000);
|
||||
|
||||
Input.Seek(0x3060, SeekOrigin.Begin);
|
||||
|
||||
ApplicationVersion = Encoding.ASCII.GetString(Reader.ReadBytes(0x10));
|
||||
BaseTitleID = Reader.ReadInt64();
|
||||
ApplicationTitleID = Reader.ReadInt64();
|
||||
|
|
12
Ryujinx.ImGui/Extensions/DialogResult.cs
Normal file
12
Ryujinx.ImGui/Extensions/DialogResult.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
public enum DialogResult
|
||||
{
|
||||
OK,
|
||||
Cancel,
|
||||
Yes,
|
||||
No,
|
||||
None
|
||||
}
|
|
@ -8,12 +8,10 @@ namespace Ryujinx.UI
|
|||
{
|
||||
class Nro : HLE.Loaders.Executables.Nro
|
||||
{
|
||||
public byte[] AssetRomfData { get; set; }
|
||||
public byte[] IconData { get; set; }
|
||||
|
||||
private byte[] NACPData { get; set; }
|
||||
|
||||
public int AssetOffset { get; set; }
|
||||
public byte[] AssetRomfData { get; set; }
|
||||
public byte[] IconData { get; set; }
|
||||
private byte[] NACPData { get; set; }
|
||||
public int AssetOffset { get; set; }
|
||||
|
||||
public ControlArchive ControlArchive { get; set; }
|
||||
|
||||
|
@ -38,18 +36,19 @@ namespace Ryujinx.UI
|
|||
if (AssetMagic == "ASET")
|
||||
{
|
||||
Input.Seek(AssetOffset, SeekOrigin.Begin);
|
||||
int AssetMagic0 = Reader.ReadInt32();
|
||||
int AssetFormat = Reader.ReadInt32();
|
||||
byte[] IconSectionInfo = Reader.ReadBytes(0x10);
|
||||
byte[] NACPSectionInfo = Reader.ReadBytes(0x10);
|
||||
|
||||
int AssetMagic0 = Reader.ReadInt32();
|
||||
int AssetFormat = Reader.ReadInt32();
|
||||
byte[] IconSectionInfo = Reader.ReadBytes(0x10);
|
||||
byte[] NACPSectionInfo = Reader.ReadBytes(0x10);
|
||||
byte[] AssetRomfSectionInfo = Reader.ReadBytes(0x10);
|
||||
|
||||
long IconOffset = BitConverter.ToInt64(IconSectionInfo, 0);
|
||||
long IconSize = BitConverter.ToInt64(IconSectionInfo, 8);
|
||||
long IconSize = BitConverter.ToInt64(IconSectionInfo, 8);
|
||||
long NACPOffset = BitConverter.ToInt64(NACPSectionInfo, 0);
|
||||
long NACPSize = BitConverter.ToInt64(NACPSectionInfo, 8);
|
||||
long NACPSize = BitConverter.ToInt64(NACPSectionInfo, 8);
|
||||
long RomfOffset = BitConverter.ToInt64(AssetRomfSectionInfo, 0);
|
||||
long RomfSize = BitConverter.ToInt64(AssetRomfSectionInfo, 8);
|
||||
long RomfSize = BitConverter.ToInt64(AssetRomfSectionInfo, 8);
|
||||
|
||||
Input.Seek(AssetOffset + IconOffset, SeekOrigin.Begin);
|
||||
IconData = Reader.ReadBytes((int)IconSize);
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
using ImGuiNET;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
using OpenTK.Graphics;
|
||||
using Ryujinx.Audio;
|
||||
using Ryujinx.Audio.OpenAL;
|
||||
using Ryujinx.Graphics.Gal;
|
||||
using Ryujinx.Graphics.Gal.OpenGL;
|
||||
using Ryujinx.HLE;
|
||||
using Ryujinx.HLE.Input;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.UI
|
||||
{
|
||||
partial class EmulationWindow : WindowHelper
|
||||
{
|
||||
public static EmulationController EmulationController;
|
||||
//toggles
|
||||
private bool showMainUI = true;
|
||||
private bool showPauseUI;
|
||||
|
@ -26,10 +26,6 @@ namespace Ryujinx.UI
|
|||
{
|
||||
isRunning = value;
|
||||
UIActive = !value;
|
||||
if (!value)
|
||||
{
|
||||
//ShowMainUI = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,8 +35,13 @@ namespace Ryujinx.UI
|
|||
set
|
||||
{
|
||||
showMainUI = value;
|
||||
showPauseUI = !value && !isRunning;
|
||||
UIActive = value;
|
||||
if (value)
|
||||
{
|
||||
CurrentPage = Page.GameList;
|
||||
UIActive = value;
|
||||
}
|
||||
else if (!ShowPauseUI)
|
||||
UIActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,12 +51,15 @@ namespace Ryujinx.UI
|
|||
set
|
||||
{
|
||||
showPauseUI = value;
|
||||
UIActive = value;
|
||||
showMainUI = !value;
|
||||
if (value)
|
||||
{
|
||||
CurrentPage = Page.Emulation;
|
||||
UIActive = value;
|
||||
}
|
||||
else if (!ShowMainUI)
|
||||
UIActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
private EmulationController EmulationController;
|
||||
}
|
||||
|
||||
private Page CurrentPage = Page.GameList;
|
||||
|
||||
|
@ -73,42 +77,33 @@ namespace Ryujinx.UI
|
|||
FilePicker FileDialog;
|
||||
|
||||
IGalRenderer Renderer;
|
||||
IAalOutput AudioOut;
|
||||
|
||||
public static Switch Ns;
|
||||
|
||||
public EmulationWindow() : base("Test")
|
||||
public EmulationWindow() : base("Ryujinx")
|
||||
{
|
||||
FileDialog = FilePicker.GetFilePicker("rom",null);
|
||||
|
||||
Renderer = new OGLRenderer();
|
||||
|
||||
AudioOut = new OpenALAudioOut();
|
||||
|
||||
Ns = new Switch(Renderer, AudioOut);
|
||||
|
||||
Config.Read(Ns.Log);
|
||||
|
||||
EmulationController = new EmulationController(Ns);
|
||||
|
||||
Ns.Log.Updated += ConsoleLog.PrintLog;
|
||||
InitializeSwitch();
|
||||
}
|
||||
|
||||
protected override void OnLoad(EventArgs e)
|
||||
{
|
||||
base.OnLoad(e);
|
||||
|
||||
VSync = VSyncMode.On;
|
||||
|
||||
Renderer.FrameBuffer.SetWindowSize(Width, Height);
|
||||
VSync = VSyncMode.On;
|
||||
}
|
||||
|
||||
protected override void OnRenderFrame(FrameEventArgs e)
|
||||
{
|
||||
_deltaTime = (float)e.Time;
|
||||
DeltaTime = (float)e.Time;
|
||||
|
||||
if (UIActive)
|
||||
{
|
||||
StartFrame();
|
||||
StartFrame();
|
||||
|
||||
isRunning = false;
|
||||
|
||||
if (ShowMainUI)
|
||||
{
|
||||
showPauseUI = false;
|
||||
|
@ -119,7 +114,7 @@ namespace Ryujinx.UI
|
|||
showMainUI = false;
|
||||
RenderPauseUI();
|
||||
}
|
||||
ImGuiNative.igShowMetricsWindow(ref UIActive);
|
||||
|
||||
EndFrame();
|
||||
}
|
||||
else
|
||||
|
@ -139,9 +134,28 @@ namespace Ryujinx.UI
|
|||
}
|
||||
}
|
||||
|
||||
public void InitializeSwitch()
|
||||
{
|
||||
MainContext.MakeCurrent(WindowInfo);
|
||||
|
||||
Renderer = new OGLRenderer();
|
||||
|
||||
Renderer.FrameBuffer.SetWindowSize(Width, Height);
|
||||
|
||||
IAalOutput AudioOut = new OpenALAudioOut();
|
||||
|
||||
Ns = new Switch(Renderer, AudioOut);
|
||||
|
||||
Config.Read(Ns.Log);
|
||||
|
||||
Ns.Log.Updated += ConsoleLog.PrintLog;
|
||||
}
|
||||
|
||||
protected override void OnUpdateFrame(FrameEventArgs e)
|
||||
{
|
||||
if(!UIActive)
|
||||
KeyboardState Keyboard = this.Keyboard.HasValue ? this.Keyboard.Value : new KeyboardState();
|
||||
|
||||
if (!UIActive)
|
||||
{
|
||||
if (Keyboard[Key.Escape] && !EscapePressed)
|
||||
{
|
||||
|
@ -153,7 +167,9 @@ namespace Ryujinx.UI
|
|||
|
||||
if (EmulationController.IsLoaded)
|
||||
ShowPauseUI = true;
|
||||
|
||||
UIActive = true;
|
||||
|
||||
return;
|
||||
}
|
||||
else if (Keyboard[Key.Escape])
|
||||
|
@ -218,8 +234,10 @@ namespace Ryujinx.UI
|
|||
|
||||
//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 (Focused && Mouse?.GetState().LeftButton == ButtonState.Pressed)
|
||||
if (Focused && Mouse?.LeftButton == ButtonState.Pressed)
|
||||
{
|
||||
MouseState Mouse = this.Mouse.Value;
|
||||
|
||||
int ScrnWidth = Width;
|
||||
int ScrnHeight = Height;
|
||||
|
||||
|
@ -289,59 +307,53 @@ namespace Ryujinx.UI
|
|||
|
||||
Renderer.RunActions();
|
||||
}
|
||||
else if(EmulationController.IsLoaded)
|
||||
{
|
||||
if (Keyboard[Key.Escape] && !EscapePressed)
|
||||
else if (EmulationController != null)
|
||||
if (EmulationController.IsLoaded)
|
||||
{
|
||||
EscapePressed = true;
|
||||
EmulationController.Resume();
|
||||
if (Keyboard[Key.Escape] && !EscapePressed)
|
||||
{
|
||||
EscapePressed = true;
|
||||
|
||||
if (ShowPauseUI & EmulationController.IsLoaded)
|
||||
showPauseUI = false;
|
||||
UIActive = false;
|
||||
IsRunning = true;
|
||||
EmulationController.Resume();
|
||||
|
||||
if (ShowPauseUI & EmulationController.IsLoaded)
|
||||
showPauseUI = false;
|
||||
|
||||
UIActive = false;
|
||||
IsRunning = true;
|
||||
}
|
||||
else if (Keyboard[Key.Escape])
|
||||
EscapePressed = true;
|
||||
else
|
||||
EscapePressed = false;
|
||||
}
|
||||
else if (Keyboard[Key.Escape])
|
||||
EscapePressed = true;
|
||||
else
|
||||
EscapePressed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadPackage(string path)
|
||||
{
|
||||
ShowMainUI = false;
|
||||
{
|
||||
|
||||
MainContext.MakeCurrent(WindowInfo);
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
string[] RomFsFiles = Directory.GetFiles(path, "*.istorage");
|
||||
|
||||
if (RomFsFiles.Length == 0)
|
||||
{
|
||||
RomFsFiles = Directory.GetFiles(path, "*.romfs");
|
||||
}
|
||||
if(Ns == null)
|
||||
InitializeSwitch();
|
||||
|
||||
if (RomFsFiles.Length > 0)
|
||||
{
|
||||
Console.WriteLine("Loading as cart with RomFS.");
|
||||
if (EmulationController == null)
|
||||
EmulationController = new EmulationController(Ns);
|
||||
|
||||
Ns.LoadCart(path, RomFsFiles[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Loading as cart WITHOUT RomFS.");
|
||||
EmulationController.IsShutDown += EmulationController_IsShutDown;
|
||||
|
||||
Ns.LoadCart(path);
|
||||
}
|
||||
}
|
||||
else if (File.Exists(path))
|
||||
{
|
||||
Console.WriteLine("Loading as homebrew.");
|
||||
EmulationController.Load(path);
|
||||
|
||||
Ns.LoadProgram(path);
|
||||
}
|
||||
IsRunning = true;
|
||||
EmulationController.IsLoaded = true;
|
||||
|
||||
ShowMainUI = false;
|
||||
}
|
||||
|
||||
private void EmulationController_IsShutDown(object sender, EventArgs e)
|
||||
{
|
||||
EmulationController = null;
|
||||
|
||||
Ns = null;
|
||||
}
|
||||
|
||||
enum Page
|
||||
|
|
|
@ -1,28 +1,25 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ImGuiNET;
|
||||
using System.Numerics;
|
||||
using ImGuiNET;
|
||||
using Ryujinx.HLE.Input;
|
||||
using OpenTK.Input;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.UI.Widgets
|
||||
{
|
||||
public partial class ConfigurationWidget
|
||||
{
|
||||
public static JoyCon CurrentJoyConLayout;
|
||||
static Page CurrentPage = Page.General;
|
||||
{
|
||||
static bool ConfigIntialized = false;
|
||||
static bool OpenFolderPicker;
|
||||
static string CurrentPath;
|
||||
|
||||
static IniParser IniParser;
|
||||
static FolderPicker FolderPicker;
|
||||
static JoyCon CurrentJoyConLayout;
|
||||
static Page CurrentPage = Page.General;
|
||||
|
||||
static ConfigurationWidget()
|
||||
{
|
||||
IniParser = new IniParser(Config.IniPath);
|
||||
IniParser = new IniParser(Config.IniPath);
|
||||
FolderPicker = FolderPicker.GetFolderPicker("FolderDialog",Config.DefaultGameDirectory);
|
||||
CurrentPath = Config.DefaultGameDirectory.ToString();
|
||||
CurrentPath = Config.DefaultGameDirectory.ToString();
|
||||
}
|
||||
|
||||
public static void Draw()
|
||||
|
@ -60,30 +57,27 @@ namespace Ryujinx.UI.Widgets
|
|||
{
|
||||
ImGui.Text("General Emulation Settings");
|
||||
ImGui.Spacing();
|
||||
ImGui.LabelText("","Default Game Directory");
|
||||
ImGui.LabelText("", "Default Game Directory");
|
||||
ImGui.SameLine();
|
||||
|
||||
if( ImGui.Selectable(Config.DefaultGameDirectory))
|
||||
if (ImGui.Selectable(Config.DefaultGameDirectory))
|
||||
{
|
||||
OpenFolderPicker = true;
|
||||
}
|
||||
if (OpenFolderPicker)
|
||||
ImGui.OpenPopup("OpenFolder");
|
||||
|
||||
ImGui.SetNextWindowSize(new Vector2(500, 500), Condition.FirstUseEver);
|
||||
if(ImGui.BeginPopupModal("OpenFolder",WindowFlags.NoResize))
|
||||
DialogResult DialogResult = FolderPicker.GetFolder(ref CurrentPath);
|
||||
if (DialogResult == DialogResult.OK)
|
||||
{
|
||||
string output = CurrentPath;
|
||||
if (FolderPicker.Draw(ref output, false))
|
||||
if (!string.IsNullOrWhiteSpace(CurrentPath))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(output))
|
||||
{
|
||||
Config.DefaultGameDirectory = output;
|
||||
}
|
||||
ImGui.CloseCurrentPopup();
|
||||
OpenFolderPicker = false;
|
||||
Config.DefaultGameDirectory = CurrentPath;
|
||||
}
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
if (DialogResult != DialogResult.None)
|
||||
{
|
||||
OpenFolderPicker = false;
|
||||
}
|
||||
|
||||
ImGui.Spacing();
|
||||
|
|
|
@ -11,115 +11,115 @@ namespace ImGuiNET
|
|||
/// </summary>
|
||||
public class FilePicker
|
||||
{
|
||||
private const string FilePickerID = "###FilePicker";
|
||||
private static readonly Dictionary<object, FilePicker> s_filePickers = new Dictionary<object, FilePicker>();
|
||||
private const string FilePickerID = "###FilePicker";
|
||||
private static readonly Dictionary<object, FilePicker> FilePickers = new Dictionary<object, FilePicker>();
|
||||
private static readonly Vector2 DefaultFilePickerSize = new Vector2(600, 400);
|
||||
|
||||
public string CurrentFolder { get; set; }
|
||||
public string SelectedFile { get; set; }
|
||||
public string SelectedEntry { get; set; }
|
||||
|
||||
public static FilePicker GetFilePicker(object o, string startingPath)
|
||||
public static FilePicker GetFilePicker(object Id, string StartingPath)
|
||||
{
|
||||
if (File.Exists(startingPath))
|
||||
if (File.Exists(StartingPath))
|
||||
{
|
||||
startingPath = new FileInfo(startingPath).DirectoryName;
|
||||
StartingPath = new FileInfo(StartingPath).DirectoryName;
|
||||
}
|
||||
else if (string.IsNullOrEmpty(startingPath) || !Directory.Exists(startingPath))
|
||||
else if (string.IsNullOrEmpty(StartingPath) || !Directory.Exists(StartingPath))
|
||||
{
|
||||
startingPath = Environment.CurrentDirectory;
|
||||
if (string.IsNullOrEmpty(startingPath))
|
||||
StartingPath = Environment.CurrentDirectory;
|
||||
if (string.IsNullOrEmpty(StartingPath))
|
||||
{
|
||||
startingPath = AppContext.BaseDirectory;
|
||||
StartingPath = AppContext.BaseDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
if (!s_filePickers.TryGetValue(o, out FilePicker fp))
|
||||
if (!FilePickers.TryGetValue(Id, out FilePicker FilePicker))
|
||||
{
|
||||
fp = new FilePicker();
|
||||
fp.CurrentFolder = startingPath;
|
||||
s_filePickers.Add(o, fp);
|
||||
FilePicker = new FilePicker
|
||||
{
|
||||
CurrentFolder = StartingPath
|
||||
};
|
||||
|
||||
FilePickers.Add(Id, FilePicker);
|
||||
}
|
||||
|
||||
return fp;
|
||||
return FilePicker;
|
||||
}
|
||||
|
||||
public bool Draw(ref string selected, bool returnOnSelection)
|
||||
public DialogResult Draw(ref string SelectedPath, bool ReturnOnSelection)
|
||||
{
|
||||
bool result = false;
|
||||
result = DrawFolder(ref selected, returnOnSelection);
|
||||
return result;
|
||||
return DrawFolder(ref SelectedPath, ReturnOnSelection);
|
||||
}
|
||||
|
||||
private bool DrawFolder(ref string selected, bool returnOnSelection = false)
|
||||
private DialogResult DrawFolder(ref string SelectedPath, bool ReturnOnSelection = false)
|
||||
{
|
||||
ImGui.Text("Current Folder: " + CurrentFolder);
|
||||
bool result = false;
|
||||
|
||||
if (ImGui.BeginChildFrame(1, ImGui.GetContentRegionAvailable() - new Vector2(20, Values.ButtonHeight),
|
||||
WindowFlags.Default))
|
||||
{
|
||||
DirectoryInfo di = new DirectoryInfo(CurrentFolder);
|
||||
if (di.Exists)
|
||||
DirectoryInfo CurrentDirectory = new DirectoryInfo(CurrentFolder);
|
||||
if (CurrentDirectory.Exists)
|
||||
{
|
||||
if (di.Parent != null)
|
||||
if (CurrentDirectory.Parent != null)
|
||||
{
|
||||
ImGui.PushStyleColor(ColorTarget.Text, Values.Color.Yellow);
|
||||
|
||||
if (ImGui.Selectable("../", false, SelectableFlags.DontClosePopups
|
||||
, new Vector2(ImGui.GetContentRegionAvailableWidth(), Values.SelectibleHeight)))
|
||||
{
|
||||
CurrentFolder = di.Parent.FullName;
|
||||
CurrentFolder = CurrentDirectory.Parent.FullName;
|
||||
}
|
||||
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
foreach (var dir in Directory.EnumerateFileSystemEntries(di.FullName))
|
||||
|
||||
foreach (string Dir in Directory.EnumerateFileSystemEntries(CurrentDirectory.FullName))
|
||||
{
|
||||
if (Directory.Exists(dir))
|
||||
if (Directory.Exists(Dir))
|
||||
{
|
||||
string name = Path.GetFileName(dir);
|
||||
bool isSelected = SelectedFile == dir;
|
||||
string Name = Path.GetFileName(Dir);
|
||||
bool IsSelected = SelectedEntry == Dir;
|
||||
|
||||
ImGui.PushStyleColor(ColorTarget.Text, Values.Color.Yellow);
|
||||
|
||||
if (ImGui.Selectable(name + "/", isSelected, SelectableFlags.DontClosePopups
|
||||
if (ImGui.Selectable(Name + "/", IsSelected, SelectableFlags.DontClosePopups
|
||||
, new Vector2(ImGui.GetContentRegionAvailableWidth(), Values.SelectibleHeight)))
|
||||
{
|
||||
SelectedFile = dir;
|
||||
selected = SelectedFile;
|
||||
SelectedEntry = Dir;
|
||||
SelectedPath = SelectedEntry;
|
||||
}
|
||||
|
||||
if (SelectedFile != null)
|
||||
if (ImGui.IsMouseDoubleClicked(0) && SelectedFile.Equals(dir))
|
||||
if (SelectedEntry != null)
|
||||
if (ImGui.IsMouseDoubleClicked(0) && SelectedEntry.Equals(Dir))
|
||||
{
|
||||
SelectedFile = null;
|
||||
selected = null;
|
||||
CurrentFolder = dir;
|
||||
SelectedEntry = null;
|
||||
SelectedPath = null;
|
||||
CurrentFolder = Dir;
|
||||
}
|
||||
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
}
|
||||
foreach (var file in Directory.EnumerateFiles(di.FullName))
|
||||
foreach (string File in Directory.EnumerateFiles(CurrentDirectory.FullName))
|
||||
{
|
||||
string name = Path.GetFileName(file);
|
||||
bool isSelected = SelectedFile == file;
|
||||
string Name = Path.GetFileName(File);
|
||||
bool IsSelected = SelectedEntry == File;
|
||||
|
||||
if (ImGui.Selectable(name, isSelected, SelectableFlags.DontClosePopups
|
||||
if (ImGui.Selectable(Name, IsSelected, SelectableFlags.DontClosePopups
|
||||
, new Vector2(ImGui.GetContentRegionAvailableWidth(), Values.SelectibleHeight)))
|
||||
{
|
||||
SelectedFile = file;
|
||||
if (returnOnSelection)
|
||||
SelectedEntry = File;
|
||||
if (ReturnOnSelection)
|
||||
{
|
||||
selected = SelectedFile;
|
||||
SelectedPath = SelectedEntry;
|
||||
}
|
||||
}
|
||||
|
||||
if (SelectedFile != null)
|
||||
if (ImGui.IsMouseDoubleClicked(0) && SelectedFile.Equals(file))
|
||||
if (SelectedEntry != null)
|
||||
if (ImGui.IsMouseDoubleClicked(0) && SelectedEntry.Equals(File))
|
||||
{
|
||||
selected = file;
|
||||
result = true;
|
||||
SelectedPath = File;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,20 +129,27 @@ namespace ImGuiNET
|
|||
|
||||
if (ImGui.Button("Cancel", new Vector2(Values.ButtonWidth, Values.ButtonHeight)))
|
||||
{
|
||||
result = false;
|
||||
return DialogResult.Cancel;
|
||||
}
|
||||
|
||||
if (SelectedFile != null)
|
||||
if (SelectedEntry != null)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Load", new Vector2(Values.ButtonWidth, Values.ButtonHeight)))
|
||||
{
|
||||
result = true;
|
||||
selected = SelectedFile;
|
||||
SelectedPath = SelectedEntry;
|
||||
|
||||
return DialogResult.OK;
|
||||
}
|
||||
else if (ReturnOnSelection)
|
||||
{
|
||||
SelectedPath = SelectedEntry;
|
||||
|
||||
return DialogResult.OK;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return DialogResult.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,91 +11,91 @@ namespace ImGuiNET
|
|||
/// </summary>
|
||||
public class FolderPicker
|
||||
{
|
||||
private const string FilePickerID = "###FilePicker";
|
||||
private static readonly Dictionary<object, FolderPicker> s_folderPickers
|
||||
private const string FolderPickerID = "###FolderPicker";
|
||||
private static readonly Dictionary<object, FolderPicker> FolderPickers
|
||||
= new Dictionary<object, FolderPicker>();
|
||||
private static readonly Vector2 DefaultFilePickerSize = new Vector2(600, 400);
|
||||
|
||||
public string CurrentFolder { get; set; }
|
||||
public string SelectedFile { get; set; }
|
||||
public string SelectedDirectory { get; set; }
|
||||
|
||||
public static FolderPicker GetFolderPicker(object o, string startingPath)
|
||||
public static FolderPicker GetFolderPicker(object Id, string StartingPath)
|
||||
{
|
||||
if (File.Exists(startingPath))
|
||||
if (File.Exists(StartingPath))
|
||||
{
|
||||
startingPath = new FileInfo(startingPath).DirectoryName;
|
||||
StartingPath = new FileInfo(StartingPath).DirectoryName;
|
||||
}
|
||||
else if (string.IsNullOrEmpty(startingPath) || !Directory.Exists(startingPath))
|
||||
else if (string.IsNullOrEmpty(StartingPath) || !Directory.Exists(StartingPath))
|
||||
{
|
||||
startingPath = Environment.CurrentDirectory;
|
||||
if (string.IsNullOrEmpty(startingPath))
|
||||
StartingPath = Environment.CurrentDirectory;
|
||||
if (string.IsNullOrEmpty(StartingPath))
|
||||
{
|
||||
startingPath = AppContext.BaseDirectory;
|
||||
StartingPath = AppContext.BaseDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
if (!s_folderPickers.TryGetValue(o, out FolderPicker fp))
|
||||
if (!FolderPickers.TryGetValue(Id, out FolderPicker FolderPicker))
|
||||
{
|
||||
fp = new FolderPicker();
|
||||
fp.CurrentFolder = startingPath;
|
||||
s_folderPickers.Add(o, fp);
|
||||
FolderPicker = new FolderPicker
|
||||
{
|
||||
CurrentFolder = StartingPath
|
||||
};
|
||||
|
||||
FolderPickers.Add(Id, FolderPicker);
|
||||
}
|
||||
|
||||
return fp;
|
||||
return FolderPicker;
|
||||
}
|
||||
|
||||
public bool Draw(ref string selected, bool returnOnSelection)
|
||||
public DialogResult Draw(ref string Selected, bool ReturnOnSelection)
|
||||
{
|
||||
bool result = false;
|
||||
result = DrawFolder(ref selected, returnOnSelection);
|
||||
return result;
|
||||
return DrawFolder(ref Selected, ReturnOnSelection);
|
||||
}
|
||||
|
||||
private bool DrawFolder(ref string selected, bool returnOnSelection = false)
|
||||
private DialogResult DrawFolder(ref string Selected, bool ReturnOnSelection = false)
|
||||
{
|
||||
ImGui.Text("Current Folder: " + CurrentFolder);
|
||||
bool result = false;
|
||||
|
||||
if (ImGui.BeginChildFrame(1, ImGui.GetContentRegionAvailable() - new Vector2(20, Values.ButtonHeight),
|
||||
WindowFlags.Default))
|
||||
{
|
||||
DirectoryInfo di = new DirectoryInfo(CurrentFolder);
|
||||
if (di.Exists)
|
||||
DirectoryInfo CurrentDirectory = new DirectoryInfo(CurrentFolder);
|
||||
if (CurrentDirectory.Exists)
|
||||
{
|
||||
if (di.Parent != null)
|
||||
if (CurrentDirectory.Parent != null)
|
||||
{
|
||||
ImGui.PushStyleColor(ColorTarget.Text, Values.Color.Yellow);
|
||||
|
||||
if (ImGui.Selectable("../", false, SelectableFlags.DontClosePopups
|
||||
, new Vector2(ImGui.GetContentRegionAvailableWidth(), Values.SelectibleHeight)))
|
||||
{
|
||||
CurrentFolder = di.Parent.FullName;
|
||||
CurrentFolder = CurrentDirectory.Parent.FullName;
|
||||
}
|
||||
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
foreach (var dir in Directory.EnumerateFileSystemEntries(di.FullName))
|
||||
foreach (var Dir in Directory.EnumerateFileSystemEntries(CurrentDirectory.FullName))
|
||||
{
|
||||
if (Directory.Exists(dir))
|
||||
if (Directory.Exists(Dir))
|
||||
{
|
||||
string name = Path.GetFileName(dir);
|
||||
bool isSelected = SelectedFile == dir;
|
||||
string Name = Path.GetFileName(Dir);
|
||||
bool IsSelected = SelectedDirectory == Dir;
|
||||
|
||||
ImGui.PushStyleColor(ColorTarget.Text, Values.Color.Yellow);
|
||||
|
||||
if (ImGui.Selectable(name + "/", isSelected, SelectableFlags.DontClosePopups
|
||||
if (ImGui.Selectable(Name + "/", IsSelected, SelectableFlags.DontClosePopups
|
||||
, new Vector2(ImGui.GetContentRegionAvailableWidth(), Values.SelectibleHeight)))
|
||||
{
|
||||
SelectedFile = dir;
|
||||
selected = SelectedFile;
|
||||
SelectedDirectory = Dir;
|
||||
Selected = SelectedDirectory;
|
||||
}
|
||||
|
||||
if (SelectedFile != null)
|
||||
if (ImGui.IsMouseDoubleClicked(0) && SelectedFile.Equals(dir))
|
||||
if (SelectedDirectory != null)
|
||||
if (ImGui.IsMouseDoubleClicked(0) && SelectedDirectory.Equals(Dir))
|
||||
{
|
||||
SelectedFile = null;
|
||||
selected = null;
|
||||
CurrentFolder = dir;
|
||||
SelectedDirectory = null;
|
||||
Selected = null;
|
||||
CurrentFolder = Dir;
|
||||
}
|
||||
|
||||
ImGui.PopStyleColor();
|
||||
|
@ -108,20 +108,59 @@ namespace ImGuiNET
|
|||
|
||||
if (ImGui.Button("Cancel", new Vector2(Values.ButtonWidth, Values.ButtonHeight)))
|
||||
{
|
||||
result = false;
|
||||
return DialogResult.Cancel;
|
||||
}
|
||||
|
||||
if (SelectedFile != null)
|
||||
if (SelectedDirectory != null)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Open", new Vector2(Values.ButtonWidth, Values.ButtonHeight)))
|
||||
{
|
||||
result = true;
|
||||
selected = SelectedFile;
|
||||
Selected = SelectedDirectory;
|
||||
|
||||
return DialogResult.OK;
|
||||
}
|
||||
else if(ReturnOnSelection)
|
||||
{
|
||||
Selected = SelectedDirectory;
|
||||
|
||||
return DialogResult.OK;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return DialogResult.None;
|
||||
}
|
||||
|
||||
public DialogResult GetFolder(ref string CurrentPath)
|
||||
{
|
||||
ImGui.SetNextWindowSize(new Vector2(500, 500), Condition.FirstUseEver);
|
||||
if (ImGui.BeginPopupModal("OpenFolder", WindowFlags.NoResize))
|
||||
{
|
||||
try
|
||||
{
|
||||
string Output = CurrentPath;
|
||||
DialogResult DialogResult = Draw(ref Output, false);
|
||||
|
||||
if (DialogResult == DialogResult.OK)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Output))
|
||||
{
|
||||
return DialogResult.None;
|
||||
}
|
||||
}
|
||||
|
||||
if(DialogResult!= DialogResult.None)
|
||||
ImGui.CloseCurrentPopup();
|
||||
|
||||
return DialogResult;
|
||||
}
|
||||
finally
|
||||
{
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
return DialogResult.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,102 +1,101 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ImGuiNET;
|
||||
using System.Numerics;
|
||||
using ImGuiNET;
|
||||
using NanoJpeg;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.UI.Widgets
|
||||
{
|
||||
class GameList
|
||||
{
|
||||
static List<GameItem> GameItems = new List<GameItem>();
|
||||
static GameItem SelectedGame;
|
||||
static bool OpenFolderPicker;
|
||||
static FolderPicker FolderPicker;
|
||||
static string CurrentPath;
|
||||
static bool OpenFolderPicker;
|
||||
static string GameDirectory;
|
||||
static List<GameItem> GameItems;
|
||||
static GameItem SelectedGame;
|
||||
static FolderPicker FolderPicker;
|
||||
|
||||
static GameList()
|
||||
{
|
||||
Refresh(Config.DefaultGameDirectory);
|
||||
FolderPicker = FolderPicker.GetFolderPicker("FolderDialog", Config.DefaultGameDirectory);
|
||||
GameDirectory = Config.DefaultGameDirectory;
|
||||
FolderPicker = FolderPicker.GetFolderPicker("FolderDialog", Config.DefaultGameDirectory);
|
||||
|
||||
Refresh(GameDirectory);
|
||||
}
|
||||
|
||||
public unsafe static void Refresh(string Path)
|
||||
{
|
||||
GameItems = new List<GameItem>();
|
||||
|
||||
foreach (string entry in Directory.EnumerateFileSystemEntries(Path))
|
||||
{
|
||||
if (File.Exists(entry))
|
||||
{
|
||||
string Extension = System.IO.Path.GetExtension(entry).ToLower();
|
||||
|
||||
if (Extension == ".nro" || Extension == ".nso")
|
||||
{
|
||||
GameItem GameItem = new GameItem(entry);
|
||||
|
||||
if (GameItem.IsNro && GameItem.HasIcon)
|
||||
{
|
||||
GameItem.TextureID = GL.GenTexture();
|
||||
|
||||
GL.BindTexture(TextureTarget.Texture2D, GameItem.TextureID);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
|
||||
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
|
||||
|
||||
NanoJpeg.NJImage image = new NJImage();
|
||||
image.Decode(GameItem.GetIconData());
|
||||
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, image.Width, image.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgb,
|
||||
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, image.Width, image.Height, 0, PixelFormat.Rgb,
|
||||
PixelType.UnsignedByte, new IntPtr(image.Image));
|
||||
image.Dispose();
|
||||
GL.BindTexture(TextureTarget.Texture2D, 0);
|
||||
}
|
||||
|
||||
GameItems.Add(GameItem);
|
||||
}
|
||||
}
|
||||
else if (Directory.Exists(Path))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe static void DrawList()
|
||||
public unsafe static Tuple<bool,string> DrawList()
|
||||
{
|
||||
uint id = 100;
|
||||
|
||||
if (ImGui.Button("Refresh GameList"))
|
||||
Refresh(Config.DefaultGameDirectory);
|
||||
|
||||
ImGui.SameLine();
|
||||
if(ImGui.Button("Select Game Directory"))
|
||||
{
|
||||
OpenFolderPicker = true;
|
||||
}
|
||||
|
||||
if (OpenFolderPicker)
|
||||
ImGui.OpenPopup("OpenFolder");
|
||||
|
||||
ImGui.SetNextWindowSize(new Vector2(500, 500), Condition.FirstUseEver);
|
||||
if (ImGui.BeginPopupModal("OpenFolder", WindowFlags.NoResize))
|
||||
DialogResult DialogResult = FolderPicker.GetFolder(ref GameDirectory);
|
||||
if (DialogResult == DialogResult.OK)
|
||||
{
|
||||
string output = CurrentPath;
|
||||
if (FolderPicker.Draw(ref output, false))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(output))
|
||||
{
|
||||
Config.DefaultGameDirectory = output;
|
||||
Refresh(output);
|
||||
}
|
||||
ImGui.CloseCurrentPopup();
|
||||
OpenFolderPicker = false;
|
||||
}
|
||||
ImGui.EndPopup();
|
||||
Config.DefaultGameDirectory = GameDirectory;
|
||||
Refresh(GameDirectory);
|
||||
}
|
||||
|
||||
if (DialogResult != DialogResult.None)
|
||||
OpenFolderPicker = false;
|
||||
|
||||
if (ImGui.BeginChildFrame(20, ImGui.GetContentRegionAvailable(), WindowFlags.AlwaysAutoResize))
|
||||
{
|
||||
foreach (GameItem GameItem in GameItems)
|
||||
{
|
||||
id++;
|
||||
|
||||
if (GameItem == SelectedGame)
|
||||
ImGui.PushStyleColor(ColorTarget.FrameBg, Values.Color.Yellow);
|
||||
|
||||
if (ImGui.BeginChildFrame(id, new Vector2(ImGui.GetContentRegionAvailableWidth(), 60)
|
||||
, WindowFlags.AlwaysAutoResize))
|
||||
{
|
||||
|
@ -113,45 +112,52 @@ namespace Ryujinx.UI.Widgets
|
|||
ImGui.Text(Path.GetFileName(GameItem.Path));
|
||||
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGuiNative.igBeginGroup();
|
||||
if (GameItem.IsNro)
|
||||
if (GameItem.IsNro)
|
||||
{
|
||||
if (GameItem.Nro.ControlArchive != null)
|
||||
{
|
||||
if (GameItem.Nro.ControlArchive != null)
|
||||
{
|
||||
ImGui.Text(GameItem.Nro.ControlArchive.LanguageEntries[0].AplicationName);
|
||||
ImGui.Text(GameItem.Nro.ControlArchive.LanguageEntries[0].DeveloperName);
|
||||
}
|
||||
|
||||
ImGui.Text(GameItem.Nro.ControlArchive.LanguageEntries[0].AplicationName);
|
||||
ImGui.Text(GameItem.Nro.ControlArchive.LanguageEntries[0].DeveloperName);
|
||||
}
|
||||
|
||||
}
|
||||
ImGuiNative.igEndGroup();
|
||||
|
||||
if (GameItem == SelectedGame)
|
||||
ImGui.PopStyleColor();
|
||||
|
||||
if (ImGui.IsMouseDoubleClicked(0) && ImGui.IsItemHovered(HoveredFlags.AllowWhenOverlapped) && GameItem == SelectedGame)
|
||||
{
|
||||
|
||||
return new Tuple<bool, string>(true, GameItem.Path);
|
||||
}
|
||||
else if (ImGui.IsMouseClicked(0) && ImGui.IsItemHovered(HoveredFlags.AllowWhenOverlapped | HoveredFlags.RootAndChildWindows))
|
||||
{
|
||||
SelectedGame = GameItem;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndChildFrame();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndChildFrame();
|
||||
}
|
||||
|
||||
return new Tuple<bool, string>(false,string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
class GameItem
|
||||
{
|
||||
public AppletType AppletType;
|
||||
public string Path;
|
||||
public Nro Nro;
|
||||
public bool IsNro;
|
||||
public AppletType AppletType { get; set; }
|
||||
public Nro Nro { get; set; }
|
||||
public string Path { get; set; }
|
||||
public int TextureID { get; set; }
|
||||
|
||||
public bool IsNro => (System.IO.Path.GetExtension(Path) == ".nro");
|
||||
public bool HasIcon => Nro?.IconData != null;
|
||||
public int TextureID;
|
||||
|
||||
public GameItem(string Path)
|
||||
{
|
||||
|
@ -163,22 +169,12 @@ namespace Ryujinx.UI.Widgets
|
|||
FileInfo Package = new FileInfo(Path);
|
||||
if (Package.Extension.ToLower() == ".nro")
|
||||
{
|
||||
IsNro = true;
|
||||
Nro = new Nro(File.Open(Path, FileMode.Open), new FileInfo(Path).Name);
|
||||
}
|
||||
}
|
||||
else
|
||||
AppletType = AppletType.Cartridge;
|
||||
}
|
||||
|
||||
public Bitmap GetBitmap()
|
||||
{
|
||||
if (IsNro)
|
||||
{
|
||||
return new Bitmap(new Bitmap(new MemoryStream(Nro.IconData)),new Size(50,50));
|
||||
}
|
||||
else return null;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] GetIconData()
|
||||
{
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace Ryujinx.UI
|
|||
{
|
||||
case Page.PackageLoader:
|
||||
string output = CurrentPath;
|
||||
if (FileDialog.Draw(ref output, false))
|
||||
if (FileDialog.Draw(ref output, false) == DialogResult.OK)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(output))
|
||||
{
|
||||
|
@ -61,7 +61,11 @@ namespace Ryujinx.UI
|
|||
Widgets.ConfigurationWidget.Draw();
|
||||
break;
|
||||
case Page.GameList:
|
||||
Widgets.GameList.DrawList();
|
||||
var SelectedPath = Widgets.GameList.DrawList();
|
||||
if (SelectedPath.Item1)
|
||||
{
|
||||
LoadPackage(SelectedPath.Item2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
ImGui.EndChildFrame();
|
||||
|
|
|
@ -1,43 +1,49 @@
|
|||
using System;
|
||||
using ImGuiNET;
|
||||
using System.Numerics;
|
||||
using Ryujinx.HLE.Input;
|
||||
using ImGuiNET;
|
||||
using OpenTK.Input;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
|
||||
namespace Ryujinx.UI.Widgets
|
||||
{
|
||||
public partial class ConfigurationWidget
|
||||
{
|
||||
static bool[] Toggles = new bool[50];
|
||||
static float ContentWidth;
|
||||
static bool[] Toggles = new bool[50];
|
||||
|
||||
static float ContentWidth;
|
||||
static Vector2 GroupSize;
|
||||
static Key pressedKey;
|
||||
static bool RequestPopup = false;
|
||||
static Key pressedKey;
|
||||
static bool RequestPopup;
|
||||
|
||||
public static void DrawInputPage()
|
||||
{
|
||||
Vector2 AvailableSpace = ImGui.GetContentRegionAvailable();
|
||||
|
||||
GroupSize = new Vector2(AvailableSpace.X / 2, AvailableSpace.Y / 3);
|
||||
|
||||
if (ImGui.BeginChildFrame(11, GroupSize, WindowFlags.AlwaysAutoResize))
|
||||
{
|
||||
ContentWidth = (ImGui.GetContentRegionAvailableWidth() - 10) / 2;
|
||||
GroupSize = ImGui.GetContentRegionMax();
|
||||
GroupSize = ImGui.GetContentRegionMax();
|
||||
|
||||
DrawLeftAnalog();
|
||||
|
||||
ImGui.EndChildFrame();
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.BeginChildFrame(12, GroupSize, WindowFlags.AlwaysAutoResize))
|
||||
{
|
||||
DrawRightAnalog();
|
||||
|
||||
ImGui.EndChildFrame();
|
||||
}
|
||||
|
||||
if (ImGui.BeginChildFrame(13, GroupSize, WindowFlags.AlwaysAutoResize))
|
||||
{
|
||||
DrawDpad();
|
||||
|
||||
ImGui.EndChildFrame();
|
||||
}
|
||||
|
||||
|
@ -45,12 +51,14 @@ namespace Ryujinx.UI.Widgets
|
|||
if (ImGui.BeginChildFrame(14, GroupSize, WindowFlags.AlwaysAutoResize))
|
||||
{
|
||||
DrawActionKeys();
|
||||
|
||||
ImGui.EndChildFrame();
|
||||
}
|
||||
|
||||
if (ImGui.BeginChildFrame(15, GroupSize, WindowFlags.AlwaysAutoResize))
|
||||
{
|
||||
DrawTriggers();
|
||||
|
||||
ImGui.EndChildFrame();
|
||||
}
|
||||
|
||||
|
@ -58,6 +66,7 @@ namespace Ryujinx.UI.Widgets
|
|||
if (ImGui.BeginChildFrame(16, GroupSize, WindowFlags.AlwaysAutoResize))
|
||||
{
|
||||
DrawExtras();
|
||||
|
||||
ImGui.EndChildFrame();
|
||||
}
|
||||
|
||||
|
@ -73,8 +82,10 @@ namespace Ryujinx.UI.Widgets
|
|||
| WindowFlags.NoResize))
|
||||
{
|
||||
ImGui.Text("Please enter a key");
|
||||
|
||||
if (!RequestPopup)
|
||||
ImGui.CloseCurrentPopup();
|
||||
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
}
|
||||
|
@ -87,11 +98,13 @@ namespace Ryujinx.UI.Widgets
|
|||
ImGuiNative.igBeginGroup();
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Up");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Left.StickUp).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[0] = true;
|
||||
}
|
||||
|
||||
if (Toggles[0])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -100,16 +113,19 @@ namespace Ryujinx.UI.Widgets
|
|||
Toggles[0] = false;
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiNative.igEndGroup();
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Down");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Left.StickDown).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[1] = true;
|
||||
}
|
||||
|
||||
if (Toggles[1])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -118,15 +134,18 @@ namespace Ryujinx.UI.Widgets
|
|||
Toggles[1] = false;
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiNative.igEndGroup();
|
||||
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Left");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Left.StickLeft).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[2] = true;
|
||||
}
|
||||
|
||||
if (Toggles[2])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -140,11 +159,13 @@ namespace Ryujinx.UI.Widgets
|
|||
ImGui.SameLine();
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Right");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Left.StickRight).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[3] = true;
|
||||
}
|
||||
|
||||
if (Toggles[3])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -167,16 +188,19 @@ namespace Ryujinx.UI.Widgets
|
|||
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Up");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Right.StickUp).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[4] = true;
|
||||
}
|
||||
|
||||
if (Toggles[4])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
{
|
||||
CurrentJoyConLayout.Right.StickUp = (int)pressedKey;
|
||||
|
||||
Toggles[4] = false;
|
||||
}
|
||||
}
|
||||
|
@ -185,11 +209,13 @@ namespace Ryujinx.UI.Widgets
|
|||
ImGui.SameLine();
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Down");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Right.StickDown).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[5] = true;
|
||||
}
|
||||
|
||||
if (Toggles[5])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -202,11 +228,13 @@ namespace Ryujinx.UI.Widgets
|
|||
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Left");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Right.StickLeft).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[6] = true;
|
||||
}
|
||||
|
||||
if (Toggles[6])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -220,11 +248,13 @@ namespace Ryujinx.UI.Widgets
|
|||
ImGui.SameLine();
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Right");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Right.StickRight).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[7] = true;
|
||||
}
|
||||
|
||||
if (Toggles[7])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -246,11 +276,13 @@ namespace Ryujinx.UI.Widgets
|
|||
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Up");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Left.DPadUp).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[8] = true;
|
||||
}
|
||||
|
||||
if (Toggles[8])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -264,11 +296,13 @@ namespace Ryujinx.UI.Widgets
|
|||
ImGui.SameLine();
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Down");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Left.DPadDown).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[9] = true;
|
||||
}
|
||||
|
||||
if (Toggles[9])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -281,11 +315,13 @@ namespace Ryujinx.UI.Widgets
|
|||
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Left");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Left.DPadLeft).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[10] = true;
|
||||
}
|
||||
|
||||
if (Toggles[10])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -299,11 +335,13 @@ namespace Ryujinx.UI.Widgets
|
|||
ImGui.SameLine();
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Right");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Left.DPadRight).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[11] = true;
|
||||
}
|
||||
|
||||
if (Toggles[11])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -325,11 +363,13 @@ namespace Ryujinx.UI.Widgets
|
|||
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("A");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Right.ButtonA).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[12] = true;
|
||||
}
|
||||
|
||||
if (Toggles[12])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -343,11 +383,13 @@ namespace Ryujinx.UI.Widgets
|
|||
ImGui.SameLine();
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("B");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Right.ButtonB).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[13] = true;
|
||||
}
|
||||
|
||||
if (Toggles[13])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -360,11 +402,13 @@ namespace Ryujinx.UI.Widgets
|
|||
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("X");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Right.ButtonX).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[14] = true;
|
||||
}
|
||||
|
||||
if (Toggles[14])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -378,11 +422,13 @@ namespace Ryujinx.UI.Widgets
|
|||
ImGui.SameLine();
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Y");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Right.ButtonY).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[15] = true;
|
||||
}
|
||||
|
||||
if (Toggles[15])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -391,6 +437,7 @@ namespace Ryujinx.UI.Widgets
|
|||
Toggles[15] = false;
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiNative.igEndGroup();
|
||||
|
||||
ImGuiNative.igEndGroup();
|
||||
|
@ -405,11 +452,13 @@ namespace Ryujinx.UI.Widgets
|
|||
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("L");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Left.ButtonL).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[17] = true;
|
||||
}
|
||||
|
||||
if (Toggles[17])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -418,16 +467,19 @@ namespace Ryujinx.UI.Widgets
|
|||
Toggles[17] = false;
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiNative.igEndGroup();
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("R");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Right.ButtonR).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[16] = true;
|
||||
}
|
||||
|
||||
if (Toggles[16])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -440,11 +492,13 @@ namespace Ryujinx.UI.Widgets
|
|||
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("ZL");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Left.ButtonZL).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[19] = true;
|
||||
}
|
||||
|
||||
if (Toggles[19])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -458,11 +512,13 @@ namespace Ryujinx.UI.Widgets
|
|||
ImGui.SameLine();
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("ZR");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Right.ButtonZR).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[18] = true;
|
||||
}
|
||||
|
||||
if (Toggles[18])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -481,13 +537,16 @@ namespace Ryujinx.UI.Widgets
|
|||
//Draw Extra
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("Extra Keys");
|
||||
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("-");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Left.ButtonMinus).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[20] = true;
|
||||
}
|
||||
|
||||
if (Toggles[20])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -500,11 +559,13 @@ namespace Ryujinx.UI.Widgets
|
|||
|
||||
ImGuiNative.igBeginGroup();
|
||||
ImGui.Text("+");
|
||||
|
||||
if (ImGui.Button(((Key)CurrentJoyConLayout.Right.ButtonPlus).ToString(),
|
||||
new Vector2(ContentWidth, 50)))
|
||||
{
|
||||
Toggles[21] = true;
|
||||
}
|
||||
|
||||
if (Toggles[21])
|
||||
{
|
||||
if (GetKey(ref pressedKey))
|
||||
|
@ -521,11 +582,11 @@ namespace Ryujinx.UI.Widgets
|
|||
static bool GetKey(ref Key pressedKey)
|
||||
{
|
||||
IO IO = ImGui.GetIO();
|
||||
foreach (Key key in Enum.GetValues(typeof(Key)))
|
||||
foreach (Key Key in Enum.GetValues(typeof(Key)))
|
||||
{
|
||||
if (IO.KeysDown[(int)key])
|
||||
if (IO.KeysDown[(int)Key])
|
||||
{
|
||||
pressedKey = key;
|
||||
pressedKey = Key;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using ImGuiNET;
|
||||
using ImGuiNET;
|
||||
namespace Ryujinx.UI
|
||||
{
|
||||
partial class EmulationWindow
|
||||
|
@ -8,6 +7,7 @@ namespace Ryujinx.UI
|
|||
{
|
||||
ImGui.SetNextWindowPos(System.Numerics.Vector2.Zero, Condition.Always,
|
||||
System.Numerics.Vector2.Zero);
|
||||
|
||||
ImGui.SetNextWindowSize(new System.Numerics.Vector2(Width, Height), Condition.Always);
|
||||
if (ImGui.BeginWindow("PauseWindow", ref showMainUI, WindowFlags.NoTitleBar
|
||||
| WindowFlags.NoMove | WindowFlags.AlwaysAutoResize))
|
||||
|
@ -51,13 +51,14 @@ namespace Ryujinx.UI
|
|||
Values.ButtonHeight)))
|
||||
{
|
||||
ShowPauseUI = false;
|
||||
EmulationController.Resume();
|
||||
EmulationController.ShutDown();
|
||||
ShowMainUI = true;
|
||||
}
|
||||
|
||||
break;
|
||||
case Page.Configuration:
|
||||
Widgets.ConfigurationWidget.Draw();
|
||||
|
||||
break;
|
||||
}
|
||||
ImGui.EndChildFrame();
|
||||
|
|
|
@ -1,39 +1,46 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ImGuiNET;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using ImGuiNET;
|
||||
using OpenTK.Input;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.UI
|
||||
{
|
||||
class WindowHelper : GameWindow
|
||||
{
|
||||
protected float _deltaTime;
|
||||
bool IsWindowOpened = false;
|
||||
int s_fontTexture;
|
||||
float _wheelPosition;
|
||||
protected float DeltaTime;
|
||||
protected GraphicsContext MainContext;
|
||||
protected GraphicsContext UIContext;
|
||||
protected bool UIActive;
|
||||
|
||||
public WindowHelper(string title) : base(1280, 720, GraphicsMode.Default, title, GameWindowFlags.Default
|
||||
private bool IsWindowOpened = false;
|
||||
private int FontTexture;
|
||||
private float WheelPosition;
|
||||
|
||||
protected KeyboardState? Keyboard = null;
|
||||
|
||||
protected MouseState? Mouse = null;
|
||||
|
||||
public WindowHelper(string Title) : base(1280, 720, GraphicsMode.Default, Title, GameWindowFlags.Default
|
||||
, DisplayDevice.Default, 3, 3, GraphicsContextFlags.ForwardCompatible)
|
||||
{
|
||||
Title = title;
|
||||
base.Title = Title;
|
||||
|
||||
IsWindowOpened = true;
|
||||
|
||||
Location = new Point(
|
||||
(DisplayDevice.Default.Width / 2) - (Width / 2),
|
||||
(DisplayDevice.Default.Height / 2) - (Height / 2));
|
||||
|
||||
MainContext = (GraphicsContext)Context;
|
||||
MainContext = new GraphicsContext(GraphicsMode.Default,
|
||||
WindowInfo, 3, 3, GraphicsContextFlags.ForwardCompatible);
|
||||
|
||||
UIContext = new GraphicsContext(GraphicsMode.Default,
|
||||
WindowInfo,4,5,GraphicsContextFlags.ForwardCompatible);
|
||||
WindowInfo, 3, 3, GraphicsContextFlags.ForwardCompatible);
|
||||
|
||||
UIContext.MakeCurrent(WindowInfo);
|
||||
|
||||
UIActive = true;
|
||||
}
|
||||
|
||||
|
@ -45,35 +52,39 @@ namespace Ryujinx.UI
|
|||
public void StartFrame()
|
||||
{
|
||||
UIContext.MakeCurrent(WindowInfo);
|
||||
IO io = ImGui.GetIO();
|
||||
io.DisplaySize = new System.Numerics.Vector2(Width, Height);
|
||||
io.DisplayFramebufferScale = new System.Numerics.Vector2(Values.CurrentWindowScale);
|
||||
io.DeltaTime = _deltaTime;
|
||||
|
||||
IO IO = ImGui.GetIO();
|
||||
IO.DisplaySize = new System.Numerics.Vector2(Width, Height);
|
||||
IO.DisplayFramebufferScale = new System.Numerics.Vector2(Values.CurrentWindowScale);
|
||||
IO.DeltaTime = DeltaTime;
|
||||
|
||||
ImGui.NewFrame();
|
||||
HandleInput(io);
|
||||
|
||||
HandleInput(IO);
|
||||
}
|
||||
|
||||
public unsafe void EndFrame()
|
||||
{
|
||||
ImGui.Render();
|
||||
|
||||
DrawData* data = ImGui.GetDrawData();
|
||||
RenderImDrawData(data);
|
||||
|
||||
MainContext.MakeCurrent(WindowInfo);
|
||||
MainContext?.MakeCurrent(WindowInfo);
|
||||
}
|
||||
|
||||
protected unsafe void PrepareTexture()
|
||||
{
|
||||
ImGui.GetIO().FontAtlas.AddDefaultFont();
|
||||
|
||||
IO io = ImGui.GetIO();
|
||||
IO IO = ImGui.GetIO();
|
||||
|
||||
// Build texture atlas
|
||||
FontTextureData texData = io.FontAtlas.GetTexDataAsAlpha8();
|
||||
FontTextureData texData = IO.FontAtlas.GetTexDataAsAlpha8();
|
||||
|
||||
// Create OpenGL texture
|
||||
s_fontTexture = GL.GenTexture();
|
||||
GL.BindTexture(TextureTarget.Texture2D, s_fontTexture);
|
||||
FontTexture = GL.GenTexture();
|
||||
GL.BindTexture(TextureTarget.Texture2D, FontTexture);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
|
||||
GL.TexImage2D(
|
||||
|
@ -88,11 +99,11 @@ namespace Ryujinx.UI
|
|||
new IntPtr(texData.Pixels));
|
||||
|
||||
// Store the texture identifier in the ImFontAtlas substructure.
|
||||
io.FontAtlas.SetTexID(s_fontTexture);
|
||||
IO.FontAtlas.SetTexID(FontTexture);
|
||||
|
||||
// Cleanup (don't clear the input data if you want to append new fonts later)
|
||||
//io.Fonts->ClearInputData();
|
||||
io.FontAtlas.ClearTexData();
|
||||
IO.FontAtlas.ClearTexData();
|
||||
GL.BindTexture(TextureTarget.Texture2D, 0);
|
||||
}
|
||||
|
||||
|
@ -101,69 +112,79 @@ namespace Ryujinx.UI
|
|||
PrepareTexture();
|
||||
}
|
||||
|
||||
unsafe void HandleInput(IO io)
|
||||
unsafe void HandleInput(IO IO)
|
||||
{
|
||||
MouseState cursorState = Mouse.GetCursorState();
|
||||
MouseState mouseState = Mouse.GetState();
|
||||
KeyboardState KeyboardState = default(KeyboardState);
|
||||
if (Keyboard != null)
|
||||
if (Keyboard.HasValue)
|
||||
KeyboardState = Keyboard.Value;
|
||||
|
||||
MouseState MouseState = default(MouseState);
|
||||
if (Mouse != null)
|
||||
if (Mouse.HasValue)
|
||||
MouseState = Mouse.Value;
|
||||
|
||||
if (Focused)
|
||||
{
|
||||
Point windowPoint = PointToClient(new Point(cursorState.X, cursorState.Y));
|
||||
io.MousePosition = new System.Numerics.Vector2(windowPoint.X / io.DisplayFramebufferScale.X,
|
||||
windowPoint.Y / io.DisplayFramebufferScale.Y);
|
||||
|
||||
foreach (Key key in Enum.GetValues(typeof(Key)))
|
||||
if (Mouse.HasValue)
|
||||
{
|
||||
io.KeysDown[(int)key] = Keyboard[key];
|
||||
if (Keyboard[key])
|
||||
continue;
|
||||
ImGuiNative.igGetIO()->KeyAlt = (byte)((Keyboard[Key.AltLeft]
|
||||
|| Keyboard[Key.AltRight]) ? 1 : 0);
|
||||
ImGuiNative.igGetIO()->KeyCtrl = (byte)((Keyboard[Key.ControlLeft]
|
||||
|| Keyboard[Key.ControlRight]) ? 1 : 0);
|
||||
ImGuiNative.igGetIO()->KeyShift = (byte)((Keyboard[Key.ShiftLeft]
|
||||
|| Keyboard[Key.ShiftRight]) ? 1 : 0);
|
||||
ImGuiNative.igGetIO()->KeySuper = (byte)((Keyboard[Key.WinLeft]
|
||||
|| Keyboard[Key.WinRight]) ? 1 : 0);
|
||||
Point WindowPoint = new Point(MouseState.X, MouseState.Y);
|
||||
IO.MousePosition = new System.Numerics.Vector2(WindowPoint.X,
|
||||
WindowPoint.Y);
|
||||
}
|
||||
|
||||
if (this.Keyboard.HasValue)
|
||||
foreach (Key Key in Enum.GetValues(typeof(Key)))
|
||||
{
|
||||
IO.KeysDown[(int)Key] = KeyboardState[Key];
|
||||
|
||||
if (KeyboardState[Key])
|
||||
continue;
|
||||
ImGuiNative.igGetIO()->KeyAlt = (byte)((KeyboardState[Key.AltLeft]
|
||||
|| KeyboardState[Key.AltRight]) ? 1 : 0);
|
||||
ImGuiNative.igGetIO()->KeyCtrl = (byte)((KeyboardState[Key.ControlLeft]
|
||||
|| KeyboardState[Key.ControlRight]) ? 1 : 0);
|
||||
ImGuiNative.igGetIO()->KeyShift = (byte)((KeyboardState[Key.ShiftLeft]
|
||||
|| KeyboardState[Key.ShiftRight]) ? 1 : 0);
|
||||
ImGuiNative.igGetIO()->KeySuper = (byte)((KeyboardState[Key.WinLeft]
|
||||
|| KeyboardState[Key.WinRight]) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
io.MousePosition = new System.Numerics.Vector2(-1f, -1f);
|
||||
IO.MousePosition = new System.Numerics.Vector2(-1f, -1f);
|
||||
for (int i = 0; i <= 512; i++)
|
||||
{
|
||||
io.KeysDown[i] = false;
|
||||
IO.KeysDown[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
io.MouseDown[0] = mouseState.LeftButton == ButtonState.Pressed;
|
||||
io.MouseDown[1] = mouseState.RightButton == ButtonState.Pressed;
|
||||
io.MouseDown[2] = mouseState.MiddleButton == ButtonState.Pressed;
|
||||
if (Mouse.HasValue)
|
||||
{
|
||||
IO.MouseDown[0] = MouseState.LeftButton == ButtonState.Pressed;
|
||||
IO.MouseDown[1] = MouseState.RightButton == ButtonState.Pressed;
|
||||
IO.MouseDown[2] = MouseState.MiddleButton == ButtonState.Pressed;
|
||||
|
||||
float newWheelPos = mouseState.WheelPrecise;
|
||||
float delta = newWheelPos - _wheelPosition;
|
||||
_wheelPosition = newWheelPos;
|
||||
io.MouseWheel = delta;
|
||||
float NewWheelPos = MouseState.WheelPrecise;
|
||||
float Delta = NewWheelPos - WheelPosition;
|
||||
WheelPosition = NewWheelPos;
|
||||
IO.MouseWheel = Delta;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void RenderImDrawData(DrawData* draw_data)
|
||||
private unsafe void RenderImDrawData(DrawData* DrawData)
|
||||
{
|
||||
// Rendering
|
||||
int display_w, display_h;
|
||||
display_w = Width;
|
||||
display_h = Height;
|
||||
|
||||
Vector4 clear_color = new Vector4(114f / 255f, 144f / 255f, 154f / 255f, 1.0f);
|
||||
GL.Viewport(0, 0, display_w, display_h);
|
||||
GL.ClearColor(clear_color.X, clear_color.Y, clear_color.Z, clear_color.W);
|
||||
Vector4 ClearColor = new Vector4(114f / 255f, 144f / 255f, 154f / 255f, 1.0f);
|
||||
GL.Viewport(0, 0, Width, Height);
|
||||
GL.ClearColor(ClearColor.X, ClearColor.Y, ClearColor.Z, ClearColor.W);
|
||||
GL.Clear(ClearBufferMask.ColorBufferBit);
|
||||
|
||||
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
|
||||
int last_texture;
|
||||
GL.GetInteger(GetPName.TextureBinding2D, out last_texture);
|
||||
GL.GetInteger(GetPName.TextureBinding2D, out int last_texture);
|
||||
GL.PushAttrib(AttribMask.EnableBit | AttribMask.ColorBufferBit | AttribMask.TransformBit);
|
||||
GL.Enable(EnableCap.Blend);
|
||||
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
|
||||
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
||||
GL.Disable(EnableCap.CullFace);
|
||||
GL.Disable(EnableCap.DepthTest);
|
||||
GL.Enable(EnableCap.ScissorTest);
|
||||
|
@ -175,8 +196,8 @@ namespace Ryujinx.UI
|
|||
GL.UseProgram(0);
|
||||
|
||||
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
|
||||
IO io = ImGui.GetIO();
|
||||
ImGui.ScaleClipRects(draw_data, io.DisplayFramebufferScale);
|
||||
IO IO = ImGui.GetIO();
|
||||
ImGui.ScaleClipRects(DrawData, IO.DisplayFramebufferScale);
|
||||
|
||||
// Setup orthographic projection matrix
|
||||
GL.MatrixMode(MatrixMode.Projection);
|
||||
|
@ -184,8 +205,8 @@ namespace Ryujinx.UI
|
|||
GL.LoadIdentity();
|
||||
GL.Ortho(
|
||||
0.0f,
|
||||
io.DisplaySize.X / io.DisplayFramebufferScale.X,
|
||||
io.DisplaySize.Y / io.DisplayFramebufferScale.Y,
|
||||
IO.DisplaySize.X / IO.DisplayFramebufferScale.X,
|
||||
IO.DisplaySize.Y / IO.DisplayFramebufferScale.Y,
|
||||
0.0f,
|
||||
-1.0f,
|
||||
1.0f);
|
||||
|
@ -194,40 +215,37 @@ namespace Ryujinx.UI
|
|||
GL.LoadIdentity();
|
||||
|
||||
// Render command lists
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
for (int n = 0; n < DrawData->CmdListsCount; n++)
|
||||
{
|
||||
NativeDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
byte* vtx_buffer = (byte*)cmd_list->VtxBuffer.Data;
|
||||
ushort* idx_buffer = (ushort*)cmd_list->IdxBuffer.Data;
|
||||
NativeDrawList* CmdList = DrawData->CmdLists[n];
|
||||
byte* VtxBuffer = (byte*)CmdList->VtxBuffer.Data;
|
||||
ushort* IdxBuffer = (ushort*)CmdList->IdxBuffer.Data;
|
||||
|
||||
DrawVert vert0 = *((DrawVert*)vtx_buffer);
|
||||
DrawVert vert1 = *(((DrawVert*)vtx_buffer) + 1);
|
||||
DrawVert vert2 = *(((DrawVert*)vtx_buffer) + 2);
|
||||
GL.VertexPointer(2, VertexPointerType.Float, sizeof(DrawVert), new IntPtr(VtxBuffer + DrawVert.PosOffset));
|
||||
GL.TexCoordPointer(2, TexCoordPointerType.Float, sizeof(DrawVert), new IntPtr(VtxBuffer + DrawVert.UVOffset));
|
||||
GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(DrawVert), new IntPtr(VtxBuffer + DrawVert.ColOffset));
|
||||
|
||||
GL.VertexPointer(2, VertexPointerType.Float, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.PosOffset));
|
||||
GL.TexCoordPointer(2, TexCoordPointerType.Float, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.UVOffset));
|
||||
GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.ColOffset));
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
for (int Cmd = 0; Cmd < CmdList->CmdBuffer.Size; Cmd++)
|
||||
{
|
||||
DrawCmd* pcmd = &(((DrawCmd*)cmd_list->CmdBuffer.Data)[cmd_i]);
|
||||
if (pcmd->UserCallback != IntPtr.Zero)
|
||||
DrawCmd* PCmd = &(((DrawCmd*)CmdList->CmdBuffer.Data)[Cmd]);
|
||||
if (PCmd->UserCallback != IntPtr.Zero)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.BindTexture(TextureTarget.Texture2D, pcmd->TextureId.ToInt32());
|
||||
GL.BindTexture(TextureTarget.Texture2D, PCmd->TextureId.ToInt32());
|
||||
GL.Scissor(
|
||||
(int)pcmd->ClipRect.X,
|
||||
(int)(io.DisplaySize.Y - pcmd->ClipRect.W),
|
||||
(int)(pcmd->ClipRect.Z - pcmd->ClipRect.X),
|
||||
(int)(pcmd->ClipRect.W - pcmd->ClipRect.Y));
|
||||
ushort[] indices = new ushort[pcmd->ElemCount];
|
||||
for (int i = 0; i < indices.Length; i++) { indices[i] = idx_buffer[i]; }
|
||||
GL.DrawElements(PrimitiveType.Triangles, (int)pcmd->ElemCount, DrawElementsType.UnsignedShort, new IntPtr(idx_buffer));
|
||||
(int)PCmd->ClipRect.X,
|
||||
(int)(IO.DisplaySize.Y - PCmd->ClipRect.W),
|
||||
(int)(PCmd->ClipRect.Z - PCmd->ClipRect.X),
|
||||
(int)(PCmd->ClipRect.W - PCmd->ClipRect.Y));
|
||||
ushort[] indices = new ushort[PCmd->ElemCount];
|
||||
for (int i = 0; i < indices.Length; i++)
|
||||
indices[i] = IdxBuffer[i];
|
||||
GL.DrawElements(PrimitiveType.Triangles, (int)PCmd->ElemCount, DrawElementsType.UnsignedShort, new IntPtr(IdxBuffer));
|
||||
}
|
||||
idx_buffer += pcmd->ElemCount;
|
||||
IdxBuffer += PCmd->ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,5 +262,30 @@ namespace Ryujinx.UI
|
|||
|
||||
SwapBuffers();
|
||||
}
|
||||
|
||||
protected override void OnKeyDown(KeyboardKeyEventArgs e)
|
||||
{
|
||||
Keyboard = e.Keyboard;
|
||||
}
|
||||
|
||||
protected override void OnKeyUp(KeyboardKeyEventArgs e)
|
||||
{
|
||||
Keyboard = e.Keyboard;
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseButtonEventArgs e)
|
||||
{
|
||||
Mouse = e.Mouse;
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseButtonEventArgs e)
|
||||
{
|
||||
Mouse = e.Mouse;
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseMoveEventArgs e)
|
||||
{
|
||||
Mouse = e.Mouse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace Ryujinx.UI
|
|||
static void Main(string[] args)
|
||||
{
|
||||
EmulationWindow mainUI = new EmulationWindow();
|
||||
|
||||
mainUI.Run(60.0, 60.0);
|
||||
|
||||
Environment.Exit(0);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ImGui.NET" Version="0.4.5" />
|
||||
<PackageReference Include="OpenTK.NETCore" Version="1.1.2749.6433" />
|
||||
<PackageReference Include="OpenTK.NetStandard" Version="1.0.4" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"profiles": {
|
||||
"Ryujinx": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "\"C:\\Users\\Emmanuel Hansen\\AppData\\Roaming\\RyuFs\\sdmc\\switch\\fruity\\fruity.nro\""
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue