From 662aef12472955555572a339a33b7396ad9f20d2 Mon Sep 17 00:00:00 2001 From: pas2704 Date: Sat, 17 May 2025 18:08:44 -0400 Subject: [PATCH] Input keybinds: hold ` for free mouse, use alt + delete to toggle free mouse --- CringeLauncher/ImGuiHandler.cs | 76 +++++++++++++++----- CringeLauncher/Patches/InputPatch.cs | 55 ++++++++++++++ CringeLauncher/Patches/XmlRootWriterPatch.cs | 2 +- 3 files changed, 114 insertions(+), 19 deletions(-) diff --git a/CringeLauncher/ImGuiHandler.cs b/CringeLauncher/ImGuiHandler.cs index a220e76..decd8b5 100644 --- a/CringeLauncher/ImGuiHandler.cs +++ b/CringeLauncher/ImGuiHandler.cs @@ -11,23 +11,27 @@ using ImGuiNET; using SharpDX.Direct3D11; using static ImGuiNET.ImGui; using VRage; +using Sandbox.Graphics.GUI; namespace CringeLauncher; internal class ImGuiHandler : IDisposable { private DeviceContext? _deviceContext; + private int _blockKeysCounter; private static nint _wndproc; public bool BlockMouse { get; private set; } - public bool BlockKeys { get; private set; } + public bool BlockKeys => _blockKeysCounter > 0; public bool DrawMouse { get; private set; } + internal bool MouseToggle { get; set; } + internal bool MouseKey { get; set; } public static ImGuiHandler? Instance; - + public static RenderTargetView? Rtv; - + private readonly IRootRenderComponent _renderHandler = new RenderHandler(); private static bool _init; @@ -36,16 +40,16 @@ internal class ImGuiHandler : IDisposable _deviceContext = deviceContext; CreateContext(); - + var io = GetIO(); - + var path = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "CringeLauncher", "imgui.ini"); io.NativePtr->IniFilename = AnsiStringMarshaller.ConvertToUnmanaged(path); io.ConfigWindowsMoveFromTitleBarOnly = true; io.ConfigFlags |= ImGuiConfigFlags.DockingEnable | ImGuiConfigFlags.ViewportsEnable; - + ImGui_ImplWin32_Init(windowHandle); ImGui_ImplDX11_Init(device.NativePointer, deviceContext.NativePointer); _init = true; @@ -58,7 +62,7 @@ internal class ImGuiHandler : IDisposable unsafe { delegate* unmanaged[Stdcall] wndProcHook = &WndProcHook; - + PInvoke.SetWindowLongPtr(windowHandle, WINDOW_LONG_PTR_INDEX.GWL_WNDPROC, (nint)wndProcHook); } } @@ -67,33 +71,69 @@ internal class ImGuiHandler : IDisposable { if (Rtv is null) return; - + ImGui_ImplDX11_NewFrame(); ImGui_ImplWin32_NewFrame(); NewFrame(); var io = GetIO(); BlockMouse = io.WantCaptureMouse; - BlockKeys = io.WantTextInput; - DrawMouse = io.MouseDrawCursor; + + if (io.WantTextInput) + _blockKeysCounter = 10; //WantTextInput can be false briefly after pressing enter in a textbox + else + _blockKeysCounter--; + + DrawMouse = io.MouseDrawCursor || MouseToggle || MouseKey; + + var focusedScreen = MyScreenManager.GetScreenWithFocus(); //migrated logic from MyDX9Gui.Draw + + if (DrawMouse || focusedScreen?.GetDrawMouseCursor() == true || (MyScreenManager.InputToNonFocusedScreens && MyScreenManager.GetScreensCount() > 1)) + { + MyGuiSandbox.SetMouseCursorVisibility(true, false); + } + else if (focusedScreen != null) + { + MyGuiSandbox.SetMouseCursorVisibility(focusedScreen.GetDrawMouseCursor()); + } + _renderHandler.OnFrame(); - + Render(); - + _deviceContext!.ClearState(); _deviceContext.OutputMerger.SetRenderTargets(Rtv); - + ImGui_ImplDX11_RenderDrawData(GetDrawData()); - + UpdatePlatformWindows(); RenderPlatformWindowsDefault(); } - + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvStdcall)])] private static unsafe int WndProcHook(HWND hWnd, int msg, nint wParam, nint lParam) { + //special handling for the mouse free key + + if (msg is 0x0100 or 0x104 && (int)wParam == 0xC0 && Instance != null) + { + Instance.MouseKey = true; + + return 0; + } + + if (msg is 0x0101 or 0x105 && (int)wParam == 0xC0 && Instance != null) + { + Instance.MouseKey = false; + + return 0; + } + + if (msg == 0x102 && (char)(int)wParam == '`') + return 0; + //ignore input if mouse is hidden - if (MyVRage.Platform?.Input?.ShowCursor == false && Instance?.DrawMouse != true) + if (Instance?.BlockKeys != true && MyVRage.Platform?.Input?.ShowCursor == false && Instance?.DrawMouse != true) return CallWindowProc(_wndproc, hWnd, msg, wParam, lParam); var hookResult = ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam); @@ -101,11 +141,11 @@ internal class ImGuiHandler : IDisposable if (hookResult != 0) return hookResult; - var io = GetIO(); - if (!_init) return CallWindowProc(_wndproc, hWnd, msg, wParam, lParam); + var io = GetIO(); + var blockMessage = (msg is >= 256 and <= 265 && io.WantTextInput) || (msg is >= 512 and <= 526 && io.WantCaptureMouse); diff --git a/CringeLauncher/Patches/InputPatch.cs b/CringeLauncher/Patches/InputPatch.cs index 03fa0d7..5e5b351 100644 --- a/CringeLauncher/Patches/InputPatch.cs +++ b/CringeLauncher/Patches/InputPatch.cs @@ -1,5 +1,9 @@ using HarmonyLib; +using Sandbox.Engine.Platform.VideoMode; +using Sandbox.Game.World; using Sandbox.Graphics; +using Sandbox.Graphics.GUI; +using System.Reflection.Emit; using VRage; using VRage.Input; using VRage.Input.Keyboard; @@ -25,6 +29,45 @@ internal static class InputPatch } } + [HarmonyPrefix, HarmonyPatch(typeof(MyVRageInput), nameof(MyVRageInput.GetMouseXForGamePlayF))] + private static bool GetMouseXForGamePlayFPrefix(ref float __result) + { + if (ImGuiHandler.Instance?.DrawMouse == true) + { + __result = 0; + return false; + } + return true; + } + + [HarmonyPrefix, HarmonyPatch(typeof(MyVRageInput), nameof(MyVRageInput.GetMouseYForGamePlayF))] + private static bool GetMouseYForGamePlayFPrefix(ref float __result) + { + if (ImGuiHandler.Instance?.DrawMouse == true) + { + __result = 0; + return false; + } + return true; + } + + [HarmonyTranspiler, HarmonyPatch(typeof(MyDX9Gui), nameof(MyDX9Gui.Draw))] + private static List Dx9GuiDrawTranspiler(IEnumerable instructions) + { + var list = instructions.ToList(); + + var method = AccessTools.Method(typeof(MyVideoSettingsManager), nameof(MyVideoSettingsManager.IsHardwareCursorUsed)); + + var index = list.FindIndex(b => b.Calls(method)); + + list[index].opcode = OpCodes.Ret; + list[index].operand = null; + + list.RemoveRange(index + 1, list.Count - index - 1); + + return list; + } + [HarmonyPrefix, HarmonyPatch(typeof(MyGuiLocalizedKeyboardState), nameof(MyGuiLocalizedKeyboardState.GetCurrentState))] private static bool GetKeyboardStatePrefix(ref MyKeyboardState __result) { @@ -46,4 +89,16 @@ internal static class InputPatch } return true; } + + [HarmonyPostfix, HarmonyPatch(typeof(MySession), nameof(MySession.HandleInput))] + private static void HandleInputPostfix() + { + if (ImGuiHandler.Instance == null || MyInput.Static == null) + return; + + if (MyInput.Static.IsAnyAltKeyPressed() && MyInput.Static.IsNewKeyPressed(MyKeys.Delete)) + { + ImGuiHandler.Instance.MouseToggle = !ImGuiHandler.Instance.MouseToggle; + } + } } diff --git a/CringeLauncher/Patches/XmlRootWriterPatch.cs b/CringeLauncher/Patches/XmlRootWriterPatch.cs index a52ebc2..5a2402e 100644 --- a/CringeLauncher/Patches/XmlRootWriterPatch.cs +++ b/CringeLauncher/Patches/XmlRootWriterPatch.cs @@ -6,7 +6,7 @@ using VRage; namespace CringeLauncher.Patches; [HarmonyPatch(typeof(CustomRootWriter), "Init")] -public class XmlRootWriterPatch +public static class XmlRootWriterPatch { private static IEnumerable Transpiler(IEnumerable instructions) {