mirror of https://github.com/AxioDL/metaforce.git
parent
cc4264cc2b
commit
fd8f72c5f0
|
@ -1,5 +1,6 @@
|
|||
make_dnalist(liblist
|
||||
CMDL)
|
||||
CMDL
|
||||
CVar)
|
||||
add_library(DNACommon
|
||||
DNACommon.hpp DNACommon.cpp
|
||||
${liblist}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
#ifndef _DNACOMMON_CVAR_HPP_
|
||||
#define _DNACOMMON_CVAR_HPP_
|
||||
|
||||
#include <Athena/Global.hpp>
|
||||
#include <type_traits>
|
||||
#include "DNACommon.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
namespace DNACVAR
|
||||
{
|
||||
enum class EType
|
||||
{
|
||||
Boolean,
|
||||
Integer,
|
||||
Float,
|
||||
Literal,
|
||||
Color,
|
||||
Bind
|
||||
};
|
||||
|
||||
enum EFlags
|
||||
{
|
||||
All = -1, // NOTE: is this really necessary? It seems rather overkill
|
||||
System = (1 << 0),
|
||||
Game = (1 << 1),
|
||||
Gui = (1 << 2),
|
||||
Cheat = (1 << 3),
|
||||
Hidden = (1 << 4),
|
||||
ReadOnly = (1 << 5),
|
||||
Archive = (1 << 6),
|
||||
Modified = (1 << 7)
|
||||
};
|
||||
ENABLE_BITWISE_ENUM(EFlags)
|
||||
|
||||
class CVar : BigYAML
|
||||
{
|
||||
public:
|
||||
DECL_YAML
|
||||
String<-1> m_name;
|
||||
String<-1> m_value;
|
||||
Value<EType> m_type;
|
||||
Value<EFlags> m_flags;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -67,6 +67,8 @@ add_library(RuntimeCommon
|
|||
CGameDebug.hpp CGameDebug.cpp
|
||||
rstl.hpp rstl.cpp
|
||||
GameGlobalObjects.hpp
|
||||
CVar.hpp CVar.cpp
|
||||
CVarManager.hpp CVarManager.cpp
|
||||
RetroTypes.hpp
|
||||
GCNTypes.hpp
|
||||
${PLAT_SRCS})
|
||||
|
|
|
@ -0,0 +1,352 @@
|
|||
#include "CVar.hpp"
|
||||
#include "CVarManager.hpp"
|
||||
#include "CVarManager.hpp"
|
||||
#include "CBasics.hpp"
|
||||
|
||||
#include <Athena/Utility.hpp>
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
CVar::CVar(const std::string& name, const std::string &value, const std::string &help, EType type, EFlags flags, CVarManager* parent)
|
||||
{
|
||||
m_name= name;
|
||||
m_value = value;
|
||||
m_defaultValue = value;
|
||||
m_help = help;
|
||||
m_type = type;
|
||||
m_flags = flags;
|
||||
m_allowedWrite = false;
|
||||
m_mgr = parent;
|
||||
}
|
||||
|
||||
CVar::CVar(const std::string& name, const std::string& value, const std::string& help, CVar::EFlags flags, CVarManager* parent)
|
||||
{
|
||||
// Unlock the cvar for writing if readonly
|
||||
unlock();
|
||||
|
||||
m_name= name;
|
||||
m_help = help;
|
||||
m_type = EType::Literal;
|
||||
m_flags = flags;
|
||||
m_allowedWrite = false;
|
||||
m_mgr = parent;
|
||||
|
||||
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(const std::string& name, const Zeus::CColor& value, const std::string& help, EFlags flags, CVarManager* parent)
|
||||
{
|
||||
// Unlock the cvar for writing if readonly
|
||||
unlock();
|
||||
|
||||
m_name= name;
|
||||
m_help = help;
|
||||
m_type = EType::Color;
|
||||
m_flags = flags;
|
||||
m_allowedWrite = false;
|
||||
m_mgr = parent;
|
||||
|
||||
fromColor(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(const std::string& name, float value, const std::string& help, EFlags flags, CVarManager* parent)
|
||||
{
|
||||
// Unlock the cvar for writing if readonly
|
||||
unlock();
|
||||
|
||||
m_name= name;
|
||||
m_help = help;
|
||||
m_type = EType::Float;
|
||||
m_flags = flags;
|
||||
m_allowedWrite = false;
|
||||
m_mgr = parent;
|
||||
|
||||
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(const std::string& name, bool value, const std::string& help, CVar::EFlags flags, CVarManager* parent)
|
||||
{
|
||||
// Unlock the cvar for writing if readonly
|
||||
unlock();
|
||||
|
||||
m_name= name;
|
||||
m_help = help;
|
||||
m_type = EType::Boolean;
|
||||
m_flags = flags;
|
||||
m_allowedWrite = false;
|
||||
m_mgr = parent;
|
||||
|
||||
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(const std::string& name, int value, const std::string& help, CVar::EFlags flags, CVarManager* parent)
|
||||
{
|
||||
// Unlock the cvar for writing if readonly
|
||||
unlock();
|
||||
|
||||
m_name= name;
|
||||
m_help = help;
|
||||
m_type = EType::Integer;
|
||||
m_flags = flags;
|
||||
m_allowedWrite = false;
|
||||
m_mgr = parent;
|
||||
|
||||
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::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
std::string CVar::help() const
|
||||
{
|
||||
return std::string(m_help + (m_defaultValue != std::string() ? "\ndefault: " + m_defaultValue : "") +
|
||||
(isReadOnly() ? "[ReadOnly]" : ""));
|
||||
}
|
||||
|
||||
Zeus::CColor CVar::toColor(bool* isValid) const
|
||||
{
|
||||
if (m_type != EType::Color)
|
||||
{
|
||||
if (isValid != nullptr)
|
||||
*isValid = false;
|
||||
|
||||
return Zeus::CColor();
|
||||
}
|
||||
|
||||
if (isValid != NULL)
|
||||
*isValid = true;
|
||||
|
||||
int r, g, b, a;
|
||||
std::sscanf(m_value.c_str(), "%i %i %i %i", &r, &g, &b, &a);
|
||||
|
||||
return Zeus::CColor(Zeus::Comp8(r), Zeus::Comp8(g), Zeus::Comp8(b), Zeus::Comp8(a));
|
||||
}
|
||||
|
||||
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;
|
||||
std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool CVar::fromColor(const Zeus::CColor& val)
|
||||
{
|
||||
if (isCheat())
|
||||
return false;
|
||||
|
||||
if (m_type != EType::Color)
|
||||
return false;
|
||||
|
||||
if (isReadOnly())
|
||||
return false;
|
||||
|
||||
m_value.assign(CBasics::Stringize("%i %i %i %i", unsigned(val.r), unsigned(val.g), unsigned(val.b), unsigned(val.a)));
|
||||
m_flags |= EFlags::Modified;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVar::fromFloat(float val)
|
||||
{
|
||||
if (isCheat() /*&& (!com_developer->toBoolean() && !com_enableCheats->toBoolean())*/)
|
||||
return false;
|
||||
|
||||
if (m_type != EType::Float)
|
||||
return false;
|
||||
|
||||
if (isReadOnly() /*&& (com_developer && !com_developer->toBoolean())*/)
|
||||
return false;
|
||||
|
||||
m_value.assign(CBasics::Stringize("%f", val));
|
||||
setModified();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVar::fromBoolean(bool val)
|
||||
{
|
||||
if (isCheat() /*&& (!com_developer->toBoolean() && !com_enableCheats->toBoolean())*/)
|
||||
return false;
|
||||
|
||||
if (m_type != EType::Boolean)
|
||||
return false;
|
||||
|
||||
if (isReadOnly() /*&& (com_developer && !com_developer->toBoolean())*/)
|
||||
return false;
|
||||
|
||||
if (val)
|
||||
m_value = "true";
|
||||
else
|
||||
m_value = "false";
|
||||
|
||||
setModified();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVar::fromInteger(int val)
|
||||
{
|
||||
if (isCheat() /*&& (!com_developer->toBoolean() && !com_enableCheats->toBoolean())*/)
|
||||
return false;
|
||||
|
||||
if (m_type != EType::Integer)
|
||||
return false;
|
||||
|
||||
if (isReadOnly() /*&& (com_developer && !com_developer->toBoolean())*/)
|
||||
return false;
|
||||
|
||||
m_value = CBasics::Stringize("%i", val);
|
||||
setModified();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVar::fromLiteral(const std::string& val)
|
||||
{
|
||||
if (isCheat() /*&& (!com_developer->toBoolean() && !com_enableCheats->toBoolean())*/)
|
||||
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::isModified() const { return int(m_flags & EFlags::Modified) != 0;}
|
||||
|
||||
bool CVar::isReadOnly() const { return int(m_flags & EFlags::ReadOnly) != 0; }
|
||||
|
||||
bool CVar::isCheat() const { return int(m_flags & EFlags::Cheat) != 0; }
|
||||
|
||||
bool CVar::isHidden() const { return int(m_flags & EFlags::Hidden) != 0; }
|
||||
|
||||
bool CVar::isArchive() const { return int(m_flags & EFlags::Archive) != 0; }
|
||||
|
||||
void CVar::clearModified() { m_flags &= ~EFlags::Modified; }
|
||||
|
||||
void CVar::setModified() { m_flags |= EFlags::Modified; }
|
||||
|
||||
void CVar::unlock()
|
||||
{
|
||||
if (!isReadOnly())
|
||||
return;
|
||||
|
||||
if (!m_allowedWrite)
|
||||
{
|
||||
m_allowedWrite = true;
|
||||
m_flags &= ~EFlags::ReadOnly;
|
||||
}
|
||||
}
|
||||
|
||||
void CVar::lock()
|
||||
{
|
||||
if (!isReadOnly())
|
||||
return;
|
||||
|
||||
if (m_allowedWrite)
|
||||
{
|
||||
m_flags |= EFlags::ReadOnly;
|
||||
m_allowedWrite = false;
|
||||
clearModified();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
#ifndef CVAR_HPP
|
||||
#define CVAR_HPP
|
||||
|
||||
#include <string>
|
||||
#include "CColor.hpp"
|
||||
#include "DataSpec/DNACommon/CVar.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
|
||||
class CVarManager;
|
||||
class CVar : protected DNACVAR::CVar
|
||||
{
|
||||
public:
|
||||
using EType = DNACVAR::EType;
|
||||
using EFlags = DNACVAR::EFlags;
|
||||
|
||||
CVar(const std::string& name, const std::string& value, const std::string& help, EType type, EFlags flags, CVarManager* parent);
|
||||
CVar(const std::string& name, const std::string& value, const std::string& help, EFlags flags, CVarManager* parent);
|
||||
CVar(const std::string& name, const Zeus::CColor& value, const std::string& help, EFlags flags, CVarManager* parent);
|
||||
CVar(const std::string& name, float value, const std::string& help, EFlags flags, CVarManager* parent);
|
||||
CVar(const std::string& name, bool value, const std::string& help, EFlags flags, CVarManager* parent);
|
||||
CVar(const std::string& name, int value, const std::string& help, EFlags flags, CVarManager* parent);
|
||||
|
||||
|
||||
std::string name() const;
|
||||
std::string help() const;
|
||||
|
||||
Zeus::CColor toColor(bool* isValid = nullptr) const;
|
||||
float toFloat(bool* isValid = nullptr) const;
|
||||
bool toBoolean(bool* isValid = nullptr) const;
|
||||
int toInteger(bool* isValid = nullptr) const;
|
||||
const std::string& toLiteral(bool* isValid = nullptr) const;
|
||||
|
||||
bool fromColor(const Zeus::CColor& val);
|
||||
bool fromFloat(float val);
|
||||
bool fromBoolean(bool val);
|
||||
bool fromInteger(int val);
|
||||
bool fromLiteral(const std::string& val);
|
||||
|
||||
bool isFloat() const { return m_type == EType::Float; }
|
||||
bool isBoolean() const { return m_type == EType::Boolean; }
|
||||
bool isInteger() const { return m_type == EType::Integer; }
|
||||
bool isLiteral() const { return m_type == EType::Literal; }
|
||||
bool isBinding() const { return m_type == EType::Bind; }
|
||||
bool isColor() const { return m_type == EType::Color; }
|
||||
bool isModified() const;
|
||||
bool isReadOnly() const;
|
||||
bool isCheat() const;
|
||||
bool isHidden() const;
|
||||
bool isArchive() const;
|
||||
void clearModified();
|
||||
void setModified();
|
||||
|
||||
EType type() const { return m_type; }
|
||||
EFlags flags() const { return m_flags; }
|
||||
|
||||
/*!
|
||||
* \brief Unlocks the CVar for writing if it is ReadOnly.
|
||||
* <b>Handle with care!!!</b> if you use unlock(), make sure
|
||||
* you lock the cvar using lock()
|
||||
* \see lock
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
/*!
|
||||
* \brief Locks the CVar to prevent writing if it is ReadOnly.
|
||||
* Unlike it's partner function unlock, lock is harmless
|
||||
* \see unlock
|
||||
*/
|
||||
void lock();
|
||||
private:
|
||||
std::string m_help;
|
||||
std::string m_defaultValue;
|
||||
bool m_allowedWrite;
|
||||
|
||||
const CVarManager* m_mgr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CVarUnlocker
|
||||
{
|
||||
CVar* m_cvar;
|
||||
public:
|
||||
CVarUnlocker(CVar* cvar) : m_cvar(cvar) { if (m_cvar) m_cvar->unlock(); }
|
||||
~CVarUnlocker() { if (m_cvar) m_cvar->lock(); }
|
||||
};
|
||||
|
||||
}
|
||||
#endif // CVAR_HPP
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
#include "CVarManager.hpp"
|
||||
#include "CVar.hpp"
|
||||
#include <Athena/Utility.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
CVarManager::CVarManager()
|
||||
{
|
||||
}
|
||||
|
||||
CVarManager::~CVarManager()
|
||||
{
|
||||
}
|
||||
|
||||
void CVarManager::initialize()
|
||||
{
|
||||
}
|
||||
|
||||
bool CVarManager::registerCVar(std::shared_ptr<CVar> cvar)
|
||||
{
|
||||
std::string tmp = cvar->name();
|
||||
Athena::utility::tolower(tmp);
|
||||
if (m_cvars.find(tmp) != m_cvars.end())
|
||||
return false;
|
||||
|
||||
m_cvars[tmp] = cvar;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<CVar> CVarManager::findCVar(const std::string &name)
|
||||
{
|
||||
std::string tmp = std::string(name);
|
||||
Athena::utility::tolower(tmp);
|
||||
if (m_cvars.find(tmp) == m_cvars.end())
|
||||
return nullptr;
|
||||
|
||||
return m_cvars[tmp];
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<CVar>> CVarManager::archivedCVars() const
|
||||
{
|
||||
std::vector<std::shared_ptr<CVar>> ret;
|
||||
for (std::pair<std::string, std::shared_ptr<CVar>> pair : m_cvars)
|
||||
{
|
||||
if (int(pair.second->flags() & CVar::EFlags::Archive) != 0)
|
||||
ret.push_back(pair.second);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<CVar>> CVarManager::cvars() const
|
||||
{
|
||||
std::vector<std::shared_ptr<CVar>> ret;
|
||||
for (std::pair<std::string, std::shared_ptr<CVar>> pair : m_cvars)
|
||||
ret.push_back(pair.second);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CVarManager::suppressDeveloper()
|
||||
{
|
||||
/*bool oldDeveloper = com_developer->toBoolean();
|
||||
CVarUnlocker unlock(com_developer);
|
||||
com_developer->fromBoolean(false);*/
|
||||
|
||||
return false; //oldDeveloper;
|
||||
}
|
||||
|
||||
void CVarManager::restoreDeveloper(bool oldDeveloper)
|
||||
{
|
||||
// CVarUnlocker unlock(com_developer);
|
||||
// com_developer->fromBoolean(oldDeveloper);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef CVARMANAGER_HPP
|
||||
#define CVARMANAGER_HPP
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include "CVar.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
|
||||
class CVarManager
|
||||
{
|
||||
template <typename T>
|
||||
std::shared_ptr<CVar> _newCVar(const std::string& name, const std::string& help, const T& value, CVar::EFlags flags)
|
||||
{
|
||||
std::shared_ptr<CVar> ret(new CVar(name, value, help, flags, this));
|
||||
if (registerCVar(ret))
|
||||
return ret;
|
||||
return nullptr;
|
||||
}
|
||||
public:
|
||||
CVarManager();
|
||||
~CVarManager();
|
||||
|
||||
void initialize();
|
||||
|
||||
std::shared_ptr<CVar> newCVar(const std::string& name, const std::string& help, const Zeus::CColor& value, CVar::EFlags flags)
|
||||
{ return _newCVar<Zeus::CColor>(name, help, value, flags); }
|
||||
std::shared_ptr<CVar> newCVar(const std::string& name, const std::string& help, const std::string& value, CVar::EFlags flags)
|
||||
{ return _newCVar<std::string>(name, help, value, flags); }
|
||||
std::shared_ptr<CVar> newCVar(const std::string& name, const std::string& help, bool value, CVar::EFlags flags)
|
||||
{ return _newCVar<bool>(name, help, value, flags); }
|
||||
std::shared_ptr<CVar> newCVar(const std::string& name, const std::string& help, float value, CVar::EFlags flags)
|
||||
{ return _newCVar<float>(name, help, value, flags); }
|
||||
std::shared_ptr<CVar> newCVar(const std::string& name, const std::string& help, int value, CVar::EFlags flags)
|
||||
{ return _newCVar<int>(name, help, value, flags); }
|
||||
|
||||
bool registerCVar(std::shared_ptr<CVar> cvar);
|
||||
|
||||
std::shared_ptr<CVar>findCVar(const std::string& name);
|
||||
|
||||
std::vector<std::shared_ptr<CVar>> archivedCVars() const;
|
||||
std::vector<std::shared_ptr<CVar>> cvars() const;
|
||||
|
||||
private:
|
||||
bool suppressDeveloper();
|
||||
void restoreDeveloper(bool oldDeveloper);
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<CVar>> m_cvars;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CVARMANAGER_HPP
|
2
hecl
2
hecl
|
@ -1 +1 @@
|
|||
Subproject commit d21e47eac6e8f8c81a7ccbc53e8df3285a2fdc64
|
||||
Subproject commit bc0aba098c43d27839f20df0c32029705def98bf
|
Loading…
Reference in New Issue