Auto-save the active render layer's sublayer file
Render layer overrides only reached disk on an explicit File > Save -- SaveDirtyRenderLayers() was called from SaveUsdFile/SaveUsdFileAs and nowhere else. Everything a user authored after switching to a render layer (property values, shader parameters, material assignments) sat in a dirty in-memory SdfLayer marked with an orange asterisk, and a crash took the whole layer's overrides with it. Application::Update() now polls the active render layer's IsDirty() and saves it 0.5s after the user goes idle, gated on IsAnyItemActive() and the left mouse button so a slider or gizmo drag produces one write on release rather than one per frame. Polling rather than hooking CommandHistory::Push/Undo/Redo is deliberate: many of the writes this is meant to catch never build a command and author straight to the ambient edit target -- PropertyPanel's live WriteTranslate/Rotate/Scale and its generic attribute widgets, TransformManipulator's gizmo drags, and MaterialEditorPanel::RenderInputWidget's shader input writes. A command hook would have silently missed exactly the property and shader-parameter edits at issue. IsDirty() catches every path, commanded or not. Scope is the active layer only. Muted render layers still rely on SaveDirtyRenderLayers() at save time, and the root layer is never auto-written -- so the persisted active-layer choice (custom layer data on the root layer) still only survives a reopen once the stage itself is saved. Auto-writing the user's main scene file was ruled out. - SaveRenderLayerIfDirty() refreshes LayerManager after a successful save, or the cached isDirty snapshot leaves a stale asterisk in StageEditorPanel and the Scene Hierarchy sublayer list. A failed save latches the layer id so a read-only file can't spam the log twice a second. - Switching layers flushes the outgoing one, and Shutdown() flushes before the panels are destroyed, so edits inside the debounce window aren't stranded. - RefreshManagers() clears the auto-save state, whose layer ids belong to the outgoing stage. - New "Auto-save active layer" checkbox in the Render Layer panel, on by default, persisted as AutoSaveRenderLayer in preferences.ini. See docs/adr/0002-render-layer.md D9-D11 for the rationale. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,8 @@ struct AppPreferences {
|
||||
/// customData so they survive reopening the material; when false, that
|
||||
/// state is session-only.
|
||||
bool keepGraphNodeViewSettingsInUsd = false;
|
||||
/// Auto-save the active render layer's SdfLayer shortly after each edit.
|
||||
bool autoSaveRenderLayer = true;
|
||||
};
|
||||
|
||||
class Application {
|
||||
@@ -73,6 +75,20 @@ private:
|
||||
/// rest would otherwise be silently dropped on save.
|
||||
void SaveDirtyRenderLayers();
|
||||
|
||||
/// Per-frame debounce driving the active render layer's auto-save.
|
||||
/// Polls SdfLayer::IsDirty() rather than hooking CommandHistory because
|
||||
/// many write paths (PropertyPanel's live transform/attribute widgets,
|
||||
/// TransformManipulator's gizmo drags, MaterialEditorPanel's shader input
|
||||
/// widgets) author straight to the ambient edit target without going
|
||||
/// through a command — a command hook would silently miss them.
|
||||
void TickRenderLayerAutoSave(float deltaTime);
|
||||
/// Saves the active render layer's SdfLayer if it's dirty. Returns true
|
||||
/// only when a save actually happened.
|
||||
bool FlushActiveRenderLayerSave();
|
||||
/// Saves one render layer by identifier if it's dirty; no-op for an empty
|
||||
/// id (Default active) or a layer whose previous save failed.
|
||||
bool SaveRenderLayerIfDirty(const std::string& layerId);
|
||||
|
||||
// Playblast
|
||||
void CapturePlayblastFrame();
|
||||
|
||||
@@ -120,6 +136,13 @@ private:
|
||||
AppPreferences m_prefs;
|
||||
bool m_showPreferences = false;
|
||||
|
||||
// Render-layer auto-save state (see TickRenderLayerAutoSave).
|
||||
float m_renderLayerAutoSaveTimer = 0.0f;
|
||||
std::string m_renderLayerAutoSaveLastActiveId;
|
||||
// Identifier of a render layer whose Save() failed — retried only after the
|
||||
// active layer changes, so a read-only file can't spam the log every tick.
|
||||
std::string m_renderLayerAutoSaveFailedId;
|
||||
|
||||
// OCIO edit buffers for Preferences dialog
|
||||
char m_prefOcioDisplayBuf[128] = {};
|
||||
char m_prefOcioViewBuf[128] = {};
|
||||
|
||||
Reference in New Issue
Block a user