From 694bc0a888fcb58fa0da5f003a924bfaed0d32f7 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Thu, 26 Apr 2018 14:10:32 -0700 Subject: [PATCH 1/3] Add ability to unregister command on the fly --- hecl/include/hecl/Console.hpp | 1 + hecl/lib/Console.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/hecl/include/hecl/Console.hpp b/hecl/include/hecl/Console.hpp index 6e6cd6f64..f863b12bd 100644 --- a/hecl/include/hecl/Console.hpp +++ b/hecl/include/hecl/Console.hpp @@ -80,6 +80,7 @@ private: public: Console(CVarManager*); void registerCommand(std::string_view name, std::string_view helpText, std::string_view usage, const std::function&)>&& func); + void unregisterCommand(std::string_view name); void executeString(const std::string& strToExec); diff --git a/hecl/lib/Console.cpp b/hecl/lib/Console.cpp index a6d03c330..c7ef715c2 100644 --- a/hecl/lib/Console.cpp +++ b/hecl/lib/Console.cpp @@ -32,6 +32,14 @@ void Console::registerCommand(std::string_view name, std::string_view helpText, m_commands[lowName] = SConsoleCommand{name.data(), helpText.data(), usage.data(), std::move(func)}; } +void Console::unregisterCommand(std::string_view name) +{ + std::string lowName = name.data(); + athena::utility::tolower(lowName); + if (m_commands.find(lowName) != m_commands.end()) + m_commands.erase(m_commands.find(lowName)); +} + void Console::executeString(const std::string& str) { if (str.empty()) From eae0dbd2bb7abeb40b1c57d7d15ce73a30c9a9a5 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sun, 29 Apr 2018 20:11:37 -0700 Subject: [PATCH 2/3] Add ability to flag commands --- hecl/include/hecl/CVarManager.hpp | 3 +++ hecl/include/hecl/Console.hpp | 12 ++++++++++- hecl/lib/CVarManager.cpp | 36 ++++++++++++++++++++++++++++++- hecl/lib/Console.cpp | 30 +++++++++++++++++++------- 4 files changed, 71 insertions(+), 10 deletions(-) diff --git a/hecl/include/hecl/CVarManager.hpp b/hecl/include/hecl/CVarManager.hpp index acf729d22..ff92bfdd1 100755 --- a/hecl/include/hecl/CVarManager.hpp +++ b/hecl/include/hecl/CVarManager.hpp @@ -4,6 +4,7 @@ #include #include #include "CVar.hpp" +#include "hecl/SystemChar.hpp" namespace hecl { @@ -78,6 +79,8 @@ public: void setDeveloperMode(bool v, bool setDeserialized=false); bool restartRequired() const; + + void parseCommandLine(const std::vector& args); private: bool suppressDeveloper(); void restoreDeveloper(bool oldDeveloper); diff --git a/hecl/include/hecl/Console.hpp b/hecl/include/hecl/Console.hpp index f863b12bd..8f0676368 100644 --- a/hecl/include/hecl/Console.hpp +++ b/hecl/include/hecl/Console.hpp @@ -14,11 +14,19 @@ class CVarManager; class CVar; struct SConsoleCommand { + enum class ECommandFlags + { + Normal = 0, + Cheat = (1 << 0), + Developer = (1 << 1) + }; std::string m_displayName; std::string m_helpString; std::string m_usage; std::function&)> m_func; + ECommandFlags m_flags; }; +ENABLE_BITWISE_ENUM(SConsoleCommand::ECommandFlags) class Console { @@ -77,9 +85,11 @@ private: CVar* m_conHeight; float m_cachedConSpeed; float m_cachedConHeight; + bool m_showCursor = true; + float m_cursorTime = 0.f; public: Console(CVarManager*); - void registerCommand(std::string_view name, std::string_view helpText, std::string_view usage, const std::function&)>&& func); + void registerCommand(std::string_view name, std::string_view helpText, std::string_view usage, const std::function&)>&& func, SConsoleCommand::ECommandFlags cmdFlags = SConsoleCommand::ECommandFlags::Normal); void unregisterCommand(std::string_view name); void executeString(const std::string& strToExec); diff --git a/hecl/lib/CVarManager.cpp b/hecl/lib/CVarManager.cpp index 29cf05036..79ebc1af3 100755 --- a/hecl/lib/CVarManager.cpp +++ b/hecl/lib/CVarManager.cpp @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include namespace hecl { @@ -12,6 +14,7 @@ CVar* com_developer = nullptr; CVar* com_configfile = nullptr; CVar* com_enableCheats = nullptr; +static const std::regex cmdLineRegex("\\+(\\w+)=([\\w\\.\\-]+)"); CVarManager* CVarManager::m_instance = nullptr; static logvisor::Module CVarLog("CVarManager"); @@ -269,11 +272,42 @@ bool CVarManager::restartRequired() const return false; } +void CVarManager::parseCommandLine(const std::vector& args) +{ + bool oldDeveloper = suppressDeveloper(); + std::string developerName = com_developer->name().data(); + ToLower(developerName); + for (const SystemString& arg : args) + { + if (arg[0] == _S('+')) + { + std::string tmp = SystemUTF8Conv(arg).c_str(); + + std::smatch matches; + if (std::regex_match(tmp, matches, cmdLineRegex)) + { + std::string cvarName = matches[1].str(); + std::string cvarValue = matches[2].str(); + if (CVar* cv = findCVar(cvarName)) + { + cv->fromLiteralToType(cvarValue); + hecl::ToLower(cvarName); + if (developerName == cvarName) + /* Make sure we're not overriding developer mode when we restore */ + oldDeveloper = com_developer->toBoolean(); + } + } + } + } + + restoreDeveloper(oldDeveloper); +} + bool CVarManager::suppressDeveloper() { bool oldDeveloper = com_developer->toBoolean(); CVarUnlocker unlock(com_developer); - com_developer->fromBoolean(false); + com_developer->fromBoolean(true); return oldDeveloper; } diff --git a/hecl/lib/Console.cpp b/hecl/lib/Console.cpp index c7ef715c2..b1eea1bc4 100644 --- a/hecl/lib/Console.cpp +++ b/hecl/lib/Console.cpp @@ -24,12 +24,12 @@ Console::Console(CVarManager* cvarMgr) } -void Console::registerCommand(std::string_view name, std::string_view helpText, std::string_view usage, const std::function &)>&& func) +void Console::registerCommand(std::string_view name, std::string_view helpText, std::string_view usage, const std::function &)>&& func, SConsoleCommand::ECommandFlags cmdFlags) { std::string lowName = name.data(); athena::utility::tolower(lowName); if (m_commands.find(lowName) == m_commands.end()) - m_commands[lowName] = SConsoleCommand{name.data(), helpText.data(), usage.data(), std::move(func)}; + m_commands[lowName] = SConsoleCommand{name.data(), helpText.data(), usage.data(), std::move(func), cmdFlags}; } void Console::unregisterCommand(std::string_view name) @@ -65,7 +65,21 @@ void Console::executeString(const std::string& str) std::string lowComName = commandName; athena::utility::tolower(lowComName); if (m_commands.find(lowComName) != m_commands.end()) + { + const SConsoleCommand& cmd = m_commands[lowComName]; + if (bool(cmd.m_flags & SConsoleCommand::ECommandFlags::Developer) && !com_developer->toBoolean()) + { + report(Level::Error, "This command can only be executed in developer mode", commandName.c_str()); + return; + } + + if (bool(cmd.m_flags & SConsoleCommand::ECommandFlags::Cheat) && !com_enableCheats->toBoolean()) + { + report(Level::Error, "This command can only be executed with cheats enabled", commandName.c_str()); + return; + } m_commands[lowComName].m_func(this, args); + } else report(Level::Error, "Command '%s' is not valid!", commandName.c_str()); } @@ -266,8 +280,8 @@ void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, b m_cursorPosition = -1; m_commandHistory.insert(m_commandHistory.begin(), m_commandString); m_commandString.clear(); - //m_showCursor = true; - //m_cursorTime = 0; + m_showCursor = true; + m_cursorTime = 0.f; break; } case boo::ESpecialKey::Left: @@ -280,8 +294,8 @@ void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, b else m_cursorPosition--; - //m_showCursor = true; - //m_cursorTime = 0; + m_showCursor = true; + m_cursorTime = 0.f; break; } case boo::ESpecialKey::Right: @@ -303,8 +317,8 @@ void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, b else m_cursorPosition++; - // m_showCursor = true; - // m_cursorTime = 0; + m_showCursor = true; + m_cursorTime = 0.f; break; } From 0aac384e6085d2963bdfb7bcb53b1d8baa41f53b Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Tue, 1 May 2018 17:41:51 -0700 Subject: [PATCH 3/3] Fix windows build --- hecl/lib/CVar.cpp | 2 +- hecl/lib/CVarManager.cpp | 4 ++-- hecl/lib/Console.cpp | 31 ++++++++++++++++++++++++------- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/hecl/lib/CVar.cpp b/hecl/lib/CVar.cpp index 9cf5c41b3..6a3d3c8c0 100755 --- a/hecl/lib/CVar.cpp +++ b/hecl/lib/CVar.cpp @@ -127,7 +127,7 @@ CVar::CVar(std::string_view name, int value, std::string_view help, CVar::EFlags std::string CVar::help() const { return std::string(m_help + (m_defaultValue != std::string() ? "\ndefault: " + m_defaultValue : "") + - (isReadOnly() ? "[ReadOnly]" : "")); + (isReadOnly() ? " [ReadOnly]" : "")); } atVec4f CVar::toVec4f(bool* isValid) const diff --git a/hecl/lib/CVarManager.cpp b/hecl/lib/CVarManager.cpp index 79ebc1af3..5ac9d5f0a 100755 --- a/hecl/lib/CVarManager.cpp +++ b/hecl/lib/CVarManager.cpp @@ -276,7 +276,7 @@ void CVarManager::parseCommandLine(const std::vector& args) { bool oldDeveloper = suppressDeveloper(); std::string developerName = com_developer->name().data(); - ToLower(developerName); + athena::utility::tolower(developerName); for (const SystemString& arg : args) { if (arg[0] == _S('+')) @@ -291,7 +291,7 @@ void CVarManager::parseCommandLine(const std::vector& args) if (CVar* cv = findCVar(cvarName)) { cv->fromLiteralToType(cvarValue); - hecl::ToLower(cvarName); + athena::utility::tolower(cvarName); if (developerName == cvarName) /* Make sure we're not overriding developer mode when we restore */ oldDeveloper = com_developer->toBoolean(); diff --git a/hecl/lib/Console.cpp b/hecl/lib/Console.cpp index b1eea1bc4..30e5b0509 100644 --- a/hecl/lib/Console.cpp +++ b/hecl/lib/Console.cpp @@ -124,7 +124,12 @@ void Console::report(Level level, const char* fmt, va_list list) { char tmp[2048]; vsnprintf(tmp, 2048, fmt, list); - m_log.emplace_back(std::string(tmp), level); + std::vector lines = athena::utility::split(tmp, '\n'); + for (const std::string& line : lines) + { + std::string v = athena::utility::sprintf("%s", line.c_str()); + m_log.emplace_back(v, level); + } printf("%s\n", tmp); } @@ -372,16 +377,24 @@ void Console::LogVisorAdapter::report(const char* modName, logvisor::Level sever { char tmp[2048]; vsnprintf(tmp, 2048, format, ap); - std::string v = athena::utility::sprintf("[%s] %s", modName, tmp); - m_con->m_log.emplace_back(v, Console::Level(severity)); + std::vector lines = athena::utility::split(tmp, '\n'); + for (const std::string& line : lines) + { + std::string v = athena::utility::sprintf("[%s] %s", modName, line.c_str()); + m_con->m_log.emplace_back(v, Console::Level(severity)); + } } void Console::LogVisorAdapter::report(const char* modName, logvisor::Level severity, const wchar_t* format, va_list ap) { wchar_t tmp[2048]; vswprintf(tmp, 2048, format, ap); - std::string v = athena::utility::sprintf("[%s] %s", modName, athena::utility::wideToUtf8(tmp).c_str()); - m_con->m_log.emplace_back(v, Console::Level(severity)); + std::vector lines = athena::utility::split(athena::utility::wideToUtf8(tmp), '\n'); + for (const std::string& line : lines) + { + std::string v = athena::utility::sprintf("[%s] %s", modName, line.c_str()); + m_con->m_log.emplace_back(v, Console::Level(severity)); + } } void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum, const char* format, va_list ap) @@ -396,8 +409,12 @@ void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level { wchar_t tmp[2048]; vswprintf(tmp, 2048, format, ap); - std::string v = athena::utility::sprintf("[%s] %s %s:%i", modName, athena::utility::wideToUtf8(tmp).c_str(), file, linenum); - m_con->m_log.emplace_back(v, Console::Level(severity)); + std::vector lines = athena::utility::split(athena::utility::wideToUtf8(tmp), '\n'); + for (const std::string& line : lines) + { + std::string v = athena::utility::sprintf("[%s] %s %s:%i", modName, line.c_str(), file, linenum); + m_con->m_log.emplace_back(v, Console::Level(severity)); + } } void Console::dumpLog()