Archived
1
Fork 0

Add console variable support

This commit is contained in:
redstrate 2020-09-22 22:43:30 -04:00
parent df0d5d1ad4
commit 83b47b31b4
4 changed files with 101 additions and 7 deletions

View file

@ -4,16 +4,31 @@
#include <functional> #include <functional>
#include <vector> #include <vector>
#include <variant> #include <variant>
#include <string>
namespace console { namespace console {
using ConsoleArgument = std::variant<std::string, int, bool>;
enum class ArgType { enum class ArgType {
String, String,
Integer, Integer,
Boolean Boolean
}; };
struct ConsoleArgument {
ConsoleArgument(bool data) : data(data) {}
ConsoleArgument(int data) : data(data) {}
ArgType query_type() const {
if(std::holds_alternative<std::string>(data))
return ArgType::String;
else if(std::holds_alternative<int>(data))
return ArgType::Integer;
else if(std::holds_alternative<bool>(data))
return ArgType::Boolean;
}
std::variant<std::string, int, bool> data;
};
struct Arguments { struct Arguments {
std::vector<ConsoleArgument> arguments; std::vector<ConsoleArgument> arguments;
}; };
@ -30,4 +45,7 @@ namespace console {
void register_command(const std::string_view name, const ArgumentFormat expected_format, const FunctionPtr function); void register_command(const std::string_view name, const ArgumentFormat expected_format, const FunctionPtr function);
void invoke_command(const std::string_view name, const Arguments arguments); void invoke_command(const std::string_view name, const Arguments arguments);
void parse_and_invoke_command(const std::string_view command);
void register_variable(const std::string_view name, bool& variable);
} }

View file

@ -4,6 +4,7 @@
#include <string> #include <string>
#include "log.hpp" #include "log.hpp"
#include "string_utils.hpp"
struct RegisteredCommand { struct RegisteredCommand {
RegisteredCommand(const console::ArgumentFormat format, const console::FunctionPtr function) : expected_format(format), function(function) {} RegisteredCommand(const console::ArgumentFormat format, const console::FunctionPtr function) : expected_format(format), function(function) {}
@ -14,6 +15,16 @@ struct RegisteredCommand {
static std::unordered_map<std::string, RegisteredCommand> registered_commands; static std::unordered_map<std::string, RegisteredCommand> registered_commands;
struct RegisteredVariable {
RegisteredVariable(bool& data) : type(console::ArgType::Boolean), data(&data) {}
console::ArgType type;
std::variant<bool*> data;
};
static std::unordered_map<std::string, RegisteredVariable> registered_variables;
void console::register_command(const std::string_view name, const ArgumentFormat expected_format, const console::FunctionPtr function) { void console::register_command(const std::string_view name, const ArgumentFormat expected_format, const console::FunctionPtr function) {
registered_commands.try_emplace(name.data(), RegisteredCommand(expected_format, function)); registered_commands.try_emplace(name.data(), RegisteredCommand(expected_format, function));
} }
@ -36,5 +47,70 @@ void console::invoke_command(const std::string_view name, const Arguments argume
} }
} }
console::info(System::Core, "{} is not a valid command!", name.data()); for(auto& [variable_name, variable_data] : registered_variables) {
if(variable_name == name) {
bool invalid_format = false;
if(arguments.arguments.empty())
invalid_format = true;
if(arguments.arguments[0].query_type() != variable_data.type)
invalid_format = true;
if(invalid_format) {
console::info(System::Core, "Wrong or empty variable type!");
} else {
auto argument = arguments.arguments[0];
switch(argument.query_type()) {
case console::ArgType::Boolean:
*std::get<bool*>(variable_data.data) = std::get<bool>(argument.data);
break;
}
}
return;
}
}
console::info(System::Core, "{} is not the name of a valid command or variable!", name.data());
}
bool is_number(const std::string_view& s)
{
return !s.empty() && std::find_if(s.begin(),
s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}
void console::parse_and_invoke_command(const std::string_view command) {
const auto tokens = tokenize(command, " ");
if(tokens.empty())
return;
const auto try_parse_argument = [](std::string_view arg) -> std::optional<ConsoleArgument> {
if(arg == "true") {
return ConsoleArgument(true);
} else if(arg == "false") {
return ConsoleArgument(false);
} else if(is_number(arg)) {
return ConsoleArgument(std::stoi(arg.data()));
}
return std::nullopt;
};
std::vector<ConsoleArgument> arguments;
for(int i = 1; i < tokens.size(); i++) {
if(auto arg = try_parse_argument(tokens[i]); arg)
arguments.push_back(*arg);
}
console::Arguments args;
args.arguments = arguments;
console::invoke_command(tokens[0], args);
}
void console::register_variable(const std::string_view name, bool& variable) {
registered_variables.try_emplace(name.data(), RegisteredVariable(variable));
} }

View file

@ -29,12 +29,12 @@ Engine::Engine(const int argc, char* argv[]) {
console::info(System::Core, "Test cmd!"); console::info(System::Core, "Test cmd!");
}); });
console::register_variable("rs_dynamic_resolution", render_options.dynamic_resolution);
console::register_command("quit", console::ArgumentFormat(0), [this](const console::Arguments) { console::register_command("quit", console::ArgumentFormat(0), [this](const console::Arguments) {
quit(); quit();
}); });
console::invoke_command("test_cmd", console::Arguments());
for(int i = 0; i < argc; i++) for(int i = 0; i < argc; i++)
command_line_arguments.push_back(argv[i]); command_line_arguments.push_back(argv[i]);

View file

@ -1040,7 +1040,7 @@ void CommonEditor::drawConsole() {
ImGui::SameLine(); ImGui::SameLine();
if(ImGui::Button("Run")) { if(ImGui::Button("Run")) {
console::invoke_command(command_buffer, console::Arguments()); console::parse_and_invoke_command(command_buffer);
command_buffer.clear(); command_buffer.clear();
} }