From bca8f28f43c4e0d647fe042ef3002fec91805190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toma=C5=BE=20V=C3=B6r=C3=B6=C5=A1?= Date: Fri, 27 Jan 2023 20:00:05 +0100 Subject: [PATCH] Centering around the mouse pointer. --- server/TracyTimelineController.cpp | 89 +++++++++++++++++++++++++++++- server/TracyTimelineController.hpp | 9 ++- server/TracyView_Timeline.cpp | 4 +- 3 files changed, 97 insertions(+), 5 deletions(-) diff --git a/server/TracyTimelineController.cpp b/server/TracyTimelineController.cpp index 2badc31c..990a34df 100644 --- a/server/TracyTimelineController.cpp +++ b/server/TracyTimelineController.cpp @@ -1,3 +1,5 @@ +#include + #include "imgui.h" #include "TracyTimelineController.hpp" @@ -8,6 +10,8 @@ namespace tracy TimelineController::TimelineController( View& view, Worker& worker ) : m_height( 0 ) , m_scroll( 0 ) + , m_centerItemkey( nullptr ) + , m_centerItemOffsetY( 0 ) , m_firstFrame( true ) , m_view( view ) , m_worker( worker ) @@ -24,8 +28,83 @@ void TimelineController::Begin() m_items.clear(); } -void TimelineController::End( double pxns, const ImVec2& wpos, bool hover, float yMin, float yMax ) +void TimelineController::UpdateCenterItem() { + ImVec2 mousePos = ImGui::GetMousePos(); + + m_centerItemkey = nullptr; + m_centerItemOffsetY = 0; + + if( m_firstFrame || !ImGui::IsMousePosValid( &mousePos ) ) return; + + const auto timelineMousePosY = mousePos.y - ImGui::GetWindowPos().y; + int centerY = timelineMousePosY + ImGui::GetScrollY(); + + int yBegin = 0; + int yEnd = 0; + for( auto& item : m_items ) + { + m_centerItemkey = item->GetKey(); + yBegin = yEnd; + yEnd += item->GetNextFrameHeight(); + + const auto inLowerBounds = m_centerItemkey == m_items.front()->GetKey() || yBegin <= centerY; + const auto inUpperBounds = m_centerItemkey == m_items.back()->GetKey() || centerY < yEnd; + + if( inLowerBounds && inUpperBounds ) + { + m_centerItemOffsetY = centerY - yBegin; + break; + } + } +} + +std::optional TimelineController::CalculateScrollPosition() const +{ + if( !m_centerItemkey ) return std::nullopt; + + ImVec2 mousePos = ImGui::GetMousePos(); + + if( !ImGui::IsMousePosValid( &mousePos ) ) return std::nullopt; + + const auto timelineMousePosY = mousePos.y - ImGui::GetWindowPos().y; + + int yBegin = 0; + int yEnd = 0; + for( auto& item : m_items ) + { + yBegin = yEnd; + yEnd += item->GetNextFrameHeight(); + + if( item->GetKey() != m_centerItemkey ) continue; + + int scrollY = yBegin + m_centerItemOffsetY - timelineMousePosY; + + return scrollY; + } + + return std::nullopt; +} + +void TimelineController::End( double pxns, const ImVec2& wpos, bool hover, bool vcenter, float yMin, float yMax ) +{ + auto shouldUpdateCenterItem = [&] () { + const auto& mouseDelta = ImGui::GetIO().MouseDelta; + const auto mouseMoved = mouseDelta.x != 0.0f || mouseDelta.y != 0.0f; + const auto imguiChangedScroll = m_scroll != ImGui::GetScrollY(); + return ( ( imguiChangedScroll || mouseMoved ) && !ImGui::IsMouseDown( 1 ) ) || !m_centerItemkey; + }; + + if( !vcenter ) + { + m_centerItemkey = nullptr; + m_centerItemOffsetY = 0; + } + else if( shouldUpdateCenterItem() ) + { + UpdateCenterItem(); + } + int yOffset = 0; for( auto& item : m_items ) @@ -36,6 +115,14 @@ void TimelineController::End( double pxns, const ImVec2& wpos, bool hover, float yOffset += currentFrameItemHeight; } + if( const auto scrollY = CalculateScrollPosition() ) + { + int clampedScrollY = std::min( *scrollY, yOffset ); + ImGui::SetScrollY( clampedScrollY ); + int minHeight = ImGui::GetWindowHeight() + clampedScrollY; + yOffset = std::max( yOffset, minHeight ); + } + const auto scrollPos = ImGui::GetScrollY(); if( ( scrollPos == 0 && m_scroll != 0 ) || yOffset > m_height ) { diff --git a/server/TracyTimelineController.hpp b/server/TracyTimelineController.hpp index eb9e0af6..b14dca67 100644 --- a/server/TracyTimelineController.hpp +++ b/server/TracyTimelineController.hpp @@ -2,6 +2,7 @@ #define __TRACYTIMELINECONTROLLER_HPP__ #include +#include #include #include "../public/common/TracyForceInline.hpp" @@ -18,7 +19,7 @@ public: void FirstFrameExpired(); void Begin(); - void End( double pxns, const ImVec2& wpos, bool hover, float yMin, float yMax ); + void End( double pxns, const ImVec2& wpos, bool hover, bool vcenter, float yMin, float yMax ); template void AddItem( U* data ) @@ -39,12 +40,18 @@ public: } private: + void UpdateCenterItem(); + std::optional CalculateScrollPosition() const; + std::vector m_items; unordered_flat_map> m_itemMap; float m_height; float m_scroll; + const void* m_centerItemkey; + int m_centerItemOffsetY; + bool m_firstFrame; View& m_view; diff --git a/server/TracyView_Timeline.cpp b/server/TracyView_Timeline.cpp index eddba3d0..0b88fdd0 100644 --- a/server/TracyView_Timeline.cpp +++ b/server/TracyView_Timeline.cpp @@ -327,8 +327,6 @@ void View::DrawTimeline() if( m_yDelta != 0 ) { auto& io = ImGui::GetIO(); - auto y = ImGui::GetScrollY(); - ImGui::SetScrollY( y - m_yDelta ); io.MouseClickedPos[1].y = io.MousePos.y; } @@ -380,7 +378,7 @@ void View::DrawTimeline() } } - m_tc.End( pxns, wpos, hover, yMin, yMax ); + m_tc.End( pxns, wpos, hover, drawMouseLine && m_viewMode == ViewMode::Paused, yMin, yMax ); ImGui::EndChild(); m_lockHighlight = m_nextLockHighlight;