Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ set(mmapper_SRCS
global/Timer.cpp
global/Timer.h
global/Version.h
global/View.h
global/WeakHandle.cpp
global/WeakHandle.h
global/WinSock.cpp
Expand Down
20 changes: 20 additions & 0 deletions src/client/Hotkey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,26 @@

#include <sstream>

namespace {
NODISCARD constexpr bool isUppercase(const char *s)
{
while (*s) {
if (*s >= 'a' && *s <= 'z')
return false;
s++;
}
return true;
}
#define X_CHECK_UPPER(id, name, qkey, policy) \
static_assert(isUppercase(name), "Hotkey name must be uppercase: " name);
XFOREACH_HOTKEY_BASE_KEYS(X_CHECK_UPPER)
#undef X_CHECK_UPPER
#define X_CHECK_UPPER(name, camel, qtenum) \
static_assert(isUppercase(#name), "Hotkey modifier must be uppercase: " #name);
XFOREACH_HOTKEY_MODIFIER(X_CHECK_UPPER)
#undef X_CHECK_UPPER
} // namespace

bool Hotkey::isPolicySatisfied() const
{
const auto mods = modifiers();
Expand Down
20 changes: 0 additions & 20 deletions src/client/Hotkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,26 +155,6 @@ class NODISCARD HotkeyModifiers final
#undef X_IS_POLICY
};

namespace {
constexpr bool isUppercase(const char *s)
{
while (*s) {
if (*s >= 'a' && *s <= 'z')
return false;
s++;
}
return true;
}
#define X_CHECK_UPPER(id, name, qkey, policy) \
static_assert(isUppercase(name), "Hotkey name must be uppercase: " name);
XFOREACH_HOTKEY_BASE_KEYS(X_CHECK_UPPER)
#undef X_CHECK_UPPER
#define X_CHECK_UPPER(name, camel, qtenum) \
static_assert(isUppercase(#name), "Hotkey modifier must be uppercase: " #name);
XFOREACH_HOTKEY_MODIFIER(X_CHECK_UPPER)
#undef X_CHECK_UPPER
} // namespace

class NODISCARD Hotkey final
{
private:
Expand Down
51 changes: 50 additions & 1 deletion src/client/HotkeyManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,54 @@
#include <QDebug>
#include <QSettings>

namespace {

NODISCARD constexpr bool is_valid_hotkey(const std::string_view hotkey_str)
{
// Find the base key (the part after the last '+')
const size_t last_plus = hotkey_str.rfind('+');
const std::string_view base_part = (last_plus == std::string_view::npos)
? hotkey_str
: hotkey_str.substr(last_plus + 1);

// Determine which modifiers are present
const bool has_ctrl = hotkey_str.find("CTRL") != std::string_view::npos;
const bool has_alt = hotkey_str.find("ALT") != std::string_view::npos;
const bool has_shift = hotkey_str.find("SHIFT") != std::string_view::npos;
const bool has_meta = hotkey_str.find("META") != std::string_view::npos;
const bool has_any_mod = has_ctrl || has_alt || has_shift || has_meta;

// Match against the base key and check policy
#define CHECK_POLICY(id, name, key, policy) \
if (base_part == name) { \
if (policy == HotkeyPolicyEnum::ModifierRequired) \
return has_any_mod; \
if (policy == HotkeyPolicyEnum::ModifierNotShift) \
return (has_ctrl || has_alt || has_meta); \
return true; \
}

XFOREACH_HOTKEY_BASE_KEYS(CHECK_POLICY)
#undef CHECK_POLICY

// Key name not found
return false;
}

// This template trick ensures the compiler evaluates the expression for every macro entry
template<bool V>
struct Validate
{
static_assert(V, "Hotkey policy violation detected!");
};

#define APPLY_VALIDATION(SerializedKey, Command) \
static_assert(is_valid_hotkey(SerializedKey), "Invalid Hotkey Policy for: " SerializedKey);
XFOREACH_DEFAULT_HOTKEYS(APPLY_VALIDATION)
#undef APPLY_VALIDATION

} // namespace

HotkeyManager::HotkeyManager()
{
setConfig().hotkeys.registerChangeCallback(m_configLifetime,
Expand Down Expand Up @@ -38,7 +86,7 @@ void HotkeyManager::syncFromConfig()
}
}

bool HotkeyManager::setHotkey(const Hotkey &hk, std::string command)
bool HotkeyManager::setHotkey(const Hotkey &hk, const std::string_view command)
{
if (!hk.isValid()) {
return false;
Expand Down Expand Up @@ -81,6 +129,7 @@ std::optional<std::string> HotkeyManager::getCommand(const Hotkey &hk) const
std::vector<std::pair<Hotkey, std::string>> HotkeyManager::getAllHotkeys() const
{
std::vector<std::pair<Hotkey, std::string>> result;
result.reserve(m_hotkeys.size());
for (const auto &[hk, cmd] : m_hotkeys) {
result.emplace_back(hk, cmd);
}
Expand Down
50 changes: 1 addition & 49 deletions src/client/HotkeyManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,54 +61,6 @@
X("NUMPAD1", "ride") \
X("NUMPAD3", "stand")

namespace {

constexpr bool is_valid_hotkey(std::string_view hotkey_str)
{
// Find the base key (the part after the last '+')
size_t last_plus = hotkey_str.rfind('+');
std::string_view base_part = (last_plus == std::string_view::npos)
? hotkey_str
: hotkey_str.substr(last_plus + 1);

// Determine which modifiers are present
bool has_ctrl = hotkey_str.find("CTRL") != std::string_view::npos;
bool has_alt = hotkey_str.find("ALT") != std::string_view::npos;
bool has_shift = hotkey_str.find("SHIFT") != std::string_view::npos;
bool has_meta = hotkey_str.find("META") != std::string_view::npos;
bool has_any_mod = has_ctrl || has_alt || has_shift || has_meta;

// Match against the base key and check policy
#define CHECK_POLICY(id, name, key, policy) \
if (base_part == name) { \
if (policy == HotkeyPolicyEnum::ModifierRequired) \
return has_any_mod; \
if (policy == HotkeyPolicyEnum::ModifierNotShift) \
return (has_ctrl || has_alt || has_meta); \
return true; \
}

XFOREACH_HOTKEY_BASE_KEYS(CHECK_POLICY)
#undef CHECK_POLICY

// Key name not found
return false;
}

// This template trick ensures the compiler evaluates the expression for every macro entry
template<bool V>
struct Validate
{
static_assert(V, "Hotkey policy violation detected!");
};

#define APPLY_VALIDATION(SerializedKey, Command) \
static_assert(is_valid_hotkey(SerializedKey), "Invalid Hotkey Policy for: " SerializedKey);
XFOREACH_DEFAULT_HOTKEYS(APPLY_VALIDATION)
#undef APPLY_VALIDATION

} // namespace

class NODISCARD HotkeyManager final
{
private:
Expand All @@ -125,7 +77,7 @@ class NODISCARD HotkeyManager final
void syncFromConfig();

public:
NODISCARD bool setHotkey(const Hotkey &hk, std::string command);
NODISCARD bool setHotkey(const Hotkey &hk, std::string_view command);
NODISCARD bool removeHotkey(const Hotkey &hk);

public:
Expand Down
36 changes: 18 additions & 18 deletions src/display/Characters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ static constexpr float CHAR_ARROW_LINE_WIDTH = 2.f;
static constexpr float PATH_LINE_WIDTH = 0.1f;
static constexpr float PATH_POINT_SIZE = 8.f;

DistantObjectTransform DistantObjectTransform::construct(const glm::vec3 &pos,
DistantObjectTransform DistantObjectTransform::construct(const glm::vec3 pos,
const MapScreen &mapScreen,
const float marginPixels)
{
Expand All @@ -44,12 +44,12 @@ DistantObjectTransform DistantObjectTransform::construct(const glm::vec3 &pos,
return DistantObjectTransform{hint, degrees};
}

bool CharacterBatch::isVisible(const Coordinate &c, float margin) const
bool CharacterBatch::isVisible(const Coordinate c, float margin) const
{
return m_mapScreen.isRoomVisible(c, margin);
}

void CharacterBatch::drawCharacter(const Coordinate &c, const Color color, bool fill)
void CharacterBatch::drawCharacter(const Coordinate c, const Color color, bool fill)
{
const Configuration::CanvasSettings &settings = getConfig().canvas;

Expand Down Expand Up @@ -103,14 +103,14 @@ void CharacterBatch::drawCharacter(const Coordinate &c, const Color color, bool
gl.drawBox(c, fill, beacon, isFar);
}

void CharacterBatch::CharFakeGL::drawPathSegment(const glm::vec3 &p1,
const glm::vec3 &p2,
void CharacterBatch::CharFakeGL::drawPathSegment(const glm::vec3 p1,
const glm::vec3 p2,
const Color color)
{
mmgl::generateLineQuadsSafe(m_pathLineQuads, p1, p2, PATH_LINE_WIDTH, color);
}

void CharacterBatch::drawPreSpammedPath(const Coordinate &c1,
void CharacterBatch::drawPreSpammedPath(const Coordinate c1,
const std::vector<Coordinate> &path,
const Color color)
{
Expand All @@ -123,13 +123,13 @@ void CharacterBatch::drawPreSpammedPath(const Coordinate &c1,
TranslatedVerts translated;
translated.reserve(path.size() + 1);

const auto add = [&translated](const Coordinate &c) -> void {
const auto add = [&translated](const Coordinate c) -> void {
static const glm::vec3 PATH_OFFSET{0.5f, 0.5f, 0.f};
translated.push_back(c.to_vec3() + PATH_OFFSET);
};

add(c1);
for (const Coordinate &c2 : path) {
for (const Coordinate c2 : path) {
add(c2);
}
return translated;
Expand All @@ -146,14 +146,14 @@ void CharacterBatch::drawPreSpammedPath(const Coordinate &c1,
gl.drawPathPoint(color, verts.back());
}

void CharacterBatch::CharFakeGL::drawQuadCommon(const glm::vec2 &in_a,
const glm::vec2 &in_b,
const glm::vec2 &in_c,
const glm::vec2 &in_d,
void CharacterBatch::CharFakeGL::drawQuadCommon(const glm::vec2 in_a,
const glm::vec2 in_b,
const glm::vec2 in_c,
const glm::vec2 in_d,
const QuadOptsEnum options)
{
const auto &m = m_stack.top().modelView;
const auto transform = [&m](const glm::vec2 &vin) -> glm::vec3 {
const auto transform = [&m](const glm::vec2 vin) -> glm::vec3 {
const auto vtmp = m * glm::vec4(vin, 0.f, 1.f);
return glm::vec3{vtmp / vtmp.w};
};
Expand Down Expand Up @@ -226,7 +226,7 @@ void CharacterBatch::CharFakeGL::drawQuadCommon(const glm::vec2 &in_a,
}
}

void CharacterBatch::CharFakeGL::drawBox(const Coordinate &coord,
void CharacterBatch::CharFakeGL::drawBox(const Coordinate coord,
bool fill,
bool beacon,
const bool isFar)
Expand Down Expand Up @@ -280,7 +280,7 @@ void CharacterBatch::CharFakeGL::drawBox(const Coordinate &coord,

const auto &color = m_color;
const auto &m = m_stack.top().modelView;
const auto addTransformed = [this, &color, &m](const glm::vec2 &in_vert) -> void {
const auto addTransformed = [this, &color, &m](const glm::vec2 in_vert) -> void {
const auto tmp = m * glm::vec4(in_vert, 0.f, 1.f);
m_charRoomQuads.emplace_back(color, glm::vec3{in_vert, 0}, glm::vec3{tmp / tmp.w});
};
Expand Down Expand Up @@ -364,7 +364,7 @@ void CharacterBatch::CharFakeGL::reallyDrawPaths(OpenGL &gl)
}
}

void CharacterBatch::CharFakeGL::addScreenSpaceArrow(const glm::vec3 &pos,
void CharacterBatch::CharFakeGL::addScreenSpaceArrow(const glm::vec3 pos,
const float degrees,
const Color color,
const bool fill)
Expand All @@ -381,7 +381,7 @@ void CharacterBatch::CharFakeGL::addScreenSpaceArrow(const glm::vec3 &pos,
const glm::vec3 z{0, 0, 1};
const glm::mat4 rotation = glm::rotate(glm::mat4(1), radians, z);
for (size_t i = 0; i < 4; ++i) {
const glm::vec2 &tc = texCoords[i];
const glm::vec2 tc = texCoords[i];
const auto tmp = rotation * glm::vec4(tc * 2.f - 1.f, 0, 1);
const glm::vec2 screenSpaceOffset = scale * glm::vec2(tmp) / tmp.w;
// solid |filled
Expand All @@ -393,7 +393,7 @@ void CharacterBatch::CharFakeGL::addScreenSpaceArrow(const glm::vec3 &pos,
}
}

void CharacterBatch::CharFakeGL::addName(const Coordinate &c,
void CharacterBatch::CharFakeGL::addName(const Coordinate c,
const std::string &name,
const Color color,
const MapScreen &mapScreen)
Expand Down
Loading
Loading