Sequencer - Work in progress on override support
This commit is contained in:
parent
9f44f119dd
commit
05c9580e71
1 changed files with 136 additions and 66 deletions
202
ui-sequencer.cc
202
ui-sequencer.cc
|
@ -264,7 +264,7 @@ struct T_SyncViewImpl_
|
||||||
float& hue ,
|
float& hue ,
|
||||||
ImRect const& bb ,
|
ImRect const& bb ,
|
||||||
ImRect const& container ,
|
ImRect const& container ,
|
||||||
T_String const& name ,
|
T_SyncTrackId_ const& id ,
|
||||||
T_SyncCurve const* curve ) noexcept;
|
T_SyncCurve const* curve ) noexcept;
|
||||||
|
|
||||||
void displayTooltips(
|
void displayTooltips(
|
||||||
|
@ -492,18 +492,21 @@ void T_SyncViewImpl_::checkSelection( ) noexcept
|
||||||
if ( !selId ) {
|
if ( !selId ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert( !selId->isOverride ); // XXX
|
auto& sync{ Common::Sync( ) };
|
||||||
auto const* const curve{ Common::Sync( ).getCurve( selId->id ) };
|
auto const* const curve{ sync.getCurve(
|
||||||
|
selId->isOverride
|
||||||
|
? sync.getOverride( selId->id )->inputNames( )[ 0 ]
|
||||||
|
: selId->id ) };
|
||||||
|
|
||||||
// Missing curve
|
// Missing curve
|
||||||
if ( !curve ) {
|
if ( !( curve || selId->isOverride ) ) {
|
||||||
// Remove segment/point selection
|
// Remove segment/point selection
|
||||||
if ( selSegment ) {
|
if ( selSegment ) {
|
||||||
selSegment.clear( );
|
selSegment.clear( );
|
||||||
selPoint.clear( );
|
selPoint.clear( );
|
||||||
}
|
}
|
||||||
// If there's no matching input, unselect the track
|
// If there's no matching input, unselect the track
|
||||||
if ( !Common::Sync( ).hasInput( selId->id ) ) {
|
if ( !sync.hasInput( selId->id ) ) {
|
||||||
selId.clear( );
|
selId.clear( );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -534,7 +537,7 @@ void T_SyncViewImpl_::checkSelection( ) noexcept
|
||||||
void T_SyncViewImpl_::displayToolbar( ) noexcept
|
void T_SyncViewImpl_::displayToolbar( ) noexcept
|
||||||
{
|
{
|
||||||
using namespace ImGui;
|
using namespace ImGui;
|
||||||
auto& sync( Common::Sync( ) );
|
auto& sync{ Common::Sync( ) };
|
||||||
|
|
||||||
if ( sync.playing( ) ) {
|
if ( sync.playing( ) ) {
|
||||||
UI::Main( ).actionButton( "Stop" );
|
UI::Main( ).actionButton( "Stop" );
|
||||||
|
@ -914,6 +917,7 @@ void T_SyncViewImpl_::sequencerBody(
|
||||||
0xffffffff );
|
0xffffffff );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void T_SyncViewImpl_::sequencerTracks(
|
void T_SyncViewImpl_::sequencerTracks(
|
||||||
ImRect& subBb ,
|
ImRect& subBb ,
|
||||||
ImRect const& container ) noexcept
|
ImRect const& container ) noexcept
|
||||||
|
@ -923,13 +927,12 @@ void T_SyncViewImpl_::sequencerTracks(
|
||||||
|
|
||||||
const auto nc{ sTracks.size( ) };
|
const auto nc{ sTracks.size( ) };
|
||||||
for ( auto i = 0u ; i < nc ; i ++ ) {
|
for ( auto i = 0u ; i < nc ; i ++ ) {
|
||||||
if ( sTracks[ i ].isOverride ) {
|
auto const& id{ sTracks[ i ] };
|
||||||
continue;
|
auto* const curve{ sync.getCurve(
|
||||||
}
|
sTracks[ i ].isOverride
|
||||||
|
? sync.getOverride( id.id )->inputNames( )[ 0 ]
|
||||||
auto const& name{ sTracks[ i ].id };
|
: id.id ) };
|
||||||
auto* const curve{ sync.getCurve( name ) };
|
sequencerTrack( hue , subBb , container , id , curve );
|
||||||
sequencerTrack( hue , subBb , container , name , curve );
|
|
||||||
subBb.Min.y += TrackHeight + 2 * TrackPadding;
|
subBb.Min.y += TrackHeight + 2 * TrackPadding;
|
||||||
subBb.Max.y += TrackHeight + 2 * TrackPadding;
|
subBb.Max.y += TrackHeight + 2 * TrackPadding;
|
||||||
hue = fmodf( hue + .17f , 1.f );
|
hue = fmodf( hue + .17f , 1.f );
|
||||||
|
@ -940,7 +943,7 @@ void T_SyncViewImpl_::sequencerTrack(
|
||||||
float& hue ,
|
float& hue ,
|
||||||
ImRect const& bb ,
|
ImRect const& bb ,
|
||||||
ImRect const& container ,
|
ImRect const& container ,
|
||||||
T_String const& id ,
|
T_SyncTrackId_ const& id ,
|
||||||
T_SyncCurve const* curve ) noexcept
|
T_SyncCurve const* curve ) noexcept
|
||||||
{
|
{
|
||||||
// Don't display if the track is fully hidden
|
// Don't display if the track is fully hidden
|
||||||
|
@ -951,14 +954,14 @@ void T_SyncViewImpl_::sequencerTrack(
|
||||||
// Add track display record
|
// Add track display record
|
||||||
const auto dTrackIdx{ dspTracks.size( ) };
|
const auto dTrackIdx{ dspTracks.size( ) };
|
||||||
auto& dTrack{ dspTracks.addNew( ) };
|
auto& dTrack{ dspTracks.addNew( ) };
|
||||||
dTrack.id = T_SyncTrackId_{ id , false };
|
dTrack.id = id;
|
||||||
dTrack.dispSegs = 0;
|
dTrack.dispSegs = 0;
|
||||||
dTrack.firstSeg = dspSegments.size( );
|
dTrack.firstSeg = dspSegments.size( );
|
||||||
dTrack.area = bb;
|
dTrack.area = bb;
|
||||||
|
|
||||||
// Compute colors
|
// Compute colors
|
||||||
using namespace ImGui;
|
using namespace ImGui;
|
||||||
const bool sCurve{ selId && !selId->isOverride && selId->id == id };
|
const bool sCurve{ selId && id == *selId };
|
||||||
const float scv{ sCurve ? 1.f : .7f };
|
const float scv{ sCurve ? 1.f : .7f };
|
||||||
const auto bgColor{ ColorHSVAToU32( hue , .25f , scv , .25f ) } ,
|
const auto bgColor{ ColorHSVAToU32( hue , .25f , scv , .25f ) } ,
|
||||||
borderColor{ ColorHSVAToU32( hue , .5f , scv , 1.f ) };
|
borderColor{ ColorHSVAToU32( hue , .5f , scv , 1.f ) };
|
||||||
|
@ -1111,7 +1114,14 @@ void T_SyncViewImpl_::displayTooltips(
|
||||||
|
|
||||||
// Curve from track
|
// Curve from track
|
||||||
auto& sync{ Common::Sync( ) };
|
auto& sync{ Common::Sync( ) };
|
||||||
T_SyncCurve const* const curve{ sync.getCurve( track.id.id ) };
|
auto const* const ovr{ track.id.isOverride
|
||||||
|
? sync.getOverride( track.id.id )
|
||||||
|
: nullptr
|
||||||
|
};
|
||||||
|
auto const* const curve{ sync.getCurve(
|
||||||
|
track.id.isOverride
|
||||||
|
? ovr->inputNames( )[ 0 ]
|
||||||
|
: track.id.id ) };
|
||||||
assert( mp.type == E_MousePosType::TRACK || curve != nullptr );
|
assert( mp.type == E_MousePosType::TRACK || curve != nullptr );
|
||||||
|
|
||||||
// Time offset
|
// Time offset
|
||||||
|
@ -1135,12 +1145,11 @@ void T_SyncViewImpl_::displayTooltips(
|
||||||
char buffer[ 12 ];
|
char buffer[ 12 ];
|
||||||
TimeToString_( buffer , sizeof( buffer ) , dTime );
|
TimeToString_( buffer , sizeof( buffer ) , dTime );
|
||||||
|
|
||||||
const float value{ point
|
stringBuffer.clear( )
|
||||||
? curve->segments[ seg->seg ].values[ point->index ]
|
<< ( track.id.isOverride ? ovr->title( ) : track.id.id )
|
||||||
: ( curve ? curve->computeValue( dUTime )
|
<< ' '
|
||||||
: sync.inputs( )[ sync.inputPos( track.id.id ) ] ) };
|
<< ( track.id.isOverride ? "(override)" : "(input)" )
|
||||||
|
<< '\n';
|
||||||
stringBuffer.clear( ) << track.id.id << " (input)\n";
|
|
||||||
if ( mp.type == E_MousePosType::TRACK ) {
|
if ( mp.type == E_MousePosType::TRACK ) {
|
||||||
stringBuffer << "No segment";
|
stringBuffer << "No segment";
|
||||||
} else {
|
} else {
|
||||||
|
@ -1151,7 +1160,25 @@ void T_SyncViewImpl_::displayTooltips(
|
||||||
stringBuffer << "On " << s.type << " segment, index " << point->index;
|
stringBuffer << "On " << s.type << " segment, index " << point->index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stringBuffer << "\nTime: " << buffer << "\nValue: " << value;
|
stringBuffer << "\nTime: " << buffer << '\n';
|
||||||
|
if ( track.id.isOverride ) {
|
||||||
|
stringBuffer << "Input values:";
|
||||||
|
for ( auto i = 0u ; i < ovr->inputNames( ).size( ) ; i ++ ) {
|
||||||
|
auto const& iName{ ovr->inputNames( )[ i ] };
|
||||||
|
auto const* const c{ sync.getCurve( iName ) };
|
||||||
|
const float value{ point
|
||||||
|
? c->segments[ seg->seg ].values[ point->index ]
|
||||||
|
: ( c ? c->computeValue( dUTime )
|
||||||
|
: sync.inputs( )[ ovr->inputPositions( )[ i ] ] ) };
|
||||||
|
stringBuffer << "\n - " << iName << ": " << value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const float value{ point
|
||||||
|
? curve->segments[ seg->seg ].values[ point->index ]
|
||||||
|
: ( curve ? curve->computeValue( dUTime )
|
||||||
|
: sync.inputs( )[ sync.inputPos( track.id.id ) ] ) };
|
||||||
|
stringBuffer << "Value: " << value;
|
||||||
|
}
|
||||||
|
|
||||||
using namespace ImGui;
|
using namespace ImGui;
|
||||||
stringBuffer << '\0';
|
stringBuffer << '\0';
|
||||||
|
@ -1506,19 +1533,37 @@ void T_SyncViewImpl_::displayTrackWindow( ) noexcept
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the curve
|
// Get the curve (or the first curve from the set)
|
||||||
auto& sync{ Common::Sync( ) };
|
auto& sync{ Common::Sync( ) };
|
||||||
auto const* const curve{ sync.getCurve( selId->id ) };
|
auto const* const ovr{ selId->isOverride
|
||||||
|
? sync.getOverride( selId->id )
|
||||||
|
: nullptr };
|
||||||
|
auto const* const curve{ sync.getCurve( selId->isOverride
|
||||||
|
? ovr->inputNames( )[ 0 ]
|
||||||
|
: selId->id ) };
|
||||||
|
|
||||||
Text( "Curve:" );
|
if ( selId->isOverride ) {
|
||||||
SameLine( 110 );
|
Text( "Override:" );
|
||||||
Text( "%s" , selId->id.toOSString( ).data( ) );
|
|
||||||
if ( !sync.hasInput( selId->id ) ) {
|
|
||||||
Text( " " );
|
|
||||||
SameLine( 110 );
|
SameLine( 110 );
|
||||||
Text( "No matching input" );
|
Text( "%s" , ovr->title( ) );
|
||||||
|
|
||||||
|
for ( auto i = 0u ; i < ovr->inputNames( ).size( ) ; i ++ ) {
|
||||||
|
Text( i == 0 ? "Curve(s):" : "" );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%s" , ovr->inputNames( )[ i ].toOSString( ).data( ) );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Text( "Curve:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%s" , selId->id.toOSString( ).data( ) );
|
||||||
|
if ( !sync.hasInput( selId->id ) ) {
|
||||||
|
Text( " " );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "No matching input" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Separator( );
|
||||||
Text( "Segments:" );
|
Text( "Segments:" );
|
||||||
SameLine( 110 );
|
SameLine( 110 );
|
||||||
Text( "%d" , curve ? curve->segments.size( ) : 0 );
|
Text( "%d" , curve ? curve->segments.size( ) : 0 );
|
||||||
|
@ -1570,6 +1615,8 @@ void T_SyncViewImpl_::displayTrackWindow( ) noexcept
|
||||||
Text( " " );
|
Text( " " );
|
||||||
SameLine( 110 );
|
SameLine( 110 );
|
||||||
if ( Button( "Clear" , ImVec2{ -1 , 0 } ) ) {
|
if ( Button( "Clear" , ImVec2{ -1 , 0 } ) ) {
|
||||||
|
assert( !selId->isOverride );
|
||||||
|
#warning blah
|
||||||
SyncEditor::DeleteCurve( selId->id );
|
SyncEditor::DeleteCurve( selId->id );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1577,6 +1624,8 @@ void T_SyncViewImpl_::displayTrackWindow( ) noexcept
|
||||||
Text( " " );
|
Text( " " );
|
||||||
SameLine( 110 );
|
SameLine( 110 );
|
||||||
if ( Button( "Append segment" , ImVec2{ -1 , 0 } ) ) {
|
if ( Button( "Append segment" , ImVec2{ -1 , 0 } ) ) {
|
||||||
|
assert( !selId->isOverride );
|
||||||
|
#warning blah
|
||||||
const uint32_t ns{ std::max( 1u ,
|
const uint32_t ns{ std::max( 1u ,
|
||||||
( sync.durationUnits( ) - duration ) / 2 ) };
|
( sync.durationUnits( ) - duration ) / 2 ) };
|
||||||
SyncEditor::AppendSegment( selId->id , ns );
|
SyncEditor::AppendSegment( selId->id , ns );
|
||||||
|
@ -1603,10 +1652,20 @@ void T_SyncViewImpl_::displaySegmentWindow( ) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t sid{ *selSegment };
|
const uint32_t sid{ *selSegment };
|
||||||
|
auto& sync{ Common::Sync( ) };
|
||||||
|
auto const* const ovr{ selId->isOverride
|
||||||
|
? sync.getOverride( selId->id )
|
||||||
|
: nullptr };
|
||||||
|
|
||||||
Text( "Curve:" );
|
if ( selId->isOverride ) {
|
||||||
SameLine( 110 );
|
Text( "Override:" );
|
||||||
Text( "%s" , selId->id.toOSString( ).data( ) );
|
SameLine( 110 );
|
||||||
|
Text( "%s" , ovr->title( ) );
|
||||||
|
} else {
|
||||||
|
Text( "Curve:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%s" , selId->id.toOSString( ).data( ) );
|
||||||
|
}
|
||||||
|
|
||||||
Text( "Index:" );
|
Text( "Index:" );
|
||||||
SameLine( 110 );
|
SameLine( 110 );
|
||||||
|
@ -1615,8 +1674,9 @@ void T_SyncViewImpl_::displaySegmentWindow( ) noexcept
|
||||||
Separator( );
|
Separator( );
|
||||||
|
|
||||||
// Access curve and segment
|
// Access curve and segment
|
||||||
auto& sync{ Common::Sync( ) };
|
auto const* const curve{ sync.getCurve( selId->isOverride
|
||||||
auto const* const curve{ sync.getCurve( selId->id ) };
|
? ovr->inputNames( )[ 0 ]
|
||||||
|
: selId->id ) };
|
||||||
auto const& segment{ curve->segments[ sid ] };
|
auto const& segment{ curve->segments[ sid ] };
|
||||||
|
|
||||||
// Find start and duration
|
// Find start and duration
|
||||||
|
@ -1655,23 +1715,29 @@ void T_SyncViewImpl_::displaySegmentWindow( ) noexcept
|
||||||
SameLine( 110 );
|
SameLine( 110 );
|
||||||
Text( "%.3f seconds" , tDuration );
|
Text( "%.3f seconds" , tDuration );
|
||||||
|
|
||||||
Separator( );
|
bool change;
|
||||||
|
int tp;
|
||||||
|
if ( !ovr ) {
|
||||||
|
Separator( );
|
||||||
|
|
||||||
// Generate the combo box's data
|
// Generate the combo box's data
|
||||||
static constexpr T_SyncSegment::E_SegmentType types[] = {
|
static constexpr T_SyncSegment::E_SegmentType types[] = {
|
||||||
T_SyncSegment::LINEAR , T_SyncSegment::RAMP , T_SyncSegment::SMOOTH
|
T_SyncSegment::LINEAR , T_SyncSegment::RAMP , T_SyncSegment::SMOOTH
|
||||||
};
|
};
|
||||||
stringBuffer.clear( );
|
stringBuffer.clear( );
|
||||||
for ( auto t : types ) {
|
for ( auto t : types ) {
|
||||||
stringBuffer << t << '\0';
|
stringBuffer << t << '\0';
|
||||||
|
}
|
||||||
|
stringBuffer << '\0';
|
||||||
|
Text( "Type:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
PushItemWidth( -1 );
|
||||||
|
tp = int( segment.type );
|
||||||
|
change = Combo( "##type" , &tp , stringBuffer.data( ) );
|
||||||
|
PopItemWidth( );
|
||||||
|
} else {
|
||||||
|
change = false;
|
||||||
}
|
}
|
||||||
stringBuffer << '\0';
|
|
||||||
Text( "Type:" );
|
|
||||||
SameLine( 110 );
|
|
||||||
PushItemWidth( -1 );
|
|
||||||
int t{ int( segment.type ) };
|
|
||||||
const bool change{ Combo( "##type" , &t , stringBuffer.data( ) ) };
|
|
||||||
PopItemWidth( );
|
|
||||||
|
|
||||||
Separator( );
|
Separator( );
|
||||||
|
|
||||||
|
@ -1679,21 +1745,23 @@ void T_SyncViewImpl_::displaySegmentWindow( ) noexcept
|
||||||
SameLine( 110 );
|
SameLine( 110 );
|
||||||
Text( "%d" , segment.values.size( ) );
|
Text( "%d" , segment.values.size( ) );
|
||||||
|
|
||||||
// Find min/max
|
if ( !ovr ) {
|
||||||
float sMin{ FLT_MAX } , sMax{ -FLT_MAX };
|
// Find min/max
|
||||||
for ( auto v : segment.values ) {
|
float sMin{ FLT_MAX } , sMax{ -FLT_MAX };
|
||||||
sMin = ImMin( sMin , v );
|
for ( auto v : segment.values ) {
|
||||||
sMax = ImMax( sMax , v );
|
sMin = ImMin( sMin , v );
|
||||||
|
sMax = ImMax( sMax , v );
|
||||||
|
}
|
||||||
|
|
||||||
|
Text( "Min. value:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%f" , sMin );
|
||||||
|
|
||||||
|
Text( "Max. value:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%f" , sMax );
|
||||||
}
|
}
|
||||||
|
|
||||||
Text( "Min. value:" );
|
|
||||||
SameLine( 110 );
|
|
||||||
Text( "%f" , sMin );
|
|
||||||
|
|
||||||
Text( "Max. value:" );
|
|
||||||
SameLine( 110 );
|
|
||||||
Text( "%f" , sMax );
|
|
||||||
|
|
||||||
Separator( );
|
Separator( );
|
||||||
|
|
||||||
Text( " " );
|
Text( " " );
|
||||||
|
@ -1705,11 +1773,13 @@ void T_SyncViewImpl_::displaySegmentWindow( ) noexcept
|
||||||
selSegment = decltype( selSegment ){};
|
selSegment = decltype( selSegment ){};
|
||||||
}
|
}
|
||||||
SyncEditor::DeleteSegment( selId->id , sid );
|
SyncEditor::DeleteSegment( selId->id , sid );
|
||||||
|
#warning blah
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( change ) {
|
if ( change ) {
|
||||||
SyncEditor::SetSegmentType( *curve , sid ,
|
SyncEditor::SetSegmentType( *curve , sid ,
|
||||||
T_SyncSegment::E_SegmentType( t ) );
|
T_SyncSegment::E_SegmentType( tp ) );
|
||||||
|
#warning blah
|
||||||
}
|
}
|
||||||
|
|
||||||
End( );
|
End( );
|
||||||
|
|
Loading…
Reference in a new issue