Add renderer settings dialog with tab categories per delegate
Surfaces each render delegate's settings (FLAG/INT/FLOAT/STRING) in a per-viewport floating dialog opened from the gear popup. Settings are grouped into tabs by key namespace prefix (split at ':'); unprefixed keys go into General. Changes apply immediately; Reset Defaults restores defValues. Settings list is cached per delegate to avoid TF_WARN flooding the log on every frame. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -369,6 +369,23 @@ bool UsdSceneRenderer::SetCurrentAov(const pxr::TfToken& aov)
|
||||
return false;
|
||||
}
|
||||
|
||||
pxr::UsdImagingGLRendererSettingsList UsdSceneRenderer::GetRendererSettingsList() const
|
||||
{
|
||||
if (!m_renderer) return {};
|
||||
return m_renderer->GetRendererSettingsList();
|
||||
}
|
||||
|
||||
pxr::VtValue UsdSceneRenderer::GetRendererSetting(const pxr::TfToken& id) const
|
||||
{
|
||||
if (!m_renderer) return {};
|
||||
return m_renderer->GetRendererSetting(id);
|
||||
}
|
||||
|
||||
void UsdSceneRenderer::SetRendererSetting(const pxr::TfToken& id, const pxr::VtValue& v)
|
||||
{
|
||||
if (m_renderer) m_renderer->SetRendererSetting(id, v);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Camera State
|
||||
// ===========================================================================
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include <glad/gl.h>
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <pxr/usd/usd/timeCode.h>
|
||||
#include <pxr/imaging/glf/drawTarget.h>
|
||||
#include <pxr/usdImaging/usdImagingGL/engine.h>
|
||||
#include <pxr/usdImaging/usdImagingGL/rendererSettings.h>
|
||||
#include <pxr/base/vt/value.h>
|
||||
#include <pxr/imaging/glf/simpleLight.h>
|
||||
#include <pxr/imaging/glf/simpleMaterial.h>
|
||||
#include <pxr/base/gf/vec3f.h>
|
||||
@@ -187,6 +189,11 @@ public:
|
||||
pxr::TfTokenVector GetRendererAovs() const;
|
||||
bool SetCurrentAov(const pxr::TfToken& aov);
|
||||
|
||||
pxr::UsdImagingGLRendererSettingsList GetRendererSettingsList() const;
|
||||
pxr::VtValue GetRendererSetting(const pxr::TfToken& id) const;
|
||||
void SetRendererSetting(const pxr::TfToken& id,
|
||||
const pxr::VtValue& value);
|
||||
|
||||
bool GetAAEnabled() const { return m_aaEnabled; }
|
||||
void SetAAEnabled(bool enabled) { m_aaEnabled = enabled; }
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace UsdLayerManager {
|
||||
@@ -1084,6 +1085,10 @@ void ViewportTile::RenderCompactToolbar(int tileIndex)
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Renderer Settings..."))
|
||||
m_showRendererSettings = true;
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
@@ -1322,6 +1327,143 @@ void ViewportTile::Render(int tileIndex, ImVec2 pos, ImVec2 size,
|
||||
|
||||
RenderContextMenu(tileIndex);
|
||||
ImGui::EndChild();
|
||||
|
||||
if (m_showRendererSettings)
|
||||
RenderRendererSettingsDialog(tileIndex);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// RenderRendererSettingsDialog
|
||||
// ---------------------------------------------------------------------------
|
||||
void ViewportTile::RenderRendererSettingsDialog(int tileIndex)
|
||||
{
|
||||
using namespace pxr;
|
||||
std::string title = "Renderer Settings [" +
|
||||
UsdSceneRenderer::GetRendererDisplayName(m_renderer.GetCurrentRendererId()) +
|
||||
"]###RendererSettingsDlg_" + std::to_string(tileIndex);
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(520, 460), ImGuiCond_FirstUseEver);
|
||||
// WindowPadding is captured by Begin(); pop it immediately after.
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(12.f, 12.f));
|
||||
bool open = ImGui::Begin(title.c_str(), &m_showRendererSettings,
|
||||
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDocking);
|
||||
ImGui::PopStyleVar();
|
||||
if (!open) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
// ItemSpacing and FramePadding are read dynamically; push for content, pop before End.
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8.f, 6.f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.f, 4.f));
|
||||
|
||||
// Cache the settings list per delegate — GetRendererSettingsList() calls TF_WARN
|
||||
// for every unsupported setting type, so querying it every frame floods the log.
|
||||
pxr::TfToken curId = m_renderer.GetCurrentRendererId();
|
||||
if (curId != m_cachedSettingsRendererId) {
|
||||
m_cachedRendererSettings = m_renderer.GetRendererSettingsList();
|
||||
m_cachedSettingsRendererId = curId;
|
||||
}
|
||||
const auto& settings = m_cachedRendererSettings;
|
||||
if (settings.empty()) {
|
||||
ImVec2 sz = ImGui::GetContentRegionAvail();
|
||||
ImGui::SetCursorPos(ImVec2(sz.x * 0.5f - 120.f, sz.y * 0.5f - 8.f));
|
||||
ImGui::TextDisabled("This renderer exposes no settings.");
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
// Group settings by namespace prefix (split key at first ':').
|
||||
// Keys without ':' go into "General". std::map keeps alphabetical order.
|
||||
std::map<std::string, std::vector<const UsdImagingGLRendererSetting*>> groups;
|
||||
for (const auto& s : settings) {
|
||||
std::string k = s.key.GetString();
|
||||
auto colon = k.find(':');
|
||||
std::string cat = (colon != std::string::npos) ? k.substr(0, colon) : "General";
|
||||
if (!cat.empty()) cat[0] = static_cast<char>(toupper(static_cast<unsigned char>(cat[0])));
|
||||
groups[cat].push_back(&s);
|
||||
}
|
||||
|
||||
bool singleGroup = (groups.size() == 1);
|
||||
bool tabBarOpen = false;
|
||||
if (!singleGroup)
|
||||
tabBarOpen = ImGui::BeginTabBar("##rdrsettings_tabs");
|
||||
|
||||
auto renderGroup = [&](const std::vector<const UsdImagingGLRendererSetting*>& items) {
|
||||
float tableH = ImGui::GetContentRegionAvail().y - 40.f;
|
||||
if (tableH < 20.f) tableH = 20.f;
|
||||
if (ImGui::BeginTable("##srows", 2,
|
||||
ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_BordersInnerH |
|
||||
ImGuiTableFlags_ScrollY, ImVec2(0, tableH)))
|
||||
{
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch, 0.55f);
|
||||
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch, 0.45f);
|
||||
for (const auto* sp : items) {
|
||||
const auto& s = *sp;
|
||||
VtValue cur = m_renderer.GetRendererSetting(s.key);
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::TextUnformatted(s.name.c_str());
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::PushItemWidth(-1.f);
|
||||
std::string wid = "##" + s.key.GetString();
|
||||
if (s.type == UsdImagingGLRendererSetting::TYPE_FLAG) {
|
||||
bool v = cur.GetWithDefault<bool>(false);
|
||||
if (ImGui::Checkbox(wid.c_str(), &v))
|
||||
m_renderer.SetRendererSetting(s.key, VtValue(v));
|
||||
} else if (s.type == UsdImagingGLRendererSetting::TYPE_INT) {
|
||||
int v = cur.GetWithDefault<int>(0);
|
||||
if (ImGui::DragInt(wid.c_str(), &v))
|
||||
m_renderer.SetRendererSetting(s.key, VtValue(v));
|
||||
} else if (s.type == UsdImagingGLRendererSetting::TYPE_FLOAT) {
|
||||
float v = cur.GetWithDefault<float>(0.f);
|
||||
if (ImGui::DragFloat(wid.c_str(), &v, 0.01f))
|
||||
m_renderer.SetRendererSetting(s.key, VtValue(v));
|
||||
} else if (s.type == UsdImagingGLRendererSetting::TYPE_STRING) {
|
||||
std::string sv = cur.GetWithDefault<std::string>("");
|
||||
char buf[256];
|
||||
strncpy(buf, sv.c_str(), sizeof(buf) - 1);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
if (ImGui::InputText(wid.c_str(), buf, sizeof(buf)) &&
|
||||
ImGui::IsItemDeactivatedAfterEdit())
|
||||
m_renderer.SetRendererSetting(s.key, VtValue(std::string(buf)));
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
if (singleGroup) {
|
||||
renderGroup(groups.begin()->second);
|
||||
} else if (tabBarOpen) {
|
||||
// Non-"General" tabs first (alphabetical via std::map), then "General" last
|
||||
for (const auto& [cat, items] : groups) {
|
||||
if (cat == "General") continue;
|
||||
if (ImGui::BeginTabItem(cat.c_str())) {
|
||||
renderGroup(items);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
}
|
||||
auto genIt = groups.find("General");
|
||||
if (genIt != groups.end() && ImGui::BeginTabItem("General")) {
|
||||
renderGroup(genIt->second);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Spacing();
|
||||
if (ImGui::Button("Reset Defaults")) {
|
||||
for (const auto& s : settings)
|
||||
m_renderer.SetRendererSetting(s.key, s.defValue);
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
} // namespace UsdLayerManager
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "../core/UsdSceneRenderer.h"
|
||||
#include "../core/ViewportCamera.h"
|
||||
@@ -184,6 +184,12 @@ private:
|
||||
// ── Per-frame interaction flags ──────────────────────────────────────────
|
||||
bool m_wasClickedThisFrame = false;
|
||||
bool m_wasHoveredThisFrame = false;
|
||||
|
||||
// ── Renderer settings dialog ─────────────────────────────────────────────
|
||||
bool m_showRendererSettings = false;
|
||||
pxr::TfToken m_cachedSettingsRendererId;
|
||||
pxr::UsdImagingGLRendererSettingsList m_cachedRendererSettings;
|
||||
void RenderRendererSettingsDialog(int tileIndex);
|
||||
};
|
||||
|
||||
} // namespace UsdLayerManager
|
||||
|
||||
Reference in New Issue
Block a user