diff --git a/src/core/UsdStageManager.cpp b/src/core/UsdStageManager.cpp index 2e18805..45f2ac3 100644 --- a/src/core/UsdStageManager.cpp +++ b/src/core/UsdStageManager.cpp @@ -133,7 +133,13 @@ bool UsdStageManager::SaveStage() { SetError("No stage to save"); 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,10 +148,17 @@ 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; - + } catch (const std::exception& e) { SetError(std::string("Exception while saving stage: ") + e.what()); return false; diff --git a/src/core/commands/LayerCommands.cpp b/src/core/commands/LayerCommands.cpp index 5361484..b665d0f 100644 --- a/src/core/commands/LayerCommands.cpp +++ b/src/core/commands/LayerCommands.cpp @@ -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(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(sublayers.size()); ++i) { + if (sublayers[i].identifier == m_path) { m_insertedIndex = i; break; } diff --git a/src/ui/Application.cpp b/src/ui/Application.cpp index 8745ee0..1ec0395 100644 --- a/src/ui/Application.cpp +++ b/src/ui/Application.cpp @@ -397,7 +397,15 @@ void Application::SaveUsdFile() { if (!m_stageManager->HasStage()) { 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()); } @@ -407,17 +415,23 @@ void Application::SaveUsdFileAs() { if (!m_stageManager->HasStage()) { return; } - + std::string filePath = FileDialog::SaveFile( "USD Files (*.usd;*.usda;*.usdc)\0*.usd;*.usda;*.usdc\0All Files (*.*)\0*.*\0", "Save USD File As", "usd", m_imguiContext->GetWindowHandle() ); - + 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(); } } }