Sequencer - Point edition, insertion and deletion
This commit is contained in:
parent
9731adc872
commit
aef7546a57
1 changed files with 193 additions and 16 deletions
209
ui-sequencer.cc
209
ui-sequencer.cc
|
@ -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>
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue