2017-10-07 16:56:20 +02:00
|
|
|
#pragma once
|
2017-10-31 14:21:42 +01:00
|
|
|
#include "filewatcher.hh"
|
|
|
|
#include "utilities.hh"
|
2017-11-16 12:20:21 +01:00
|
|
|
#include "imgui_internal.h"
|
2017-10-07 16:56:20 +02:00
|
|
|
|
2017-11-05 21:06:38 +01:00
|
|
|
#include <ebcl/SRDParserConfig.hh>
|
2017-11-16 09:55:56 +01:00
|
|
|
#include <ebcl/Sets.hh>
|
2017-11-05 21:06:38 +01:00
|
|
|
|
|
|
|
|
2017-10-30 10:20:09 +01:00
|
|
|
// Duration and current playing time
|
|
|
|
struct T_SyncTime
|
2017-10-07 16:56:20 +02:00
|
|
|
{
|
2017-10-30 18:29:52 +01:00
|
|
|
float uDuration = 1.f / 60.f; // Duration - unit size
|
|
|
|
uint32_t iDuration = 3600; // Duration - total units
|
2017-10-30 10:20:09 +01:00
|
|
|
float time = 0;
|
2017-10-17 11:30:44 +02:00
|
|
|
|
2017-10-30 10:20:09 +01:00
|
|
|
void setDuration(
|
2017-11-03 09:08:19 +01:00
|
|
|
const float uDuration ,
|
|
|
|
const uint32_t iDuration );
|
2017-10-17 11:30:44 +02:00
|
|
|
|
2017-10-30 10:20:09 +01:00
|
|
|
float duration( ) const noexcept
|
|
|
|
{ return uDuration * iDuration; }
|
2017-10-17 11:30:44 +02:00
|
|
|
|
2017-11-03 09:08:19 +01:00
|
|
|
void setTime( const float t ) noexcept
|
2017-10-30 10:20:09 +01:00
|
|
|
{ time = std::max( 0.f , std::min( t , duration( ) ) ); }
|
2017-10-07 16:56:20 +02:00
|
|
|
};
|
|
|
|
|
2017-10-17 11:30:44 +02:00
|
|
|
/*============================================================================*/
|
|
|
|
|
|
|
|
// Segment of an input's curve
|
2017-10-07 16:56:20 +02:00
|
|
|
struct T_SyncSegment
|
|
|
|
{
|
2017-10-17 11:30:44 +02:00
|
|
|
enum E_SegmentType
|
|
|
|
{
|
|
|
|
LINEAR ,
|
|
|
|
RAMP ,
|
|
|
|
SMOOTH ,
|
|
|
|
//HERMITE
|
|
|
|
};
|
|
|
|
|
|
|
|
E_SegmentType type;
|
2017-11-05 21:06:38 +01:00
|
|
|
T_Array< float > values;
|
|
|
|
T_Array< uint32_t > durations; // n(values) - 1 items
|
2017-10-07 16:56:20 +02:00
|
|
|
};
|
|
|
|
|
2017-10-17 11:30:44 +02:00
|
|
|
// An input curve
|
|
|
|
struct T_SyncCurve
|
|
|
|
{
|
2017-11-03 09:08:19 +01:00
|
|
|
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( ) )
|
|
|
|
{ }
|
2017-10-17 11:30:44 +02:00
|
|
|
};
|
|
|
|
|
2017-10-30 10:20:09 +01:00
|
|
|
// 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
|
|
|
|
{
|
|
|
|
|
2017-11-03 09:08:19 +01:00
|
|
|
T_ObjectTable< T_String , T_SyncCurve > curves;
|
|
|
|
|
|
|
|
T_SyncCurves( )
|
|
|
|
: curves( []( T_SyncCurve const& c ) -> T_String { return c.name; } )
|
|
|
|
{ }
|
2017-10-30 10:20:09 +01:00
|
|
|
|
|
|
|
void clear( );
|
2017-11-03 09:08:19 +01:00
|
|
|
void setCurve( T_SyncCurve curve );
|
2017-10-30 10:20:09 +01:00
|
|
|
|
|
|
|
// Returns -1 on lookup failure
|
2017-11-03 09:08:19 +01:00
|
|
|
int32_t indexOf( T_String const& name ) noexcept;
|
|
|
|
int32_t indexOf( char const* name ) noexcept
|
|
|
|
{
|
|
|
|
return indexOf( T_String( name ) );
|
|
|
|
}
|
2017-10-30 10:20:09 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
2017-10-17 11:30:44 +02:00
|
|
|
// Pre-computed data for a curve
|
|
|
|
struct T_SyncCurveCache
|
|
|
|
{
|
|
|
|
using T_SegRef = std::pair< uint32_t , uint32_t >;
|
2017-10-07 16:56:20 +02:00
|
|
|
|
2017-10-30 10:20:09 +01:00
|
|
|
uint32_t curve;
|
2017-11-03 09:08:19 +01:00
|
|
|
T_Array< T_SegRef > segRefs;
|
|
|
|
T_Array< float > segStarts;
|
|
|
|
T_Array< float > segEnds;
|
2017-10-23 11:03:38 +02:00
|
|
|
uint32_t curPos;
|
2017-10-07 16:56:20 +02:00
|
|
|
|
2017-10-17 11:30:44 +02:00
|
|
|
T_SyncCurveCache(
|
2017-11-03 09:08:19 +01:00
|
|
|
T_SyncTime const& time ,
|
|
|
|
T_SyncCurves const& curves ,
|
|
|
|
const uint32_t curve ) noexcept;
|
2017-10-30 10:20:09 +01:00
|
|
|
|
|
|
|
// Find the index of the segment for the specified time
|
|
|
|
uint32_t findSegment(
|
2017-11-03 09:08:19 +01:00
|
|
|
const float time ) const noexcept;
|
2017-10-17 11:30:44 +02:00
|
|
|
|
2017-10-30 10:20:09 +01:00
|
|
|
// Compute the value of the curve at the specified location, ignoring
|
|
|
|
// curPos.
|
2017-10-17 11:30:44 +02:00
|
|
|
float valueAt(
|
2017-11-03 09:08:19 +01:00
|
|
|
T_SyncTime const& time ,
|
|
|
|
T_SyncCurves const& curves ,
|
|
|
|
const float position ) const noexcept;
|
2017-10-30 10:20:09 +01:00
|
|
|
|
|
|
|
// Compute the value of the curve at the current time, using and
|
|
|
|
// updating curPos as necessary.
|
|
|
|
float value(
|
2017-11-03 09:08:19 +01:00
|
|
|
T_SyncTime const& time ,
|
|
|
|
T_SyncCurves const& curves ) noexcept;
|
2017-10-30 10:20:09 +01:00
|
|
|
|
|
|
|
float segmentValue(
|
2017-11-03 09:08:19 +01:00
|
|
|
float time ,
|
|
|
|
uint32_t segIndex ,
|
|
|
|
T_Array< T_SyncSegment > const& segments ) const noexcept;
|
2017-10-17 11:30:44 +02:00
|
|
|
};
|
2017-11-03 09:08:19 +01:00
|
|
|
using P_SyncCurveCache = T_OwnPtr< T_SyncCurveCache >;
|
2017-10-17 11:30:44 +02:00
|
|
|
|
|
|
|
/*============================================================================*/
|
|
|
|
|
2017-10-30 10:20:09 +01:00
|
|
|
// Synchronization values. The values vector always contains an extra entry
|
|
|
|
// used for missing inputs.
|
|
|
|
struct T_SyncValues
|
|
|
|
{
|
2017-11-03 09:08:19 +01:00
|
|
|
T_HashIndex index;
|
|
|
|
T_Array< T_String > identifiers;
|
|
|
|
T_Array< float > values;
|
|
|
|
T_Array< bool > overriden;
|
2017-10-30 10:20:09 +01:00
|
|
|
|
|
|
|
T_SyncValues( );
|
|
|
|
void clear( );
|
|
|
|
|
|
|
|
// Returns true on success, false on duplicate
|
|
|
|
bool addValue(
|
2017-11-03 09:08:19 +01:00
|
|
|
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 );
|
|
|
|
}
|
2017-10-30 10:20:09 +01:00
|
|
|
|
|
|
|
// If the name isn't found, the last entry of values[] is returned
|
|
|
|
uint32_t indexOf(
|
2017-11-03 09:08:19 +01:00
|
|
|
T_String const& name ) const noexcept;
|
2017-10-30 10:20:09 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/*============================================================================*/
|
|
|
|
|
2017-11-16 09:55:56 +01:00
|
|
|
class A_SyncOverride;
|
|
|
|
using P_SyncOverride = T_OwnPtr< A_SyncOverride >;
|
|
|
|
|
|
|
|
struct T_SyncOverrideSection;
|
|
|
|
using P_SyncOverrideSection = T_OwnPtr< T_SyncOverrideSection >;
|
|
|
|
|
|
|
|
// Base class for overrides
|
|
|
|
class A_SyncOverride
|
|
|
|
{
|
|
|
|
private:
|
2017-11-16 12:20:21 +01:00
|
|
|
const T_String type_;
|
|
|
|
bool enabled_{ false };
|
2017-11-17 20:33:56 +01:00
|
|
|
ebcl::T_SRDLocation location_;
|
2017-11-16 09:55:56 +01:00
|
|
|
|
|
|
|
protected:
|
2017-11-16 12:20:21 +01:00
|
|
|
ebcl::T_Buffer< char > title_;
|
2017-11-16 09:55:56 +01:00
|
|
|
ebcl::T_Set< T_String > inputs_{
|
|
|
|
ebcl::UseTag< ebcl::ArrayBacked< 8 > >( ) };
|
|
|
|
T_AutoArray< uint32_t , 8 > inputPos_;
|
|
|
|
|
2017-11-16 23:15:44 +01:00
|
|
|
A_SyncOverride( char const* type ,
|
2017-11-16 12:20:21 +01:00
|
|
|
T_String const& title ) noexcept;
|
|
|
|
|
|
|
|
// Draw the UI for that specific override.
|
|
|
|
virtual void makeEditWidgets( ) noexcept = 0;
|
2017-11-16 09:55:56 +01:00
|
|
|
|
|
|
|
public:
|
2017-11-16 12:20:21 +01:00
|
|
|
A_SyncOverride( ) = delete;
|
2017-11-16 09:55:56 +01:00
|
|
|
virtual ~A_SyncOverride( ) = 0;
|
|
|
|
|
|
|
|
T_String const& type( ) const noexcept
|
|
|
|
{ return type_; }
|
|
|
|
|
|
|
|
ebcl::T_Set< T_String > const& inputNames( ) const noexcept
|
|
|
|
{ return inputs_; }
|
|
|
|
|
|
|
|
bool enabled( ) const noexcept
|
|
|
|
{ return enabled_; }
|
|
|
|
|
2017-11-17 20:33:56 +01:00
|
|
|
ebcl::T_SRDLocation& location( ) noexcept
|
|
|
|
{ return location_; }
|
|
|
|
ebcl::T_SRDLocation const& location( ) const noexcept
|
|
|
|
{ return location_; }
|
|
|
|
|
2017-11-16 09:55:56 +01:00
|
|
|
// Connect the required inputs to the sync manager. Called once
|
|
|
|
// the inputs have been added.
|
|
|
|
virtual void setup( ) noexcept;
|
|
|
|
|
2017-11-16 12:20:21 +01:00
|
|
|
// Draw the title, enable button and editor.
|
|
|
|
virtual void makeUI( ) noexcept;
|
2017-11-16 09:55:56 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
// Overrides section
|
|
|
|
struct T_SyncOverrideSection
|
|
|
|
{
|
2017-11-16 12:20:21 +01:00
|
|
|
const T_String title;
|
|
|
|
const ebcl::T_Buffer< char > cTitle;
|
2017-11-16 09:55:56 +01:00
|
|
|
bool open{ false };
|
|
|
|
T_Array< P_SyncOverrideSection > subsections;
|
|
|
|
T_Array< P_SyncOverride > overrides;
|
|
|
|
|
|
|
|
T_SyncOverrideSection( ) = delete;
|
|
|
|
NO_COPY( T_SyncOverrideSection );
|
2017-11-16 12:20:21 +01:00
|
|
|
NO_MOVE( T_SyncOverrideSection );
|
2017-11-16 09:55:56 +01:00
|
|
|
|
|
|
|
explicit T_SyncOverrideSection( T_String title ) noexcept;
|
|
|
|
|
|
|
|
void merge( T_SyncOverrideSection& other ) noexcept;
|
|
|
|
void makeUI( bool topLevel ) noexcept;
|
|
|
|
|
|
|
|
T_SyncOverrideSection& section(
|
|
|
|
T_String const& name ) noexcept;
|
|
|
|
T_SyncOverrideSection const* section(
|
|
|
|
T_String const& name ) const noexcept;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*============================================================================*/
|
|
|
|
|
2017-10-30 10:20:09 +01:00
|
|
|
// Synchronisation manager; handles all the synchronization data and makes it
|
|
|
|
// work together.
|
|
|
|
struct T_SyncManager
|
|
|
|
{
|
2017-11-05 21:06:38 +01:00
|
|
|
T_SyncManager( );
|
|
|
|
|
2017-10-30 10:20:09 +01:00
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
// Duration & time controls
|
|
|
|
|
|
|
|
void setDuration(
|
2017-11-03 09:08:19 +01:00
|
|
|
const float uDuration ,
|
|
|
|
const uint32_t iDuration );
|
2017-10-30 10:20:09 +01:00
|
|
|
float duration( ) const noexcept
|
|
|
|
{ return time_.duration( ); }
|
|
|
|
|
2017-11-03 09:08:19 +01:00
|
|
|
void setTime( const float time );
|
|
|
|
void timeDelta( const float delta )
|
2017-10-30 10:20:09 +01:00
|
|
|
{ setTime( time_.time + delta ); }
|
|
|
|
float time( ) const noexcept
|
|
|
|
{ return time_.time; }
|
|
|
|
|
|
|
|
bool finished( ) const noexcept
|
|
|
|
{ return time_.time >= time_.duration( ); }
|
|
|
|
|
2017-10-30 18:29:52 +01:00
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
// Value access
|
|
|
|
|
2017-10-30 19:04:10 +01:00
|
|
|
void clearInputs( )
|
|
|
|
{ values_.clear( ); }
|
2017-11-04 09:17:31 +01:00
|
|
|
bool addInput( T_String const& name ,
|
2017-11-03 09:08:19 +01:00
|
|
|
const float initial = 0.f ) noexcept
|
2017-11-04 09:17:31 +01:00
|
|
|
{ return values_.addValue( name , initial ); }
|
2017-10-30 19:04:10 +01:00
|
|
|
|
2017-11-03 09:08:19 +01:00
|
|
|
uint32_t inputPos( T_String const& name ) const noexcept
|
2017-10-30 18:29:52 +01:00
|
|
|
{ return values_.indexOf( name ); }
|
2017-11-03 09:08:19 +01:00
|
|
|
T_Array< float > const& inputs( ) const noexcept
|
2017-10-30 18:29:52 +01:00
|
|
|
{ return values_.values; }
|
2017-11-16 23:15:44 +01:00
|
|
|
T_Array< float >& inputs( ) noexcept
|
|
|
|
{ return values_.values; }
|
2017-10-30 18:29:52 +01:00
|
|
|
|
2017-10-30 22:32:28 +01:00
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
// Curves
|
|
|
|
|
2017-10-31 14:21:42 +01:00
|
|
|
void checkCurveFile( );
|
2017-10-30 22:32:28 +01:00
|
|
|
void clearCurves( );
|
2017-11-03 09:08:19 +01:00
|
|
|
void setCurve( T_SyncCurve curve );
|
2017-10-30 22:32:28 +01:00
|
|
|
|
2017-10-31 14:21:42 +01:00
|
|
|
private:
|
|
|
|
void curvesChanged_( );
|
2017-11-03 09:08:19 +01:00
|
|
|
bool loadCurves_( bool& missing );
|
2017-10-31 14:21:42 +01:00
|
|
|
|
2017-10-30 10:20:09 +01:00
|
|
|
// ---------------------------------------------------------------------
|
2017-11-16 09:55:56 +01:00
|
|
|
// Overrides
|
2017-10-30 10:20:09 +01:00
|
|
|
|
2017-10-31 14:21:42 +01:00
|
|
|
public:
|
2017-11-16 12:20:21 +01:00
|
|
|
void registerOverrideRule( ebcl::T_SRDInputRule rule );
|
|
|
|
void mergeOverrides( T_SyncOverrideSection& overrides );
|
|
|
|
void makeOverridesWindow( );
|
2017-11-16 09:55:56 +01:00
|
|
|
|
2017-11-16 23:15:44 +01:00
|
|
|
// Mark a bunch of inputs as overridden / not overridden
|
|
|
|
void setOverridesActive( bool active ,
|
|
|
|
uint32_t n ,
|
|
|
|
uint32_t const* pos );
|
|
|
|
|
2017-11-16 09:55:56 +01:00
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
// Update
|
|
|
|
|
2017-10-30 10:20:09 +01:00
|
|
|
void updateCurveCaches( );
|
|
|
|
void updateValues( );
|
|
|
|
|
|
|
|
private:
|
2017-11-16 09:55:56 +01:00
|
|
|
ebcl::T_SRDParserConfig pConfig_; // Parser config for curves
|
|
|
|
P_WatchedFiles watcher_; // Curves file watcher
|
|
|
|
T_SyncTime time_; // Duration/time information
|
|
|
|
T_SyncValues values_; // Value storage
|
|
|
|
T_SyncCurves curves_; // Curves storage
|
|
|
|
T_Array< P_SyncCurveCache > curveCaches_; // Cache for curve segments
|
|
|
|
ebcl::T_SRDParserDefs pdOverrides_; // Parser definitions for UI overrides
|
|
|
|
ebcl::OP_SRDParserConfig pcOverrides_; // Parser configuration for UI overrides
|
2017-11-16 12:20:21 +01:00
|
|
|
T_SyncOverrideSection soRoot_; // Root for overrides
|
2017-10-30 10:20:09 +01:00
|
|
|
};
|