2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-08 22:27:43 +00:00

Refactor CVar class

This commit is contained in:
2018-01-15 04:34:02 -08:00
parent 4543e2a87e
commit 5c66ffc5df
9 changed files with 585 additions and 676 deletions

View File

@@ -1,6 +1,5 @@
#include "hecl/hecl.hpp"
#include "hecl/CVar.hpp"
#include "hecl/CVarManager.hpp"
#include <athena/Utility.hpp>
#include <algorithm>
@@ -8,427 +7,40 @@
namespace hecl
{
extern CVar* com_developer;
extern CVar* com_enableCheats;
using namespace std::literals;
extern BoolCVar* com_developer;
extern BoolCVar* com_enableCheats;
CVar::CVar(std::string_view name, std::string_view value, std::string_view help, EType type, EFlags flags, CVarManager& parent)
: m_mgr(parent)
CVar::CVar(std::string_view name, std::string_view help, CVar::EFlags flags)
: m_name(name)
, m_help(help)
, m_flags(flags)
{
m_name = std::string(name);
m_value = std::string(value);
m_defaultValue = std::string(value);
m_help = help;
m_type = type;
m_flags = flags;
}
CVar::CVar(std::string_view name, std::string_view value, std::string_view help, CVar::EFlags flags, CVarManager& parent)
: m_mgr(parent)
{
m_flags = flags;
m_name = std::string(name);
m_help = help;
m_type = EType::Literal;
// Unlock the cvar for writing if readonly
unlock();
fromLiteral(value);
m_defaultValue = m_value;
// Lock the cvar
lock();
// Clear the modified flag, just incase lock didn't do it.
m_flags = flags;
}
CVar::CVar(std::string_view name, const atVec4f& value, std::string_view help, EFlags flags, CVarManager& parent)
: m_mgr(parent)
{
m_name = std::string(name);
m_help = help;
m_type = EType::Vec4f;
m_flags = flags;
// Unlock the cvar for writing if readonly
unlock();
fromVec4f(value);
m_defaultValue = m_value;
// Lock the cvar
lock();
// Clear the modified flag, just incase lock didn't do it.
m_flags = flags;
}
CVar::CVar(std::string_view name, float value, std::string_view help, EFlags flags, CVarManager& parent)
: m_mgr(parent)
{
m_name = std::string(name);
m_help = help;
m_type = EType::Float;
m_flags = flags;
// Unlock the cvar for writing if readonly
unlock();
fromFloat(value);
m_defaultValue = m_value;
// Lock the cvar
lock();
// Clear the modified flag, just incase lock didn't do it.
m_flags = flags;
}
CVar::CVar(std::string_view name, bool value, std::string_view help, CVar::EFlags flags, CVarManager& parent)
: m_mgr(parent)
{
m_name = std::string(name);
m_help = help;
m_type = EType::Boolean;
m_flags = flags;
// Unlock the cvar for writing if readonly
unlock();
fromBoolean(value);
m_defaultValue = m_value;
// Lock the cvar
lock();
// Clear the modified flag, just incase lock didn't do it.
m_flags = flags;
}
CVar::CVar(std::string_view name, int value, std::string_view help, CVar::EFlags flags, CVarManager& parent)
: m_mgr(parent)
{
m_name = std::string(name);
m_help = help;
m_type = EType::Integer;
m_flags = flags;
// Unlock the cvar for writing if readonly
unlock();
fromInteger(value);
m_defaultValue = m_value;
// Lock the cvar
lock();
// Clear the modified flag, just incase lock didn't do it.
m_flags = flags;
}
std::string CVar::help() const
{
return std::string(m_help + (m_defaultValue != std::string() ? "\ndefault: " + m_defaultValue : "") +
(isReadOnly() ? "[ReadOnly]" : ""));
return std::string(m_help + (hasDefaultValue() ? " (default: " + defaultValueString() : "") +
(isReadOnly() ? " [ReadOnly]" : "")) + ")";
}
atVec4f CVar::toVec4f(bool* isValid) const
bool CVar::fromString(std::string_view v)
{
if (m_type != EType::Vec4f)
{
if (isValid != nullptr)
*isValid = false;
return atVec4f{};
}
if (isValid != nullptr)
*isValid = true;
atVec4f vec;
std::sscanf(m_value.c_str(), "%f %f %f %f", &vec.vec[0], &vec.vec[1], &vec.vec[2], &vec.vec[3]);
return vec;
}
float CVar::toFloat(bool* isValid) const
{
if (m_type != EType::Float)
{
if (isValid)
*isValid = false;
return 0.0f;
}
return strtof(m_value.c_str(), nullptr);
}
bool CVar::toBoolean(bool* isValid) const
{
if (m_type != EType::Boolean)
{
if (isValid)
*isValid = false;
return false;
}
// We don't want to modify the original value;
std::string tmp = m_value;
athena::utility::tolower(tmp);
if (!tmp.compare("yes") || !tmp.compare("true") || !tmp.compare("1"))
{
if (isValid)
*isValid = true;
return true;
}
else if (!tmp.compare("no") || !tmp.compare("false") || !tmp.compare("0"))
{
if (isValid)
*isValid = true;
return false;
}
if (isValid)
*isValid = false;
return false;
}
int CVar::toInteger(bool* isValid) const
{
if (m_type != EType::Integer)
{
if (isValid)
*isValid = false;
return 0;
}
return strtol(m_value.c_str(), nullptr, 0);
}
const std::string CVar::toLiteral(bool* isValid) const
{
if (m_type != EType::Literal && (com_developer && com_developer->toBoolean()))
{
if (isValid != nullptr)
*isValid = false;
}
else if (isValid != nullptr)
*isValid = true;
// Even if it's not a literal, it's still safe to return
return m_value;
}
const std::wstring CVar::toWideLiteral(bool* isValid) const
{
if (m_type != EType::Literal && (com_developer && com_developer->toBoolean()))
{
if (isValid != nullptr)
*isValid = false;
}
else if (isValid != nullptr)
*isValid = true;
// Even if it's not a literal, it's still safe to return
return hecl::UTF8ToWide(m_value);
}
bool CVar::fromVec4f(const atVec4f& val)
{
if (isCheat() && (com_developer && !com_developer->toBoolean() && !com_enableCheats->toBoolean()))
if (isCheat() && (com_developer && !com_developer->value() && !com_enableCheats->value()))
return false;
else if (isCheat())
return false;
if (m_type != EType::Vec4f)
if (isReadOnly() && (com_developer && !com_developer->value()))
return false;
if (isReadOnly() && (com_developer && !com_developer->toBoolean()))
return false;
m_value.assign(hecl::Format("%f %f %f %f", val.vec[0], val.vec[1], val.vec[2], val.vec[3]));
m_flags |= EFlags::Modified;
return true;
bool ret = _fromString(v);
if (ret)
m_flags |= EFlags::Modified;
return ret;
}
bool CVar::fromFloat(float val)
{
if (isCheat() && (com_developer && !com_developer->toBoolean() && !com_enableCheats->toBoolean()))
return false;
else if (isCheat())
return false;
if (m_type != EType::Float)
return false;
if (isReadOnly() && (com_developer && !com_developer->toBoolean()))
return false;
m_value.assign(hecl::Format("%f", val));
setModified();
return true;
}
bool CVar::fromBoolean(bool val)
{
if (isCheat() && (com_developer && !com_developer->toBoolean() && !com_enableCheats->toBoolean()))
return false;
else if (isCheat())
return false;
if (m_type != EType::Boolean)
return false;
if (isReadOnly() && (com_developer && !com_developer->toBoolean()))
return false;
if (val)
m_value = "true"sv;
else
m_value = "false"sv;
setModified();
return true;
}
bool CVar::fromInteger(int val)
{
if (isCheat() && (com_developer && !com_developer->toBoolean() && !com_enableCheats->toBoolean()))
return false;
else if (isCheat())
return false;
if (m_type != EType::Integer)
return false;
if (isReadOnly() && (com_developer && !com_developer->toBoolean()))
return false;
m_value = hecl::Format("%i", val);
setModified();
return true;
}
bool CVar::fromLiteral(std::string_view val)
{
if (isCheat() && (com_developer && !com_developer->toBoolean() && !com_enableCheats->toBoolean()))
return false;
else if (isCheat())
return false;
if (m_type != EType::Literal)
return false;
if (isReadOnly() && (com_developer && !com_developer->toBoolean()))
return false;
m_value.assign(val);
setModified();
return true;
}
bool CVar::fromLiteral(std::wstring_view val)
{
if (isCheat() && (com_developer && !com_developer->toBoolean() && !com_enableCheats->toBoolean()))
return false;
else if (isCheat())
return false;
if (m_type != EType::Literal)
return false;
if (isReadOnly() && (com_developer && !com_developer->toBoolean()))
return false;
m_value.assign(hecl::WideToUTF8(val));
setModified();
return true;
}
bool CVar::fromLiteralToType(std::string_view val, bool setDefault)
{
switch (m_type)
{
case EType::Literal: return fromLiteral(val);
case EType::Boolean:
{
std::stringstream ss;
ss << std::boolalpha << val;
bool v;
ss >> v;
return fromBoolean(v);
}
case EType::Float:
{
std::stringstream ss;
ss << val;
float v;
ss >> v;
return fromFloat(v);
}
case EType::Integer:
{
std::stringstream ss;
ss << val;
int v;
ss >> v;
return fromInteger(v);
}
case EType::Vec4f:
{
atVec4f vec;
std::sscanf(val.data(), "%f %f %f %f", &vec.vec[0], &vec.vec[1], &vec.vec[2], &vec.vec[3]);
return fromVec4f(vec);
}
}
if (setDefault)
m_value = m_defaultValue;
return false;
}
bool CVar::fromLiteralToType(std::wstring_view val, bool setDefault)
{
switch (m_type)
{
case EType::Literal: return fromLiteral(val);
case EType::Boolean:
{
std::wstringstream ss;
ss << std::boolalpha << val;
bool v;
ss >> v;
return fromBoolean(v);
}
case EType::Float:
{
std::wstringstream ss;
ss << val;
float v;
ss >> v;
return fromFloat(v);
}
case EType::Integer:
{
std::wstringstream ss;
ss << val;
int v;
ss >> v;
return fromInteger(v);
}
case EType::Vec4f:
{
atVec4f vec;
std::swscanf(val.data(), L"%f %f %f %f", &vec.vec[0], &vec.vec[1], &vec.vec[2], &vec.vec[3]);
return fromVec4f(vec);
}
}
if (setDefault)
m_value = m_defaultValue;
return false;
}
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; }
@@ -443,8 +55,6 @@ bool CVar::isInternalArchivable() const { return int(m_flags & EFlags::InternalA
bool CVar::wasDeserialized() const { return m_wasDeserialized; }
bool CVar::hasDefaultValue() const { return m_defaultValue == m_value; }
void CVar::clearModified()
{
if (!modificationRequiresRestart())
@@ -472,10 +82,293 @@ void CVar::lock()
}
}
void CVar::dispatch()
template <typename T>
TCVar<T>::TCVar(T& value, std::string_view name, std::string_view description, EFlags flags)
: CVar(name, description, flags)
, m_value(value)
, m_defaultValue(value)
{
for (const ListenerFunc& listen : m_listeners)
listen(this);
}
}
template<typename T>
std::string TCVar<T>::toString() const
{
std::stringstream ss;
ss << std::boolalpha << m_value;
return ss.str();
}
template<typename T>
std::wstring TCVar<T>::toWideString() const
{
return hecl::UTF8ToWide(toString());
}
template<typename T>
bool TCVar<T>::_fromString(std::string_view v)
{
T tmp;
std::stringstream ss;
ss << std::boolalpha << v;
ss >> tmp;
if (ss.good())
m_value = tmp;
return ss.good();
}
template<typename T>
void TCVar<T>::deserialize(athena::io::YAMLDocReader &reader)
{
m_value = reader.readVal<T>(m_name.c_str());
}
template<typename T>
void TCVar<T>::serialize(athena::io::YAMLDocWriter& writer) const
{
writer.writeVal(m_name.c_str(), m_value);
}
template<typename T>
bool TCVar<T>::hasDefaultValue() const
{
return m_value == m_defaultValue;
}
template<typename T>
T TCVar<T>::value() const
{
return m_value;
}
template<typename T>
T TCVar<T>::defaultValue() const
{
return m_defaultValue;
}
template<typename T>
std::string TCVar<T>::defaultValueString() const
{
std::stringstream ss;
ss << std::boolalpha << m_defaultValue;
return ss.str();
}
Vec3fCVar::Vec3fCVar(atVec3f &value, std::string_view name, std::string_view description, CVar::EFlags flags)
: CVar(name, description, flags)
, m_value(value)
, m_defaultValue(value)
{}
std::string Vec3fCVar::toString() const
{
return athena::utility::sprintf("%f %f %f", double(m_value.vec[0]), double(m_value.vec[1]), double(m_value.vec[2]));
}
bool Vec3fCVar::_fromString(std::string_view v)
{
float x, y, z;
if (std::sscanf(v.data(), "%f %f %f", &x, &y, &z) != 3)
return false;
m_value.vec[0] = x;
m_value.vec[1] = y;
m_value.vec[2] = y;
return true;
}
bool Vec3fCVar::hasDefaultValue() const
{
return !memcmp(&m_value.vec, &m_defaultValue.vec[0], sizeof(atVec3f));
}
void Vec3fCVar::deserialize(athena::io::YAMLDocReader& reader)
{
m_value = reader.readVec3f(m_name.c_str());
}
void Vec3fCVar::serialize(athena::io::YAMLDocWriter& writer) const
{
writer.writeVec3f(m_name.c_str(), m_value);
}
std::string Vec3fCVar::defaultValueString() const
{
return athena::utility::sprintf("%f %f %f", double(m_defaultValue.vec[0]), double(m_defaultValue.vec[1]), double(m_defaultValue.vec[2]));
}
Vec3dCVar::Vec3dCVar(atVec3d &value, std::string_view name, std::string_view description, CVar::EFlags flags)
: CVar(name, description, flags)
, m_value(value)
, m_defaultValue(value)
{}
std::string Vec3dCVar::toString() const
{
return athena::utility::sprintf("%lf %lf %lf", m_value.vec[0], m_value.vec[1], m_value.vec[2]);
}
bool Vec3dCVar::_fromString(std::string_view v)
{
double x, y, z;
if (std::sscanf(v.data(), "%lf %lf %lf", &x, &y, &z) != 3)
return false;
m_value.vec[0] = x;
m_value.vec[1] = y;
m_value.vec[2] = y;
return true;
}
bool Vec3dCVar::hasDefaultValue() const
{
return !memcmp(&m_value.vec, &m_defaultValue.vec[0], sizeof(atVec3d));
}
void Vec3dCVar::deserialize(athena::io::YAMLDocReader& reader)
{
m_value = reader.readVec3d(m_name.c_str());
}
void Vec3dCVar::serialize(athena::io::YAMLDocWriter& writer) const
{
writer.writeVec3d(m_name.c_str(), m_value);
}
std::string Vec3dCVar::defaultValueString() const
{
return athena::utility::sprintf("%g %g %g", m_defaultValue.vec[0], m_defaultValue.vec[1], m_defaultValue.vec[2]);
}
Vec4fCVar::Vec4fCVar(atVec4f &value, std::string_view name, std::string_view description, CVar::EFlags flags)
: CVar(name, description, flags)
, m_value(value)
, m_defaultValue(value)
{}
std::string Vec4fCVar::toString() const
{
return athena::utility::sprintf("%g %g %g %g", &m_value.vec[0], &m_value.vec[1], &m_value.vec[2], &m_value.vec[3]);
}
bool Vec4fCVar::_fromString(std::string_view v)
{
float x, y, z, w;
if (std::sscanf(v.data(), "%f %f %f %f", &x, &y, &z, &w) != 4)
return false;
m_value.vec[0] = x;
m_value.vec[1] = y;
m_value.vec[2] = y;
m_value.vec[3] = w;
return true;
}
bool Vec4fCVar::hasDefaultValue() const
{
return !memcmp(&m_value.vec, &m_defaultValue.vec[0], sizeof(atVec4f));
}
void Vec4fCVar::deserialize(athena::io::YAMLDocReader& reader)
{
m_value = reader.readVec4f(m_name.c_str());
}
void Vec4fCVar::serialize(athena::io::YAMLDocWriter& writer) const
{
writer.writeVec4f(m_name.c_str(), m_value);
}
std::string Vec4fCVar::defaultValueString() const
{
return athena::utility::sprintf("%f %f %f", &m_defaultValue.vec[0], &m_defaultValue.vec[1], &m_defaultValue.vec[2]);
}
Vec4dCVar::Vec4dCVar(atVec4d &value, std::string_view name, std::string_view description, CVar::EFlags flags)
: CVar(name, description, flags)
, m_value(value)
, m_defaultValue(value)
{}
std::string Vec4dCVar::toString() const
{
return athena::utility::sprintf("%f %f %f %f", m_value.vec[0], m_value.vec[1], m_value.vec[2], m_value.vec[3]);
}
bool Vec4dCVar::_fromString(std::string_view v)
{
double x, y, z, w;
if (std::sscanf(v.data(), "%lf %lf %lf %lf", &x, &y, &z, &w) != 4)
return false;
m_value.vec[0] = x;
m_value.vec[1] = y;
m_value.vec[2] = y;
m_value.vec[3] = w;
return true;
}
bool Vec4dCVar::hasDefaultValue() const
{
return !memcmp(&m_value.vec, &m_defaultValue.vec[0], sizeof(atVec4d));
}
void Vec4dCVar::deserialize(athena::io::YAMLDocReader& reader)
{
m_value = reader.readVec4d(m_name.c_str());
}
void Vec4dCVar::serialize(athena::io::YAMLDocWriter& writer) const
{
writer.writeVec4d(m_name.c_str(), m_value);
}
std::string Vec4dCVar::defaultValueString() const
{
return athena::utility::sprintf("%g %g %g", m_defaultValue.vec[0], m_defaultValue.vec[1], m_defaultValue.vec[2]);
}
StringCVar::StringCVar(std::string& value, std::string_view name, std::string_view help, CVar::EFlags flags)
: CVar(name, help, flags)
, m_value(value)
, m_defaultValue(value)
{
}
std::string StringCVar::toString() const
{
return m_value;
}
bool StringCVar::_fromString(std::string_view v)
{
m_value = v;
return true;
}
bool StringCVar::hasDefaultValue() const
{
return m_value == m_defaultValue;
}
void StringCVar::deserialize(athena::io::YAMLDocReader& reader)
{
m_value = reader.readString(m_name.c_str());
}
void StringCVar::serialize(athena::io::YAMLDocWriter& writer) const
{
writer.writeString(m_name.c_str(), m_value.c_str());
}
template class TCVar<bool>;
template class TCVar<int16_t>;
template class TCVar<uint16_t>;
template class TCVar<int32_t>;
template class TCVar<uint32_t>;
template class TCVar<int64_t>;
template class TCVar<uint64_t>;
template class TCVar<float>;
template class TCVar<double>;
}