mirror of https://github.com/AxioDL/metaforce.git
Initial `Console` implementation
This commit is contained in:
parent
70c97c1c2a
commit
e247733d04
|
@ -31,7 +31,8 @@ enum EFlags
|
||||||
Hidden = (1 << 5),
|
Hidden = (1 << 5),
|
||||||
ReadOnly = (1 << 6),
|
ReadOnly = (1 << 6),
|
||||||
Archive = (1 << 7),
|
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)
|
ENABLE_BITWISE_ENUM(EFlags)
|
||||||
|
|
||||||
|
@ -98,6 +99,7 @@ public:
|
||||||
bool isLiteral() const { return m_type == EType::Literal; }
|
bool isLiteral() const { return m_type == EType::Literal; }
|
||||||
bool isVec4f() const { return m_type == EType::Vec4f; }
|
bool isVec4f() const { return m_type == EType::Vec4f; }
|
||||||
bool isModified() const;
|
bool isModified() const;
|
||||||
|
bool modificationRequiresRestart() const;
|
||||||
bool isReadOnly() const;
|
bool isReadOnly() const;
|
||||||
bool isCheat() const;
|
bool isCheat() const;
|
||||||
bool isHidden() const;
|
bool isHidden() const;
|
||||||
|
|
|
@ -30,13 +30,13 @@ public:
|
||||||
{
|
{
|
||||||
m_graphicsApi = m_mgr.findOrMakeCVar("graphicsApi"sv,
|
m_graphicsApi = m_mgr.findOrMakeCVar("graphicsApi"sv,
|
||||||
"API to use for rendering graphics"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,
|
m_drawSamples = m_mgr.findOrMakeCVar("drawSamples"sv,
|
||||||
"Number of MSAA samples to use for render targets"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,
|
m_texAnisotropy = m_mgr.findOrMakeCVar("texAnisotropy"sv,
|
||||||
"Number of anisotropic samples to use for sampling textures"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
|
std::string getGraphicsApi() const
|
||||||
|
|
|
@ -71,6 +71,12 @@ public:
|
||||||
|
|
||||||
static CVarManager* instance();
|
static CVarManager* instance();
|
||||||
|
|
||||||
|
void list(const std::vector<std::string>& args);
|
||||||
|
void setCVar(const std::vector<std::string>& args);
|
||||||
|
void getCVar(const std::vector<std::string>& args);
|
||||||
|
|
||||||
|
|
||||||
|
bool restartRequired() const;
|
||||||
private:
|
private:
|
||||||
bool suppressDeveloper();
|
bool suppressDeveloper();
|
||||||
void restoreDeveloper(bool oldDeveloper);
|
void restoreDeveloper(bool oldDeveloper);
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef __URDE_CONSOLE_HPP__
|
||||||
|
#define __URDE_CONSOLE_HPP__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace hecl
|
||||||
|
{
|
||||||
|
|
||||||
|
struct SConsoleCommand
|
||||||
|
{
|
||||||
|
std::string m_displayName;
|
||||||
|
std::string m_helpString;
|
||||||
|
std::string m_usage;
|
||||||
|
std::function<void(const std::vector<std::string>&)> 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<std::string, SConsoleCommand> m_commands;
|
||||||
|
std::vector<std::pair<std::string, Level>> m_log;
|
||||||
|
public:
|
||||||
|
Console(class CVarManager*);
|
||||||
|
void registerCommand(std::string_view name, std::string_view helpText, std::string_view usage, const std::function<void(const std::vector<std::string>&)>&& func);
|
||||||
|
|
||||||
|
void executeString(const std::string& strToExec);
|
||||||
|
|
||||||
|
void help(const std::vector<std::string>& args);
|
||||||
|
void listCommands(const std::vector<std::string>& 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__
|
|
@ -27,6 +27,7 @@ endif()
|
||||||
set(HECL_HEADERS
|
set(HECL_HEADERS
|
||||||
../include/hecl/CVar.hpp
|
../include/hecl/CVar.hpp
|
||||||
../include/hecl/CVarManager.hpp
|
../include/hecl/CVarManager.hpp
|
||||||
|
../include/hecl/Console.hpp
|
||||||
../include/hecl/CVarCommons.hpp
|
../include/hecl/CVarCommons.hpp
|
||||||
../include/hecl/hecl.hpp
|
../include/hecl/hecl.hpp
|
||||||
../include/hecl/FourCC.hpp
|
../include/hecl/FourCC.hpp
|
||||||
|
@ -56,6 +57,7 @@ set(COMMON_SOURCES
|
||||||
HumanizeNumber.cpp
|
HumanizeNumber.cpp
|
||||||
CVar.cpp
|
CVar.cpp
|
||||||
CVarManager.cpp
|
CVarManager.cpp
|
||||||
|
Console.cpp
|
||||||
ClientProcess.cpp
|
ClientProcess.cpp
|
||||||
SteamFinder.cpp
|
SteamFinder.cpp
|
||||||
WideStringConvert.cpp
|
WideStringConvert.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::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; }
|
bool CVar::isReadOnly() const { return int(m_flags & EFlags::ReadOnly) != 0; }
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "hecl/CVarManager.hpp"
|
#include "hecl/CVarManager.hpp"
|
||||||
#include "hecl/CVar.hpp"
|
#include "hecl/CVar.hpp"
|
||||||
|
#include "hecl/Console.hpp"
|
||||||
#include <athena/FileWriter.hpp>
|
#include <athena/FileWriter.hpp>
|
||||||
#include <athena/Utility.hpp>
|
#include <athena/Utility.hpp>
|
||||||
#include <hecl/Runtime.hpp>
|
#include <hecl/Runtime.hpp>
|
||||||
|
@ -175,6 +176,32 @@ CVarManager* CVarManager::instance()
|
||||||
return m_instance;
|
return m_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CVarManager::list(const std::vector<std::string> &args)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVarManager::setCVar(const std::vector<std::string> &args)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVarManager::getCVar(const std::vector<std::string> &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 CVarManager::suppressDeveloper()
|
||||||
{
|
{
|
||||||
bool oldDeveloper = com_developer->toBoolean();
|
bool oldDeveloper = com_developer->toBoolean();
|
||||||
|
|
|
@ -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", "<command>", 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", "<cvar> <value>", std::bind(&CVarManager::setCVar, cvarMgr, std::placeholders::_1));
|
||||||
|
registerCommand("getCVar", "Prints the value stored in the specified Console Variable", "<cvar>", 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<void(const std::vector<std::__cxx11::string> &)>&& 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<std::string> commands = athena::utility::split(str, ';');
|
||||||
|
|
||||||
|
if (commands.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (std::string command : commands)
|
||||||
|
{
|
||||||
|
command = athena::utility::trim(command);
|
||||||
|
std::vector<std::string> 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<std::string>& args)
|
||||||
|
{
|
||||||
|
if (args.empty())
|
||||||
|
{
|
||||||
|
print(Level::Info, "Expected usage: help <command>");
|
||||||
|
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<std::string>& /*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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue