demotool/syncoverrides.cc

712 lines
18 KiB
C++
Raw Normal View History

#include "externals.hh"
#include "globals.hh"
#include "syncoverrides.hh"
#include <ebcl/SRDParser.hh>
using namespace sov;
#define M_SETOPT_( FIELD , VAR ) \
if ( FIELD ) { return false; } \
FIELD = (VAR); \
return true
/*= PARSER DEFINITIONS =========================================================*/
namespace {
using namespace ebcl;
using SP_Section = T_SharedPtr< T_SyncOverrideSection >;
bool EnterSection_( T_SRDParserData const& data )
{
*( data.targetData ) = NewShared< T_SyncOverrideSection >( (*data.input)[ 1 ].stringValue( ) );
return true;
}
bool ExitSection_( T_SRDParserData const& data )
{
auto& section( data.currentData->value< SP_Section >( ) );
auto& parent( data.targetData->value< SP_Section >( ) );
if ( section->overrides.empty( ) && section->subsections.empty( ) ) {
T_StringBuilder sb;
sb << "empty section '" << section->title << "'";
data.errors.add( std::move( sb ) , (*data.input)[ 0 ] );
} else {
parent->subsections.add( section.makeOwned( ) );
}
return true;
}
/*------------------------------------------------------------------------------*/
using SP_Float = T_SharedPtr< A_Float >;
bool EnterFloat1_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
SP_Float ptr{ NewShared< T_Float >( input[ 2 ].stringValue( ) ,
input[ 1 ].stringValue( ) ) };
2017-11-17 20:33:56 +01:00
ptr->location( ) = input[ 0 ].location( );
*( data.targetData ) = std::move( ptr );
return true;
}
bool EnterFloat2_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
SP_Float ptr{ NewShared< T_Float2 >(
input[ 2 ].stringValue( ) , input[ 3 ].stringValue( ) ,
input[ 1 ].stringValue( ) ) };
2017-11-17 20:33:56 +01:00
ptr->location( ) = input[ 0 ].location( );
*( data.targetData ) = std::move( ptr );
return true;
}
bool EnterFloat3_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
SP_Float ptr{ NewShared< T_Float3 >(
input[ 2 ].stringValue( ) , input[ 3 ].stringValue( ) ,
input[ 4 ].stringValue( ) ,
input[ 1 ].stringValue( ) ) };
2017-11-17 20:33:56 +01:00
ptr->location( ) = input[ 0 ].location( );
*( data.targetData ) = std::move( ptr );
return true;
}
bool EnterFloat4_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
SP_Float ptr{ NewShared< T_Float4 >(
input[ 2 ].stringValue( ) , input[ 3 ].stringValue( ) ,
input[ 4 ].stringValue( ) , input[ 5 ].stringValue( ) ,
input[ 1 ].stringValue( ) ) };
2017-11-17 20:33:56 +01:00
ptr->location( ) = input[ 0 ].location( );
*( data.targetData ) = std::move( ptr );
return true;
}
bool AddFloat_( T_SRDParserData const& data )
{
auto& fl( data.currentData->value< SP_Float >( ) );
auto& parent( data.targetData->value< SP_Section >( ) );
if ( fl->min( ) > fl->max( ) ) {
data.errors.add( "invalid bounds" , (*data.input)[ 0 ] );
}
parent->overrides.add( fl.makeOwned( ) );
return true;
}
/*------------------------------------------------------------------------------*/
bool FloatSetSlider_( T_SRDParserData const& data )
{
data.currentData->value< SP_Float >( )->setSlider( );
return true;
}
bool FloatSetMin_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
if ( !data.currentData->value< SP_Float >( )->setMin( input[ 1 ].floatValue( ) ) ) {
data.errors.add( "duplicate minimal value" , (*data.input)[ 0 ] );
}
return true;
}
bool FloatSetMax_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
if ( !data.currentData->value< SP_Float >( )->setMax( input[ 1 ].floatValue( ) ) ) {
data.errors.add( "duplicate maximal value" , (*data.input)[ 0 ] );
}
return true;
}
bool FloatSetStep_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
const auto v( input[ 1 ].floatValue( ) );
if ( v <= 0 ) {
data.errors.add( "invalid step value" , (*data.input)[ 1 ] );
} else if ( !data.currentData->value< SP_Float >( )->setStep( v ) ) {
data.errors.add( "duplicate step value" , (*data.input)[ 0 ] );
}
return true;
}
bool FloatSetPower_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
const auto v( input[ 1 ].floatValue( ) );
if ( v <= 0 ) {
data.errors.add( "invalid power value" , (*data.input)[ 1 ] );
} else if ( !data.currentData->value< SP_Float >( )->setPower( v ) ) {
data.errors.add( "duplicate power value" , (*data.input)[ 0 ] );
}
return true;
}
bool FloatSetDecimals_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
const auto v( input[ 1 ].longValue( ) );
if ( v < 0 || v > 10 ) {
data.errors.add( "invalid decimals value" , (*data.input)[ 1 ] );
} else if ( !data.currentData->value< SP_Float >( )->setDecimals( v ) ) {
data.errors.add( "duplicate decimals value" , (*data.input)[ 0 ] );
}
return true;
}
2017-11-18 15:17:42 +01:00
/*------------------------------------------------------------------------------*/
using SP_Int = T_SharedPtr< A_Integer >;
bool EnterInt1_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
SP_Int ptr{ NewShared< T_Integer >( input[ 2 ].stringValue( ) ,
input[ 1 ].stringValue( ) ) };
ptr->location( ) = input[ 0 ].location( );
*( data.targetData ) = std::move( ptr );
return true;
}
bool EnterInt2_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
SP_Int ptr{ NewShared< T_Integer2 >(
input[ 2 ].stringValue( ) , input[ 3 ].stringValue( ) ,
input[ 1 ].stringValue( ) ) };
ptr->location( ) = input[ 0 ].location( );
*( data.targetData ) = std::move( ptr );
return true;
}
bool EnterInt3_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
SP_Int ptr{ NewShared< T_Integer3 >(
input[ 2 ].stringValue( ) , input[ 3 ].stringValue( ) ,
input[ 4 ].stringValue( ) ,
input[ 1 ].stringValue( ) ) };
ptr->location( ) = input[ 0 ].location( );
*( data.targetData ) = std::move( ptr );
return true;
}
bool EnterInt4_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
SP_Int ptr{ NewShared< T_Integer4 >(
input[ 2 ].stringValue( ) , input[ 3 ].stringValue( ) ,
input[ 4 ].stringValue( ) , input[ 5 ].stringValue( ) ,
input[ 1 ].stringValue( ) ) };
ptr->location( ) = input[ 0 ].location( );
*( data.targetData ) = std::move( ptr );
return true;
}
bool AddInt_( T_SRDParserData const& data )
{
auto& fl( data.currentData->value< SP_Int >( ) );
auto& parent( data.targetData->value< SP_Section >( ) );
if ( fl->min( ) > fl->max( ) ) {
data.errors.add( "invalid bounds" , (*data.input)[ 0 ] );
}
parent->overrides.add( fl.makeOwned( ) );
return true;
}
/*------------------------------------------------------------------------------*/
bool IntSetSlider_( T_SRDParserData const& data )
{
data.currentData->value< SP_Int >( )->setSlider( );
return true;
}
bool IntSetMin_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
if ( !data.currentData->value< SP_Int >( )->setMin( input[ 1 ].longValue( ) ) ) {
data.errors.add( "duplicate minimal value" , (*data.input)[ 0 ] );
}
return true;
}
bool IntSetMax_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
if ( !data.currentData->value< SP_Int >( )->setMax( input[ 1 ].longValue( ) ) ) {
data.errors.add( "duplicate maximal value" , (*data.input)[ 0 ] );
}
return true;
}
bool IntSetStep_( T_SRDParserData const& data )
{
auto const& input( *( data.input ) );
const auto v( input[ 1 ].floatValue( ) );
if ( v <= 0 ) {
data.errors.add( "invalid step value" , (*data.input)[ 1 ] );
} else if ( !data.currentData->value< SP_Int >( )->setStep( v ) ) {
data.errors.add( "duplicate step value" , (*data.input)[ 0 ] );
}
return true;
}
} // namespace
/*------------------------------------------------------------------------------*/
ebcl::T_SRDParserConfig sov::GetParserConfig( )
{
using namespace ebcl;
using namespace ebcl::SRD;
T_SRDParserDefs defs( "root" );
defs << OnStart( []( T_SRDParserData const& data ) -> bool {
*( data.currentData ) = NewShared< T_SyncOverrideSection >( "*" );
return true;
} );
defs.context( "root" )
<< ( Rule() << "section" << Text( ) << EnterContext( "section" )
<< OnEnter( EnterSection_ )
<< OnExit( ExitSection_ ) )
;
defs.context( "section" )
<< ( Rule() << "section" << Text( ) << EnterContext( "section" )
<< OnEnter( EnterSection_ )
<< OnExit( ExitSection_ ) )
// Floating point controls
<< ( Rule() << "float" << Text( ) << Word( )
<< EnterContext( "float" )
<< OnEnter( EnterFloat1_ )
<< OnExit( AddFloat_ ) )
<< ( Rule() << "float2" << Text( )
<< ( SRD::Times( 2 ) << Word( ) )
<< EnterContext( "float" )
<< OnEnter( EnterFloat2_ )
<< OnExit( AddFloat_ ) )
<< ( Rule() << "float3" << Text( )
<< ( SRD::Times( 3 ) << Word( ) )
<< EnterContext( "float" )
<< OnEnter( EnterFloat3_ )
<< OnExit( AddFloat_ ) )
<< ( Rule() << "float4" << Text( )
<< ( SRD::Times( 4 ) << Word( ) )
<< EnterContext( "float" )
<< OnEnter( EnterFloat4_ )
<< OnExit( AddFloat_ ) )
2017-11-18 15:17:42 +01:00
// Integer controls
<< ( Rule() << "int" << Text( ) << Word( )
<< EnterContext( "int" )
<< OnEnter( EnterInt1_ )
<< OnExit( AddInt_ ) )
<< ( Rule() << "int2" << Text( )
<< ( SRD::Times( 2 ) << Word( ) )
<< EnterContext( "int" )
<< OnEnter( EnterInt2_ )
<< OnExit( AddInt_ ) )
<< ( Rule() << "int3" << Text( )
<< ( SRD::Times( 3 ) << Word( ) )
<< EnterContext( "int" )
<< OnEnter( EnterInt3_ )
<< OnExit( AddInt_ ) )
<< ( Rule() << "int4" << Text( )
<< ( SRD::Times( 4 ) << Word( ) )
<< EnterContext( "int" )
<< OnEnter( EnterInt4_ )
<< OnExit( AddInt_ ) )
;
// Floating point control parameters
defs.context( "float" )
<< ( Rule() << "slider" << FloatSetSlider_ )
<< ( Rule() << "min" << Numeric() << FloatSetMin_ )
<< ( Rule() << "max" << Numeric() << FloatSetMax_ )
<< ( Rule() << "step" << Numeric() << FloatSetStep_ )
<< ( Rule() << "power" << Numeric() << FloatSetPower_ )
<< ( Rule() << "decimals" << Integer() << FloatSetDecimals_ )
;
2017-11-18 15:17:42 +01:00
// Integer control parameters
defs.context( "int" )
<< ( Rule() << "slider" << IntSetSlider_ )
<< ( Rule() << "min" << Int32() << IntSetMin_ )
<< ( Rule() << "max" << Int32() << IntSetMax_ )
<< ( Rule() << "step" << Numeric() << IntSetStep_ )
;
return T_SRDParserConfig{ defs };
}
/*= A_Float ====================================================================*/
bool A_Float::setMin(
const float v ) noexcept
{
M_SETOPT_( min_ , v );
}
bool A_Float::setMax(
const float v ) noexcept
{
M_SETOPT_( max_ , v );
}
bool A_Float::setStep(
const float v ) noexcept
{
assert( v > 0 );
M_SETOPT_( step_ , v );
}
bool A_Float::setDecimals(
const uint32_t n ) noexcept
{
assert( n <= 100 );
if ( decimals_ ) {
return false;
}
T_StringBuilder sb;
sb << "%." << n << 'f' << '\0';
assert( sb.size( ) < 12 );
decimals_.setNew( );
for ( auto i = 0u ; i < sb.size( ) ; i ++ ) {
decimals_->add( sb.data( )[ i ] );
}
return true;
}
bool A_Float::setPower(
const float v ) noexcept
{
assert( v > 0 );
M_SETOPT_( power_ , v );
}
void A_Float::setSlider( ) noexcept
{
slider_ = true;
}
/*= T_Float ====================================================================*/
T_Float::T_Float(
T_String const& input ,
T_String const& title ) noexcept
: A_Float( "float" , title )
{
inputs_.add( input );
}
void T_Float::makeEditWidgets(
uint32_t& counter ,
T_StringBuilder& sb ) noexcept
{
using namespace ImGui;
float v[ 1 ] = {
Globals::Sync( ).inputs( )[ inputPos_[ 0 ] ]
};
char const* const label( buildLabel( counter , sb ) );
const bool changed( slider( )
? SliderFloat( label , v , min( ) , max( ) , decimals( ) , power( ) )
: DragFloat( label , v , step( ) , min( ) , max( ) , decimals( ) , power( ) ) );
if ( changed ) {
Globals::Sync( ).inputs( )[ inputPos_[ 0 ] ] = v[ 0 ];
}
}
/*= T_Float2 ===================================================================*/
T_Float2::T_Float2(
T_String const& input0 ,
T_String const& input1 ,
T_String const& title ) noexcept
2017-11-18 15:17:42 +01:00
: A_Float( "float2" , title )
{
inputs_.add( input0 );
inputs_.add( input1 );
}
void T_Float2::makeEditWidgets(
uint32_t& counter ,
T_StringBuilder& sb ) noexcept
{
using namespace ImGui;
auto& sinp( Globals::Sync( ).inputs( ) );
float v[ 2 ];
for ( auto i = 0 ; i < 2 ; i ++ ) {
v[ i ] = sinp[ inputPos_[ i ] ];
}
char const* const label( buildLabel( counter , sb ) );
const bool changed( slider( )
? SliderFloat2( label , v , min( ) , max( ) , decimals( ) , power( ) )
: DragFloat2( label , v , step( ) , min( ) , max( ) , decimals( ) , power( ) ) );
if ( changed ) {
for ( auto i = 0 ; i < 2 ; i ++ ) {
sinp[ inputPos_[ i ] ] = v[ i ];
}
}
}
/*= T_Float3 ===================================================================*/
T_Float3::T_Float3(
T_String const& input0 ,
T_String const& input1 ,
T_String const& input2 ,
T_String const& title ) noexcept
2017-11-18 15:17:42 +01:00
: A_Float( "float3" , title )
{
inputs_.add( input0 );
inputs_.add( input1 );
inputs_.add( input2 );
}
void T_Float3::makeEditWidgets(
uint32_t& counter ,
T_StringBuilder& sb ) noexcept
{
using namespace ImGui;
auto& sinp( Globals::Sync( ).inputs( ) );
float v[ 3 ];
for ( auto i = 0 ; i < 3 ; i ++ ) {
v[ i ] = sinp[ inputPos_[ i ] ];
}
char const* const label( buildLabel( counter , sb ) );
const bool changed( slider( )
? SliderFloat3( label , v , min( ) , max( ) , decimals( ) , power( ) )
: DragFloat3( label , v , step( ) , min( ) , max( ) , decimals( ) , power( ) ) );
if ( changed ) {
for ( auto i = 0 ; i < 3 ; i ++ ) {
sinp[ inputPos_[ i ] ] = v[ i ];
}
}
}
/*= T_Float4 ===================================================================*/
T_Float4::T_Float4(
T_String const& input0 ,
T_String const& input1 ,
T_String const& input2 ,
T_String const& input3 ,
T_String const& title ) noexcept
2017-11-18 15:17:42 +01:00
: A_Float( "float4" , title )
{
inputs_.add( input0 );
inputs_.add( input1 );
inputs_.add( input2 );
inputs_.add( input3 );
}
void T_Float4::makeEditWidgets(
uint32_t& counter ,
T_StringBuilder& sb ) noexcept
{
using namespace ImGui;
auto& sinp( Globals::Sync( ).inputs( ) );
float v[ 4 ];
for ( auto i = 0 ; i < 4 ; i ++ ) {
v[ i ] = sinp[ inputPos_[ i ] ];
}
char const* const label( buildLabel( counter , sb ) );
const bool changed( slider( )
? SliderFloat4( label , v , min( ) , max( ) , decimals( ) , power( ) )
: DragFloat4( label , v , step( ) , min( ) , max( ) , decimals( ) , power( ) ) );
if ( changed ) {
for ( auto i = 0 ; i < 4 ; i ++ ) {
sinp[ inputPos_[ i ] ] = v[ i ];
}
}
}
2017-11-18 15:17:42 +01:00
/*= A_Integer ==================================================================*/
bool A_Integer::setMin(
const int32_t v ) noexcept
{
M_SETOPT_( min_ , v );
}
bool A_Integer::setMax(
const int32_t v ) noexcept
{
M_SETOPT_( max_ , v );
}
bool A_Integer::setStep(
const float v ) noexcept
{
assert( v > 0 );
M_SETOPT_( step_ , v );
}
void A_Integer::setSlider( ) noexcept
{
slider_ = true;
}
/*= T_Integer ==================================================================*/
T_Integer::T_Integer(
T_String const& input ,
T_String const& title ) noexcept
: A_Integer( "int" , title )
{
inputs_.add( input );
}
void T_Integer::makeEditWidgets(
uint32_t& counter ,
T_StringBuilder& sb ) noexcept
{
using namespace ImGui;
int32_t v[ 1 ] = {
int32_t( Globals::Sync( ).inputs( )[ inputPos_[ 0 ] ] )
};
char const* const label( buildLabel( counter , sb ) );
const bool changed( slider( )
? SliderInt( label , v , min( ) , max( ) )
: DragInt( label , v , step( ) , min( ) , max( ) ) );
if ( changed ) {
Globals::Sync( ).inputs( )[ inputPos_[ 0 ] ] = v[ 0 ];
}
}
/*= T_Integer2 =================================================================*/
T_Integer2::T_Integer2(
T_String const& input0 ,
T_String const& input1 ,
T_String const& title ) noexcept
: A_Integer( "int2" , title )
{
inputs_.add( input0 );
inputs_.add( input1 );
}
void T_Integer2::makeEditWidgets(
uint32_t& counter ,
T_StringBuilder& sb ) noexcept
{
using namespace ImGui;
auto& sinp( Globals::Sync( ).inputs( ) );
int32_t v[ 2 ];
for ( auto i = 0 ; i < 2 ; i ++ ) {
v[ i ] = sinp[ inputPos_[ i ] ];
}
char const* const label( buildLabel( counter , sb ) );
const bool changed( slider( )
? SliderInt2( label , v , min( ) , max( ) )
: DragInt2( label , v , step( ) , min( ) , max( ) ) );
if ( changed ) {
for ( auto i = 0 ; i < 2 ; i ++ ) {
sinp[ inputPos_[ i ] ] = v[ i ];
}
}
}
/*= T_Integer3 =================================================================*/
T_Integer3::T_Integer3(
T_String const& input0 ,
T_String const& input1 ,
T_String const& input2 ,
T_String const& title ) noexcept
: A_Integer( "int3" , title )
{
inputs_.add( input0 );
inputs_.add( input1 );
inputs_.add( input2 );
}
void T_Integer3::makeEditWidgets(
uint32_t& counter ,
T_StringBuilder& sb ) noexcept
{
using namespace ImGui;
auto& sinp( Globals::Sync( ).inputs( ) );
int32_t v[ 3 ];
for ( auto i = 0 ; i < 3 ; i ++ ) {
v[ i ] = sinp[ inputPos_[ i ] ];
}
char const* const label( buildLabel( counter , sb ) );
const bool changed( slider( )
? SliderInt3( label , v , min( ) , max( ) )
: DragInt3( label , v , step( ) , min( ) , max( ) ) );
if ( changed ) {
for ( auto i = 0 ; i < 3 ; i ++ ) {
sinp[ inputPos_[ i ] ] = v[ i ];
}
}
}
/*= T_Integer4 =================================================================*/
T_Integer4::T_Integer4(
T_String const& input0 ,
T_String const& input1 ,
T_String const& input2 ,
T_String const& input3 ,
T_String const& title ) noexcept
: A_Integer( "int4" , title )
{
inputs_.add( input0 );
inputs_.add( input1 );
inputs_.add( input2 );
inputs_.add( input3 );
}
void T_Integer4::makeEditWidgets(
uint32_t& counter ,
T_StringBuilder& sb ) noexcept
{
using namespace ImGui;
auto& sinp( Globals::Sync( ).inputs( ) );
int32_t v[ 4 ];
for ( auto i = 0 ; i < 4 ; i ++ ) {
v[ i ] = sinp[ inputPos_[ i ] ];
}
char const* const label( buildLabel( counter , sb ) );
const bool changed( slider( )
? SliderInt4( label , v , min( ) , max( ) )
: DragInt4( label , v , step( ) , min( ) , max( ) ) );
if ( changed ) {
for ( auto i = 0 ; i < 4 ; i ++ ) {
sinp[ inputPos_[ i ] ] = v[ i ];
}
}
}