Curves use SRD file
This commit is contained in:
parent
2ce821c4c0
commit
13d7a544ef
7 changed files with 214 additions and 203 deletions
23
curves.json
23
curves.json
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"dof:sharp-distance" : [
|
||||
{
|
||||
"type" : "smooth" ,
|
||||
"values" : [ 35 , 100 , 35 ] ,
|
||||
"durations" : [ 300 , 300 ]
|
||||
}
|
||||
] ,
|
||||
"dof:sharp-range" : [
|
||||
{
|
||||
"type" : "smooth" ,
|
||||
"values" : [ 20 , 2 ] ,
|
||||
"durations" : [ 900 ]
|
||||
}
|
||||
] ,
|
||||
"dof:falloff" : [
|
||||
{
|
||||
"type" : "linear" ,
|
||||
"values" : [ 2 , 2 ] ,
|
||||
"durations" : [ 1 ]
|
||||
}
|
||||
]
|
||||
}
|
20
curves.srd
Normal file
20
curves.srd
Normal file
|
@ -0,0 +1,20 @@
|
|||
(dof-sharp-distance
|
||||
(segment smooth
|
||||
(values 35 100 35)
|
||||
(durations 300 300)
|
||||
)
|
||||
)
|
||||
|
||||
(dof-sharp-range
|
||||
(segment smooth
|
||||
(values 20 2)
|
||||
(durations 900)
|
||||
)
|
||||
)
|
||||
|
||||
(dof-falloff
|
||||
(segment linear
|
||||
(values 2 2)
|
||||
(durations 1)
|
||||
)
|
||||
)
|
10
demo.cc
10
demo.cc
|
@ -25,11 +25,11 @@ bool T_Demo::initialise( )
|
|||
|
||||
Globals::Sync( ).clearInputs( );
|
||||
// XXX should come from program
|
||||
Globals::Sync( ).addInput( "dof:sharp-distance" , 15 );
|
||||
Globals::Sync( ).addInput( "dof:sharp-range" , 5 );
|
||||
Globals::Sync( ).addInput( "dof:falloff" , 10 );
|
||||
Globals::Sync( ).addInput( "dof:max-blur" , 16 );
|
||||
Globals::Sync( ).addInput( "dof:samples" , 16 );
|
||||
Globals::Sync( ).addInput( "dof-sharp-distance" , 15 );
|
||||
Globals::Sync( ).addInput( "dof-sharp-range" , 5 );
|
||||
Globals::Sync( ).addInput( "dof-falloff" , 10 );
|
||||
Globals::Sync( ).addInput( "dof-max-blur" , 16 );
|
||||
Globals::Sync( ).addInput( "dof-samples" , 16 );
|
||||
Globals::Sync( ).updateCurveCaches( );
|
||||
|
||||
return true;
|
||||
|
|
10
dof.cc
10
dof.cc
|
@ -63,13 +63,13 @@ void T_DoFPass::render( )
|
|||
<< OPLoadVariable( "width" )
|
||||
<< OPLoadConstant( U_RES_TIME )
|
||||
<< OPDup( 8 )
|
||||
<< OPLoadInput( "dof:samples" )
|
||||
<< OPLoadInput( "dof-samples" )
|
||||
<< OPLoadConstant( U_SAMPLES )
|
||||
<< OPDup( 11 )
|
||||
<< OPLoadInput( "dof:max-blur" )
|
||||
<< OPLoadInput( "dof:falloff" )
|
||||
<< OPLoadInput( "dof:sharp-range" )
|
||||
<< OPLoadInput( "dof:sharp-distance" )
|
||||
<< OPLoadInput( "dof-max-blur" )
|
||||
<< OPLoadInput( "dof-falloff" )
|
||||
<< OPLoadInput( "dof-sharp-range" )
|
||||
<< OPLoadInput( "dof-sharp-distance" )
|
||||
<< OPLoadConstant( U_PARAMS )
|
||||
<< OPDup( 17 )
|
||||
<< OPLoadConstant( 1 )
|
||||
|
|
2
ebcl
2
ebcl
|
@ -1 +1 @@
|
|||
Subproject commit 1b1be9e6b2149867c5de67a3dc62ed997f803334
|
||||
Subproject commit 073fcb3d5e9366de941ebce73a42cbf3c7686b4d
|
332
sync.cc
332
sync.cc
|
@ -2,6 +2,11 @@
|
|||
#include "sync.hh"
|
||||
#include "globals.hh"
|
||||
|
||||
#include <ebcl/Files.hh>
|
||||
#include <ebcl/SRDText.hh>
|
||||
#include <ebcl/SRDParser.hh>
|
||||
using ebcl::T_SRDParserConfig;
|
||||
|
||||
namespace {
|
||||
|
||||
const std::map< std::string , T_SyncSegment::E_SegmentType > SegmentTypes_( ([] {
|
||||
|
@ -15,6 +20,135 @@ const std::map< std::string , T_SyncSegment::E_SegmentType > SegmentTypes_( ([]
|
|||
}
|
||||
|
||||
|
||||
/*= SRD parser for the curves ================================================*/
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace ebcl;
|
||||
|
||||
bool CPEnterCurve_( T_SRDParserData const& data )
|
||||
{
|
||||
*( data.targetData ) = T_SyncCurve{ (*data.input)[ 0 ].stringValue( ) };
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPExitCurve_( T_SRDParserData const& data )
|
||||
{
|
||||
T_SyncCurve& curve( data.currentData->value< T_SyncCurve >( ) );
|
||||
T_SyncCurves& curves( *( data.targetData->value< T_SharedPtr< T_SyncCurves > >( ) ) );
|
||||
|
||||
if ( curve.segments.empty( ) ) {
|
||||
T_StringBuilder sb;
|
||||
sb << "curve '" << curve.name << "' is empty";
|
||||
data.errors.add( std::move( sb ) , (*data.input)[ 0 ] );
|
||||
}
|
||||
|
||||
if ( curves.curves.contains( curve.name ) ) {
|
||||
T_StringBuilder sb;
|
||||
sb << "duplicate curve '" << curve.name << "'";
|
||||
data.errors.add( std::move( sb ) , (*data.input)[ 0 ] );
|
||||
} else {
|
||||
curves.setCurve( std::move( curve ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPHandleSegment_(
|
||||
const T_SyncSegment::E_SegmentType type ,
|
||||
T_SRDList const& lValues ,
|
||||
T_SRDList const& lDurations ,
|
||||
T_SRDErrors& errors ,
|
||||
T_SyncCurve& curve )
|
||||
{
|
||||
bool failed = false;
|
||||
if ( lDurations.size( ) != lValues.size( ) - 1 ) {
|
||||
errors.add( "values / durations count mismatch" , lValues[ 0 ] );
|
||||
failed = true;
|
||||
}
|
||||
|
||||
// Check durations
|
||||
const auto nd( lDurations.size( ) );
|
||||
for ( auto i = 1u ; i < nd ; i ++ ) {
|
||||
auto const& tok( lDurations[ i ] );
|
||||
const uint64_t v( tok.longValue( ) );
|
||||
if ( v < 1 || v > UINT32_MAX ) {
|
||||
errors.add( "invalid duration" , tok );
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !failed ) {
|
||||
T_SyncSegment& segment( curve.segments.addNew( ) );
|
||||
segment.type = type;
|
||||
segment.durations.ensureCapacity( nd - 1 );
|
||||
for ( auto i = 1u ; i < nd ; i ++ ) {
|
||||
auto const& tok( lDurations[ i ] );
|
||||
segment.durations.add( uint32_t( tok.longValue( ) ) );
|
||||
}
|
||||
|
||||
segment.values.ensureCapacity( nd );
|
||||
for ( auto i = 1u ; i <= nd ; i ++ ) {
|
||||
auto const& tok( lValues[ i ] );
|
||||
segment.values.add( tok.floatValue( ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CPSegmentVD_( T_SRDParserData const& data )
|
||||
{
|
||||
auto const& input( *data.input );
|
||||
const auto ev( data.config.enumValue( "segment-type" , input[ 1 ].stringValue( ) ) );
|
||||
assert( ev.present( ) );
|
||||
CPHandleSegment_( (T_SyncSegment::E_SegmentType) *ev.target( ) ,
|
||||
input[ 2 ].list( ) , input[ 3 ].list( ) ,
|
||||
data.errors , data.targetData->value< T_SyncCurve >( ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPSegmentDV_( T_SRDParserData const& data )
|
||||
{
|
||||
auto const& input( *data.input );
|
||||
const auto ev( data.config.enumValue( "segment-type" , input[ 1 ].stringValue( ) ) );
|
||||
assert( ev.present( ) );
|
||||
CPHandleSegment_( (T_SyncSegment::E_SegmentType) *ev.target( ) ,
|
||||
input[ 3 ].list( ) , input[ 2 ].list( ) ,
|
||||
data.errors , data.targetData->value< T_SyncCurve >( ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
T_SRDParserConfig MakeCurvesParser_( )
|
||||
{
|
||||
using namespace ebcl::SRD;
|
||||
|
||||
T_SRDParserDefs defs( "default" );
|
||||
defs << OnStart( []( T_SRDParserData const& data ) -> bool {
|
||||
*( data.currentData ) = NewShared< T_SyncCurves >( );
|
||||
return true;
|
||||
} );
|
||||
|
||||
defs.enumeration( "segment-type" )
|
||||
<< "linear" << "ramp" << "smooth";
|
||||
|
||||
defs.context( "default" )
|
||||
<< ( Rule( ) << Text( ) << EnterContext( "segments" )
|
||||
<< OnEnter( CPEnterCurve_ ) << OnExit( CPExitCurve_ ) );
|
||||
defs.context( "segments" )
|
||||
<< ( Rule( ) << "segment" << Enum( "segment-type" )
|
||||
<< ( List( ) << "values" << ( AtLeast( 2 ) << Numeric( ) ) )
|
||||
<< ( List( ) << "durations" << ( AtLeast( 1 ) << Integer( ) ) )
|
||||
<< CPSegmentVD_ )
|
||||
<< ( Rule( ) << "segment" << Enum( "segment-type" )
|
||||
<< ( List( ) << "durations" << ( AtLeast( 1 ) << Integer( ) ) )
|
||||
<< ( List( ) << "values" << ( AtLeast( 2 ) << Numeric( ) ) )
|
||||
<< CPSegmentDV_ );
|
||||
|
||||
return defs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*= T_SyncTime ===============================================================*/
|
||||
|
||||
void T_SyncTime::setDuration(
|
||||
|
@ -63,10 +197,9 @@ T_SyncCurveCache::T_SyncCurveCache(
|
|||
uint32_t s = 0;
|
||||
for ( auto i = 0u ; i < ns ; i ++ ) {
|
||||
auto const& v( c.segments[ i ] );
|
||||
assert( v.nPoints >= 2 );
|
||||
assert( v.durations.size( ) == v.nPoints - 1 );
|
||||
assert( v.durations.size( ) == v.values.size( ) - 1 );
|
||||
|
||||
const auto nd( v.nPoints - 1 );
|
||||
const auto nd( v.durations.size( ) );
|
||||
for ( auto j = 0u ; j < nd ; j ++ ) {
|
||||
const auto sStart( s * time.uDuration );
|
||||
if ( time.time >= sStart ) {
|
||||
|
@ -227,6 +360,12 @@ uint32_t T_SyncValues::indexOf(
|
|||
|
||||
/*= T_SyncManager ============================================================*/
|
||||
|
||||
T_SyncManager::T_SyncManager( )
|
||||
: pConfig_( MakeCurvesParser_( ) )
|
||||
{ }
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
void T_SyncManager::setDuration(
|
||||
const float uDuration ,
|
||||
const uint32_t iDuration )
|
||||
|
@ -250,15 +389,12 @@ void T_SyncManager::checkCurveFile( )
|
|||
return;
|
||||
}
|
||||
|
||||
printf( "CURVE INIT\n" );
|
||||
watcher_ = NewOwned< T_WatchedFiles >(
|
||||
Globals::Watcher( ) ,
|
||||
[this] { curvesChanged_( ); } );
|
||||
watcher_->watch( "curves.srd" );
|
||||
bool missing;
|
||||
if ( loadCurves_( missing ) || !missing ) {
|
||||
watcher_ = NewOwned< T_WatchedFiles >(
|
||||
Globals::Watcher( ) ,
|
||||
[this] { curvesChanged_( ); } );
|
||||
watcher_->watch( "curves.json" );
|
||||
}
|
||||
printf( "INIT MISSING IS %c\n" , missing ? 'Y' : 'N' );
|
||||
loadCurves_( missing );
|
||||
}
|
||||
|
||||
void T_SyncManager::clearCurves( )
|
||||
|
@ -277,166 +413,48 @@ void T_SyncManager::setCurve(
|
|||
void T_SyncManager::curvesChanged_( )
|
||||
{
|
||||
bool missing;
|
||||
if ( !loadCurves_( missing ) && missing ) {
|
||||
watcher_.clear( );
|
||||
}
|
||||
loadCurves_( missing );
|
||||
}
|
||||
|
||||
bool T_SyncManager::loadCurves_(
|
||||
bool& missing )
|
||||
{
|
||||
using T_STI_ = std::istream_iterator< char >;
|
||||
std::ifstream file( "curves.json" );
|
||||
picojson::value root;
|
||||
printf( "Loading curves data\n" );
|
||||
missing = true;
|
||||
try {
|
||||
missing = !file.is_open( );
|
||||
if ( missing ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string errors;
|
||||
picojson::parse( root , T_STI_( file ) , T_STI_( ) , &errors );
|
||||
if ( !errors.empty( ) ) {
|
||||
printf( "Failed to parse 'curves.json':\n%s\n" , errors.c_str( ) );
|
||||
return false;
|
||||
}
|
||||
} catch ( std::ios_base::failure const& e ) {
|
||||
printf( "I/O error while reading 'curves.json'\n%s\n" , e.what( ) );
|
||||
using namespace ebcl;
|
||||
const T_SRDParserConfig cfg( MakeCurvesParser_( ) );
|
||||
T_File file( "curves.srd" , E_FileMode::READ_ONLY );
|
||||
file.open( );
|
||||
missing = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
T_SyncCurves nCurves;
|
||||
if ( !loadCurvesData_( nCurves , root ) ) {
|
||||
T_FileInputStream fis( file );
|
||||
T_SRDParser parser( cfg );
|
||||
T_SRDTextReader reader( parser );
|
||||
reader.read( "curves.srd" , fis );
|
||||
|
||||
curves_ = std::move( *parser.getData< T_SharedPtr< T_SyncCurves > >( ) );
|
||||
} catch ( ebcl::X_StreamError const& e ) {
|
||||
printf( "... ERR %s\n" , e.what( ) );
|
||||
return false;
|
||||
|
||||
} catch ( ebcl::X_SRDErrors const& e ) {
|
||||
T_StringBuilder sb;
|
||||
auto const ne( e.errors.size( ) );
|
||||
for ( auto i = 0u ; i < ne ; i ++ ) {
|
||||
auto const& err( e.errors[ i ] );
|
||||
sb << "... ERR " << err.location( ) << ": " << err.error( ) << '\n';
|
||||
}
|
||||
sb << '\0';
|
||||
printf( "%s" , sb.data( ) );
|
||||
return false;
|
||||
}
|
||||
curves_ = std::move( nCurves );
|
||||
printf( "... success\n" );
|
||||
|
||||
updateCurveCaches( );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool T_SyncManager::loadCurvesData_(
|
||||
T_SyncCurves& curves ,
|
||||
picojson::value const& root )
|
||||
{
|
||||
if ( !root.is< T_JSONObject >( ) ) {
|
||||
printf( "Curves data: root is not a JSON object\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
auto const& r( root.get< T_JSONObject >( ) );
|
||||
bool ok( true );
|
||||
for ( auto const& item : r ) {
|
||||
if ( curves.indexOf( item.first.c_str( ) ) != -1 ) {
|
||||
printf( "Curves data: duplicate curve '%s'\n" ,
|
||||
item.first.c_str( ) );
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
if ( !item.second.is< T_JSONArray >( ) ) {
|
||||
printf( "Curves data: entry for curve '%s' is not an array\n" ,
|
||||
item.first.c_str( ) );
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
T_SyncCurve nsc{ item.first.c_str( ) };
|
||||
|
||||
bool segsOk( true );
|
||||
for ( auto const& v : item.second.get< T_JSONArray >( ) ) {
|
||||
if ( !v.is< T_JSONObject >( ) ) {
|
||||
printf( "Curves data: curve '%s': invalid segment\n" ,
|
||||
item.first.c_str( ) );
|
||||
segsOk = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
T_SyncSegment segment;
|
||||
try {
|
||||
if ( !loadSegmentData_( segment , (char*) nsc.name.toOSString( ).data( ) ,
|
||||
v.get< T_JSONObject >( ) ) ) {
|
||||
segsOk = false;
|
||||
continue;
|
||||
}
|
||||
} catch ( X_JsonGetFailed const& ) {
|
||||
printf( "Curves data: curve '%s': could not parse segment data\n" ,
|
||||
item.first.c_str( ) );
|
||||
segsOk = false;
|
||||
continue;
|
||||
}
|
||||
nsc.segments.add( std::move( segment ) );
|
||||
}
|
||||
|
||||
ok = ok && segsOk;
|
||||
if ( nsc.segments.size( ) == 0 && segsOk ) {
|
||||
printf( "Curves data: curve '%s': no segments\n" ,
|
||||
item.first.c_str( ) );
|
||||
ok = false;
|
||||
}
|
||||
curves.setCurve( std::move( nsc ) );
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool T_SyncManager::loadSegmentData_(
|
||||
T_SyncSegment& segment ,
|
||||
T_String const& curve ,
|
||||
T_JSONObject const& sd )
|
||||
{
|
||||
auto const& sType( jsonGet< std::string >( sd , "type" ) );
|
||||
|
||||
const auto p( SegmentTypes_.find( sType ) );
|
||||
if ( p == SegmentTypes_.end( ) ) {
|
||||
printf( "Curves data: curve '%s': invalid segment type '%s'\n" ,
|
||||
curve.toOSString( ).data( ) , sType.c_str( ) );
|
||||
return false;
|
||||
}
|
||||
segment.type = p->second;
|
||||
|
||||
auto const& vList( jsonGet< T_JSONArray >( sd , "values" ) );
|
||||
auto const& dList( jsonGet< T_JSONArray >( sd , "durations" ) );
|
||||
|
||||
if ( vList.size( ) < 2 ) {
|
||||
printf( "Curves data: curve '%s': segment doesn't have enough values\n" ,
|
||||
curve.toOSString( ).data( ) );
|
||||
return false;
|
||||
}
|
||||
if ( vList.size( ) != dList.size( ) + 1 ) {
|
||||
printf( "Curves data: curve '%s': segment values / durations count mismatch\n" ,
|
||||
curve.toOSString( ).data( ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( auto const& vv : vList ) {
|
||||
if ( !vv.is< double >( ) ) {
|
||||
printf( "Curves data: curve '%s': non-numeric entry in segment values\n" ,
|
||||
curve.toOSString( ).data( ) );
|
||||
return false;
|
||||
}
|
||||
segment.values.add( vv.get< double >( ) );
|
||||
}
|
||||
|
||||
for ( auto const& dv : dList ) {
|
||||
if ( !dv.is< double >( ) ) {
|
||||
printf( "Curves data: curve '%s': non-numeric entry in segment durations\n" ,
|
||||
curve.toOSString( ).data( ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
const double dvn( dv.get< double >( ) );
|
||||
if ( fmod( dvn , 1.0 ) != 0.0 || dvn <= 0 ) {
|
||||
printf( "Curves data: curve '%s': invalid segment duration %f\n" ,
|
||||
curve.toOSString( ).data( ) , dvn );
|
||||
return false;
|
||||
}
|
||||
segment.durations.add( dvn );
|
||||
}
|
||||
|
||||
segment.nPoints = segment.values.size( );
|
||||
return true;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
void T_SyncManager::updateCurveCaches( )
|
||||
|
|
20
sync.hh
20
sync.hh
|
@ -2,6 +2,9 @@
|
|||
#include "filewatcher.hh"
|
||||
#include "utilities.hh"
|
||||
|
||||
#include <ebcl/SRDParserConfig.hh>
|
||||
|
||||
|
||||
// Duration and current playing time
|
||||
struct T_SyncTime
|
||||
{
|
||||
|
@ -33,10 +36,9 @@ struct T_SyncSegment
|
|||
//HERMITE
|
||||
};
|
||||
|
||||
uint32_t nPoints;
|
||||
E_SegmentType type;
|
||||
T_Array< float > values; // nPoints items
|
||||
T_Array< uint32_t > durations; // nPoints - 1 items
|
||||
T_Array< float > values;
|
||||
T_Array< uint32_t > durations; // n(values) - 1 items
|
||||
};
|
||||
|
||||
// An input curve
|
||||
|
@ -70,8 +72,6 @@ struct T_SyncCurves
|
|||
{ }
|
||||
|
||||
void clear( );
|
||||
|
||||
// Returns true on success, false on duplicate
|
||||
void setCurve( T_SyncCurve curve );
|
||||
|
||||
// Returns -1 on lookup failure
|
||||
|
@ -161,6 +161,8 @@ struct T_SyncValues
|
|||
// work together.
|
||||
struct T_SyncManager
|
||||
{
|
||||
T_SyncManager( );
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Duration & time controls
|
||||
|
||||
|
@ -203,13 +205,6 @@ struct T_SyncManager
|
|||
private:
|
||||
void curvesChanged_( );
|
||||
bool loadCurves_( bool& missing );
|
||||
bool loadCurvesData_(
|
||||
T_SyncCurves& curves ,
|
||||
picojson::value const& root );
|
||||
bool loadSegmentData_(
|
||||
T_SyncSegment& segment ,
|
||||
T_String const& curve ,
|
||||
T_JSONObject const& sd );
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Update
|
||||
|
@ -219,6 +214,7 @@ struct T_SyncManager
|
|||
void updateValues( );
|
||||
|
||||
private:
|
||||
ebcl::T_SRDParserConfig pConfig_;
|
||||
P_WatchedFiles watcher_;
|
||||
T_SyncTime time_;
|
||||
T_SyncValues values_;
|
||||
|
|
Loading…
Reference in a new issue