Files
Commonwealth-Online-Public/plugin/lib/commonlibf4/include/RE/C/ControlMap.h
T
2026-05-30 18:33:24 +12:00

129 lines
4.8 KiB
C++

#pragma once
#include "RE/B/BSFixedString.h"
#include "RE/B/BSTArray.h"
#include "RE/B/BSTSingleton.h"
#include "RE/I/INPUT_DEVICE.h"
#include "RE/U/UserEvents.h"
namespace RE
{
enum class PC_GAMEPAD_TYPE;
class ControlMap :
public BSTSingletonSDM<ControlMap> // 000
{
public:
using InputContextID = UserEvents::INPUT_CONTEXT_ID;
enum : std::uint32_t
{
kInvalid = static_cast<std::uint8_t>(-1)
};
class UserEventMapping
{
public:
// members
BSFixedString eventID; // 00
std::int32_t inputKey; // 08
std::int8_t byIndexInContext; // 0C
bool remappable; // 0D
bool linked; // 0E
REX::TEnumSet<UserEvents::USER_EVENT_FLAG, std::int32_t> userEventGroupFlag; // 10
};
static_assert(sizeof(UserEventMapping) == 0x18);
class InputContext
{
public:
// members
BSTArray<UserEventMapping> deviceMappings[std::to_underlying(INPUT_DEVICE::kSupported)]; // 00
};
static_assert(sizeof(InputContext) == 0x48);
class LinkedMapping
{
public:
// members
BSFixedString linkedMappingName; // 00
REX::TEnumSet<UserEvents::INPUT_CONTEXT_ID, std::int32_t> linkedMappingContext; // 08
REX::TEnumSet<INPUT_DEVICE, std::int32_t> device; // 0C
REX::TEnumSet<UserEvents::INPUT_CONTEXT_ID, std::int32_t> linkFromContext; // 10
BSFixedString linkFromName; // 18
};
static_assert(sizeof(LinkedMapping) == 0x20);
[[nodiscard]] static ControlMap* GetSingleton()
{
static REL::Relocation<ControlMap**> singleton{ ID::ControlMap::Singleton };
return *singleton;
}
std::uint32_t GetMappedKey(std::string_view a_eventID, INPUT_DEVICE a_device, InputContextID a_context = InputContextID::kMainGameplay) const
{
assert(a_device < INPUT_DEVICE::kTotal);
assert(a_context < InputContextID::kTotal);
if (controlMaps[std::to_underlying(a_context)]) {
const auto& mappings = controlMaps[std::to_underlying(a_context)]->deviceMappings[std::to_underlying(a_device)];
BSFixedString eventID(a_eventID);
for (auto& mapping : mappings) {
if (mapping.eventID == eventID) {
return mapping.inputKey;
}
}
}
return kInvalid;
}
bool PopInputContext(UserEvents::INPUT_CONTEXT_ID a_context)
{
using func_t = decltype(&ControlMap::PopInputContext);
static REL::Relocation<func_t> func{ ID::ControlMap::PopInputContext };
return func(this, a_context);
}
void PushInputContext(UserEvents::INPUT_CONTEXT_ID a_context)
{
using func_t = decltype(&ControlMap::PushInputContext);
static REL::Relocation<func_t> func{ ID::ControlMap::PushInputContext };
return func(this, a_context);
}
bool RemapButton(BSFixedString const& a_id, INPUT_DEVICE a_device, std::int32_t a_buttonID)
{
using func_t = decltype(&ControlMap::RemapButton);
static REL::Relocation<func_t> func{ ID::ControlMap::RemapButton };
return func(this, a_id, a_device, a_buttonID);
}
void SaveRemappings()
{
using func_t = decltype(&ControlMap::SaveRemappings);
static REL::Relocation<func_t> func{ ID::ControlMap::SaveRemappings };
return func(this);
}
void SetTextEntryMode(bool a_enable)
{
using func_t = decltype(&ControlMap::SetTextEntryMode);
static REL::Relocation<func_t> func{ ID::ControlMap::SetTextEntryMode };
return func(this, a_enable);
}
void SetIgnoreKeyboardMouse(bool a_value) noexcept { ignoreKeyboardMouse = a_value; }
// members
InputContext* controlMaps[std::to_underlying(UserEvents::INPUT_CONTEXT_ID::kTotal)]; // 008
BSTArray<LinkedMapping> linkedMappings; // 110
BSTArray<REX::TEnumSet<UserEvents::INPUT_CONTEXT_ID, std::int32_t>> contextPriorityStack; // 128
std::int8_t byTextEntryCount; // 140
bool ignoreKeyboardMouse; // 141
bool ignoreActivateDisabledEvents; // 142
REX::TEnumSet<PC_GAMEPAD_TYPE, std::int32_t> pcGamePadMapType; // 144
};
static_assert(sizeof(ControlMap) == 0x148);
}