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.
 
 

212 lines
9.7 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using gaemstone.Client.Utility;
using gaemstone.ECS;
using ImGuiNET;
using Silk.NET.GLFW;
using Silk.NET.Input;
using static gaemstone.Client.Components.InputComponents;
using static gaemstone.Client.Systems.ImGuiManager;
namespace gaemstone.Client.Systems;
[Module]
[DependsOn<gaemstone.Client.Components.InputComponents>]
[DependsOn<gaemstone.Client.Systems.ImGuiManager>]
public class ImGuiInputDebug
{
private bool _isOpen = false;
[System]
public void ShowInputDebugWindow(Universe universe, ImGuiData _)
{
var input = universe.LookupByType<Input>();
if (input == null) return;
if (!ImGuiUtility.UIButtonToggle(1, ForkAwesome.Gamepad, "Input Information", ref _isOpen)) return;
var center = ImGui.GetMainViewport().GetCenter();
ImGui.SetNextWindowPos(center, ImGuiCond.Appearing, new(0.5f, 0.5f));
ImGui.PushFont(ImGui.GetIO().Fonts.Fonts[1]);
if (ImGui.Begin($"{ForkAwesome.Gamepad} Input Information", ref _isOpen,
ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize)) {
ImGui.PushFont(ImGui.GetIO().Fonts.Fonts[0]);
if (universe.LookupByType<Keyboard>() is EntityRef keyboard)
DrawKeyboard(keyboard);
if (universe.LookupByType<Mouse>() is EntityRef mouse) {
ImGui.BeginChild("Mouse Info", new(160, 180), true);
ImGui.Text("Position: " + (Vector2?)mouse.LookupChild("Position")?.GetOrNull<RawValue2D>());
ImGui.Text("Delta: " + (Vector2?)mouse.LookupChild("Delta" )?.GetOrNull<RawValue2D>());
ImGui.Text("Wheel: " + (float?) mouse.LookupChild("Wheel" )?.GetOrNull<RawValue1D>());
ImGui.Spacing();
var buttons = mouse.LookupChild("Buttons")?.GetChildren().ToArray() ?? Array.Empty<EntityRef>();
ImGui.Text("Buttons: " + string.Join(" ", buttons
.Where (button => button.Has<Active>())
.Select(button => $"{button.Name} ({button.GetOrThrow<Active>().Duration.TotalSeconds:f2}s)")));
ImGui.Text(" Pressed: " + string.Join(" ", buttons
.Where (button => button.Has<Activated>())
.Select(button => button.Name)));
ImGui.Text(" Released: " + string.Join(" ", buttons
.Where (button => button.Has<Deactivated>())
.Select(button => button.Name)));
ImGui.EndChild();
}
for (var index = 0; input.LookupChild("Gamepad" + index) is EntityRef gamepad; index++) {
ImGui.SameLine();
ImGui.BeginChild($"{gamepad.Name} Info", new(160, 180), true);
var buttons = gamepad.LookupChild("Buttons")?.GetChildren().ToArray() ?? Array.Empty<EntityRef>();
ImGui.Text("Buttons: " + string.Join(" ", buttons.Where(b => b.Has<Active>())
.Select(b => $"{b.Name} ({b.GetOrThrow<Active>().Duration.TotalSeconds:f2}s)")));
ImGui.Text(" Pressed: " + string.Join(" ", buttons.Where(b => b.Has<Activated>()).Select(b => b.Name)));
ImGui.Text(" Released: " + string.Join(" ", buttons.Where(b => b.Has<Deactivated>()).Select(b => b.Name)));
ImGui.Spacing();
ImGui.Text("Triggers:");
for (var i = 0; gamepad.LookupChild("Trigger" + i) is EntityRef trigger; i++) {
var text = $" {i}: {(float?)trigger.GetOrNull<RawValue1D>() ?? default:f2}";
if (trigger.Has<Activated>()) text += " pressed!";
else if (trigger.Has<Deactivated>()) text += " released!";
else if (trigger.GetOrNull<Active>() is Active active)
text += $" ({active.Duration.TotalSeconds:f2}s)";
ImGui.Text(text);
}
ImGui.Text("Thumbsticks:");
for (var i = 0; gamepad.LookupChild("Thumbstick" + i) is EntityRef thumbstick; i++)
ImGui.Text($" {i}: {(Vector2?)thumbstick.GetOrNull<RawValue2D>() ?? default:f2}");
ImGui.EndChild();
}
ImGui.PopFont();
}
ImGui.PopFont();
ImGui.End();
}
private const float U = 1.00f;
private const float SM = 1.25f;
// Spacing (invisible)
private const float I = -0.50f;
private const float _ = -1.00f;
private const float ER = -1.25f;
// Special
private const float T = -11.00f;
private const float ENT = -11.50f;
private static readonly float[][] KeyboardLayout = {
new[] { U, _, U, U, U, U,I,U, U, U, U,I, U, U, U, U, I,U, U, U },
new[] { U, U, U, U, U, U, U, U, U, U, U, U, U, 2.0f, I,U, U, U,I, U, U, U, U },
new[] { 1.5f, U, U, U, U, U, U, U, U, U, U, U, U, ENT, I,U, U, U,I, U, U, U, T },
new[] { 1.75f, U, U, U, U, U, U, U, U, U, U, U, U, ER, I,_, _, _,I, U, U, U, _ },
new[] { SM, U, U, U, U, U, U, U, U, U, U, U, 2.75f, I,_, U, _,I, U, U, U, T },
new[] { SM, SM, SM, 6.25f, SM, SM, SM, SM, I,U, U, U,I, 2.0f, U, _ },
};
private static readonly Key?[][] KeyboardKeys = {
new Key?[] { Key.Escape, null, Key.F1, Key.F2, Key.F3, Key.F4, null, Key.F5, Key.F6, Key.F7, Key.F8, null, Key.F9, Key.F10, Key.F11, Key.F12, null, Key.PrintScreen, Key.ScrollLock, Key.Pause },
new Key?[] { Key.GraveAccent, Key.Number1, Key.Number2, Key.Number3, Key.Number4, Key.Number5, Key.Number6, Key.Number7, Key.Number8, Key.Number9, Key.Number0, Key.Minus, Key.Equal, Key.Backspace, null, Key.Insert, Key.Home, Key.PageUp, null, Key.NumLock, Key.KeypadDivide, Key.KeypadMultiply, Key.KeypadSubtract },
new Key?[] { Key.Tab, Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P, Key.LeftBracket, Key.RightBracket, Key.Enter, null, Key.Delete, Key.End, Key.PageDown, null, Key.Keypad7, Key.Keypad8, Key.Keypad9, Key.KeypadAdd },
new Key?[] { Key.CapsLock, Key.A, Key.S, Key.D, Key.F, Key.G, Key.H, Key.J, Key.K, Key.L, Key.Semicolon, Key.Apostrophe, Key.BackSlash, null, null, null, null, null, null, Key.Keypad4, Key.Keypad5, Key.Keypad6, null },
new Key?[] { Key.ShiftLeft, Key.World1, Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M, Key.Comma, Key.Period, Key.Slash, Key.ShiftRight, null, null, Key.Up, null, null, Key.Keypad1, Key.Keypad2, Key.Keypad3, Key.KeypadEnter },
new Key?[] { Key.ControlLeft, Key.SuperLeft, Key.AltLeft, Key.Space, Key.AltRight, Key.SuperRight, Key.Menu, Key.ControlRight, null, Key.Left, Key.Down, Key.Right, null, Key.Keypad0, Key.KeypadDecimal, null },
};
private static readonly Dictionary<Key, string> KeyToNameMapping = new() {
[Key.Escape] = "Esc", [Key.PrintScreen] = "Prn\nScr", [Key.ScrollLock] = "Scr\nLck", [Key.Pause] = "Pause",
[Key.F1] = "F1", [Key.F2] = "F2", [Key.F3] = "F3", [Key.F4] = "F4", [Key.F5] = "F5", [Key.F6] = "F6",
[Key.F7] = "F7", [Key.F8] = "F8", [Key.F9] = "F9", [Key.F10] = "F10", [Key.F11] = "F11", [Key.F12] = "F12",
[Key.Tab] = "Tab", [Key.CapsLock] = "Caps\nLock", [Key.Menu] = "Menu",
[Key.Backspace] = "Backspace", [Key.Enter] = "Enter",
[Key.ControlLeft] = "Ctrl", [Key.ControlRight] = "Ctrl",
[Key.ShiftLeft] = "Shift", [Key.ShiftRight] = "Shift",
[Key.AltLeft] = "Alt", [Key.AltRight] = "Alt",
[Key.SuperLeft] = "Super", [Key.SuperRight] = "Super",
[Key.Insert] = "Ins", [Key.Delete] = "Del",
[Key.Home] = "Home", [Key.End] = "End",
[Key.PageUp] = "PgUp", [Key.PageDown] = "PgDn",
[Key.NumLock] = "Num\nLck", [Key.KeypadEnter] = "=",
};
public static void DrawKeyboard(EntityRef keyboard)
{
const float UnitKeySize = 32.0f;
var GLFW = Glfw.GetApi();
var draw = ImGui.GetWindowDrawList();
var offset = ImGui.GetCursorScreenPos();
var current = Vector2.Zero;
foreach (var (widths, keys) in KeyboardLayout.Zip(KeyboardKeys)) {
foreach (var (width, key) in widths.Zip(keys)) {
var active = (key != null) && (keyboard.LookupChild(key.Value.ToString())?.Has<Active>() == true);
var keySize = new Vector2(width, 1.0f);
if (width == T) keySize = new Vector2((-keySize.X - 10), 2.0f);
else if (width < -10) keySize = new Vector2((-keySize.X - 10), 1.0f);
else if (width < 0) { current += new Vector2(-keySize.X * UnitKeySize, 0); continue; }
var label = (key != null) ? KeyToNameMapping.GetValueOrDefault(key.Value)
?? GLFW.GetKeyName((int)key.Value, 0)?.ToUpper() : null;
if (width == ENT) {
DrawButton(draw, label, active,
(offset + current, keySize * UnitKeySize),
(offset + current + new Vector2(0.25f * UnitKeySize, 0), (keySize + new Vector2(-0.25f, 1)) * UnitKeySize));
} else DrawButton(draw, label, active,
(offset + current, keySize * UnitKeySize));
current += new Vector2(keySize.X * UnitKeySize, 0);
}
current = new Vector2(0, current.Y + UnitKeySize);
if (widths == KeyboardLayout[0]) current += new Vector2(0, UnitKeySize / 2);
}
ImGui.Dummy(new Vector2(23, 6.5f) * UnitKeySize);
}
private static void DrawButton(ImDrawListPtr draw, string? label,
bool active, params (Vector2 Pos, Vector2 Size)[] parts)
{
const int Rounding = 3;
var Border = new Vector2(1, 1);
var LabelOffset = new Vector2(7, 3);
var FaceStartOffset = new Vector2(5, 3);
var FaceEndOffset = new Vector2(5, 6);
var BorderColor = Color.FromGrayscale(0.10f);
var LabelColor = Color.FromGrayscale(0.25f);
var OuterKeyColorActive = Color.FromRGB(0.8f, 0.4f, 0.4f);
var OuterKeyColorInactive = Color.FromGrayscale(0.8f);
var InnerKeyColorActive = Color.FromRGB(1.0f, 0.0f, 0.0f);
var InnerKeyColorInactive = Color.FromGrayscale(1.0f);
var outerKeyColor = active ? OuterKeyColorActive : OuterKeyColorInactive;
var innerKeyColor = active ? InnerKeyColorActive : InnerKeyColorInactive;
foreach (var (pos, size) in parts)
draw.AddRectFilled(pos, pos + size, BorderColor.RGBA, Rounding);
foreach (var (pos, size) in parts)
draw.AddRectFilled(pos + Border, pos + size - Border, outerKeyColor.RGBA, Rounding);
foreach (var (pos, size) in parts)
draw.AddRectFilled(pos + FaceStartOffset, pos + size - FaceEndOffset, innerKeyColor.RGBA, Rounding - 1);
if (label != null) {
var pos = parts[0].Pos + LabelOffset;
var height = ImGui.GetTextLineHeight() - 4;
foreach (var line in label.Split('\n')) {
draw.AddText(pos, LabelColor.RGBA, line);
pos += new Vector2(0, height);
}
}
}
}