From 82100cecc4b2a845adb40f83a0220ec7e9803fea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Wed, 29 Nov 2017 10:23:24 +0100 Subject: [PATCH] Sequencer - Segment management for overrides --- 3rdparty/ebcl | 2 +- c-syncedit.cc | 79 ++++++++++++++++++++++++++++----- c-syncedit.hh | 8 +++- ui-sequencer.cc | 114 ++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 167 insertions(+), 36 deletions(-) diff --git a/3rdparty/ebcl b/3rdparty/ebcl index 5db2619..86a3fe3 160000 --- a/3rdparty/ebcl +++ b/3rdparty/ebcl @@ -1 +1 @@ -Subproject commit 5db261909a4883faf80a89a3211a11c9c5dfd7f0 +Subproject commit 86a3fe34b4d0361ff1deb307f211d7bbdb1f14fa diff --git a/c-syncedit.cc b/c-syncedit.cc index 063570d..3b80fbd 100644 --- a/c-syncedit.cc +++ b/c-syncedit.cc @@ -301,26 +301,43 @@ void SyncEditor::AppendSegment( /*----------------------------------------------------------------------------*/ void SyncEditor::DeleteSegment( - T_String const& id , + T_SyncTrackId const& id , const uint32_t segmentIndex ) noexcept { auto& sync{ Common::Sync( ) }; - auto const* const curve{ sync.getCurve( id ) }; - if ( !curve || segmentIndex >= curve->segments.size( ) ) { + auto const* const ovr{ id.isOverride ? sync.getOverride( id.id ) : nullptr }; + if ( id.isOverride && !ovr ) { return; } + const auto nc{ ovr ? ovr->inputNames( ).size( ) : 1 }; + T_SyncCurve const* curves[ nc ]; + if ( ovr ) { + for ( auto i = 0u ; i < nc ; i ++ ) { + curves[ i ] = sync.getCurve( ovr->inputNames( )[ i ] ); + } + } else { + curves[ 0 ] = sync.getCurve( id.id ); + } + for ( auto i = 0u ; i < nc ; i ++ ) { + if ( !curves[ i ] || segmentIndex >= curves[ i ]->segments.size( ) ) { + return; + } + } + auto& undo{ dynamic_cast< T_UndoSyncChanges& >( Common::Undo( ).add< T_UndoSyncChanges >( ) ) }; - if ( curve->segments.size( ) == 1 ) { - undo.curveDeletion( *curve ); - sync.removeCurve( id ); - } else { - auto nCurve{ *curve }; - nCurve.segments.remove( segmentIndex ); - undo.curveReplacement( *curve , nCurve ); - sync.setCurve( std::move( nCurve ) ); + for ( auto i = 0u ; i < nc ; i ++ ) { + if ( curves[ i ]->segments.size( ) == 1 ) { + undo.curveDeletion( *curves[ i ] ); + sync.removeCurve( curves[ i ]->name ); + } else { + auto nCurve{ *curves[ i ] }; + nCurve.segments.remove( segmentIndex ); + undo.curveReplacement( *curves[ i ] , nCurve ); + sync.setCurve( std::move( nCurve ) ); + } } } @@ -352,6 +369,46 @@ void SyncEditor::SetSegmentType( /*----------------------------------------------------------------------------*/ +void SyncEditor::SetSegmentTypes( + A_SyncOverride const& ovr , + const uint32_t segmentIndex , + const T_SyncSegment::E_SegmentType newType ) noexcept +{ + auto& sync{ Common::Sync( ) }; + auto const& iNames{ ovr.inputNames( ) }; + const auto nc{ iNames.size( ) }; + { + auto nSame{ 0u }; + for ( auto i = 0u ; i < nc ; i ++ ) { + auto const* const c{ sync.getCurve( iNames[ i ] ) }; + assert( c ); + assert( segmentIndex < c->segments.size( ) ); + T_SyncSegment const& iSegment{ c->segments[ segmentIndex ] }; + if ( iSegment.type == newType ) { + nSame ++; + } + } + if ( nSame == nc ) { + return; + } + } + + auto& undo{ dynamic_cast< T_UndoSyncChanges& >( + Common::Undo( ).add< T_UndoSyncChanges >( ) ) }; + for ( auto i = 0u ; i < nc ; i ++ ) { + auto const* const c{ sync.getCurve( iNames[ i ] ) }; + if ( c->segments[ segmentIndex ].type == newType ) { + continue; + } + T_SyncCurve copy{ *c }; + copy.segments[ segmentIndex ].type = newType; + undo.curveReplacement( *c , copy ); + sync.setCurve( std::move( copy ) ); + } +} + +/*----------------------------------------------------------------------------*/ + void SyncEditor::InsertPoint( T_String const& id , const uint32_t segmentIndex , diff --git a/c-syncedit.hh b/c-syncedit.hh index b8bf235..9e6427c 100644 --- a/c-syncedit.hh +++ b/c-syncedit.hh @@ -134,7 +134,7 @@ struct SyncEditor final // Delete a segment from a curve. static void DeleteSegment( - T_String const& id , + T_SyncTrackId const& id , uint32_t segmentIndex ) noexcept; // Change the type of a segment in a curve. @@ -143,6 +143,12 @@ struct SyncEditor final uint32_t segmentIndex , T_SyncSegment::E_SegmentType newType ) noexcept; + // Change the type of a segment for all inputs covered by an override. + static void SetSegmentTypes( + A_SyncOverride const& ovr , + uint32_t segmentIndex , + T_SyncSegment::E_SegmentType newType ) noexcept; + //---------------------------------------------------------------------- // Insert a point in a segment. The pointIndex parameter indicates the diff --git a/ui-sequencer.cc b/ui-sequencer.cc index 11e191f..e5ee7be 100644 --- a/ui-sequencer.cc +++ b/ui-sequencer.cc @@ -1128,6 +1128,28 @@ void T_SyncViewImpl_::displayTooltips( << '\n'; if ( mp.type == E_MousePosType::TRACK ) { stringBuffer << "No segment"; + } else if ( ovr ) { + if ( mp.type == E_MousePosType::SEGMENT ) { + int cType{ -1 }; + for ( auto i = 0u ; i < ovr->inputNames( ).size( ) ; i ++ ) { + auto const& iName{ ovr->inputNames( )[ i ] }; + auto const* const c{ sync.getCurve( iName ) }; + if ( i == 0 ) { + cType = c->segments[ seg->seg ].type; + } else if ( cType != c->segments[ seg->seg ].type ) { + cType = -1; + } + } + if ( cType == -1 ) { + stringBuffer << "Various segment types"; + } else { + stringBuffer << "Segment type: " + << T_SyncSegment::E_SegmentType( cType ); + } + } else { + stringBuffer << "Point index " << point->index; + } + } else { auto const& s{ curve->segments[ seg->seg ] }; if ( mp.type == E_MousePosType::SEGMENT ) { @@ -1138,7 +1160,7 @@ void T_SyncViewImpl_::displayTooltips( } stringBuffer << "\nTime: " << buffer << '\n'; if ( track.id.isOverride ) { - stringBuffer << "Input values:"; + stringBuffer << "\nInput values:"; for ( auto i = 0u ; i < ovr->inputNames( ).size( ) ; i ++ ) { auto const& iName{ ovr->inputNames( )[ i ] }; auto const* const c{ sync.getCurve( iName ) }; @@ -1686,28 +1708,71 @@ void T_SyncViewImpl_::displaySegmentWindow( ) noexcept SameLine( 110 ); Text( "%.3f seconds" , tDuration ); - 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( ) << "various types" << '\0'; + const auto ts{ stringBuffer.size( ) }; + for ( auto t : types ) { + stringBuffer << t << '\0'; + } + stringBuffer << '\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'; + // Display segment type selectors + auto const nc{ ovr ? ovr->inputNames( ).size( ) : 1u }; + int change; + int sTypes[ nc + 1 ]; + Separator( ); + if ( !ovr ) { Text( "Type:" ); SameLine( 110 ); PushItemWidth( -1 ); - tp = int( segment.type ); - change = Combo( "##type" , &tp , stringBuffer.data( ) ); + sTypes[ 0 ] = int( segment.type ); + change = Combo( "##type" , &sTypes[ 0 ] , stringBuffer.data( ) + ts ) ? 0 : -1; PopItemWidth( ); + } else if ( TreeNode( "Segment types" ) ) { + change = -1; + const uint32_t sblen{ stringBuffer.size( ) }; + PushItemWidth( -1 ); + int common{ -1 }; + for ( auto i = 0u ; i < nc ; i ++ ) { + auto const& iName{ ovr->inputNames( )[ i ] }; + sTypes[ i ] = int( sync.getCurve( iName )->segments[ sid ].type ); + if ( i == 0 ) { + common = sTypes[ i ]; + } else if ( common != sTypes[ i ] ) { + common = -1; + } + + stringBuffer << iName << '\0'; + Text( "%s" , stringBuffer.data( ) + sblen ); + SameLine( 200 ); + + stringBuffer.truncate( sblen ) << "##type" << i << '\0'; + if ( Combo( stringBuffer.data( ) + sblen , &sTypes[ i ] , + stringBuffer.data( ) + ts ) ) { + change = i; + } + stringBuffer.truncate( sblen ); + } + Separator( ); + + const auto cOffset{ common == -1 ? 0 : ts }; + if ( common == -1 ) { + common ++; + } + Text( "All inputs" ); + SameLine( 200 ); + if ( Combo( "##type-all" , &common , stringBuffer.data( ) + cOffset ) ) { + sTypes[ nc ] = common - ( cOffset == 0 ? 1 : 0 ); + change = nc; + } + + PopItemWidth( ); + TreePop( ); } else { - change = false; + change = -1; } Separator( ); @@ -1743,14 +1808,17 @@ void T_SyncViewImpl_::displaySegmentWindow( ) noexcept } else { selSegment = decltype( selSegment ){}; } - SyncEditor::DeleteSegment( selId->id , sid ); -#warning blah + SyncEditor::DeleteSegment( *selId , sid ); } - if ( change ) { - SyncEditor::SetSegmentType( *curve , sid , - T_SyncSegment::E_SegmentType( tp ) ); -#warning blah + if ( change >= 0 && change < int32_t( nc ) ) { + SyncEditor::SetSegmentType( + *( ovr ? sync.getCurve( ovr->inputNames( )[ change ] ) : curve ) , + sid , T_SyncSegment::E_SegmentType( sTypes[ change ] ) ); + } else if ( change == int32_t( nc ) && sTypes[ nc ] != -1 ) { + assert( ovr ); + SyncEditor::SetSegmentTypes( *ovr , sid , + T_SyncSegment::E_SegmentType( sTypes[ nc ] ) ); } End( );