diff --git a/profiler/build/win32/Tracy.vcxproj b/profiler/build/win32/Tracy.vcxproj index ec13eba9..a45e987f 100644 --- a/profiler/build/win32/Tracy.vcxproj +++ b/profiler/build/win32/Tracy.vcxproj @@ -137,6 +137,7 @@ + @@ -273,6 +274,7 @@ + diff --git a/profiler/build/win32/Tracy.vcxproj.filters b/profiler/build/win32/Tracy.vcxproj.filters index c233fda0..a0f18cf7 100644 --- a/profiler/build/win32/Tracy.vcxproj.filters +++ b/profiler/build/win32/Tracy.vcxproj.filters @@ -357,6 +357,9 @@ server + + server + @@ -725,6 +728,9 @@ common + + server + diff --git a/server/TracyTimelineItem.cpp b/server/TracyTimelineItem.cpp new file mode 100644 index 00000000..38fd2d41 --- /dev/null +++ b/server/TracyTimelineItem.cpp @@ -0,0 +1,156 @@ +#include + +#include "TracyImGui.hpp" +#include "TracyMouse.hpp" +#include "TracyTimelineItem.hpp" +#include "TracyView.hpp" + +namespace tracy +{ + +TimelineItem::TimelineItem( View& view, const Worker& worker ) + : m_visible( true ) + , m_showFull( true ) + , m_height( 0 ) + , m_offset( 0 ) + , m_view( view ) + , m_worker( worker ) +{ +} + +void TimelineItem::Draw( bool firstFrame, double pxns, int& offset, const ImVec2& wpos, bool hover, float yMin, float yMax ) +{ + if( !m_visible ) + { + m_height = 0; + m_offset = 0; + return; + } + if( IsEmpty() ) return; + + const auto w = ImGui::GetContentRegionAvail().x - 1; + const auto ty = ImGui::GetTextLineHeight(); + const auto yPos = AdjustThreadPosition( wpos.y, offset ); + 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 ); + + float labelWidth; + const bool drawHeader = yPos + ty >= yMin && yPos <= yMax; + if( drawHeader ) + { + const auto to = 9.f; + const auto th = ( ty - to ) * sqrt( 3 ) * 0.5; + + const auto color = HeaderColor(); + const auto colorInactive = HeaderColorInactive(); + + if( m_showFull ) + { + draw->AddTriangleFilled( wpos + ImVec2( to/2, offset + to/2 ), wpos + ImVec2( ty - to/2, offset + to/2 ), wpos + ImVec2( ty * 0.5, offset + to/2 + th ), color ); + } + else + { + draw->AddTriangle( wpos + ImVec2( to/2, offset + to/2 ), wpos + ImVec2( to/2, offset + ty - to/2 ), wpos + ImVec2( to/2 + th, offset + ty * 0.5 ), colorInactive, 2.0f ); + } + const auto label = HeaderLabel(); + labelWidth = ImGui::CalcTextSize( label ).x; + DrawTextContrast( draw, wpos + ImVec2( ty, offset ), m_showFull ? color : colorInactive, label ); + DrawLine( draw, dpos + ImVec2( 0, offset + ty - 1 ), dpos + ImVec2( w, offset + ty - 1 ), 0x8844DDDD ); + + if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( 0, offset ), wpos + ImVec2( ty + labelWidth, offset + ty ) ) ) + { + HeaderTooltip( label ); + + if( IsMouseClicked( 0 ) ) + { + m_showFull = !m_showFull; + } + if( IsMouseClicked( 2 ) ) + { + m_view.ZoomToRange( RangeBegin(), RangeEnd() ); + } + if( IsMouseClicked( 1 ) ) + { + ImGui::OpenPopup( "menuPopup" ); + } + } + } + + if( ImGui::BeginPopup( "menuPopup" ) ) + { + if( ImGui::MenuItem( ICON_FA_EYE_SLASH " Hide" ) ) + { + m_visible = false; + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + + auto hdrOffset = offset; + offset += ty; + if( m_showFull ) + { + DrawContents( pxns, offset, wpos, hover, yMin, yMax ); + if( drawHeader ) + { + HeaderExtraContents( hdrOffset, wpos, labelWidth ); + } + } + + offset += 0.2 * ty; + AdjustThreadHeight( firstFrame, oldOffset, offset ); + + ImGui::PopClipRect(); + ImGui::PopID(); +} + +void TimelineItem::AdjustThreadHeight( bool firstFrame, int oldOffset, int& offset ) +{ + const auto h = offset - oldOffset; + if( m_height > h ) + { + m_height = h; + offset = oldOffset + m_height; + } + else if( m_height < h ) + { + if( firstFrame ) + { + m_height = h; + offset = oldOffset + h; + } + else + { + const auto diff = h - m_height; + const auto move = std::max( 2.0, diff * 10.0 * ImGui::GetIO().DeltaTime ); + m_height = int( std::min( m_height + move, h ) ); + offset = oldOffset + m_height; + } + } +} + +float TimelineItem::AdjustThreadPosition( float wy, int& offset ) +{ + if( m_offset < offset ) + { + m_offset = offset; + } + else if( m_offset > offset ) + { + const auto diff = m_offset - offset; + const auto move = std::max( 2.0, diff * 10.0 * ImGui::GetIO().DeltaTime ); + offset = m_offset = int( std::max( m_offset - move, offset ) ); + } + return offset + wy; +} + +void TimelineItem::VisibilityCheckbox() +{ + SmallCheckbox( HeaderLabel(), &m_visible ); +} + +} diff --git a/server/TracyTimelineItem.hpp b/server/TracyTimelineItem.hpp new file mode 100644 index 00000000..ef9d7a4e --- /dev/null +++ b/server/TracyTimelineItem.hpp @@ -0,0 +1,55 @@ +#ifndef __TRACYTIMELINEITEM_HPP__ +#define __TRACYTIMELINEITEM_HPP__ + +#include + +#include "imgui.h" + +namespace tracy +{ + +class View; +class Worker; + +class TimelineItem +{ +public: + TimelineItem( View& view, const Worker& worker ); + virtual ~TimelineItem() = default; + + void Draw( bool firstFrame, double pxns, int& offset, const ImVec2& wpos, bool hover, float yMin, float yMax ); + virtual void DrawContents( double pxns, int& offset, const ImVec2& wpos, bool hover, float yMin, float yMax ) = 0; + + virtual bool IsEmpty() const { return false; } + + void VisibilityCheckbox(); + +protected: + virtual uint32_t HeaderColor() const = 0; + virtual uint32_t HeaderColorInactive() const = 0; + virtual uint32_t HeaderLineColor() const = 0; + virtual const char* HeaderLabel() const = 0; + + virtual void HeaderTooltip( const char* label ) const {}; + virtual void HeaderExtraContents( int offset, const ImVec2& wpos, float labelWidth ) {}; + + virtual int64_t RangeBegin() const = 0; + virtual int64_t RangeEnd() const = 0; + +private: + void AdjustThreadHeight( bool firstFrame, int oldOffset, int& offset ); + float AdjustThreadPosition( float wy, int& offset ); + + bool m_visible; + bool m_showFull; + int m_height; + int m_offset; + +protected: + View& m_view; + const Worker& m_worker; +}; + +} + +#endif