Studio: various panel usability improvements
- Reorder Physics section, move Actuator Groups to end. - Rename "Physics Settings" → "Physics", "Rendering Settings" → "Rendering". - Reduce IndentSpacing from 20 to 6. - Reduce FramePadding Y from 6 to 2 for narrower buttons and popups. - Remove explicit Unindent/Indent overrides in Rendering and Visibility Groups sections so buttons are naturally indented under their tree nodes. - Dynamically adjust convergence and counts plot X-axis limits based on actual solver iterations instead of hardcoded 20. PiperOrigin-RevId: 906244477 Change-Id: Ic3e6e6e793395158c8cb6692af885884ca3f7f50
This commit is contained in:
committed by
Copybara-Service
parent
3a5a48b9f9
commit
2e3205229c
@@ -192,7 +192,7 @@ void SetupTheme(GuiTheme theme) {
|
||||
float rounding = 4.0f;
|
||||
s.DisplaySafeAreaPadding = ImVec2(0, 0);
|
||||
s.WindowPadding = ImVec2(hspacing, vspacing);
|
||||
s.FramePadding = ImVec2(hspacing, vspacing);
|
||||
s.FramePadding = ImVec2(hspacing, 2);
|
||||
s.ItemSpacing = ImVec2(hspacing, vspacing);
|
||||
s.ItemInnerSpacing = ImVec2(hspacing, vspacing);
|
||||
s.WindowRounding = rounding;
|
||||
@@ -205,7 +205,7 @@ void SetupTheme(GuiTheme theme) {
|
||||
s.WindowBorderSize = 0.0f;
|
||||
s.FrameBorderSize = 1.0f;
|
||||
s.PopupBorderSize = 1.0f;
|
||||
s.IndentSpacing = 20.0f;
|
||||
s.IndentSpacing = 6.0f;
|
||||
s.ScrollbarSize = 12.0f;
|
||||
s.GrabMinSize = 5.0f;
|
||||
s.WindowMenuButtonPosition = ImGuiDir_None;
|
||||
@@ -817,22 +817,6 @@ void PhysicsGui(mjModel* model, float min_width) {
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::TreeNodeEx("Actuator Groups")) {
|
||||
if (ImGui::BeginTable("##ActuatorGroupsTable", num_cols)) {
|
||||
const ImVec2 size = GetFlexElementSize(num_cols);
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
char label[64];
|
||||
std::snprintf(label, sizeof(label), "Act Group %d", i);
|
||||
ImGui::TableNextColumn();
|
||||
int flipped = ~opt.disableactuator;
|
||||
ImGui_BitToggle(label, &flipped, 1 << i, size);
|
||||
opt.disableactuator = ~flipped;
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
};
|
||||
|
||||
if (ImGui::TreeNodeEx("Algorithmic Parameters")) {
|
||||
ImGui_Input("Timestep", &opt.timestep, {0, 1, 0.01, 0.1});
|
||||
ImGui_Input("Iterations", &opt.iterations, {0, 1000, 1, 10});
|
||||
@@ -867,6 +851,22 @@ void PhysicsGui(mjModel* model, float min_width) {
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::TreeNodeEx("Actuator Groups")) {
|
||||
if (ImGui::BeginTable("##ActuatorGroupsTable", num_cols)) {
|
||||
const ImVec2 size = GetFlexElementSize(num_cols);
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
char label[64];
|
||||
std::snprintf(label, sizeof(label), "Act Group %d", i);
|
||||
ImGui::TableNextColumn();
|
||||
int flipped = ~opt.disableactuator;
|
||||
ImGui_BitToggle(label, &flipped, 1 << i, size);
|
||||
opt.disableactuator = ~flipped;
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
@@ -986,8 +986,6 @@ void RenderingGui(const mjModel* model, mjvOption* vis_options,
|
||||
static_cast<int>(std::floor(available_width / min_width)), 1, 6);
|
||||
|
||||
if (ImGui::TreeNodeEx("Model Elements", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing() / 2);
|
||||
|
||||
if (ImGui::BeginTable("##ModelElementsTable", num_cols)) {
|
||||
const ImVec2 size = GetFlexElementSize(num_cols);
|
||||
for (int i = 0; i < mjNVISFLAG; ++i) {
|
||||
@@ -996,14 +994,10 @@ void RenderingGui(const mjModel* model, mjvOption* vis_options,
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing() / 2);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::TreeNodeEx("Render Flags", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing() / 2);
|
||||
|
||||
if (ImGui::BeginTable("##RenderFlagsTable", num_cols)) {
|
||||
const ImVec2 size = GetFlexElementSize(num_cols);
|
||||
for (int i = 0; i < mjNRNDFLAG; ++i) {
|
||||
@@ -1012,8 +1006,6 @@ void RenderingGui(const mjModel* model, mjvOption* vis_options,
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing() / 2);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
@@ -1030,8 +1022,6 @@ void GroupsGui(const mjModel* model, mjvOption* vis_options, float min_width) {
|
||||
|
||||
auto GroupGui = [&](const char* name, mjtByte* group) {
|
||||
if (ImGui::TreeNodeEx(name, ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing() / 2);
|
||||
|
||||
char label[64];
|
||||
std::snprintf(label, sizeof(label), "##%s", name);
|
||||
if (ImGui::BeginTable(label, num_cols)) {
|
||||
@@ -1044,8 +1034,6 @@ void GroupsGui(const mjModel* model, mjvOption* vis_options, float min_width) {
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing() / 2);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
};
|
||||
@@ -1150,12 +1138,24 @@ void ControlsGui(const mjModel* model, const mjData* data,
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
static int GetPlotXLimit(const mjData* data) {
|
||||
int max_niter = 0;
|
||||
const int nisland0 =
|
||||
data->nefc ? mjMAX(1, mjMIN(data->nisland, mjNISLAND)) : 0;
|
||||
for (int k = 0; k < nisland0; k++) {
|
||||
max_niter = mjMAX(max_niter, data->solver_niter[k]);
|
||||
}
|
||||
return mjMAX(10, ((max_niter + 9) / 10) * 10);
|
||||
}
|
||||
|
||||
void ConvergenceGui(const mjModel* model, mjData* data) {
|
||||
int xlim = GetPlotXLimit(data);
|
||||
|
||||
if (ImPlot::BeginPlot("Convergence (log 10)", ImVec2(-1, 0),
|
||||
ImPlotFlags_NoMouseText)) {
|
||||
ImPlot::PushStyleVar(ImPlotStyleVar_LineWeight, 2.0f);
|
||||
ImPlot::SetupAxis(ImAxis_X1, "iteration", ImPlotAxisFlags_AutoFit);
|
||||
ImPlot::SetupAxisLimits(ImAxis_X1, 0, 20, ImPlotCond_Always);
|
||||
ImPlot::SetupAxisLimits(ImAxis_X1, 0, xlim, ImPlotCond_Always);
|
||||
ImPlot::SetupAxisFormat(ImAxis_Y1, "%.1f");
|
||||
ImPlot::SetupAxisLimits(ImAxis_Y1, -20, 5, ImPlotCond_Always);
|
||||
ImPlot::SetupLegend(ImPlotLocation_NorthEast);
|
||||
@@ -1212,10 +1212,12 @@ void ConvergenceGui(const mjModel* model, mjData* data) {
|
||||
}
|
||||
|
||||
void CountsGui(const mjModel* model, mjData* data) {
|
||||
int xlim = GetPlotXLimit(data);
|
||||
|
||||
if (ImPlot::BeginPlot("Counts", ImVec2(-1, 0), ImPlotFlags_NoMouseText)) {
|
||||
ImPlot::PushStyleVar(ImPlotStyleVar_LineWeight, 2.0f);
|
||||
ImPlot::SetupAxis(ImAxis_X1, "iteration", ImPlotAxisFlags_AutoFit);
|
||||
ImPlot::SetupAxisLimits(ImAxis_X1, 0, 20, ImPlotCond_Always);
|
||||
ImPlot::SetupAxisLimits(ImAxis_X1, 0, xlim, ImPlotCond_Always);
|
||||
ImPlot::SetupAxisFormat(ImAxis_Y1, "%.0f");
|
||||
ImPlot::SetupAxisLimits(ImAxis_Y1, 0, 80, ImPlotCond_Always);
|
||||
ImPlot::SetupLegend(ImPlotLocation_NorthEast);
|
||||
|
||||
@@ -1011,14 +1011,14 @@ void App::ModelOptionsGui() {
|
||||
ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_Framed;
|
||||
|
||||
ImGui::BeginChild("PhysicsGui", {0, 0}, child_flags);
|
||||
if (ImGui::TreeNodeEx("Physics Settings", node_flags)) {
|
||||
if (ImGui::TreeNodeEx("Physics", node_flags)) {
|
||||
platform::PhysicsGui(model(), min_width);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::BeginChild("RenderingGui", {0, 0}, child_flags);
|
||||
if (ImGui::TreeNodeEx("Rendering Settings", node_flags)) {
|
||||
if (ImGui::TreeNodeEx("Rendering", node_flags)) {
|
||||
platform::RenderingGui(model(), &vis_options_, renderer_->GetRenderFlags(),
|
||||
min_width);
|
||||
ImGui::TreePop();
|
||||
|
||||
Reference in New Issue
Block a user