Add gear icon toolbar button with viewport options dropdown

Adds a ⚙ icon button to the right of the AA toggle in each viewport
tile's compact toolbar.  Clicking it opens a dropdown with:
  - Shading submenu: Smooth Shaded / Flat Shaded / Wireframe on Surface /
    Wireframe / Unlit  (new ShadingMode enum driving UsdImagingGLDrawMode)
  - Lighting submenu: Camera Headlight / Scene Lights + Dome Light toggle
  - Show Grid and Anti-Aliasing toggles (mirrored from icon buttons)
  - Bounding Box submenu: None / Per Object / All Selection
  - Background submenu: Dark Gray / Black / Light Gray / Midnight Blue

ShadingMode is persisted in viewport_settings.ini alongside the existing
per-tile settings (saved on shutdown, restored on startup).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-25 09:56:49 +08:00
parent 9d8840ced6
commit 8316e419ba
8 changed files with 137 additions and 3 deletions
+96
View File
@@ -99,6 +99,7 @@ ViewportTileSettings ViewportTile::GetSettings() const
s.bboxMode = static_cast<int>(m_renderer.GetBBoxMode());
s.ambientLightOnly = m_renderer.GetAmbientLightOnly();
s.domeLightEnabled = m_renderer.GetDomeLightEnabled();
s.shadingMode = static_cast<int>(m_renderer.GetShadingMode());
return s;
}
@@ -112,6 +113,7 @@ void ViewportTile::ApplySettings(const ViewportTileSettings& s)
m_renderer.SetBBoxMode(static_cast<BBoxMode>(s.bboxMode));
m_renderer.SetAmbientLightOnly(s.ambientLightOnly);
m_renderer.SetDomeLightEnabled(s.domeLightEnabled);
m_renderer.SetShadingMode(static_cast<ShadingMode>(s.shadingMode));
}
// ---------------------------------------------------------------------------
@@ -963,6 +965,100 @@ void ViewportTile::RenderCompactToolbar(int tileIndex)
if (iconToggle(aaId.c_str(), "AA", Icon::Antialias, aa, "Toggle anti-aliasing"))
m_renderer.SetAAEnabled(!aa);
ImGui::SameLine();
ImGui::TextDisabled("|");
ImGui::SameLine();
// -- Gear / viewport options popup ---------------------------------------
{
std::string gearId = "##gear_" + std::to_string(tileIndex);
std::string gearPopupId = "GearPopup_" + std::to_string(tileIndex);
if (m_iconManager) {
ImTextureID tex = m_iconManager->Get(Icon::Settings);
ImGui::ImageButton(gearId.c_str(), ImTextureRef(tex), ImVec2(16.f, 16.f));
} else {
ImGui::Button("*");
}
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Viewport options");
if (ImGui::BeginPopupContextItem(gearPopupId.c_str(),
ImGuiPopupFlags_MouseButtonLeft))
{
// -- Shading mode ------------------------------------------------
if (ImGui::BeginMenu("Shading")) {
ShadingMode cur = m_renderer.GetShadingMode();
auto shadingItem = [&](const char* label, ShadingMode mode) {
if (ImGui::MenuItem(label, nullptr, cur == mode))
m_renderer.SetShadingMode(mode);
};
shadingItem("Smooth Shaded", ShadingMode::SmoothShaded);
shadingItem("Flat Shaded", ShadingMode::FlatShaded);
shadingItem("Wireframe on Surface", ShadingMode::WireframeOnSurface);
shadingItem("Wireframe", ShadingMode::Wireframe);
shadingItem("Unlit", ShadingMode::Unlit);
ImGui::EndMenu();
}
// -- Lighting ----------------------------------------------------
if (ImGui::BeginMenu("Lighting")) {
bool ambient = m_renderer.GetAmbientLightOnly();
if (ImGui::MenuItem("Camera Headlight", nullptr, ambient))
m_renderer.SetAmbientLightOnly(true);
if (ImGui::MenuItem("Scene Lights", nullptr, !ambient))
m_renderer.SetAmbientLightOnly(false);
ImGui::Separator();
bool dome = m_renderer.GetDomeLightEnabled();
if (ImGui::MenuItem("Dome Light", nullptr, dome))
m_renderer.SetDomeLightEnabled(!dome);
ImGui::EndMenu();
}
ImGui::Separator();
// -- Display toggles ---------------------------------------------
{
bool grid = m_renderer.ShowGrid();
if (ImGui::MenuItem("Show Grid", nullptr, grid))
m_renderer.SetShowGrid(!grid);
bool aaItem = m_renderer.GetAAEnabled();
if (ImGui::MenuItem("Anti-Aliasing", nullptr, aaItem))
m_renderer.SetAAEnabled(!aaItem);
}
ImGui::Separator();
// -- BBox --------------------------------------------------------
if (ImGui::BeginMenu("Bounding Box")) {
BBoxMode bbox = m_renderer.GetBBoxMode();
if (ImGui::MenuItem("None", nullptr, bbox == BBoxMode::None))
m_renderer.SetBBoxMode(BBoxMode::None);
if (ImGui::MenuItem("Per Object", nullptr, bbox == BBoxMode::PerObject))
m_renderer.SetBBoxMode(BBoxMode::PerObject);
if (ImGui::MenuItem("All Selection", nullptr, bbox == BBoxMode::AllSelection))
m_renderer.SetBBoxMode(BBoxMode::AllSelection);
ImGui::EndMenu();
}
// -- Background --------------------------------------------------
if (ImGui::BeginMenu("Background")) {
auto& bg = m_renderer.GetBackgroundColor();
if (ImGui::MenuItem("Dark Gray", nullptr, bg == pxr::GfVec3f(0.15f, 0.15f, 0.15f)))
m_renderer.SetBackgroundColor(pxr::GfVec3f(0.15f, 0.15f, 0.15f));
if (ImGui::MenuItem("Black", nullptr, bg == pxr::GfVec3f(0.0f, 0.0f, 0.0f)))
m_renderer.SetBackgroundColor(pxr::GfVec3f(0.0f, 0.0f, 0.0f));
if (ImGui::MenuItem("Light Gray", nullptr, bg == pxr::GfVec3f(0.45f, 0.45f, 0.45f)))
m_renderer.SetBackgroundColor(pxr::GfVec3f(0.45f, 0.45f, 0.45f));
if (ImGui::MenuItem("Midnight Blue", nullptr, bg == pxr::GfVec3f(0.1f, 0.1f, 0.2f)))
m_renderer.SetBackgroundColor(pxr::GfVec3f(0.1f, 0.1f, 0.2f));
ImGui::EndMenu();
}
ImGui::EndPopup();
}
}
ImGui::PopStyleVar(); // ItemSpacing
}