mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-02-20 06:47:44 +01:00
Merge pull request #64 from ff-meli/key_state_reset
Fix keypress state getting stuck when entering ImGui windows
This commit is contained in:
commit
3b9e04e7a2
5 changed files with 89 additions and 1 deletions
|
|
@ -80,6 +80,11 @@ namespace Dalamud.Game.ClientState
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public JobGauges JobGauges;
|
public JobGauges JobGauges;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides access to the keypress state of keyboard keys in game.
|
||||||
|
/// </summary>
|
||||||
|
public KeyState KeyState;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set up client state access.
|
/// Set up client state access.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -98,6 +103,8 @@ namespace Dalamud.Game.ClientState
|
||||||
|
|
||||||
this.JobGauges = new JobGauges(Address);
|
this.JobGauges = new JobGauges(Address);
|
||||||
|
|
||||||
|
this.KeyState = new KeyState(Address, scanner.Module.BaseAddress);
|
||||||
|
|
||||||
Log.Verbose("SetupTerritoryType address {SetupTerritoryType}", Address.SetupTerritoryType);
|
Log.Verbose("SetupTerritoryType address {SetupTerritoryType}", Address.SetupTerritoryType);
|
||||||
|
|
||||||
this.setupTerritoryTypeHook = new Hook<SetupTerritoryTypeDelegate>(Address.SetupTerritoryType,
|
this.setupTerritoryTypeHook = new Hook<SetupTerritoryTypeDelegate>(Address.SetupTerritoryType,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ namespace Dalamud.Game.ClientState
|
||||||
public IntPtr ActorTable { get; private set; }
|
public IntPtr ActorTable { get; private set; }
|
||||||
public IntPtr LocalContentId { get; private set; }
|
public IntPtr LocalContentId { get; private set; }
|
||||||
public IntPtr JobGaugeData { get; private set; }
|
public IntPtr JobGaugeData { get; private set; }
|
||||||
|
public IntPtr KeyboardState { get; private set; }
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
public IntPtr SetupTerritoryType { get; private set; }
|
public IntPtr SetupTerritoryType { get; private set; }
|
||||||
|
|
@ -18,6 +19,9 @@ namespace Dalamud.Game.ClientState
|
||||||
JobGaugeData = sig.GetStaticAddressFromSig("E8 ?? ?? ?? ?? FF C6 48 8D 5B 0C", 0xB9) + 0x10;
|
JobGaugeData = sig.GetStaticAddressFromSig("E8 ?? ?? ?? ?? FF C6 48 8D 5B 0C", 0xB9) + 0x10;
|
||||||
|
|
||||||
SetupTerritoryType = sig.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F9 66 89 91 ?? ?? ?? ??");
|
SetupTerritoryType = sig.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F9 66 89 91 ?? ?? ?? ??");
|
||||||
|
|
||||||
|
// This resolves to a fixed offset only, without the base address added in, so GetStaticAddressFromSig() can't be used
|
||||||
|
KeyboardState = sig.ScanText("48 8D 0C 85 ?? ?? ?? ?? 8B 04 31 85 C2 0F 85") + 0x4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
62
Dalamud/Game/ClientState/KeyState.cs
Normal file
62
Dalamud/Game/ClientState/KeyState.cs
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
using Serilog;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Dalamud.Game.ClientState
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Wrapper around the game keystate buffer, which contains the pressed state for
|
||||||
|
/// all keyboard keys, indexed by virtual vkCode
|
||||||
|
/// </summary>
|
||||||
|
public class KeyState
|
||||||
|
{
|
||||||
|
private IntPtr bufferBase;
|
||||||
|
|
||||||
|
// The array is accessed in a way that this limit doesn't appear to exist
|
||||||
|
// but there is other state data past this point, and keys beyond here aren't
|
||||||
|
// generally valid for most things anyway
|
||||||
|
private const int MaxKeyCodeIndex = 0xA0;
|
||||||
|
|
||||||
|
public KeyState(ClientStateAddressResolver addressResolver, IntPtr moduleBaseAddress)
|
||||||
|
{
|
||||||
|
this.bufferBase = moduleBaseAddress + Marshal.ReadInt32(addressResolver.KeyboardState);
|
||||||
|
|
||||||
|
Log.Verbose($"Keyboard state buffer address {this.bufferBase}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the keypressed state for a given vkCode.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vkCode">The virtual key to change.</param>
|
||||||
|
/// <returns>Whether the specified key is currently pressed.</returns>
|
||||||
|
public bool this[int vkCode]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (vkCode< 0 || vkCode > MaxKeyCodeIndex)
|
||||||
|
throw new ArgumentException($"Keycode state only appears to be valid up to {MaxKeyCodeIndex}");
|
||||||
|
|
||||||
|
return (Marshal.ReadInt32(this.bufferBase + (4 * vkCode)) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (vkCode < 0 || vkCode > MaxKeyCodeIndex)
|
||||||
|
throw new ArgumentException($"Keycode state only appears to be valid up to {MaxKeyCodeIndex}");
|
||||||
|
|
||||||
|
Marshal.WriteInt32(this.bufferBase + (4 * vkCode), value ? 1 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears the pressed state for all keys.
|
||||||
|
/// </summary>
|
||||||
|
public void ClearAll()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < MaxKeyCodeIndex; i++)
|
||||||
|
{
|
||||||
|
Marshal.WriteInt32(this.bufferBase + (i * 4), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -155,6 +155,7 @@ namespace Dalamud.Interface
|
||||||
this.scene = new RawDX11Scene(swapChain);
|
this.scene = new RawDX11Scene(swapChain);
|
||||||
this.scene.ImGuiIniPath = Path.Combine(Path.GetDirectoryName(this.dalamud.StartInfo.ConfigurationPath), "dalamudUI.ini");
|
this.scene.ImGuiIniPath = Path.Combine(Path.GetDirectoryName(this.dalamud.StartInfo.ConfigurationPath), "dalamudUI.ini");
|
||||||
this.scene.OnBuildUI += Display;
|
this.scene.OnBuildUI += Display;
|
||||||
|
this.scene.OnNewInputFrame += OnNewInputFrame;
|
||||||
|
|
||||||
var fontPathJp = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "NotoSansCJKjp-Medium.otf");
|
var fontPathJp = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "NotoSansCJKjp-Medium.otf");
|
||||||
ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathJp, 17.0f, null, ImGui.GetIO().Fonts.GetGlyphRangesJapanese());
|
ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathJp, 17.0f, null, ImGui.GetIO().Fonts.GetGlyphRangesJapanese());
|
||||||
|
|
@ -222,6 +223,20 @@ namespace Dalamud.Interface
|
||||||
return this.setCursorHook.Original(hCursor);
|
return this.setCursorHook.Original(hCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnNewInputFrame()
|
||||||
|
{
|
||||||
|
// fix for keys in game getting stuck, if you were holding a game key (like run)
|
||||||
|
// and then clicked on an imgui textbox - imgui would swallow the keyup event,
|
||||||
|
// so the game would think the key remained pressed continuously until you left
|
||||||
|
// imgui and pressed and released the key again
|
||||||
|
if (ImGui.GetIO().WantTextInput)
|
||||||
|
{
|
||||||
|
this.dalamud.ClientState.KeyState.ClearAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: mouse state?
|
||||||
|
}
|
||||||
|
|
||||||
private void Display()
|
private void Display()
|
||||||
{
|
{
|
||||||
// this is more or less part of what reshade/etc do to avoid having to manually
|
// this is more or less part of what reshade/etc do to avoid having to manually
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit dda60b7faa1b12225d165d9e5d239e7e66648aae
|
Subproject commit d0c03cd31dac7a3eede52a467ef81def69f87ef9
|
||||||
Loading…
Add table
Add a link
Reference in a new issue