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_TRACK ,
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
@ -248,6 +256,7 @@ struct T_SyncViewImpl_
void displayTrackWindow( ) noexcept;
void displaySegmentWindow( ) noexcept;
void displayPointWindow( ) noexcept;
//----------------------------------------------------------------------
@ -296,8 +305,11 @@ struct T_SyncViewImpl_
T_Optional< uint32_t > selPoint;
bool selPointDnD{ false };
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
E_SubWindow sub{ SW_NONE };
@ -355,6 +367,10 @@ bool T_SyncViewImpl_::display( ) noexcept
case SW_SEGMENT:
displaySegmentWindow( );
break;
case SW_POINT:
displayPointWindow( );
break;
}
return true;
@ -597,11 +613,12 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept
selPoint = dPoint.index;
selPointDnD = io.MouseDown[ 0 ] && dPoint.index != 0;
if ( selPointDnD ) {
assert( selUpdate == E_ChangeType::NONE );
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;
#warning fix that shit
sub = E_SubWindow::SW_POINT;
}
}
}
@ -833,13 +850,13 @@ void T_SyncViewImpl_::sequencerTrack(
// If there's a curve, go through all segments
const auto units{ Common::Sync( ).durationUnits( ) };
const bool useCopy{ sCurve && curve && selPointDnDCopy };
const bool useCopy{ sCurve && curve && selUpdatingCopy };
const auto nSeg{ curve
? ( useCopy ? *selPointDnDCopy : *curve ).segments.size( )
? ( useCopy ? *selUpdatingCopy : *curve ).segments.size( )
: 0u };
uint32_t segStart{ 0 };
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{ [&](){
auto t{ 0u };
for ( auto d : seg.durations ) {
@ -1005,8 +1022,8 @@ bool T_SyncViewImpl_::handlePointDrag(
// Update the point as necessary
if ( moved ) {
selPointDnDCopy = selPointDnDOriginal; // XXX
auto& seg{ selPointDnDCopy->segments[ *selSegment ] };
selUpdatingCopy = selUpdatingOriginal; // XXX
auto& seg{ selUpdatingCopy->segments[ *selSegment ] };
if ( *selPoint == seg.durations.size( ) ) {
// We're dragging the end point
// XXX make it work "normally"
@ -1024,21 +1041,23 @@ bool T_SyncViewImpl_::handlePointDrag(
d0 += diff;
d1 -= diff;
}
sync.setCurve( *selPointDnDCopy );
sync.setCurve( *selUpdatingCopy );
} else {
selPointDnDCopy.clear( );
selUpdatingCopy.clear( );
}
if ( mouseDown ) {
return true;
}
assert( selUpdate == E_ChangeType::POINT_DND );
selUpdate = E_ChangeType::NONE;
selPointDnD = false;
sync.setCurve( std::move( *selPointDnDOriginal ) );
selPointDnDOriginal.clear( );
sync.setCurve( std::move( *selUpdatingOriginal ) );
selUpdatingOriginal.clear( );
if ( moved ) {
SyncEditor::ReplaceCurve( std::move( *selPointDnDCopy ) );
selPointDnDCopy.clear( );
SyncEditor::ReplaceCurve( std::move( *selUpdatingCopy ) );
selUpdatingCopy.clear( );
}
return false;
}
@ -1466,6 +1485,164 @@ void T_SyncViewImpl_::displaySegmentWindow( ) noexcept
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>