From e247733d04bcad18e95e2467f531aa4a3eee1c55 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Thu, 11 Jan 2018 01:35:27 -0800 Subject: [PATCH 1/3] Initial `Console` implementation --- hecl/include/hecl/CVar.hpp | 4 +- hecl/include/hecl/CVarCommons.hpp | 6 +- hecl/include/hecl/CVarManager.hpp | 6 ++ hecl/include/hecl/Console.hpp | 52 ++++++++++++ hecl/lib/CMakeLists.txt | 2 + hecl/lib/CVar.cpp | 1 + hecl/lib/CVarManager.cpp | 27 ++++++ hecl/lib/Console.cpp | 134 ++++++++++++++++++++++++++++++ 8 files changed, 228 insertions(+), 4 deletions(-) create mode 100644 hecl/include/hecl/Console.hpp create mode 100644 hecl/lib/Console.cpp diff --git a/hecl/include/hecl/CVar.hpp b/hecl/include/hecl/CVar.hpp index d93e749c6..f3427bc23 100755 --- a/hecl/include/hecl/CVar.hpp +++ b/hecl/include/hecl/CVar.hpp @@ -31,7 +31,8 @@ enum EFlags Hidden = (1 << 5), ReadOnly = (1 << 6), Archive = (1 << 7), - Modified = (1 << 8) + Modified = (1 << 8), + ModifyRestart = (1 << 9) /*!< If this bit is set, any modification will inform the user that a restart is required */ }; ENABLE_BITWISE_ENUM(EFlags) @@ -98,6 +99,7 @@ public: bool isLiteral() const { return m_type == EType::Literal; } bool isVec4f() const { return m_type == EType::Vec4f; } bool isModified() const; + bool modificationRequiresRestart() const; bool isReadOnly() const; bool isCheat() const; bool isHidden() const; diff --git a/hecl/include/hecl/CVarCommons.hpp b/hecl/include/hecl/CVarCommons.hpp index fd0fb5e97..0f29f2a42 100644 --- a/hecl/include/hecl/CVarCommons.hpp +++ b/hecl/include/hecl/CVarCommons.hpp @@ -30,13 +30,13 @@ public: { m_graphicsApi = m_mgr.findOrMakeCVar("graphicsApi"sv, "API to use for rendering graphics"sv, - DEFAULT_GRAPHICS_API, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive); + DEFAULT_GRAPHICS_API, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart); m_drawSamples = m_mgr.findOrMakeCVar("drawSamples"sv, "Number of MSAA samples to use for render targets"sv, - 1, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive); + 1, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart); m_texAnisotropy = m_mgr.findOrMakeCVar("texAnisotropy"sv, "Number of anisotropic samples to use for sampling textures"sv, - 1, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive); + 1, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart); } std::string getGraphicsApi() const diff --git a/hecl/include/hecl/CVarManager.hpp b/hecl/include/hecl/CVarManager.hpp index b4f6d39d4..68854b0db 100755 --- a/hecl/include/hecl/CVarManager.hpp +++ b/hecl/include/hecl/CVarManager.hpp @@ -71,6 +71,12 @@ public: static CVarManager* instance(); + void list(const std::vector& args); + void setCVar(const std::vector& args); + void getCVar(const std::vector& args); + + + bool restartRequired() const; private: bool suppressDeveloper(); void restoreDeveloper(bool oldDeveloper); diff --git a/hecl/include/hecl/Console.hpp b/hecl/include/hecl/Console.hpp new file mode 100644 index 000000000..ae9224128 --- /dev/null +++ b/hecl/include/hecl/Console.hpp @@ -0,0 +1,52 @@ +#ifndef __URDE_CONSOLE_HPP__ +#define __URDE_CONSOLE_HPP__ + +#include +#include +#include +#include + +namespace hecl +{ + +struct SConsoleCommand +{ + std::string m_displayName; + std::string m_helpString; + std::string m_usage; + std::function&)> m_func; +}; + +class Console +{ +public: + static Console* m_instance; + enum class Level + { + Info, /**< Non-error informative message */ + Warning, /**< Non-error warning message */ + Error, /**< Recoverable error message */ + Fatal /**< Non-recoverable error message (Kept for compatibility with logvisor) */ + }; +private: + std::unordered_map m_commands; + std::vector> m_log; +public: + Console(class CVarManager*); + void registerCommand(std::string_view name, std::string_view helpText, std::string_view usage, const std::function&)>&& func); + + void executeString(const std::string& strToExec); + + void help(const std::vector& args); + void listCommands(const std::vector& args); + bool commandExists(std::string_view cmd); + + + void print(Level level, const char *fmt, va_list list); + void print(Level, const char* fmt, ...); + void dumpLog(); + static Console* instance(); +}; +} + +#endif // __URDE_CONSOLE_HPP__ diff --git a/hecl/lib/CMakeLists.txt b/hecl/lib/CMakeLists.txt index 5cad1c6d6..839fb582f 100644 --- a/hecl/lib/CMakeLists.txt +++ b/hecl/lib/CMakeLists.txt @@ -27,6 +27,7 @@ endif() set(HECL_HEADERS ../include/hecl/CVar.hpp ../include/hecl/CVarManager.hpp + ../include/hecl/Console.hpp ../include/hecl/CVarCommons.hpp ../include/hecl/hecl.hpp ../include/hecl/FourCC.hpp @@ -56,6 +57,7 @@ set(COMMON_SOURCES HumanizeNumber.cpp CVar.cpp CVarManager.cpp + Console.cpp ClientProcess.cpp SteamFinder.cpp WideStringConvert.cpp diff --git a/hecl/lib/CVar.cpp b/hecl/lib/CVar.cpp index 376fc2234..7a3312684 100755 --- a/hecl/lib/CVar.cpp +++ b/hecl/lib/CVar.cpp @@ -352,6 +352,7 @@ bool CVar::fromLiteral(std::wstring_view val) } bool CVar::isModified() const { return int(m_flags & EFlags::Modified) != 0;} +bool CVar::modificationRequiresRestart() const { return int(m_flags & EFlags::ModifyRestart) != 0; } bool CVar::isReadOnly() const { return int(m_flags & EFlags::ReadOnly) != 0; } diff --git a/hecl/lib/CVarManager.cpp b/hecl/lib/CVarManager.cpp index fa974c5d2..ccc19780a 100755 --- a/hecl/lib/CVarManager.cpp +++ b/hecl/lib/CVarManager.cpp @@ -1,5 +1,6 @@ #include "hecl/CVarManager.hpp" #include "hecl/CVar.hpp" +#include "hecl/Console.hpp" #include #include #include @@ -175,6 +176,32 @@ CVarManager* CVarManager::instance() return m_instance; } +void CVarManager::list(const std::vector &args) +{ + +} + +void CVarManager::setCVar(const std::vector &args) +{ + +} + +void CVarManager::getCVar(const std::vector &args) +{ + +} + +bool CVarManager::restartRequired() const +{ + for (const auto& cv : m_cvars) + { + if (cv.second->isModified() && cv.second->modificationRequiresRestart()) + return true; + } + + return false; +} + bool CVarManager::suppressDeveloper() { bool oldDeveloper = com_developer->toBoolean(); diff --git a/hecl/lib/Console.cpp b/hecl/lib/Console.cpp new file mode 100644 index 000000000..c804b67e0 --- /dev/null +++ b/hecl/lib/Console.cpp @@ -0,0 +1,134 @@ +#include "hecl/Console.hpp" +#include "hecl/CVarManager.hpp" +#include "hecl/CVar.hpp" +#include "athena/Utility.hpp" + +namespace hecl +{ +Console* Console::m_instance = nullptr; +Console::Console(CVarManager* cvarMgr) +{ + m_instance = this; + registerCommand("help", "Prints information about a given function", "", std::bind(&Console::help, this, std::placeholders::_1)); + registerCommand("listCommands", "Prints a list of all available Commands", "", std::bind(&Console::listCommands, this, std::placeholders::_1)); + registerCommand("listCVars", "Lists all available CVars", "", std::bind(&CVarManager::list, cvarMgr, std::placeholders::_1)); + registerCommand("setCVar", "Sets a given Console Variable to the specified value", " ", std::bind(&CVarManager::setCVar, cvarMgr, std::placeholders::_1)); + registerCommand("getCVar", "Prints the value stored in the specified Console Variable", "", std::bind(&CVarManager::getCVar, cvarMgr, std::placeholders::_1)); +} + +void Console::registerCommand(std::string_view name, std::string_view helpText, std::string_view usage, const std::function &)>&& func) +{ + 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)}; +} + +void Console::executeString(const std::string& str) +{ + if (str.empty()) + return; + + /* First let's split semi-colon delimited commands */ + std::vector commands = athena::utility::split(str, ';'); + + if (commands.empty()) + return; + + for (std::string command : commands) + { + command = athena::utility::trim(command); + std::vector args = athena::utility::split(command, ' '); + + if (args.empty()) + continue; + + std::string commandName = args[0]; + args.erase(args.begin()); + + std::string lowComName = commandName; + athena::utility::tolower(lowComName); + if (m_commands.find(lowComName) != m_commands.end()) + m_commands[lowComName].m_func(args); + else + print(Level::Error, "Command '%s' is not valid!", commandName.c_str()); + } +} + +void Console::help(const std::vector& args) +{ + if (args.empty()) + { + print(Level::Info, "Expected usage: help "); + return; + } + std::string cmd = args.front(); + athena::utility::tolower(cmd); + auto it = m_commands.find(cmd); + if (it == m_commands.end()) + { + print(Level::Error, "No such command '%s'", args.front().c_str()); + return; + } + + print(Level::Info, "%s: %s", it->second.m_displayName.c_str(), it->second.m_helpString.c_str()); + if (!it->second.m_usage.empty()) + print(Level::Info, "Usage: %s %s", it->second.m_displayName.c_str(), it->second.m_usage.c_str()); +} + +void Console::listCommands(const std::vector& /*args*/) +{ + for (const auto& comPair : m_commands) + print(Level::Info, "'%s': %s", comPair.second.m_displayName.c_str(), comPair.second.m_helpString.c_str()); +} + +bool Console::commandExists(std::string_view cmd) +{ + std::string cmdName = cmd.data(); + athena::utility::tolower(cmdName); + + return m_commands.find(cmdName) != m_commands.end(); +} + +void Console::print(Level level, const char* fmt, va_list list) +{ + char tmp[2048]; + vsnprintf(tmp, 2048, fmt, list); + m_log.emplace_back(std::string(tmp), level); +} + +void Console::print(Level level, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + print(level, fmt, ap); + va_end(ap); +} + +void Console::dumpLog() +{ + for (const auto& l : m_log) + { + switch(l.second) + { + case Level::Info: + printf("%s\n", l.first.c_str()); + break; + case Level::Warning: + printf("[Warning] %s\n", l.first.c_str()); + break; + case Level::Error: + printf("[ Error ] %s\n", l.first.c_str()); + break; + case Level::Fatal: + printf("[ Fatal ] %s\n", l.first.c_str()); + break; + } + } +} + +Console* Console::instance() +{ + return m_instance; +} +} From 24ee3fa21ea4ffa7139bbd255c63766787bff5ef Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Thu, 11 Jan 2018 04:38:35 -0800 Subject: [PATCH 2/3] Windows build fix --- hecl/lib/Console.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hecl/lib/Console.cpp b/hecl/lib/Console.cpp index c804b67e0..7890d0954 100644 --- a/hecl/lib/Console.cpp +++ b/hecl/lib/Console.cpp @@ -16,7 +16,7 @@ Console::Console(CVarManager* cvarMgr) registerCommand("getCVar", "Prints the value stored in the specified Console Variable", "", std::bind(&CVarManager::getCVar, cvarMgr, std::placeholders::_1)); } -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) { std::string lowName = name.data(); athena::utility::tolower(lowName); From 7f6913e04674758d88b0191d53b670eea9da3573 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Thu, 11 Jan 2018 08:26:33 -0800 Subject: [PATCH 3/3] Fix linux build, initial logvisor integration into Console --- hecl/extern/boo | 2 +- hecl/include/hecl/CVarManager.hpp | 6 +- hecl/include/hecl/Console.hpp | 43 ++++++++-- hecl/lib/CVarManager.cpp | 7 +- hecl/lib/Console.cpp | 136 ++++++++++++++++++++++++++---- 5 files changed, 161 insertions(+), 33 deletions(-) diff --git a/hecl/extern/boo b/hecl/extern/boo index 1a48dd9c4..0a93d6c10 160000 --- a/hecl/extern/boo +++ b/hecl/extern/boo @@ -1 +1 @@ -Subproject commit 1a48dd9c42cd25030281345831e7cfb2359426bd +Subproject commit 0a93d6c105e7807bd520bf37b262e922e9817473 diff --git a/hecl/include/hecl/CVarManager.hpp b/hecl/include/hecl/CVarManager.hpp index 68854b0db..db22db5b9 100755 --- a/hecl/include/hecl/CVarManager.hpp +++ b/hecl/include/hecl/CVarManager.hpp @@ -71,9 +71,9 @@ public: static CVarManager* instance(); - void list(const std::vector& args); - void setCVar(const std::vector& args); - void getCVar(const std::vector& args); + void list(class Console* con, const std::vector& args); + void setCVar(class Console* con, const std::vector& args); + void getCVar(class Console* con, const std::vector& args); bool restartRequired() const; diff --git a/hecl/include/hecl/Console.hpp b/hecl/include/hecl/Console.hpp index ae9224128..2da4f9cf2 100644 --- a/hecl/include/hecl/Console.hpp +++ b/hecl/include/hecl/Console.hpp @@ -5,6 +5,7 @@ #include #include #include +#include "logvisor/logvisor.hpp" namespace hecl { @@ -14,11 +15,31 @@ struct SConsoleCommand std::string m_displayName; std::string m_helpString; std::string m_usage; - std::function&)> m_func; + std::function&)> m_func; }; class Console { + friend class LogVisorAdapter; + struct LogVisorAdapter : logvisor::ILogger + { + Console* m_con; + LogVisorAdapter(Console* con) + : m_con(con) {} + + ~LogVisorAdapter() {} + void report(const char* modName, logvisor::Level severity, + const char* format, va_list ap); + void report(const char* modName, logvisor::Level severity, + const wchar_t* format, va_list ap); + void reportSource(const char* modName, logvisor::Level severity, + const char* file, unsigned linenum, + const char* format, va_list ap); + void reportSource(const char* modName, logvisor::Level severity, + const char* file, unsigned linenum, + const wchar_t* format, va_list ap); + }; + public: static Console* m_instance; enum class Level @@ -31,21 +52,29 @@ public: private: std::unordered_map m_commands; std::vector> m_log; + void visorReport(Level level, const char* mod, const char* fmt, va_list list); + void visorReport(Level level, const char* mod, const char* fmt, ...); + void visorReportSource(Level, const char* mod, const char* file, unsigned line, const char* fmt, va_list); + void visorReportSource(Level, const char* mod, const char* file, unsigned line, const char* fmt, ...); + void visorReport(Level level, const char* mod, const wchar_t* fmt, va_list list); + void visorReport(Level level, const char* mod, const wchar_t* fmt, ...); + void visorReportSource(Level, const char* mod, const char* file, unsigned line, const wchar_t* fmt, va_list); + void visorReportSource(Level, const char* mod, const char* file, unsigned line, const wchar_t* fmt, ...); public: Console(class 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); void executeString(const std::string& strToExec); - void help(const std::vector& args); - void listCommands(const std::vector& args); + void help(Console* con, const std::vector& args); + void listCommands(Console* con, const std::vector& args); bool commandExists(std::string_view cmd); - - void print(Level level, const char *fmt, va_list list); - void print(Level, const char* fmt, ...); + void report(Level level, const char *fmt, va_list list); + void report(Level, const char* fmt, ...); void dumpLog(); static Console* instance(); + static void RegisterLogger(Console* con); }; } diff --git a/hecl/lib/CVarManager.cpp b/hecl/lib/CVarManager.cpp index ccc19780a..2f4e2c729 100755 --- a/hecl/lib/CVarManager.cpp +++ b/hecl/lib/CVarManager.cpp @@ -176,19 +176,18 @@ CVarManager* CVarManager::instance() return m_instance; } -void CVarManager::list(const std::vector &args) +void CVarManager::list(Console* con, const std::vector &args) { } -void CVarManager::setCVar(const std::vector &args) +void CVarManager::setCVar(Console* con, const std::vector &args) { } -void CVarManager::getCVar(const std::vector &args) +void CVarManager::getCVar(Console* con, const std::vector &args) { - } bool CVarManager::restartRequired() const diff --git a/hecl/lib/Console.cpp b/hecl/lib/Console.cpp index 7890d0954..fb221df8c 100644 --- a/hecl/lib/Console.cpp +++ b/hecl/lib/Console.cpp @@ -9,14 +9,14 @@ Console* Console::m_instance = nullptr; Console::Console(CVarManager* cvarMgr) { m_instance = this; - registerCommand("help", "Prints information about a given function", "", std::bind(&Console::help, this, std::placeholders::_1)); - registerCommand("listCommands", "Prints a list of all available Commands", "", std::bind(&Console::listCommands, this, std::placeholders::_1)); - registerCommand("listCVars", "Lists all available CVars", "", std::bind(&CVarManager::list, cvarMgr, std::placeholders::_1)); - registerCommand("setCVar", "Sets a given Console Variable to the specified value", " ", std::bind(&CVarManager::setCVar, cvarMgr, std::placeholders::_1)); - registerCommand("getCVar", "Prints the value stored in the specified Console Variable", "", std::bind(&CVarManager::getCVar, cvarMgr, std::placeholders::_1)); + registerCommand("help", "Prints information about a given function", "", std::bind(&Console::help, this, std::placeholders::_1, std::placeholders::_2)); + registerCommand("listCommands", "Prints a list of all available Commands", "", std::bind(&Console::listCommands, this, std::placeholders::_1, std::placeholders::_2)); + registerCommand("listCVars", "Lists all available CVars", "", std::bind(&CVarManager::list, cvarMgr, std::placeholders::_1, std::placeholders::_2)); + registerCommand("setCVar", "Sets a given Console Variable to the specified value", " ", std::bind(&CVarManager::setCVar, cvarMgr, std::placeholders::_1, std::placeholders::_2)); + registerCommand("getCVar", "Prints the value stored in the specified Console Variable", "", std::bind(&CVarManager::getCVar, cvarMgr, std::placeholders::_1, std::placeholders::_2)); } -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) { std::string lowName = name.data(); athena::utility::tolower(lowName); @@ -49,17 +49,17 @@ void Console::executeString(const std::string& str) std::string lowComName = commandName; athena::utility::tolower(lowComName); if (m_commands.find(lowComName) != m_commands.end()) - m_commands[lowComName].m_func(args); + m_commands[lowComName].m_func(this, args); else - print(Level::Error, "Command '%s' is not valid!", commandName.c_str()); + report(Level::Error, "Command '%s' is not valid!", commandName.c_str()); } } -void Console::help(const std::vector& args) +void Console::help(Console* /*con*/, const std::vector& args) { if (args.empty()) { - print(Level::Info, "Expected usage: help "); + report(Level::Info, "Expected usage: help "); return; } std::string cmd = args.front(); @@ -67,19 +67,19 @@ void Console::help(const std::vector& args) auto it = m_commands.find(cmd); if (it == m_commands.end()) { - print(Level::Error, "No such command '%s'", args.front().c_str()); + report(Level::Error, "No such command '%s'", args.front().c_str()); return; } - print(Level::Info, "%s: %s", it->second.m_displayName.c_str(), it->second.m_helpString.c_str()); + report(Level::Info, "%s: %s", it->second.m_displayName.c_str(), it->second.m_helpString.c_str()); if (!it->second.m_usage.empty()) - print(Level::Info, "Usage: %s %s", it->second.m_displayName.c_str(), it->second.m_usage.c_str()); + report(Level::Info, "Usage: %s %s", it->second.m_displayName.c_str(), it->second.m_usage.c_str()); } -void Console::listCommands(const std::vector& /*args*/) +void Console::listCommands(Console* /*con*/, const std::vector& /*args*/) { for (const auto& comPair : m_commands) - print(Level::Info, "'%s': %s", comPair.second.m_displayName.c_str(), comPair.second.m_helpString.c_str()); + report(Level::Info, "'%s': %s", comPair.second.m_displayName.c_str(), comPair.second.m_helpString.c_str()); } bool Console::commandExists(std::string_view cmd) @@ -90,21 +90,108 @@ bool Console::commandExists(std::string_view cmd) return m_commands.find(cmdName) != m_commands.end(); } -void Console::print(Level level, const char* fmt, va_list list) +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); } -void Console::print(Level level, const char* fmt, ...) +void Console::report(Level level, const char* fmt, ...) { va_list ap; va_start(ap, fmt); - print(level, fmt, ap); + report(level, fmt, ap); va_end(ap); } +void Console::visorReport(Console::Level level, const char* mod, const wchar_t* fmt, va_list list) +{ + wchar_t tmp[2048]; + vswprintf(tmp, 2048, fmt, list); + std::string v = athena::utility::sprintf("[%s] %s", mod, athena::utility::wideToUtf8(tmp).c_str()); + m_log.emplace_back(athena::utility::wideToUtf8(tmp), level); +} + +void Console::visorReport(Console::Level level, const char* mod, const wchar_t* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + report(level, mod, fmt, ap); + va_end(ap); +} + +void Console::visorReportSource(Console::Level level, const char* mod, const char* file, unsigned line, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + visorReportSource(level, mod, file, line, fmt, ap); + va_end(ap); +} + +void Console::visorReportSource(Console::Level level, const char *mod, const char *file, unsigned line, const wchar_t *fmt, va_list ap) +{ + wchar_t tmp[2048]; + vswprintf(tmp, 2048, fmt, ap); + std::string v = athena::utility::sprintf("[%s] %s %s:%i", mod, athena::utility::wideToUtf8(tmp).c_str(), file, line); + m_log.emplace_back(v, level); +} + +void Console::visorReportSource(Console::Level level, const char *mod, const char* file, unsigned line, const wchar_t* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + visorReportSource(level, mod, file, line, fmt, ap); + va_end(ap); +} + +void Console::visorReport(Console::Level level, const char* mod, const char* fmt, va_list ap) +{ + char tmp[2048]; + vsnprintf(tmp, 2048, fmt, ap); + std::string v = athena::utility::sprintf("[%s] %s", mod, tmp); + m_log.emplace_back(v, level); +} + +void Console::visorReport(Console::Level level, const char* mod, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + report(level, mod, fmt, ap); + va_end(ap); +} + +void Console::visorReportSource(Console::Level level, const char* mod, const char* file, unsigned line, const char* fmt, va_list ap) +{ + char tmp[2048]; + vsnprintf(tmp, 2048, fmt, ap); + std::string v = athena::utility::sprintf("[%s] %s %s:%i", mod, tmp, file, line); + m_log.emplace_back(v, level); +} + +void Console::LogVisorAdapter::report(const char* modName, logvisor::Level severity, const char *format, va_list ap) +{ + m_con->visorReport(Console::Level(severity), modName, format, ap); +} + +void Console::LogVisorAdapter::report(const char* modName, logvisor::Level severity, const wchar_t* format, va_list ap) +{ + m_con->visorReport(Console::Level(severity), modName, format, ap); +} + +void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum, const char* format, va_list ap) +{ + m_con->visorReportSource(Console::Level(severity), modName, file, linenum, format, ap); +} + +void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum, const wchar_t* format, va_list ap) +{ + wchar_t tmp[2048]; + vswprintf(tmp, 2048, format, ap); + std::string v = athena::utility::wideToUtf8(tmp); + m_con->visorReportSource(Console::Level(severity), modName, file, linenum, format, ap); +} + void Console::dumpLog() { for (const auto& l : m_log) @@ -127,6 +214,19 @@ void Console::dumpLog() } } +void Console::RegisterLogger(Console* con) +{ + /* Determine if console logger already added */ + for (auto& logger : logvisor::MainLoggers) + { + if (typeid(logger.get()) == typeid(LogVisorAdapter)) + return; + } + + /* Otherwise construct new console logger */ + logvisor::MainLoggers.emplace_back(new LogVisorAdapter(con)); +} + Console* Console::instance() { return m_instance;