Emmanuel BENOîT
aa58b016c2
Camera control using the input overrides panel works, although the controls are a bit too sensitive (and there's a risk of fucking things up with bad Up vectors)
1195 lines
31 KiB
C++
1195 lines
31 KiB
C++
#include "externals.hh"
|
|
#include "globals.hh"
|
|
#include "syncoverrides.hh"
|
|
#include "colorgrading.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( ) ) };
|
|
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( ) ) };
|
|
if ( ptr->inputNames( ).size( ) != 2 ) {
|
|
data.errors.add( "duplicate input names" , input[ 3 ].location( ) );
|
|
}
|
|
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( ) ) };
|
|
if ( ptr->inputNames( ).size( ) != 3 ) {
|
|
data.errors.add( "duplicate input names" , input[ 3 ].location( ) );
|
|
}
|
|
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( ) ) };
|
|
if ( ptr->inputNames( ).size( ) != 4 ) {
|
|
data.errors.add( "duplicate input names" , input[ 3 ].location( ) );
|
|
}
|
|
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 > 20 ) {
|
|
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;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
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( ) ) };
|
|
if ( ptr->inputNames( ).size( ) != 2 ) {
|
|
data.errors.add( "duplicate input names" , input[ 3 ].location( ) );
|
|
}
|
|
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( ) ) };
|
|
if ( ptr->inputNames( ).size( ) != 3 ) {
|
|
data.errors.add( "duplicate input names" , input[ 3 ].location( ) );
|
|
}
|
|
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( ) ) };
|
|
if ( ptr->inputNames( ).size( ) != 4 ) {
|
|
data.errors.add( "duplicate input names" , input[ 3 ].location( ) );
|
|
}
|
|
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;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
using SP_Cg = T_SharedPtr< T_ColorGrading >;
|
|
|
|
bool EnterColorGrading_( T_SRDParserData const& data )
|
|
{
|
|
auto const& input( *( data.input ) );
|
|
SP_Cg ptr{ NewShared< T_ColorGrading >(
|
|
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 AddColorGrading_( T_SRDParserData const& data )
|
|
{
|
|
auto& fl( data.currentData->value< SP_Cg >( ) );
|
|
auto& parent( data.targetData->value< SP_Section >( ) );
|
|
parent->overrides.add( fl.makeOwned( ) );
|
|
return true;
|
|
}
|
|
|
|
bool CgSetBase_( T_SRDParserData const& data )
|
|
{
|
|
auto const& input( *( data.input ) );
|
|
if ( !data.currentData->value< SP_Cg >( )->setBase( input[ 1 ].floatValue( ) ) ) {
|
|
data.errors.add( "duplicate base value" , (*data.input)[ 0 ] );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CgSetUnit_( T_SRDParserData const& data )
|
|
{
|
|
auto const& input( *( data.input ) );
|
|
const float v( input[ 1 ].floatValue( ) );
|
|
if ( v == 0 ) {
|
|
data.errors.add( "invalid unit value" , (*data.input)[ 1 ] );
|
|
} else if ( !data.currentData->value< SP_Cg >( )->setUnit( v ) ) {
|
|
data.errors.add( "duplicate unit value" , (*data.input)[ 0 ] );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
using SP_Cam = T_SharedPtr< T_CamOverride >;
|
|
|
|
bool EnterCam_( T_SRDParserData const& data )
|
|
{
|
|
auto const& input( *( data.input ) );
|
|
SP_Cam ptr{ NewShared< T_CamOverride >( input[ 1 ].stringValue( ) ) };
|
|
ptr->location( ) = input[ 0 ].location( );
|
|
*( data.targetData ) = std::move( ptr );
|
|
return true;
|
|
}
|
|
|
|
bool ExitCam_( T_SRDParserData const& data )
|
|
{
|
|
auto const& input( *( data.input ) );
|
|
auto& ov( data.currentData->value< SP_Cam >( ) );
|
|
auto& parent( data.targetData->value< SP_Section >( ) );
|
|
|
|
if ( !ov->isFovConfigured( ) ) {
|
|
data.errors.add( "field of view or near plane missing" , input[ 0 ] );
|
|
}
|
|
if ( !ov->isTargetConfigured( ) ) {
|
|
data.errors.add( "target vector missing" , input[ 0 ] );
|
|
}
|
|
if ( !ov->checkValidConfig( ) ) {
|
|
data.errors.add( "invalid camera configuration" , input[ 0 ] );
|
|
}
|
|
|
|
parent->overrides.add( ov.makeOwned( ) );
|
|
return true;
|
|
}
|
|
|
|
bool CamSetFov_( T_SRDParserData const& data )
|
|
{
|
|
auto const& input( *( data.input ) );
|
|
auto& ov( data.currentData->value< SP_Cam >( ) );
|
|
const auto s{ ov->setFieldOfView( input[ 1 ].stringValue( ) ) };
|
|
if ( s == T_CamOverride::S_DEF ) {
|
|
data.errors.add( "field of view or near plane already set" , input[ 0 ] );
|
|
} else if ( s == T_CamOverride::S_INPUTS ) {
|
|
data.errors.add( "input already in use" , input[ 1 ] );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CamSetNP_( T_SRDParserData const& data )
|
|
{
|
|
auto const& input( *( data.input ) );
|
|
auto& ov( data.currentData->value< SP_Cam >( ) );
|
|
const auto s{ ov->setNearPlane( input[ 1 ].stringValue( ) ) };
|
|
if ( s == T_CamOverride::S_DEF ) {
|
|
data.errors.add( "field of view or near plane already set" , input[ 0 ] );
|
|
} else if ( s == T_CamOverride::S_INPUTS ) {
|
|
data.errors.add( "input already in use" , input[ 1 ] );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CamSetTarget_( T_SRDParserData const& data )
|
|
{
|
|
auto const& input( *( data.input ) );
|
|
auto& ov( data.currentData->value< SP_Cam >( ) );
|
|
const auto s{ ov->setTarget( input[ 1 ].stringValue( ) ,
|
|
input[ 2 ].stringValue( ) ,
|
|
input[ 3 ].stringValue( ) ) };
|
|
if ( s == T_CamOverride::S_DEF ) {
|
|
data.errors.add( "camera target already set" , input[ 0 ] );
|
|
} else if ( s == T_CamOverride::S_INPUTS ) {
|
|
data.errors.add( "inputs already in use" , input[ 1 ] );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CamSetPosition_( T_SRDParserData const& data )
|
|
{
|
|
auto const& input( *( data.input ) );
|
|
auto& ov( data.currentData->value< SP_Cam >( ) );
|
|
const auto s{ ov->setPositionVector( input[ 1 ].stringValue( ) ,
|
|
input[ 2 ].stringValue( ) , input[ 3 ].stringValue( ) ) };
|
|
if ( s == T_CamOverride::S_DEF ) {
|
|
data.errors.add( "camera position already set" , input[ 0 ] );
|
|
} else if ( s == T_CamOverride::S_INPUTS ) {
|
|
data.errors.add( "inputs already in use" , input[ 1 ] );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CamSetUpVector_( T_SRDParserData const& data )
|
|
{
|
|
auto const& input( *( data.input ) );
|
|
auto& ov( data.currentData->value< SP_Cam >( ) );
|
|
const auto s{ ov->setUpVector( input[ 1 ].stringValue( ) ,
|
|
input[ 2 ].stringValue( ) , input[ 3 ].stringValue( ) ) };
|
|
if ( s == T_CamOverride::S_DEF ) {
|
|
data.errors.add( "'up' vector already set" , input[ 0 ] );
|
|
} else if ( s == T_CamOverride::S_INPUTS ) {
|
|
data.errors.add( "inputs already in use" , input[ 1 ] );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CamSetAngles_( T_SRDParserData const& data )
|
|
{
|
|
auto const& input( *( data.input ) );
|
|
auto& ov( data.currentData->value< SP_Cam >( ) );
|
|
const auto s{ ov->setAngles( input[ 1 ].stringValue( ) ,
|
|
input[ 2 ].stringValue( ) , input[ 3 ].stringValue( ) ) };
|
|
if ( s == T_CamOverride::S_DEF ) {
|
|
data.errors.add( "camera angles already set" , input[ 0 ] );
|
|
} else if ( s == T_CamOverride::S_INPUTS ) {
|
|
data.errors.add( "inputs already in use" , input[ 1 ] );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CamSetDistance_( T_SRDParserData const& data )
|
|
{
|
|
auto const& input( *( data.input ) );
|
|
auto& ov( data.currentData->value< SP_Cam >( ) );
|
|
const auto s{ ov->setDistance( input[ 1 ].stringValue( ) ) };
|
|
if ( s == T_CamOverride::S_DEF ) {
|
|
data.errors.add( "camera distance already set" , input[ 0 ] );
|
|
} else if ( s == T_CamOverride::S_INPUTS ) {
|
|
data.errors.add( "input already in use" , input[ 1 ] );
|
|
}
|
|
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_ ) )
|
|
// 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_ ) )
|
|
// Color grading controls
|
|
<< ( Rule() << "color-grading" << Text( )
|
|
<< ( SRD::Times( 3 ) << Word( ) )
|
|
<< EnterContext( "color-grading" )
|
|
<< OnEnter( EnterColorGrading_ )
|
|
<< OnExit( AddColorGrading_ ) )
|
|
// Camera controls
|
|
<< ( Rule() << "camera" << Text( ) << EnterContext( "camera" )
|
|
<< OnEnter( EnterCam_ )
|
|
<< OnExit( ExitCam_ ) )
|
|
;
|
|
|
|
// 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_ )
|
|
;
|
|
|
|
// Integer control parameters
|
|
defs.context( "int" )
|
|
<< ( Rule() << "slider" << IntSetSlider_ )
|
|
<< ( Rule() << "min" << Int32() << IntSetMin_ )
|
|
<< ( Rule() << "max" << Int32() << IntSetMax_ )
|
|
<< ( Rule() << "step" << Numeric() << IntSetStep_ )
|
|
;
|
|
|
|
// Color grading controls
|
|
defs.context( "color-grading" )
|
|
<< ( Rule() << "base" << Numeric( ) << CgSetBase_ )
|
|
<< ( Rule() << "unit" << Numeric( ) << CgSetUnit_ )
|
|
;
|
|
|
|
// Camera controls
|
|
defs.context( "camera" )
|
|
<< ( Rule() << "fov" << Word() << CamSetFov_ )
|
|
<< ( Rule() << "near-plane" << Word() << CamSetNP_ )
|
|
//
|
|
<< ( Rule() << ( Alt() << "target" << "look-at" )
|
|
<< ( SRD::Times( 3 ) << Word() )
|
|
<< CamSetTarget_ )
|
|
//
|
|
<< ( Rule() << "position" << ( SRD::Times( 3 ) << Word() ) << CamSetPosition_ )
|
|
<< ( Rule() << "up" << ( SRD::Times( 3 ) << Word() ) << CamSetUpVector_ )
|
|
//
|
|
<< ( Rule() << "angles" << ( SRD::Times( 3 ) << Word() ) << CamSetAngles_ )
|
|
<< ( Rule() << "distance" << Word() << CamSetDistance_ )
|
|
;
|
|
|
|
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 >= 0 && n <= 20 );
|
|
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
|
|
: 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
|
|
: 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
|
|
: 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 ];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*= 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 ];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*= T_ColorGrading =============================================================*/
|
|
|
|
T_ColorGrading::T_ColorGrading(
|
|
T_String const& iRed ,
|
|
T_String const& iGreen ,
|
|
T_String const& iBlue ,
|
|
T_String const& title ) noexcept
|
|
: A_SyncOverride( "cg" , title )
|
|
{
|
|
inputs_.add( iRed );
|
|
inputs_.add( iGreen );
|
|
inputs_.add( iBlue );
|
|
}
|
|
|
|
void T_ColorGrading::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{ ColorGradingControls(
|
|
label ,
|
|
&v[ 0 ] , &v[ 1 ] , &v[ 2 ] ,
|
|
base( ) , unit( ) ) };
|
|
|
|
if ( changed ) {
|
|
for ( auto i = 0 ; i < 3 ; i ++ ) {
|
|
sinp[ inputPos_[ i ] ] = v[ i ];
|
|
}
|
|
}
|
|
}
|
|
|
|
bool T_ColorGrading::setBase(
|
|
const float v ) noexcept
|
|
{
|
|
M_SETOPT_( base_ , v );
|
|
}
|
|
|
|
bool T_ColorGrading::setUnit(
|
|
const float v ) noexcept
|
|
{
|
|
assert( v != 0 );
|
|
M_SETOPT_( unit_ , v );
|
|
}
|
|
|
|
|
|
/*= T_CamOverride ==============================================================*/
|
|
|
|
T_CamOverride::T_CamOverride(
|
|
T_String const& title ) noexcept
|
|
: A_SyncOverride( "cam" , title ) ,
|
|
camMode_( CM_INVALID )
|
|
{}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
T_CamOverride::E_SetState T_CamOverride::setFieldOfView(
|
|
T_String const& input ) noexcept
|
|
{
|
|
if ( fovConfig_ ) {
|
|
return S_DEF;
|
|
}
|
|
if ( inputs_.contains( input ) ) {
|
|
return S_INPUTS;
|
|
}
|
|
fovConfig_.setNew( FM_FOV , inputs_.size( ) );
|
|
inputs_.add( input );
|
|
return S_OK;
|
|
}
|
|
|
|
T_CamOverride::E_SetState T_CamOverride::setNearPlane(
|
|
T_String const& input ) noexcept
|
|
{
|
|
if ( fovConfig_ ) {
|
|
return S_DEF;
|
|
}
|
|
if ( inputs_.contains( input ) ) {
|
|
return S_INPUTS;
|
|
}
|
|
fovConfig_.setNew( FM_NEARPLANE , inputs_.size( ) );
|
|
inputs_.add( input );
|
|
return S_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
T_CamOverride::E_SetState T_CamOverride::setTarget(
|
|
T_String const& inX ,
|
|
T_String const& inY ,
|
|
T_String const& inZ ) noexcept
|
|
{
|
|
return setVector( target_ , inX , inY , inZ );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
T_CamOverride::E_SetState T_CamOverride::setUpVector(
|
|
T_String const& inX ,
|
|
T_String const& inY ,
|
|
T_String const& inZ ) noexcept
|
|
{
|
|
return setVector( upVector_ , inX , inY , inZ );
|
|
}
|
|
|
|
T_CamOverride::E_SetState T_CamOverride::setPositionVector(
|
|
T_String const& inX ,
|
|
T_String const& inY ,
|
|
T_String const& inZ ) noexcept
|
|
{
|
|
return setVector( position_ , inX , inY , inZ );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
T_CamOverride::E_SetState T_CamOverride::setAngles(
|
|
T_String const& in1 ,
|
|
T_String const& in2 ,
|
|
T_String const& in3 ) noexcept
|
|
{
|
|
return setVector( angles_ , in1 , in2 , in3 );
|
|
}
|
|
|
|
T_CamOverride::E_SetState T_CamOverride::setDistance(
|
|
T_String const& input ) noexcept
|
|
{
|
|
if ( distance_ ) {
|
|
return S_DEF;
|
|
}
|
|
if ( inputs_.contains( input ) ) {
|
|
return S_INPUTS;
|
|
}
|
|
distance_ = inputs_.size( );
|
|
inputs_.add( input );
|
|
return S_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
bool T_CamOverride::checkValidConfig( ) noexcept
|
|
{
|
|
if ( camMode_ != CM_INVALID ) {
|
|
return true;
|
|
}
|
|
|
|
if ( angles_ && distance_ && !( position_ || upVector_ ) ) {
|
|
camMode_ = CM_ANGLES;
|
|
} else if ( position_ && upVector_ && !( angles_ || distance_ ) ) {
|
|
camMode_ = CM_VECTORS;
|
|
}
|
|
return ( camMode_ != CM_INVALID );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
T_CamOverride::E_SetState T_CamOverride::setVector(
|
|
T_Optional< T_VectorConfig_ >& vector ,
|
|
T_String const& inX ,
|
|
T_String const& inY ,
|
|
T_String const& inZ ) noexcept
|
|
{
|
|
if ( vector ) {
|
|
return S_DEF;
|
|
}
|
|
if ( inputs_.contains( inX ) || inputs_.contains( inY ) || inputs_.contains( inZ ) ) {
|
|
return S_INPUTS;
|
|
}
|
|
|
|
const uint32_t s( inputs_.size( ) );
|
|
vector.setNew( s , s+1 , s+2 );
|
|
inputs_.add( inX );
|
|
inputs_.add( inY );
|
|
inputs_.add( inZ );
|
|
return S_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
void T_CamOverride::makeEditWidgets(
|
|
uint32_t& counter ,
|
|
T_StringBuilder& sb ) noexcept
|
|
{
|
|
auto& sinp( Globals::Sync( ).inputs( ) );
|
|
|
|
// Set field of view / near plane
|
|
auto const& fc( *fovConfig_ );
|
|
if ( fc.mode == FM_FOV ) {
|
|
camera_.fieldOfView( sinp[ inputPos_[ fc.inputIndex ] ] );
|
|
} else {
|
|
camera_.nearPlane( sinp[ inputPos_[ fc.inputIndex ] ] );
|
|
}
|
|
|
|
// Set camera parameters
|
|
const glm::vec3 lookAt{ vectorFromInputs( *target_ ) };
|
|
if ( camMode_ == CM_ANGLES ) {
|
|
const glm::vec3 angles{ vectorFromInputs( *angles_ ) };
|
|
const float distance{ sinp[ inputPos_[ *distance_ ] ] };
|
|
camera_.camera( lookAt , angles , distance );
|
|
} else {
|
|
const glm::vec3 position{ vectorFromInputs( *position_ ) };
|
|
const glm::vec3 up{ vectorFromInputs( *upVector_ ) };
|
|
camera_.camera( lookAt , position , up );
|
|
}
|
|
|
|
// Draw UI
|
|
char const* const name( buildLabel( counter , sb ) );
|
|
using namespace ImGui;
|
|
PushItemWidth( 0 ); // Compensate for -1
|
|
PushID( GetCurrentWindow( )->GetID( name ) );
|
|
const auto changes{ camera_.makeUI( ) };
|
|
PopID( );
|
|
PopItemWidth( );
|
|
|
|
if ( changes & T_Camera::E_Changes::FOV ) {
|
|
if ( fc.mode == FM_FOV ) {
|
|
sinp[ inputPos_[ fc.inputIndex ] ] = camera_.fieldOfView( );
|
|
} else {
|
|
sinp[ inputPos_[ fc.inputIndex ] ] = camera_.nearPlane( );
|
|
}
|
|
}
|
|
if ( changes & T_Camera::E_Changes::MATRIX ) {
|
|
inputsFromVector( *target_ , camera_.lookAt( ) );
|
|
if ( camMode_ == CM_ANGLES ) {
|
|
inputsFromVector( *angles_ , camera_.angles( ) );
|
|
sinp[ inputPos_[ *distance_ ] ] = camera_.distance( );
|
|
} else {
|
|
inputsFromVector( *position_ , camera_.position( ) );
|
|
inputsFromVector( *upVector_ , camera_.upVector( ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
glm::vec3 T_CamOverride::vectorFromInputs(
|
|
T_VectorConfig_ const& vc ) noexcept
|
|
{
|
|
auto& sinp( Globals::Sync( ).inputs( ) );
|
|
return glm::vec3{
|
|
sinp[ inputPos_[ vc.x ] ] ,
|
|
sinp[ inputPos_[ vc.y ] ] ,
|
|
sinp[ inputPos_[ vc.z ] ] };
|
|
}
|
|
|
|
void T_CamOverride::inputsFromVector(
|
|
T_VectorConfig_ const& vc ,
|
|
glm::vec3 const& v ) noexcept
|
|
{
|
|
auto& sinp( Globals::Sync( ).inputs( ) );
|
|
sinp[ inputPos_[ vc.x ] ] = v.x;
|
|
sinp[ inputPos_[ vc.y ] ] = v.y;
|
|
sinp[ inputPos_[ vc.z ] ] = v.z;
|
|
}
|