Add global Preferences dialog and per-viewport render delegate
Preferences (Edit > Preferences, tabbed General/Animation/Viewport): - Viewport tab: Default Render Delegate and Color Correction settings - Persisted to %APPDATA%\UsdLayerManager\preferences.ini - Render delegate: startup default only (not live-applied to running tiles) - Color correction: global, applied live to all viewports on change Render delegate per-viewport: - Each tile toolbar switches its own delegate independently - Saved per-tile in viewport_settings.ini; restored on next launch - Tiles with no saved delegate get the pref default on startup Color correction global: - Removed from gear popup; lives in Preferences > Viewport only - Applied to all tiles on init and on live change from Preferences Fix InitRenderer always applying m_currentRendererPlugin when set, rather than skipping when UsdImagingGLEngine auto-selects a default. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -547,23 +547,25 @@ void UsdSceneRenderer::InitRenderer() {
|
||||
if (!hasCycles)
|
||||
LOG_WARNING("HdCyclesPlugin not available (see startup log for DLL load errors).");
|
||||
|
||||
pxr::TfToken currentPlugin = m_renderer->GetCurrentRendererId();
|
||||
if (currentPlugin.IsEmpty() && !plugins.empty()) {
|
||||
// Apply the requested plugin. m_currentRendererPlugin is set from global
|
||||
// preferences before InitRenderer runs; always honour it rather than
|
||||
// checking whether the engine already chose something by default.
|
||||
if (!m_currentRendererPlugin.IsEmpty()) {
|
||||
pxr::TfToken cur = m_renderer->GetCurrentRendererId();
|
||||
if (cur != m_currentRendererPlugin)
|
||||
m_renderer->SetRendererPlugin(m_currentRendererPlugin);
|
||||
} else if (!plugins.empty()) {
|
||||
// Fallback heuristic: prefer Storm/GL
|
||||
pxr::TfToken best;
|
||||
// If a plugin was previously selected, honour it
|
||||
if (!m_currentRendererPlugin.IsEmpty()) {
|
||||
best = m_currentRendererPlugin;
|
||||
} else {
|
||||
for (const auto& p : plugins) {
|
||||
std::string n(p.GetText());
|
||||
if (n.find("Storm") != std::string::npos ||
|
||||
n.find("GL") != std::string::npos) { best = p; break; }
|
||||
}
|
||||
if (best.IsEmpty()) best = plugins[0];
|
||||
for (const auto& p : plugins) {
|
||||
std::string n(p.GetText());
|
||||
if (n.find("Storm") != std::string::npos ||
|
||||
n.find("GL") != std::string::npos) { best = p; break; }
|
||||
}
|
||||
if (best.IsEmpty()) best = plugins[0];
|
||||
m_renderer->SetRendererPlugin(best);
|
||||
LOG_INFO("Selected renderer: " + std::string(m_renderer->GetCurrentRendererId().GetText()));
|
||||
}
|
||||
LOG_INFO("Selected renderer: " + std::string(m_renderer->GetCurrentRendererId().GetText()));
|
||||
|
||||
// Enable AOV "color" (matches stageView._handleRendererChanged)
|
||||
m_renderer->SetRendererAov(pxr::TfToken("color"));
|
||||
|
||||
@@ -313,7 +313,7 @@ private:
|
||||
|
||||
pxr::UsdStageRefPtr m_stage;
|
||||
std::shared_ptr<pxr::UsdImagingGLEngine> m_renderer;
|
||||
pxr::TfToken m_currentRendererPlugin; ///< Active plugin ID (empty = default)
|
||||
pxr::TfToken m_currentRendererPlugin; ///< empty = use Storm/GL heuristic on init
|
||||
pxr::GlfDrawTargetRefPtr m_drawTarget;
|
||||
|
||||
pxr::UsdImagingGLRenderParams m_renderParams;
|
||||
|
||||
+244
-1
@@ -2,6 +2,7 @@
|
||||
#include "../utils/Logger.h"
|
||||
#include "../utils/FileDialog.h"
|
||||
#include "../utils/PathUtils.h"
|
||||
#include "../utils/OcioConfigParser.h"
|
||||
#include <pxr/usd/usd/prim.h>
|
||||
#include <pxr/usd/usd/references.h>
|
||||
#include <pxr/usd/sdf/path.h>
|
||||
@@ -10,6 +11,7 @@
|
||||
#include <imgui_internal.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
@@ -132,6 +134,7 @@ bool Application::Initialize(const std::string& windowTitle, int width, int heig
|
||||
m_curveEditorPanel->SetSelectedPrimPath(paths.empty() ? "" : paths.front());
|
||||
};
|
||||
|
||||
|
||||
if (!m_stageManager->CreateInMemoryStage()) {
|
||||
LOG_ERROR("Failed to create default in-memory stage");
|
||||
} else {
|
||||
@@ -150,13 +153,21 @@ bool Application::Initialize(const std::string& windowTitle, int width, int heig
|
||||
}
|
||||
}
|
||||
|
||||
// Load per-viewport settings (render delegate, grid, AA, etc.) from AppData.
|
||||
// Load per-viewport settings and global preferences from AppData.
|
||||
if (const char* appData = getenv("APPDATA")) {
|
||||
namespace fs = std::filesystem;
|
||||
fs::path dir = fs::path(appData) / "UsdLayerManager";
|
||||
fs::create_directories(dir);
|
||||
m_viewportSettingsPath = (dir / "viewport_settings.ini").string();
|
||||
m_prefsPath = (dir / "preferences.ini").string();
|
||||
m_viewportPanel->LoadSettings(m_viewportSettingsPath);
|
||||
LoadPreferences();
|
||||
// Apply pref delegate only to tiles that have no saved delegate.
|
||||
m_viewportPanel->ApplyDefaultDelegate(m_prefs.renderDelegate);
|
||||
// Color correction is always global — apply to all tiles.
|
||||
m_viewportPanel->ApplyGlobalColorCorrection(
|
||||
m_prefs.colorCorrectionMode, m_prefs.ocioDisplay,
|
||||
m_prefs.ocioView, m_prefs.ocioColorSpace, m_prefs.ocioLook);
|
||||
}
|
||||
|
||||
LOG_INFO("Application initialized successfully");
|
||||
@@ -178,6 +189,8 @@ void Application::Run() {
|
||||
void Application::Shutdown() {
|
||||
if (m_viewportPanel && !m_viewportSettingsPath.empty())
|
||||
m_viewportPanel->SaveSettings(m_viewportSettingsPath);
|
||||
if (!m_prefsPath.empty())
|
||||
SavePreferences();
|
||||
|
||||
m_viewportPanel.reset();
|
||||
m_sceneHierarchyPanel.reset();
|
||||
@@ -300,6 +313,9 @@ void Application::RenderUI() {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (m_showPreferences)
|
||||
RenderPreferencesDialog();
|
||||
|
||||
// Capture happens after the timeline so that the "Start" button click in
|
||||
// this frame is detected, and after the viewport has rendered the scene.
|
||||
if (m_timelinePanel->IsPlayblasting()) {
|
||||
@@ -346,6 +362,229 @@ void Application::RenderStatusBar() {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Global preferences persistence
|
||||
// ---------------------------------------------------------------------------
|
||||
void Application::LoadPreferences()
|
||||
{
|
||||
std::ifstream f(m_prefsPath);
|
||||
if (!f) return;
|
||||
std::string line;
|
||||
while (std::getline(f, line)) {
|
||||
if (!line.empty() && line.back() == '\r') line.pop_back();
|
||||
if (line.empty() || line.front() == '#' || line.front() == '[') continue;
|
||||
size_t eq = line.find('=');
|
||||
if (eq == std::string::npos) continue;
|
||||
std::string key = line.substr(0, eq);
|
||||
std::string val = line.substr(eq + 1);
|
||||
if (key == "RenderDelegate") m_prefs.renderDelegate = val;
|
||||
else if (key == "ColorCorrectionMode")
|
||||
m_prefs.colorCorrectionMode = [&]{ try { return std::stoi(val); } catch(...){ return 1; } }();
|
||||
else if (key == "OcioDisplay") m_prefs.ocioDisplay = val;
|
||||
else if (key == "OcioView") m_prefs.ocioView = val;
|
||||
else if (key == "OcioColorSpace") m_prefs.ocioColorSpace = val;
|
||||
else if (key == "OcioLook") m_prefs.ocioLook = val;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::SavePreferences()
|
||||
{
|
||||
std::ofstream f(m_prefsPath);
|
||||
if (!f) return;
|
||||
f << "[Preferences]\n";
|
||||
f << "RenderDelegate=" << m_prefs.renderDelegate << "\n";
|
||||
f << "ColorCorrectionMode=" << m_prefs.colorCorrectionMode << "\n";
|
||||
f << "OcioDisplay=" << m_prefs.ocioDisplay << "\n";
|
||||
f << "OcioView=" << m_prefs.ocioView << "\n";
|
||||
f << "OcioColorSpace=" << m_prefs.ocioColorSpace << "\n";
|
||||
f << "OcioLook=" << m_prefs.ocioLook << "\n";
|
||||
}
|
||||
|
||||
void Application::ApplyPrefsToAllViewports()
|
||||
{
|
||||
if (!m_viewportPanel) return;
|
||||
m_viewportPanel->ApplyGlobalColorCorrection(
|
||||
m_prefs.colorCorrectionMode,
|
||||
m_prefs.ocioDisplay,
|
||||
m_prefs.ocioView,
|
||||
m_prefs.ocioColorSpace,
|
||||
m_prefs.ocioLook);
|
||||
}
|
||||
|
||||
void Application::RenderPreferencesDialog()
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(520, 400), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
|
||||
ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f));
|
||||
if (!ImGui::Begin("Preferences", &m_showPreferences,
|
||||
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDocking))
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
bool ccChanged = false;
|
||||
|
||||
if (ImGui::BeginTabBar("PrefTabs")) {
|
||||
|
||||
// ── General ─────────────────────────────────────────────────────────
|
||||
if (ImGui::BeginTabItem("General")) {
|
||||
ImGui::Spacing();
|
||||
ImGui::TextDisabled("No general settings yet.");
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// ── Animation ───────────────────────────────────────────────────────
|
||||
if (ImGui::BeginTabItem("Animation")) {
|
||||
ImGui::Spacing();
|
||||
ImGui::TextDisabled("No animation settings yet.");
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// ── Viewport ────────────────────────────────────────────────────────
|
||||
if (ImGui::BeginTabItem("Viewport")) {
|
||||
ImGui::Spacing();
|
||||
|
||||
// Render Delegate default — applied to viewports with no saved delegate on startup.
|
||||
// Each viewport's toolbar controls its delegate independently after load.
|
||||
ImGui::SeparatorText("Default Render Delegate");
|
||||
ImGui::TextDisabled("Applied to viewports with no saved setting on startup.");
|
||||
ImGui::Spacing();
|
||||
auto plugins = UsdSceneRenderer::GetRendererPlugins();
|
||||
pxr::TfToken curId(m_prefs.renderDelegate);
|
||||
for (const auto& pluginId : plugins) {
|
||||
std::string name = UsdSceneRenderer::GetRendererDisplayName(pluginId);
|
||||
if (name.empty()) name = pluginId.GetString();
|
||||
bool sel = (pluginId == curId);
|
||||
if (ImGui::RadioButton(name.c_str(), sel))
|
||||
m_prefs.renderDelegate = pluginId.GetString();
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
// Color Correction
|
||||
ImGui::SeparatorText("Color Correction");
|
||||
|
||||
auto ccItem = [&](const char* label, int mode) {
|
||||
if (ImGui::RadioButton(label, m_prefs.colorCorrectionMode == mode)) {
|
||||
m_prefs.colorCorrectionMode = mode;
|
||||
m_prefOcioFieldsSynced = false;
|
||||
ccChanged = true;
|
||||
}
|
||||
};
|
||||
ccItem("Disabled", 0);
|
||||
ccItem("sRGB", 1);
|
||||
ccItem("OpenColorIO", 2);
|
||||
|
||||
if (m_prefs.colorCorrectionMode == 2) {
|
||||
ImGui::Spacing();
|
||||
const OcioConfig& ocfg = GetCurrentOcioConfig();
|
||||
|
||||
if (!m_prefOcioFieldsSynced) {
|
||||
std::string disp = m_prefs.ocioDisplay.empty() ? ocfg.defaultDisplay : m_prefs.ocioDisplay;
|
||||
std::string view = m_prefs.ocioView.empty() ? ocfg.defaultView : m_prefs.ocioView;
|
||||
strncpy(m_prefOcioDisplayBuf, disp.c_str(), 127);
|
||||
strncpy(m_prefOcioViewBuf, view.c_str(), 127);
|
||||
strncpy(m_prefOcioColorSpaceBuf, m_prefs.ocioColorSpace.c_str(), 127);
|
||||
strncpy(m_prefOcioLookBuf, m_prefs.ocioLook.c_str(), 127);
|
||||
if (m_prefs.ocioDisplay.empty()) m_prefs.ocioDisplay = disp;
|
||||
if (m_prefs.ocioView.empty()) m_prefs.ocioView = view;
|
||||
m_prefOcioFieldsSynced = true;
|
||||
}
|
||||
|
||||
ImGui::PushItemWidth(280.f);
|
||||
|
||||
if (ImGui::BeginCombo("Display##pref", m_prefOcioDisplayBuf)) {
|
||||
for (const auto& d : ocfg.displays) {
|
||||
bool sel = (d == m_prefOcioDisplayBuf);
|
||||
if (ImGui::Selectable(d.c_str(), sel)) {
|
||||
strncpy(m_prefOcioDisplayBuf, d.c_str(), 127);
|
||||
m_prefs.ocioDisplay = d;
|
||||
auto vit = ocfg.views.find(d);
|
||||
if (vit != ocfg.views.end() && !vit->second.empty()) {
|
||||
strncpy(m_prefOcioViewBuf, vit->second[0].c_str(), 127);
|
||||
m_prefs.ocioView = vit->second[0];
|
||||
}
|
||||
ccChanged = true;
|
||||
}
|
||||
if (sel) ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
{
|
||||
static const std::vector<std::string> kEmpty;
|
||||
auto vit = ocfg.views.find(std::string(m_prefOcioDisplayBuf));
|
||||
const auto& views = (vit != ocfg.views.end()) ? vit->second : kEmpty;
|
||||
if (ImGui::BeginCombo("View##pref", m_prefOcioViewBuf)) {
|
||||
for (const auto& v : views) {
|
||||
bool sel = (v == m_prefOcioViewBuf);
|
||||
if (ImGui::Selectable(v.c_str(), sel)) {
|
||||
strncpy(m_prefOcioViewBuf, v.c_str(), 127);
|
||||
m_prefs.ocioView = v;
|
||||
ccChanged = true;
|
||||
}
|
||||
if (sel) ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::BeginCombo("Color Space##pref",
|
||||
m_prefOcioColorSpaceBuf[0] ? m_prefOcioColorSpaceBuf : "(default)")) {
|
||||
if (ImGui::Selectable("(default)", m_prefOcioColorSpaceBuf[0] == '\0')) {
|
||||
m_prefOcioColorSpaceBuf[0] = '\0';
|
||||
m_prefs.ocioColorSpace.clear();
|
||||
ccChanged = true;
|
||||
}
|
||||
if (m_prefOcioColorSpaceBuf[0] == '\0') ImGui::SetItemDefaultFocus();
|
||||
for (const auto& cs : ocfg.colorSpaces) {
|
||||
bool sel = (cs == m_prefOcioColorSpaceBuf);
|
||||
if (ImGui::Selectable(cs.c_str(), sel)) {
|
||||
strncpy(m_prefOcioColorSpaceBuf, cs.c_str(), 127);
|
||||
m_prefs.ocioColorSpace = cs;
|
||||
ccChanged = true;
|
||||
}
|
||||
if (sel) ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui::BeginCombo("Look##pref",
|
||||
m_prefOcioLookBuf[0] ? m_prefOcioLookBuf : "(none)")) {
|
||||
if (ImGui::Selectable("(none)", m_prefOcioLookBuf[0] == '\0')) {
|
||||
m_prefOcioLookBuf[0] = '\0';
|
||||
m_prefs.ocioLook.clear();
|
||||
ccChanged = true;
|
||||
}
|
||||
if (m_prefOcioLookBuf[0] == '\0') ImGui::SetItemDefaultFocus();
|
||||
for (const auto& look : ocfg.looks) {
|
||||
bool sel = (look == m_prefOcioLookBuf);
|
||||
if (ImGui::Selectable(look.c_str(), sel)) {
|
||||
strncpy(m_prefOcioLookBuf, look.c_str(), 127);
|
||||
m_prefs.ocioLook = look;
|
||||
ccChanged = true;
|
||||
}
|
||||
if (sel) ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
if (ccChanged)
|
||||
ApplyPrefsToAllViewports();
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void Application::RenderMenuBar() {
|
||||
if (ImGui::BeginMainMenuBar()) {
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
@@ -403,6 +642,10 @@ void Application::RenderMenuBar() {
|
||||
m_commandHistory.Redo();
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Preferences..."))
|
||||
m_showPreferences = true;
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
+36
-10
@@ -18,15 +18,25 @@
|
||||
|
||||
namespace UsdLayerManager {
|
||||
|
||||
/// Global (non-per-viewport) rendering preferences persisted to preferences.ini.
|
||||
struct AppPreferences {
|
||||
std::string renderDelegate = "HdStormRendererPlugin";
|
||||
int colorCorrectionMode = 1; ///< ColorCorrectionMode cast to int (1 = sRGB)
|
||||
std::string ocioDisplay;
|
||||
std::string ocioView;
|
||||
std::string ocioColorSpace;
|
||||
std::string ocioLook;
|
||||
};
|
||||
|
||||
class Application {
|
||||
public:
|
||||
Application();
|
||||
~Application();
|
||||
|
||||
|
||||
bool Initialize(const std::string& windowTitle = "USD Layer Manager", int width = 1280, int height = 720);
|
||||
void Run();
|
||||
void Shutdown();
|
||||
|
||||
|
||||
private:
|
||||
void Update();
|
||||
void RenderUI();
|
||||
@@ -34,21 +44,27 @@ private:
|
||||
void RenderStatusBar();
|
||||
void RenderStageInfo();
|
||||
void RefreshManagers();
|
||||
|
||||
|
||||
// File operations
|
||||
void OpenUsdFile();
|
||||
void CreateNewUsdFile(); // creates fresh in-memory stage
|
||||
void CreateNewUsdFile();
|
||||
void SaveUsdFile();
|
||||
void SaveUsdFileAs();
|
||||
void CloseUsdFile(); // closes file-backed stage, falls back to default stage
|
||||
void CloseUsdFile();
|
||||
|
||||
// Stage editing operations (also exposed via Stage menu)
|
||||
// Stage editing operations
|
||||
void AddReferenceToStage();
|
||||
void CreatePrimOnStage(const std::string& typeName);
|
||||
|
||||
// Playblast — called each frame while a capture is in progress.
|
||||
// Playblast
|
||||
void CapturePlayblastFrame();
|
||||
|
||||
|
||||
// Preferences
|
||||
void LoadPreferences();
|
||||
void SavePreferences();
|
||||
void ApplyPrefsToAllViewports();
|
||||
void RenderPreferencesDialog();
|
||||
|
||||
std::unique_ptr<ImGuiContext> m_imguiContext;
|
||||
std::unique_ptr<IconManager> m_iconManager;
|
||||
std::unique_ptr<UsdStageManager> m_stageManager;
|
||||
@@ -71,8 +87,18 @@ private:
|
||||
bool m_showCurveEditor;
|
||||
bool m_running;
|
||||
|
||||
MovieEncoder m_movieEncoder;
|
||||
std::string m_viewportSettingsPath; ///< %APPDATA%\UsdLayerManager\viewport_settings.ini
|
||||
MovieEncoder m_movieEncoder;
|
||||
std::string m_viewportSettingsPath;
|
||||
std::string m_prefsPath;
|
||||
AppPreferences m_prefs;
|
||||
bool m_showPreferences = false;
|
||||
|
||||
// OCIO edit buffers for Preferences dialog
|
||||
char m_prefOcioDisplayBuf[128] = {};
|
||||
char m_prefOcioViewBuf[128] = {};
|
||||
char m_prefOcioColorSpaceBuf[128] = {};
|
||||
char m_prefOcioLookBuf[128] = {};
|
||||
bool m_prefOcioFieldsSynced = false;
|
||||
};
|
||||
|
||||
} // namespace UsdLayerManager
|
||||
|
||||
+41
-22
@@ -67,6 +67,7 @@ void ViewportPanel::WireCallbacks(int i)
|
||||
BroadcastSelection();
|
||||
if (OnPrimsPickedRect) OnPrimsPickedRect(paths);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -610,6 +611,34 @@ void ViewportPanel::Render(bool* p_open)
|
||||
ImGui::PopStyleVar(); // outer WindowPadding
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Global preferences
|
||||
// ---------------------------------------------------------------------------
|
||||
void ViewportPanel::ApplyDefaultDelegate(const std::string& delegate)
|
||||
{
|
||||
if (delegate.empty()) return;
|
||||
for (auto& tile : m_tiles) {
|
||||
if (tile->GetRenderer().GetCurrentRendererId().IsEmpty())
|
||||
tile->GetRenderer().SetRendererPlugin(pxr::TfToken(delegate));
|
||||
}
|
||||
}
|
||||
|
||||
void ViewportPanel::ApplyGlobalColorCorrection(int ccMode,
|
||||
const std::string& ocioDisplay,
|
||||
const std::string& ocioView,
|
||||
const std::string& ocioColorSpace,
|
||||
const std::string& ocioLook)
|
||||
{
|
||||
for (auto& tile : m_tiles) {
|
||||
auto& r = tile->GetRenderer();
|
||||
r.SetColorCorrectionMode(static_cast<ColorCorrectionMode>(ccMode));
|
||||
r.SetOcioDisplay(ocioDisplay);
|
||||
r.SetOcioView(ocioView);
|
||||
r.SetOcioColorSpace(ocioColorSpace);
|
||||
r.SetOcioLook(ocioLook);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Settings persistence
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -626,21 +655,16 @@ void ViewportPanel::SaveSettings(const std::string& path) const
|
||||
for (int i = 0; i < static_cast<int>(m_tiles.size()); ++i) {
|
||||
ViewportTileSettings s = m_tiles[i]->GetSettings();
|
||||
f << "\n[Tile" << i << "]\n";
|
||||
f << "RenderDelegate=" << s.renderDelegate << "\n";
|
||||
f << "ShowGrid=" << (s.showGrid ? 1 : 0) << "\n";
|
||||
f << "AAEnabled=" << (s.aaEnabled ? 1 : 0) << "\n";
|
||||
f << "BgColorR=" << s.bgColorR << "\n";
|
||||
f << "BgColorG=" << s.bgColorG << "\n";
|
||||
f << "BgColorB=" << s.bgColorB << "\n";
|
||||
f << "BBoxMode=" << s.bboxMode << "\n";
|
||||
f << "AmbientLightOnly=" << (s.ambientLightOnly ? 1 : 0) << "\n";
|
||||
f << "DomeLightEnabled=" << (s.domeLightEnabled ? 1 : 0) << "\n";
|
||||
f << "ShadingMode=" << s.shadingMode << "\n";
|
||||
f << "ColorCorrectionMode=" << s.colorCorrectionMode << "\n";
|
||||
f << "OcioDisplay=" << s.ocioDisplay << "\n";
|
||||
f << "OcioView=" << s.ocioView << "\n";
|
||||
f << "OcioColorSpace=" << s.ocioColorSpace << "\n";
|
||||
f << "OcioLook=" << s.ocioLook << "\n";
|
||||
f << "RenderDelegate=" << s.renderDelegate << "\n";
|
||||
f << "ShowGrid=" << (s.showGrid ? 1 : 0) << "\n";
|
||||
f << "AAEnabled=" << (s.aaEnabled ? 1 : 0) << "\n";
|
||||
f << "BgColorR=" << s.bgColorR << "\n";
|
||||
f << "BgColorG=" << s.bgColorG << "\n";
|
||||
f << "BgColorB=" << s.bgColorB << "\n";
|
||||
f << "BBoxMode=" << s.bboxMode << "\n";
|
||||
f << "AmbientLightOnly=" << (s.ambientLightOnly ? 1 : 0) << "\n";
|
||||
f << "DomeLightEnabled=" << (s.domeLightEnabled ? 1 : 0) << "\n";
|
||||
f << "ShadingMode=" << s.shadingMode << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -697,7 +721,7 @@ void ViewportPanel::LoadSettings(const std::string& path)
|
||||
else if (key == "SplitV") splitV = toFloat(val, splitV);
|
||||
} else {
|
||||
auto& ts = tileSettings[section];
|
||||
if (key == "RenderDelegate") ts.renderDelegate = val;
|
||||
if (key == "RenderDelegate") ts.renderDelegate = val;
|
||||
else if (key == "ShowGrid") ts.showGrid = (val == "1");
|
||||
else if (key == "AAEnabled") ts.aaEnabled = (val == "1");
|
||||
else if (key == "BgColorR") ts.bgColorR = toFloat(val, ts.bgColorR);
|
||||
@@ -706,12 +730,7 @@ void ViewportPanel::LoadSettings(const std::string& path)
|
||||
else if (key == "BBoxMode") ts.bboxMode = toInt(val, ts.bboxMode);
|
||||
else if (key == "AmbientLightOnly") ts.ambientLightOnly = (val == "1");
|
||||
else if (key == "DomeLightEnabled") ts.domeLightEnabled = (val == "1");
|
||||
else if (key == "ShadingMode") ts.shadingMode = toInt(val, ts.shadingMode);
|
||||
else if (key == "ColorCorrectionMode") ts.colorCorrectionMode = toInt(val, ts.colorCorrectionMode);
|
||||
else if (key == "OcioDisplay") ts.ocioDisplay = val;
|
||||
else if (key == "OcioView") ts.ocioView = val;
|
||||
else if (key == "OcioColorSpace") ts.ocioColorSpace = val;
|
||||
else if (key == "OcioLook") ts.ocioLook = val;
|
||||
else if (key == "ShadingMode") ts.shadingMode = toInt(val, ts.shadingMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-2
@@ -52,7 +52,7 @@ public:
|
||||
// ── Main render (called from Application::RenderUI) ──────────────────────
|
||||
void Render(bool* p_open = nullptr);
|
||||
|
||||
// ── Pick callbacks (wired by Application after construction) ─────────────
|
||||
// ── Callbacks (wired by Application after construction) ──────────────────
|
||||
std::function<void(const std::string&)> OnPrimPicked;
|
||||
std::function<void(const std::vector<std::string>&)> OnPrimsPickedRect;
|
||||
|
||||
@@ -65,9 +65,18 @@ public:
|
||||
LayoutMode GetLayout() const { return m_layout; }
|
||||
int GetFocusedTileIndex() const { return m_focusedTileIndex; }
|
||||
|
||||
// ── Global preferences ────────────────────────────────────────────────────
|
||||
/// Set render delegate on tiles that have no saved delegate yet (empty token).
|
||||
/// Called once on startup so the pref default applies to fresh tiles.
|
||||
void ApplyDefaultDelegate(const std::string& delegate);
|
||||
/// Apply color correction to every tile (always global).
|
||||
void ApplyGlobalColorCorrection(int ccMode, const std::string& ocioDisplay,
|
||||
const std::string& ocioView,
|
||||
const std::string& ocioColorSpace,
|
||||
const std::string& ocioLook);
|
||||
|
||||
// ── Settings persistence ─────────────────────────────────────────────────
|
||||
/// Load layout and per-tile render settings from a simple INI file.
|
||||
/// Safe to call immediately after construction (before any Render call).
|
||||
void LoadSettings(const std::string& path);
|
||||
/// Save current layout and per-tile render settings to a simple INI file.
|
||||
void SaveSettings(const std::string& path) const;
|
||||
|
||||
+23
-151
@@ -1,6 +1,5 @@
|
||||
#include "ViewportTile.h"
|
||||
#include "../utils/Logger.h"
|
||||
#include "../utils/OcioConfigParser.h"
|
||||
|
||||
#include <pxr/usd/usdGeom/camera.h>
|
||||
#include <pxr/usd/usdGeom/xformCommonAPI.h>
|
||||
@@ -100,12 +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());
|
||||
s.colorCorrectionMode = static_cast<int>(m_renderer.GetColorCorrectionMode());
|
||||
s.ocioDisplay = m_renderer.GetOcioDisplay();
|
||||
s.ocioView = m_renderer.GetOcioView();
|
||||
s.ocioColorSpace = m_renderer.GetOcioColorSpace();
|
||||
s.ocioLook = m_renderer.GetOcioLook();
|
||||
s.shadingMode = static_cast<int>(m_renderer.GetShadingMode());
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -120,12 +114,6 @@ void ViewportTile::ApplySettings(const ViewportTileSettings& s)
|
||||
m_renderer.SetAmbientLightOnly(s.ambientLightOnly);
|
||||
m_renderer.SetDomeLightEnabled(s.domeLightEnabled);
|
||||
m_renderer.SetShadingMode(static_cast<ShadingMode>(s.shadingMode));
|
||||
m_renderer.SetColorCorrectionMode(static_cast<ColorCorrectionMode>(s.colorCorrectionMode));
|
||||
m_renderer.SetOcioDisplay(s.ocioDisplay);
|
||||
m_renderer.SetOcioView(s.ocioView);
|
||||
m_renderer.SetOcioColorSpace(s.ocioColorSpace);
|
||||
m_renderer.SetOcioLook(s.ocioLook);
|
||||
m_ocioFieldsSynced = false; // re-seed OCIO edit buffers from restored values
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -912,29 +900,31 @@ void ViewportTile::RenderCompactToolbar(int tileIndex)
|
||||
ImGui::TextDisabled("|");
|
||||
ImGui::SameLine();
|
||||
|
||||
// -- Render delegate -----------------------------------------------------
|
||||
pxr::TfToken currentId = m_renderer.GetCurrentRendererId();
|
||||
std::string displayName = currentId.IsEmpty()
|
||||
? "Rdr"
|
||||
: UsdSceneRenderer::GetRendererDisplayName(currentId);
|
||||
if (displayName.size() > 8) displayName = displayName.substr(0, 8);
|
||||
// -- Render delegate (global) --------------------------------------------
|
||||
{
|
||||
pxr::TfToken currentId = m_renderer.GetCurrentRendererId();
|
||||
std::string displayName = currentId.IsEmpty()
|
||||
? "Rdr"
|
||||
: UsdSceneRenderer::GetRendererDisplayName(currentId);
|
||||
if (displayName.size() > 8) displayName = displayName.substr(0, 8);
|
||||
|
||||
std::string rdrBtnId = "##Rdr_" + std::to_string(tileIndex);
|
||||
ImGui::Button(displayName.c_str(), ImVec2(72.0f, 0.0f));
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("Render delegate -- click to change");
|
||||
std::string rdrPopupId = "RdrPopup_" + std::to_string(tileIndex);
|
||||
ImGui::Button(displayName.c_str(), ImVec2(72.0f, 0.0f));
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("Render delegate");
|
||||
|
||||
ImGuiPopupFlags popupFlags = ImGuiPopupFlags_MouseButtonLeft;
|
||||
std::string rdrPopupId = "RdrPopup_" + std::to_string(tileIndex);
|
||||
if (ImGui::BeginPopupContextItem(rdrPopupId.c_str(), popupFlags)) {
|
||||
for (const auto& pluginId : UsdSceneRenderer::GetRendererPlugins()) {
|
||||
std::string name = UsdSceneRenderer::GetRendererDisplayName(pluginId);
|
||||
if (name.empty()) name = pluginId.GetString();
|
||||
bool selected = (pluginId == currentId);
|
||||
if (ImGui::MenuItem(name.c_str(), nullptr, selected))
|
||||
if (!selected) m_renderer.SetRendererPlugin(pluginId);
|
||||
if (ImGui::BeginPopupContextItem(rdrPopupId.c_str(),
|
||||
ImGuiPopupFlags_MouseButtonLeft))
|
||||
{
|
||||
for (const auto& pluginId : UsdSceneRenderer::GetRendererPlugins()) {
|
||||
std::string name = UsdSceneRenderer::GetRendererDisplayName(pluginId);
|
||||
if (name.empty()) name = pluginId.GetString();
|
||||
bool selected = (pluginId == currentId);
|
||||
if (ImGui::MenuItem(name.c_str(), nullptr, selected) && !selected)
|
||||
m_renderer.SetRendererPlugin(pluginId);
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
@@ -997,124 +987,6 @@ void ViewportTile::RenderCompactToolbar(int tileIndex)
|
||||
if (ImGui::BeginPopupContextItem(gearPopupId.c_str(),
|
||||
ImGuiPopupFlags_MouseButtonLeft))
|
||||
{
|
||||
// -- Color correction --------------------------------------------
|
||||
if (ImGui::BeginMenu("Color Correction")) {
|
||||
ColorCorrectionMode ccm = m_renderer.GetColorCorrectionMode();
|
||||
auto ccItem = [&](const char* label, ColorCorrectionMode mode) {
|
||||
if (ImGui::MenuItem(label, nullptr, ccm == mode)) {
|
||||
m_renderer.SetColorCorrectionMode(mode);
|
||||
m_ocioFieldsSynced = false;
|
||||
}
|
||||
};
|
||||
ccItem("Disabled", ColorCorrectionMode::Disabled);
|
||||
ccItem("sRGB", ColorCorrectionMode::sRGB);
|
||||
ccItem("OpenColorIO", ColorCorrectionMode::OpenColorIO);
|
||||
|
||||
if (ccm == ColorCorrectionMode::OpenColorIO) {
|
||||
ImGui::Separator();
|
||||
const OcioConfig& ocfg = GetCurrentOcioConfig();
|
||||
|
||||
// Seed buffers from renderer, falling back to OCIO config defaults
|
||||
if (!m_ocioFieldsSynced) {
|
||||
std::string disp = m_renderer.GetOcioDisplay();
|
||||
std::string view = m_renderer.GetOcioView();
|
||||
if (disp.empty()) disp = ocfg.defaultDisplay;
|
||||
if (view.empty()) view = ocfg.defaultView;
|
||||
strncpy(m_ocioDisplayBuf, disp.c_str(), 127);
|
||||
strncpy(m_ocioViewBuf, view.c_str(), 127);
|
||||
strncpy(m_ocioColorSpaceBuf, m_renderer.GetOcioColorSpace().c_str(), 127);
|
||||
strncpy(m_ocioLookBuf, m_renderer.GetOcioLook().c_str(), 127);
|
||||
if (m_renderer.GetOcioDisplay().empty() && !disp.empty())
|
||||
m_renderer.SetOcioDisplay(disp);
|
||||
if (m_renderer.GetOcioView().empty() && !view.empty())
|
||||
m_renderer.SetOcioView(view);
|
||||
m_ocioFieldsSynced = true;
|
||||
}
|
||||
|
||||
ImGui::PushItemWidth(200.f);
|
||||
|
||||
// Display combo
|
||||
if (ImGui::BeginCombo("Display##ocio", m_ocioDisplayBuf)) {
|
||||
for (const auto& d : ocfg.displays) {
|
||||
bool sel = (d == m_ocioDisplayBuf);
|
||||
if (ImGui::Selectable(d.c_str(), sel)) {
|
||||
strncpy(m_ocioDisplayBuf, d.c_str(), 127);
|
||||
m_renderer.SetOcioDisplay(d);
|
||||
// Auto-select default view for new display
|
||||
auto vit = ocfg.views.find(d);
|
||||
if (vit != ocfg.views.end() && !vit->second.empty()) {
|
||||
strncpy(m_ocioViewBuf, vit->second[0].c_str(), 127);
|
||||
m_renderer.SetOcioView(vit->second[0]);
|
||||
}
|
||||
}
|
||||
if (sel) ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
// View combo — filtered by current display
|
||||
{
|
||||
static const std::vector<std::string> kEmpty;
|
||||
auto vit = ocfg.views.find(std::string(m_ocioDisplayBuf));
|
||||
const auto& views = (vit != ocfg.views.end()) ? vit->second : kEmpty;
|
||||
if (ImGui::BeginCombo("View##ocio", m_ocioViewBuf)) {
|
||||
for (const auto& v : views) {
|
||||
bool sel = (v == m_ocioViewBuf);
|
||||
if (ImGui::Selectable(v.c_str(), sel)) {
|
||||
strncpy(m_ocioViewBuf, v.c_str(), 127);
|
||||
m_renderer.SetOcioView(v);
|
||||
}
|
||||
if (sel) ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
// Color Space combo
|
||||
if (ImGui::BeginCombo("Color Space##ocio",
|
||||
m_ocioColorSpaceBuf[0] ? m_ocioColorSpaceBuf : "(default)")) {
|
||||
if (ImGui::Selectable("(default)", m_ocioColorSpaceBuf[0] == '\0')) {
|
||||
m_ocioColorSpaceBuf[0] = '\0';
|
||||
m_renderer.SetOcioColorSpace("");
|
||||
}
|
||||
if (m_ocioColorSpaceBuf[0] == '\0') ImGui::SetItemDefaultFocus();
|
||||
for (const auto& cs : ocfg.colorSpaces) {
|
||||
bool sel = (cs == m_ocioColorSpaceBuf);
|
||||
if (ImGui::Selectable(cs.c_str(), sel)) {
|
||||
strncpy(m_ocioColorSpaceBuf, cs.c_str(), 127);
|
||||
m_renderer.SetOcioColorSpace(cs);
|
||||
}
|
||||
if (sel) ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
// Look combo
|
||||
if (ImGui::BeginCombo("Look##ocio",
|
||||
m_ocioLookBuf[0] ? m_ocioLookBuf : "(none)")) {
|
||||
if (ImGui::Selectable("(none)", m_ocioLookBuf[0] == '\0')) {
|
||||
m_ocioLookBuf[0] = '\0';
|
||||
m_renderer.SetOcioLook("");
|
||||
}
|
||||
if (m_ocioLookBuf[0] == '\0') ImGui::SetItemDefaultFocus();
|
||||
for (const auto& look : ocfg.looks) {
|
||||
bool sel = (look == m_ocioLookBuf);
|
||||
if (ImGui::Selectable(look.c_str(), sel)) {
|
||||
strncpy(m_ocioLookBuf, look.c_str(), 127);
|
||||
m_renderer.SetOcioLook(look);
|
||||
}
|
||||
if (sel) ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// -- Shading mode ------------------------------------------------
|
||||
if (ImGui::BeginMenu("Shading")) {
|
||||
ShadingMode cur = m_renderer.GetShadingMode();
|
||||
|
||||
+5
-16
@@ -17,23 +17,19 @@
|
||||
|
||||
namespace UsdLayerManager {
|
||||
|
||||
/// Serialisable snapshot of all per-tile render settings.
|
||||
/// Serialisable snapshot of per-tile render settings.
|
||||
/// Color correction is global (AppPreferences); render delegate is per-tile.
|
||||
struct ViewportTileSettings {
|
||||
std::string renderDelegate; ///< TfToken string, empty = default (Storm)
|
||||
std::string renderDelegate; ///< empty = use AppPreferences default on first load
|
||||
bool showGrid = true;
|
||||
bool aaEnabled = false;
|
||||
float bgColorR = 0.15f;
|
||||
float bgColorG = 0.15f;
|
||||
float bgColorB = 0.15f;
|
||||
int bboxMode = 0; ///< BBoxMode cast to int
|
||||
int bboxMode = 0;
|
||||
bool ambientLightOnly = true;
|
||||
bool domeLightEnabled = false;
|
||||
int shadingMode = 0; ///< ShadingMode cast to int (0 = SmoothShaded)
|
||||
int colorCorrectionMode = 1; ///< ColorCorrectionMode cast to int (1 = sRGB)
|
||||
std::string ocioDisplay;
|
||||
std::string ocioView;
|
||||
std::string ocioColorSpace;
|
||||
std::string ocioLook;
|
||||
int shadingMode = 0;
|
||||
};
|
||||
|
||||
/// Named orthographic view directions.
|
||||
@@ -183,13 +179,6 @@ private:
|
||||
// ── Orthographic view ────────────────────────────────────────────────────
|
||||
OrthoView m_orthoView = OrthoView::None;
|
||||
|
||||
// ── OCIO InputText edit buffers (per-tile, seeded on mode activation) ────
|
||||
char m_ocioDisplayBuf[128] = {};
|
||||
char m_ocioViewBuf[128] = {};
|
||||
char m_ocioColorSpaceBuf[128] = {};
|
||||
char m_ocioLookBuf[128] = {};
|
||||
bool m_ocioFieldsSynced = false;
|
||||
|
||||
// ── Per-frame interaction flags ──────────────────────────────────────────
|
||||
bool m_wasClickedThisFrame = false;
|
||||
bool m_wasHoveredThisFrame = false;
|
||||
|
||||
Reference in New Issue
Block a user