Sequencer - Segment creation & deletion, curve deletion

This commit is contained in:
Emmanuel BENOîT 2017-11-26 10:14:00 +01:00
parent 93aec231c5
commit 4e5991d2ea
4 changed files with 244 additions and 8 deletions

View file

@ -315,6 +315,8 @@ struct T_SyncManager : public virtual A_ProjectPathListener
bool addInput( T_String const& name , bool addInput( T_String const& name ,
const float initial = 0.f ) noexcept const float initial = 0.f ) noexcept
{ return values_.addValue( name , initial ); } { return values_.addValue( name , initial ); }
bool hasInput( T_String const& name ) const noexcept
{ return values_.identifiers.contains( name ); }
T_Array< T_String > const& inputNames( ) const noexcept T_Array< T_String > const& inputNames( ) const noexcept
{ return values_.identifiers; } { return values_.identifiers; }

View file

@ -172,6 +172,94 @@ void SyncEditor::SetDuration(
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
void SyncEditor::DeleteCurve(
T_String const& id ) noexcept
{
auto const* const curve{ Common::Sync( ).getCurve( id ) };
if ( !curve ) {
return;
}
// Create undo entry
auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
undo.curveDeletion( *curve );
// Delete curve
Common::Sync( ).removeCurve( id );
}
/*----------------------------------------------------------------------------*/
void SyncEditor::AppendSegment(
T_String const& id ,
uint32_t nsDuration ) noexcept
{
assert( nsDuration > 0 );
auto& sync{ Common::Sync( ) };
auto const* const curve{ sync.getCurve( id ) };
auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
if ( curve && !curve->segments.empty( ) ) {
const float lastValue{ [&](){
auto const& lSeg{ curve->segments.last( ) };
return lSeg.values.last( );
}( ) };
auto nCurve{ *curve };
auto& nSeg{ nCurve.segments.addNew( ) };
nSeg.type = T_SyncSegment::LINEAR;
nSeg.values.add( lastValue );
nSeg.values.add( lastValue );
nSeg.durations.add( nsDuration );
undo.curveReplacement( *curve , nCurve );
sync.setCurve( std::move( nCurve ) );
} else {
T_SyncCurve nCurve;
nCurve.name = id;
const auto value{ sync.inputs( )[ sync.inputPos( id ) ] };
auto& nSeg{ nCurve.segments.addNew( ) };
nSeg.type = T_SyncSegment::LINEAR;
nSeg.values.add( value );
nSeg.values.add( value );
nSeg.durations.add( nsDuration );
undo.curveCreation( nCurve );
sync.setCurve( std::move( nCurve ) );
}
}
/*----------------------------------------------------------------------------*/
void SyncEditor::DeleteSegment(
T_String const& id ,
const uint32_t segmentIndex ) noexcept
{
auto& sync{ Common::Sync( ) };
auto const* const curve{ sync.getCurve( id ) };
if ( !curve || segmentIndex >= curve->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 ) );
}
}
/*----------------------------------------------------------------------------*/
void SyncEditor::SetSegmentType( void SyncEditor::SetSegmentType(
T_SyncCurve const& initial , T_SyncCurve const& initial ,
const uint32_t segmentIndex , const uint32_t segmentIndex ,

View file

@ -90,6 +90,25 @@ struct SyncEditor final
float uSize , float uSize ,
bool scaleCurves ) noexcept; bool scaleCurves ) noexcept;
//----------------------------------------------------------------------
// Delete a curve's record completely.
static void DeleteCurve(
T_String const& id ) noexcept;
//----------------------------------------------------------------------
// Append a segment with the specified amount of units at the end of
// the curve. If the curve does not exist it will be created.
static void AppendSegment(
T_String const& id ,
uint32_t nsDuration ) noexcept;
// Delete a segment from a curve.
static void DeleteSegment(
T_String const& id ,
uint32_t segmentIndex ) noexcept;
// Change the type of a segment in a curve. // Change the type of a segment in a curve.
static void SetSegmentType( static void SetSegmentType(
T_SyncCurve const& initial , T_SyncCurve const& initial ,

View file

@ -205,6 +205,7 @@ struct T_SyncViewImpl_
SW_NONE , SW_NONE ,
SW_INPUT_SELECTOR , SW_INPUT_SELECTOR ,
SW_OVERRIDE_SELECTOR , SW_OVERRIDE_SELECTOR ,
SW_TRACK ,
SW_SEGMENT , SW_SEGMENT ,
}; };
@ -215,8 +216,8 @@ struct T_SyncViewImpl_
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// Sequencer widget methods // Sequencer widget methods
void computeMetrics( float innerWidth ) noexcept;
void sequencerWidget( ) noexcept; void sequencerWidget( ) noexcept;
void computeMetrics( float innerWidth ) noexcept;
void sequencerHeader( ImRect const& bb ) noexcept; void sequencerHeader( ImRect const& bb ) noexcept;
void sequencerBody( ImRect const& bb ) noexcept; void sequencerBody( ImRect const& bb ) noexcept;
void sequencerTracks( void sequencerTracks(
@ -242,6 +243,7 @@ struct T_SyncViewImpl_
void displayInputSelector( ) noexcept; void displayInputSelector( ) noexcept;
void displayOverrideSelector( ) noexcept; void displayOverrideSelector( ) noexcept;
void displayTrackWindow( ) noexcept;
void displaySegmentWindow( ) noexcept; void displaySegmentWindow( ) noexcept;
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -285,7 +287,7 @@ struct T_SyncViewImpl_
// Selected item // Selected item
T_String selId{ }; T_String selId{ };
bool selIsOverride; bool selIsOverride;
uint32_t selSegment; T_Optional< uint32_t > selSegment;
T_Optional< uint32_t > selPoint; T_Optional< uint32_t > selPoint;
// Sub-windows // Sub-windows
@ -337,6 +339,10 @@ bool T_SyncViewImpl_::display( ) noexcept
displayTrackSelectorWindow( ); displayTrackSelectorWindow( );
break; break;
case SW_TRACK:
displayTrackWindow( );
break;
case SW_SEGMENT: case SW_SEGMENT:
displaySegmentWindow( ); displaySegmentWindow( );
break; break;
@ -548,6 +554,15 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept
curZoomPixel = mPixels; curZoomPixel = mPixels;
} }
} else if ( mp.type == E_MousePosType::TRACK ) {
auto const& dTrack{ dspTracks[ mp.index ] };
if ( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) {
selId = dTrack.id;
selIsOverride = dTrack.isOverride;
selSegment = {};
selPoint = {};
sub = E_SubWindow::SW_TRACK;
}
} else if ( mp.type == E_MousePosType::SEGMENT ) { } else if ( mp.type == E_MousePosType::SEGMENT ) {
auto const& dSeg{ dspSegments[ mp.index ] }; auto const& dSeg{ dspSegments[ mp.index ] };
auto const& dTrack{ dspTracks[ dSeg.track ] }; auto const& dTrack{ dspTracks[ dSeg.track ] };
@ -1135,6 +1150,102 @@ void T_SyncViewImpl_::displayOverrideSelector( ) noexcept
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
void T_SyncViewImpl_::displayTrackWindow( ) noexcept
{
using namespace ImGui;
auto const& dspSize( GetIO( ).DisplaySize );
// Window set-up
SetNextWindowSize( ImVec2( dspSize.x * .25f , dspSize.y * .66f - 20 ) , ImGuiSetCond_Appearing );
SetNextWindowPos( ImVec2( dspSize.x * .75f , 20 ) , ImGuiSetCond_Appearing );
bool displayed{ true };
Begin( "Selected track" , &displayed , ImGuiWindowFlags_NoCollapse );
if ( !displayed ) {
End( );
sub = SW_NONE;
return;
}
// Get the curve
auto& sync{ Common::Sync( ) };
auto const* const curve{ sync.getCurve( selId ) };
Text( "Curve:" );
SameLine( 110 );
Text( "%s" , selId.toOSString( ).data( ) );
if ( !sync.hasInput( selId ) ) {
Text( " " );
SameLine( 110 );
Text( "No matching input" );
}
Text( "Segments:" );
SameLine( 110 );
Text( "%d" , curve ? curve->segments.size( ) : 0 );
Separator( );
// Compute total duration
const uint32_t duration{ [&](){
uint32_t t{ 0 };
if ( !curve ) {
return 0u;
}
for ( auto const& s : curve->segments ) {
for ( auto const& d : s.durations ) {
t += d;
}
}
return t;
}() };
const float tDuration{ duration * sync.durationUnitSize( ) };
Text( "Duration:" );
SameLine( 110 );
Text( "%d units" , duration );
Text( " " );
SameLine( 110 );
Text( "%.3f seconds" , tDuration );
const float dDuration{ sync.duration( ) };
if ( tDuration == 0.f ) {
Text( " " );
SameLine( 110 );
Text( "Empty track" );
} else if ( tDuration == dDuration ) {
Text( " " );
SameLine( 110 );
Text( "Covers the whole demo" );
} else if ( tDuration > dDuration ) {
Text( " " );
SameLine( 110 );
Text( "Longer than the demo" );
}
if ( ( curve && !curve->segments.empty( ) ) || tDuration < dDuration ) {
Separator( );
}
if ( curve && !curve->segments.empty( ) ) {
Text( " " );
SameLine( 110 );
if ( Button( "Clear" , ImVec2{ -1 , 0 } ) ) {
SyncEditor::DeleteCurve( selId );
}
}
if ( tDuration < dDuration ) {
Text( " " );
SameLine( 110 );
if ( Button( "Append segment" , ImVec2{ -1 , 0 } ) ) {
const uint32_t ns{ std::max( 1u ,
( sync.durationUnits( ) - duration ) / 2 ) };
SyncEditor::AppendSegment( selId , ns );
}
}
End( );
}
void T_SyncViewImpl_::displaySegmentWindow( ) noexcept void T_SyncViewImpl_::displaySegmentWindow( ) noexcept
{ {
using namespace ImGui; using namespace ImGui;
@ -1151,25 +1262,28 @@ void T_SyncViewImpl_::displaySegmentWindow( ) noexcept
return; return;
} }
const uint32_t sid{ *selSegment };
Text( "Curve:" ); Text( "Curve:" );
SameLine( 110 ); SameLine( 110 );
Text( "%s" , selId.toOSString( ).data( ) ); Text( "%s" , selId.toOSString( ).data( ) );
Text( "Index:" ); Text( "Index:" );
SameLine( 110 ); SameLine( 110 );
Text( "%d" , selSegment ); Text( "%d" , sid );
Separator( ); Separator( );
// Access curve and segment
auto& sync{ Common::Sync( ) }; auto& sync{ Common::Sync( ) };
auto* const curve{ sync.getCurve( selId ) }; auto const* const curve{ sync.getCurve( selId ) };
auto& segment{ curve->segments[ selSegment ] }; auto const& segment{ curve->segments[ sid ] };
// Find start and duration // Find start and duration
uint32_t start{ 0 } , duration{ 0 }; uint32_t start{ 0 } , duration{ 0 };
for ( auto i = 0u ; i <= selSegment ; i ++ ) { for ( auto i = 0u ; i <= sid ; i ++ ) {
auto const& s{ curve->segments[ i ] }; auto const& s{ curve->segments[ i ] };
auto& tgt{ i == selSegment ? duration : start }; auto& tgt{ i == sid ? duration : start };
for ( auto d : s.durations ) { for ( auto d : s.durations ) {
tgt += d; tgt += d;
} }
@ -1240,8 +1354,21 @@ void T_SyncViewImpl_::displaySegmentWindow( ) noexcept
SameLine( 110 ); SameLine( 110 );
Text( "%f" , sMax ); Text( "%f" , sMax );
Separator( );
Text( " " );
SameLine( 110 );
if ( Button( "Delete segment" , ImVec2{ -1 , 0 } ) ) {
if ( curve->segments.size( ) > 1 ) {
selSegment = ( sid == 0 ? 0 : ( sid - 1 ) );
} else {
selSegment = {};
}
SyncEditor::DeleteSegment( selId , sid );
}
if ( change ) { if ( change ) {
SyncEditor::SetSegmentType( *curve , selSegment , SyncEditor::SetSegmentType( *curve , sid ,
T_SyncSegment::E_SegmentType( t ) ); T_SyncSegment::E_SegmentType( t ) );
} }