fix native libs
add SdlEvent callback add OpenWindow function
This commit is contained in:
+63
-7
@@ -15,7 +15,14 @@ public class ImGuiInstance
|
|||||||
}
|
}
|
||||||
|
|
||||||
public string Name => _name;
|
public string Name => _name;
|
||||||
|
/// <summary>
|
||||||
|
/// Called whenever ImGui is being rendered. You can use ImGui functions inside here.
|
||||||
|
/// </summary>
|
||||||
public event Action? Layout;
|
public event Action? Layout;
|
||||||
|
/// <summary>
|
||||||
|
/// Called whenever the window is processing an event. Returning false means that the event will not be processed further.
|
||||||
|
/// </summary>
|
||||||
|
public event Func<SDL.Event, bool>? SdlEvent;
|
||||||
|
|
||||||
private string _name;
|
private string _name;
|
||||||
private ConfigEntry<int4> _entry;
|
private ConfigEntry<int4> _entry;
|
||||||
@@ -26,6 +33,14 @@ public class ImGuiInstance
|
|||||||
internal static ConcurrentQueue<ImGuiInstance> newInstances = new();
|
internal static ConcurrentQueue<ImGuiInstance> newInstances = new();
|
||||||
internal static ConcurrentQueue<(string, Action<SDL3Window>)> windowRequests = new();
|
internal static ConcurrentQueue<(string, Action<SDL3Window>)> windowRequests = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to open the window. If it's already open, nothing happens. This function may be expensive to call rapidly.
|
||||||
|
/// </summary>
|
||||||
|
public void OpenWindow()
|
||||||
|
{
|
||||||
|
newInstances.Enqueue(this);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a reference to the SDL3Window inside of a callback.
|
/// Gets a reference to the SDL3Window inside of a callback.
|
||||||
/// The callback will be called inside the SDL3 Thread.
|
/// The callback will be called inside the SDL3 Thread.
|
||||||
@@ -74,7 +89,7 @@ public class ImGuiInstance
|
|||||||
if (IsSDL3Running)
|
if (IsSDL3Running)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_sdl3Thread = new Thread(() => RunSDL3())
|
_sdl3Thread = new Thread(RunSDL3)
|
||||||
{
|
{
|
||||||
Name = $"Resonite ImGui SDL3",
|
Name = $"Resonite ImGui SDL3",
|
||||||
Priority = ThreadPriority.Highest,
|
Priority = ThreadPriority.Highest,
|
||||||
@@ -93,16 +108,21 @@ public class ImGuiInstance
|
|||||||
{
|
{
|
||||||
while (newInstances.TryDequeue(out var request))
|
while (newInstances.TryDequeue(out var request))
|
||||||
{
|
{
|
||||||
|
if (windows.ContainsKey(request.Name)) continue;
|
||||||
|
|
||||||
SDL3Window app = new SDL3Window("ImGuiContext: " + request.Name, request._entry.Value.x, request._entry.Value.y, request._entry.Value.z, request._entry.Value.w);
|
SDL3Window app = new SDL3Window("ImGuiContext: " + request.Name, request._entry.Value.x, request._entry.Value.y, request._entry.Value.z, request._entry.Value.w);
|
||||||
app.WindowRectModified += (rect) => request._entry.Value = rect;
|
app.WindowRectModified += (rect) => request._entry.Value = rect;
|
||||||
// TODO: maybe listen to config changes to resize window
|
// TODO: maybe listen to config changes to resize window
|
||||||
// request._entry.SettingChanged += (_, _) => { };
|
// request._entry.SettingChanged += (_, _) => { };
|
||||||
app.RenderCallback = request.Layout!;
|
app.RenderCallback = request.Layout;
|
||||||
windows[request.Name] = app;
|
app.SdlEventReceived = request.SdlEvent;
|
||||||
var winId = SDL.GetWindowID(app.Window);
|
if (!windows.TryAdd(request.Name, app))
|
||||||
if (!windowsById.TryAdd(winId, app))
|
|
||||||
{
|
{
|
||||||
Plugin.Log.LogError($"Failed to add window with id {(uint) app.Window}, name {request.Name}!");
|
Plugin.Log.LogError($"Failed to add window with name {request.Name}!");
|
||||||
|
}
|
||||||
|
if (!windowsById.TryAdd(app.SdlWindowId, app))
|
||||||
|
{
|
||||||
|
Plugin.Log.LogError($"Failed to add window with id {app.SdlWindowId}, name {request.Name}!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < windowRequests.Count; i++)
|
for (int i = 0; i < windowRequests.Count; i++)
|
||||||
@@ -119,7 +139,6 @@ public class ImGuiInstance
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (SDL.PollEvent(out SDL.Event ev))
|
while (SDL.PollEvent(out SDL.Event ev))
|
||||||
{
|
{
|
||||||
if (windowsById.TryGetValue(ev.Window.WindowID, out var window))
|
if (windowsById.TryGetValue(ev.Window.WindowID, out var window))
|
||||||
@@ -128,10 +147,47 @@ public class ImGuiInstance
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var removed = new HashSet<(string, uint)>();
|
||||||
foreach (var (key, window) in windows)
|
foreach (var (key, window) in windows)
|
||||||
{
|
{
|
||||||
|
if(window.Disposed)
|
||||||
|
{
|
||||||
|
removed.Add((key, window.SdlWindowId));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
window.SetContext();
|
||||||
|
|
||||||
|
if (Plugin.CancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
window.ForceDispose();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.ShouldClose)
|
||||||
|
{
|
||||||
|
removed.Add((key, window.SdlWindowId));
|
||||||
|
window.Dispose();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
window.RunOneFrame();
|
window.RunOneFrame();
|
||||||
}
|
}
|
||||||
|
foreach (var (k, k2) in removed)
|
||||||
|
{
|
||||||
|
var b = windows.Remove(k);
|
||||||
|
var b2 = windowsById.Remove(k2);
|
||||||
|
Plugin.Log.LogDebug($"Removed window {k}, success codes: {b}|{b2}");
|
||||||
|
}
|
||||||
|
if (Plugin.CancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent busy looping when nothing is happening.
|
||||||
|
if (windows.Count == 0)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>2.0.0</Version>
|
<Version>2.1.0</Version>
|
||||||
<Authors>art0007i</Authors>
|
<Authors>art0007i</Authors>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<RepositoryUrl>https://github.com/art0007i/ResoniteImGuiLib</RepositoryUrl>
|
<RepositoryUrl>https://github.com/art0007i/ResoniteImGuiLib</RepositoryUrl>
|
||||||
|
|||||||
+31
-13
@@ -1,5 +1,4 @@
|
|||||||
using CodeGenerationConfig;
|
using Elements.Core;
|
||||||
using Elements.Core;
|
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using SDL3;
|
using SDL3;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -12,12 +11,14 @@ public class SDL3Window : IDisposable
|
|||||||
public readonly IntPtr Device;
|
public readonly IntPtr Device;
|
||||||
public readonly ImGuiSDL3 Platform;
|
public readonly ImGuiSDL3 Platform;
|
||||||
public readonly ImGuiSDL3Renderer Renderer;
|
public readonly ImGuiSDL3Renderer Renderer;
|
||||||
|
public readonly uint SdlWindowId;
|
||||||
internal readonly Queue<SDL.Event> EventQueue = new();
|
internal readonly Queue<SDL.Event> EventQueue = new();
|
||||||
|
internal Action? RenderCallback { get; set; }
|
||||||
|
internal Func<SDL.Event, bool>? SdlEventReceived { get; set; }
|
||||||
public event Action<int4>? WindowRectModified;
|
public event Action<int4>? WindowRectModified;
|
||||||
|
|
||||||
public color? ClearColor = null;
|
public color? ClearColor = null;
|
||||||
|
|
||||||
public Action? RenderCallback { get; set; }
|
|
||||||
|
|
||||||
private readonly Stopwatch _timer = Stopwatch.StartNew();
|
private readonly Stopwatch _timer = Stopwatch.StartNew();
|
||||||
private TimeSpan _time = TimeSpan.Zero;
|
private TimeSpan _time = TimeSpan.Zero;
|
||||||
@@ -57,9 +58,11 @@ public class SDL3Window : IDisposable
|
|||||||
Platform = new ImGuiSDL3(Window, Device);
|
Platform = new ImGuiSDL3(Window, Device);
|
||||||
Renderer = new ImGuiSDL3Renderer(Device);
|
Renderer = new ImGuiSDL3Renderer(Device);
|
||||||
|
|
||||||
|
SdlWindowId = SDL.GetWindowID(Window);
|
||||||
//ImGuiManager.TriggerImGuiRecreated();
|
//ImGuiManager.TriggerImGuiRecreated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Disposed => _disposed;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
~SDL3Window()
|
~SDL3Window()
|
||||||
@@ -68,6 +71,11 @@ public class SDL3Window : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ForceDispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
@@ -102,8 +110,8 @@ public class SDL3Window : IDisposable
|
|||||||
|
|
||||||
if (_imGuiContext != IntPtr.Zero)
|
if (_imGuiContext != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
ImGui.SetCurrentContext(_imGuiContext);
|
ImGui.SetCurrentContext(IntPtr.Zero);
|
||||||
ImGui.DestroyContext();
|
ImGui.DestroyContext(_imGuiContext);
|
||||||
_imGuiContext = IntPtr.Zero;
|
_imGuiContext = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,12 +126,15 @@ public class SDL3Window : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetContext()
|
||||||
|
{
|
||||||
|
ImGui.SetCurrentContext(_imGuiContext);
|
||||||
|
}
|
||||||
|
|
||||||
public void RunOneFrame()
|
public void RunOneFrame()
|
||||||
{
|
{
|
||||||
if (_disposed) return;
|
if (_disposed) return;
|
||||||
|
|
||||||
ImGui.SetCurrentContext(_imGuiContext);
|
|
||||||
|
|
||||||
ImGui.GetIO().DeltaTime = (float) (_timer.Elapsed - _time).TotalSeconds;
|
ImGui.GetIO().DeltaTime = (float) (_timer.Elapsed - _time).TotalSeconds;
|
||||||
_time = _timer.Elapsed;
|
_time = _timer.Elapsed;
|
||||||
|
|
||||||
@@ -136,14 +147,10 @@ public class SDL3Window : IDisposable
|
|||||||
|
|
||||||
Render();
|
Render();
|
||||||
|
|
||||||
if (_shouldClose || Plugin.CancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
ImGui.SetCurrentContext(IntPtr.Zero);
|
ImGui.SetCurrentContext(IntPtr.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _shouldClose;
|
public bool ShouldClose;
|
||||||
|
|
||||||
private void PollEvents()
|
private void PollEvents()
|
||||||
{
|
{
|
||||||
@@ -154,6 +161,17 @@ public class SDL3Window : IDisposable
|
|||||||
|
|
||||||
while (EventQueue.TryDequeue(out var ev))
|
while (EventQueue.TryDequeue(out var ev))
|
||||||
{
|
{
|
||||||
|
var skip = false;
|
||||||
|
foreach (var func in Delegate.EnumerateInvocationList(SdlEventReceived))
|
||||||
|
{
|
||||||
|
if (!func(ev))
|
||||||
|
{
|
||||||
|
skip = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skip) continue;
|
||||||
|
|
||||||
Platform.ProcessEvent(ev);
|
Platform.ProcessEvent(ev);
|
||||||
|
|
||||||
switch ((SDL.EventType) ev.Type)
|
switch ((SDL.EventType) ev.Type)
|
||||||
@@ -168,7 +186,7 @@ public class SDL3Window : IDisposable
|
|||||||
case SDL.EventType.Terminating:
|
case SDL.EventType.Terminating:
|
||||||
case SDL.EventType.WindowCloseRequested:
|
case SDL.EventType.WindowCloseRequested:
|
||||||
case SDL.EventType.Quit:
|
case SDL.EventType.Quit:
|
||||||
_shouldClose = true;
|
ShouldClose = true;
|
||||||
break;
|
break;
|
||||||
case SDL.EventType.WindowResized:
|
case SDL.EventType.WindowResized:
|
||||||
SetupScreenClipRect();
|
SetupScreenClipRect();
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
A [Resonite](https://resonite.com/) library that allows modders to create ImGui windows.
|
A [Resonite](https://resonite.com/) library that allows modders to create ImGui windows.
|
||||||
|
|
||||||
|
Example usage can be found here: https://github.com/art0007i/ImGuiExample
|
||||||
|
|
||||||
## Installation (Manual)
|
## Installation (Manual)
|
||||||
1. Install [BepisLoader](https://github.com/ResoniteModding/BepisLoader) for Resonite.
|
1. Install [BepisLoader](https://github.com/ResoniteModding/BepisLoader) for Resonite.
|
||||||
2. Download the latest release ZIP file (e.g., `art0007i-ResoniteImGuiLib-2.0.0.zip`) from the [Releases](https://github.com/art0007i/ResoniteImGuiLib/releases) page.
|
2. Download the latest release ZIP file (e.g., `art0007i-ResoniteImGuiLib-2.0.0.zip`) from the [Releases](https://github.com/art0007i/ResoniteImGuiLib/releases) page.
|
||||||
|
|||||||
+2
-2
@@ -33,11 +33,11 @@ target = "plugins/ResoniteImGuiLib/"
|
|||||||
|
|
||||||
[[build.copy]]
|
[[build.copy]]
|
||||||
source = "./Plugin/bin/Release/runtimes/linux-x64/native/libcimgui.so"
|
source = "./Plugin/bin/Release/runtimes/linux-x64/native/libcimgui.so"
|
||||||
target = "plugins/ResoniteImGuiLib/native/"
|
target = "plugins/ResoniteImGuiLib/"
|
||||||
|
|
||||||
[[build.copy]]
|
[[build.copy]]
|
||||||
source = "./Plugin/bin/Release/runtimes/win-x64/native/cimgui.dll"
|
source = "./Plugin/bin/Release/runtimes/win-x64/native/cimgui.dll"
|
||||||
target = "plugins/ResoniteImGuiLib/native/"
|
target = "plugins/ResoniteImGuiLib/"
|
||||||
|
|
||||||
[[build.copy]]
|
[[build.copy]]
|
||||||
source = "./CHANGELOG.md"
|
source = "./CHANGELOG.md"
|
||||||
|
|||||||
Reference in New Issue
Block a user