Fix sublayers not persisted on save
- SaveStage: explicitly call rootLayer->Save() before m_stage->Save() to ensure root-layer metadata (subLayers field) is always written to disk - SaveUsdFile: redirect to SaveAs when the root layer is anonymous so Ctrl+S on an in-memory stage no longer silently does nothing - SaveUsdFileAs: call RefreshManagers() after SaveStageAs so LayerManager stays in sync with the newly opened file-backed stage; without this, sublayers added after a Save As went to the old stale stage and were lost - LayerCreateCommand::Execute: use GetSublayers() (sublayer-local indices) instead of GetLayerStack() (full-stack indices) to record m_insertedIndex, fixing undo of add-sublayer removing the wrong layer Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -134,6 +134,12 @@ bool UsdStageManager::SaveStage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
SdfLayerHandle rootLayer = m_stage->GetRootLayer();
|
||||
if (!rootLayer || rootLayer->IsAnonymous()) {
|
||||
SetError("Stage has no file path — use Save As to save to disk");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
LOG_INFO("Saving USD stage");
|
||||
|
||||
@@ -142,6 +148,13 @@ bool UsdStageManager::SaveStage() {
|
||||
// cannot be saved by UsdStage::Save() itself).
|
||||
MergeSessionLayerIntoRoot(m_stage);
|
||||
|
||||
// Explicitly save the root layer first. UsdStage::Save() iterates
|
||||
// the PCP composition stack and saves dirty layers, but sublayer-path
|
||||
// edits (InsertSubLayerPath) are root-layer metadata changes that may
|
||||
// not be flushed by stage-level Save() in all USD versions.
|
||||
rootLayer->Save();
|
||||
|
||||
// Save any other dirty sublayers that have file paths.
|
||||
m_stage->Save();
|
||||
LOG_INFO("Successfully saved USD stage");
|
||||
return true;
|
||||
|
||||
@@ -15,15 +15,15 @@ LayerCreateCommand::LayerCreateCommand(LayerManager* mgr, std::string path, int
|
||||
|
||||
void LayerCreateCommand::Execute() {
|
||||
if (!m_mgr) return;
|
||||
// Record how many sublayers exist before insert to compute the real index used.
|
||||
auto before = m_mgr->GetLayerStack().size();
|
||||
auto before = m_mgr->GetSublayers().size();
|
||||
m_mgr->CreateSublayer(m_path, m_index);
|
||||
auto after = m_mgr->GetLayerStack().size();
|
||||
// If a layer was actually inserted, compute its index.
|
||||
if (after > before) {
|
||||
auto layers = m_mgr->GetLayerStack();
|
||||
for (int i = 0; i < static_cast<int>(layers.size()); ++i) {
|
||||
if (layers[i].identifier == m_path || layers[i].displayName == m_path) {
|
||||
// Find the sublayer-local index so Undo() can call RemoveSublayer() correctly.
|
||||
// RemoveSublayer() uses indices into GetSubLayerPaths() (0..N-1), not the full
|
||||
// layer stack that includes session and root layers.
|
||||
auto sublayers = m_mgr->GetSublayers();
|
||||
if (sublayers.size() > before) {
|
||||
for (int i = 0; i < static_cast<int>(sublayers.size()); ++i) {
|
||||
if (sublayers[i].identifier == m_path) {
|
||||
m_insertedIndex = i;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -398,6 +398,14 @@ void Application::SaveUsdFile() {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the current stage is in-memory (anonymous root layer), fall through to
|
||||
// Save As — UsdStage::Save() cannot write anonymous layers to disk.
|
||||
auto rootLayer = m_stageManager->GetRootLayer();
|
||||
if (!rootLayer || rootLayer->IsAnonymous()) {
|
||||
SaveUsdFileAs();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_stageManager->SaveStage()) {
|
||||
LOG_ERROR("Failed to save USD file: " + m_stageManager->GetLastError());
|
||||
}
|
||||
@@ -418,6 +426,12 @@ void Application::SaveUsdFileAs() {
|
||||
if (!filePath.empty()) {
|
||||
if (!m_stageManager->SaveStageAs(filePath)) {
|
||||
LOG_ERROR("Failed to save USD file: " + m_stageManager->GetLastError());
|
||||
} else {
|
||||
// SaveStageAs reopens m_stageManager's stage from the new file path.
|
||||
// RefreshManagers syncs m_layerManager (and others) to that new stage;
|
||||
// without this, subsequent sublayer edits go to the old (now stale) stage
|
||||
// and are silently lost on the next save.
|
||||
RefreshManagers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user