Sequencer - Segment management for overrides
This commit is contained in:
parent
9a15267749
commit
82100cecc4
4 changed files with 167 additions and 36 deletions
2
3rdparty/ebcl
vendored
2
3rdparty/ebcl
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 5db261909a4883faf80a89a3211a11c9c5dfd7f0
|
Subproject commit 86a3fe34b4d0361ff1deb307f211d7bbdb1f14fa
|
|
@ -301,26 +301,43 @@ void SyncEditor::AppendSegment(
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SyncEditor::DeleteSegment(
|
void SyncEditor::DeleteSegment(
|
||||||
T_String const& id ,
|
T_SyncTrackId const& id ,
|
||||||
const uint32_t segmentIndex ) noexcept
|
const uint32_t segmentIndex ) noexcept
|
||||||
{
|
{
|
||||||
auto& sync{ Common::Sync( ) };
|
auto& sync{ Common::Sync( ) };
|
||||||
|
|
||||||
auto const* const curve{ sync.getCurve( id ) };
|
auto const* const ovr{ id.isOverride ? sync.getOverride( id.id ) : nullptr };
|
||||||
if ( !curve || segmentIndex >= curve->segments.size( ) ) {
|
if ( id.isOverride && !ovr ) {
|
||||||
return;
|
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& >(
|
auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
|
||||||
Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
|
Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
|
||||||
if ( curve->segments.size( ) == 1 ) {
|
for ( auto i = 0u ; i < nc ; i ++ ) {
|
||||||
undo.curveDeletion( *curve );
|
if ( curves[ i ]->segments.size( ) == 1 ) {
|
||||||
sync.removeCurve( id );
|
undo.curveDeletion( *curves[ i ] );
|
||||||
} else {
|
sync.removeCurve( curves[ i ]->name );
|
||||||
auto nCurve{ *curve };
|
} else {
|
||||||
nCurve.segments.remove( segmentIndex );
|
auto nCurve{ *curves[ i ] };
|
||||||
undo.curveReplacement( *curve , nCurve );
|
nCurve.segments.remove( segmentIndex );
|
||||||
sync.setCurve( std::move( nCurve ) );
|
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(
|
void SyncEditor::InsertPoint(
|
||||||
T_String const& id ,
|
T_String const& id ,
|
||||||
const uint32_t segmentIndex ,
|
const uint32_t segmentIndex ,
|
||||||
|
|
|
@ -134,7 +134,7 @@ struct SyncEditor final
|
||||||
|
|
||||||
// Delete a segment from a curve.
|
// Delete a segment from a curve.
|
||||||
static void DeleteSegment(
|
static void DeleteSegment(
|
||||||
T_String const& id ,
|
T_SyncTrackId const& id ,
|
||||||
uint32_t segmentIndex ) noexcept;
|
uint32_t segmentIndex ) noexcept;
|
||||||
|
|
||||||
// Change the type of a segment in a curve.
|
// Change the type of a segment in a curve.
|
||||||
|
@ -143,6 +143,12 @@ struct SyncEditor final
|
||||||
uint32_t segmentIndex ,
|
uint32_t segmentIndex ,
|
||||||
T_SyncSegment::E_SegmentType newType ) noexcept;
|
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
|
// Insert a point in a segment. The pointIndex parameter indicates the
|
||||||
|
|
114
ui-sequencer.cc
114
ui-sequencer.cc
|
@ -1128,6 +1128,28 @@ void T_SyncViewImpl_::displayTooltips(
|
||||||
<< '\n';
|
<< '\n';
|
||||||
if ( mp.type == E_MousePosType::TRACK ) {
|
if ( mp.type == E_MousePosType::TRACK ) {
|
||||||
stringBuffer << "No segment";
|
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 {
|
} else {
|
||||||
auto const& s{ curve->segments[ seg->seg ] };
|
auto const& s{ curve->segments[ seg->seg ] };
|
||||||
if ( mp.type == E_MousePosType::SEGMENT ) {
|
if ( mp.type == E_MousePosType::SEGMENT ) {
|
||||||
|
@ -1138,7 +1160,7 @@ void T_SyncViewImpl_::displayTooltips(
|
||||||
}
|
}
|
||||||
stringBuffer << "\nTime: " << buffer << '\n';
|
stringBuffer << "\nTime: " << buffer << '\n';
|
||||||
if ( track.id.isOverride ) {
|
if ( track.id.isOverride ) {
|
||||||
stringBuffer << "Input values:";
|
stringBuffer << "\nInput values:";
|
||||||
for ( auto i = 0u ; i < ovr->inputNames( ).size( ) ; i ++ ) {
|
for ( auto i = 0u ; i < ovr->inputNames( ).size( ) ; i ++ ) {
|
||||||
auto const& iName{ ovr->inputNames( )[ i ] };
|
auto const& iName{ ovr->inputNames( )[ i ] };
|
||||||
auto const* const c{ sync.getCurve( iName ) };
|
auto const* const c{ sync.getCurve( iName ) };
|
||||||
|
@ -1686,28 +1708,71 @@ void T_SyncViewImpl_::displaySegmentWindow( ) noexcept
|
||||||
SameLine( 110 );
|
SameLine( 110 );
|
||||||
Text( "%.3f seconds" , tDuration );
|
Text( "%.3f seconds" , tDuration );
|
||||||
|
|
||||||
bool change;
|
// Generate the combo box's data
|
||||||
int tp;
|
static constexpr T_SyncSegment::E_SegmentType types[] = {
|
||||||
if ( !ovr ) {
|
T_SyncSegment::LINEAR , T_SyncSegment::RAMP , T_SyncSegment::SMOOTH
|
||||||
Separator( );
|
};
|
||||||
|
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
|
// Display segment type selectors
|
||||||
static constexpr T_SyncSegment::E_SegmentType types[] = {
|
auto const nc{ ovr ? ovr->inputNames( ).size( ) : 1u };
|
||||||
T_SyncSegment::LINEAR , T_SyncSegment::RAMP , T_SyncSegment::SMOOTH
|
int change;
|
||||||
};
|
int sTypes[ nc + 1 ];
|
||||||
stringBuffer.clear( );
|
Separator( );
|
||||||
for ( auto t : types ) {
|
if ( !ovr ) {
|
||||||
stringBuffer << t << '\0';
|
|
||||||
}
|
|
||||||
stringBuffer << '\0';
|
|
||||||
Text( "Type:" );
|
Text( "Type:" );
|
||||||
SameLine( 110 );
|
SameLine( 110 );
|
||||||
PushItemWidth( -1 );
|
PushItemWidth( -1 );
|
||||||
tp = int( segment.type );
|
sTypes[ 0 ] = int( segment.type );
|
||||||
change = Combo( "##type" , &tp , stringBuffer.data( ) );
|
change = Combo( "##type" , &sTypes[ 0 ] , stringBuffer.data( ) + ts ) ? 0 : -1;
|
||||||
PopItemWidth( );
|
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 {
|
} else {
|
||||||
change = false;
|
change = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Separator( );
|
Separator( );
|
||||||
|
@ -1743,14 +1808,17 @@ void T_SyncViewImpl_::displaySegmentWindow( ) noexcept
|
||||||
} else {
|
} else {
|
||||||
selSegment = decltype( selSegment ){};
|
selSegment = decltype( selSegment ){};
|
||||||
}
|
}
|
||||||
SyncEditor::DeleteSegment( selId->id , sid );
|
SyncEditor::DeleteSegment( *selId , sid );
|
||||||
#warning blah
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( change ) {
|
if ( change >= 0 && change < int32_t( nc ) ) {
|
||||||
SyncEditor::SetSegmentType( *curve , sid ,
|
SyncEditor::SetSegmentType(
|
||||||
T_SyncSegment::E_SegmentType( tp ) );
|
*( ovr ? sync.getCurve( ovr->inputNames( )[ change ] ) : curve ) ,
|
||||||
#warning blah
|
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( );
|
End( );
|
||||||
|
|
Loading…
Reference in a new issue