demotool/sync.hh

323 lines
7.9 KiB
C++

#pragma once
#include "filewatcher.hh"
#include "utilities.hh"
// Duration and current playing time
struct T_SyncTime
{
float uDuration = 1.f / 60.f; // Duration - unit size
uint32_t iDuration = 3600; // Duration - total units
float time = 0;
void setDuration(
const float uDuration ,
const uint32_t iDuration );
float duration( ) const noexcept
{ return uDuration * iDuration; }
void setTime( 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;
T_Array< float > values; // nPoints items
T_Array< uint32_t > durations; // nPoints - 1 items
};
// An input curve
struct T_SyncCurve
{
T_String name;
T_Array< T_SyncSegment > segments;
T_SyncCurve( ) noexcept { }
T_SyncCurve( T_String const& name ) noexcept
: name( name )
{ }
T_SyncCurve( char const* name ) noexcept
: name( T_String( name ).usePool( ) )
{ }
};
// 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
{
T_ObjectTable< T_String , T_SyncCurve > curves;
T_SyncCurves( )
: curves( []( T_SyncCurve const& c ) -> T_String { return c.name; } )
{ }
void clear( );
// Returns true on success, false on duplicate
void setCurve( T_SyncCurve curve );
// Returns -1 on lookup failure
int32_t indexOf( T_String const& name ) noexcept;
int32_t indexOf( char const* name ) noexcept
{
return indexOf( T_String( name ) );
}
};
/*----------------------------------------------------------------------------*/
// Pre-computed data for a curve
struct T_SyncCurveCache
{
using T_SegRef = std::pair< uint32_t , uint32_t >;
uint32_t curve;
T_Array< T_SegRef > segRefs;
T_Array< float > segStarts;
T_Array< float > segEnds;
uint32_t curPos;
T_SyncCurveCache(
T_SyncTime const& time ,
T_SyncCurves const& curves ,
const uint32_t curve ) noexcept;
// Find the index of the segment for the specified time
uint32_t findSegment(
const float time ) const noexcept;
// Compute the value of the curve at the specified location, ignoring
// curPos.
float valueAt(
T_SyncTime const& time ,
T_SyncCurves const& curves ,
const float position ) const noexcept;
// Compute the value of the curve at the current time, using and
// updating curPos as necessary.
float value(
T_SyncTime const& time ,
T_SyncCurves const& curves ) noexcept;
float segmentValue(
float time ,
uint32_t segIndex ,
T_Array< T_SyncSegment > const& segments ) const noexcept;
};
using P_SyncCurveCache = T_OwnPtr< T_SyncCurveCache >;
/*============================================================================*/
// Synchronization values. The values vector always contains an extra entry
// used for missing inputs.
struct T_SyncValues
{
T_HashIndex index;
T_Array< T_String > identifiers;
T_Array< float > values;
T_Array< bool > overriden;
T_SyncValues( );
void clear( );
// Returns true on success, false on duplicate
bool addValue(
T_String const& name ,
const float initial = 0.f ) noexcept;
bool addValue(
char const* name ,
const float initial = 0.f ) noexcept
{
return addValue( T_String( name ) , initial );
}
// If the name isn't found, the last entry of values[] is returned
uint32_t indexOf(
T_String const& name ) const noexcept;
};
/*============================================================================*/
// Synchronisation manager; handles all the synchronization data and makes it
// work together.
struct T_SyncManager
{
// ---------------------------------------------------------------------
// Duration & time controls
void setDuration(
const float uDuration ,
const uint32_t iDuration );
float duration( ) const noexcept
{ return time_.duration( ); }
void setTime( const float time );
void timeDelta( const float delta )
{ setTime( time_.time + delta ); }
float time( ) const noexcept
{ return time_.time; }
bool finished( ) const noexcept
{ return time_.time >= time_.duration( ); }
// ---------------------------------------------------------------------
// Value access
void clearInputs( )
{ values_.clear( ); }
bool addInput( T_String const& name ,
const float initial = 0.f ) noexcept
{ return values_.addValue( name , initial ); }
uint32_t inputPos( T_String const& name ) const noexcept
{ return values_.indexOf( name ); }
T_Array< float > const& inputs( ) const noexcept
{ return values_.values; }
// ---------------------------------------------------------------------
// Curves
void checkCurveFile( );
void clearCurves( );
void setCurve( T_SyncCurve curve );
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
public:
void updateCurveCaches( );
void updateValues( );
private:
P_WatchedFiles watcher_;
T_SyncTime time_;
T_SyncValues values_;
T_SyncCurves curves_;
T_Array< 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( std::string const& identifier ,
const float min ,
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(
T_SyncUISections& sections ,
const bool topLevel = false );
void displayOvControls(
T_SyncUIOverrides& overrides );
};
#endif