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