File state change include external delete detection

Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com>
main^2^2
chcurran 4 years ago committed by Chris Burel
parent 805bd8ef56
commit d9f849b03e

@ -107,11 +107,15 @@ namespace ScriptCanvasEditor
return ScriptCanvasBuilder::CreateLuaAsset(editAsset, graphPathForRawLuaFile);
}
void EditorAssetSystemComponent::AddSourceFileOpeners([[maybe_unused]] const char* fullSourceFileName, [[maybe_unused]] const AZ::Uuid& sourceUuid, [[maybe_unused]] AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers)
void EditorAssetSystemComponent::AddSourceFileOpeners
( [[maybe_unused]] const char* fullSourceFileName
, const AZ::Uuid& sourceUuid
, AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers)
{
using namespace AzToolsFramework;
using namespace AzToolsFramework::AssetBrowser;
if (const SourceAssetBrowserEntry* source = SourceAssetBrowserEntry::GetSourceByUuid(sourceUuid)) // get the full details of the source file based on its UUID.
// get the full details of the source file based on its UUID.
if (const SourceAssetBrowserEntry* source = SourceAssetBrowserEntry::GetSourceByUuid(sourceUuid))
{
if (!HandlesSource(source))
{
@ -123,23 +127,31 @@ namespace ScriptCanvasEditor
// has no UUID / Not a source file.
return;
}
// You can push back any number of "Openers" - choose a unique identifier, and icon, and then a lambda which will be activated if the user chooses to open it with your opener:
// #sc_editor_asset
// openers.push_back({ "ScriptCanvas_Editor_Asset_Edit", "Script Canvas Editor...", QIcon(),
// [](const char*, const AZ::Uuid& scSourceUuid)
// {
// AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas);
// AZ::Data::AssetId sourceAssetId(scSourceUuid, 0);
//
// auto& assetManager = AZ::Data::AssetManager::Instance();
// AZ::Data::Asset<ScriptCanvasAsset> scriptCanvasAsset = assetManager.GetAsset(sourceAssetId, azrtti_typeid<ScriptCanvasAsset>(), AZ::Data::AssetLoadBehavior::Default);
// AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
// GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, scriptCanvasAsset.GetId(), -1);
// if (!openOutcome)
// {
// AZ_Warning("Script Canvas", openOutcome, "%s", openOutcome.GetError().data());
// }
// } });
// You can push back any number of "Openers" - choose a unique identifier, and icon,
// and then a lambda which will be activated if the user chooses to open it with your opener:
openers.push_back({ "ScriptCanvas_Editor_Asset_Edit", "Script Canvas Editor..."
, QIcon(ScriptCanvasAssetDescription().GetIconPathImpl()),
[](const char*, const AZ::Uuid& scSourceUuid)
{
AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas);
if (auto sourceHandle = CompleteDescription(SourceHandle(nullptr, scSourceUuid, {})))
{
AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset
, *sourceHandle, Tracker::ScriptCanvasFileState::UNMODIFIED, -1);
if (!openOutcome)
{
AZ_Warning("ScriptCanvas", openOutcome, "%s", openOutcome.GetError().data());
}
}
else
{
AZ_Warning("ScriptCanvas", false
, "Unabled to find full path for Source UUid %s", scSourceUuid.ToString<AZStd::string>().c_str());
}
}});
}
}

@ -60,57 +60,6 @@ namespace ScriptCanvasBuilder
graphData = sourceGraph->GetGraphDataConst();
}
#if defined(EDITOR_ASSET_SUPPORT_ENABLED)
if (graphData == nullptr)
{
if (!m_editorAssetHandler)
{
AZ_Error(s_scriptCanvasBuilder, false, R"(CreateJobs for %s failed because the ScriptCanvas Editor Asset handler is missing.)", fullPath.data());
}
AZStd::shared_ptr<AZ::Data::AssetDataStream> assetDataStream = AZStd::make_shared<AZ::Data::AssetDataStream>();
AZ::IO::FileIOStream stream(fullPath.c_str(), AZ::IO::OpenMode::ModeRead);
if (!AZ::IO::RetryOpenStream(stream))
{
AZ_Warning(s_scriptCanvasBuilder, false, "CreateJobs for \"%s\" failed because the source file could not be opened.", fullPath.data());
return;
}
// Read the asset into a memory buffer, then hand ownership of the buffer to assetDataStream
{
AZ::IO::FileIOStream ioStream;
if (!ioStream.Open(fullPath.data(), AZ::IO::OpenMode::ModeRead))
{
AZ_Warning(s_scriptCanvasBuilder, false, "CreateJobs for \"%s\" failed because the source file could not be opened.", fullPath.data());
return;
}
AZStd::vector<AZ::u8> fileBuffer(ioStream.GetLength());
size_t bytesRead = ioStream.Read(fileBuffer.size(), fileBuffer.data());
if (bytesRead != ioStream.GetLength())
{
AZ_Warning(s_scriptCanvasBuilder, false, AZStd::string::format("File failed to read completely: %s", fullPath.data()).c_str());
return;
}
assetDataStream->Open(AZStd::move(fileBuffer));
}
m_processEditorAssetDependencies.clear();
asset.Create(AZ::Data::AssetId(AZ::Uuid::CreateRandom()));
if (m_editorAssetHandler->LoadAssetDataFromStream(asset, assetDataStream, {}) != AZ::Data::AssetHandler::LoadResult::LoadComplete)
{
AZ_Warning(s_scriptCanvasBuilder, false, "CreateJobs for \"%s\" failed because the asset data could not be loaded from the file", fullPath.data());
return;
}
sourceGraph = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvasEditor::Graph>(asset.Get()->GetScriptCanvasEntity());
graphData = sourceGraph->GetGraphDataConst();
}
#endif
AZ_Assert(sourceGraph, "Graph component is missing from entity.");
AZ_Assert(graphData, "GraphData is missing from entity");

@ -541,48 +541,4 @@ namespace ScriptCanvasEditor
return AZ::EntityId();
}
void AssetTracker::OnAssetReady(const ScriptCanvasMemoryAsset* asset)
{
AZ::Data::AssetId assetId = CheckAssetId(asset->GetId());
auto assetInUseIter = m_assetsInUse.find(assetId);
if (assetInUseIter != m_assetsInUse.end())
{
AssetTrackerNotificationBus::Broadcast(&AssetTrackerNotifications::OnAssetReady, assetInUseIter->second);
}
}
void AssetTracker::OnAssetReloaded(const ScriptCanvasMemoryAsset* asset)
{
AZ::Data::AssetId assetId = CheckAssetId(asset->GetId());
auto assetInUseIter = m_assetsInUse.find(assetId);
if (assetInUseIter != m_assetsInUse.end())
{
AssetTrackerNotificationBus::Broadcast(&AssetTrackerNotifications::OnAssetReloaded, assetInUseIter->second);
}
}
void AssetTracker::OnAssetSaved(const ScriptCanvasMemoryAsset* asset, bool isSuccessful)
{
AZ::Data::AssetId assetId = CheckAssetId(asset->GetId());
auto assetInUseIter = m_assetsInUse.find(assetId);
if (assetInUseIter != m_assetsInUse.end())
{
AssetTrackerNotificationBus::Broadcast(&AssetTrackerNotifications::OnAssetSaved, assetInUseIter->second, isSuccessful);
}
}
void AssetTracker::OnAssetError(const ScriptCanvasMemoryAsset* asset)
{
AZ::Data::AssetId assetId = CheckAssetId(asset->GetId());
auto assetInUseIter = m_assetsInUse.find(assetId);
if (assetInUseIter != m_assetsInUse.end())
{
AssetTrackerNotificationBus::Broadcast(&AssetTrackerNotifications::OnAssetError, assetInUseIter->second);
}
}
}

@ -16,6 +16,7 @@
#include <Editor/Assets/ScriptCanvasAssetTrackerBus.h>
#include <GraphCanvas/Editor/EditorTypes.h>
#include <ScriptCanvas/Bus/RequestBus.h>
namespace ScriptCanvasEditor
@ -122,10 +123,5 @@ namespace ScriptCanvasEditor
// Invoked when an asset is loaded from file and becomes ready
Callbacks::OnAssetReadyCallback m_onAssetReadyCallback;
// Internal::MemoryAssetNotificationBus
void OnAssetReady(const ScriptCanvasMemoryAsset* asset) override;
void OnAssetReloaded(const ScriptCanvasMemoryAsset* asset) override;
void OnAssetSaved(const ScriptCanvasMemoryAsset* asset, bool isSuccessful) override;
void OnAssetError(const ScriptCanvasMemoryAsset* asset) override;
};
}

@ -17,6 +17,7 @@
#include <Editor/Assets/ScriptCanvasAssetTrackerDefinitions.h>
#include <Editor/Assets/ScriptCanvasMemoryAsset.h>
#include <ScriptCanvas/Bus/RequestBus.h>
class QWidget;

@ -24,17 +24,5 @@ namespace ScriptCanvasEditor
using OnAssetCreatedCallback = OnAssetReadyCallback;
}
namespace Tracker
{
enum class ScriptCanvasFileState : AZ::s32
{
NEW,
MODIFIED,
UNMODIFIED,
// #sc_editor_asset restore this
SOURCE_REMOVED,
INVALID = -1
};
}
}

@ -29,6 +29,8 @@
#include <Editor/View/Widgets/CanvasWidget.h>
#include <Editor/Undo/ScriptCanvasUndoManager.h>
#include <ScriptCanvas/Bus/RequestBus.h>
namespace ScriptCanvasEditor
{

@ -235,7 +235,7 @@ namespace ScriptCanvasEditor
if (m_sourceHandle.IsValid())
{
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, m_sourceHandle, -1);
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, m_sourceHandle, Tracker::ScriptCanvasFileState::UNMODIFIED, -1);
if (!openOutcome)
{

@ -35,37 +35,46 @@ namespace ScriptCanvasEditor
{
if (source.IsValidDescription())
{
return source.Describe();
return source;
}
AZStd::string watchFolder;
AZ::Data::AssetInfo assetInfo;
bool sourceInfoFound{};
if (!source.Id().IsNull())
AzToolsFramework::AssetSystemRequestBus::Events* assetSystem = AzToolsFramework::AssetSystemRequestBus::FindFirstHandler();
if (assetSystem)
{
AzToolsFramework::AssetSystemRequestBus::BroadcastResult
( sourceInfoFound
, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourceUUID, source.Id(), assetInfo, watchFolder);
AZStd::string watchFolder;
AZ::Data::AssetInfo assetInfo;
if (sourceInfoFound && !assetInfo.m_relativePath.empty())
if (!source.Id().IsNull())
{
return SourceHandle(nullptr, assetInfo.m_assetId.m_guid, assetInfo.m_relativePath);
}
}
if (assetSystem->GetSourceInfoBySourceUUID(source.Id(), assetInfo, watchFolder))
{
AZ::IO::Path watchPath(watchFolder);
AZ::IO::Path assetInfoPath(assetInfo.m_relativePath);
SourceHandle fullPathHandle(nullptr, assetInfo.m_assetId.m_guid, watchPath / assetInfoPath);
if (!source.Path().empty())
{
AzToolsFramework::AssetSystemRequestBus::BroadcastResult
( sourceInfoFound
, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, source.Path().c_str(), assetInfo, watchFolder);
if (assetSystem->GetSourceInfoBySourcePath(fullPathHandle.Path().c_str(), assetInfo, watchFolder) && assetInfo.m_assetId.IsValid())
{
if (assetInfo.m_assetId.m_guid != source.Id())
{
AZ_TracePrintf("ScriptCanvas", "This is what I don't get");
}
if (sourceInfoFound && assetInfo.m_assetId.IsValid())
auto path = fullPathHandle.Path();
return SourceHandle(source, assetInfo.m_assetId.m_guid, path.MakePreferred());
}
}
}
if (!source.Path().empty())
{
return SourceHandle(nullptr, assetInfo.m_assetId.m_guid, assetInfo.m_relativePath);
if (assetSystem->GetSourceInfoBySourcePath(source.Path().c_str(), assetInfo, watchFolder) && assetInfo.m_assetId.IsValid())
{
return SourceHandle(source, assetInfo.m_assetId.m_guid, source.Path());
}
}
}
return AZStd::nullopt;
}

@ -97,7 +97,8 @@ namespace ScriptCanvasEditor
}
AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, SourceHandle( nullptr, assetInfo.m_assetId.m_guid, {} ), -1);
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset
, SourceHandle( nullptr, assetInfo.m_assetId.m_guid, {} ), Tracker::ScriptCanvasFileState::UNMODIFIED, -1);
return openOutcome.IsSuccess();
}

@ -47,6 +47,18 @@ namespace ScriptCanvasEditor
struct CategoryInformation;
struct NodePaletteModelInformation;
namespace Tracker
{
enum class ScriptCanvasFileState : AZ::s32
{
NEW,
MODIFIED,
UNMODIFIED,
// #sc_editor_asset restore this
SOURCE_REMOVED,
INVALID = -1
};
}
namespace Widget
{
@ -68,8 +80,8 @@ namespace ScriptCanvasEditor
//! Opens an existing graph and returns the tab index in which it was open in.
//! \param File AssetId
//! \return index of open tab if the asset was able to be open successfully or error message of why the open failed
virtual AZ::Outcome<int, AZStd::string> OpenScriptCanvasAsset(SourceHandle scriptCanvasAssetId, int tabIndex = -1) = 0;
virtual AZ::Outcome<int, AZStd::string> OpenScriptCanvasAssetId(const SourceHandle& scriptCanvasAsset) = 0;
virtual AZ::Outcome<int, AZStd::string> OpenScriptCanvasAsset(SourceHandle scriptCanvasAssetId, Tracker::ScriptCanvasFileState fileState, int tabIndex = -1) = 0;
virtual AZ::Outcome<int, AZStd::string> OpenScriptCanvasAssetId(const SourceHandle& scriptCanvasAsset, Tracker::ScriptCanvasFileState fileState) = 0;
virtual int CloseScriptCanvasAsset(const SourceHandle&) = 0;

@ -85,12 +85,7 @@ namespace ScriptCanvasEditor
AZ::Data::AssetId GetAssetId() const override;
//=====================================================================
//=====================================================================
// AssetTrackerNotificationBus
void OnAssetReady(const ScriptCanvasMemoryAsset::pointer asset) ;
void OnAssetSaved(const ScriptCanvasMemoryAsset::pointer asset, bool isSuccessful) ;
void OnAssetReloaded(const ScriptCanvasMemoryAsset::pointer asset) ;
//=====================================================================
//=====================================================================
@ -119,7 +114,6 @@ namespace ScriptCanvasEditor
// complete the id, load call OnScriptCanvasAssetChanged
void SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid fileAssetId) override;
// update the display icon for failure, save the values in the graph
void SourceFileRemoved(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid fileAssetId) override;
void SourceFileFailed(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid fileAssetId) override;

@ -21,6 +21,9 @@ namespace GraphCanvas
namespace ScriptCanvasEditor
{
// If only the Path or the Id is valid, attempts to fill in the missing piece.
// If both Path and Id is valid, including after correction, returns the handle including source Data,
// otherwise, returns null
AZStd::optional<SourceHandle> CompleteDescription(const SourceHandle& source);
class Graph;

@ -46,9 +46,9 @@ namespace ScriptCanvasEditor
connect(this, &QTabBar::customContextMenuRequested, this, &GraphTabBar::OnContextMenu);
}
void GraphTabBar::AddGraphTab(ScriptCanvasEditor::SourceHandle assetId)
void GraphTabBar::AddGraphTab(ScriptCanvasEditor::SourceHandle assetId, Tracker::ScriptCanvasFileState fileState)
{
InsertGraphTab(count(), assetId);
InsertGraphTab(count(), assetId, fileState);
}
void GraphTabBar::ClearTabView(int tabIndex)
@ -143,7 +143,7 @@ namespace ScriptCanvasEditor
}
}
int GraphTabBar::InsertGraphTab(int tabIndex, ScriptCanvasEditor::SourceHandle assetId)
int GraphTabBar::InsertGraphTab(int tabIndex, ScriptCanvasEditor::SourceHandle assetId, Tracker::ScriptCanvasFileState fileState)
{
if (!SelectTab(assetId))
{
@ -159,9 +159,6 @@ namespace ScriptCanvasEditor
AzFramework::StringFunc::Path::GetFileName(assetId.Path().c_str(), tabName);
metaData.m_name = tabName.c_str();
// #sc_editor_asset filestate
Tracker::ScriptCanvasFileState fileState = Tracker::ScriptCanvasFileState::INVALID;
// AssetTrackerRequestBus::BroadcastResult(fileState, &AssetTrackerRequests::GetFileState, fileAssetId);
SetTabText(tabIndex, tabName.c_str(), fileState);
setTabData(tabIndex, QVariant::fromValue(metaData));
return tabIndex;

@ -18,6 +18,8 @@
#include <ScriptCanvas/Core/Core.h>
#include <Editor/Assets/ScriptCanvasAssetTracker.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#endif
class QGraphicsView;
@ -54,11 +56,11 @@ namespace ScriptCanvasEditor
void SetTabData(const GraphTabMetadata& data, int index);
void SetTabData(const GraphTabMetadata& data, ScriptCanvasEditor::SourceHandle assetId);
void AddGraphTab(ScriptCanvasEditor::SourceHandle assetId);
void AddGraphTab(ScriptCanvasEditor::SourceHandle assetId, Tracker::ScriptCanvasFileState fileState);
void CloseTab(int index);
void CloseAllTabs();
int InsertGraphTab(int tabIndex, ScriptCanvasEditor::SourceHandle assetId);
int InsertGraphTab(int tabIndex, ScriptCanvasEditor::SourceHandle assetId, Tracker::ScriptCanvasFileState fileState);
bool SelectTab(ScriptCanvasEditor::SourceHandle assetId);
// void ConfigureTab(int tabIndex, ScriptCanvasEditor::SourceHandle fileAssetId, const AZStd::string& tabName);

@ -256,7 +256,8 @@ namespace ScriptCanvasEditor
const AZ::Data::AssetId& assetId = executionItem->GetAssetId();
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAssetId, SourceHandle(nullptr, assetId.m_guid, {}));
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAssetId
, SourceHandle(nullptr, assetId.m_guid, {}), Tracker::ScriptCanvasFileState::UNMODIFIED);
}
}
}
@ -272,10 +273,12 @@ namespace ScriptCanvasEditor
bool isAssetOpen = false;
GeneralRequestBus::BroadcastResult(isAssetOpen, &GeneralRequests::IsScriptCanvasAssetOpen, SourceHandle(nullptr, assetId.m_guid, {}));
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAssetId, SourceHandle(nullptr, assetId.m_guid, {}));
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAssetId
, SourceHandle(nullptr, assetId.m_guid, {}), Tracker::ScriptCanvasFileState::UNMODIFIED);
AZ::EntityId graphCanvasGraphId;
GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::FindGraphCanvasGraphIdByAssetId, SourceHandle(nullptr, assetId.m_guid, {}));
GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::FindGraphCanvasGraphIdByAssetId
, SourceHandle(nullptr, assetId.m_guid, {}));
if (isAssetOpen)
{

@ -433,7 +433,10 @@ namespace ScriptCanvasEditor
AZ::Data::AssetId sourceAssetId(sourceUuid, 0);
AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAssetId, ScriptCanvasEditor::SourceHandle(nullptr, sourceUuid, {}));
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAssetId
, ScriptCanvasEditor::SourceHandle(nullptr, sourceUuid, {})
, Tracker::ScriptCanvasFileState::UNMODIFIED);
if (!openOutcome)
{
AZ_Warning("Script Canvas", openOutcome, "%s", openOutcome.GetError().data());

@ -666,6 +666,7 @@ namespace ScriptCanvasEditor
AzToolsFramework::ToolsApplicationNotificationBus::Handler::BusConnect();
AzToolsFramework::AssetSystemBus::Handler::BusConnect();
ScriptCanvas::ScriptCanvasSettingsRequestBus::Handler::BusConnect();
AZ::SystemTickBus::Handler::BusConnect();
UINotificationBus::Broadcast(&UINotifications::MainWindowCreationEvent, this);
@ -1112,13 +1113,47 @@ namespace ScriptCanvasEditor
RestartAutoTimerSave(forceTimer);
}
void MainWindow::SourceFileChanged
( [[maybe_unused]] AZStd::string relativePath
, AZStd::string scanFolder
, [[maybe_unused]] AZ::Uuid fileAssetId)
{
auto handle = CompleteDescription(SourceHandle(nullptr, fileAssetId, {}));
if (handle)
{
if (!IsRecentSave(*handle))
{
UpdateFileState(*handle, Tracker::ScriptCanvasFileState::MODIFIED);
}
else
{
AZ_TracePrintf
( "ScriptCanvas"
, "Ignoring source file modification notification (possibly external), as a it was recently saved by the editor: %s"
, relativePath.c_str());
}
}
}
void MainWindow::SourceFileRemoved
( AZStd::string relativePath
, [[maybe_unused]] AZStd::string scanFolder
, [[maybe_unused]] AZ::Uuid fileAssetId)
, AZ::Uuid fileAssetId)
{
ScriptCanvasEditor::SourceHandle handle(nullptr, fileAssetId, relativePath);
UpdateFileState(handle, Tracker::ScriptCanvasFileState::SOURCE_REMOVED);
SourceHandle handle(nullptr, fileAssetId, relativePath);
{
if (!IsRecentSave(handle))
{
UpdateFileState(handle, Tracker::ScriptCanvasFileState::SOURCE_REMOVED);
}
else
{
AZ_TracePrintf
( "ScriptCanvas"
, "Ignoring source file removed notification (possibly external), as a it was recently saved by the editor: %s"
, relativePath.c_str());
}
}
}
void MainWindow::SignalSceneDirty(ScriptCanvasEditor::SourceHandle assetId)
@ -1149,21 +1184,7 @@ namespace ScriptCanvasEditor
m_tabBar->UpdateFileState(assetId, fileState);
}
void MainWindow::RefreshScriptCanvasAsset(const AZ::Data::Asset<ScriptCanvas::ScriptCanvasAssetBase>& /*asset*/)
{
// #sc_editor_asset
/*
ScriptCanvasMemoryAsset::pointer memoryAsset;
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, asset.GetId());
if (memoryAsset && asset.IsReady())
{
}
*/
}
AZ::Outcome<int, AZStd::string> MainWindow::OpenScriptCanvasAssetId(const ScriptCanvasEditor::SourceHandle& fileAssetId)
AZ::Outcome<int, AZStd::string> MainWindow::OpenScriptCanvasAssetId(const ScriptCanvasEditor::SourceHandle& fileAssetId, Tracker::ScriptCanvasFileState fileState)
{
if (fileAssetId.Id().IsNull())
{
@ -1178,7 +1199,7 @@ namespace ScriptCanvasEditor
return AZ::Success(outTabIndex);
}
outTabIndex = CreateAssetTab(fileAssetId);
outTabIndex = CreateAssetTab(fileAssetId, fileState);
if (!m_isRestoringWorkspace)
{
@ -1188,7 +1209,7 @@ namespace ScriptCanvasEditor
if (outTabIndex >= 0)
{
AddRecentFile(fileAssetId.Path().c_str());
OpenScriptCanvasAssetImplementation(fileAssetId);
OpenScriptCanvasAssetImplementation(fileAssetId, fileState);
return AZ::Success(outTabIndex);
}
else
@ -1197,7 +1218,7 @@ namespace ScriptCanvasEditor
}
}
AZ::Outcome<int, AZStd::string> MainWindow::OpenScriptCanvasAssetImplementation(const SourceHandle& scriptCanvasAsset, int tabIndex)
AZ::Outcome<int, AZStd::string> MainWindow::OpenScriptCanvasAssetImplementation(const SourceHandle& scriptCanvasAsset, Tracker::ScriptCanvasFileState fileState, int tabIndex)
{
const ScriptCanvasEditor::SourceHandle& fileAssetId = scriptCanvasAsset;
if (!fileAssetId.IsValid())
@ -1239,7 +1260,7 @@ namespace ScriptCanvasEditor
return AZ::Success(outTabIndex);
}
outTabIndex = CreateAssetTab(fileAssetId, tabIndex);
outTabIndex = CreateAssetTab(fileAssetId, fileState, tabIndex);
if (outTabIndex == -1)
{
@ -1259,21 +1280,21 @@ namespace ScriptCanvasEditor
return AZ::Success(outTabIndex);
}
AZ::Outcome<int, AZStd::string> MainWindow::OpenScriptCanvasAsset(ScriptCanvasEditor::SourceHandle scriptCanvasAssetId, int tabIndex)
AZ::Outcome<int, AZStd::string> MainWindow::OpenScriptCanvasAsset(ScriptCanvasEditor::SourceHandle scriptCanvasAssetId, Tracker::ScriptCanvasFileState fileState, int tabIndex)
{
if (scriptCanvasAssetId.IsValid())
{
return OpenScriptCanvasAssetImplementation(scriptCanvasAssetId, tabIndex);
return OpenScriptCanvasAssetImplementation(scriptCanvasAssetId, fileState, tabIndex);
}
else
{
return OpenScriptCanvasAssetId(scriptCanvasAssetId);
return OpenScriptCanvasAssetId(scriptCanvasAssetId, fileState);
}
}
int MainWindow::CreateAssetTab(const ScriptCanvasEditor::SourceHandle& assetId, int tabIndex)
int MainWindow::CreateAssetTab(const ScriptCanvasEditor::SourceHandle& assetId, Tracker::ScriptCanvasFileState fileState, int tabIndex)
{
return m_tabBar->InsertGraphTab(tabIndex, assetId);
return m_tabBar->InsertGraphTab(tabIndex, assetId, fileState);
}
void MainWindow::RemoveScriptCanvasAsset(const ScriptCanvasEditor::SourceHandle& assetId)
@ -1316,7 +1337,7 @@ namespace ScriptCanvasEditor
{
if (createdAssetPair.second == requestingEntityId)
{
return OpenScriptCanvasAssetId(createdAssetPair.first).IsSuccess();
return OpenScriptCanvasAssetId(createdAssetPair.first, Tracker::ScriptCanvasFileState::NEW).IsSuccess();
}
}
@ -1355,33 +1376,6 @@ namespace ScriptCanvasEditor
return m_nodePaletteModel.FindNodePaletteInformation(nodeType);
}
void MainWindow::GetSuggestedFullFilenameToSaveAs(const ScriptCanvasEditor::SourceHandle& /*assetId*/, AZStd::string& /*filePath*/, AZStd::string& /*fileFilter*/)
{
// #sc_editor_asset
//
// ScriptCanvasMemoryAsset::pointer memoryAsset;
// AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, assetId);
//
// AZStd::string assetPath;
// if (memoryAsset)
// {
// assetPath = memoryAsset->GetAbsolutePath();
// fileFilter = ScriptCanvasAssetDescription().GetFileFilterImpl();
//
// AZStd::string tabName;
// AssetTrackerRequestBus::BroadcastResult(tabName, &AssetTrackerRequests::GetTabName, assetId);
//
// assetPath = AZStd::string::format("%s/%s%s"
// , ScriptCanvasAssetDescription().GetSuggestedSavePathImpl()
// , tabName.c_str()
// , ScriptCanvasAssetDescription().GetExtensionImpl());
// }
//
// AZStd::array<char, AZ::IO::MaxPathLength> resolvedPath;
// AZ::IO::FileIOBase::GetInstance()->ResolvePath(assetPath.data(), resolvedPath.data(), resolvedPath.size());
// filePath = resolvedPath.data();
}
void MainWindow::OpenFile(const char* fullPath)
{
auto tabIndex = m_tabBar->FindTabByPath(fullPath);
@ -1418,7 +1412,7 @@ namespace ScriptCanvasEditor
m_errorFilePath.clear();
auto activeGraph = ScriptCanvasEditor::SourceHandle(outcome.TakeValue(), assetInfo.m_assetId.m_guid, fullPath);
auto openOutcome = OpenScriptCanvasAsset(activeGraph);
auto openOutcome = OpenScriptCanvasAsset(activeGraph, Tracker::ScriptCanvasFileState::UNMODIFIED);
if (openOutcome)
{
RunGraphValidation(false);
@ -1429,66 +1423,10 @@ namespace ScriptCanvasEditor
{
AZ_Warning("Script Canvas", openOutcome, "%s", openOutcome.GetError().data());
}
#if defined(EDITOR_ASSET_SUPPORT_ENABLED)
/*
m_errorFilePath = fullPath;
// Let's find the source file on disk
AZStd::string watchFolder;
AZ::Data::AssetInfo assetInfo;
bool sourceInfoFound{};
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, fullPath, assetInfo, watchFolder);
if (sourceInfoFound)
{
const Tracker::ScriptCanvasFileState& fileState = GetAssetFileState(assetInfo.m_assetId);
if (fileState != Tracker::ScriptCanvasFileState::NEW && fileState != Tracker::ScriptCanvasFileState::INVALID)
{
ScriptCanvasMemoryAsset::pointer memoryAsset;
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, assetInfo.m_assetId);
if (m_tabBar->FindTab(assetInfo.m_assetId) < 0)
{
CreateAssetTab(assetInfo.m_assetId);
}
SetActiveAsset(memoryAsset->GetFileAssetId());
OpenNextFile();
return;
}
Callbacks::OnAssetReadyCallback onAssetReady = [this, assetInfo](ScriptCanvasMemoryAsset&)
{
ScriptCanvasMemoryAsset::pointer memoryAsset;
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, assetInfo.m_assetId);
auto openOutcome = OpenScriptCanvasAsset(*memoryAsset);
if (openOutcome)
{
RunGraphValidation(false);
SetRecentAssetId(assetInfo.m_assetId);
}
else
{
AZ_Warning("Script Canvas", openOutcome, "%s", openOutcome.GetError().data());
}
OpenNextFile();
};
// TODO-LS the assetInfo.m_assetType is always null for some reason, I know in this case we want default assets so it's ok to hardcode it
AssetTrackerRequestBus::Broadcast(&AssetTrackerRequests::Load, assetInfo.m_assetId, assetInfo.m_assetType, azrtti_typeid<ScriptCanvasAsset>(), onAssetReady);
}
else
{
QMessageBox::warning(this, "Invalid Source Asset", QString("'%1' is not a valid asset path.").arg(fullPath), QMessageBox::Ok);
}
*/
#endif
}
GraphCanvas::Endpoint MainWindow::HandleProposedConnection(const GraphCanvas::GraphId&, const GraphCanvas::ConnectionId&, const GraphCanvas::Endpoint& endpoint, const GraphCanvas::NodeId& nodeId, const QPoint& screenPoint)
GraphCanvas::Endpoint MainWindow::HandleProposedConnection(const GraphCanvas::GraphId&, const GraphCanvas::ConnectionId&
, const GraphCanvas::Endpoint& endpoint, const GraphCanvas::NodeId& nodeId, const QPoint& screenPoint)
{
GraphCanvas::Endpoint retVal;
@ -1633,7 +1571,7 @@ namespace ScriptCanvasEditor
// Insert tab block
AZStd::string tabName;
AzFramework::StringFunc::Path::GetFileName(assetPath.data(), tabName);
m_tabBar->InsertGraphTab(tabIndex, assetId);
m_tabBar->InsertGraphTab(tabIndex, assetId, Tracker::ScriptCanvasFileState::NEW);
if (!IsTabOpen(assetId, outTabIndex))
{
@ -1666,17 +1604,13 @@ namespace ScriptCanvasEditor
ScriptCanvasEditor::SourceHandle handle = ScriptCanvasEditor::SourceHandle(graph, assetId, assetPath);
outTabIndex = InsertTabForAsset(assetPath, handle, tabIndex);
m_tabBar->UpdateFileState(handle, Tracker::ScriptCanvasFileState::NEW);
if (outTabIndex == -1)
{
return AZ::Failure(AZStd::string::format("Script Canvas Asset %.*s is not open in a tab", assetPath.data()));
}
SetActiveAsset(handle);
// #sc_editor_asset delete candidate
PushPreventUndoStateUpdate();
AZ::EntityId scriptCanvasEntityId = graph->GetGraph()->GetScriptCanvasId();
@ -1790,7 +1724,6 @@ namespace ScriptCanvasEditor
}
else
{
// replaces GetSuggestedFullFilenameToSaveAs
suggestedFileFilter = ScriptCanvasAssetDescription().GetExtensionImpl();
if (inMemoryAssetId.Path().empty())
@ -1880,7 +1813,8 @@ namespace ScriptCanvasEditor
void MainWindow::OnSaveCallBack(const VersionExplorer::FileSaveResult& result)
{
const bool saveSuccess = result.fileSaveError.empty();
auto memoryAsset = m_fileSaver->GetSource();
auto completeDescription = CompleteDescription(m_fileSaver->GetSource());
auto memoryAsset = completeDescription ? *completeDescription : m_fileSaver->GetSource();
int saveTabIndex = m_tabBar->FindTab(memoryAsset);
AZStd::string tabName = saveTabIndex >= 0 ? m_tabBar->tabText(saveTabIndex).toUtf8().data() : "";
@ -2002,18 +1936,11 @@ namespace ScriptCanvasEditor
const bool displayAsNotification = true;
RunGraphValidation(displayAsNotification);
// 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 (saveSuccess && m_closeCurrentGraphAfterSave)
{
AddSystemTickAction(SystemTickActionFlag::CloseCurrentGraph);
}
m_closeCurrentGraphAfterSave = false;
EnableAssetView(memoryAsset);
UpdateSaveState(true);
UnblockCloseRequests();
m_fileSaver.reset();
}
@ -2027,15 +1954,15 @@ namespace ScriptCanvasEditor
void MainWindow::SaveAs(AZStd::string_view path, ScriptCanvasEditor::SourceHandle inMemoryAssetId)
{
DisableAssetView(inMemoryAssetId);
UpdateSaveState(false);
m_fileSaver = AZStd::make_unique<VersionExplorer::FileSaver>
( nullptr
, [this](const VersionExplorer::FileSaveResult& fileSaveResult) { OnSaveCallBack(fileSaveResult); });
ScriptCanvasEditor::SourceHandle newLocation(inMemoryAssetId, {}, path);
ScriptCanvasEditor::SourceHandle newLocation(inMemoryAssetId, AZ::Uuid::CreateNull(), path);
MarkRecentSave(newLocation);
m_fileSaver->Save(newLocation);
UpdateSaveState();
BlockCloseRequests();
}
@ -2827,7 +2754,6 @@ namespace ScriptCanvasEditor
void MainWindow::OnActiveFileStateChanged()
{
UpdateSaveState();
UpdateAssignToSelectionState();
}
@ -3457,7 +3383,6 @@ namespace ScriptCanvasEditor
UpdateAssignToSelectionState();
UpdateUndoRedoState();
UpdateSaveState();
}
void MainWindow::OnWorkspaceRestoreStart()
@ -3535,25 +3460,10 @@ namespace ScriptCanvasEditor
ui->action_Redo->setEnabled(isEnabled);
}
void MainWindow::UpdateSaveState()
void MainWindow::UpdateSaveState(bool enabled)
{
// #sc_editor_asset todo, consider making blocking
// bool enabled = m_activeGraph.IsValid();
// bool isSaving = false;
// bool hasModifications = false;
//
// if (enabled)
// {
// Tracker::ScriptCanvasFileState fileState = GetAssetFileState(m_activeGraph);
// hasModifications = ( fileState == Tracker::ScriptCanvasFileState::MODIFIED
// || fileState == Tracker::ScriptCanvasFileState::NEW
// || fileState == Tracker::ScriptCanvasFileState::SOURCE_REMOVED);
//
// AssetTrackerRequestBus::BroadcastResult(isSaving, &AssetTrackerRequests::IsSaving, m_activeGraph);
// }
//
// ui->action_Save->setEnabled(enabled && !isSaving && hasModifications);
// ui->action_Save_As->setEnabled(enabled && !isSaving);
ui->action_Save->setEnabled(enabled);
ui->action_Save_As->setEnabled(enabled);
}
void MainWindow::CreateFunctionInput()
@ -4143,12 +4053,6 @@ namespace ScriptCanvasEditor
qobject_cast<QWidget*>(parent())->close();
}
if (HasSystemTickAction(SystemTickActionFlag::UpdateSaveMenuState))
{
RemoveSystemTickAction(SystemTickActionFlag::UpdateSaveMenuState);
UpdateSaveState();
}
if (HasSystemTickAction(SystemTickActionFlag::CloseCurrentGraph))
{
RemoveSystemTickAction(SystemTickActionFlag::CloseCurrentGraph);
@ -4165,10 +4069,7 @@ namespace ScriptCanvasEditor
CloseNextTab();
}
if (m_systemTickActions == 0)
{
AZ::SystemTickBus::Handler::BusDisconnect();
}
ClearStaleSaves();
}
void MainWindow::OnCommandStarted(AZ::Crc32)
@ -4395,11 +4296,6 @@ namespace ScriptCanvasEditor
void MainWindow::AddSystemTickAction(SystemTickActionFlag action)
{
if (!AZ::SystemTickBus::Handler::BusIsConnected())
{
AZ::SystemTickBus::Handler::BusConnect();
}
m_systemTickActions |= action;
}
@ -4749,5 +4645,34 @@ namespace ScriptCanvasEditor
UpdateUndoRedoState();
}
void MainWindow::ClearStaleSaves()
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
auto timeNow = AZStd::chrono::system_clock::now();
AZStd::erase_if(m_saves, [&timeNow](const auto& item)
{
AZStd::sys_time_t delta = AZStd::chrono::seconds(timeNow - item.second).count();
return delta > 2.0f;
});
}
bool MainWindow::IsRecentSave(const SourceHandle& handle) const
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(const_cast<MainWindow*>(this)->m_mutex);
AZStd::string key = handle.Path().Native();
AZStd::to_lower(key.begin(), key.end());
auto iter = m_saves.find(key);
return iter != m_saves.end();
}
void MainWindow::MarkRecentSave(const SourceHandle& handle)
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
AZStd::string key = handle.Path().Native();
AZStd::to_lower(key.begin(), key.end());
m_saves[key] = AZStd::chrono::system_clock::now();
}
#include <Editor/View/Windows/moc_MainWindow.cpp>
}

@ -425,9 +425,9 @@ namespace ScriptCanvasEditor
QVariant GetTabData(const SourceHandle& assetId);
//! GeneralRequestBus
AZ::Outcome<int, AZStd::string> OpenScriptCanvasAssetId(const SourceHandle& assetId) override;
AZ::Outcome<int, AZStd::string> OpenScriptCanvasAsset(SourceHandle scriptCanvasAssetId, int tabIndex = -1) override;
AZ::Outcome<int, AZStd::string> OpenScriptCanvasAssetImplementation(const SourceHandle& sourceHandle, int tabIndex = -1);
AZ::Outcome<int, AZStd::string> OpenScriptCanvasAssetId(const SourceHandle& assetId, Tracker::ScriptCanvasFileState fileState) override;
AZ::Outcome<int, AZStd::string> OpenScriptCanvasAsset(SourceHandle scriptCanvasAssetId, Tracker::ScriptCanvasFileState fileState, int tabIndex = -1) override;
AZ::Outcome<int, AZStd::string> OpenScriptCanvasAssetImplementation(const SourceHandle& sourceHandle, Tracker::ScriptCanvasFileState fileState, int tabIndex = -1);
int CloseScriptCanvasAsset(const SourceHandle& assetId) override;
bool CreateScriptCanvasAssetFor(const TypeDefs::EntityComponentId& requestingEntityId) override;
@ -438,8 +438,7 @@ namespace ScriptCanvasEditor
////
AZ::Outcome<int, AZStd::string> CreateScriptCanvasAsset(AZStd::string_view assetPath, int tabIndex = -1);
void RefreshScriptCanvasAsset(const AZ::Data::Asset<ScriptCanvas::ScriptCanvasAssetBase>& scriptCanvasAsset);
//! Removes the assetId -> ScriptCanvasAsset mapping and disconnects from the asset tracker
void RemoveScriptCanvasAsset(const ScriptCanvasEditor::SourceHandle& assetId);
void OnChangeActiveGraphTab(ScriptCanvasEditor::SourceHandle) override;
@ -525,8 +524,9 @@ namespace ScriptCanvasEditor
AZ::EntityId FindAssetNodeIdByEditorNodeId(const ScriptCanvasEditor::SourceHandle& assetId, AZ::EntityId editorNodeId) const override;
private:
void SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid fileAssetId) override;
void SourceFileRemoved(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid fileAssetId) override;
void DeleteNodes(const AZ::EntityId& sceneId, const AZStd::vector<AZ::EntityId>& nodes) override;
void DeleteConnections(const AZ::EntityId& sceneId, const AZStd::vector<AZ::EntityId>& connections) override;
void DisconnectEndpoints(const AZ::EntityId& sceneId, const AZStd::vector<GraphCanvas::Endpoint>& endpoints) override;
@ -549,11 +549,6 @@ namespace ScriptCanvasEditor
void OnAutoSave();
//! Helper function which serializes a file to disk
//! \param filename name of file to serialize the Entity
//! \param asset asset to save
void GetSuggestedFullFilenameToSaveAs(const ScriptCanvasEditor::SourceHandle& assetId, AZStd::string& filePath, AZStd::string& fileFilter);
void UpdateFileState(const ScriptCanvasEditor::SourceHandle& assetId, Tracker::ScriptCanvasFileState fileState);
// QMainWindow
@ -599,14 +594,14 @@ namespace ScriptCanvasEditor
void UpdateAssignToSelectionState();
void UpdateUndoRedoState();
void UpdateSaveState();
void UpdateSaveState(bool enabled);
void CreateFunctionInput();
void CreateFunctionOutput();
void CreateFunctionDefinitionNode(int positionOffset);
int CreateAssetTab(const ScriptCanvasEditor::SourceHandle& assetId, int tabIndex = -1);
int CreateAssetTab(const ScriptCanvasEditor::SourceHandle& assetId, Tracker::ScriptCanvasFileState fileState, int tabIndex = -1);
//! \param asset The AssetId of the ScriptCanvas Asset.
void SetActiveAsset(const ScriptCanvasEditor::SourceHandle& assetId);
@ -767,5 +762,11 @@ namespace ScriptCanvasEditor
AZStd::unique_ptr<VersionExplorer::FileSaver> m_fileSaver;
VersionExplorer::FileSaveResult m_fileSaveResult;
void OnSaveCallBack(const VersionExplorer::FileSaveResult& result);
void ClearStaleSaves();
bool IsRecentSave(const SourceHandle& handle) const;
void MarkRecentSave(const SourceHandle& handle);
AZStd::recursive_mutex m_mutex;
AZStd::unordered_map <AZStd::string, AZStd::chrono::system_clock::time_point> m_saves;
};
}

@ -98,7 +98,7 @@ namespace ScriptCanvasEditor
if (!asset.Path().empty())
{
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, asset, -1);
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, asset, Tracker::ScriptCanvasFileState::UNMODIFIED, -1);
}
if (!openOutcome)

@ -194,14 +194,18 @@ namespace ScriptCanvasEditor
, m_id(id)
, m_path(path)
{
m_path.MakePreferred();
m_id = id;
}
SourceHandle::SourceHandle(ScriptCanvas::DataPtr graph, const AZ::Uuid& id, const AZ::IO::Path& path)
: m_data(graph)
, m_id(id)
, m_path(path)
{}
{
m_path.MakePreferred();
m_id = id;
}
bool SourceHandle::AnyEquals(const SourceHandle& other) const
{

@ -27,8 +27,6 @@
#define OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED
// #define EDITOR_ASSET_SUPPORT_ENABLED
namespace AZ
{
class Entity;

Loading…
Cancel
Save