Add KeyboardModule

- Added KeyboardModule
This commit is contained in:
izawartka 2026-08-08 15:54:05 +02:00
parent 92621c710a
commit c46c4458c4
13 changed files with 242 additions and 0 deletions

View File

@ -363,6 +363,14 @@
<ClInclude Include="src\modules\keybinding\bind-manager.h" />
<ClInclude Include="src\modules\keybinding\keybinding.h" />
<ClInclude Include="src\modules\keybinding\root.h" />
<ClInclude Include="src\modules\keyboard\common.h" />
<ClInclude Include="src\modules\keyboard\events\events.h" />
<ClInclude Include="src\modules\keyboard\events\key-down.h" />
<ClInclude Include="src\modules\keyboard\events\key-up.h" />
<ClInclude Include="src\modules\keyboard\events\keyboard-base.h" />
<ClInclude Include="src\modules\keyboard\events\keyboard.h" />
<ClInclude Include="src\modules\keyboard\keyboard.h" />
<ClInclude Include="src\modules\keyboard\root.h" />
<ClInclude Include="src\modules\modmenu\cheat-base.h" />
<ClInclude Include="src\modules\modmenu\cheat-manager.h" />
<ClInclude Include="src\modules\modmenu\cheat-registry.h" />
@ -664,6 +672,9 @@
<ClCompile Include="src\logging.cpp" />
<ClCompile Include="src\modules\keybinding\bind-manager.cpp" />
<ClCompile Include="src\modules\keybinding\root.cpp" />
<ClCompile Include="src\modules\keyboard\events\key-down.cpp" />
<ClCompile Include="src\modules\keyboard\events\key-up.cpp" />
<ClCompile Include="src\modules\keyboard\root.cpp" />
<ClCompile Include="src\modules\modmenu\cheat-manager.cpp" />
<ClCompile Include="src\modules\modmenu\cheats\camera\camera-pos.cpp" />
<ClCompile Include="src\modules\modmenu\cheats\camera\camera.cpp" />

View File

@ -224,6 +224,9 @@
<ClCompile Include="src\modules\modmenu\utils\get-ped-by-encoded-id.cpp" />
<ClCompile Include="src\modules\modmenu\utils\get-car-by-encoded-id.cpp" />
<ClCompile Include="src\modules\modmenu\utils\get-object-by-encoded-id.cpp" />
<ClCompile Include="src\modules\keyboard\events\key-down.cpp" />
<ClCompile Include="src\modules\keyboard\events\key-up.cpp" />
<ClCompile Include="src\modules\keyboard\root.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\converters\ammo.h" />
@ -577,6 +580,14 @@
<ClInclude Include="src\modules\modmenu\utils\get-ped-by-encoded-id.h" />
<ClInclude Include="src\modules\modmenu\utils\get-car-by-encoded-id.h" />
<ClInclude Include="src\modules\modmenu\utils\get-object-by-encoded-id.h" />
<ClInclude Include="src\modules\keyboard\common.h" />
<ClInclude Include="src\modules\keyboard\events\events.h" />
<ClInclude Include="src\modules\keyboard\events\key-down.h" />
<ClInclude Include="src\modules\keyboard\events\key-up.h" />
<ClInclude Include="src\modules\keyboard\events\keyboard-base.h" />
<ClInclude Include="src\modules\keyboard\events\keyboard.h" />
<ClInclude Include="src\modules\keyboard\keyboard.h" />
<ClInclude Include="src\modules\keyboard\root.h" />
</ItemGroup>
<ItemGroup>
<None Include="GTA2.props" />

View File

@ -6,6 +6,7 @@
#include "version.h"
#include "game-version-check.cpp"
#include "core/core.h"
#include "modules/keyboard/keyboard.h"
#include "modules/persistence/persistence.h"
#include "modules/keybinding/keybinding.h"
#include "modules/ui/ui.h"
@ -28,6 +29,7 @@ static void Init()
coreInstance = new Core::Core();
Core::ModuleManager* moduleManager = Core::ModuleManager::GetInstance();
KeyboardModule::RootModule* keyboardModule = moduleManager->AddModule<KeyboardModule::RootModule>();
PersistenceModule::RootModule* persistenceModule = moduleManager->AddModule<PersistenceModule::RootModule>();
KeyBindingModule::RootModule* keyBindingModule = moduleManager->AddModule<KeyBindingModule::RootModule>();
UiModule::RootModule* uiModule = moduleManager->AddModule<UiModule::RootModule>();
@ -48,6 +50,7 @@ static void Deinit()
moduleManager->RemoveModule<UiModule::RootModule>();
moduleManager->RemoveModule<KeyBindingModule::RootModule>();
moduleManager->RemoveModule<PersistenceModule::RootModule>();
moduleManager->RemoveModule<KeyboardModule::RootModule>();
delete coreInstance;
coreInstance = nullptr;
}

View File

@ -0,0 +1,4 @@
#pragma once
#include "../../core/core.h"
#include "../../game/game.h"

View File

@ -0,0 +1,5 @@
#pragma once
#include "keyboard-base.h"
#include "key-down.h"
#include "key-up.h"

View File

@ -0,0 +1,6 @@
#include "key-down.h"
#include "../root.h"
bool KeyboardModule::KeyDownEvent::Init() {
return KeyboardModule::RootModule::GetInstance() != nullptr;
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "keyboard-base.h"
namespace KeyboardModule {
/*
Dispatched when a key is pressed down.
*/
class KeyDownEvent : public KeyboardEventBase {
public:
static bool Init();
KeyDownEvent(Game::KeyCode keyCode, bool shift = false, bool ctrl = false, bool alt = false, bool capsLock = false)
: KeyboardEventBase(keyCode, shift, ctrl, alt, capsLock) {}
};
}

View File

@ -0,0 +1,6 @@
#include "key-up.h"
#include "../root.h"
bool KeyboardModule::KeyUpEvent::Init() {
return KeyboardModule::RootModule::GetInstance() != nullptr;
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "keyboard-base.h"
namespace KeyboardModule {
/*
Dispatched when a key is released.
*/
class KeyUpEvent : public KeyboardEventBase {
public:
static bool Init();
KeyUpEvent(Game::KeyCode keyCode, bool shift = false, bool ctrl = false, bool alt = false, bool capsLock = false)
: KeyboardEventBase(keyCode, shift, ctrl, alt, capsLock) {}
};
}

View File

@ -0,0 +1,28 @@
#pragma once
#include "../common.h"
namespace KeyboardModule {
/*
Base class for all keyboard events. Not to be used directly.
*/
class KeyboardEventBase : public Core::CancellableEventBase {
public:
static bool Init() { return false; }
Game::KeyCode GetKeyCode() const { return m_keyCode; }
bool IsShiftPressed() const { return m_shift; }
bool IsCtrlPressed() const { return m_ctrl; }
bool IsAltPressed() const { return m_alt; }
bool IsCapsLockOn() const { return m_capsLock; }
protected:
KeyboardEventBase(Game::KeyCode keyCode, bool shift = false, bool ctrl = false, bool alt = false, bool capsLock = false)
: m_keyCode(keyCode), m_shift(shift), m_ctrl(ctrl), m_alt(alt), m_capsLock(capsLock) {}
virtual ~KeyboardEventBase() override {};
Game::KeyCode m_keyCode;
bool m_shift = false;
bool m_ctrl = false;
bool m_alt = false;
bool m_capsLock = false;
};
}

View File

@ -0,0 +1,5 @@
#pragma once
#include "common.h"
#include "events/events.h"
#include "root.h"

View File

@ -0,0 +1,103 @@
#include "root.h"
#include "events/key-down.h"
#include "events/key-up.h"
static constexpr unsigned int KEYBOARD_EVENT_PRIORITY = 100 * 1000;
KeyboardModule::RootModule* KeyboardModule::RootModule::m_instance = nullptr;
KeyboardModule::RootModule::RootModule() {
assert(m_instance == nullptr && "KeyboardModule::RootModule instance already exists!");
m_instance = this;
spdlog::info("KeyboardModule::RootModule module initialized.");
}
KeyboardModule::RootModule::~RootModule()
{
m_instance = nullptr;
}
KeyboardModule::RootModule* KeyboardModule::RootModule::GetInstance()
{
return m_instance;
}
bool KeyboardModule::RootModule::Attach()
{
EventListenerSupport::AddEventListener<KeyboardGetDataEvent>(&RootModule::OnKeyboardGetData, false, KEYBOARD_EVENT_PRIORITY);
spdlog::info("KeyboardModule::RootModule module attached.");
return true;
}
void KeyboardModule::RootModule::Detach()
{
EventListenerSupport::RemoveEventListener<KeyboardGetDataEvent>();
spdlog::info("KeyboardModule::RootModule module detached.");
}
bool KeyboardModule::RootModule::IsKeyDown(Game::KeyCode keyCode) const
{
unsigned char keyIndex = static_cast<unsigned char>(keyCode);
return m_keys[keyIndex];
}
bool KeyboardModule::RootModule::IsCapsLockOn() const
{
return m_isCapsLockOn;
}
void KeyboardModule::RootModule::OnKeyboardGetData(KeyboardGetDataEvent& event)
{
if (event.GetModifiedDataCount() == 0) return;
bool isDown = event.GetModifiedIsDown();
Game::KeyCode keyCode = event.GetModifiedKeyCode();
UpdateCapsLock();
bool prevIsDown = SetKeyState(keyCode, isDown);
if (isDown == prevIsDown) {
spdlog::warn(
"KeyboardModule: Recieved key {} update event, but its state is unchanged ({})",
static_cast<unsigned char>(keyCode),
isDown ? "down" : "up"
);
}
Core::EventManager* eventManager = Core::EventManager::GetInstance();
if (isDown) {
KeyDownEvent keyEvent(
keyCode,
IsKeyDown(Game::KeyCode::DIK_LSHIFT) || IsKeyDown(Game::KeyCode::DIK_RSHIFT),
IsKeyDown(Game::KeyCode::DIK_LCONTROL) || IsKeyDown(Game::KeyCode::DIK_RCONTROL),
IsKeyDown(Game::KeyCode::DIK_LMENU) || IsKeyDown(Game::KeyCode::DIK_RMENU),
m_isCapsLockOn
);
eventManager->Dispatch(keyEvent);
if (keyEvent.IsCancelled()) event.Drop();
} else {
KeyUpEvent keyEvent(
keyCode,
IsKeyDown(Game::KeyCode::DIK_LSHIFT) || IsKeyDown(Game::KeyCode::DIK_RSHIFT),
IsKeyDown(Game::KeyCode::DIK_LCONTROL) || IsKeyDown(Game::KeyCode::DIK_RCONTROL),
IsKeyDown(Game::KeyCode::DIK_LMENU) || IsKeyDown(Game::KeyCode::DIK_RMENU),
m_isCapsLockOn
);
eventManager->Dispatch(keyEvent);
if (keyEvent.IsCancelled()) event.Drop();
}
}
bool KeyboardModule::RootModule::SetKeyState(Game::KeyCode keyCode, bool isDown)
{
unsigned char keyIndex = static_cast<unsigned char>(keyCode);
bool prevState = m_keys[keyIndex];
m_keys[keyIndex] = isDown;
return prevState;
}
void KeyboardModule::RootModule::UpdateCapsLock()
{
m_isCapsLockOn = (GetKeyState(VK_CAPITAL) & 0x0001) != 0;
}

View File

@ -0,0 +1,30 @@
#pragma once
#include "common.h"
#include "../../events/keyboard-get-data.h"
namespace KeyboardModule {
class KeyboardEvent;
class RootModule : public Core::ModuleBase {
public:
RootModule();
virtual ~RootModule() override;
static RootModule* GetInstance();
bool Attach();
void Detach();
bool IsKeyDown(Game::KeyCode keyCode) const;
bool IsCapsLockOn() const;
private:
void OnKeyboardGetData(KeyboardGetDataEvent& event);
void OnPostKeyboardGetData(PostKeyboardGetDataEvent& event);
// @returns Previous isDown state
bool SetKeyState(Game::KeyCode keyCode, bool isDown);
void UpdateCapsLock();
static RootModule* m_instance;
bool m_keys[256] = { 0 };
bool m_isCapsLockOn = false;
};
}