studio: replace separate Solver and Performance charts with a unified Profiler, bound to F3
Combines the "Solver" and "Performance" chart windows into a single "Profiler" window for better ergonomics and visual layout: - Unified Dashboard: Groups the Solver block (Counts & Convergence) and the Performance block (Dimensions & CPU Time) in a single viewable window that scales cleanly without vertical scrollbars. - Adaptive Stacking: Uses ImGui grouping so each block internally stacks its charts vertically, but tiles side-by-side horizontally when the window is stretched wide. - Default Docking & Width: Integrates the Profiler into the default dockspace layout attached to the right of the main viewable area, with an optimized initial width scaling factor of 0.42. - Shortcut and Menus: Adds a toggle shortcut bound to `F3`, updates the Help Shortcuts overlay, and replaces old separate entries in the Charts menu. PiperOrigin-RevId: 912491435 Change-Id: I1f9215e5498866a01ce48b6aeb4a7461191fa01d
This commit is contained in:
committed by
Copybara-Service
parent
395a002801
commit
531a571dda
@@ -28,6 +28,7 @@
|
||||
#include <implot.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/platform/helpers.h"
|
||||
#include "experimental/platform/sim/sim_profiler.h"
|
||||
#include "experimental/platform/sim/step_control.h"
|
||||
#include "experimental/platform/ux/imgui_widgets.h"
|
||||
#include "experimental/platform/ux/interaction.h"
|
||||
@@ -275,6 +276,9 @@ ImVec4 ConfigureDockingLayout() {
|
||||
ImGui::DockBuilderSplitNode(inspector, ImGuiDir_Down, kStatsRelHeight,
|
||||
&properties, &inspector);
|
||||
|
||||
ImGuiID profiler = 0;
|
||||
ImGui::DockBuilderSplitNode(main, ImGuiDir_Right, 0.42f, &profiler, &main);
|
||||
|
||||
ImGui::DockBuilderDockWindow("Dockspace", main);
|
||||
ImGui::DockBuilderDockWindow("Options", options);
|
||||
ImGui::DockBuilderDockWindow("Explorer", inspector);
|
||||
@@ -282,6 +286,7 @@ ImVec4 ConfigureDockingLayout() {
|
||||
ImGui::DockBuilderDockWindow("Inspector", inspector);
|
||||
ImGui::DockBuilderDockWindow("Properties", properties);
|
||||
ImGui::DockBuilderDockWindow("Stats", stats);
|
||||
ImGui::DockBuilderDockWindow("Profiler", profiler);
|
||||
ImGui::DockBuilderFinish(root);
|
||||
}
|
||||
|
||||
@@ -1392,4 +1397,56 @@ void StatsGui(const mjModel* model, const mjData* data, bool paused,
|
||||
ImGui::Columns();
|
||||
}
|
||||
|
||||
void ProfilerGui(const mjModel* model, mjData* data, SimProfiler* profiler) {
|
||||
ImGui::SetWindowFontScale(0.8f);
|
||||
ImVec2 avail = ImGui::GetContentRegionAvail();
|
||||
const float pad = ImGui::GetStyle().ItemSpacing.x;
|
||||
const float aspect = avail.y > 0 ? avail.x / avail.y : 1.0f;
|
||||
|
||||
ImVec2 plot_size;
|
||||
int cols;
|
||||
if (aspect < 0.8f) {
|
||||
plot_size.x = avail.x;
|
||||
plot_size.y = (avail.y - pad * 3.0f) * 0.25f;
|
||||
cols = 1;
|
||||
} else if (aspect < 1.8f) {
|
||||
plot_size.x = (avail.x - pad) * 0.5f;
|
||||
plot_size.y = (avail.y - pad) * 0.5f;
|
||||
cols = 2;
|
||||
} else {
|
||||
plot_size.x = (avail.x - pad * 3.0f) * 0.25f;
|
||||
plot_size.y = avail.y;
|
||||
cols = 4;
|
||||
}
|
||||
|
||||
int current_col = 0;
|
||||
auto advance = [&]() {
|
||||
current_col++;
|
||||
if (current_col < cols) {
|
||||
ImGui::SameLine();
|
||||
} else {
|
||||
current_col = 0;
|
||||
}
|
||||
};
|
||||
|
||||
if (cols == 2) {
|
||||
// In 2x2 layout, vertically stack charts with the same x-axis.
|
||||
CountsGui(model, data, plot_size);
|
||||
advance();
|
||||
profiler->DimensionsGraph(plot_size);
|
||||
advance();
|
||||
ConvergenceGui(model, data, plot_size);
|
||||
advance();
|
||||
profiler->CpuTimeGraph(plot_size);
|
||||
} else {
|
||||
CountsGui(model, data, plot_size);
|
||||
advance();
|
||||
ConvergenceGui(model, data, plot_size);
|
||||
advance();
|
||||
profiler->DimensionsGraph(plot_size);
|
||||
advance();
|
||||
profiler->CpuTimeGraph(plot_size);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mujoco::platform
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <imgui.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/platform/sim/sim_profiler.h"
|
||||
#include "experimental/platform/sim/step_control.h"
|
||||
|
||||
namespace mujoco::platform {
|
||||
@@ -148,6 +149,9 @@ void ConvergenceGui(const mjModel* model, mjData* data,
|
||||
void CountsGui(const mjModel* model, mjData* data,
|
||||
ImVec2 plot_size = ImVec2(-1, 0));
|
||||
|
||||
// UX for Profiler panel combining Solver and Performance metrics.
|
||||
void ProfilerGui(const mjModel* model, mjData* data, SimProfiler* profiler);
|
||||
|
||||
// UX for displaying basic simulation information. Note that the pause state and
|
||||
// FPS needs to be tracked by the caller and passed here to be displayed.
|
||||
void StatsGui(const mjModel* model, const mjData* data, bool paused, float fps);
|
||||
|
||||
@@ -382,10 +382,10 @@ ImPlotFlags ImPlot_SetupPlotFlags(ImVec2 plot_size) {
|
||||
ImPlotFlags flags = ImPlotFlags_None;
|
||||
if (plot_size.x > 0 && plot_size.y > 0) {
|
||||
const float min_dim = std::min(plot_size.x, plot_size.y);
|
||||
if (min_dim < 300) {
|
||||
if (min_dim < 150) {
|
||||
flags |= ImPlotFlags_NoTitle;
|
||||
}
|
||||
if (min_dim < 200) {
|
||||
if (min_dim < 140) {
|
||||
flags |= ImPlotFlags_NoLegend;
|
||||
}
|
||||
}
|
||||
@@ -395,7 +395,7 @@ ImPlotFlags ImPlot_SetupPlotFlags(ImVec2 plot_size) {
|
||||
void ImPlot_SetupTimeAxis(ImVec2 plot_size, const char* label,
|
||||
ImPlotAxisFlags extra_flags) {
|
||||
ImPlotAxisFlags flags = extra_flags;
|
||||
if (plot_size.x > 0 && plot_size.x < 300) {
|
||||
if (plot_size.x > 0 && plot_size.x < 180) {
|
||||
flags |= ImPlotAxisFlags_NoTickLabels;
|
||||
}
|
||||
ImPlot::SetupAxis(ImAxis_X1, label, flags);
|
||||
@@ -404,7 +404,7 @@ void ImPlot_SetupTimeAxis(ImVec2 plot_size, const char* label,
|
||||
void ImPlot_SetupValueAxis(ImVec2 plot_size, const char* label,
|
||||
const char* format, ImPlotAxisFlags extra_flags) {
|
||||
ImPlotAxisFlags flags = extra_flags;
|
||||
if (plot_size.y > 0 && plot_size.y < 150) {
|
||||
if (plot_size.y > 0 && plot_size.y < 90) {
|
||||
flags |= ImPlotAxisFlags_NoTickLabels;
|
||||
}
|
||||
ImPlot::SetupAxis(ImAxis_Y1, label, flags);
|
||||
@@ -418,7 +418,7 @@ void ImPlot_SetupFixedAxis(ImVec2 plot_size, double y_min, double y_max,
|
||||
const double* tick_values,
|
||||
const char* const* tick_labels, int n_ticks) {
|
||||
ImPlotAxisFlags flags = ImPlotAxisFlags_None;
|
||||
if (plot_size.y > 0 && plot_size.y < 150) {
|
||||
if (plot_size.y > 0 && plot_size.y < 90) {
|
||||
flags |= ImPlotAxisFlags_NoTickLabels;
|
||||
}
|
||||
ImPlot::SetupAxis(ImAxis_Y1, label, flags);
|
||||
|
||||
@@ -625,14 +625,12 @@ void App::HandleKeyboardEvents() {
|
||||
ToggleWindow(tmp_.help);
|
||||
} else if (ImGui_IsChordJustPressed(ImGuiKey_F2)) {
|
||||
ToggleWindow(tmp_.stats);
|
||||
} else if (ImGui_IsChordJustPressed(ImGuiKey_F3)) {
|
||||
ToggleWindow(tmp_.profiler);
|
||||
} else if (ImGui_IsChordJustPressed(ImGuiKey_F6)) {
|
||||
vis_options_.frame = (vis_options_.frame + 1) % mjNFRAME;
|
||||
} else if (ImGui_IsChordJustPressed(ImGuiKey_F7)) {
|
||||
vis_options_.label = (vis_options_.label + 1) % mjNLABEL;
|
||||
} else if (ImGui_IsChordJustPressed(ImGuiKey_F9)) {
|
||||
tmp_.chart_solver = !tmp_.chart_solver;
|
||||
} else if (ImGui_IsChordJustPressed(ImGuiKey_F10)) {
|
||||
tmp_.chart_performance = !tmp_.chart_performance;
|
||||
} else if (ImGui_IsChordJustPressed(ImGuiKey_F11)) {
|
||||
tmp_.full_screen = !tmp_.full_screen;
|
||||
} else if (ImGui_IsChordJustPressed(ImGuiKey_H)) {
|
||||
@@ -887,30 +885,10 @@ void App::BuildGui() {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (tmp_.chart_performance) {
|
||||
ImGui::SetNextWindowPos(chart_pos, ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(chart_size, ImGuiCond_FirstUseEver);
|
||||
if (ImGui::Begin("Performance", &tmp_.chart_performance)) {
|
||||
auto layout = platform::ImPlot_ComputePairLayout();
|
||||
profiler_.CpuTimeGraph(layout.plot_size);
|
||||
if (layout.direction == platform::ImPlotLayoutDirection::kHorizontal) {
|
||||
ImGui::SameLine();
|
||||
}
|
||||
profiler_.DimensionsGraph(layout.plot_size);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (tmp_.chart_solver) {
|
||||
ImGui::SetNextWindowPos(chart_pos, ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(chart_size, ImGuiCond_FirstUseEver);
|
||||
if (ImGui::Begin("Solver", &tmp_.chart_solver)) {
|
||||
auto layout = platform::ImPlot_ComputePairLayout();
|
||||
platform::CountsGui(model(), data(), layout.plot_size);
|
||||
if (layout.direction == platform::ImPlotLayoutDirection::kHorizontal) {
|
||||
ImGui::SameLine();
|
||||
}
|
||||
platform::ConvergenceGui(model(), data(), layout.plot_size);
|
||||
if (tmp_.profiler) {
|
||||
if (ImGui::Begin("Profiler", &tmp_.profiler,
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||
platform::ProfilerGui(model(), data(), &profiler_);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
@@ -1311,10 +1289,9 @@ void App::HelpGui() {
|
||||
|
||||
ImGui::Text("Help");
|
||||
ImGui::Text("Stats");
|
||||
ImGui::Text("Profiler");
|
||||
ImGui::Text("Cycle Frames");
|
||||
ImGui::Text("Cycle Labels");
|
||||
ImGui::Text("Solver Charts");
|
||||
ImGui::Text("Perf. Charts");
|
||||
ImGui::Text("Toggle Fullscreen");
|
||||
ImGui::Text("Free Camera");
|
||||
ImGui::Text("Toggle Pause");
|
||||
@@ -1338,10 +1315,9 @@ void App::HelpGui() {
|
||||
ImGui::Indent(indent);
|
||||
ImGui::Text("F1");
|
||||
ImGui::Text("F2");
|
||||
ImGui::Text("F3");
|
||||
ImGui::Text("F6");
|
||||
ImGui::Text("F7");
|
||||
ImGui::Text("F9");
|
||||
ImGui::Text("F10");
|
||||
ImGui::Text("F11");
|
||||
ImGui::Text("Esc");
|
||||
ImGui::Text("Spc");
|
||||
@@ -1733,11 +1709,8 @@ void App::MainMenuGui() {
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Charts")) {
|
||||
if (ImGui::MenuItem("Solver", "F9")) {
|
||||
tmp_.chart_solver = !tmp_.chart_solver;
|
||||
}
|
||||
if (ImGui::MenuItem("Performance", "F10")) {
|
||||
tmp_.chart_performance = !tmp_.chart_performance;
|
||||
if (ImGui::MenuItem("Profiler", "F3")) {
|
||||
ToggleWindow(tmp_.profiler);
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -120,8 +120,7 @@ class App {
|
||||
// Windows.
|
||||
bool help = false;
|
||||
bool stats = false;
|
||||
bool chart_solver = false;
|
||||
bool chart_performance = false;
|
||||
bool profiler = false;
|
||||
bool picture_in_picture = false;
|
||||
bool options_panel = true;
|
||||
bool inspector_panel = true;
|
||||
|
||||
Reference in New Issue
Block a user