Sequencer - Points can be moved
This commit is contained in:
parent
052d51a22f
commit
9731adc872
3 changed files with 110 additions and 6 deletions
|
@ -172,6 +172,23 @@ void SyncEditor::SetDuration(
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SyncEditor::ReplaceCurve(
|
||||||
|
T_SyncCurve replacement ) noexcept
|
||||||
|
{
|
||||||
|
auto* const curve{ Common::Sync( ).getCurve( replacement.name ) };
|
||||||
|
if ( !curve ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create undo entry
|
||||||
|
auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
|
||||||
|
Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
|
||||||
|
undo.curveReplacement( std::move( *curve ) , replacement );
|
||||||
|
Common::Sync( ).setCurve( std::move( replacement ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SyncEditor::DeleteCurve(
|
void SyncEditor::DeleteCurve(
|
||||||
T_String const& id ) noexcept
|
T_String const& id ) noexcept
|
||||||
{
|
{
|
||||||
|
|
|
@ -92,6 +92,10 @@ struct SyncEditor final
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Replaces a curve with a new record
|
||||||
|
static void ReplaceCurve(
|
||||||
|
T_SyncCurve replacement ) noexcept;
|
||||||
|
|
||||||
// Delete a curve's record completely.
|
// Delete a curve's record completely.
|
||||||
static void DeleteCurve(
|
static void DeleteCurve(
|
||||||
T_String const& id ) noexcept;
|
T_String const& id ) noexcept;
|
||||||
|
|
|
@ -233,6 +233,9 @@ struct T_SyncViewImpl_
|
||||||
|
|
||||||
void displayTooltips(
|
void displayTooltips(
|
||||||
const float time ) noexcept;
|
const float time ) noexcept;
|
||||||
|
bool handlePointDrag(
|
||||||
|
const float mPixels ,
|
||||||
|
bool mouseDown ) noexcept;
|
||||||
|
|
||||||
T_MousePos getMousePos( ) const noexcept;
|
T_MousePos getMousePos( ) const noexcept;
|
||||||
|
|
||||||
|
@ -254,6 +257,8 @@ struct T_SyncViewImpl_
|
||||||
const uint32_t ColHeaderText{ ImGui::GetColorU32( ImVec4{ 0 , 0 , 0 , 1 } ) };
|
const uint32_t ColHeaderText{ ImGui::GetColorU32( ImVec4{ 0 , 0 , 0 , 1 } ) };
|
||||||
const uint32_t ColMain{ ImGui::GetColorU32( ImVec4{ .4 , .4 , .4 , .8 } ) };
|
const uint32_t ColMain{ ImGui::GetColorU32( ImVec4{ .4 , .4 , .4 , .8 } ) };
|
||||||
const uint32_t ColSelection{ ImGui::GetColorU32( ImVec4{ .8 , 1 , .8 , .2 } ) };
|
const uint32_t ColSelection{ ImGui::GetColorU32( ImVec4{ .8 , 1 , .8 , .2 } ) };
|
||||||
|
const uint32_t ColPointNormal{ ImGui::GetColorU32( ImVec4{ 0 , 0 , 0 , .25 } ) };
|
||||||
|
const uint32_t ColPointSelected{ ImGui::GetColorU32( ImVec4{ 0 , 0 , 0 , .75 } ) };
|
||||||
const ImVec2 BtSize{ 20 , 0 };
|
const ImVec2 BtSize{ 20 , 0 };
|
||||||
|
|
||||||
// Sequencer settings
|
// Sequencer settings
|
||||||
|
@ -289,6 +294,10 @@ struct T_SyncViewImpl_
|
||||||
bool selIsOverride;
|
bool selIsOverride;
|
||||||
T_Optional< uint32_t > selSegment;
|
T_Optional< uint32_t > selSegment;
|
||||||
T_Optional< uint32_t > selPoint;
|
T_Optional< uint32_t > selPoint;
|
||||||
|
bool selPointDnD{ false };
|
||||||
|
float selPointDnDStart , selPointDnDCur;
|
||||||
|
T_Optional< T_SyncCurve > selPointDnDOriginal;
|
||||||
|
T_Optional< T_SyncCurve > selPointDnDCopy;
|
||||||
|
|
||||||
// Sub-windows
|
// Sub-windows
|
||||||
E_SubWindow sub{ SW_NONE };
|
E_SubWindow sub{ SW_NONE };
|
||||||
|
@ -536,6 +545,10 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( selPointDnD && handlePointDrag( mPixels , io.MouseDown[ 0 ] ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( !( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) ) {
|
if ( !( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) ) {
|
||||||
ClearActiveID( );
|
ClearActiveID( );
|
||||||
return;
|
return;
|
||||||
|
@ -573,6 +586,23 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept
|
||||||
selPoint = decltype( selPoint ){};
|
selPoint = decltype( selPoint ){};
|
||||||
sub = E_SubWindow::SW_SEGMENT;
|
sub = E_SubWindow::SW_SEGMENT;
|
||||||
}
|
}
|
||||||
|
} else if ( mp.type == E_MousePosType::POINT ) {
|
||||||
|
auto const& dPoint{ dspPoints[ mp.index ] };
|
||||||
|
auto const& dSeg{ dspSegments[ dPoint.seg ] };
|
||||||
|
auto const& dTrack{ dspTracks[ dSeg.track ] };
|
||||||
|
if ( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) {
|
||||||
|
selId = dTrack.id;
|
||||||
|
selIsOverride = dTrack.isOverride;
|
||||||
|
selSegment = dSeg.seg;
|
||||||
|
selPoint = dPoint.index;
|
||||||
|
selPointDnD = io.MouseDown[ 0 ] && dPoint.index != 0;
|
||||||
|
if ( selPointDnD ) {
|
||||||
|
selPointDnDStart = selPointDnDCur = mPixels;
|
||||||
|
selPointDnDOriginal = *sync.getCurve( dTrack.id ); // XXX
|
||||||
|
}
|
||||||
|
// sub = E_SubWindow::SW_SEGMENT;
|
||||||
|
#warning fix that shit
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -803,10 +833,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 auto nSeg{ curve ? curve->segments.size( ) : 0u };
|
const bool useCopy{ sCurve && curve && selPointDnDCopy };
|
||||||
|
const auto nSeg{ curve
|
||||||
|
? ( useCopy ? *selPointDnDCopy : *curve ).segments.size( )
|
||||||
|
: 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{ curve->segments[ i ] };
|
auto const& seg{ ( useCopy ? *selPointDnDCopy : *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 ) {
|
||||||
|
@ -827,9 +860,6 @@ void T_SyncViewImpl_::sequencerTrack(
|
||||||
|
|
||||||
// Add segment to displayed list
|
// Add segment to displayed list
|
||||||
const bool sSegment{ sCurve && selSegment && *selSegment == i };
|
const bool sSegment{ sCurve && selSegment && *selSegment == i };
|
||||||
if ( sSegment ) {
|
|
||||||
printf( "SelSeg! %d\n" , *selSegment );
|
|
||||||
}
|
|
||||||
const auto color{ segColors[ i % 2 + ( sSegment ? 2 : 0 ) ] };
|
const auto color{ segColors[ i % 2 + ( sSegment ? 2 : 0 ) ] };
|
||||||
auto dSegIdx{ dspSegments.size( ) };
|
auto dSegIdx{ dspSegments.size( ) };
|
||||||
auto& dSeg{ dspSegments.addNew( ) };
|
auto& dSeg{ dspSegments.addNew( ) };
|
||||||
|
@ -857,7 +887,9 @@ void T_SyncViewImpl_::sequencerTrack(
|
||||||
std::roundf( xStart + cDur * totalPixels / units ) ,
|
std::roundf( xStart + cDur * totalPixels / units ) ,
|
||||||
ym
|
ym
|
||||||
};
|
};
|
||||||
dl->AddCircleFilled( ctr , PointRadius , 0x7f000000 ); // XXX color
|
const bool sPoint{ sSegment && selPoint && *selPoint == j };
|
||||||
|
dl->AddCircleFilled( ctr , PointRadius ,
|
||||||
|
sPoint ? ColPointSelected : ColPointNormal );
|
||||||
cDur += j < nd ? seg.durations[ j ] : 0;
|
cDur += j < nd ? seg.durations[ j ] : 0;
|
||||||
|
|
||||||
// Add point record
|
// Add point record
|
||||||
|
@ -960,6 +992,57 @@ void T_SyncViewImpl_::displayTooltips(
|
||||||
EndTooltip( );
|
EndTooltip( );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool T_SyncViewImpl_::handlePointDrag(
|
||||||
|
const float mPixels ,
|
||||||
|
bool mouseDown ) noexcept
|
||||||
|
{
|
||||||
|
auto& sync( Common::Sync( ) );
|
||||||
|
|
||||||
|
selPointDnDCur = mPixels;
|
||||||
|
const float diff{ selPointDnDCur - selPointDnDStart };
|
||||||
|
const int32_t diffUnits{ int32_t( round( diff * sync.durationUnits( ) / totalPixels ) ) };
|
||||||
|
const bool moved{ fabsf( diff ) >= 2 && abs( diffUnits ) > 0 };
|
||||||
|
|
||||||
|
// Update the point as necessary
|
||||||
|
if ( moved ) {
|
||||||
|
selPointDnDCopy = selPointDnDOriginal; // XXX
|
||||||
|
auto& seg{ selPointDnDCopy->segments[ *selSegment ] };
|
||||||
|
if ( *selPoint == seg.durations.size( ) ) {
|
||||||
|
// We're dragging the end point
|
||||||
|
// XXX make it work "normally"
|
||||||
|
seg.durations.last( ) = std::max( 1 ,
|
||||||
|
diffUnits + int32_t( seg.durations.last( ) ) );
|
||||||
|
} else {
|
||||||
|
// We're dragging some other point, move units
|
||||||
|
// from one side to the other
|
||||||
|
assert( *selPoint > 0 );
|
||||||
|
auto& d0{ seg.durations[ *selPoint - 1 ] };
|
||||||
|
auto& d1{ seg.durations[ *selPoint ] };
|
||||||
|
const int32_t mmNeg( 1 - d0 ) , mmPos( d1 - 1 );
|
||||||
|
const int32_t diff{ diffUnits < mmNeg ? mmNeg
|
||||||
|
: ( diffUnits > mmPos ? mmPos : diffUnits ) };
|
||||||
|
d0 += diff;
|
||||||
|
d1 -= diff;
|
||||||
|
}
|
||||||
|
sync.setCurve( *selPointDnDCopy );
|
||||||
|
} else {
|
||||||
|
selPointDnDCopy.clear( );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mouseDown ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
selPointDnD = false;
|
||||||
|
sync.setCurve( std::move( *selPointDnDOriginal ) );
|
||||||
|
selPointDnDOriginal.clear( );
|
||||||
|
if ( moved ) {
|
||||||
|
SyncEditor::ReplaceCurve( std::move( *selPointDnDCopy ) );
|
||||||
|
selPointDnDCopy.clear( );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
T_SyncViewImpl_::T_MousePos T_SyncViewImpl_::getMousePos( ) const noexcept
|
T_SyncViewImpl_::T_MousePos T_SyncViewImpl_::getMousePos( ) const noexcept
|
||||||
|
|
Loading…
Reference in a new issue