forked from ValveSoftware/steamos-compositor
-
Notifications
You must be signed in to change notification settings - Fork 201
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Alpyne <[email protected]>
- Loading branch information
1 parent
332f348
commit d70530c
Showing
3 changed files
with
156 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#include "convar.h" | ||
|
||
namespace gamescope | ||
{ | ||
Dict<ConCommand *>& ConCommand::GetCommands() | ||
{ | ||
static Dict<ConCommand *> s_Commands; | ||
return s_Commands; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
#pragma once | ||
|
||
#include <span> | ||
#include <string> | ||
#include <string_view> | ||
#include <unordered_map> | ||
#include <utility> | ||
#include <optional> | ||
#include <charconv> | ||
#include <type_traits> | ||
#include <cstdint> | ||
#include <functional> | ||
#include <cassert> | ||
|
||
namespace gamescope | ||
{ | ||
class ConCommand; | ||
|
||
template <typename T> | ||
inline std::optional<T> Parse( std::string_view chars ) | ||
{ | ||
T obj; | ||
auto result = std::from_chars( chars.begin(), chars.end(), obj ); | ||
if ( result.ec == std::errc{} ) | ||
return obj; | ||
else | ||
return std::nullopt; | ||
} | ||
|
||
template <> | ||
inline std::optional<bool> Parse( std::string_view chars ) | ||
{ | ||
std::optional<uint32_t> oNumber = Parse<uint32_t>( chars ); | ||
if ( oNumber ) | ||
return !!*oNumber; | ||
|
||
if ( chars == "true" ) | ||
return true; | ||
else | ||
return false; | ||
} | ||
|
||
struct StringHash | ||
{ | ||
using is_transparent = void; | ||
[[nodiscard]] size_t operator()( const char *string ) const { return std::hash<std::string_view>{}( string ); } | ||
[[nodiscard]] size_t operator()( std::string_view string ) const { return std::hash<std::string_view>{}( string ); } | ||
[[nodiscard]] size_t operator()( const std::string &string ) const { return std::hash<std::string>{}( string ); } | ||
}; | ||
|
||
template <typename T> | ||
using Dict = std::unordered_map<std::string, T, StringHash, std::equal_to<>>; | ||
|
||
class ConCommand | ||
{ | ||
using ConCommandFunc = std::function<void( std::span<std::string_view> )>; | ||
|
||
public: | ||
ConCommand( std::string_view pszName, std::string_view pszDescription, ConCommandFunc func ) | ||
: m_pszName{ pszName } | ||
, m_pszDescription{ pszDescription } | ||
, m_Func{ func } | ||
{ | ||
assert( !GetCommands().contains( pszName ) ); | ||
GetCommands()[ std::string( pszName ) ] = this; | ||
} | ||
|
||
~ConCommand() | ||
{ | ||
GetCommands().erase( GetCommands().find( m_pszName ) ); | ||
} | ||
|
||
void Invoke( std::span<std::string_view> args ) | ||
{ | ||
if ( m_Func ) | ||
m_Func( args ); | ||
} | ||
|
||
static Dict<ConCommand *>& GetCommands(); | ||
protected: | ||
std::string_view m_pszName; | ||
std::string_view m_pszDescription; | ||
ConCommandFunc m_Func; | ||
}; | ||
|
||
template <typename T> | ||
class ConVar : public ConCommand | ||
{ | ||
using ConVarCallbackFunc = std::function<void()>; | ||
public: | ||
ConVar( std::string_view pszName, T defaultValue = T{}, std::string_view pszDescription = "", ConVarCallbackFunc func = nullptr ) | ||
: ConCommand( pszName, pszDescription, [this]( std::span<std::string_view> pArgs ){ this->InvokeFunc( pArgs ); } ) | ||
, m_Value{ defaultValue } | ||
, m_Callback{ func } | ||
{ | ||
} | ||
|
||
const T& Get() const | ||
{ | ||
return m_Value; | ||
} | ||
|
||
template <typename J> | ||
void SetValue( const J &newValue ) | ||
{ | ||
m_Value = T{ newValue }; | ||
|
||
if ( !m_bInCallback && m_Callback ) | ||
{ | ||
m_bInCallback = true; | ||
m_Callback(); | ||
m_bInCallback = false; | ||
} | ||
} | ||
|
||
template <typename J> | ||
ConVar<T>& operator =( const J &newValue ) { SetValue<J>( newValue ); return *this; } | ||
|
||
operator T() const { return m_Value; } | ||
|
||
template <typename J> bool operator == ( const J &other ) const { return m_Value == other; } | ||
template <typename J> bool operator != ( const J &other ) const { return m_Value != other; } | ||
template <typename J> bool operator <=>( const J &other ) const { return m_Value <=> other; } | ||
|
||
void InvokeFunc( std::span<std::string_view> pArgs ) | ||
{ | ||
if ( pArgs.size() != 2 ) | ||
return; | ||
|
||
if constexpr ( std::is_integral<T>::value ) | ||
{ | ||
std::optional<T> oResult = Parse<T>( pArgs[1] ); | ||
SetValue( oResult ? *oResult : T{} ); | ||
} | ||
else | ||
{ | ||
SetValue( pArgs[1] ); | ||
} | ||
} | ||
private: | ||
T m_Value{}; | ||
ConVarCallbackFunc m_Callback; | ||
bool m_bInCallback; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters