diff --git a/syncview.cc b/syncview.cc index 4b0beec..b3cf1e7 100644 --- a/syncview.cc +++ b/syncview.cc @@ -15,7 +15,7 @@ namespace { struct T_SyncViewImpl_ { static constexpr float SeqHeaderHeight = 24; - static constexpr float MinUnitWidth = 80; + static constexpr float BarWidth = 40; const uint32_t ColFrame{ ImGui::GetColorU32( ImVec4{ 0 , 0 , 0 , .8 } ) }; const uint32_t ColHeader{ ImGui::GetColorU32( ImVec4{ .5 , .5 , .5 , .8 } ) }; @@ -23,10 +23,13 @@ struct T_SyncViewImpl_ const uint32_t ColMain{ ImGui::GetColorU32( ImVec4{ .4 , .4 , .4 , .8 } ) }; float zoomLevel{ 1.f }; + float startPos{ 100.895f }; + bool followTime{ true }; bool display( ) noexcept; void sequencerWidget( ) noexcept; void sequencerHeader( ImRect const& bb ) noexcept; + void sequencerBody( ImRect const& bb ) noexcept; }; @@ -47,6 +50,11 @@ bool T_SyncViewImpl_::display( ) noexcept return false; } + PushItemWidth( 100 ); + SliderFloat( "Zoom" , &zoomLevel , 0 , 1 , "%.2f" ); + PopItemWidth( ); + SameLine( ); + PushID( "playing" ); if ( Button( sync.playing( ) ? "Stop" : "Play" ) ) { sync.playing( ) = !sync.playing( ) && !sync.finished( ); @@ -109,18 +117,51 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept */ auto& sync( Globals::Sync( ) ); + const float innerWidth{ width - 2 }; const uint32_t units{ sync.durationUnits( ) }; - const float maxZoomUnits{ width / MinUnitWidth }; - const float slope{ maxZoomUnits - units }; - const float dUnits{ units + zoomLevel * slope }; -printf( "%d units ; %f/screen at max zoom ; slope %f ; display %f units at ZL %f\n" , units , maxZoomUnits , slope , dUnits , zoomLevel ); + zoomLevel = ImSaturate( zoomLevel ); + const float zoom1Pixels{ std::max( units * BarWidth , innerWidth ) }; + const float 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 ) }; + return uint32_t( b + ( mod ? ( 1 - mod ) : 0 ) ); + }() }; + const float unitsPerBar{ float( units ) / totalBars }; + const float barWidth{ totalPixels / totalBars }; + const float absCursorPos{ sync.time( ) * totalPixels / sync.duration( ) }; + if ( followTime ) { + const float dispUnits{ innerWidth * units / totalPixels }; + const float uSize{ sync.durationUnitSize( ) }; + const float endPos{ std::min( startPos + dispUnits , float( units ) ) }; + startPos = endPos - dispUnits; + 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 ); + } + } + const float unadjustedStartPixel{ totalPixels * startPos / units }; + if ( unadjustedStartPixel + innerWidth > totalPixels ) { + startPos = std::max( 0.f , totalPixels - innerWidth ); + } + const float startPixel{ totalPixels * startPos / units }; + const uint32_t startBar{ [=](){ + const float b{ startPixel * totalBars / totalPixels }; + const float mod{ fmod( b , 1.f ) }; + return uint32_t( std::max( 0 , int32_t( b - ( mod ? mod : 1 ) ) ) ); + }() }; + const float startBarPos{ startBar * barWidth - startPixel }; + const float cursorPos{ absCursorPos - startPixel }; + 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 ); PushID( seqId ); BeginGroup( ); const auto hdrId{ win->GetID( "##header" ) }; const auto dspId{ win->GetID( "##display" ) }; - auto* const dl( GetWindowDrawList( ) ); if ( ItemAdd( bbHeader , hdrId ) ) { PushID( hdrId ); @@ -128,9 +169,15 @@ printf( "%d units ; %f/screen at max zoom ; slope %f ; display %f units at ZL %f PopID( ); } if ( bbDisplay.Min.y < bbDisplay.Max.y && ItemAdd( bbDisplay , dspId ) ) { - // XXX display main area - dl->AddRectFilled( bbDisplay.Min , bbDisplay.Max , - ImGui::GetColorU32( ImVec4( .4 , .4 , .4 , .8 ) ) ); + PushID( dspId ); + sequencerBody( bbDisplay ); + PopID( ); + } + if ( cursorPos >= 0 && cursorPos <= width ) { + auto* const dl( GetWindowDrawList( ) ); + dl->AddLine( bbAll.Min + ImVec2{ cursorPos + 1 , 0 } , + ImVec2{ bbAll.Min.x + cursorPos + 1 , bbAll.Max.y } , + 0xffffffff ); } EndGroup( ); @@ -156,6 +203,15 @@ void T_SyncViewImpl_::sequencerHeader( PopFont( ); } +void T_SyncViewImpl_::sequencerBody( + ImRect const& bb ) noexcept +{ + using namespace ImGui; + auto* const dl( GetWindowDrawList( ) ); + + dl->AddRectFilled( bb.Min , bb.Max , ColMain ); +} + } // namespace /*= T_SyncView =================================================================*/