diff --git a/Volt/Sandbox/src/Sandbox/Window/LogPanel.cpp b/Volt/Sandbox/src/Sandbox/Window/LogPanel.cpp index 1216446f4..53a82d4eb 100644 --- a/Volt/Sandbox/src/Sandbox/Window/LogPanel.cpp +++ b/Volt/Sandbox/src/Sandbox/Window/LogPanel.cpp @@ -3,6 +3,9 @@ #include #include +#include + +#include namespace Utility { @@ -48,10 +51,73 @@ void LogPanel::UpdateMainContent() myCategories.emplace_back("Default"); } + ImGui::SameLine(); + ImGui::PushItemWidth(200.f); + + static std::string commandStr; + + if (ImGui::InputTextWithHintString("##commandLine", "Command...", &commandStr, ImGuiInputTextFlags_EnterReturnsTrue)) + { + auto strings = Utility::SplitStringsByCharacter(commandStr, ' '); + if (!strings.empty()) + { + if (Volt::ConsoleVariableRegistry::VariableExists(strings[0])) + { + auto variable = Volt::ConsoleVariableRegistry::GetVariable(strings[0]); + + std::string message = std::string(variable->GetName()) + " = "; + + if (strings.size() > 1) + { + if (variable->IsFloat()) + { + const float value = std::stof(strings[1]); + variable->Set(&value); + } + else if (variable->IsInteger()) + { + const int32_t value = std::stoi(strings[1]); + variable->Set(&value); + } + else if (variable->IsString()) + { + variable->Set(&strings[1]); + } + + message += strings[1]; + } + else + { + if (variable->IsFloat()) + { + message += std::to_string(*static_cast(variable->Get())); + } + else if (variable->IsInteger()) + { + message += std::to_string(*static_cast(variable->Get())); + } + else if (variable->IsString()) + { + message += *static_cast(variable->Get()); + } + + } + + VT_CORE_TRACE(message); + } + else + { + VT_CORE_TRACE("Command {0} not found!", strings[0]); + } + } + + commandStr = ""; + } + + ImGui::SameLine(); static int32_t logLevel = 0; - ImGui::PushItemWidth(200.f); if (ImGui::Combo("##level", &logLevel, "Trace\0Info\0Warning\0Error\0Critical")) { switch (logLevel) diff --git a/Volt/Volt/src/Volt/Console/ConsoleVariableRegistry.h b/Volt/Volt/src/Volt/Console/ConsoleVariableRegistry.h new file mode 100644 index 000000000..9eb5f72da --- /dev/null +++ b/Volt/Volt/src/Volt/Console/ConsoleVariableRegistry.h @@ -0,0 +1,185 @@ +#pragma once + +#include "Volt/Core/Base.h" + +#include "Volt/Utility/StringUtility.h" + +#include +#include + +namespace Volt +{ + class RegisteredConsoleVariableBase + { + public: + virtual const void* Get() const = 0; + virtual void Set(const void* value) = 0; + + virtual std::string_view GetName() const = 0; + virtual std::string_view GetDescription() const = 0; + + virtual bool IsInteger() const = 0; + virtual bool IsFloat() const = 0; + virtual bool IsString() const = 0; + }; + + template + concept ValidConsoleVariableType = std::is_same_v || std::is_same_v || std::is_same_v; + + template + class RegisteredConsoleVariable : public RegisteredConsoleVariableBase + { + public: + RegisteredConsoleVariable(const std::string& variableName, const T& defaultValue, std::string_view description); + + [[nodiscard]] const void* Get() const override; + void Set(const void* value) override; + + [[nodiscard]] inline std::string_view GetName() const override { return m_variableName; } + [[nodiscard]] inline std::string_view GetDescription() const override { return m_description; } + + [[nodiscard]] inline constexpr bool IsInteger() const override { return std::is_integral_v; } + [[nodiscard]] inline constexpr bool IsFloat() const override { return std::is_floating_point_v; } + [[nodiscard]] inline constexpr bool IsString() const override { return std::is_same_v; } + + private: + T m_value; + std::string m_variableName; + std::string_view m_description; + }; + + template + class ConsoleVariable + { + public: + ConsoleVariable(std::string_view variableName, const T& defaultValue, std::string_view description); + + const T& GetValue() const { return *reinterpret_cast(m_variableReference->Get()); } + void SetValue(const T& value) { m_variableReference->Set(&value); } + + T& operator=(const T& other) + { + if (this == &other) + { + return GetValue(); + } + + SetValue(other); + } + + private: + Weak> m_variableReference; + }; + + template + class ConsoleVariableRef + { + public: + ConsoleVariableRef(std::string_view variableName); + + const T& GetValue() const { return *reinterpret_cast(m_variableReference->Get()); } + void SetValue(const T& value) { m_variableReference->Set(&value); } + + T& operator=(const T& other) + { + if (this == &other) + { + return GetValue(); + } + + SetValue(other); + } + + private: + Weak> m_variableReference; + }; + + class ConsoleVariableRegistry + { + public: + template + static Weak> RegisterVariable(std::string_view variableName, const T& defaultValue, std::string_view description); + + template + static Weak> FindVariable(const std::string& variableName); + + inline static Weak GetVariable(const std::string& variableName); + inline static bool VariableExists(const std::string& variableName); + + static std::unordered_map>& GetRegisteredVariables() { return s_registeredVariables; } + + private: + ConsoleVariableRegistry() = delete; + + inline static std::unordered_map> s_registeredVariables; + }; + + inline bool ConsoleVariableRegistry::VariableExists(const std::string& variableName) + { + std::string tempVarName = ::Utility::ToLower(std::string(variableName)); + return s_registeredVariables.contains(tempVarName); + } + + template + inline RegisteredConsoleVariable::RegisteredConsoleVariable(const std::string& variableName, const T& defaultValue, std::string_view description) + : m_value(defaultValue), m_variableName(variableName), m_description(description) + { + } + + template + inline const void* RegisteredConsoleVariable::Get() const + { + return reinterpret_cast(&m_value); + } + + template + inline void RegisteredConsoleVariable::Set(const void* value) + { + m_value = *reinterpret_cast(value); + } + + template + inline ConsoleVariable::ConsoleVariable(std::string_view variableName, const T& defaultValue, std::string_view description) + { + m_variableReference = ConsoleVariableRegistry::RegisterVariable(variableName, defaultValue, description); + } + + template + inline Weak> ConsoleVariableRegistry::RegisterVariable(std::string_view variableName, const T& defaultValue, std::string_view description) + { + std::string tempVarName = ::Utility::ToLower(std::string(variableName)); + + Ref> consoleVariable = CreateRef>(tempVarName, defaultValue, description); + + VT_CORE_ASSERT(!s_registeredVariables.contains(tempVarName), "Command variable with name already registered!"); + s_registeredVariables[tempVarName] = consoleVariable; + + return consoleVariable; + } + + template + inline Weak> ConsoleVariableRegistry::FindVariable(const std::string& variableName) + { + const std::string tempVarName = ::Utility::ToLower(variableName); + + if (s_registeredVariables.contains(tempVarName)) + { + return s_registeredVariables.at(tempVarName); + } + + return Weak>(); + } + + template + inline ConsoleVariableRef::ConsoleVariableRef(std::string_view variableName) + { + m_variableReference = ConsoleVariableRegistry::FindVariable(variableName); + VT_CORE_ASSERT(m_variableReference, "Variable with name not found!"); + } + + inline Weak ConsoleVariableRegistry::GetVariable(const std::string& variableName) + { + const std::string tempVarName = ::Utility::ToLower(variableName); + return s_registeredVariables.at(tempVarName); + } +}