Centering around the mouse pointer.

This commit is contained in:
Tomaž Vöröš
2023-01-27 20:00:05 +01:00
parent dbefb70db3
commit bca8f28f43
3 changed files with 97 additions and 5 deletions

View File

@@ -1,3 +1,5 @@
#include <algorithm>
#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<int> 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<int>( *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 )
{