Skip to content

Commit

Permalink
Implemented basic console variable support (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChunkTreasure1 authored Dec 29, 2023
2 parents 829cb27 + d6d7ea9 commit 7b12987
Show file tree
Hide file tree
Showing 2 changed files with 252 additions and 1 deletion.
68 changes: 67 additions & 1 deletion Volt/Sandbox/src/Sandbox/Window/LogPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

#include <Volt/Log/Log.h>
#include <Volt/Utility/UIUtility.h>
#include <Volt/Utility/StringUtility.h>

#include <Volt/Console/ConsoleVariableRegistry.h>

namespace Utility
{
Expand Down Expand Up @@ -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<const float*>(variable->Get()));
}
else if (variable->IsInteger())
{
message += std::to_string(*static_cast<const int32_t*>(variable->Get()));
}
else if (variable->IsString())
{
message += *static_cast<const std::string*>(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)
Expand Down
185 changes: 185 additions & 0 deletions Volt/Volt/src/Volt/Console/ConsoleVariableRegistry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
#pragma once

#include "Volt/Core/Base.h"

#include "Volt/Utility/StringUtility.h"

#include <unordered_map>
#include <string_view>

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<typename T>
concept ValidConsoleVariableType = std::is_same_v<T, int32_t> || std::is_same_v<T, float> || std::is_same_v<T, std::string>;

template<ValidConsoleVariableType T>
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<T>; }
[[nodiscard]] inline constexpr bool IsFloat() const override { return std::is_floating_point_v<T>; }
[[nodiscard]] inline constexpr bool IsString() const override { return std::is_same_v<T, std::string>; }

private:
T m_value;
std::string m_variableName;
std::string_view m_description;
};

template<ValidConsoleVariableType T>
class ConsoleVariable
{
public:
ConsoleVariable(std::string_view variableName, const T& defaultValue, std::string_view description);

const T& GetValue() const { return *reinterpret_cast<T*>(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<RegisteredConsoleVariable<T>> m_variableReference;
};

template<ValidConsoleVariableType T>
class ConsoleVariableRef
{
public:
ConsoleVariableRef(std::string_view variableName);

const T& GetValue() const { return *reinterpret_cast<T*>(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<RegisteredConsoleVariable<T>> m_variableReference;
};

class ConsoleVariableRegistry
{
public:
template<ValidConsoleVariableType T>
static Weak<RegisteredConsoleVariable<T>> RegisterVariable(std::string_view variableName, const T& defaultValue, std::string_view description);

template<ValidConsoleVariableType T>
static Weak<RegisteredConsoleVariable<T>> FindVariable(const std::string& variableName);

inline static Weak<RegisteredConsoleVariableBase> GetVariable(const std::string& variableName);
inline static bool VariableExists(const std::string& variableName);

static std::unordered_map<std::string, Ref<RegisteredConsoleVariableBase>>& GetRegisteredVariables() { return s_registeredVariables; }

private:
ConsoleVariableRegistry() = delete;

inline static std::unordered_map<std::string, Ref<RegisteredConsoleVariableBase>> s_registeredVariables;
};

inline bool ConsoleVariableRegistry::VariableExists(const std::string& variableName)
{
std::string tempVarName = ::Utility::ToLower(std::string(variableName));
return s_registeredVariables.contains(tempVarName);
}

template<ValidConsoleVariableType T>
inline RegisteredConsoleVariable<T>::RegisteredConsoleVariable(const std::string& variableName, const T& defaultValue, std::string_view description)
: m_value(defaultValue), m_variableName(variableName), m_description(description)
{
}

template<ValidConsoleVariableType T>
inline const void* RegisteredConsoleVariable<T>::Get() const
{
return reinterpret_cast<const void*>(&m_value);
}

template<ValidConsoleVariableType T>
inline void RegisteredConsoleVariable<T>::Set(const void* value)
{
m_value = *reinterpret_cast<const T*>(value);
}

template<ValidConsoleVariableType T>
inline ConsoleVariable<T>::ConsoleVariable(std::string_view variableName, const T& defaultValue, std::string_view description)
{
m_variableReference = ConsoleVariableRegistry::RegisterVariable<T>(variableName, defaultValue, description);
}

template<ValidConsoleVariableType T>
inline Weak<RegisteredConsoleVariable<T>> ConsoleVariableRegistry::RegisterVariable(std::string_view variableName, const T& defaultValue, std::string_view description)
{
std::string tempVarName = ::Utility::ToLower(std::string(variableName));

Ref<RegisteredConsoleVariable<T>> consoleVariable = CreateRef<RegisteredConsoleVariable<T>>(tempVarName, defaultValue, description);

VT_CORE_ASSERT(!s_registeredVariables.contains(tempVarName), "Command variable with name already registered!");
s_registeredVariables[tempVarName] = consoleVariable;

return consoleVariable;
}

template<ValidConsoleVariableType T>
inline Weak<RegisteredConsoleVariable<T>> 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<RegisteredConsoleVariable<T>>();
}

template<ValidConsoleVariableType T>
inline ConsoleVariableRef<T>::ConsoleVariableRef(std::string_view variableName)
{
m_variableReference = ConsoleVariableRegistry::FindVariable(variableName);
VT_CORE_ASSERT(m_variableReference, "Variable with name not found!");
}

inline Weak<RegisteredConsoleVariableBase> ConsoleVariableRegistry::GetVariable(const std::string& variableName)
{
const std::string tempVarName = ::Utility::ToLower(variableName);
return s_registeredVariables.at(tempVarName);
}
}

0 comments on commit 7b12987

Please sign in to comment.