Skip to content

Commit

Permalink
Merge pull request #519 from tvoeroes/vertical-timeline-rescale-center
Browse files Browse the repository at this point in the history
Vertical timeline centering
  • Loading branch information
wolfpld authored Jan 31, 2023
2 parents 52b6af8 + 645d53f commit a26df1d
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 41 deletions.
102 changes: 98 additions & 4 deletions server/TracyTimelineController.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <algorithm>

#include "imgui.h"

#include "TracyTimelineController.hpp"
Expand All @@ -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 )
Expand All @@ -24,17 +28,107 @@ void TimelineController::Begin()
m_items.clear();
}

void TimelineController::End( double pxns, int offset, 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 )
{
item->Draw( m_firstFrame, pxns, offset, wpos, hover, yMin, yMax );
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 imguiChangedScroll = m_scroll != ImGui::GetScrollY();
const auto& mouseDelta = ImGui::GetIO().MouseDelta;
const auto mouseMoved = mouseDelta.x != 0.0f || mouseDelta.y != 0.0f;
const auto& mousePos = ImGui::GetIO().MousePos;
const auto mouseVisible = ImGui::IsMousePosValid( &mousePos );
return ( ( imguiChangedScroll || mouseMoved || !mouseVisible ) && !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 )
{
auto currentFrameItemHeight = item->GetNextFrameHeight();
item->Draw( m_firstFrame, pxns, yOffset, wpos, hover, yMin, yMax );
if( m_firstFrame ) currentFrameItemHeight = item->GetNextFrameHeight();
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 ) || offset > m_height )
if( ( scrollPos == 0 && m_scroll != 0 ) || yOffset > m_height )
{
m_height = offset;
m_height = yOffset;
}
m_scroll = scrollPos;
}
Expand Down
9 changes: 8 additions & 1 deletion server/TracyTimelineController.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define __TRACYTIMELINECONTROLLER_HPP__

#include <assert.h>
#include <optional>
#include <vector>

#include "../public/common/TracyForceInline.hpp"
Expand All @@ -18,7 +19,7 @@ class TimelineController

void FirstFrameExpired();
void Begin();
void End( double pxns, int offset, 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<class T, class U>
void AddItem( U* data )
Expand All @@ -39,12 +40,18 @@ class TimelineController
}

private:
void UpdateCenterItem();
std::optional<int> CalculateScrollPosition() const;

std::vector<TimelineItem*> m_items;
unordered_flat_map<const void*, std::unique_ptr<TimelineItem>> m_itemMap;

float m_height;
float m_scroll;

const void* m_centerItemkey;
int m_centerItemOffsetY;

bool m_firstFrame;

View& m_view;
Expand Down
46 changes: 24 additions & 22 deletions server/TracyTimelineItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,53 +8,56 @@
namespace tracy
{

TimelineItem::TimelineItem( View& view, Worker& worker )
TimelineItem::TimelineItem( View& view, Worker& worker, const void* key )
: m_visible( true )
, m_showFull( true )
, m_height( 0 )
, m_key( key )
, m_view( view )
, m_worker( worker )
{
}

void TimelineItem::Draw( bool firstFrame, double pxns, int& offset, const ImVec2& wpos, bool hover, float yMin, float yMax )
void TimelineItem::Draw( bool firstFrame, double pxns, int yOffset, const ImVec2& wpos, bool hover, float yMin, float yMax )
{
const auto yBegin = yOffset;
auto yEnd = yOffset;

if( !IsVisible() )
{
if( m_height != 0 ) AdjustThreadHeight( firstFrame, offset, offset );
if( m_height != 0 ) AdjustThreadHeight( firstFrame, yBegin, yEnd );
return;
}
if( IsEmpty() ) return;

const auto w = ImGui::GetContentRegionAvail().x - 1;
const auto ty = ImGui::GetTextLineHeight();
const auto ostep = ty + 1;
const auto yPos = wpos.y + offset;
const auto yPos = wpos.y + yBegin;
const auto dpos = wpos + ImVec2( 0.5f, 0.5f );
const auto oldOffset = offset;
auto draw = ImGui::GetWindowDrawList();

ImGui::PushID( this );
ImGui::PushClipRect( wpos + ImVec2( 0, offset ), wpos + ImVec2( w, offset + m_height ), true );
ImGui::PushClipRect( wpos + ImVec2( 0, yBegin ), wpos + ImVec2( w, yBegin + m_height ), true );

offset += ostep;
yEnd += ostep;
if( m_showFull )
{
if( !DrawContents( pxns, offset, wpos, hover, yMin, yMax ) && !m_view.GetViewData().drawEmptyLabels )
if( !DrawContents( pxns, yEnd, wpos, hover, yMin, yMax ) && !m_view.GetViewData().drawEmptyLabels )
{
offset = oldOffset;
AdjustThreadHeight( firstFrame, oldOffset, offset );
yEnd = yBegin;
AdjustThreadHeight( firstFrame, yBegin, yEnd );
ImGui::PopClipRect();
ImGui::PopID();
return;
}
}

DrawOverlay( wpos + ImVec2( 0, oldOffset ), wpos + ImVec2( w, offset ) );
DrawOverlay( wpos + ImVec2( 0, yBegin ), wpos + ImVec2( w, yEnd ) );
ImGui::PopClipRect();

float labelWidth;
const auto hdrOffset = oldOffset;
const auto hdrOffset = yBegin;
const bool drawHeader = yPos + ty >= yMin && yPos <= yMax;
if( drawHeader )
{
Expand Down Expand Up @@ -112,39 +115,38 @@ void TimelineItem::Draw( bool firstFrame, double pxns, int& offset, const ImVec2
ImGui::EndPopup();
}

offset += 0.2f * ostep;
AdjustThreadHeight( firstFrame, oldOffset, offset );
yEnd += 0.2f * ostep;
AdjustThreadHeight( firstFrame, yBegin, yEnd );

ImGui::PopID();
}

void TimelineItem::AdjustThreadHeight( bool firstFrame, int oldOffset, int& offset )
void TimelineItem::AdjustThreadHeight( bool firstFrame, int yBegin, int yEnd )
{
const auto speed = 4.0;
const auto baseMove = 1.0;

const auto h = offset - oldOffset;
const auto newHeight = yEnd - yBegin;
if( firstFrame )
{
m_height = h;
m_height = newHeight;
}
else if( m_height != h )
else if( m_height != newHeight )
{
const auto diff = h - m_height;
const auto diff = newHeight - m_height;
const auto preClampMove = diff * speed * ImGui::GetIO().DeltaTime;
if( diff > 0 )
{
const auto move = preClampMove + baseMove;
m_height = int( std::min<double>( m_height + move, h ) );
m_height = int( std::min<double>( m_height + move, newHeight ) );
}
else
{
const auto move = preClampMove - baseMove;
m_height = int( std::max<double>( m_height + move, h ) );
m_height = int( std::max<double>( m_height + move, newHeight ) );
}
s_wasActive = true;
}
offset = oldOffset + m_height;
}

void TimelineItem::VisibilityCheckbox()
Expand Down
14 changes: 11 additions & 3 deletions server/TracyTimelineItem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,23 @@ class Worker;
class TimelineItem
{
public:
TimelineItem( View& view, Worker& worker );
TimelineItem( View& view, Worker& worker, const void* key );
virtual ~TimelineItem() = default;

void Draw( bool firstFrame, double pxns, int& offset, const ImVec2& wpos, bool hover, float yMin, float yMax );
// draws the timeilne item and also updates the next frame height value
void Draw( bool firstFrame, double pxns, int yOffset, const ImVec2& wpos, bool hover, float yMin, float yMax );

void VisibilityCheckbox();
virtual void SetVisible( bool visible ) { m_visible = visible; }
virtual bool IsVisible() const { return m_visible; }

void SetShowFull( bool showFull ) { m_showFull = showFull; }

// returns 0 instead of the correct value for the first frame
int GetNextFrameHeight() const { return m_height; }

const void* GetKey() const { return m_key; }

protected:
virtual uint32_t HeaderColor() const = 0;
virtual uint32_t HeaderColorInactive() const = 0;
Expand All @@ -46,10 +52,12 @@ class TimelineItem
bool m_showFull;

private:
void AdjustThreadHeight( bool firstFrame, int oldOffset, int& offset );
void AdjustThreadHeight( bool firstFrame, int yBegin, int yEnd );

int m_height;

const void* m_key;

protected:
View& m_view;
Worker& m_worker;
Expand Down
4 changes: 2 additions & 2 deletions server/TracyTimelineItemCpuData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
namespace tracy
{

TimelineItemCpuData::TimelineItemCpuData( View& view, Worker& worker, void* )
: TimelineItem( view, worker )
TimelineItemCpuData::TimelineItemCpuData( View& view, Worker& worker, void* key )
: TimelineItem( view, worker, key )
{
}

Expand Down
2 changes: 1 addition & 1 deletion server/TracyTimelineItemCpuData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace tracy
class TimelineItemCpuData final : public TimelineItem
{
public:
TimelineItemCpuData( View& view, Worker& worker, void* );
TimelineItemCpuData( View& view, Worker& worker, void* key );

void SetVisible( bool visible ) override;
bool IsVisible() const override;
Expand Down
2 changes: 1 addition & 1 deletion server/TracyTimelineItemGpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace tracy
{

TimelineItemGpu::TimelineItemGpu( View& view, Worker& worker, GpuCtxData* gpu )
: TimelineItem( view, worker )
: TimelineItem( view, worker, gpu )
, m_gpu( gpu )
, m_idx( view.GetNextGpuIdx() )
{
Expand Down
2 changes: 1 addition & 1 deletion server/TracyTimelineItemPlot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace tracy
{

TimelineItemPlot::TimelineItemPlot( View& view, Worker& worker, PlotData* plot )
: TimelineItem( view, worker )
: TimelineItem( view, worker, plot )
, m_plot( plot )
{
}
Expand Down
2 changes: 1 addition & 1 deletion server/TracyTimelineItemThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace tracy
{

TimelineItemThread::TimelineItemThread( View& view, Worker& worker, const ThreadData* thread )
: TimelineItem( view, worker )
: TimelineItem( view, worker, thread )
, m_thread( thread )
, m_ghost( false )
{
Expand Down
Loading

0 comments on commit a26df1d

Please sign in to comment.