You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
4.2 KiB
121 lines
4.2 KiB
2 years ago
|
using System;
|
||
|
using gaemstone.ECS;
|
||
|
using gaemstone.Flecs;
|
||
|
using ImGuiNET;
|
||
|
using Silk.NET.Input;
|
||
|
using Silk.NET.OpenGL.Extensions.ImGui;
|
||
|
using static gaemstone.Client.Components.InputComponents;
|
||
|
using static gaemstone.Client.Systems.Windowing;
|
||
|
|
||
|
namespace gaemstone.Client.Systems;
|
||
|
|
||
|
[Module]
|
||
|
[DependsOn<gaemstone.Client.Components.InputComponents>]
|
||
|
[DependsOn<gaemstone.Client.Systems.InputManager>]
|
||
|
[DependsOn<gaemstone.Client.Systems.Windowing>]
|
||
|
public class ImGuiManager
|
||
|
{
|
||
|
[Entity, Add<Pipeline.Phase>]
|
||
|
[DependsOn<SystemPhase.OnLoad>]
|
||
|
public struct ImGuiUpdatePhase { }
|
||
|
|
||
|
[Entity, Add<Pipeline.Phase>]
|
||
|
[DependsOn<SystemPhase.OnStore>]
|
||
|
public struct ImGuiRenderPhase { }
|
||
|
|
||
|
[Component, Singleton]
|
||
|
public class ImGuiData
|
||
|
{
|
||
|
public ImGuiController Controller { get; }
|
||
|
internal ImGuiData(ImGuiController controller) => Controller = controller;
|
||
|
}
|
||
|
|
||
|
[System<SystemPhase.OnLoad>]
|
||
|
public unsafe void Initialize(Universe universe, GameWindow window, Canvas canvas,
|
||
|
[Source<Input>] IInputContext inputContext, [Not] ImGuiData _)
|
||
|
=> universe.LookupOrThrow<ImGuiData>().Set(new ImGuiData(
|
||
|
new(canvas.GL, window.Handle, inputContext, () => {
|
||
|
var IO = ImGui.GetIO();
|
||
|
|
||
|
// Do not save a settings or log file.
|
||
|
IO.NativePtr->IniFilename = null;
|
||
|
IO.NativePtr->LogFilename = null;
|
||
|
|
||
|
IO.BackendFlags |= ImGuiBackendFlags.HasMouseCursors
|
||
|
| ImGuiBackendFlags.HasSetMousePos;
|
||
|
IO.ConfigFlags |= ImGuiConfigFlags.NavEnableKeyboard
|
||
|
| ImGuiConfigFlags.NavEnableSetMousePos;
|
||
|
IO.ConfigWindowsResizeFromEdges = true;
|
||
|
|
||
|
// Set up key mappings.
|
||
|
foreach (var imguiKey in Enum.GetValues<ImGuiKey>()) {
|
||
|
var name = imguiKey.ToString();
|
||
|
|
||
|
// Adjust ImGuiKey enum names to match Silk.NET.Input.Key enum.
|
||
|
if (name.StartsWith("_")) name = name.Replace("_", "Number");
|
||
|
if (name.EndsWith("Arrow")) name = name[..^"Arrow".Length];
|
||
|
if (name.EndsWith("Ctrl" )) name = name.Replace("Ctrl", "Control");
|
||
|
|
||
|
if (!name.EndsWith("Bracket")) { // Leave "LeftBracket" and "RightBracket" alone.
|
||
|
if (name.StartsWith("Left" )) name = name["Left" .Length..] + "Left";
|
||
|
if (name.StartsWith("Right")) name = name["Right".Length..] + "Right";
|
||
|
}
|
||
|
|
||
|
if (Enum.TryParse<Key>(name, true, out var silkKey))
|
||
|
IO.KeyMap[(int)imguiKey] = (int)silkKey;
|
||
|
}
|
||
|
})));
|
||
|
|
||
|
[System<SystemPhase.OnLoad>]
|
||
|
public static void UpdateMouse(Universe universe,
|
||
|
[Source<Mouse>] IMouse impl, ImGuiData _)
|
||
|
{
|
||
|
var input = universe.LookupOrThrow<Input>();
|
||
|
var module = universe.LookupOrThrow<ImGuiManager>();
|
||
|
var capturedBy = input.GetTarget<MouseInputCapturedBy>();
|
||
|
var isCaptured = (capturedBy != null);
|
||
|
// If another system has the mouse captured, don't do anything here.
|
||
|
if (isCaptured && (capturedBy != module)) return;
|
||
|
|
||
|
var IO = ImGui.GetIO();
|
||
|
|
||
|
// Set the mouse position if ImGui wants to move it.
|
||
|
if (IO.WantSetMousePos) impl.Position = IO.MousePos;
|
||
|
|
||
|
// Capture the mouse input it is above GUI elements.
|
||
|
if (IO.WantCaptureMouse != isCaptured) {
|
||
|
if (IO.WantCaptureMouse) input.Add <MouseInputCapturedBy>(module);
|
||
|
else input.Remove<MouseInputCapturedBy>(module);
|
||
|
}
|
||
|
|
||
|
var cursor = ImGui.GetMouseCursor();
|
||
|
impl.Cursor.CursorMode = (cursor == ImGuiMouseCursor.None)
|
||
|
? CursorMode.Hidden : CursorMode.Normal;
|
||
|
// TODO: Use additional cursors once Silk.NET supports GLFW 3.4.
|
||
|
impl.Cursor.StandardCursor = cursor switch {
|
||
|
ImGuiMouseCursor.Arrow => StandardCursor.Arrow,
|
||
|
ImGuiMouseCursor.TextInput => StandardCursor.IBeam,
|
||
|
// ImGuiMouseCursor.ResizeAll => StandardCursor.,
|
||
|
ImGuiMouseCursor.ResizeNS => StandardCursor.VResize,
|
||
|
ImGuiMouseCursor.ResizeEW => StandardCursor.HResize,
|
||
|
// ImGuiMouseCursor.ResizeNESW => StandardCursor.,
|
||
|
// ImGuiMouseCursor.ResizeNWSE => StandardCursor.,
|
||
|
ImGuiMouseCursor.Hand => StandardCursor.Hand,
|
||
|
// ImGuiMouseCursor.NotAllowed => StandardCursor.,
|
||
|
_ => StandardCursor.Default,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
[System<ImGuiUpdatePhase>]
|
||
|
public static void Update(TimeSpan delta, ImGuiData imgui)
|
||
|
=> imgui.Controller.Update((float)delta.TotalSeconds);
|
||
|
|
||
|
[System]
|
||
|
public static void ShowDemoWindow(ImGuiData _)
|
||
|
=> ImGui.ShowDemoWindow();
|
||
|
|
||
|
[System<ImGuiRenderPhase>]
|
||
|
public static void Render(ImGuiData imgui)
|
||
|
=> imgui.Controller.Render();
|
||
|
}
|