#pragma once #ifndef REAL_BUILD # include "externals.hh" #endif // Duration and current playing time struct T_SyncTime { float uDuration = 1e-3f; // Duration - unit size uint32_t iDuration = 1; // Duration - total units float time = 0; void setDuration( __rd__ const float uDuration , __rd__ const uint32_t iDuration ); float duration( ) const noexcept { return uDuration * iDuration; } void setTime( __rd__ const float t ) noexcept { time = std::max( 0.f , std::min( t , duration( ) ) ); } }; /*============================================================================*/ // Segment of an input's curve struct T_SyncSegment { enum E_SegmentType { LINEAR , RAMP , SMOOTH , //HERMITE }; uint32_t nPoints; E_SegmentType type; std::vector< float > values; // nPoints items std::vector< uint32_t > durations; // nPoints - 1 items }; // An input curve struct T_SyncCurve { std::string name; std::vector< T_SyncSegment > segments; }; // All configured curves. Some may not actually correspond to an input and may // have been defined for inputs that have been removed temporarily (e.g. // because some include was commented out), in which case we don't want to // waste them. struct T_SyncCurves { std::vector< T_SyncCurve > curves; std::map< std::string , int32_t > positions; void clear( ); // Returns true on success, false on duplicate bool addCurve( __rd__ T_SyncCurve curve ); // Returns -1 on lookup failure int32_t indexOf( __rd__ std::string const& name ); }; /*----------------------------------------------------------------------------*/ // Pre-computed data for a curve struct T_SyncCurveCache { using T_SegRef = std::pair< uint32_t , uint32_t >; uint32_t curve; std::vector< T_SegRef > segRefs; std::vector< float > segStarts; std::vector< float > segEnds; uint32_t curPos; T_SyncCurveCache( __rd__ T_SyncTime const& time , __rd__ T_SyncCurves const& curves , __rd__ const uint32_t curve ) noexcept; // Find the index of the segment for the specified time uint32_t findSegment( __rd__ const float time ) const noexcept; // Compute the value of the curve at the specified location, ignoring // curPos. float valueAt( __rd__ T_SyncTime const& time , __rd__ T_SyncCurves const& curves , __rd__ const float position ) const noexcept; // Compute the value of the curve at the current time, using and // updating curPos as necessary. float value( __rd__ T_SyncTime const& time , __rd__ T_SyncCurves const& curves ) noexcept; float segmentValue( __rd__ float time , __rd__ uint32_t segIndex , __rd__ std::vector< T_SyncSegment > const& segments ) const noexcept; }; using P_SyncCurveCache = std::unique_ptr< T_SyncCurveCache >; /*============================================================================*/ // Synchronization values. The values vector always contains an extra entry // used for missing inputs. struct T_SyncValues { std::vector< std::string > identifiers; std::vector< float > values; std::vector< bool > overriden; std::unordered_map< std::string , uint32_t > positions; T_SyncValues( ); void clear( ); // Returns true on success, false on duplicate bool addValue( __rd__ std::string const& name , __rd__ const float initial = 0.f ); // If the name isn't found, the last entry of values[] is returned uint32_t indexOf( __rd__ std::string const& name ) const; }; /*============================================================================*/ // Synchronisation manager; handles all the synchronization data and makes it // work together. struct T_SyncManager { // --------------------------------------------------------------------- // Duration & time controls void setDuration( __rd__ const float uDuration , __rd__ const uint32_t iDuration ); float duration( ) const noexcept { return time_.duration( ); } void setTime( __rd__ const float time ); void timeDelta( __rd__ const float delta ) { setTime( time_.time + delta ); } float time( ) const noexcept { return time_.time; } bool finished( ) const noexcept { return time_.time >= time_.duration( ); } // --------------------------------------------------------------------- void updateCurveCaches( ); void updateValues( ); private: T_SyncTime time_; T_SyncValues values_; T_SyncCurves curves_; std::vector< P_SyncCurveCache > curveCaches_; }; /*============================================================================*/ // DISREGARD EVERYTHING BELOW, IT SUCKS! /*============================================================================*/ #if 0 // Definition of a single input - id & range struct T_SyncInputDfn { std::string identifier; float min = -std::numeric_limits< float >::infinity( ), max = std::numeric_limits< float >::infinity( ); T_SyncInputDfn( __rd__ std::string const& identifier , __rd__ const float min , __rd__ const float max ) noexcept : identifier( identifier ) , min( min ) , max( max ) { } }; using P_SyncInputDfn = std::unique_ptr< T_SyncInputDfn >; /*============================================================================*/ // Definition of UI overrides for inputs struct T_SyncUIOverride { enum E_Type { FLOAT , VEC2 , VEC3 , VEC4 , INT , COLOR , COLOR_GRADING , CAMERA }; std::string title; E_Type type; std::vector< std::string > inputs; bool enabled; }; using P_SyncUIOverride = std::unique_ptr< T_SyncUIOverride >; using T_SyncUIOverrides = std::vector< P_SyncUIOverride >; // UI override sections struct T_SyncUISection; using P_SyncUISection = std::unique_ptr< T_SyncUISection >; using T_SyncUISections = std::vector< P_SyncUISection >; struct T_SyncUISection { std::string title; T_SyncUISections subsections; T_SyncUIOverrides overrides; }; /*============================================================================*/ struct T_SyncManager { float uDuration; // Duration - unit size uint32_t iDuration; // Duration - total units float duration( ) const noexcept { return uDuration * iDuration; } // Sync manager data for an input may include a definition, a curve, // or both. The idea behind supporting "curve only" is that a curve may // have been defined for an input that has been removed temporarily // (e.g. because some include was commented out), in which case we don't // want to waste it. struct T_Data { P_SyncInputDfn definition; P_SyncCurveCache curve; bool overriden; }; // Data and ID<->index map std::vector< T_Data > data; std::map< std::string , uint32_t > posMap; // Current time & values float time; std::vector< float > values; // Root of the UI's tree T_SyncUISections uiRoot; void makeUI( ); bool wOverrides = false; bool wCurves = false; private: void displayOvSections( __rw__ T_SyncUISections& sections , __rd__ const bool topLevel = false ); void displayOvControls( __rw__ T_SyncUIOverrides& overrides ); }; #endif /*============================================================================*/ using T_SyncVariable = std::vector< T_SyncSegment >; struct T_SyncData { T_SyncData( ); T_SyncData( __rd__ const uint32_t duration , __rd__ const float units ) noexcept; float duration( ) const noexcept { return duration_ * units_; } void setSyncVariable( __rd__ std::string const& name , __rw__ T_SyncVariable&& variable ) noexcept; T_SyncVariable const& variable( __rd__ std::string const& name ) const noexcept; uint32_t offsetOf( __rd__ std::string const& name ) const noexcept; float valueOf( __rd__ std::string const& variable , __rd__ const float time ) const noexcept; void computeValues( __rd__ const float time , __wr__ std::vector< float >& values ) const noexcept; private: static const T_SyncVariable MissingVariable_; // Caching structure used to access segments using T_SegRef_ = std::pair< uint32_t , uint32_t >; struct T_VarHelper_ { T_SyncVariable variable; std::vector< T_SegRef_ > segRefs; std::vector< float > segStarts; uint32_t position; T_VarHelper_( __rw__ T_SyncVariable&& variable , __rd__ const uint32_t duration , __rd__ const uint32_t position ) noexcept; float valueAt( __rd__ const float position , __rd__ const float units ) const noexcept; }; uint32_t duration_; float units_; std::unordered_map< std::string , T_VarHelper_ > variables_; };