source save asset-free WIP
Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com>
This commit is contained in:
@@ -186,6 +186,7 @@ namespace ScriptCanvasEditor
|
||||
, AZ::IO::GenericStream* stream
|
||||
, [[maybe_unused]] AZ::DataStream::StreamType streamType)
|
||||
{
|
||||
// #sc_editor_asset delete usage of this, and route to ScriptCanvasEditor::SaveToStream
|
||||
namespace JSRU = AZ::JsonSerializationUtils;
|
||||
using namespace ScriptCanvas;
|
||||
|
||||
|
||||
@@ -139,4 +139,64 @@ namespace ScriptCanvasEditor
|
||||
|
||||
return AZ::Success(ScriptCanvasEditor::SourceHandle(scriptCanvasData, {}, path));
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> SaveToStream(const SourceHandle& source, AZ::IO::GenericStream& stream)
|
||||
{
|
||||
namespace JSRU = AZ::JsonSerializationUtils;
|
||||
|
||||
if (!source)
|
||||
{
|
||||
return AZ::Failure(AZStd::string("no source graph to save"));
|
||||
}
|
||||
|
||||
if (source.Path().empty())
|
||||
{
|
||||
return AZ::Failure(AZStd::string("no destination path specified"));
|
||||
}
|
||||
|
||||
AZ::SerializeContext* serializeContext = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
|
||||
if (!serializeContext)
|
||||
{
|
||||
return AZ::Failure(AZStd::string("no serialize context available to properly save source file"));
|
||||
}
|
||||
|
||||
auto graphData = source.Get()->GetOwnership();
|
||||
if (!graphData)
|
||||
{
|
||||
return AZ::Failure(AZStd::string("source is missing save container"));
|
||||
}
|
||||
|
||||
if (graphData->GetEditorGraph() != source.Get())
|
||||
{
|
||||
return AZ::Failure(AZStd::string("source save container refers to incorrect graph"));
|
||||
}
|
||||
|
||||
auto saveTarget = graphData->ModGraph();
|
||||
if (saveTarget || !saveTarget->GetGraphData())
|
||||
{
|
||||
return AZ::Failure(AZStd::string("source save container failed to return graph data"));
|
||||
}
|
||||
|
||||
AZ::JsonSerializerSettings settings;
|
||||
settings.m_metadata.Create<ScriptCanvas::SerializationListeners>();
|
||||
auto listeners = settings.m_metadata.Find<ScriptCanvas::SerializationListeners>();
|
||||
AZ_Assert(listeners, "Failed to create SerializationListeners");
|
||||
ScriptCanvasFileHandlingCpp::CollectNodes(saveTarget->GetGraphData()->m_nodes, *listeners);
|
||||
settings.m_keepDefaults = false;
|
||||
settings.m_serializeContext = serializeContext;
|
||||
|
||||
for (auto listener : *listeners)
|
||||
{
|
||||
listener->OnSerialize();
|
||||
}
|
||||
|
||||
auto saveOutcome = JSRU::SaveObjectToStream<ScriptCanvas::ScriptCanvasData>(graphData.get(), stream, nullptr, &settings);
|
||||
if (!saveOutcome.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(AZStd::string("JSON serialization failed to save source: %s", saveOutcome.GetError().c_str()));
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1067,6 +1067,11 @@ namespace ScriptCanvasEditor
|
||||
m_owner = &owner;
|
||||
}
|
||||
|
||||
ScriptCanvas::DataPtr Graph::GetOwnership() const
|
||||
{
|
||||
return ScriptCanvas::DataPtr(const_cast<Graph*>(this)->m_owner);
|
||||
}
|
||||
|
||||
bool Graph::CreateConnection(const GraphCanvas::ConnectionId& connectionId, const GraphCanvas::Endpoint& sourcePoint, const GraphCanvas::Endpoint& targetPoint)
|
||||
{
|
||||
if (!sourcePoint.IsValid() || !targetPoint.IsValid())
|
||||
|
||||
+4
-2
@@ -26,10 +26,12 @@ namespace ScriptCanvas
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
AZ::Outcome<ScriptCanvasEditor::SourceHandle, AZStd::string> LoadFromFile(AZStd::string_view path);
|
||||
AZ::Outcome<SourceHandle, AZStd::string> LoadFromFile(AZStd::string_view path);
|
||||
|
||||
AZ::Outcome<void, AZStd::string> LoadDataFromJson
|
||||
( ScriptCanvas::ScriptCanvasData& dataTarget
|
||||
, AZStd::string_view source
|
||||
, AZ::SerializeContext& serializeContext);
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> SaveToStream(const SourceHandle& source, AZ::IO::GenericStream& stream);
|
||||
}
|
||||
|
||||
@@ -309,6 +309,7 @@ namespace ScriptCanvasEditor
|
||||
const GraphStatisticsHelper& GetNodeUsageStatistics() const;
|
||||
|
||||
void MarkOwnership(ScriptCanvas::ScriptCanvasData& owner);
|
||||
ScriptCanvas::DataPtr GetOwnership() const;
|
||||
|
||||
// Finds and returns all nodes within the graph that are of the specified type
|
||||
template <typename NodeType>
|
||||
@@ -393,6 +394,7 @@ namespace ScriptCanvasEditor
|
||||
bool m_saveFormatConverted = true;
|
||||
|
||||
ScriptCanvasEditor::SourceHandle m_assetId;
|
||||
// #sc_editor_asset temporary step in cleaning up the graph / asset class structure. This reference is deliberately weak.
|
||||
ScriptCanvas::ScriptCanvasData* m_owner;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1723,17 +1723,18 @@ namespace ScriptCanvasEditor
|
||||
// return AZ::Success(outTabIndex);
|
||||
}
|
||||
|
||||
bool MainWindow::OnFileSave(const Callbacks::OnSave& saveCB)
|
||||
bool MainWindow::OnFileSave()
|
||||
{
|
||||
return SaveAssetAsImpl(m_activeGraph, saveCB);
|
||||
return SaveAssetImpl(m_activeGraph, Save::InPlace);
|
||||
}
|
||||
|
||||
bool MainWindow::OnFileSaveAs(const Callbacks::OnSave& saveCB)
|
||||
bool MainWindow::OnFileSaveAs()
|
||||
{
|
||||
return SaveAssetAsImpl(m_activeGraph, saveCB);
|
||||
return SaveAssetImpl(m_activeGraph, Save::As);
|
||||
}
|
||||
|
||||
bool MainWindow::SaveAssetImpl(const ScriptCanvasEditor::SourceHandle& assetId, const Callbacks::OnSave& saveCB)
|
||||
/*
|
||||
bool MainWindow::SaveAssetImpl_OLD(const ScriptCanvasEditor::SourceHandle& assetId, const Callbacks::OnSave& saveCB)
|
||||
{
|
||||
if (!assetId.IsValid())
|
||||
{
|
||||
@@ -1748,7 +1749,7 @@ namespace ScriptCanvasEditor
|
||||
|
||||
if (fileState == Tracker::ScriptCanvasFileState::NEW)
|
||||
{
|
||||
saveSuccessful = SaveAssetAsImpl(assetId, saveCB);
|
||||
saveSuccessful = SaveAssetImpl(assetId, saveCB);
|
||||
}
|
||||
else if (fileState == Tracker::ScriptCanvasFileState::MODIFIED
|
||||
|| fileState == Tracker::ScriptCanvasFileState::SOURCE_REMOVED)
|
||||
@@ -1759,8 +1760,16 @@ namespace ScriptCanvasEditor
|
||||
|
||||
return saveSuccessful;
|
||||
}
|
||||
*/
|
||||
|
||||
bool MainWindow::SaveAssetAsImpl(const ScriptCanvasEditor::SourceHandle& inMemoryAssetId, const Callbacks::OnSave& saveCB)
|
||||
|
||||
// 1. SaveAssetImpl
|
||||
// 2. SaveAs
|
||||
// // 3. OnSaveCallback
|
||||
// SaveAsEnd
|
||||
// SaveAssetImpl end
|
||||
|
||||
bool MainWindow::SaveAssetImpl(const ScriptCanvasEditor::SourceHandle& inMemoryAssetId, Save /*save*/)
|
||||
{
|
||||
if (!inMemoryAssetId.IsValid())
|
||||
{
|
||||
@@ -1803,11 +1812,12 @@ namespace ScriptCanvasEditor
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@engroot@", assetRootChar.data(), assetRootChar.size());
|
||||
assetRoot = assetRootChar.data();
|
||||
|
||||
/* if (!AZ::StringFunc::StartsWith(filePath, assetRoot))
|
||||
{
|
||||
QMessageBox::information(this, "Unable to Save", AZStd::string::format("You must select a path within the current project\n\n%s", assetRoot.c_str()).c_str());
|
||||
}
|
||||
else*/ if (AzFramework::StringFunc::Path::GetFileName(filePath.c_str(), fileName))
|
||||
// if (!AZ::StringFunc::StartsWith(filePath, assetRoot))
|
||||
// {
|
||||
// QMessageBox::information(this, "Unable to Save", AZStd::string::format("You must select a path within the current project\n\n%s", assetRoot.c_str()).c_str());
|
||||
// }
|
||||
// else
|
||||
if (AzFramework::StringFunc::Path::GetFileName(filePath.c_str(), fileName))
|
||||
{
|
||||
isValidFileName = !(fileName.empty());
|
||||
}
|
||||
@@ -1833,7 +1843,7 @@ namespace ScriptCanvasEditor
|
||||
return false;
|
||||
}
|
||||
|
||||
SaveAs(internalStringFile, inMemoryAssetId, saveCB);
|
||||
SaveAs(internalStringFile, inMemoryAssetId);
|
||||
|
||||
m_newlySavedFile = internalStringFile;
|
||||
|
||||
@@ -1842,103 +1852,95 @@ namespace ScriptCanvasEditor
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::OnSaveCallback(bool /*saveSuccess*/, AZ::Data::AssetPtr /*fileAsset*/, ScriptCanvasEditor::SourceHandle /*previousFileAssetId*/)
|
||||
void MainWindow::OnSaveCallback(bool saveSuccess, ScriptCanvasEditor::SourceHandle memoryAsset)
|
||||
{
|
||||
// #sc_editor_asset yikes...just save the thing...move to ::SaveAsset maybe
|
||||
|
||||
/*
|
||||
ScriptCanvasMemoryAsset::pointer memoryAsset;
|
||||
AZStd::string tabName = m_tabBar->tabText(m_tabBar->currentIndex()).toUtf8().data();
|
||||
|
||||
int saveTabIndex = m_tabBar->currentIndex();
|
||||
int saveTabIndex = m_tabBar->FindTab(memoryAsset);
|
||||
AZStd::string tabName = saveTabIndex >= 0 ? m_tabBar->tabText(saveTabIndex).toUtf8().data() : "";
|
||||
|
||||
if (saveSuccess)
|
||||
{
|
||||
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, fileAsset->GetId());
|
||||
AZ_Assert(memoryAsset, "At this point we must have a MemoryAsset");
|
||||
|
||||
// #sc_editor_asset find a tab with the same path name and close non focused old ones with the same name
|
||||
// Update the editor with the new information about this asset.
|
||||
const ScriptCanvasEditor::SourceHandle& fileAssetId = memoryAsset->GetFileAssetId();
|
||||
|
||||
saveTabIndex = m_tabBar->FindTab(fileAssetId);
|
||||
|
||||
const ScriptCanvasEditor::SourceHandle& fileAssetId = memoryAsset;
|
||||
// We've saved as over a new graph, so we need to close the old one.
|
||||
if (saveTabIndex != m_tabBar->currentIndex())
|
||||
{
|
||||
// Invalidate the file asset id so we don't delete trigger the asset flow.
|
||||
m_tabBar->setTabData(saveTabIndex, QVariant::fromValue(GraphTabMetaData));
|
||||
|
||||
m_tabBar->setTabData(saveTabIndex, QVariant::fromValue(Widget::GraphTabMetadata()));
|
||||
m_tabBar->CloseTab(saveTabIndex);
|
||||
saveTabIndex = -1;
|
||||
}
|
||||
|
||||
// #sc_editor_asset clean up these actions as well, save and close, save as and close, just save, etc
|
||||
if (saveTabIndex < 0)
|
||||
{
|
||||
// This asset had not been saved yet, we will need to use the in memory asset Id to get the index.
|
||||
saveTabIndex = m_tabBar->FindTab(memoryAsset->GetId());
|
||||
// saveTabIndex = m_tabBar->FindTab(memoryAsset->GetId());
|
||||
|
||||
if (saveTabIndex < 0)
|
||||
{
|
||||
// Finally, we may have Saved-As and we need the previous file asset Id to find the tab
|
||||
saveTabIndex = m_tabBar->FindTab(previousFileAssetId);
|
||||
//saveTabIndex = m_tabBar->FindTab(previousFileAssetId);
|
||||
}
|
||||
}
|
||||
|
||||
AzFramework::StringFunc::Path::GetFileName(memoryAsset->GetAbsolutePath().c_str(), tabName);
|
||||
AzFramework::StringFunc::Path::GetFileName(memoryAsset.Path().c_str(), tabName);
|
||||
|
||||
// Update the tab's assetId to the file asset Id (necessary when saving a new asset)
|
||||
// used to be configure tab...sets the name and file state
|
||||
m_tabBar->ConfigureTab(saveTabIndex, fileAssetId, tabName);
|
||||
// #sc_editor_asset used to be configure tab...sets the name and file state
|
||||
// m_tabBar->ConfigureTab(saveTabIndex, fileAssetId, tabName);
|
||||
|
||||
GeneralAssetNotificationBus::Event(memoryAsset->GetId(), &GeneralAssetNotifications::OnAssetVisualized);
|
||||
|
||||
auto requestorIter = m_assetCreationRequests.find(fileAsset->GetId());
|
||||
|
||||
if (requestorIter != m_assetCreationRequests.end())
|
||||
{
|
||||
auto editorComponents = AZ::EntityUtils::FindDerivedComponents<EditorScriptCanvasComponent>(requestorIter->second.first);
|
||||
|
||||
if (editorComponents.empty())
|
||||
{
|
||||
auto firstRequestBus = EditorScriptCanvasComponentRequestBus::FindFirstHandler(requestorIter->second.first);
|
||||
|
||||
if (firstRequestBus)
|
||||
{
|
||||
firstRequestBus->SetAssetId(fileAsset->GetId());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto editorComponent : editorComponents)
|
||||
{
|
||||
if (editorComponent->GetId() == requestorIter->second.second)
|
||||
{
|
||||
editorComponent->SetAssetId(fileAsset->GetId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_assetCreationRequests.erase(requestorIter);
|
||||
}
|
||||
// GeneralAssetNotificationBus::Event(memoryAsset, &GeneralAssetNotifications::OnAssetVisualized);
|
||||
//
|
||||
// auto requestorIter = m_assetCreationRequests.find(fileAsset->GetId());
|
||||
//
|
||||
// if (requestorIter != m_assetCreationRequests.end())
|
||||
// {
|
||||
// auto editorComponents = AZ::EntityUtils::FindDerivedComponents<EditorScriptCanvasComponent>(requestorIter->second.first);
|
||||
//
|
||||
// if (editorComponents.empty())
|
||||
// {
|
||||
// auto firstRequestBus = EditorScriptCanvasComponentRequestBus::FindFirstHandler(requestorIter->second.first);
|
||||
//
|
||||
// if (firstRequestBus)
|
||||
// {
|
||||
// firstRequestBus->SetAssetId(fileAsset->GetId());
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// for (auto editorComponent : editorComponents)
|
||||
// {
|
||||
// if (editorComponent->GetId() == requestorIter->second.second)
|
||||
// {
|
||||
// editorComponent->SetAssetId(fileAsset->GetId());
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// m_assetCreationRequests.erase(requestorIter);
|
||||
// }
|
||||
|
||||
// Soft switch the asset id here. We'll do a double scene switch down below to actually switch the active assetid
|
||||
m_activeGraph = fileAssetId;
|
||||
}
|
||||
else
|
||||
{
|
||||
// #sc_editor_asset this seems to remove the unsaved indicator even on failure
|
||||
|
||||
// Use the previous memory asset to find what we had setup as our display
|
||||
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, m_activeGraph);
|
||||
// AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, m_activeGraph);
|
||||
|
||||
// Drop off our file modifier status for our display name when we fail to save.
|
||||
if (tabName.at(tabName.size() -1) == '*')
|
||||
{
|
||||
tabName = tabName.substr(0, tabName.size() - 2);
|
||||
}
|
||||
// if (tabName.at(tabName.size() -1) == '*')
|
||||
// {
|
||||
// tabName = tabName.substr(0, tabName.size() - 2);
|
||||
// }
|
||||
}
|
||||
|
||||
if (m_tabBar->currentIndex() != saveTabIndex)
|
||||
@@ -1961,7 +1963,7 @@ namespace ScriptCanvasEditor
|
||||
const bool displayAsNotification = true;
|
||||
RunGraphValidation(displayAsNotification);
|
||||
|
||||
// This is called during saving, so the is scaving flag is always true Need to update the state after this callback is complete. So schedule for next system tick.
|
||||
// This is called during saving, so the is saving flag is always true Need to update the state after this callback is complete. So schedule for next system tick.
|
||||
AddSystemTickAction(SystemTickActionFlag::UpdateSaveMenuState);
|
||||
|
||||
if (m_closeCurrentGraphAfterSave)
|
||||
@@ -1974,69 +1976,27 @@ namespace ScriptCanvasEditor
|
||||
EnableAssetView(memoryAsset);
|
||||
|
||||
UnblockCloseRequests();
|
||||
*/
|
||||
}
|
||||
|
||||
bool MainWindow::ActivateAndSaveAsset(const ScriptCanvasEditor::SourceHandle& unsavedAssetId, const Callbacks::OnSave& saveCB)
|
||||
bool MainWindow::ActivateAndSaveAsset(const ScriptCanvasEditor::SourceHandle& unsavedAssetId)
|
||||
{
|
||||
SetActiveAsset(unsavedAssetId);
|
||||
return OnFileSave(saveCB);
|
||||
return OnFileSave();
|
||||
}
|
||||
|
||||
void MainWindow::SaveAs(AZStd::string_view /*path*/, ScriptCanvasEditor::SourceHandle /*inMemoryAssetId*/, const Callbacks::OnSave& /*onSave*/)
|
||||
void MainWindow::SaveAs(AZStd::string_view path, ScriptCanvasEditor::SourceHandle inMemoryAssetId)
|
||||
{
|
||||
/*
|
||||
PrepareAssetForSave(inMemoryAssetId);
|
||||
AZ_TracePrintf("ScriptCanvas", "Saving %s to %.*s", inMemoryAssetId.Path().c_str(), path.data());
|
||||
// #sc_editor_asset maybe delete this
|
||||
|
||||
DisableAssetView(inMemoryAssetId);
|
||||
|
||||
ScriptCanvasMemoryAsset::pointer memoryAsset;
|
||||
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, inMemoryAssetId);
|
||||
// use the file saver, make new version that works on source handle and not asset
|
||||
// then...connect the failed and succeed versions
|
||||
// to OnSaveCallBack
|
||||
|
||||
// Disable the current view if we are saving.
|
||||
if (memoryAsset)
|
||||
{
|
||||
DisableAssetView(memoryAsset);
|
||||
}
|
||||
|
||||
auto onSaveCallback = [this, onSave](bool saveSuccess, AZ::Data::AssetPtr asset, ScriptCanvasEditor::SourceHandle previousAssetId)
|
||||
{
|
||||
OnSaveCallback(saveSuccess, asset, previousAssetId);
|
||||
if (onSave)
|
||||
{
|
||||
AZStd::invoke(onSave, saveSuccess, asset, previousAssetId);
|
||||
}
|
||||
};
|
||||
|
||||
AZ::Data::AssetStreamInfo streamInfo;
|
||||
streamInfo.m_streamFlags = AZ::IO::OpenMode::ModeWrite;
|
||||
streamInfo.m_streamName = m_saveAsPath;
|
||||
|
||||
if (!streamInfo.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool sourceControlActive = false;
|
||||
AzToolsFramework::SourceControlConnectionRequestBus::BroadcastResult(sourceControlActive, &AzToolsFramework::SourceControlConnectionRequests::IsActive);
|
||||
// If Source Control is active then use it to check out the file before saving otherwise query the file info and save only if the file is not read-only
|
||||
if (sourceControlActive)
|
||||
{
|
||||
AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit,
|
||||
streamInfo.m_streamName.c_str(),
|
||||
true,
|
||||
[this, streamInfo, onSaveCallback](bool success, AzToolsFramework::SourceControlFileInfo info) { FinalizeAssetSave(success, info, streamInfo, onSaveCallback); }
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::GetFileInfo,
|
||||
streamInfo.m_streamName.c_str(),
|
||||
[this, streamInfo, onSaveCallback](bool success, AzToolsFramework::SourceControlFileInfo info) { FinalizeAssetSave(success, info, streamInfo, onSaveCallback); }
|
||||
);
|
||||
}
|
||||
|
||||
UpdateSaveState();
|
||||
BlockCloseRequests();
|
||||
*/
|
||||
UpdateSaveState();
|
||||
BlockCloseRequests();
|
||||
}
|
||||
|
||||
void MainWindow::OnFileOpen()
|
||||
@@ -2802,7 +2762,7 @@ namespace ScriptCanvasEditor
|
||||
//
|
||||
// if (fileState == Tracker::ScriptCanvasFileState::NEW)
|
||||
// {
|
||||
// SaveAssetAsImpl(fileAssetId, saveCB);
|
||||
// SaveAssetImpl(fileAssetId, saveCB);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
@@ -2822,7 +2782,7 @@ namespace ScriptCanvasEditor
|
||||
if (tabdata.isValid())
|
||||
{
|
||||
auto assetId = tabdata.value<Widget::GraphTabMetadata>();
|
||||
SaveAssetAsImpl(assetId.m_assetId, nullptr);
|
||||
SaveAssetImpl(assetId.m_assetId, Save::InPlace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4761,11 +4721,11 @@ namespace ScriptCanvasEditor
|
||||
//connect(m_unitTestDockWidget, &QDockWidget::visibilityChanged, this, &MainWindow::OnViewVisibilityChanged);
|
||||
}
|
||||
|
||||
void MainWindow::DisableAssetView(ScriptCanvasMemoryAsset::pointer memoryAsset)
|
||||
void MainWindow::DisableAssetView(const ScriptCanvasEditor::SourceHandle& memoryAssetId)
|
||||
{
|
||||
if (memoryAsset->GetView())
|
||||
if (auto view = m_tabBar->ModTabView(m_tabBar->FindTab(memoryAssetId)))
|
||||
{
|
||||
memoryAsset->GetView()->DisableView();
|
||||
view->DisableView();
|
||||
}
|
||||
|
||||
m_tabBar->setEnabled(false);
|
||||
@@ -4785,11 +4745,11 @@ namespace ScriptCanvasEditor
|
||||
m_autoSaveTimer.stop();
|
||||
}
|
||||
|
||||
void MainWindow::EnableAssetView(ScriptCanvasMemoryAsset::pointer memoryAsset)
|
||||
void MainWindow::EnableAssetView(const ScriptCanvasEditor::SourceHandle& memoryAssetId)
|
||||
{
|
||||
if (memoryAsset->GetView())
|
||||
if (auto view = m_tabBar->ModTabView(m_tabBar->FindTab(memoryAssetId)))
|
||||
{
|
||||
memoryAsset->GetView()->EnableView();
|
||||
view->EnableView();
|
||||
}
|
||||
|
||||
m_tabBar->setEnabled(true);
|
||||
|
||||
@@ -325,12 +325,17 @@ namespace ScriptCanvasEditor
|
||||
// File menu
|
||||
void OnFileNew();
|
||||
|
||||
bool OnFileSave(const Callbacks::OnSave& saveCB);
|
||||
bool OnFileSaveAs(const Callbacks::OnSave& saveCB);
|
||||
bool OnFileSaveCaller(){return OnFileSave(nullptr);};
|
||||
bool OnFileSaveAsCaller(){return OnFileSaveAs(nullptr);};
|
||||
bool SaveAssetImpl(const ScriptCanvasEditor::SourceHandle& assetId, const Callbacks::OnSave& saveCB);
|
||||
bool SaveAssetAsImpl(const ScriptCanvasEditor::SourceHandle& assetId, const Callbacks::OnSave& saveCB);
|
||||
bool OnFileSave();
|
||||
bool OnFileSaveAs();
|
||||
bool OnFileSaveCaller(){return OnFileSave();};
|
||||
bool OnFileSaveAsCaller(){return OnFileSaveAs();};
|
||||
bool SaveAssetImpl_OLD(const ScriptCanvasEditor::SourceHandle& assetId, const Callbacks::OnSave& saveCB);
|
||||
enum class Save
|
||||
{
|
||||
InPlace,
|
||||
As
|
||||
};
|
||||
bool SaveAssetImpl(const ScriptCanvasEditor::SourceHandle& assetId, Save save);
|
||||
void OnFileOpen();
|
||||
|
||||
// Edit menu
|
||||
@@ -554,9 +559,9 @@ namespace ScriptCanvasEditor
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
UnsavedChangesOptions ShowSaveDialog(const QString& filename);
|
||||
|
||||
bool ActivateAndSaveAsset(const ScriptCanvasEditor::SourceHandle& unsavedAssetId, const Callbacks::OnSave& onSave);
|
||||
bool ActivateAndSaveAsset(const ScriptCanvasEditor::SourceHandle& unsavedAssetId);
|
||||
|
||||
void SaveAs(AZStd::string_view path, ScriptCanvasEditor::SourceHandle assetId, const Callbacks::OnSave& onSave);
|
||||
void SaveAs(AZStd::string_view path, ScriptCanvasEditor::SourceHandle assetId);
|
||||
|
||||
void OpenFile(const char* fullPath);
|
||||
void CreateMenus();
|
||||
@@ -667,8 +672,8 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
}
|
||||
|
||||
void DisableAssetView(ScriptCanvasMemoryAsset::pointer memoryAsset);
|
||||
void EnableAssetView(ScriptCanvasMemoryAsset::pointer memoryAsset);
|
||||
void DisableAssetView(const ScriptCanvasEditor::SourceHandle& memoryAssetId);
|
||||
void EnableAssetView(const ScriptCanvasEditor::SourceHandle& memoryAssetId);
|
||||
|
||||
|
||||
QWidget* m_host = nullptr;
|
||||
@@ -783,6 +788,6 @@ namespace ScriptCanvasEditor
|
||||
//! this object manages the Save/Restore operations
|
||||
Workspace* m_workspace;
|
||||
|
||||
void OnSaveCallback(bool saveSuccess, AZ::Data::AssetPtr, ScriptCanvasEditor::SourceHandle previousFileAssetId);
|
||||
void OnSaveCallback(bool saveSuccess, ScriptCanvasEditor::SourceHandle previousFileAssetId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -186,12 +186,73 @@ namespace ScriptCanvasEditor
|
||||
});
|
||||
}
|
||||
|
||||
void FileSaver::OnSourceFileReleased(const SourceHandle& source)
|
||||
{
|
||||
AZStd::string tmpFileName;
|
||||
// here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file.
|
||||
// This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP.
|
||||
if (!AZ::IO::CreateTempFileName(source.Path().c_str(), tmpFileName))
|
||||
{
|
||||
FileSaveResult result;
|
||||
result.fileSaveError = "Failure to create temporary file name";
|
||||
m_onComplete(result);
|
||||
return;
|
||||
}
|
||||
|
||||
bool tempSavedSucceeded = false;
|
||||
AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText);
|
||||
if (fileStream.IsOpen())
|
||||
{
|
||||
if (asset.GetType() == azrtti_typeid<ScriptCanvasEditor::ScriptCanvasAsset>())
|
||||
{
|
||||
ScriptCanvasEditor::ScriptCanvasAssetHandler handler;
|
||||
tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream);
|
||||
}
|
||||
|
||||
fileStream.Close();
|
||||
}
|
||||
|
||||
if (!tempSavedSucceeded)
|
||||
{
|
||||
FileSaveResult result;
|
||||
result.fileSaveError = "Save asset data to temporary file failed";
|
||||
m_onComplete(result);
|
||||
return;
|
||||
}
|
||||
|
||||
AzToolsFramework::SourceControlCommandBus::Broadcast
|
||||
( &AzToolsFramework::SourceControlCommandBus::Events::RequestEdit
|
||||
, fullPath.c_str()
|
||||
, true
|
||||
, [this, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info)
|
||||
{
|
||||
constexpr const size_t k_maxAttemps = 10;
|
||||
|
||||
if (!info.IsReadOnly())
|
||||
{
|
||||
PerformMove(tmpFileName, fullPath, k_maxAttemps);
|
||||
}
|
||||
else if (m_onReadOnlyFile && m_onReadOnlyFile())
|
||||
{
|
||||
AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true);
|
||||
PerformMove(tmpFileName, fullPath, k_maxAttemps);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileSaveResult result;
|
||||
result.fileSaveError = "Source file was and remained read-only";
|
||||
result.tempFileRemovalError = RemoveTempFile(tmpFileName);
|
||||
m_onComplete(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AZStd::string FileSaver::RemoveTempFile(AZStd::string_view tempFile)
|
||||
{
|
||||
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
if (!fileIO)
|
||||
{
|
||||
return "GraphUpgradeComplete: No FileIO instance";
|
||||
return "No FileIO instance";
|
||||
}
|
||||
|
||||
if (fileIO->Exists(tempFile.data()) && !fileIO->Remove(tempFile.data()))
|
||||
@@ -202,13 +263,34 @@ namespace ScriptCanvasEditor
|
||||
return "";
|
||||
}
|
||||
|
||||
void FileSaver::Save(const SourceHandle& source)
|
||||
{
|
||||
if (source.Path().empty())
|
||||
{
|
||||
FileSaveResult result;
|
||||
result.fileSaveError = "No save location specified";
|
||||
m_onComplete(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto streamer = AZ::Interface<AZ::IO::IStreamer>::Get();
|
||||
AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(source.Path());
|
||||
streamer->SetRequestCompleteCallback(flushRequest, [this, source]([[maybe_unused]] AZ::IO::FileRequestHandle request)
|
||||
{
|
||||
this->OnSourceFileReleased(source);
|
||||
});
|
||||
streamer->QueueRequest(flushRequest);
|
||||
}
|
||||
}
|
||||
|
||||
void FileSaver::Save(AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
{
|
||||
// #sc_editor_asset fix this path from the version explorer
|
||||
AZStd::string relativePath, fullPath;
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId());
|
||||
bool fullPathFound = false;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult
|
||||
(fullPathFound
|
||||
( fullPathFound
|
||||
, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath
|
||||
, relativePath, fullPath);
|
||||
|
||||
|
||||
@@ -30,11 +30,13 @@ namespace ScriptCanvasEditor
|
||||
, AZStd::function<void(const FileSaveResult& result)> onComplete);
|
||||
|
||||
void Save(AZ::Data::Asset<AZ::Data::AssetData> asset);
|
||||
void Save(const SourceHandle& source);
|
||||
|
||||
private:
|
||||
AZStd::function<void(const FileSaveResult& result)> m_onComplete;
|
||||
AZStd::function<bool()> m_onReadOnlyFile;
|
||||
|
||||
void OnSourceFileReleased(const SourceHandle& source);
|
||||
void OnSourceFileReleased(AZ::Data::Asset<AZ::Data::AssetData> asset);
|
||||
|
||||
void PerformMove
|
||||
|
||||
Reference in New Issue
Block a user