diff --git a/profiler/CMakeLists.txt b/profiler/CMakeLists.txt index 7825af70..1681a64b 100644 --- a/profiler/CMakeLists.txt +++ b/profiler/CMakeLists.txt @@ -98,6 +98,7 @@ set(SERVER_FILES TracyView_FrameTree.cpp TracyView_GpuTimeline.cpp TracyView_Locks.cpp + TracyView_Manual.cpp TracyView_Memory.cpp TracyView_Messages.cpp TracyView_Navigation.cpp diff --git a/profiler/src/profiler/TracyView.cpp b/profiler/src/profiler/TracyView.cpp index ceb4fd84..5ffbdf4d 100644 --- a/profiler/src/profiler/TracyView.cpp +++ b/profiler/src/profiler/TracyView.cpp @@ -944,6 +944,8 @@ bool View::DrawImpl() } ImGui::EndPopup(); } + ImGui::SameLine(); + ToggleButton( ICON_FA_BOOK, m_showManual ); if( m_sscb ) { ImGui::SameLine(); @@ -1167,6 +1169,7 @@ bool View::DrawImpl() if( m_sampleParents.symAddr != 0 ) DrawSampleParents(); if( m_showRanges ) DrawRanges(); if( m_showWaitStacks ) DrawWaitStacks(); + if( m_showManual ) DrawManual(); #ifndef __EMSCRIPTEN__ if( m_llm.m_show ) m_llm.Draw(); #endif diff --git a/profiler/src/profiler/TracyView.hpp b/profiler/src/profiler/TracyView.hpp index 452d0dea..c76e8302 100644 --- a/profiler/src/profiler/TracyView.hpp +++ b/profiler/src/profiler/TracyView.hpp @@ -18,6 +18,7 @@ #include "TracyBuzzAnim.hpp" #include "TracyConfig.hpp" #include "TracyDecayValue.hpp" +#include "TracyMarkdown.hpp" #include "TracySourceContents.hpp" #include "TracyTimelineController.hpp" #include "TracyUserData.hpp" @@ -290,6 +291,7 @@ private: void DrawRangeEntry( Range& range, const char* label, uint32_t color, const char* popupLabel, int id ); void DrawSourceTooltip( const char* filename, uint32_t line, int before = 3, int after = 3, bool separateTooltip = true ); void DrawWaitStacks(); + void DrawManual(); void DrawFlameGraph(); void DrawFlameGraphHeader( uint64_t timespan ); void DrawFlameGraphLevel( const std::vector& data, FlameGraphContext& ctx, int depth, bool samples ); @@ -531,6 +533,7 @@ private: bool m_showAnnotationList = false; bool m_showWaitStacks = false; bool m_showFlameGraph = false; + bool m_showManual = false; AccumulationMode m_statAccumulationMode = AccumulationMode::SelfOnly; bool m_statSampleTime = true; @@ -931,6 +934,8 @@ private: double m_verticalScrollMultiplier = 1.0; std::shared_ptr m_manualData; + size_t m_activeManualChunk = 0; + Markdown m_markdown; TaskDispatch m_td; std::vector m_flameGraphData; diff --git a/profiler/src/profiler/TracyView_Manual.cpp b/profiler/src/profiler/TracyView_Manual.cpp new file mode 100644 index 00000000..28a8442d --- /dev/null +++ b/profiler/src/profiler/TracyView_Manual.cpp @@ -0,0 +1,90 @@ +#include +#include + +#include "TracyImGui.hpp" +#include "TracyManualData.hpp" +#include "TracyMarkdown.hpp" +#include "TracyView.hpp" + +namespace tracy +{ + +void View::DrawManual() +{ + const auto scale = GetScale(); + ImGui::SetNextWindowSize( ImVec2( 1200 * scale, 800 * scale ), ImGuiCond_Always ); + ImGui::Begin( "User manual", &m_showManual ); + if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; } + + ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.f, 1.f, 0.f, 1.0f ) ); + ImGui::AlignTextToFramePadding(); + ImGui::TextWrapped( ICON_FA_TRIANGLE_EXCLAMATION ); + ImGui::PopStyleColor(); + ImGui::SameLine(); + TextDisabledUnformatted( "This user manual is missing features. See the PDF file for the proper version." ); + + ImGui::Separator(); + ImGui::BeginChild( "##usermanual" ); + + ImGui::Columns( 2 ); + static bool widthSet = false; + if( !widthSet ) + { + widthSet = true; + ImGui::SetColumnWidth( 0, 350 * scale ); + } + + ImGui::BeginChild( "##toc", ImVec2( 0, 0 ), ImGuiChildFlags_AlwaysUseWindowPadding ); + int level = 0; + auto& chunks = m_manualData->GetChunks(); + assert( !chunks.empty() ); + for( size_t i=0; i level ) continue; + + char tmp[1024]; + if( chunk.section.empty() ) + { + snprintf( tmp, 1024, "%s", chunk.title.c_str() ); + } + else + { + snprintf( tmp, 1024, "%s. %s", chunk.section.c_str(), chunk.title.c_str() ); + } + + while( level > chunk.level ) + { + ImGui::TreePop(); + level--; + } + + ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth; + const bool isLeaf = i == ( chunks.size() - 1 ) || chunks[i+1].level <= chunk.level; + if( isLeaf ) flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; + if( i == m_activeManualChunk ) flags |= ImGuiTreeNodeFlags_Selected; + if( ImGui::TreeNodeEx( tmp, flags ) ) + { + if( !isLeaf ) level++; + } + if( ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen() ) + { + m_activeManualChunk = i; + } + } + while( level-- > 0 ) ImGui::TreePop(); + + ImGui::EndChild(); + ImGui::NextColumn(); + ImGui::BeginChild( "##content", ImVec2( 0, 0 ), ImGuiChildFlags_AlwaysUseWindowPadding ); + + auto& chunk = chunks[m_activeManualChunk]; + m_markdown.Print( chunk.text.c_str(), chunk.text.size() ); + + ImGui::EndChild(); + ImGui::EndColumns(); + ImGui::EndChild(); + ImGui::End(); +} + +}