diff --git a/profiler/build/win32/Tracy.vcxproj b/profiler/build/win32/Tracy.vcxproj
index 0da1387f..7aeea162 100644
--- a/profiler/build/win32/Tracy.vcxproj
+++ b/profiler/build/win32/Tracy.vcxproj
@@ -145,6 +145,7 @@
+
diff --git a/profiler/build/win32/Tracy.vcxproj.filters b/profiler/build/win32/Tracy.vcxproj.filters
index e5b11729..fe1bdfb9 100644
--- a/profiler/build/win32/Tracy.vcxproj.filters
+++ b/profiler/build/win32/Tracy.vcxproj.filters
@@ -312,6 +312,9 @@
server
+
+ server
+
diff --git a/server/TracyView.cpp b/server/TracyView.cpp
index df36b962..8660e01c 100644
--- a/server/TracyView.cpp
+++ b/server/TracyView.cpp
@@ -59,7 +59,6 @@ namespace tracy
double s_time = 0;
enum { MinVisSize = 3 };
-enum { MinFrameSize = 5 };
static View* s_instance = nullptr;
@@ -1412,72 +1411,6 @@ void View::HandleZoneViewMouse( int64_t timespan, const ImVec2& wpos, float w, d
}
}
-void View::DrawZoneFramesHeader()
-{
- const auto wpos = ImGui::GetCursorScreenPos();
- const auto dpos = wpos + ImVec2( 0.5f, 0.5f );
- const auto w = ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize;
- auto draw = ImGui::GetWindowDrawList();
- const auto ty = ImGui::GetTextLineHeight();
- const auto ty025 = round( ty * 0.25f );
- const auto ty0375 = round( ty * 0.375f );
- const auto ty05 = round( ty * 0.5f );
-
- const auto timespan = m_vd.zvEnd - m_vd.zvStart;
- const auto pxns = w / double( timespan );
- const auto nspx = 1.0 / pxns;
- const auto scale = std::max( 0.0, round( log10( nspx ) + 2 ) );
- const auto step = pow( 10, scale );
-
- ImGui::InvisibleButton( "##zoneFrames", ImVec2( w, ty * 1.5f ) );
- TooltipIfHovered( TimeToStringExact( m_vd.zvStart + ( ImGui::GetIO().MousePos.x - wpos.x ) * nspx ) );
-
- const auto dx = step * pxns;
- double x = 0;
- int tw = 0;
- int tx = 0;
- int64_t tt = 0;
- while( x < w )
- {
- DrawLine( draw, dpos + ImVec2( x, 0 ), dpos + ImVec2( x, ty05 ), 0x66FFFFFF );
- if( tw == 0 )
- {
- char buf[128];
- auto txt = TimeToStringExact( m_vd.zvStart );
- if( m_vd.zvStart >= 0 )
- {
- sprintf( buf, "+%s", txt );
- txt = buf;
- }
- draw->AddText( wpos + ImVec2( x, ty05 ), 0x66FFFFFF, txt );
- tw = ImGui::CalcTextSize( txt ).x;
- }
- else if( x > tx + tw + ty * 2 )
- {
- tx = x;
- auto txt = TimeToString( tt );
- draw->AddText( wpos + ImVec2( x, ty05 ), 0x66FFFFFF, txt );
- tw = ImGui::CalcTextSize( txt ).x;
- }
-
- if( scale != 0 )
- {
- for( int i=1; i<5; i++ )
- {
- DrawLine( draw, dpos + ImVec2( x + i * dx / 10, 0 ), dpos + ImVec2( x + i * dx / 10, ty025 ), 0x33FFFFFF );
- }
- DrawLine( draw, dpos + ImVec2( x + 5 * dx / 10, 0 ), dpos + ImVec2( x + 5 * dx / 10, ty0375 ), 0x33FFFFFF );
- for( int i=6; i<10; i++ )
- {
- DrawLine( draw, dpos + ImVec2( x + i * dx / 10, 0 ), dpos + ImVec2( x + i * dx / 10, ty025 ), 0x33FFFFFF );
- }
- }
-
- x += dx;
- tt += step;
- }
-}
-
static uint32_t MixGhostColor( uint32_t c0, uint32_t c1 )
{
return 0xFF000000 |
@@ -1486,257 +1419,6 @@ static uint32_t MixGhostColor( uint32_t c0, uint32_t c1 )
( ( ( ( ( c0 & 0x000000FF ) ) + 3 * ( ( c1 & 0x000000FF ) ) ) >> 2 ) );
}
-static uint32_t GetColorMuted( uint32_t color, bool active )
-{
- if( active )
- {
- return 0xFF000000 | color;
- }
- else
- {
- return 0x66000000 | color;
- }
-}
-
-void View::DrawZoneFrames( const FrameData& frames )
-{
- const auto wpos = ImGui::GetCursorScreenPos();
- const auto dpos = wpos + ImVec2( 0.5f, 0.5f );
- const auto w = ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize;
- const auto wh = ImGui::GetContentRegionAvail().y;
- auto draw = ImGui::GetWindowDrawList();
- const auto ty = ImGui::GetTextLineHeight();
- const auto ty025 = ty * 0.25f;
- const auto ty05 = round( ty * 0.5f );
-
- ImGui::InvisibleButton( "##zoneFrames", ImVec2( w, ty ) );
- bool hover = ImGui::IsItemHovered();
-
- auto timespan = m_vd.zvEnd - m_vd.zvStart;
- auto pxns = w / double( timespan );
-
- const auto nspx = 1.0 / pxns;
-
- const std::pair zrange = m_worker.GetFrameRange( frames, m_vd.zvStart, m_vd.zvEnd );
- if( zrange.first < 0 ) return;
-
- int64_t prev = -1;
- int64_t prevEnd = -1;
- int64_t endPos = -1;
- bool tooltipDisplayed = false;
- const auto activeFrameSet = m_frames == &frames;
- const int64_t frameTarget = ( activeFrameSet && m_vd.drawFrameTargets ) ? 1000000000ll / m_vd.frameTarget : std::numeric_limits::max();
-
- const auto inactiveColor = GetColorMuted( 0x888888, activeFrameSet );
- const auto activeColor = GetColorMuted( 0xFFFFFF, activeFrameSet );
- const auto redColor = GetColorMuted( 0x4444FF, activeFrameSet );
-
- int i = zrange.first;
- auto x1 = ( m_worker.GetFrameBegin( frames, i ) - m_vd.zvStart ) * pxns;
- while( i < zrange.second )
- {
- const auto ftime = m_worker.GetFrameTime( frames, i );
- const auto fbegin = m_worker.GetFrameBegin( frames, i );
- const auto fend = m_worker.GetFrameEnd( frames, i );
- const auto fsz = pxns * ftime;
-
- if( hover )
- {
- const auto x0 = frames.continuous ? x1 : ( fbegin - m_vd.zvStart ) * pxns;
- x1 = ( fend - m_vd.zvStart ) * pxns;
- if( ImGui::IsMouseHoveringRect( wpos + ImVec2( x0, 0 ), wpos + ImVec2( x1, ty ) ) )
- {
- tooltipDisplayed = true;
- if( IsMouseClickReleased( 1 ) ) m_setRangePopup = RangeSlim { fbegin, fend, true };
-
- ImGui::BeginTooltip();
- ImGui::TextUnformatted( GetFrameText( frames, i, ftime, m_worker.GetFrameOffset() ) );
- ImGui::SameLine();
- ImGui::TextDisabled( "(%.1f FPS)", 1000000000.0 / ftime );
- TextFocused( "Time from start of program:", TimeToStringExact( m_worker.GetFrameBegin( frames, i ) ) );
- auto fi = m_worker.GetFrameImage( frames, i );
- if( fi )
- {
- const auto scale = GetScale();
- if( fi != m_frameTexturePtr )
- {
- if( !m_frameTexture ) m_frameTexture = MakeTexture();
- UpdateTexture( m_frameTexture, m_worker.UnpackFrameImage( *fi ), fi->w, fi->h );
- m_frameTexturePtr = fi;
- }
- ImGui::Separator();
- if( fi->flip )
- {
- ImGui::Image( m_frameTexture, ImVec2( fi->w * scale, fi->h * scale ), ImVec2( 0, 1 ), ImVec2( 1, 0 ) );
- }
- else
- {
- ImGui::Image( m_frameTexture, ImVec2( fi->w * scale, fi->h * scale ) );
- }
-
- if( ImGui::GetIO().KeyCtrl && IsMouseClicked( 0 ) )
- {
- m_showPlayback = true;
- m_playback.pause = true;
- SetPlaybackFrame( frames.frames[i].frameImage );
- }
- }
- ImGui::EndTooltip();
-
- if( IsMouseClicked( 2 ) )
- {
- ZoomToRange( fbegin, fend );
- }
-
- if( activeFrameSet ) m_frameHover = i;
- }
- }
-
- if( fsz < MinFrameSize )
- {
- if( !frames.continuous && prev != -1 )
- {
- if( ( fbegin - prevEnd ) * pxns >= MinFrameSize )
- {
- DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), ( prev - m_vd.zvStart ) * pxns, ( prevEnd - m_vd.zvStart ) * pxns, ty025, inactiveColor );
- prev = -1;
- }
- else
- {
- prevEnd = std::max( fend, fbegin + MinFrameSize * nspx );
- }
- }
- if( prev == -1 )
- {
- prev = fbegin;
- prevEnd = std::max( fend, fbegin + MinFrameSize * nspx );
- }
-
- const auto begin = frames.frames.begin() + i;
- const auto end = frames.frames.begin() + zrange.second;
- auto it = std::lower_bound( begin, end, int64_t( fbegin + MinVisSize * nspx ), [this, &frames] ( const auto& l, const auto& r ) { return m_worker.GetFrameEnd( frames, std::distance( frames.frames.begin(), &l ) ) < r; } );
- if( it == begin ) ++it;
- i += std::distance( begin, it );
- continue;
- }
-
- if( prev != -1 )
- {
- if( frames.continuous )
- {
- DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), ( prev - m_vd.zvStart ) * pxns, ( fbegin - m_vd.zvStart ) * pxns, ty025, inactiveColor );
- }
- else
- {
- DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), ( prev - m_vd.zvStart ) * pxns, ( prevEnd - m_vd.zvStart ) * pxns, ty025, inactiveColor );
- }
- prev = -1;
- }
-
- if( activeFrameSet )
- {
- if( fend - fbegin > frameTarget )
- {
- draw->AddRectFilled( wpos + ImVec2( ( fbegin + frameTarget - m_vd.zvStart ) * pxns, 0 ), wpos + ImVec2( ( fend - m_vd.zvStart ) * pxns, wh ), 0x224444FF );
- }
- if( fbegin >= m_vd.zvStart && endPos != fbegin )
- {
- DrawLine( draw, dpos + ImVec2( ( fbegin - m_vd.zvStart ) * pxns, 0 ), dpos + ImVec2( ( fbegin - m_vd.zvStart ) * pxns, wh ), 0x22FFFFFF );
- }
- if( fend <= m_vd.zvEnd )
- {
- DrawLine( draw, dpos + ImVec2( ( fend - m_vd.zvStart ) * pxns, 0 ), dpos + ImVec2( ( fend - m_vd.zvStart ) * pxns, wh ), 0x22FFFFFF );
- }
- endPos = fend;
- }
-
- auto buf = GetFrameText( frames, i, ftime, m_worker.GetFrameOffset() );
- auto tx = ImGui::CalcTextSize( buf ).x;
- uint32_t color = ( frames.name == 0 && i == 0 ) ? redColor : activeColor;
-
- if( fsz - 7 <= tx )
- {
- static char tmp[256];
- sprintf( tmp, "%s (%s)", RealToString( i ), TimeToString( ftime ) );
- buf = tmp;
- tx = ImGui::CalcTextSize( buf ).x;
- }
- if( fsz - 7 <= tx )
- {
- buf = TimeToString( ftime );
- tx = ImGui::CalcTextSize( buf ).x;
- }
-
- if( fbegin >= m_vd.zvStart )
- {
- DrawLine( draw, dpos + ImVec2( ( fbegin - m_vd.zvStart ) * pxns + 2, 1 ), dpos + ImVec2( ( fbegin - m_vd.zvStart ) * pxns + 2, ty - 1 ), color );
- }
- if( fend <= m_vd.zvEnd )
- {
- DrawLine( draw, dpos + ImVec2( ( fend - m_vd.zvStart ) * pxns - 2, 1 ), dpos + ImVec2( ( fend - m_vd.zvStart ) * pxns - 2, ty - 1 ), color );
- }
- if( fsz - 7 > tx )
- {
- const auto f0 = ( fbegin - m_vd.zvStart ) * pxns + 2;
- const auto f1 = ( fend - m_vd.zvStart ) * pxns - 2;
- const auto x0 = f0 + 1;
- const auto x1 = f1 - 1;
- const auto te = x1 - tx;
-
- auto tpos = ( x0 + te ) / 2;
- if( tpos < 0 )
- {
- tpos = std::min( std::min( 0., te - tpos ), te );
- }
- else if( tpos > w - tx )
- {
- tpos = std::max( double( w - tx ), x0 );
- }
- tpos = round( tpos );
-
- DrawLine( draw, dpos + ImVec2( std::max( -10.0, f0 ), ty05 ), dpos + ImVec2( tpos, ty05 ), color );
- DrawLine( draw, dpos + ImVec2( std::max( -10.0, tpos + tx + 1 ), ty05 ), dpos + ImVec2( std::min( w + 20.0, f1 ), ty05 ), color );
- draw->AddText( wpos + ImVec2( tpos, 0 ), color, buf );
- }
- else
- {
- DrawLine( draw, dpos + ImVec2( std::max( -10.0, ( fbegin - m_vd.zvStart ) * pxns + 2 ), ty05 ), dpos + ImVec2( std::min( w + 20.0, ( fend - m_vd.zvStart ) * pxns - 2 ), ty05 ), color );
- }
-
- i++;
- }
-
- if( prev != -1 )
- {
- if( frames.continuous )
- {
- DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), ( prev - m_vd.zvStart ) * pxns, ( m_worker.GetFrameBegin( frames, zrange.second-1 ) - m_vd.zvStart ) * pxns, ty025, inactiveColor );
- }
- else
- {
- const auto begin = ( prev - m_vd.zvStart ) * pxns;
- const auto end = ( m_worker.GetFrameBegin( frames, zrange.second-1 ) - m_vd.zvStart ) * pxns;
- DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), begin, std::max( begin + MinFrameSize, end ), ty025, inactiveColor );
- }
- }
-
- if( hover )
- {
- if( !tooltipDisplayed )
- {
- ImGui::BeginTooltip();
- TextDisabledUnformatted( "Frame set:" );
- ImGui::SameLine();
- ImGui::TextUnformatted( frames.name == 0 ? "Frames" : m_worker.GetString( frames.name ) );
- ImGui::EndTooltip();
- }
- if( IsMouseClicked( 0 ) )
- {
- m_frames = &frames;
- }
- }
-}
-
float View::AdjustThreadPosition( View::VisData& vis, float wy, int& offset )
{
if( vis.offset < offset )
diff --git a/server/TracyView_FrameTimeline.cpp b/server/TracyView_FrameTimeline.cpp
new file mode 100644
index 00000000..b3d51bcf
--- /dev/null
+++ b/server/TracyView_FrameTimeline.cpp
@@ -0,0 +1,330 @@
+#include
+
+#include "TracyMouse.hpp"
+#include "TracyPrint.hpp"
+#include "TracyView.hpp"
+
+namespace tracy
+{
+
+enum { MinVisSize = 3 };
+enum { MinFrameSize = 5 };
+
+static tracy_force_inline uint32_t GetColorMuted( uint32_t color, bool active )
+{
+ if( active )
+ {
+ return 0xFF000000 | color;
+ }
+ else
+ {
+ return 0x66000000 | color;
+ }
+}
+
+void View::DrawZoneFramesHeader()
+{
+ const auto wpos = ImGui::GetCursorScreenPos();
+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );
+ const auto w = ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize;
+ auto draw = ImGui::GetWindowDrawList();
+ const auto ty = ImGui::GetTextLineHeight();
+ const auto ty025 = round( ty * 0.25f );
+ const auto ty0375 = round( ty * 0.375f );
+ const auto ty05 = round( ty * 0.5f );
+
+ const auto timespan = m_vd.zvEnd - m_vd.zvStart;
+ const auto pxns = w / double( timespan );
+ const auto nspx = 1.0 / pxns;
+ const auto scale = std::max( 0.0, round( log10( nspx ) + 2 ) );
+ const auto step = pow( 10, scale );
+
+ ImGui::InvisibleButton( "##zoneFrames", ImVec2( w, ty * 1.5f ) );
+ TooltipIfHovered( TimeToStringExact( m_vd.zvStart + ( ImGui::GetIO().MousePos.x - wpos.x ) * nspx ) );
+
+ const auto dx = step * pxns;
+ double x = 0;
+ int tw = 0;
+ int tx = 0;
+ int64_t tt = 0;
+ while( x < w )
+ {
+ DrawLine( draw, dpos + ImVec2( x, 0 ), dpos + ImVec2( x, ty05 ), 0x66FFFFFF );
+ if( tw == 0 )
+ {
+ char buf[128];
+ auto txt = TimeToStringExact( m_vd.zvStart );
+ if( m_vd.zvStart >= 0 )
+ {
+ sprintf( buf, "+%s", txt );
+ txt = buf;
+ }
+ draw->AddText( wpos + ImVec2( x, ty05 ), 0x66FFFFFF, txt );
+ tw = ImGui::CalcTextSize( txt ).x;
+ }
+ else if( x > tx + tw + ty * 2 )
+ {
+ tx = x;
+ auto txt = TimeToString( tt );
+ draw->AddText( wpos + ImVec2( x, ty05 ), 0x66FFFFFF, txt );
+ tw = ImGui::CalcTextSize( txt ).x;
+ }
+
+ if( scale != 0 )
+ {
+ for( int i=1; i<5; i++ )
+ {
+ DrawLine( draw, dpos + ImVec2( x + i * dx / 10, 0 ), dpos + ImVec2( x + i * dx / 10, ty025 ), 0x33FFFFFF );
+ }
+ DrawLine( draw, dpos + ImVec2( x + 5 * dx / 10, 0 ), dpos + ImVec2( x + 5 * dx / 10, ty0375 ), 0x33FFFFFF );
+ for( int i=6; i<10; i++ )
+ {
+ DrawLine( draw, dpos + ImVec2( x + i * dx / 10, 0 ), dpos + ImVec2( x + i * dx / 10, ty025 ), 0x33FFFFFF );
+ }
+ }
+
+ x += dx;
+ tt += step;
+ }
+}
+
+void View::DrawZoneFrames( const FrameData& frames )
+{
+ const auto wpos = ImGui::GetCursorScreenPos();
+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );
+ const auto w = ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize;
+ const auto wh = ImGui::GetContentRegionAvail().y;
+ auto draw = ImGui::GetWindowDrawList();
+ const auto ty = ImGui::GetTextLineHeight();
+ const auto ty025 = ty * 0.25f;
+ const auto ty05 = round( ty * 0.5f );
+
+ ImGui::InvisibleButton( "##zoneFrames", ImVec2( w, ty ) );
+ bool hover = ImGui::IsItemHovered();
+
+ auto timespan = m_vd.zvEnd - m_vd.zvStart;
+ auto pxns = w / double( timespan );
+
+ const auto nspx = 1.0 / pxns;
+
+ const std::pair zrange = m_worker.GetFrameRange( frames, m_vd.zvStart, m_vd.zvEnd );
+ if( zrange.first < 0 ) return;
+
+ int64_t prev = -1;
+ int64_t prevEnd = -1;
+ int64_t endPos = -1;
+ bool tooltipDisplayed = false;
+ const auto activeFrameSet = m_frames == &frames;
+ const int64_t frameTarget = ( activeFrameSet && m_vd.drawFrameTargets ) ? 1000000000ll / m_vd.frameTarget : std::numeric_limits::max();
+
+ const auto inactiveColor = GetColorMuted( 0x888888, activeFrameSet );
+ const auto activeColor = GetColorMuted( 0xFFFFFF, activeFrameSet );
+ const auto redColor = GetColorMuted( 0x4444FF, activeFrameSet );
+
+ int i = zrange.first;
+ auto x1 = ( m_worker.GetFrameBegin( frames, i ) - m_vd.zvStart ) * pxns;
+ while( i < zrange.second )
+ {
+ const auto ftime = m_worker.GetFrameTime( frames, i );
+ const auto fbegin = m_worker.GetFrameBegin( frames, i );
+ const auto fend = m_worker.GetFrameEnd( frames, i );
+ const auto fsz = pxns * ftime;
+
+ if( hover )
+ {
+ const auto x0 = frames.continuous ? x1 : ( fbegin - m_vd.zvStart ) * pxns;
+ x1 = ( fend - m_vd.zvStart ) * pxns;
+ if( ImGui::IsMouseHoveringRect( wpos + ImVec2( x0, 0 ), wpos + ImVec2( x1, ty ) ) )
+ {
+ tooltipDisplayed = true;
+ if( IsMouseClickReleased( 1 ) ) m_setRangePopup = RangeSlim { fbegin, fend, true };
+
+ ImGui::BeginTooltip();
+ ImGui::TextUnformatted( GetFrameText( frames, i, ftime, m_worker.GetFrameOffset() ) );
+ ImGui::SameLine();
+ ImGui::TextDisabled( "(%.1f FPS)", 1000000000.0 / ftime );
+ TextFocused( "Time from start of program:", TimeToStringExact( m_worker.GetFrameBegin( frames, i ) ) );
+ auto fi = m_worker.GetFrameImage( frames, i );
+ if( fi )
+ {
+ const auto scale = GetScale();
+ if( fi != m_frameTexturePtr )
+ {
+ if( !m_frameTexture ) m_frameTexture = MakeTexture();
+ UpdateTexture( m_frameTexture, m_worker.UnpackFrameImage( *fi ), fi->w, fi->h );
+ m_frameTexturePtr = fi;
+ }
+ ImGui::Separator();
+ if( fi->flip )
+ {
+ ImGui::Image( m_frameTexture, ImVec2( fi->w * scale, fi->h * scale ), ImVec2( 0, 1 ), ImVec2( 1, 0 ) );
+ }
+ else
+ {
+ ImGui::Image( m_frameTexture, ImVec2( fi->w * scale, fi->h * scale ) );
+ }
+
+ if( ImGui::GetIO().KeyCtrl && IsMouseClicked( 0 ) )
+ {
+ m_showPlayback = true;
+ m_playback.pause = true;
+ SetPlaybackFrame( frames.frames[i].frameImage );
+ }
+ }
+ ImGui::EndTooltip();
+
+ if( IsMouseClicked( 2 ) )
+ {
+ ZoomToRange( fbegin, fend );
+ }
+
+ if( activeFrameSet ) m_frameHover = i;
+ }
+ }
+
+ if( fsz < MinFrameSize )
+ {
+ if( !frames.continuous && prev != -1 )
+ {
+ if( ( fbegin - prevEnd ) * pxns >= MinFrameSize )
+ {
+ DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), ( prev - m_vd.zvStart ) * pxns, ( prevEnd - m_vd.zvStart ) * pxns, ty025, inactiveColor );
+ prev = -1;
+ }
+ else
+ {
+ prevEnd = std::max( fend, fbegin + MinFrameSize * nspx );
+ }
+ }
+ if( prev == -1 )
+ {
+ prev = fbegin;
+ prevEnd = std::max( fend, fbegin + MinFrameSize * nspx );
+ }
+
+ const auto begin = frames.frames.begin() + i;
+ const auto end = frames.frames.begin() + zrange.second;
+ auto it = std::lower_bound( begin, end, int64_t( fbegin + MinVisSize * nspx ), [this, &frames] ( const auto& l, const auto& r ) { return m_worker.GetFrameEnd( frames, std::distance( frames.frames.begin(), &l ) ) < r; } );
+ if( it == begin ) ++it;
+ i += std::distance( begin, it );
+ continue;
+ }
+
+ if( prev != -1 )
+ {
+ if( frames.continuous )
+ {
+ DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), ( prev - m_vd.zvStart ) * pxns, ( fbegin - m_vd.zvStart ) * pxns, ty025, inactiveColor );
+ }
+ else
+ {
+ DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), ( prev - m_vd.zvStart ) * pxns, ( prevEnd - m_vd.zvStart ) * pxns, ty025, inactiveColor );
+ }
+ prev = -1;
+ }
+
+ if( activeFrameSet )
+ {
+ if( fend - fbegin > frameTarget )
+ {
+ draw->AddRectFilled( wpos + ImVec2( ( fbegin + frameTarget - m_vd.zvStart ) * pxns, 0 ), wpos + ImVec2( ( fend - m_vd.zvStart ) * pxns, wh ), 0x224444FF );
+ }
+ if( fbegin >= m_vd.zvStart && endPos != fbegin )
+ {
+ DrawLine( draw, dpos + ImVec2( ( fbegin - m_vd.zvStart ) * pxns, 0 ), dpos + ImVec2( ( fbegin - m_vd.zvStart ) * pxns, wh ), 0x22FFFFFF );
+ }
+ if( fend <= m_vd.zvEnd )
+ {
+ DrawLine( draw, dpos + ImVec2( ( fend - m_vd.zvStart ) * pxns, 0 ), dpos + ImVec2( ( fend - m_vd.zvStart ) * pxns, wh ), 0x22FFFFFF );
+ }
+ endPos = fend;
+ }
+
+ auto buf = GetFrameText( frames, i, ftime, m_worker.GetFrameOffset() );
+ auto tx = ImGui::CalcTextSize( buf ).x;
+ uint32_t color = ( frames.name == 0 && i == 0 ) ? redColor : activeColor;
+
+ if( fsz - 7 <= tx )
+ {
+ static char tmp[256];
+ sprintf( tmp, "%s (%s)", RealToString( i ), TimeToString( ftime ) );
+ buf = tmp;
+ tx = ImGui::CalcTextSize( buf ).x;
+ }
+ if( fsz - 7 <= tx )
+ {
+ buf = TimeToString( ftime );
+ tx = ImGui::CalcTextSize( buf ).x;
+ }
+
+ if( fbegin >= m_vd.zvStart )
+ {
+ DrawLine( draw, dpos + ImVec2( ( fbegin - m_vd.zvStart ) * pxns + 2, 1 ), dpos + ImVec2( ( fbegin - m_vd.zvStart ) * pxns + 2, ty - 1 ), color );
+ }
+ if( fend <= m_vd.zvEnd )
+ {
+ DrawLine( draw, dpos + ImVec2( ( fend - m_vd.zvStart ) * pxns - 2, 1 ), dpos + ImVec2( ( fend - m_vd.zvStart ) * pxns - 2, ty - 1 ), color );
+ }
+ if( fsz - 7 > tx )
+ {
+ const auto f0 = ( fbegin - m_vd.zvStart ) * pxns + 2;
+ const auto f1 = ( fend - m_vd.zvStart ) * pxns - 2;
+ const auto x0 = f0 + 1;
+ const auto x1 = f1 - 1;
+ const auto te = x1 - tx;
+
+ auto tpos = ( x0 + te ) / 2;
+ if( tpos < 0 )
+ {
+ tpos = std::min( std::min( 0., te - tpos ), te );
+ }
+ else if( tpos > w - tx )
+ {
+ tpos = std::max( double( w - tx ), x0 );
+ }
+ tpos = round( tpos );
+
+ DrawLine( draw, dpos + ImVec2( std::max( -10.0, f0 ), ty05 ), dpos + ImVec2( tpos, ty05 ), color );
+ DrawLine( draw, dpos + ImVec2( std::max( -10.0, tpos + tx + 1 ), ty05 ), dpos + ImVec2( std::min( w + 20.0, f1 ), ty05 ), color );
+ draw->AddText( wpos + ImVec2( tpos, 0 ), color, buf );
+ }
+ else
+ {
+ DrawLine( draw, dpos + ImVec2( std::max( -10.0, ( fbegin - m_vd.zvStart ) * pxns + 2 ), ty05 ), dpos + ImVec2( std::min( w + 20.0, ( fend - m_vd.zvStart ) * pxns - 2 ), ty05 ), color );
+ }
+
+ i++;
+ }
+
+ if( prev != -1 )
+ {
+ if( frames.continuous )
+ {
+ DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), ( prev - m_vd.zvStart ) * pxns, ( m_worker.GetFrameBegin( frames, zrange.second-1 ) - m_vd.zvStart ) * pxns, ty025, inactiveColor );
+ }
+ else
+ {
+ const auto begin = ( prev - m_vd.zvStart ) * pxns;
+ const auto end = ( m_worker.GetFrameBegin( frames, zrange.second-1 ) - m_vd.zvStart ) * pxns;
+ DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), begin, std::max( begin + MinFrameSize, end ), ty025, inactiveColor );
+ }
+ }
+
+ if( hover )
+ {
+ if( !tooltipDisplayed )
+ {
+ ImGui::BeginTooltip();
+ TextDisabledUnformatted( "Frame set:" );
+ ImGui::SameLine();
+ ImGui::TextUnformatted( frames.name == 0 ? "Frames" : m_worker.GetString( frames.name ) );
+ ImGui::EndTooltip();
+ }
+ if( IsMouseClicked( 0 ) )
+ {
+ m_frames = &frames;
+ }
+ }
+}
+
+}