Sequencer - Point edition, insertion and deletion

This commit is contained in:
Emmanuel BENOîT 2017-11-26 17:39:17 +01:00
parent 9731adc872
commit aef7546a57

View file

@ -207,6 +207,14 @@ struct T_SyncViewImpl_
SW_OVERRIDE_SELECTOR , SW_OVERRIDE_SELECTOR ,
SW_TRACK , SW_TRACK ,
SW_SEGMENT , SW_SEGMENT ,
SW_POINT ,
};
// Type of change in progress
enum class E_ChangeType {
NONE ,
POINT_DND ,
POINT_VALUE ,
}; };
// Make sure all displayed curves/inputs/overrides still exist // Make sure all displayed curves/inputs/overrides still exist
@ -248,6 +256,7 @@ struct T_SyncViewImpl_
void displayTrackWindow( ) noexcept; void displayTrackWindow( ) noexcept;
void displaySegmentWindow( ) noexcept; void displaySegmentWindow( ) noexcept;
void displayPointWindow( ) noexcept;
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -296,8 +305,11 @@ struct T_SyncViewImpl_
T_Optional< uint32_t > selPoint; T_Optional< uint32_t > selPoint;
bool selPointDnD{ false }; bool selPointDnD{ false };
float selPointDnDStart , selPointDnDCur; float selPointDnDStart , selPointDnDCur;
T_Optional< T_SyncCurve > selPointDnDOriginal;
T_Optional< T_SyncCurve > selPointDnDCopy; // Original and copy of curve being modified
E_ChangeType selUpdate{ E_ChangeType::NONE };
T_Optional< T_SyncCurve > selUpdatingOriginal;
T_Optional< T_SyncCurve > selUpdatingCopy;
// Sub-windows // Sub-windows
E_SubWindow sub{ SW_NONE }; E_SubWindow sub{ SW_NONE };
@ -355,6 +367,10 @@ bool T_SyncViewImpl_::display( ) noexcept
case SW_SEGMENT: case SW_SEGMENT:
displaySegmentWindow( ); displaySegmentWindow( );
break; break;
case SW_POINT:
displayPointWindow( );
break;
} }
return true; return true;
@ -597,11 +613,12 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept
selPoint = dPoint.index; selPoint = dPoint.index;
selPointDnD = io.MouseDown[ 0 ] && dPoint.index != 0; selPointDnD = io.MouseDown[ 0 ] && dPoint.index != 0;
if ( selPointDnD ) { if ( selPointDnD ) {
assert( selUpdate == E_ChangeType::NONE );
selPointDnDStart = selPointDnDCur = mPixels; selPointDnDStart = selPointDnDCur = mPixels;
selPointDnDOriginal = *sync.getCurve( dTrack.id ); // XXX selUpdatingOriginal = *sync.getCurve( dTrack.id ); // XXX
selUpdate = E_ChangeType::POINT_DND;
} }
// sub = E_SubWindow::SW_SEGMENT; sub = E_SubWindow::SW_POINT;
#warning fix that shit
} }
} }
} }
@ -833,13 +850,13 @@ void T_SyncViewImpl_::sequencerTrack(
// If there's a curve, go through all segments // If there's a curve, go through all segments
const auto units{ Common::Sync( ).durationUnits( ) }; const auto units{ Common::Sync( ).durationUnits( ) };
const bool useCopy{ sCurve && curve && selPointDnDCopy }; const bool useCopy{ sCurve && curve && selUpdatingCopy };
const auto nSeg{ curve const auto nSeg{ curve
? ( useCopy ? *selPointDnDCopy : *curve ).segments.size( ) ? ( useCopy ? *selUpdatingCopy : *curve ).segments.size( )
: 0u }; : 0u };
uint32_t segStart{ 0 }; uint32_t segStart{ 0 };
for ( auto i = 0u ; i < nSeg ; i ++ ) { for ( auto i = 0u ; i < nSeg ; i ++ ) {
auto const& seg{ ( useCopy ? *selPointDnDCopy : *curve ).segments[ i ] }; auto const& seg{ ( useCopy ? *selUpdatingCopy : *curve ).segments[ i ] };
const auto segDur{ [&](){ const auto segDur{ [&](){
auto t{ 0u }; auto t{ 0u };
for ( auto d : seg.durations ) { for ( auto d : seg.durations ) {
@ -1005,8 +1022,8 @@ bool T_SyncViewImpl_::handlePointDrag(
// Update the point as necessary // Update the point as necessary
if ( moved ) { if ( moved ) {
selPointDnDCopy = selPointDnDOriginal; // XXX selUpdatingCopy = selUpdatingOriginal; // XXX
auto& seg{ selPointDnDCopy->segments[ *selSegment ] }; auto& seg{ selUpdatingCopy->segments[ *selSegment ] };
if ( *selPoint == seg.durations.size( ) ) { if ( *selPoint == seg.durations.size( ) ) {
// We're dragging the end point // We're dragging the end point
// XXX make it work "normally" // XXX make it work "normally"
@ -1024,21 +1041,23 @@ bool T_SyncViewImpl_::handlePointDrag(
d0 += diff; d0 += diff;
d1 -= diff; d1 -= diff;
} }
sync.setCurve( *selPointDnDCopy ); sync.setCurve( *selUpdatingCopy );
} else { } else {
selPointDnDCopy.clear( ); selUpdatingCopy.clear( );
} }
if ( mouseDown ) { if ( mouseDown ) {
return true; return true;
} }
assert( selUpdate == E_ChangeType::POINT_DND );
selUpdate = E_ChangeType::NONE;
selPointDnD = false; selPointDnD = false;
sync.setCurve( std::move( *selPointDnDOriginal ) ); sync.setCurve( std::move( *selUpdatingOriginal ) );
selPointDnDOriginal.clear( ); selUpdatingOriginal.clear( );
if ( moved ) { if ( moved ) {
SyncEditor::ReplaceCurve( std::move( *selPointDnDCopy ) ); SyncEditor::ReplaceCurve( std::move( *selUpdatingCopy ) );
selPointDnDCopy.clear( ); selUpdatingCopy.clear( );
} }
return false; return false;
} }
@ -1466,6 +1485,164 @@ void T_SyncViewImpl_::displaySegmentWindow( ) noexcept
End( ); End( );
} }
void T_SyncViewImpl_::displayPointWindow( ) 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 point" , &displayed , ImGuiWindowFlags_NoCollapse );
if ( !displayed ) {
End( );
sub = SW_NONE;
return;
}
// Access curve, segment and point
const uint32_t sid{ *selSegment };
const uint32_t pid{ *selPoint };
auto& sync{ Common::Sync( ) };
auto const* const curve{ selUpdatingCopy
? selUpdatingCopy.target( )
: sync.getCurve( selId ) };
auto const& segment{ curve->segments[ sid ] };
Text( "Curve:" );
SameLine( 110 );
Text( "%s" , selId.toOSString( ).data( ) );
Text( "Segment index:" );
SameLine( 110 );
Text( "%d" , sid );
Text( "Point index:" );
SameLine( 110 );
Text( "%d / %d" , pid , segment.durations.size( ) );
Separator( );
// Find start and duration
uint32_t segStart{ 0 } , pointPosRel{ 0 };
for ( auto i = 0u ; i <= sid ; i ++ ) {
auto const& s{ curve->segments[ i ] };
auto& tgt{ i == sid ? pointPosRel : segStart };
const auto end{ i == sid ? pid : s.durations.size( ) };
for ( auto j = 0u ; j < end ; j ++ ) {
tgt += s.durations[ j ];
}
}
const uint32_t pointPosAbs{ segStart + pointPosRel };
const float tPointPosAbs{ sync.durationUnitSize( ) * pointPosAbs } ,
tPointPosRel{ sync.durationUnitSize( ) * pointPosRel };
Text( "Absolute:" );
SameLine( 110 );
Text( "%d units" , pointPosAbs );
Text( " " );
SameLine( 110 );
Text( "%.3f seconds" , tPointPosAbs );
Text( "Relative:" );
SameLine( 110 );
Text( "%d units" , pointPosRel );
Text( " " );
SameLine( 110 );
Text( "%.3f seconds" , tPointPosRel );
Separator( );
Text( "Value:" );
SameLine( 110 );
float value{ segment.values[ pid ] };
PushItemWidth( -1 );
DragFloat( "##value" , &value , .01f , 0 , 0 , "%.6f" );
const bool changed{ IsItemActive( ) };
PopItemWidth( );
const bool canUseButtons{ !changed && selUpdate == E_ChangeType::NONE };
if ( pid != 0 && pid != segment.durations.size( ) ) {
Separator( );
Text( " " );
SameLine( 110 );
if ( Button( "Delete point" , ImVec2{ -1 , 0 } ) && canUseButtons ) {
// FIXME move to syncedit
auto c{ *curve };
auto& ns{ c.segments[ sid ] };
ns.durations[ pid ] += ns.durations[ pid - 1 ];
ns.durations.remove( pid - 1 );
ns.values.remove( pid );
SyncEditor::ReplaceCurve( std::move( c ) );
selPoint.clear( );
sub = SW_SEGMENT;
}
}
const auto canInsertBefore{ pid != 0
&& segment.durations[ pid - 1 ] > 1 };
const auto canInsertAfter{ pid != segment.durations.size( )
&& segment.durations[ pid ] > 1 };
if ( canInsertAfter || canInsertBefore ) {
Separator( );
if ( canInsertBefore ) {
Text( " " );
SameLine( 110 );
if ( Button( "Insert before" , ImVec2{ -1 , 0 } ) && canUseButtons ) {
// FIXME move to syncedit
auto c{ *curve };
auto& ns{ c.segments[ sid ] };
const auto hd{ ns.durations[ pid - 1 ] / 2 };
// FIXME: this should use the actual value
const float hv{ ( ns.values[ pid ] + ns.values[ pid - 1 ] ) * .5f };
ns.durations[ pid - 1 ] -= hd;
ns.durations.insert( pid - 1 , hd );
ns.values.insert( pid , hv );
SyncEditor::ReplaceCurve( std::move( c ) );
(*selPoint) ++;
}
}
if ( canInsertAfter ) {
Text( " " );
SameLine( 110 );
if ( Button( "Insert after" , ImVec2{ -1 , 0 } ) && canUseButtons ) {
// FIXME move to syncedit
auto c{ *curve };
auto& ns{ c.segments[ sid ] };
const auto hd{ ns.durations[ pid ] / 2 };
// FIXME: this should use the actual value
const float hv{ ( ns.values[ pid ] + ns.values[ pid + 1 ] ) * .5f };
ns.durations[ pid ] -= hd;
ns.durations.insert( pid , hd );
ns.values.insert( pid + 1 , hv );
SyncEditor::ReplaceCurve( std::move( c ) );
}
}
}
if ( changed ) {
if ( selUpdate == E_ChangeType::NONE ) {
selUpdatingOriginal = *curve;
selUpdatingCopy = *curve;
selUpdate = E_ChangeType::POINT_VALUE;
} else {
assert( selUpdate == E_ChangeType::POINT_VALUE );
}
selUpdatingCopy->segments[ sid ].values[ pid ] = value;
sync.setCurve( *selUpdatingCopy );
} else if ( selUpdate == E_ChangeType::POINT_VALUE ) {
selUpdate = E_ChangeType::NONE;
sync.setCurve( *selUpdatingOriginal );
SyncEditor::ReplaceCurve( std::move( *selUpdatingCopy ) );
selUpdatingCopy.clear( );
}
End( );
}
} // namespace <anon> } // namespace <anon>