diff --git a/curves.srd b/curves.srd index 981c663..37c6d74 100644 --- a/curves.srd +++ b/curves.srd @@ -1,3 +1,5 @@ +(duration 0.016667 3600) + (dof-sharp-distance (segment smooth (values 35 100 35) diff --git a/main.cc b/main.cc index 9b7ab74..4558b5c 100644 --- a/main.cc +++ b/main.cc @@ -82,7 +82,6 @@ void T_Main::mainLoop( ) Globals::Watcher( ).check( ); Globals::Shaders( ).update( ); - Globals::Sync( ).checkCurveFile( ); glFinish( ); p.startFrame( ); @@ -205,9 +204,17 @@ void T_Main::makeUI( ) { using namespace ImGui; auto& undo( Globals::Undo( ) ); + auto& sync( Globals::Sync( ) ); bool eSequencer{ sequencer }; if ( BeginMainMenuBar( ) ) { if ( BeginMenu( "File" ) ) { + if ( MenuItem( "Save curves" , "C-s" , false , sync.curvesModified( ) ) ) { + } + if ( MenuItem( "Reload curves" , "C-R" , false , sync.curvesModified( ) ) ) { + // FIXME: confirmation dialog + sync.loadCurves( ); + } + Separator( ); if ( MenuItem( "Undo" , "C-z" , false , undo.canUndo( ) ) ) { undo.undo( ); } @@ -222,7 +229,7 @@ void T_Main::makeUI( ) } if ( BeginMenu( "Views" ) ) { MenuItemCheckbox( "Input overrides" , - &Globals::Sync( ).overridesWindowEnabled( ) ); + &sync.overridesWindowEnabled( ) ); MenuItemCheckbox( "Output debugger" , &Globals::ODbg( ).uiEnabled( ) ); MenuItemCheckbox( "Profiler" , diff --git a/sync.cc b/sync.cc index d8831ae..5164c40 100644 --- a/sync.cc +++ b/sync.cc @@ -25,6 +25,13 @@ const std::map< std::string , T_SyncSegment::E_SegmentType > SegmentTypes_( ([] namespace { +struct T_ParserOutput_ +{ + T_SyncCurves curves; + T_Optional< T_SyncTime > time; + ebcl::T_SRDLocation tLocation; +}; + using namespace ebcl; bool CPEnterCurve_( T_SRDParserData const& data ) @@ -35,8 +42,8 @@ bool CPEnterCurve_( T_SRDParserData const& data ) bool CPExitCurve_( T_SRDParserData const& data ) { - T_SyncCurve& curve( data.currentData->value< T_SyncCurve >( ) ); - T_SyncCurves& curves( *( data.targetData->value< T_SharedPtr< T_SyncCurves > >( ) ) ); + auto& curve( data.currentData->value< T_SyncCurve >( ) ); + auto& po( *( data.targetData->value< T_SharedPtr< T_ParserOutput_ > >( ) ) ); if ( curve.segments.empty( ) ) { T_StringBuilder sb; @@ -44,12 +51,12 @@ bool CPExitCurve_( T_SRDParserData const& data ) data.errors.add( std::move( sb ) , (*data.input)[ 0 ] ); } - if ( curves.curves.contains( curve.name ) ) { + if ( po.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 ) ); + po.curves.setCurve( std::move( curve ) ); } return true; @@ -118,13 +125,30 @@ bool CPSegmentDV_( T_SRDParserData const& data ) return true; } +bool CPSetDuration_( T_SRDParserData const& data ) +{ + auto const& input( *data.input ); + auto& po( *( data.currentData->value< T_SharedPtr< T_ParserOutput_ > >( ) ) ); + if ( po.time ) { + T_StringBuilder eb; + eb << "duplicate duration specification; previous: " + << po.tLocation; + data.errors.add( std::move( eb ) , input[ 0 ].location( ) ); + } else { + po.time = T_SyncTime( ); + po.time->uDuration = std::min( 2. , std::max( 1. / 60. , input[ 1 ].floatValue( ) ) ); + po.time->iDuration = std::max( 1l , input[ 2 ].longValue( ) ); + } + 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 >( ); + *( data.currentData ) = NewShared< T_ParserOutput_ >( ); return true; } ); @@ -133,7 +157,9 @@ T_SRDParserConfig MakeCurvesParser_( ) defs.context( "default" ) << ( Rule( ) << Text( ) << EnterContext( "segments" ) - << OnEnter( CPEnterCurve_ ) << OnExit( CPExitCurve_ ) ); + << OnEnter( CPEnterCurve_ ) << OnExit( CPExitCurve_ ) ) + << ( Rule( ) << "duration" << Float( ) << Int32( ) + << CPSetDuration_ ); defs.context( "segments" ) << ( Rule( ) << "segment" << Enum( "segment-type" ) << ( List( ) << "values" << ( AtLeast( 2 ) << Numeric( ) ) ) @@ -516,8 +542,12 @@ T_SyncOverrideVisitor::T_OpElement T_SyncOverrideVisitor::nodeBrowser( T_SyncManager::T_SyncManager( ) : pConfig_( MakeCurvesParser_( ) ) , + watcher_{ Globals::Watcher( ) , [this](){ curvesChanged_( ); } } , soRoot_( "*root*" ) -{ } +{ + watcher_.watch( "curves.srd" ); + loadCurves( ); +} /*----------------------------------------------------------------------------*/ @@ -559,24 +589,11 @@ void T_SyncManager::clearInputs( ) noexcept /*----------------------------------------------------------------------------*/ -void T_SyncManager::checkCurveFile( ) -{ - if ( watcher_ ) { - return; - } - - watcher_ = NewOwned< T_WatchedFiles >( - Globals::Watcher( ) , - [this] { curvesChanged_( ); } ); - watcher_->watch( "curves.srd" ); - bool missing; - loadCurves_( missing ); -} - void T_SyncManager::clearCurves( ) { curves_.clear( ); updateCurveCaches( ); + modified_ = true; } void T_SyncManager::setCurve( @@ -584,6 +601,7 @@ void T_SyncManager::setCurve( { curves_.setCurve( curve ); updateCurveCaches( ); + modified_ = true; } void T_SyncManager::removeCurve( @@ -591,33 +609,42 @@ void T_SyncManager::removeCurve( { if ( curves_.removeCurve( curve ) ) { updateCurveCaches( ); + modified_ = true; } } void T_SyncManager::curvesChanged_( ) { - bool missing; - loadCurves_( missing ); + if ( modified_ ) { + fileChanged_ = true; + } else { + loadCurves( ); + } } -bool T_SyncManager::loadCurves_( - bool& missing ) +bool T_SyncManager::loadCurves( ) { printf( "Loading curves data\n" ); - missing = true; try { using namespace ebcl; const T_SRDParserConfig cfg( MakeCurvesParser_( ) ); T_File file( "curves.srd" , E_FileMode::READ_ONLY ); file.open( ); - missing = false; 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 > >( ) ); + auto p( parser.getData< T_SharedPtr< T_ParserOutput_ > >( ) ); + curves_ = std::move( p->curves ); + if ( p->time ) { + time_.iDuration = p->time->iDuration; + time_.uDuration = p->time->uDuration; + } else { + time_.iDuration = 3600; + time_.uDuration = 1.f / 60.f; + } } catch ( ebcl::X_StreamError const& e ) { printf( "... ERR %s\n" , e.what( ) ); return false; @@ -636,6 +663,7 @@ bool T_SyncManager::loadCurves_( printf( "... success\n" ); updateCurveCaches( ); + modified_ = fileChanged_ = false; return true; } diff --git a/sync.hh b/sync.hh index 983e5b1..b2a5505 100644 --- a/sync.hh +++ b/sync.hh @@ -343,7 +343,6 @@ struct T_SyncManager : public virtual A_MouseCtrl // --------------------------------------------------------------------- // Curves - void checkCurveFile( ); void clearCurves( ); void setCurve( T_SyncCurve curve ); void removeCurve( T_String const& curve ) noexcept; @@ -351,9 +350,15 @@ struct T_SyncManager : public virtual A_MouseCtrl T_Array< T_SyncCurve > const& curves( ) const noexcept { return curves_.curves.values( ); } + bool curvesModified( ) const noexcept + { return modified_; } + bool curvesFileChanged( ) const noexcept + { return fileChanged_; } + + bool loadCurves( ); + private: void curvesChanged_( ); - bool loadCurves_( bool& missing ); // --------------------------------------------------------------------- @@ -407,7 +412,9 @@ struct T_SyncManager : public virtual A_MouseCtrl private: ebcl::T_SRDParserConfig pConfig_; // Parser config for curves - P_WatchedFiles watcher_; // Curves file watcher + T_WatchedFiles watcher_; // Curves file watcher + bool modified_; // Locally modified + bool fileChanged_; // File modified T_SyncTime time_; // Duration/time information bool playing_{ false }; // Is it playing?