From 5916e9f61cd993ce307cca59c648aac7d4fa194c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Tue, 21 Nov 2017 15:48:34 +0100 Subject: [PATCH] Sequencer - Right click selection zoom --- syncview.cc | 85 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 8 deletions(-) diff --git a/syncview.cc b/syncview.cc index 7059b81..95c5639 100644 --- a/syncview.cc +++ b/syncview.cc @@ -21,6 +21,7 @@ struct T_SyncViewImpl_ const uint32_t ColHeader{ ImGui::GetColorU32( ImVec4{ .5 , .5 , .5 , .8 } ) }; 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 ColSelection{ ImGui::GetColorU32( ImVec4{ .8 , 1 , .8 , .2 } ) }; float zoomLevel{ 0.f }; float startPos{ 0.f }; @@ -38,8 +39,18 @@ struct T_SyncViewImpl_ uint32_t startBar; float startBarPos; float timePerBar; + float totalPixels; + float startPixel; + + // Zoom area selection + bool zoomInProgress{ false }; + bool justZoomed{ false }; + float firstZoomPixel; + float curZoomPixel; }; +constexpr float T_SyncViewImpl_::BarWidth; + bool T_SyncViewImpl_::display( ) noexcept { @@ -122,14 +133,13 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept if ( !ItemAdd( bbAll , seqId ) ) { return; } + const bool hovered{ ItemHoverable( bbAll , seqId ) }; computeMetrics( std::max( 0.f , width - 2.f ) ); - PushID( seqId ); BeginGroup( ); - const auto hdrId{ win->GetID( "##header" ) }; const auto dspId{ win->GetID( "##display" ) }; - + PushID( seqId ); if ( ItemAdd( bbHeader , hdrId ) ) { PushID( hdrId ); sequencerHeader( bbHeader ); @@ -140,9 +150,53 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept sequencerBody( bbDisplay ); PopID( ); } + PopID( ); + + auto& io( GetIO( ) ); + if ( hovered && ( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) ) { + SetActiveID( seqId , win ); + FocusWindow( win ); + } + + const bool active( GetCurrentContext( )->ActiveId == seqId ); + if ( active ) { + if ( io.MouseDown[ 0 ] ) { + const float p{ io.MousePos.x - bbAll.Min.x + startPixel }; + auto& sync( Globals::Sync( ) ); + sync.setTime( p * Globals::Sync( ).duration( ) / totalPixels ); + } + if ( io.MouseDown[ 1 ] ) { + const float p{ io.MousePos.x - bbAll.Min.x + startPixel }; + if ( !zoomInProgress ) { + firstZoomPixel = p; + zoomInProgress = true; + } + curZoomPixel = p; + } else if ( zoomInProgress ) { + zoomInProgress = false; + justZoomed = true; + const auto zMin{ std::min( firstZoomPixel , curZoomPixel ) } , + zMax{ std::max( firstZoomPixel , curZoomPixel ) } , + diff{ zMax - zMin }; + if ( diff > 4 ) { + auto& sync( Globals::Sync( ) ); + const float u( sync.durationUnits( ) ); + startPos = zMin * u / totalPixels; + if ( ( width - 2.f ) / u >= BarWidth ) { + zoomLevel = 0; + } else { + const auto length{ std::min( u , diff * u / totalPixels ) }; + const auto ppu{ std::min( ( width - 2 ) / length , BarWidth ) }; + zoomLevel = ( ppu - BarWidth ) / ( BarWidth - width / u ) + 1; + } + } + } + if ( !( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) ) { + ClearActiveID( ); + } + } EndGroup( ); - PopID( ); } void T_SyncViewImpl_::computeMetrics( @@ -152,7 +206,7 @@ void T_SyncViewImpl_::computeMetrics( const uint32_t units{ sync.durationUnits( ) }; zoomLevel = ImSaturate( zoomLevel ); const float zoom1Pixels{ std::max( units * BarWidth , innerWidth ) }; - const float totalPixels{ zoomLevel * ( zoom1Pixels - innerWidth ) + innerWidth }; + totalPixels = zoomLevel * ( zoom1Pixels - innerWidth ) + innerWidth; const uint32_t totalBars{ [=](){ const float b{ std::max( std::min( totalPixels / BarWidth , float( units ) ) , 1.f ) }; const float mod{ fmod( b , 1.f ) }; @@ -169,14 +223,18 @@ void T_SyncViewImpl_::computeMetrics( const float spp{ startPos * totalPixels / units }; const float epp{ endPos * totalPixels / units }; if ( absCursorPos < spp || absCursorPos > epp ) { - startPos = std::max( 0.f , sync.time( ) / uSize - unitsPerBar * .5f ); + if ( justZoomed ) { + followTime = false; + } else { + startPos = std::max( 0.f , sync.time( ) / uSize - unitsPerBar * .5f ); + } } } const float unadjustedStartPixel{ totalPixels * startPos / units }; if ( unadjustedStartPixel + innerWidth > totalPixels ) { startPos = std::max( 0.f , totalPixels - innerWidth ); } - const float startPixel{ totalPixels * startPos / units }; + startPixel = totalPixels * startPos / units; startBar = [=](){ const float b{ startPixel * totalBars / totalPixels }; const float mod{ fmod( b , 1.f ) }; @@ -185,9 +243,10 @@ void T_SyncViewImpl_::computeMetrics( startBarPos = startBar * barWidth - startPixel; cursorPos = absCursorPos - startPixel; timePerBar = unitsPerBar * sync.durationUnitSize( ); - printf( "Z: %f; P@zl1: %f; Pt: %f; Bt: %d; U/B: %f; Bw: %f; Sp: %f; Sb: %d, SbP: %f\n" , zoomLevel , zoom1Pixels , totalPixels , totalBars , unitsPerBar , barWidth , startPixel , startBar , startBarPos ); assert( startBarPos <= 0 ); assert( totalPixels >= innerWidth ); + + justZoomed = false; } void T_SyncViewImpl_::sequencerHeader( @@ -241,6 +300,16 @@ void T_SyncViewImpl_::sequencerBody( dl->AddRectFilled( inner.Min , inner.Max , ColMain ); dl->AddRect( bb.Min , bb.Max , ColFrame ); + if ( zoomInProgress ) { + const float z0{ ImClamp( firstZoomPixel - startPixel + inner.Min.x , inner.Min.x , inner.Max.x ) } , + z1{ ImClamp( curZoomPixel - startPixel + bb.Min.x , inner.Min.x , inner.Max.x ) }; + const float zMin{ std::min( z0 , z1 ) } , zMax{ std::max( z0 , z1 ) }; + if ( zMin != zMax ) { + dl->AddRectFilled( ImVec2{ zMin , inner.Min.y } , + ImVec2{ zMax , inner.Max.y } , + ColSelection ); + } + } auto pos{ startBarPos }; auto bar{ startBar };