Add per-viewport render settings persistence (delegate, grid, AA, bg, bbox, lighting)
ViewportTileSettings struct captures: render delegate, show grid, AA, background color, bbox mode, ambient-light-only, dome-light flags. ViewportPanel::SaveSettings() writes a simple INI file (layout + one [TileN] section per tile) to %APPDATA%\UsdLayerManager\viewport_settings.ini on Application::Shutdown(). ViewportPanel::LoadSettings() is called at the end of Application::Initialize() — after the viewport panel is constructed but before the first frame — so the saved render delegate is picked up by UsdSceneRenderer::InitRenderer() on the first Render() call. Layout (Single/HSplit/VSplit/Quad) and split ratios are also restored, creating the correct number of tiles before settings are applied. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -138,6 +138,15 @@ bool Application::Initialize(const std::string& windowTitle, int width, int heig
|
||||
RefreshManagers();
|
||||
}
|
||||
|
||||
// Load per-viewport settings (render delegate, grid, AA, etc.) 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_viewportPanel->LoadSettings(m_viewportSettingsPath);
|
||||
}
|
||||
|
||||
LOG_INFO("Application initialized successfully");
|
||||
return true;
|
||||
}
|
||||
@@ -155,6 +164,9 @@ void Application::Run() {
|
||||
}
|
||||
|
||||
void Application::Shutdown() {
|
||||
if (m_viewportPanel && !m_viewportSettingsPath.empty())
|
||||
m_viewportPanel->SaveSettings(m_viewportSettingsPath);
|
||||
|
||||
m_viewportPanel.reset();
|
||||
m_sceneHierarchyPanel.reset();
|
||||
m_propertyPanel.reset();
|
||||
|
||||
@@ -72,6 +72,7 @@ private:
|
||||
bool m_running;
|
||||
|
||||
MovieEncoder m_movieEncoder;
|
||||
std::string m_viewportSettingsPath; ///< %APPDATA%\UsdLayerManager\viewport_settings.ini
|
||||
};
|
||||
|
||||
} // namespace UsdLayerManager
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <imgui.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
namespace UsdLayerManager {
|
||||
|
||||
@@ -608,4 +610,109 @@ void ViewportPanel::Render(bool* p_open)
|
||||
ImGui::PopStyleVar(); // outer WindowPadding
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Settings persistence
|
||||
// ---------------------------------------------------------------------------
|
||||
void ViewportPanel::SaveSettings(const std::string& path) const
|
||||
{
|
||||
std::ofstream f(path);
|
||||
if (!f) return;
|
||||
|
||||
f << "[Viewport]\n";
|
||||
f << "Layout=" << static_cast<int>(m_layout) << "\n";
|
||||
f << "SplitH=" << m_splitH << "\n";
|
||||
f << "SplitV=" << m_splitV << "\n";
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
void ViewportPanel::LoadSettings(const std::string& path)
|
||||
{
|
||||
std::ifstream f(path);
|
||||
if (!f) return;
|
||||
|
||||
int layoutMode = static_cast<int>(m_layout);
|
||||
float splitH = m_splitH;
|
||||
float splitV = m_splitV;
|
||||
std::vector<ViewportTileSettings> tileSettings; // indexed by tile number
|
||||
|
||||
int section = -1; // -1=Viewport, >=0 = tile index
|
||||
std::string line;
|
||||
while (std::getline(f, line)) {
|
||||
// Strip leading whitespace and CR
|
||||
while (!line.empty() && (line.front() == ' ' || line.front() == '\t'))
|
||||
line.erase(line.begin());
|
||||
if (!line.empty() && line.back() == '\r')
|
||||
line.pop_back();
|
||||
if (line.empty() || line.front() == '#') continue;
|
||||
|
||||
if (line.front() == '[') {
|
||||
size_t close = line.find(']');
|
||||
if (close == std::string::npos) continue;
|
||||
std::string name = line.substr(1, close - 1);
|
||||
if (name == "Viewport") {
|
||||
section = -1;
|
||||
} else if (name.size() > 4 && name.substr(0, 4) == "Tile") {
|
||||
try {
|
||||
int idx = std::stoi(name.substr(4));
|
||||
if (idx >= 0) {
|
||||
section = idx;
|
||||
if (static_cast<int>(tileSettings.size()) <= idx)
|
||||
tileSettings.resize(idx + 1);
|
||||
}
|
||||
} catch (...) { section = -1; }
|
||||
}
|
||||
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);
|
||||
|
||||
auto toInt = [](const std::string& v, int def) { try { return std::stoi(v); } catch (...) { return def; } };
|
||||
auto toFloat = [](const std::string& v, float def) { try { return std::stof(v); } catch (...) { return def; } };
|
||||
|
||||
if (section == -1) {
|
||||
if (key == "Layout") layoutMode = toInt(val, layoutMode);
|
||||
else if (key == "SplitH") splitH = toFloat(val, splitH);
|
||||
else if (key == "SplitV") splitV = toFloat(val, splitV);
|
||||
} else {
|
||||
auto& ts = tileSettings[section];
|
||||
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);
|
||||
else if (key == "BgColorG") ts.bgColorG = toFloat(val, ts.bgColorG);
|
||||
else if (key == "BgColorB") ts.bgColorB = toFloat(val, ts.bgColorB);
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
// Apply layout (creates/destroys tiles as needed)
|
||||
m_splitH = splitH;
|
||||
m_splitV = splitV;
|
||||
SetLayout(static_cast<LayoutMode>(std::clamp(layoutMode, 0, 3)));
|
||||
|
||||
// Apply per-tile settings to whichever tiles now exist
|
||||
for (int i = 0; i < static_cast<int>(tileSettings.size()); ++i) {
|
||||
if (i < static_cast<int>(m_tiles.size()))
|
||||
m_tiles[i]->ApplySettings(tileSettings[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace UsdLayerManager
|
||||
|
||||
@@ -65,6 +65,13 @@ public:
|
||||
LayoutMode GetLayout() const { return m_layout; }
|
||||
int GetFocusedTileIndex() const { return m_focusedTileIndex; }
|
||||
|
||||
// ── 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;
|
||||
|
||||
|
||||
private:
|
||||
// ── Tile rect helper ─────────────────────────────────────────────────────
|
||||
|
||||
@@ -87,6 +87,33 @@ void ViewportTile::FrameScene()
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
ViewportTileSettings ViewportTile::GetSettings() const
|
||||
{
|
||||
ViewportTileSettings s;
|
||||
s.renderDelegate = m_renderer.GetCurrentRendererId().GetString();
|
||||
s.showGrid = m_renderer.ShowGrid();
|
||||
s.aaEnabled = m_renderer.GetAAEnabled();
|
||||
const pxr::GfVec3f& bg = m_renderer.GetBackgroundColor();
|
||||
s.bgColorR = bg[0]; s.bgColorG = bg[1]; s.bgColorB = bg[2];
|
||||
s.bboxMode = static_cast<int>(m_renderer.GetBBoxMode());
|
||||
s.ambientLightOnly = m_renderer.GetAmbientLightOnly();
|
||||
s.domeLightEnabled = m_renderer.GetDomeLightEnabled();
|
||||
return s;
|
||||
}
|
||||
|
||||
void ViewportTile::ApplySettings(const ViewportTileSettings& s)
|
||||
{
|
||||
if (!s.renderDelegate.empty())
|
||||
m_renderer.SetRendererPlugin(pxr::TfToken(s.renderDelegate));
|
||||
m_renderer.SetShowGrid(s.showGrid);
|
||||
m_renderer.SetAAEnabled(s.aaEnabled);
|
||||
m_renderer.SetBackgroundColor(pxr::GfVec3f(s.bgColorR, s.bgColorG, s.bgColorB));
|
||||
m_renderer.SetBBoxMode(static_cast<BBoxMode>(s.bboxMode));
|
||||
m_renderer.SetAmbientLightOnly(s.ambientLightOnly);
|
||||
m_renderer.SetDomeLightEnabled(s.domeLightEnabled);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
void ViewportTile::RefreshCameraList()
|
||||
{
|
||||
|
||||
@@ -17,6 +17,19 @@
|
||||
|
||||
namespace UsdLayerManager {
|
||||
|
||||
/// Serialisable snapshot of all per-tile render settings.
|
||||
struct ViewportTileSettings {
|
||||
std::string renderDelegate; ///< TfToken string, empty = default (Storm)
|
||||
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
|
||||
bool ambientLightOnly = false;
|
||||
bool domeLightEnabled = false;
|
||||
};
|
||||
|
||||
/// Named orthographic view directions.
|
||||
/// When m_orthoView != None the tile renders an orthographic camera locked to
|
||||
/// that world-space direction; the free-camera orbital state (center + dist)
|
||||
@@ -87,6 +100,11 @@ public:
|
||||
|
||||
void FrameScene();
|
||||
|
||||
/// Snapshot all current render settings into a portable struct.
|
||||
ViewportTileSettings GetSettings() const;
|
||||
/// Apply a previously-saved settings snapshot (safe to call before first Render).
|
||||
void ApplySettings(const ViewportTileSettings& s);
|
||||
|
||||
private:
|
||||
// ── Render sub-functions ─────────────────────────────────────────────────
|
||||
pxr::GfCamera ResolveCamera();
|
||||
|
||||
Reference in New Issue
Block a user