Merge pull request #5296 from aws-lumberyard-dev/sc-editor-asset-redux

Sc editor asset redux
This commit is contained in:
carlitosan
2021-12-07 09:15:52 -08:00
committed by GitHub
113 changed files with 3210 additions and 2792 deletions
@@ -5073,13 +5073,26 @@ LUA_API const Node* lua_getDummyNode()
// Check all constructors if they have use ScriptDataContext and if so choose this one
if (!customConstructorMethod)
{
int overrideIndex = -1;
AZ::AttributeReader(nullptr, FindAttribute
( Script::Attributes::DefaultConstructorOverrideIndex, behaviorClass->m_attributes)).Read<int>(overrideIndex);
int methodIndex = 0;
for (BehaviorMethod* method : behaviorClass->m_constructors)
{
if (methodIndex == overrideIndex)
{
customConstructorMethod = method;
break;
}
if (method->GetNumArguments() && method->GetArgument(method->GetNumArguments() - 1)->m_typeId == AZ::AzTypeInfo<ScriptDataContext>::Uuid())
{
customConstructorMethod = method;
break;
}
++methodIndex;
}
}
@@ -21,6 +21,7 @@ namespace AZ
static constexpr AZ::Crc32 ClassNameOverride = AZ_CRC_CE("ScriptClassNameOverride"); ///< Provide a custom name for script reflection, that doesn't match the behavior Context name
static constexpr AZ::Crc32 MethodOverride = AZ_CRC_CE("ScriptFunctionOverride"); ///< Use a custom function in the attribute instead of the function
static constexpr AZ::Crc32 ConstructorOverride = AZ_CRC_CE("ConstructorOverride"); ///< You can provide a custom constructor to be called when created from Lua script
static constexpr AZ::Crc32 DefaultConstructorOverrideIndex = AZ_CRC_CE("DefaultConstructorOverrideIndex"); ///< Use a different class constructor as the default constructor in Lua
static constexpr AZ::Crc32 EventHandlerCreationFunction = AZ_CRC_CE("EventHandlerCreationFunction"); ///< helps create a handler for any script target so that script functions can be used for AZ::Event signals
static constexpr AZ::Crc32 GenericConstructorOverride = AZ_CRC_CE("GenericConstructorOverride"); ///< You can provide a custom constructor to be called when creating a script
static constexpr AZ::Crc32 ReaderWriterOverride = AZ_CRC_CE("ReaderWriterOverride"); ///< paired with \ref ScriptContext::CustomReaderWriter allows you to customize read/write to Lua VM
@@ -133,6 +133,8 @@ namespace AZ
const static AZ::Crc32 AllowClearAsset = AZ_CRC("AllowClearAsset", 0x24827182);
// Show the name of the asset that was produced from the source asset
const static AZ::Crc32 ShowProductAssetFileName = AZ_CRC("ShowProductAssetFileName");
//! Regular expression pattern filter for source files
const static AZ::Crc32 SourceAssetFilterPattern = AZ_CRC_CE("SourceAssetFilterPattern");
//! Component icon attributes
const static AZ::Crc32 Icon = AZ_CRC("Icon", 0x659429db);
@@ -204,6 +204,22 @@ namespace AZ
// BaseJsonSerializer
//
JsonSerializationResult::Result BaseJsonSerializer::Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
{
JsonSerializationResult::ResultCode result(JsonSerializationResult::Tasks::ReadField);
result.Combine(ContinueLoading(outputValue, outputValueTypeId, inputValue, context, ContinuationFlags::IgnoreTypeSerializer));
return context.Report(result, "Ignoring custom serialization during load");
}
JsonSerializationResult::Result BaseJsonSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context)
{
JsonSerializationResult::ResultCode result(JsonSerializationResult::Tasks::WriteValue);
result.Combine(ContinueStoring(outputValue, inputValue, defaultValue, valueTypeId, context, ContinuationFlags::IgnoreTypeSerializer));
return context.Report(result, "Ignoring custom serialization during store");
}
BaseJsonSerializer::OperationFlags BaseJsonSerializer::GetOperationsFlags() const
{
return OperationFlags::None;
@@ -180,13 +180,16 @@ namespace AZ
//! Transforms the data from the rapidjson Value to outputValue, if the conversion is possible and supported.
//! The serializer is responsible for casting to the proper type and safely writing to the outputValue memory.
//! \note The default implementation is to load the object ignoring a custom serializers for the type, which allows for custom serializers
//! to modify the object after all default loading has occurred.
virtual JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) = 0;
JsonDeserializerContext& context);
//! Write the input value to a rapidjson value if the default value is not null and doesn't match the input value, otherwise
//! an error is returned and sets the rapidjson value to a null value.
//! \note The default implementation is to store the object ignoring custom serializers.
virtual JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) = 0;
const Uuid& valueTypeId, JsonSerializerContext& context);
//! Returns the operation flags which tells the Json Serialization how this custom json serializer can be used.
virtual OperationFlags GetOperationsFlags() const;
+2 -3
View File
@@ -165,13 +165,12 @@ namespace AZ::Utils
}
Container fileContent;
fileContent.resize(length);
fileContent.resize_no_construct(length);
AZ::IO::SizeType bytesRead = file.Read(length, fileContent.data());
file.Close();
// Resize again just in case bytesRead is less than length for some reason
fileContent.resize(bytesRead);
fileContent.resize_no_construct(bytesRead);
return AZ::Success(AZStd::move(fileContent));
}
@@ -99,6 +99,18 @@ namespace AzToolsFramework
}
}
if (selection.GetSelectedAssetIds().empty())
{
for (auto& filePath : selection.GetSelectedFilePaths())
{
if (!filePath.empty())
{
selectedAsset = true;
m_ui->m_assetBrowserTreeViewWidget->SelectFileAtPath(filePath);
}
}
}
if (!selectedAsset)
{
m_ui->m_assetBrowserTreeViewWidget->SelectFolder(selection.GetDefaultDirectory());
@@ -10,18 +10,24 @@
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/EBusFindAssetTypeByName.h>
#if !defined(Q_MOC_RUN)
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option")
#include <QRegExp>
AZ_POP_DISABLE_WARNING
#endif
namespace AzToolsFramework
{
namespace AssetBrowser
{
namespace
{
FilterConstType ProductsNoFoldersFilter()
FilterConstType EntryTypeNoFoldersFilter(AssetBrowserEntry::AssetEntryType entryType = AssetBrowserEntry::AssetEntryType::Product)
{
EntryTypeFilter* productFilter = new EntryTypeFilter();
productFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Product);
EntryTypeFilter* entryTypeFilter = new EntryTypeFilter();
entryTypeFilter->SetEntryType(entryType);
// in case entry is a source or folder, it may still contain relevant product
productFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::Down);
entryTypeFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::Down);
EntryTypeFilter* foldersFilter = new EntryTypeFilter();
foldersFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Folder);
@@ -30,7 +36,7 @@ namespace AzToolsFramework
noFoldersFilter->SetFilter(FilterConstType(foldersFilter));
CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
compFilter->AddFilter(FilterConstType(productFilter));
compFilter->AddFilter(FilterConstType(entryTypeFilter));
compFilter->AddFilter(FilterConstType(noFoldersFilter));
return FilterConstType(compFilter);
@@ -79,15 +85,39 @@ namespace AzToolsFramework
void AssetSelectionModel::SetSelectedAssetIds(const AZStd::vector<AZ::Data::AssetId>& selectedAssetIds)
{
m_selectedFilePaths.clear();
m_selectedAssetIds = selectedAssetIds;
}
void AssetSelectionModel::SetSelectedAssetId(const AZ::Data::AssetId& selectedAssetId)
{
m_selectedFilePaths.clear();
m_selectedAssetIds.clear();
m_selectedAssetIds.push_back(selectedAssetId);
}
const AZStd::vector<AZStd::string>& AssetSelectionModel::GetSelectedFilePaths() const
{
return m_selectedFilePaths;
}
void AssetSelectionModel::SetSelectedFilePaths(const AZStd::vector<AZStd::string>& selectedFilePaths)
{
m_selectedAssetIds.clear();
m_selectedFilePaths = selectedFilePaths;
}
void AssetSelectionModel::SetSelectedFilePath(const AZStd::string& selectedFilePath)
{
m_selectedAssetIds.clear();
m_selectedFilePaths.clear();
m_selectedFilePaths.push_back(selectedFilePath);
}
void AssetSelectionModel::SetDefaultDirectory(AZStd::string_view defaultDirectory)
{
m_defaultDirectory = defaultDirectory;
@@ -136,7 +166,7 @@ namespace AzToolsFramework
CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
compFilter->AddFilter(assetTypeFilterPtr);
compFilter->AddFilter(ProductsNoFoldersFilter());
compFilter->AddFilter(EntryTypeNoFoldersFilter());
selection.SetSelectionFilter(FilterConstType(compFilter));
selection.SetMultiselect(multiselect);
@@ -169,7 +199,7 @@ namespace AzToolsFramework
CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
compFilter->AddFilter(anyAssetTypeFilterPtr);
compFilter->AddFilter(ProductsNoFoldersFilter());
compFilter->AddFilter(EntryTypeNoFoldersFilter());
selection.SetSelectionFilter(FilterConstType(compFilter));
selection.SetMultiselect(multiselect);
@@ -190,7 +220,28 @@ namespace AzToolsFramework
CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
compFilter->AddFilter(assetGroupFilterPtr);
compFilter->AddFilter(ProductsNoFoldersFilter());
compFilter->AddFilter(EntryTypeNoFoldersFilter());
selection.SetSelectionFilter(FilterConstType(compFilter));
selection.SetMultiselect(multiselect);
return selection;
}
AssetSelectionModel AssetSelectionModel::SourceAssetTypeSelection(const QString& pattern, bool multiselect)
{
AssetSelectionModel selection;
RegExpFilter* patternFilter = new RegExpFilter();
patternFilter->SetFilterPattern(pattern);
patternFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::Down);
auto patternFilterPtr = FilterConstType(patternFilter);
selection.SetDisplayFilter(patternFilterPtr);
CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
compFilter->AddFilter(patternFilterPtr);
compFilter->AddFilter(EntryTypeNoFoldersFilter(AssetBrowserEntry::AssetEntryType::Source));
selection.SetSelectionFilter(FilterConstType(compFilter));
selection.SetMultiselect(multiselect);
@@ -204,7 +255,7 @@ namespace AzToolsFramework
CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::OR);
selection.SetDisplayFilter(FilterConstType(compFilter));
selection.SetSelectionFilter(ProductsNoFoldersFilter());
selection.SetSelectionFilter(EntryTypeNoFoldersFilter());
selection.SetMultiselect(multiselect);
return selection;
@@ -44,6 +44,10 @@ namespace AzToolsFramework
void SetSelectedAssetIds(const AZStd::vector<AZ::Data::AssetId>& selectedAssetIds);
void SetSelectedAssetId(const AZ::Data::AssetId& selectedAssetId);
const AZStd::vector<AZStd::string>& GetSelectedFilePaths() const;
void SetSelectedFilePaths(const AZStd::vector<AZStd::string>& selectedFilePaths);
void SetSelectedFilePath(const AZStd::string& selectedFilePath);
void SetDefaultDirectory(AZStd::string_view defaultDirectory);
AZStd::string_view GetDefaultDirectory() const;
@@ -60,6 +64,7 @@ namespace AzToolsFramework
static AssetSelectionModel AssetTypeSelection(const char* assetTypeName, bool multiselect = false);
static AssetSelectionModel AssetTypesSelection(const AZStd::vector<AZ::Data::AssetType>& assetTypes, bool multiselect = false);
static AssetSelectionModel AssetGroupSelection(const char* group, bool multiselect = false);
static AssetSelectionModel SourceAssetTypeSelection(const QString& pattern, bool multiselect = false);
static AssetSelectionModel EverythingSelection(bool multiselect = false);
private:
@@ -68,8 +73,12 @@ namespace AzToolsFramework
// some entries like folder should always be displayed, but not always selectable, thus 2 separate filters
FilterConstType m_selectionFilter;
FilterConstType m_displayFilter;
//! Selection can be based on asset ids (for products), or file paths (for sources)
//! These are mututally exclusive
AZStd::vector<AZ::Data::AssetId> m_selectedAssetIds;
AZStd::vector<AZStd::string> m_selectedFilePaths;
AZStd::vector<const AssetBrowserEntry*> m_results;
AZStd::string m_defaultDirectory;
@@ -251,6 +251,40 @@ namespace AzToolsFramework
return false;
}
//////////////////////////////////////////////////////////////////////////
// RegExpFilter
//////////////////////////////////////////////////////////////////////////
RegExpFilter::RegExpFilter()
: m_filterPattern("")
{
}
void RegExpFilter::SetFilterPattern(const QString& filterPattern)
{
m_filterPattern = filterPattern;
Q_EMIT updatedSignal();
}
QString RegExpFilter::GetNameInternal() const
{
return m_filterPattern;
}
bool RegExpFilter::MatchInternal(const AssetBrowserEntry* entry) const
{
// no filter pattern matches any asset
if (m_filterPattern.isEmpty())
{
return true;
}
// entry's name matches regular expression pattern
QRegExp regExp(m_filterPattern);
regExp.setPatternSyntax(QRegExp::Wildcard);
return regExp.exactMatch(entry->GetDisplayName());
}
//////////////////////////////////////////////////////////////////////////
// AssetTypeFilter
//////////////////////////////////////////////////////////////////////////
@@ -115,6 +115,28 @@ namespace AzToolsFramework
QString m_filterString;
};
//////////////////////////////////////////////////////////////////////////
// RegExpFilter
//////////////////////////////////////////////////////////////////////////
//! RegExpFilter filters assets based on a regular expression pattern
class RegExpFilter
: public AssetBrowserEntryFilter
{
Q_OBJECT
public:
RegExpFilter();
~RegExpFilter() override = default;
void SetFilterPattern(const QString& filterPattern);
protected:
QString GetNameInternal() const override;
bool MatchInternal(const AssetBrowserEntry* entry) const override;
private:
QString m_filterPattern;
};
//////////////////////////////////////////////////////////////////////////
// AssetTypeFilter
//////////////////////////////////////////////////////////////////////////
@@ -39,7 +39,12 @@ namespace AzToolsFramework
typeFilter->SetAssetType(filterType);
typeFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::Down);
m_assetBrowserFilterModel->SetFilter(FilterConstType(typeFilter));
SetFilter(FilterConstType(typeFilter));
}
void AssetCompleterModel::SetFilter(FilterConstType filter)
{
m_assetBrowserFilterModel->SetFilter(filter);
RefreshAssetList();
}
@@ -120,9 +125,6 @@ namespace AzToolsFramework
int rows = m_assetBrowserFilterModel->rowCount(index);
if (rows == 0)
{
if (index != QModelIndex()) {
AZ_Error("AssetCompleterModel", false, "No children detected in FetchResources()");
}
return;
}
@@ -131,7 +133,7 @@ namespace AzToolsFramework
QModelIndex childIndex = m_assetBrowserFilterModel->index(i, 0, index);
AssetBrowserEntry* childEntry = GetAssetEntry(m_assetBrowserFilterModel->mapToSource(childIndex));
if (childEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product)
if (childEntry->GetEntryType() == m_entryType)
{
ProductAssetBrowserEntry* productEntry = static_cast<ProductAssetBrowserEntry*>(childEntry);
AZStd::string assetName;
@@ -167,7 +169,6 @@ namespace AzToolsFramework
return m_assets[index.row()].m_displayName;
}
const AZ::Data::AssetId AssetCompleterModel::GetAssetIdFromIndex(const QModelIndex& index)
{
if (!index.isValid())
@@ -177,4 +178,19 @@ namespace AzToolsFramework
return m_assets[index.row()].m_assetId;
}
const AZStd::string_view AssetCompleterModel::GetPathFromIndex(const QModelIndex& index)
{
if (!index.isValid())
{
return "";
}
return m_assets[index.row()].m_path;
}
void AssetCompleterModel::SetFetchEntryType(AssetBrowserEntry::AssetEntryType entryType)
{
m_entryType = entryType;
}
}
@@ -32,6 +32,7 @@ namespace AzToolsFramework
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
void SetFilter(AZ::Data::AssetType filterType);
void SetFilter(FilterConstType filter);
void RefreshAssetList();
void SearchStringHighlight(QString searchString);
@@ -39,6 +40,9 @@ namespace AzToolsFramework
const AZStd::string_view GetNameFromIndex(const QModelIndex& index);
const AZ::Data::AssetId GetAssetIdFromIndex(const QModelIndex& index);
const AZStd::string_view GetPathFromIndex(const QModelIndex& index);
void SetFetchEntryType(AssetBrowserEntry::AssetEntryType entryType);
private:
struct AssetItem
@@ -57,6 +61,8 @@ namespace AzToolsFramework
AZStd::vector<AssetItem> m_assets;
//! String that will be highlighted in the suggestions
QString m_highlightString;
AssetBrowserEntry::AssetEntryType m_entryType = AssetBrowserEntry::AssetEntryType::Product;
};
}
@@ -1288,7 +1288,7 @@ namespace AzToolsFramework
return newCtrl;
}
void AssetPropertyHandlerDefault::ConsumeAttribute(PropertyAssetCtrl* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName)
void AssetPropertyHandlerDefault::ConsumeAttributeInternal(PropertyAssetCtrl* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName)
{
(void)debugName;
@@ -1487,6 +1487,11 @@ namespace AzToolsFramework
}
}
void AssetPropertyHandlerDefault::ConsumeAttribute(PropertyAssetCtrl* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName)
{
ConsumeAttributeInternal(GUI, attrib, attrValue, debugName);
}
void AssetPropertyHandlerDefault::WriteGUIValuesIntoProperty(size_t index, PropertyAssetCtrl* GUI, property_t& instance, InstanceDataNode* node)
{
(void)index;
@@ -1629,8 +1634,8 @@ namespace AzToolsFramework
void RegisterAssetPropertyHandler()
{
EBUS_EVENT(PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew AssetPropertyHandlerDefault());
EBUS_EVENT(PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SimpleAssetPropertyHandlerDefault());
PropertyTypeRegistrationMessages::Bus::Broadcast(&PropertyTypeRegistrationMessages::RegisterPropertyType, aznew AssetPropertyHandlerDefault());
PropertyTypeRegistrationMessages::Bus::Broadcast(&PropertyTypeRegistrationMessages::RegisterPropertyType, aznew SimpleAssetPropertyHandlerDefault());
}
}
@@ -175,10 +175,11 @@ namespace AzToolsFramework
virtual void SetFolderSelection(const AZStd::string& /* folderPath */) {}
virtual void ClearAssetInternal();
void ConfigureAutocompleter();
virtual void ConfigureAutocompleter();
void RefreshAutocompleter();
void EnableAutocompleter();
void DisableAutocompleter();
const QModelIndex GetSourceIndex(const QModelIndex& index);
void HandleFieldClear();
AZStd::string AddDefaultSuffix(const AZStd::string& filename);
@@ -235,20 +236,19 @@ namespace AzToolsFramework
void SetSelectedAssetID(const AZ::Data::AssetId& newID, const AZ::Data::AssetType& newType);
void SetCurrentAssetHint(const AZStd::string& hint);
void SetDefaultAssetID(const AZ::Data::AssetId& defaultID);
void PopupAssetPicker();
virtual void PopupAssetPicker();
void OnClearButtonClicked();
void UpdateAssetDisplay();
void OnLineEditFocus(bool focus);
virtual void OnEditButtonClicked();
void OnThumbnailClicked();
void OnCompletionModelReset();
void OnAutocomplete(const QModelIndex& index);
virtual void OnAutocomplete(const QModelIndex& index);
void OnTextChange(const QString& text);
void OnReturnPressed();
void ShowContextMenu(const QPoint& pos);
private:
const QModelIndex GetSourceIndex(const QModelIndex& index);
void UpdateThumbnail();
};
@@ -270,7 +270,8 @@ namespace AzToolsFramework
virtual void UpdateWidgetInternalTabbing(PropertyAssetCtrl* widget) override { widget->UpdateTabOrder(); }
virtual QWidget* CreateGUI(QWidget* pParent) override;
virtual void ConsumeAttribute(PropertyAssetCtrl* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName) override;
static void ConsumeAttributeInternal(PropertyAssetCtrl* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName);
void ConsumeAttribute(PropertyAssetCtrl* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName) override;
virtual void WriteGUIValuesIntoProperty(size_t index, PropertyAssetCtrl* GUI, property_t& instance, InstanceDataNode* node) override;
virtual bool ReadValuesIntoGUI(size_t index, PropertyAssetCtrl* GUI, const property_t& instance, InstanceDataNode* node) override;
};
@@ -669,6 +669,7 @@ namespace GraphCanvas
{
GeometryNotificationBus::Handler::BusDisconnect();
SceneNotificationBus::Handler::BusDisconnect();
AZ::SystemTickBus::Handler::BusDisconnect();
}
void GestureSceneHelper::TrackElement(const AZ::EntityId& elementId)
@@ -195,7 +195,7 @@ namespace GraphCanvas
}
else
{
AZ_Error("TranslationAsset", false, "Serialization of the TranslationFormat failed for: %s", asset.GetHint().c_str());
AZ_Warning("TranslationAsset", false, "Serialization of the TranslationFormat failed for: %s", asset.GetHint().c_str());
}
}
}
@@ -26,17 +26,14 @@ namespace ScriptCanvas
namespace ScriptCanvasEditor
{
class ScriptCanvasAsset;
class EditorAssetConversionBusTraits
: public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> LoadAsset(AZStd::string_view graphPath) = 0;
virtual AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> CreateLuaAsset(const AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>& editAsset, AZStd::string_view graphPathForRawLuaFile) = 0;
virtual AZ::Outcome<AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> CreateRuntimeAsset(const AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>& editAsset) = 0;
virtual AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> CreateLuaAsset(const SourceHandle& editAsset, AZStd::string_view graphPathForRawLuaFile) = 0;
virtual AZ::Outcome<AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> CreateRuntimeAsset(const SourceHandle& editAsset) = 0;
};
using EditorAssetConversionBus = AZ::EBus<EditorAssetConversionBusTraits>;
@@ -64,7 +64,6 @@ namespace ScriptCanvasEditor
void EditorAssetSystemComponent::Activate()
{
m_editorAssetRegistry.Register<ScriptCanvasAsset, ScriptCanvasAssetHandler, ScriptCanvasAssetDescription>();
m_editorAssetRegistry.Register<ScriptCanvas::SubgraphInterfaceAsset, ScriptCanvas::SubgraphInterfaceAssetHandler, ScriptCanvas::SubgraphInterfaceAssetDescription>();
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect();
@@ -98,35 +97,25 @@ namespace ScriptCanvasEditor
return false;
}
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> EditorAssetSystemComponent::LoadAsset(AZStd::string_view graphPath)
{
auto outcome = ScriptCanvasBuilder::LoadEditorAsset(graphPath, AZ::Data::AssetId(AZ::Uuid::CreateRandom()));
if (outcome.IsSuccess())
{
return outcome.GetValue();
}
else
{
return {};
}
}
AZ::Outcome<AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> EditorAssetSystemComponent::CreateRuntimeAsset(const AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>& editAsset)
AZ::Outcome<AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> EditorAssetSystemComponent::CreateRuntimeAsset(const SourceHandle& editAsset)
{
return ScriptCanvasBuilder::CreateRuntimeAsset(editAsset);
}
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> EditorAssetSystemComponent::CreateLuaAsset(const AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>& editAsset, AZStd::string_view graphPathForRawLuaFile)
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> EditorAssetSystemComponent::CreateLuaAsset(const SourceHandle& editAsset, AZStd::string_view graphPathForRawLuaFile)
{
return ScriptCanvasBuilder::CreateLuaAsset(editAsset->GetScriptCanvasEntity(), editAsset->GetId(), graphPathForRawLuaFile);
return ScriptCanvasBuilder::CreateLuaAsset(editAsset, graphPathForRawLuaFile);
}
void EditorAssetSystemComponent::AddSourceFileOpeners([[maybe_unused]] const char* fullSourceFileName, const AZ::Uuid& sourceUuid, 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))
{
@@ -138,22 +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:
openers.push_back({ "ScriptCanvas_Editor_Asset_Edit", "Script Canvas Editor...", QIcon(),
// 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);
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());
}
} });
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());
}
}});
}
}
@@ -49,9 +49,8 @@ namespace ScriptCanvasEditor
//////////////////////////////////////////////////////////////////////////
// EditorAssetConversionBus::Handler...
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> LoadAsset(AZStd::string_view graphPath) override;
AZ::Outcome<AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> CreateRuntimeAsset(const AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>& editAsset) override;
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> CreateLuaAsset(const AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>& editAsset, AZStd::string_view graphPathForRawLuaFile) override;
AZ::Outcome<AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> CreateRuntimeAsset(const SourceHandle& editAsset) override;
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> CreateLuaAsset(const SourceHandle& editAsset, AZStd::string_view graphPathForRawLuaFile) override;
//////////////////////////////////////////////////////////////////////////
ScriptCanvas::AssetRegistry& GetAssetRegistry();
@@ -13,15 +13,50 @@
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
#include <ScriptCanvas/Grammar/AbstractCodeModel.h>
#include <AzCore/Asset/AssetSerializer.h>
#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
#include <ScriptCanvas/Components/EditorGraph.h>
namespace ScriptCanvasBuilderCpp
namespace BuildVariableOverridesCpp
{
void AppendTabs(AZStd::string& result, size_t depth)
enum Version
{
for (size_t i = 0; i < depth; ++i)
Original = 1,
EditorAssetRedux,
// add description above
Current
};
bool VersionConverter
( AZ::SerializeContext& serializeContext
, AZ::SerializeContext::DataElementNode& rootElement)
{
if (rootElement.GetVersion() < BuildVariableOverridesCpp::Version::EditorAssetRedux)
{
result += "\t";
auto sourceIndex = rootElement.FindElement(AZ_CRC_CE("source"));
if (sourceIndex == -1)
{
AZ_Error("ScriptCanvas", false, "BuildVariableOverrides coversion failed: 'source' was missing");
return false;
}
auto& sourceElement = rootElement.GetSubElement(sourceIndex);
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> asset;
if (!sourceElement.GetData(asset))
{
AZ_Error("ScriptCanvas", false, "BuildVariableOverrides coversion failed: could not retrieve 'source' data");
return false;
}
ScriptCanvasEditor::SourceHandle sourceHandle(nullptr, asset.GetId().m_guid, {});
if (!rootElement.AddElementWithData(serializeContext, "source", sourceHandle))
{
AZ_Error("ScriptCanvas", false, "BuildVariableOverrides coversion failed: could not add updated 'source' data");
return false;
}
}
return true;
}
}
@@ -29,7 +64,7 @@ namespace ScriptCanvasBuilder
{
void BuildVariableOverrides::Clear()
{
m_source.Reset();
m_source = {};
m_variables.clear();
m_overrides.clear();
m_overridesUnused.clear();
@@ -39,12 +74,20 @@ namespace ScriptCanvasBuilder
void BuildVariableOverrides::CopyPreviousOverriddenValues(const BuildVariableOverrides& source)
{
auto copyPreviousIfFound = [](ScriptCanvas::GraphVariable& overriddenValue, const AZStd::vector<ScriptCanvas::GraphVariable>& source)
auto isEqual = [](const ScriptCanvas::GraphVariable& lhs, const ScriptCanvas::GraphVariable& rhs)
{
if (auto iter = AZStd::find_if(source.begin(), source.end(), [&overriddenValue](const auto& candidate) { return candidate.GetVariableId() == overriddenValue.GetVariableId(); });
iter != source.end())
return (lhs.GetVariableId() == rhs.GetVariableId() && lhs.GetDataType() == rhs.GetDataType())
|| (lhs.GetVariableName() == rhs.GetVariableName() && lhs.GetDataType() == rhs.GetDataType());
};
auto copyPreviousIfFound = [isEqual](ScriptCanvas::GraphVariable& overriddenValue, const AZStd::vector<ScriptCanvas::GraphVariable>& source)
{
auto iter = AZStd::find_if(source.begin(), source.end()
, [&overriddenValue, isEqual](const auto& candidate) { return isEqual(candidate, overriddenValue); });
if (iter != source.end())
{
overriddenValue.DeepCopy(*iter);
overriddenValue.ModDatum().DeepCopyDatum(*iter->GetDatum());
overriddenValue.SetScriptInputControlVisibility(AZ::Edit::PropertyVisibility::Hide);
overriddenValue.SetAllowSignalOnChange(false);
return true;
@@ -64,6 +107,15 @@ namespace ScriptCanvasBuilder
}
}
for (auto& overriddenValue : m_overridesUnused)
{
if (!copyPreviousIfFound(overriddenValue, source.m_overridesUnused))
{
// the variable in question may have been previously used, and is now unused, so copy the previous value over
copyPreviousIfFound(overriddenValue, source.m_overrides);
}
}
//////////////////////////////////////////////////////////////////////////
// #functions2 provide an identifier for the node/variable in the source that caused the dependency. the root will not have one.
// the above will provide the data to handle the cases where only certain dependency nodes were removed
@@ -100,7 +152,7 @@ namespace ScriptCanvasBuilder
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext))
{
serializeContext->Class<BuildVariableOverrides>()
->Version(1)
->Version(BuildVariableOverridesCpp::Version::Current, &BuildVariableOverridesCpp::VersionConverter)
->Field("source", &BuildVariableOverrides::m_source)
->Field("variables", &BuildVariableOverrides::m_variables)
->Field("entityId", &BuildVariableOverrides::m_entityIds)
@@ -194,45 +246,12 @@ namespace ScriptCanvasBuilder
}
}
EditorAssetTree* EditorAssetTree::ModRoot()
{
if (!m_parent)
{
return this;
}
return m_parent->ModRoot();
}
void EditorAssetTree::SetParent(EditorAssetTree& parent)
{
m_parent = &parent;
}
AZStd::string EditorAssetTree::ToString(size_t depth) const
{
AZStd::string result;
ScriptCanvasBuilderCpp::AppendTabs(result, depth);
result += m_asset.GetId().ToString<AZStd::string>();
result += m_asset.GetHint();
depth += m_dependencies.empty() ? 0 : 1;
for (const auto& dependency : m_dependencies)
{
result += "\n";
ScriptCanvasBuilderCpp::AppendTabs(result, depth);
result += dependency.ToString(depth);
}
return result;
}
ScriptCanvas::RuntimeDataOverrides ConvertToRuntime(const BuildVariableOverrides& buildOverrides)
{
ScriptCanvas::RuntimeDataOverrides runtimeOverrides;
runtimeOverrides.m_runtimeAsset = AZ::Data::Asset<ScriptCanvas::RuntimeAsset>
(AZ::Data::AssetId(buildOverrides.m_source.GetId().m_guid, AZ_CRC("RuntimeData", 0x163310ae)), azrtti_typeid<ScriptCanvas::RuntimeAsset>(), {});
(AZ::Data::AssetId(buildOverrides.m_source.Id(), AZ_CRC("RuntimeData", 0x163310ae)), azrtti_typeid<ScriptCanvas::RuntimeAsset>(), {});
runtimeOverrides.m_runtimeAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad);
runtimeOverrides.m_variableIndices.resize(buildOverrides.m_variables.size());
@@ -295,76 +314,9 @@ namespace ScriptCanvasBuilder
return runtimeOverrides;
}
AZ::Outcome<EditorAssetTree, AZStd::string> LoadEditorAssetTree(AZ::Data::AssetId editorAssetId, AZStd::string_view assetHint, EditorAssetTree* parent)
AZ::Outcome<BuildVariableOverrides, AZStd::string> ParseEditorAssetTree(const ScriptCanvasEditor::EditorAssetTree& editorAssetTree)
{
EditorAssetTree result;
AZ::Data::AssetInfo assetInfo;
AZStd::string watchFolder;
bool resultFound = false;
if (!AzToolsFramework::AssetSystemRequestBus::FindFirstHandler())
{
return AZ::Failure(AZStd::string("LoadEditorAssetTree found no handler for AzToolsFramework::AssetSystemRequestBus."));
}
AzToolsFramework::AssetSystemRequestBus::BroadcastResult
( resultFound
, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourceUUID
, editorAssetId.m_guid
, assetInfo
, watchFolder);
if (!resultFound)
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to get engine relative path from %s-%.*s.", editorAssetId.ToString<AZStd::string>().c_str(), aznumeric_cast<int>(assetHint.size()), assetHint.data()));
}
AZStd::vector<AZ::Data::AssetId> dependentAssets;
auto filterCB = [&dependentAssets](const AZ::Data::AssetFilterInfo& filterInfo)->bool
{
if (filterInfo.m_assetType == azrtti_typeid<ScriptCanvas::SubgraphInterfaceAsset>())
{
dependentAssets.push_back(AZ::Data::AssetId(filterInfo.m_assetId.m_guid, 0));
}
else if (filterInfo.m_assetType == azrtti_typeid<ScriptCanvasEditor::ScriptCanvasAsset>())
{
dependentAssets.push_back(filterInfo.m_assetId);
}
return true;
};
auto loadAssetOutcome = ScriptCanvasBuilder::LoadEditorAsset(assetInfo.m_relativePath, editorAssetId, filterCB);
if (!loadAssetOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to load graph from %s-%s: %s", editorAssetId.ToString<AZStd::string>().c_str(), assetHint.data(), loadAssetOutcome.GetError().c_str()));
}
for (auto& dependentAsset : dependentAssets)
{
auto loadDependentOutcome = LoadEditorAssetTree(dependentAsset, "", &result);
if (!loadDependentOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to load dependent graph from %s-%s: %s", editorAssetId.ToString<AZStd::string>().c_str(), assetHint.data(), loadDependentOutcome.GetError().c_str()));
}
result.m_dependencies.push_back(loadDependentOutcome.TakeValue());
}
if (parent)
{
result.SetParent(*parent);
}
result.m_asset = loadAssetOutcome.TakeValue();
return AZ::Success(result);
}
AZ::Outcome<BuildVariableOverrides, AZStd::string> ParseEditorAssetTree(const EditorAssetTree& editorAssetTree)
{
auto buildEntity = editorAssetTree.m_asset->GetScriptCanvasEntity();
auto buildEntity = editorAssetTree.m_asset.Get()->GetEntity();
if (!buildEntity)
{
return AZ::Failure(AZStd::string("No entity from source asset"));
@@ -400,9 +352,8 @@ namespace ScriptCanvasBuilder
if (!parseDependentOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string::format
( "ParseEditorAssetTree failed to parse dependent graph from %s-%s: %s"
, dependentAsset.m_asset.GetId().ToString<AZStd::string>().c_str()
, dependentAsset.m_asset.GetHint().c_str()
( "ParseEditorAssetTree failed to parse dependent graph from %s: %s"
, dependentAsset.m_asset.ToString().c_str()
, parseDependentOutcome.GetError().c_str()));
}
@@ -16,6 +16,7 @@
namespace ScriptCanvasEditor
{
class ScriptCanvasAsset;
class EditorAssetTree;
}
namespace ScriptCanvasBuilder
@@ -39,8 +40,8 @@ namespace ScriptCanvasBuilder
void PopulateFromParsedResults(ScriptCanvas::Grammar::AbstractCodeModelConstPtr abstractCodeModel, const ScriptCanvas::VariableData& variables);
// #functions2 provide an identifier for the node/variable in the source that caused the dependency. the root will not have one.
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> m_source;
ScriptCanvasEditor::SourceHandle m_source;
// all of the variables here are overrides
AZStd::vector<ScriptCanvas::GraphVariable> m_variables;
// the values here may or may not be overrides
@@ -48,30 +49,11 @@ namespace ScriptCanvasBuilder
// these two variable lists are all that gets exposed to the edit context
AZStd::vector<ScriptCanvas::GraphVariable> m_overrides;
AZStd::vector<ScriptCanvas::GraphVariable> m_overridesUnused;
// AZStd::vector<size_t> m_entityIdRuntimeInputIndices; since all of the entity ids need to go in, they may not need indices
AZStd::vector<BuildVariableOverrides> m_dependencies;
};
class EditorAssetTree
{
public:
AZ_CLASS_ALLOCATOR(EditorAssetTree, AZ::SystemAllocator, 0);
EditorAssetTree* m_parent = nullptr;
AZStd::vector<EditorAssetTree> m_dependencies;
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> m_asset;
EditorAssetTree* ModRoot();
void SetParent(EditorAssetTree& parent);
AZStd::string ToString(size_t depth = 0) const;
};
// copy the variables overridden during editor / prefab build time back to runtime data
ScriptCanvas::RuntimeDataOverrides ConvertToRuntime(const BuildVariableOverrides& overrides);
AZ::Outcome<EditorAssetTree, AZStd::string> LoadEditorAssetTree(AZ::Data::AssetId editorAssetId, AZStd::string_view assetHint, EditorAssetTree* parent = nullptr);
AZ::Outcome<BuildVariableOverrides, AZStd::string> ParseEditorAssetTree(const EditorAssetTree& editorAssetTree);
AZ::Outcome<BuildVariableOverrides, AZStd::string> ParseEditorAssetTree(const ScriptCanvasEditor::EditorAssetTree& editorAssetTree);
}
@@ -48,7 +48,6 @@ namespace ScriptCanvasBuilder
SharedHandlers HandleAssetTypes()
{
SharedHandlers handlers;
handlers.m_editorAssetHandler = RegisterHandler<ScriptCanvasEditor::ScriptCanvasAsset, ScriptCanvasEditor::ScriptCanvasAssetHandler>("scriptcanvas", false);
handlers.m_subgraphInterfaceHandler = RegisterHandler<ScriptCanvas::SubgraphInterfaceAsset, ScriptCanvas::SubgraphInterfaceAssetHandler>("scriptcanvas_fn_compiled", true);
handlers.m_runtimeAssetHandler = RegisterHandler<ScriptCanvas::RuntimeAsset, JobDependencyVerificationHandler>("scriptcanvas_compiled", true);
@@ -19,6 +19,7 @@
#include <ScriptCanvas/Asset/RuntimeAssetHandler.h>
#include <ScriptCanvas/Asset/SubgraphInterfaceAssetHandler.h>
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
#include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
#include <ScriptCanvas/Core/Connection.h>
@@ -27,12 +28,12 @@
#include <ScriptCanvas/Grammar/AbstractCodeModel.h>
#include <ScriptCanvas/Results/ErrorText.h>
#include <ScriptCanvas/Utils/BehaviorContextUtils.h>
#include <ScriptCanvas/Core/Core.h>
namespace ScriptCanvasBuilder
{
void Worker::Activate(const AssetHandlers& handlers)
{
m_editorAssetHandler = handlers.m_editorAssetHandler;
m_runtimeAssetHandler = handlers.m_runtimeAssetHandler;
m_subgraphInterfaceHandler = handlers.m_subgraphInterfaceHandler;
}
@@ -44,54 +45,22 @@ namespace ScriptCanvasBuilder
AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.data(), request.m_sourceFile.data(), fullPath, false);
AzFramework::StringFunc::Path::Normalize(fullPath);
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();
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> asset;
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;
}
const ScriptCanvasEditor::Graph* sourceGraph = nullptr;
const ScriptCanvas::GraphData* graphData = nullptr;
auto* scriptCanvasEntity = asset.Get()->GetScriptCanvasEntity();
auto* sourceGraph = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvasEditor::Graph>(scriptCanvasEntity);
ScriptCanvasEditor::SourceHandle sourceHandle;
auto sourceOutcome = ScriptCanvasEditor::LoadFromFile(fullPath);
if (sourceOutcome.IsSuccess())
{
sourceHandle = sourceOutcome.TakeValue();
sourceGraph = sourceHandle.Get();
graphData = sourceGraph->GetGraphDataConst();
}
AZ_Assert(sourceGraph, "Graph component is missing from entity.");
AZ_Assert(sourceGraph->GetGraphData(), "GraphData is missing from entity");
AZ_Assert(graphData, "GraphData is missing from entity");
struct EntityIdComparer
{
@@ -102,7 +71,7 @@ namespace ScriptCanvasBuilder
return lhsEntityId < rhsEntityId;
}
};
const AZStd::set<AZ::Entity*, EntityIdComparer> sortedEntities(sourceGraph->GetGraphData()->m_nodes.begin(), sourceGraph->GetGraphData()->m_nodes.end());
const AZStd::set<AZ::Entity*, EntityIdComparer> sortedEntities(graphData->m_nodes.begin(), graphData->m_nodes.end());
size_t fingerprint = 0;
for (const auto& nodeEntity : sortedEntities)
@@ -155,7 +124,7 @@ namespace ScriptCanvasBuilder
};
AZ_Verify(serializeContext->EnumerateInstanceConst
( sourceGraph->GetGraphData()
( graphData
, azrtti_typeid<ScriptCanvas::GraphData>()
, assetFilter
, {}
@@ -168,17 +137,6 @@ namespace ScriptCanvasBuilder
for (const AssetBuilderSDK::PlatformInfo& info : request.m_enabledPlatforms)
{
if (info.HasTag("tools"))
{
AssetBuilderSDK::JobDescriptor copyDescriptor;
copyDescriptor.m_priority = 2;
copyDescriptor.m_critical = true;
copyDescriptor.m_jobKey = s_scriptCanvasCopyJobKey;
copyDescriptor.SetPlatformIdentifier(info.m_identifier.c_str());
copyDescriptor.m_additionalFingerprintInfo = AZStd::string(GetFingerprintString()).append("|").append(AZStd::to_string(static_cast<AZ::u64>(fingerprint)));
response.m_createJobOutputs.push_back(copyDescriptor);
}
AssetBuilderSDK::JobDescriptor jobDescriptor;
jobDescriptor.m_priority = 2;
jobDescriptor.m_critical = true;
@@ -244,49 +202,14 @@ namespace ScriptCanvasBuilder
return;
}
if (!m_editorAssetHandler)
{
AZ_Error(s_scriptCanvasBuilder, false, R"(Exporting of .scriptcanvas for "%s" file failed as no editor asset handler was registered for script canvas. The ScriptCanvas Gem might not be enabled.)", fullPath.data());
return;
}
if (!m_runtimeAssetHandler)
{
AZ_Error(s_scriptCanvasBuilder, false, R"(Exporting of .scriptcanvas for "%s" file failed as no runtime asset handler was registered for script canvas.)", fullPath.data());
return;
}
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));
}
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> asset;
asset.Create(request.m_sourceFileUUID);
if (m_editorAssetHandler->LoadAssetDataFromStream(asset, assetDataStream, nullptr) != AZ::Data::AssetHandler::LoadResult::LoadComplete)
auto loadOutcome = ScriptCanvasEditor::LoadFromFile(request.m_fullPath);
if (!loadOutcome.IsSuccess())
{
AZ_Error(s_scriptCanvasBuilder, false, R"(Loading of ScriptCanvas asset for source file "%s" has failed)", fullPath.data());
return;
@@ -299,23 +222,11 @@ namespace ScriptCanvasBuilder
AzFramework::StringFunc::Path::Join(request.m_tempDirPath.c_str(), fileNameOnly.c_str(), runtimeScriptCanvasOutputPath, true, true);
AzFramework::StringFunc::Path::ReplaceExtension(runtimeScriptCanvasOutputPath, ScriptCanvas::RuntimeAsset::GetFileExtension());
if (request.m_jobDescription.m_jobKey == s_scriptCanvasCopyJobKey)
{
// ScriptCanvas Editor Asset Copy job
// The SubID is zero as this represents the main asset
AssetBuilderSDK::JobProduct jobProduct;
jobProduct.m_productFileName = fullPath;
jobProduct.m_productAssetType = azrtti_typeid<ScriptCanvasEditor::ScriptCanvasAsset>();
jobProduct.m_productSubID = 0;
jobProduct.m_dependenciesHandled = true;
jobProduct.m_dependencies.clear();
response.m_outputProducts.push_back(AZStd::move(jobProduct));
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
}
else
{
AZ::Entity* buildEntity = asset.Get()->GetScriptCanvasEntity();
auto sourceHandle = loadOutcome.TakeValue();
if (request.m_jobDescription.m_jobKey == s_scriptCanvasProcessJobKey)
{
AZ::Entity* buildEntity = sourceHandle.Get()->GetEntity();
ProcessTranslationJobInput input;
input.assetID = AZ::Data::AssetId(request.m_sourceFileUUID, AZ_CRC("RuntimeData", 0x163310ae));
input.request = &request;
@@ -37,12 +37,12 @@ namespace ScriptCanvasEditor
{
class Graph;
class ScriptCanvasAsset;
class SourceHandle;
}
namespace ScriptCanvasBuilder
{
constexpr const char* s_scriptCanvasBuilder = "ScriptCanvasBuilder";
constexpr const char* s_scriptCanvasCopyJobKey = "Script Canvas Copy Job";
constexpr const char* s_scriptCanvasProcessJobKey = "Script Canvas Process Job";
constexpr const char* s_unitTestParseErrorPrefix = "LY_SC_UnitTest";
@@ -59,6 +59,8 @@ namespace ScriptCanvasBuilder
PrefabIntegration,
CorrectGraphVariableVersion,
ReflectEntityIdNodes,
FixExecutionStateNodeableConstruction,
// add new entries above
Current,
};
@@ -69,7 +71,6 @@ namespace ScriptCanvasBuilder
struct AssetHandlers
{
AZ::Data::AssetHandler* m_editorAssetHandler = nullptr;
AZ::Data::AssetHandler* m_editorFunctionAssetHandler = nullptr;
AZ::Data::AssetHandler* m_runtimeAssetHandler = nullptr;
AZ::Data::AssetHandler* m_subgraphInterfaceHandler = nullptr;
@@ -80,7 +81,6 @@ namespace ScriptCanvasBuilder
struct SharedHandlers
{
HandlerOwnership m_editorAssetHandler{};
HandlerOwnership m_editorFunctionAssetHandler{};
HandlerOwnership m_runtimeAssetHandler{};
HandlerOwnership m_subgraphInterfaceHandler{};
@@ -122,13 +122,13 @@ namespace ScriptCanvasBuilder
}
};
AZ::Outcome<AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> CreateRuntimeAsset(const AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>& asset);
AZ::Outcome<AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> CreateRuntimeAsset(const ScriptCanvasEditor::SourceHandle& asset);
AZ::Outcome<ScriptCanvas::GraphData, AZStd::string> CompileGraphData(AZ::Entity* scriptCanvasEntity);
AZ::Outcome<ScriptCanvas::VariableData, AZStd::string> CompileVariableData(AZ::Entity* scriptCanvasEntity);
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> CreateLuaAsset(AZ::Entity* buildEntity, AZ::Data::AssetId scriptAssetId, AZStd::string_view rawLuaFilePath);
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> CreateLuaAsset(const ScriptCanvasEditor::SourceHandle& editAsset, AZStd::string_view rawLuaFilePath);
int GetBuilderVersion();
@@ -169,7 +169,6 @@ namespace ScriptCanvasBuilder
void ShutDown() override {};
private:
AZ::Data::AssetHandler* m_editorAssetHandler = nullptr;
AZ::Data::AssetHandler* m_runtimeAssetHandler = nullptr;
AZ::Data::AssetHandler* m_subgraphInterfaceHandler = nullptr;
@@ -29,19 +29,20 @@
#include <ScriptCanvas/Results/ErrorText.h>
#include <ScriptCanvas/Utils/BehaviorContextUtils.h>
#include <Source/Components/SceneComponent.h>
#include <ScriptCanvas/Core/Core.h>
#include <AzCore/Asset/AssetManagerBus.h>
namespace ScriptCanvasBuilder
{
AssetHandlers::AssetHandlers(SharedHandlers& source)
: m_editorAssetHandler(source.m_editorAssetHandler.first)
, m_editorFunctionAssetHandler(source.m_editorFunctionAssetHandler.first)
: m_editorFunctionAssetHandler(source.m_editorFunctionAssetHandler.first)
, m_runtimeAssetHandler(source.m_runtimeAssetHandler.first)
, m_subgraphInterfaceHandler(source.m_subgraphInterfaceHandler.first)
{}
void SharedHandlers::DeleteOwnedHandlers()
{
DeleteIfOwned(m_editorAssetHandler);
DeleteIfOwned(m_editorFunctionAssetHandler);
DeleteIfOwned(m_runtimeAssetHandler);
DeleteIfOwned(m_subgraphInterfaceHandler);
@@ -77,36 +78,23 @@ namespace ScriptCanvasBuilder
return ScriptCanvas::Translation::ParseGraph(request);
}
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> CreateLuaAsset(AZ::Entity* buildEntity, AZ::Data::AssetId scriptAssetId, AZStd::string_view rawLuaFilePath)
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> CreateLuaAsset(const ScriptCanvasEditor::SourceHandle& editAsset, AZStd::string_view rawLuaFilePath)
{
AZStd::string fullPath(rawLuaFilePath);
AZStd::string fileNameOnly;
AzFramework::StringFunc::Path::GetFullFileName(rawLuaFilePath.data(), fileNameOnly);
AzFramework::StringFunc::Path::Normalize(fullPath);
auto sourceGraph = PrepareSourceGraph(buildEntity);
auto sourceGraph = PrepareSourceGraph(editAsset.Mod()->GetEntity());
ScriptCanvas::Grammar::Request request;
request.scriptAssetId = scriptAssetId;
request.scriptAssetId = editAsset.Id();
request.graph = sourceGraph;
request.name = fileNameOnly;
request.rawSaveDebugOutput = ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile;
request.printModelToConsole = ScriptCanvas::Grammar::g_printAbstractCodeModel;
request.path = fullPath;
bool pathFound = false;
AZStd::string relativePath;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult
( pathFound
, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetRelativeProductPathFromFullSourceOrProductPath
, fullPath.c_str(), relativePath);
if (!pathFound)
{
AZ::Failure(AZStd::string::format("Failed to get engine relative path from %s", fullPath.c_str()));
}
request.namespacePath = relativePath;
const ScriptCanvas::Translation::Result translationResult = TranslateToLua(request);
auto isSuccessOutcome = translationResult.IsSuccess(ScriptCanvas::Translation::TargetFlags::Lua);
@@ -117,7 +105,7 @@ namespace ScriptCanvasBuilder
auto& translation = translationResult.m_translations.find(ScriptCanvas::Translation::TargetFlags::Lua)->second;
AZ::Data::Asset<AZ::ScriptAsset> asset;
scriptAssetId.m_subId = AZ::ScriptAsset::CompiledAssetSubId;
AZ::Data::AssetId scriptAssetId(editAsset.Id(), AZ::ScriptAsset::CompiledAssetSubId);
asset.Create(scriptAssetId);
auto writeStream = asset.Get()->CreateWriteStream();
@@ -144,12 +132,12 @@ namespace ScriptCanvasBuilder
return AZ::Success(result);
}
AZ::Outcome<AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> CreateRuntimeAsset(const AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>& editAsset)
AZ::Outcome<AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> CreateRuntimeAsset(const ScriptCanvasEditor::SourceHandle& editAsset)
{
// Flush asset manager events to ensure no asset references are held by closures queued on Ebuses.
AZ::Data::AssetManager::Instance().DispatchEvents();
auto runtimeAssetId = editAsset.GetId();
AZ::Data::AssetId runtimeAssetId = editAsset.Id();
runtimeAssetId.m_subId = AZ_CRC("RuntimeData", 0x163310ae);
AZ::Data::Asset<ScriptCanvas::RuntimeAsset> runtimeAsset;
runtimeAsset.Create(runtimeAssetId);
@@ -23,6 +23,7 @@
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
#include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
@@ -93,49 +94,6 @@ namespace ScriptCanvasEditor
}
}
AZ::Outcome<void, AZStd::string> LoadScriptCanvasDataFromJson
( ScriptCanvas::ScriptCanvasData& dataTarget
, AZStd::string_view source
, AZ::SerializeContext& serializeContext)
{
namespace JSRU = AZ::JsonSerializationUtils;
using namespace ScriptCanvas;
AZ::JsonDeserializerSettings settings;
settings.m_serializeContext = &serializeContext;
settings.m_metadata.Create<SerializationListeners>();
auto loadResult = JSRU::LoadObjectFromStringByType
( &dataTarget
, azrtti_typeid<ScriptCanvasData>()
, source
, &settings);
if (!loadResult.IsSuccess())
{
return loadResult;
}
if (auto graphData = dataTarget.ModGraph())
{
auto listeners = settings.m_metadata.Find<SerializationListeners>();
AZ_Assert(listeners, "Failed to find SerializationListeners");
ScriptCanvasAssetHandlerCpp::CollectNodes(graphData->GetGraphData()->m_nodes, *listeners);
for (auto listener : *listeners)
{
listener->OnDeserialize();
}
}
else
{
return AZ::Failure(AZStd::string("Failed to find graph data after loading source"));
}
return AZ::Success();
}
AZ::Data::AssetHandler::LoadResult ScriptCanvasAssetHandler::LoadAssetData
( const AZ::Data::Asset<AZ::Data::AssetData>& assetTarget
, AZStd::shared_ptr<AZ::Data::AssetDataStream> streamSource
@@ -167,7 +125,7 @@ namespace ScriptCanvasEditor
settings.m_serializeContext = m_serializeContext;
settings.m_metadata.Create<SerializationListeners>();
// attempt JSON deserialization...
auto jsonResult = LoadScriptCanvasDataFromJson
auto jsonResult = LoadDataFromJson
( scriptCanvasDataTarget
, AZStd::string_view{ byteBuffer.begin(), byteBuffer.size() }
, *m_serializeContext);
@@ -228,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;
@@ -82,30 +82,6 @@ namespace ScriptCanvasEditor
void ScriptCanvasAssetHolder::OpenEditor() const
{
AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas);
AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
if (m_scriptCanvasAsset.IsReady())
{
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, m_scriptCanvasAsset.GetId(), -1);
if (!openOutcome)
{
AZ_Warning("Script Canvas", openOutcome, "%s", openOutcome.GetError().data());
}
}
else if (m_ownerId.first.IsValid())
{
AzToolsFramework::EntityIdList selectedEntityIds;
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(selectedEntityIds, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities);
// Going to bypass the multiple selected entities flow for right now.
if (selectedEntityIds.size() == 1)
{
GeneralRequestBus::Broadcast(&GeneralRequests::CreateScriptCanvasAssetFor, m_ownerId);
}
}
}
ScriptCanvas::ScriptCanvasId ScriptCanvasAssetHolder::GetScriptCanvasId() const
@@ -58,111 +58,8 @@ namespace ScriptCanvasEditor
SaveAs(assetId, {}, onSaveCallback);
}
void AssetTracker::SaveAs(AZ::Data::AssetId assetId, const AZStd::string& path, Callbacks::OnSave onSaveCallback)
void AssetTracker::SaveAs(AZ::Data::AssetId /*assetId*/, const AZStd::string& /*path*/, Callbacks::OnSave /*onSaveCallback*/)
{
auto assetIter = m_assetsInUse.find(assetId);
if (assetIter != m_assetsInUse.end())
{
auto onSave = [this, assetId, onSaveCallback](bool saveSuccess, AZ::Data::AssetPtr asset, AZ::Data::AssetId previousFileAssetId)
{
AZ::Data::AssetId signalId = assetId;
AZ::Data::AssetId fileAssetId = asset->GetId();
// If there is a previous file Id is valid, it means this is a save-as operation and we need to remap the tracking.
if (previousFileAssetId.IsValid())
{
if (saveSuccess)
{
fileAssetId = m_assetsInUse[assetId]->GetFileAssetId();
m_remappedAsset[asset->GetId()] = fileAssetId;
// Erase the asset first so the smart pointer can deal with it's things.
m_assetsInUse.erase(fileAssetId);
// Then perform the insert once we know nothing will attempt to delete this while we are operating on it.
m_assetsInUse[fileAssetId] = m_assetsInUse[assetId];
m_assetsInUse.erase(assetId);
}
m_savingAssets.erase(assetId);
m_savingAssets.insert(fileAssetId);
signalId = fileAssetId;
if (m_queuedCloses.erase(assetId))
{
m_queuedCloses.insert(fileAssetId);
}
auto assetIter = m_assetsInUse.find(fileAssetId);
if (assetIter != m_assetsInUse.end())
{
AZStd::invoke(onSaveCallback, saveSuccess, m_assetsInUse[fileAssetId]->GetAsset().Get(), previousFileAssetId);
}
else
{
AZ_Error("ScriptCanvas", !saveSuccess, "Unable to find Memory Asset for Asset(%s)", fileAssetId.ToString<AZStd::string>().c_str());
AZStd::invoke(onSaveCallback, saveSuccess, asset, previousFileAssetId);
}
}
else
{
if (saveSuccess)
{
// This should be the case when we get a save as from a newly created file.
//
// If we find the 'memory' asset id in the assets in use. This means this was a new file that was saved.
// To maintain all of the look-up stuff, we need to treat this like a remapping stage.
auto assetInUseIter = m_assetsInUse.find(assetId);
if (assetInUseIter != m_assetsInUse.end())
{
fileAssetId = assetInUseIter->second->GetFileAssetId();
if (assetId != fileAssetId)
{
m_remappedAsset[assetId] = fileAssetId;
m_assetsInUse.erase(fileAssetId);
m_assetsInUse[fileAssetId] = AZStd::move(assetInUseIter->second);
m_assetsInUse.erase(assetId);
m_savingAssets.erase(assetId);
m_savingAssets.insert(fileAssetId);
if (m_queuedCloses.erase(assetId))
{
m_queuedCloses.insert(fileAssetId);
}
}
}
else
{
fileAssetId = CheckAssetId(fileAssetId);
}
signalId = fileAssetId;
}
if (onSaveCallback)
{
AZStd::invoke(onSaveCallback, saveSuccess, m_assetsInUse[signalId]->GetAsset().Get(), previousFileAssetId);
}
AssetTrackerNotificationBus::Broadcast(&AssetTrackerNotifications::OnAssetSaved, m_assetsInUse[signalId], saveSuccess);
}
SignalSaveComplete(signalId);
};
m_savingAssets.insert(assetId);
assetIter->second->SaveAs(path, onSave);
}
else
{
AZ_Assert(false, "Cannot SaveAs into an existing AssetId");
}
}
bool AssetTracker::Load(AZ::Data::AssetId fileAssetId, AZ::Data::AssetType assetType, Callbacks::OnAssetReadyCallback onAssetReadyCallback)
@@ -541,48 +438,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
@@ -119,10 +120,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;
@@ -154,17 +155,5 @@ namespace ScriptCanvasEditor
using MemoryAssetSystemNotificationBus = AZ::EBus<MemoryAssetSystemNotifications>;
}
class MemoryAssetNotifications
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = AZ::Data::AssetId;
virtual void OnFileStateChanged(Tracker::ScriptCanvasFileState) {}
};
using MemoryAssetNotificationBus = AZ::EBus<MemoryAssetNotifications>;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
}
@@ -18,22 +18,11 @@ namespace ScriptCanvasEditor
namespace Callbacks
{
//! Callback used to know when a save operation failed or succeeded
using OnSave = AZStd::function<void(bool saveSuccess, AZ::Data::AssetPtr, AZ::Data::AssetId previousFileAssetId)>;
using OnSave = AZStd::function<void(bool saveSuccess, const SourceHandle& attempt, const SourceHandle& previous)>;
using OnAssetReadyCallback = AZStd::function<void(ScriptCanvasMemoryAsset&)>;
using OnAssetCreatedCallback = OnAssetReadyCallback;
}
namespace Tracker
{
enum class ScriptCanvasFileState : AZ::s32
{
NEW,
MODIFIED,
UNMODIFIED,
SOURCE_REMOVED,
INVALID = -1
};
}
}
@@ -0,0 +1,329 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/GenericStreams.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/Utils.h>
#include <AzCore/Utils/Utils.h>
#include <AzCore/std/string/string_view.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
#include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/Core/SerializationListener.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Libraries/Math/MathNodeUtilities.h>
namespace ScriptCanvasFileHandlingCpp
{
void AppendTabs(AZStd::string& result, size_t depth)
{
for (size_t i = 0; i < depth; ++i)
{
result += "\t";
}
}
void CollectNodes(const ScriptCanvas::GraphData::NodeContainer& container, ScriptCanvas::SerializationListeners& listeners)
{
for (auto& nodeEntity : container)
{
if (nodeEntity)
{
if (auto listener = azrtti_cast<ScriptCanvas::SerializationListener*>
( AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Node>(nodeEntity)))
{
listeners.push_back(listener);
}
}
}
}
}
namespace ScriptCanvasEditor
{
EditorAssetTree* EditorAssetTree::ModRoot()
{
if (!m_parent)
{
return this;
}
return m_parent->ModRoot();
}
void EditorAssetTree::SetParent(EditorAssetTree& parent)
{
m_parent = &parent;
}
AZStd::string EditorAssetTree::ToString(size_t depth) const
{
AZStd::string result;
ScriptCanvasFileHandlingCpp::AppendTabs(result, depth);
result += m_asset.ToString();
depth += m_dependencies.empty() ? 0 : 1;
for (const auto& dependency : m_dependencies)
{
result += "\n";
ScriptCanvasFileHandlingCpp::AppendTabs(result, depth);
result += dependency.ToString(depth);
}
return result;
}
AZ::Outcome<void, AZStd::string> LoadDataFromJson
( ScriptCanvas::ScriptCanvasData& dataTarget
, AZStd::string_view source
, AZ::SerializeContext& serializeContext)
{
namespace JSRU = AZ::JsonSerializationUtils;
using namespace ScriptCanvas;
AZ::JsonDeserializerSettings settings;
settings.m_serializeContext = &serializeContext;
settings.m_metadata.Create<SerializationListeners>();
auto loadResult = JSRU::LoadObjectFromStringByType
( &dataTarget
, azrtti_typeid<ScriptCanvasData>()
, source
, &settings);
if (!loadResult.IsSuccess())
{
return loadResult;
}
if (auto graphData = dataTarget.ModGraph())
{
auto listeners = settings.m_metadata.Find<SerializationListeners>();
AZ_Assert(listeners, "Failed to find SerializationListeners");
ScriptCanvasFileHandlingCpp::CollectNodes(graphData->GetGraphData()->m_nodes, *listeners);
for (auto listener : *listeners)
{
listener->OnDeserialize();
}
}
else
{
return AZ::Failure(AZStd::string("Failed to find graph data after loading source"));
}
return AZ::Success();
}
AZ::Outcome<EditorAssetTree, AZStd::string> LoadEditorAssetTree(SourceHandle handle, EditorAssetTree* parent)
{
if (!CompleteDescriptionInPlace(handle))
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to describe graph from %s", handle.ToString().c_str()));
}
if (!handle.Get())
{
auto loadAssetOutcome = LoadFromFile(handle.Path().c_str());
if (!loadAssetOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to load graph from %s: %s"
, handle.ToString().c_str(), loadAssetOutcome.GetError().c_str()));
}
handle = SourceHandle(loadAssetOutcome.GetValue(), handle.Id(), handle.Path().c_str());
}
AZStd::vector<SourceHandle> dependentAssets;
const auto subgraphInterfaceAssetTypeID = azrtti_typeid<AZ::Data::Asset<ScriptCanvas::SubgraphInterfaceAsset>>();
auto beginElementCB = [&subgraphInterfaceAssetTypeID, &dependentAssets]
( void* instance
, const AZ::SerializeContext::ClassData* classData
, const AZ::SerializeContext::ClassElement* classElement) -> bool
{
if (classElement)
{
// if we are a pointer, then we may be pointing to a derived type.
if (classElement->m_flags & AZ::SerializeContext::ClassElement::FLG_POINTER)
{
// if ptr is a pointer-to-pointer, cast its value to a void* (or const void*) and dereference to get to the actual object pointer.
instance = *(void**)(instance);
}
}
if (classData->m_typeId == subgraphInterfaceAssetTypeID)
{
auto asset = reinterpret_cast<AZ::Data::Asset<ScriptCanvas::SubgraphInterfaceAsset>*>(instance);
auto id = asset->GetId();
dependentAssets.push_back(SourceHandle(nullptr, id.m_guid, {}));
}
return true;
};
AZ::SerializeContext* serializeContext = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
AZ_Assert(serializeContext, "LoadEditorAssetTree() ailed to retrieve serialize context!");
const ScriptCanvasEditor::Graph* graph = handle.Get();
serializeContext->EnumerateObject(graph, beginElementCB, nullptr, AZ::SerializeContext::ENUM_ACCESS_FOR_READ);
EditorAssetTree result;
for (auto& dependentAsset : dependentAssets)
{
auto loadDependentOutcome = LoadEditorAssetTree(dependentAsset, &result);
if (!loadDependentOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to load graph from %s: %s"
, dependentAsset.ToString().c_str(), loadDependentOutcome.GetError().c_str()));
}
result.m_dependencies.push_back(loadDependentOutcome.TakeValue());
}
if (parent)
{
result.SetParent(*parent);
}
result.m_asset = AZStd::move(handle);
return AZ::Success(result);
}
AZ::Outcome<ScriptCanvasEditor::SourceHandle, AZStd::string> LoadFromFile(AZStd::string_view path)
{
namespace JSRU = AZ::JsonSerializationUtils;
auto fileStringOutcome = AZ::Utils::ReadFile<AZStd::string>(path);
if (!fileStringOutcome)
{
return AZ::Failure(fileStringOutcome.TakeError());
}
const auto& asString = fileStringOutcome.GetValue();
ScriptCanvas::DataPtr scriptCanvasData = aznew ScriptCanvas::ScriptCanvasData();
if (!scriptCanvasData)
{
return AZ::Failure(AZStd::string("failed to allocate ScriptCanvas::ScriptCanvasData after loading source file"));
}
AZ::SerializeContext* serializeContext = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
if (!serializeContext)
{
return AZ::Failure(AZStd::string("no serialize context available to properly parse source file"));
}
// attempt JSON deserialization...
auto jsonResult = LoadDataFromJson(*scriptCanvasData, AZStd::string_view{ asString.begin(), asString.size() }, *serializeContext);
if (!jsonResult.IsSuccess())
{
// ...try legacy xml as a failsafe
AZ::IO::ByteContainerStream byteStream(&asString);
if (!AZ::Utils::LoadObjectFromStreamInPlace
( byteStream
, *scriptCanvasData
, serializeContext
, AZ::ObjectStream::FilterDescriptor(nullptr, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES)))
{
return AZ::Failure(AZStd::string::format("XML and JSON load attempts failed: %s", jsonResult.GetError().c_str()));
}
}
if (auto entity = scriptCanvasData->GetScriptCanvasEntity())
{
AZ_Assert(entity->GetState() == AZ::Entity::State::Constructed, "Entity loaded in bad state");
AZ::u64 entityId =
aznumeric_caster(ScriptCanvas::MathNodeUtilities::GetRandomIntegral<AZ::s64>(1, std::numeric_limits<AZ::s64>::max()));
entity->SetId(AZ::EntityId(entityId));
auto graph = entity->FindComponent<ScriptCanvasEditor::Graph>();
graph->MarkOwnership(*scriptCanvasData);
entity->Init();
entity->Activate();
}
else
{
return AZ::Failure(AZStd::string("Loaded script canvas file was missing a necessary Entity."));
}
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.IsGraphValid())
{
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 serializable 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::format("JSON serialization failed to save source: %s", saveOutcome.GetError().c_str()));
}
return AZ::Success();
}
}
@@ -19,8 +19,7 @@
namespace ScriptCanvasEditor
{
ScriptCanvasMemoryAsset::ScriptCanvasMemoryAsset()
: m_isSaving(false)
, m_sourceInError(false)
: m_sourceInError(false)
{
m_undoState = AZStd::make_unique<SceneUndoState>(this);
}
@@ -279,14 +278,11 @@ namespace ScriptCanvasEditor
EditorGraphNotificationBus::Handler::BusDisconnect();
EditorGraphNotificationBus::Handler::BusConnect(m_scriptCanvasId);
m_undoHelper = AZStd::make_unique<UndoHelper>(*this);
}
ScriptCanvasEditor::Widget::CanvasWidget* ScriptCanvasMemoryAsset::CreateView(QWidget* parent)
ScriptCanvasEditor::Widget::CanvasWidget* ScriptCanvasMemoryAsset::CreateView(QWidget* /*parent*/)
{
m_canvasWidget = new Widget::CanvasWidget(m_fileAssetId, parent);
return m_canvasWidget;
return nullptr;
}
void ScriptCanvasMemoryAsset::ClearView()
@@ -430,68 +426,13 @@ namespace ScriptCanvasEditor
}
}
void ScriptCanvasMemoryAsset::SourceFileFailed(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid)
void ScriptCanvasMemoryAsset::SourceFileFailed(AZStd::string /*relativePath*/, AZStd::string /*scanFolder*/, AZ::Uuid)
{
AZStd::string fullPath;
AzFramework::StringFunc::Path::Join(scanFolder.data(), relativePath.data(), fullPath);
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::NormalizePath, fullPath);
auto assetPathIdIt = AZStd::find(m_pendingSave.begin(), m_pendingSave.end(), fullPath);
if (assetPathIdIt != m_pendingSave.end())
{
if (m_onSaveCallback)
{
m_onSaveCallback(false, m_inMemoryAsset.Get(), AZ::Data::AssetId());
m_onSaveCallback = nullptr;
}
m_pendingSave.erase(assetPathIdIt);
}
}
void ScriptCanvasMemoryAsset::SavingComplete(const AZStd::string& streamName, AZ::Uuid sourceAssetId)
void ScriptCanvasMemoryAsset::SavingComplete(const AZStd::string& /*streamName*/, AZ::Uuid /*sourceAssetId*/)
{
AZStd::string normPath = streamName;
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::NormalizePath, normPath);
auto assetPathIdIt = AZStd::find(m_pendingSave.begin(), m_pendingSave.end(), normPath);
if (assetPathIdIt != m_pendingSave.end())
{
AZ::Data::AssetId previousFileAssetId;
if (sourceAssetId != m_fileAssetId.m_guid)
{
previousFileAssetId = m_fileAssetId;
// The source file has changed, store the AssetId to the canonical asset on file
SetFileAssetId(sourceAssetId);
}
else if (!m_fileAssetId.IsValid())
{
SetFileAssetId(sourceAssetId);
}
m_formerGraphIdPair = AZStd::make_pair(m_scriptCanvasId, m_graphId);
m_fileState = Tracker::ScriptCanvasFileState::UNMODIFIED;
m_pendingSave.erase(assetPathIdIt);
m_absolutePath = m_saveAsPath;
m_saveAsPath.clear();
// Connect to the source asset's bus to monitor for situations we may need to handle
AZ::Data::AssetBus::MultiHandler::BusConnect(m_inMemoryAsset.GetId());
AZ::Data::AssetBus::MultiHandler::BusConnect(m_fileAssetId);
if (m_onSaveCallback)
{
m_onSaveCallback(true, m_inMemoryAsset.Get(), previousFileAssetId);
m_onSaveCallback = nullptr;
}
}
}
void ScriptCanvasMemoryAsset::FinalizeAssetSave(bool, const AzToolsFramework::SourceControlFileInfo& fileInfo, const AZ::Data::AssetStreamInfo& saveInfo, Callbacks::OnSave onSaveCallback)
@@ -525,19 +466,13 @@ namespace ScriptCanvasEditor
UndoNotificationBus::Broadcast(&UndoNotifications::OnCanRedoChanged, m_undoState->m_undoStack->CanRedo());
}
void ScriptCanvasMemoryAsset::SetFileAssetId(const AZ::Data::AssetId& fileAssetId)
void ScriptCanvasMemoryAsset::SetFileAssetId(const AZ::Data::AssetId& /*fileAssetId*/)
{
m_fileAssetId = fileAssetId;
if (m_canvasWidget)
{
m_canvasWidget->SetAssetId(fileAssetId);
}
}
void ScriptCanvasMemoryAsset::SignalFileStateChanged()
{
MemoryAssetNotificationBus::Event(m_fileAssetId, &MemoryAssetNotifications::OnFileStateChanged, GetFileState());
}
AZStd::string ScriptCanvasMemoryAsset::MakeTemporaryFilePathForSave(AZStd::string_view targetFilename)
@@ -604,27 +539,8 @@ namespace ScriptCanvasEditor
// AssetSaveFinalizer
//////////////////////////////////////
bool AssetSaveFinalizer::ValidateStatus(const AzToolsFramework::SourceControlFileInfo& fileInfo)
bool AssetSaveFinalizer::ValidateStatus(const AzToolsFramework::SourceControlFileInfo& /*fileInfo*/)
{
auto fileIO = AZ::IO::FileIOBase::GetInstance();
if (fileInfo.IsLockedByOther())
{
AZ_Error("Script Canvas", !fileInfo.IsLockedByOther(), "The file is already exclusively opened by another user: %s", fileInfo.m_filePath.data());
AZStd::invoke(m_onSave, false, m_inMemoryAsset, m_fileAssetId);
return false;
}
else if (fileInfo.IsReadOnly() && fileIO->Exists(fileInfo.m_filePath.c_str()))
{
AZ_Error("Script Canvas", !fileInfo.IsReadOnly(), "File %s is read-only. It cannot be saved."
" If this file is in Perforce it may not have been checked out by the Source Control API.", fileInfo.m_filePath.data());
AZStd::invoke(m_onSave, false, m_inMemoryAsset, m_fileAssetId);
return false;
}
else if (m_saving)
{
AZ_Warning("Script Canvas", false, "Trying to save the same file twice. Will result in one save callback being ignored.");
return false;
}
return true;
}
@@ -29,6 +29,8 @@
#include <Editor/View/Widgets/CanvasWidget.h>
#include <Editor/Undo/ScriptCanvasUndoManager.h>
#include <ScriptCanvas/Bus/RequestBus.h>
namespace ScriptCanvasEditor
{
@@ -172,7 +174,6 @@ namespace ScriptCanvasEditor
bool IsSourceInError() const;
void OnSourceAssetFinalized(const AZStd::string& fullPath, AZ::Uuid sourceAssetId);
void SavingComplete(const AZStd::string& fullPath, AZ::Uuid sourceAssetId);
AZ::Data::AssetId GetSourceUuid() const { return m_sourceUuid; }
@@ -320,7 +321,6 @@ namespace ScriptCanvasEditor
//! The undo helper is an object that implements the Undo behaviors
AZStd::unique_ptr<UndoHelper> m_undoHelper;
bool m_isSaving;
bool m_sourceInError;
AZ::Data::AssetId m_sourceUuid;
@@ -9,13 +9,19 @@
#include "ScriptCanvasUndoHelper.h"
#include "ScriptCanvasMemoryAsset.h"
#include <Undo/ScriptCanvasGraphCommand.h>
#include <ScriptCanvas/Components/EditorGraph.h>
namespace ScriptCanvasEditor
{
UndoHelper::UndoHelper(ScriptCanvasMemoryAsset& memoryAsset)
: m_memoryAsset(memoryAsset)
UndoHelper::UndoHelper()
: m_undoState(this)
{
UndoRequestBus::Handler::BusConnect(memoryAsset.GetScriptCanvasId());
}
UndoHelper::UndoHelper(Graph* graph)
: m_undoState(this)
{
SetSource(graph);
}
UndoHelper::~UndoHelper()
@@ -23,15 +29,21 @@ namespace ScriptCanvasEditor
UndoRequestBus::Handler::BusDisconnect();
}
void UndoHelper::SetSource(Graph* graph)
{
m_graph = graph;
UndoRequestBus::Handler::BusConnect(graph->GetScriptCanvasId());
}
ScriptCanvasEditor::UndoCache* UndoHelper::GetSceneUndoCache()
{
return m_memoryAsset.GetUndoState()->m_undoCache.get();
return m_undoState.m_undoCache.get();
}
ScriptCanvasEditor::UndoData UndoHelper::CreateUndoData()
{
AZ::EntityId graphCanvasGraphId = m_memoryAsset.GetGraphId();
ScriptCanvas::ScriptCanvasId scriptCanvasId = m_memoryAsset.GetScriptCanvasId();
AZ::EntityId graphCanvasGraphId = m_graph->GetGraphCanvasGraphId();
ScriptCanvas::ScriptCanvasId scriptCanvasId = m_graph->GetScriptCanvasId();
GraphCanvas::GraphModelRequestBus::Event(graphCanvasGraphId, &GraphCanvas::GraphModelRequests::OnSaveDataDirtied, graphCanvasGraphId);
@@ -56,17 +68,17 @@ namespace ScriptCanvasEditor
void UndoHelper::BeginUndoBatch(AZStd::string_view label)
{
m_memoryAsset.GetUndoState()->BeginUndoBatch(label);
m_undoState.BeginUndoBatch(label);
}
void UndoHelper::EndUndoBatch()
{
m_memoryAsset.GetUndoState()->EndUndoBatch();
m_undoState.EndUndoBatch();
}
void UndoHelper::AddUndo(AzToolsFramework::UndoSystem::URSequencePoint* sequencePoint)
{
if (SceneUndoState* sceneUndoState = m_memoryAsset.GetUndoState())
if (SceneUndoState* sceneUndoState = &m_undoState)
{
if (!sceneUndoState->m_currentUndoBatch)
{
@@ -82,22 +94,22 @@ namespace ScriptCanvasEditor
void UndoHelper::AddGraphItemChangeUndo(AZStd::string_view undoLabel)
{
GraphItemChangeCommand* command = aznew GraphItemChangeCommand(undoLabel);
command->Capture(m_memoryAsset, true);
command->Capture(m_memoryAsset, false);
command->Capture(m_graph, true);
command->Capture(m_graph, false);
AddUndo(command);
}
void UndoHelper::AddGraphItemAdditionUndo(AZStd::string_view undoLabel)
{
GraphItemAddCommand* command = aznew GraphItemAddCommand(undoLabel);
command->Capture(m_memoryAsset, false);
command->Capture(m_graph, false);
AddUndo(command);
}
void UndoHelper::AddGraphItemRemovalUndo(AZStd::string_view undoLabel)
{
GraphItemRemovalCommand* command = aznew GraphItemRemovalCommand(undoLabel);
command->Capture(m_memoryAsset, true);
command->Capture(m_graph, true);
AddUndo(command);
}
@@ -105,7 +117,7 @@ namespace ScriptCanvasEditor
{
AZ_PROFILE_FUNCTION(ScriptCanvas);
SceneUndoState* sceneUndoState = m_memoryAsset.GetUndoState();
SceneUndoState* sceneUndoState = &m_undoState;
if (sceneUndoState)
{
AZ_Warning("Script Canvas", !sceneUndoState->m_currentUndoBatch, "Script Canvas Editor has an open undo batch when performing a redo operation");
@@ -125,7 +137,7 @@ namespace ScriptCanvasEditor
{
AZ_PROFILE_FUNCTION(ScriptCanvas);
SceneUndoState* sceneUndoState = m_memoryAsset.GetUndoState();
SceneUndoState* sceneUndoState = &m_undoState;
if (sceneUndoState)
{
AZ_Warning("Script Canvas", !sceneUndoState->m_currentUndoBatch, "Script Canvas Editor has an open undo batch when performing a redo operation");
@@ -143,7 +155,7 @@ namespace ScriptCanvasEditor
void UndoHelper::Reset()
{
if (SceneUndoState* sceneUndoState = m_memoryAsset.GetUndoState())
if (SceneUndoState* sceneUndoState = &m_undoState)
{
AZ_Warning("Script Canvas", !sceneUndoState->m_currentUndoBatch, "Script Canvas Editor has an open undo batch when resetting the undo stack");
sceneUndoState->m_undoStack->Reset();
@@ -162,17 +174,23 @@ namespace ScriptCanvasEditor
bool UndoHelper::CanUndo() const
{
return m_memoryAsset.GetUndoState()->m_undoStack->CanUndo();
return m_undoState.m_undoStack->CanUndo();
}
bool UndoHelper::CanRedo() const
{
return m_memoryAsset.GetUndoState()->m_undoStack->CanRedo();
return m_undoState.m_undoStack->CanRedo();
}
void UndoHelper::OnUndoStackChanged()
{
UndoNotificationBus::Broadcast(&UndoNotifications::OnCanUndoChanged, m_undoState.m_undoStack->CanUndo());
UndoNotificationBus::Broadcast(&UndoNotifications::OnCanRedoChanged, m_undoState.m_undoStack->CanRedo());
}
void UndoHelper::UpdateCache()
{
ScriptCanvas::ScriptCanvasId scriptCanvasId = m_memoryAsset.GetScriptCanvasId();
ScriptCanvas::ScriptCanvasId scriptCanvasId = m_graph->GetScriptCanvasId();
UndoCache* undoCache = nullptr;
UndoRequestBus::EventResult(undoCache, scriptCanvasId, &UndoRequests::GetSceneUndoCache);
@@ -8,22 +8,27 @@
#pragma once
#include <ScriptCanvas/Bus/UndoBus.h>
#include <Editor/Undo/ScriptCanvasUndoManager.h>
namespace ScriptCanvasEditor
{
class ScriptCanvasMemoryAsset;
// Helper class that provides the implementation for UndoRequestBus
class UndoHelper : UndoRequestBus::Handler
class UndoHelper
: public UndoRequestBus::Handler
, public AzToolsFramework::UndoSystem::IUndoNotify
{
public:
UndoHelper(ScriptCanvasMemoryAsset& memoryAsset);
UndoHelper();
UndoHelper(Graph* source);
~UndoHelper();
UndoCache* GetSceneUndoCache() override;
UndoData CreateUndoData() override;
void SetSource(Graph* source);
void BeginUndoBatch(AZStd::string_view label) override;
void EndUndoBatch() override;
void AddUndo(AzToolsFramework::UndoSystem::URSequencePoint* seqPoint) override;
@@ -41,6 +46,7 @@ namespace ScriptCanvasEditor
bool CanRedo() const override;
private:
void OnUndoStackChanged() override;
void UpdateCache();
@@ -51,7 +57,7 @@ namespace ScriptCanvasEditor
};
Status m_status = Status::Idle;
ScriptCanvasMemoryAsset& m_memoryAsset;
SceneUndoState m_undoState;
Graph* m_graph = nullptr;
};
}
@@ -77,6 +77,7 @@ AZ_POP_DISABLE_WARNING
#include <Libraries/Core/EBusEventHandler.h>
#include <Libraries/Core/ReceiveScriptEvent.h>
#include <Libraries/Core/ScriptEventBase.h>
#include <ScriptCanvas/Assets/ScriptCanvasBaseAssetData.h>
#include <Libraries/Core/SendScriptEvent.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Core/Connection.h>
@@ -480,6 +481,7 @@ namespace ScriptCanvasEditor
ScriptCanvas::Graph::Activate();
PostActivate();
m_undoHelper.SetSource(this);
}
void Graph::Deactivate()
@@ -489,7 +491,7 @@ namespace ScriptCanvasEditor
EditorGraphRequestBus::Handler::BusDisconnect();
SceneCounterRequestBus::Handler::BusDisconnect();
NodeCreationNotificationBus::Handler::BusDisconnect();
AZ::SystemTickBus::Handler::BusDisconnect();
GraphCanvas::SceneNotificationBus::Handler::BusDisconnect();
GraphCanvas::GraphModelRequestBus::Handler::BusDisconnect();
@@ -1029,18 +1031,50 @@ namespace ScriptCanvasEditor
{
AZStd::any* connectionUserData = nullptr;
GraphCanvas::ConnectionRequestBus::EventResult(connectionUserData, connectionId, &GraphCanvas::ConnectionRequests::GetUserData);
auto scConnectionId = connectionUserData && connectionUserData->is<AZ::EntityId>() ? *AZStd::any_cast<AZ::EntityId>(connectionUserData) : AZ::EntityId();
auto scConnectionId = connectionUserData && connectionUserData->is<AZ::EntityId>()
? *AZStd::any_cast<AZ::EntityId>(connectionUserData)
: AZ::EntityId();
ScriptCanvas::Connection* connection = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Connection>(scConnectionId);
if (connection)
if (ScriptCanvas::Connection* connection = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Connection>(scConnectionId))
{
ScriptCanvas::GraphNotificationBus::Event(GetScriptCanvasId(), &ScriptCanvas::GraphNotifications::OnDisonnectionComplete, connectionId);
ScriptCanvas::GraphNotificationBus::Event
( GetScriptCanvasId()
, &ScriptCanvas::GraphNotifications::OnDisonnectionComplete
, connectionId);
DisconnectById(scConnectionId);
}
}
ScriptCanvas::DataPtr Graph::Create()
{
if (AZ::Entity* entity = aznew AZ::Entity("Script Canvas Graph"))
{
auto graph = entity->CreateComponent<ScriptCanvasEditor::Graph>();
entity->CreateComponent<EditorGraphVariableManagerComponent>(graph->GetScriptCanvasId());
if (ScriptCanvas::DataPtr data = aznew ScriptCanvas::ScriptCanvasData())
{
data->m_scriptCanvasEntity.reset(entity);
graph->MarkOwnership(*data);
entity->Init();
entity->Activate();
return data;
}
}
return nullptr;
}
void Graph::MarkOwnership(ScriptCanvas::ScriptCanvasData& owner)
{
m_owner = &owner;
}
ScriptCanvas::DataPtr Graph::GetOwnership() const
{
return 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())
@@ -1323,7 +1357,8 @@ namespace ScriptCanvasEditor
void Graph::SignalDirty()
{
GeneralRequestBus::Broadcast(&GeneralRequests::SignalSceneDirty, GetAssetId());
SourceHandle handle(m_owner, {}, {});
GeneralRequestBus::Broadcast(&GeneralRequests::SignalSceneDirty, handle);
}
void Graph::HighlightNodesByType(const ScriptCanvas::NodeTypeIdentifier& nodeTypeIdentifier)
@@ -3354,11 +3389,6 @@ namespace ScriptCanvasEditor
}
}
void Graph::SetAssetType(AZ::Data::AssetType assetType)
{
m_assetType = assetType;
}
void Graph::ReportError(const ScriptCanvas::Node& node, const AZStd::string& errorSource, const AZStd::string& errorMessage)
{
AzQtComponents::ToastConfiguration toastConfiguration(AzQtComponents::ToastType::Error, errorSource.c_str(), errorMessage.c_str());
@@ -3463,7 +3493,7 @@ namespace ScriptCanvasEditor
m_focusHelper.SetActiveGraph(GetGraphCanvasGraphId());
}
bool Graph::UpgradeGraph(const AZ::Data::Asset<AZ::Data::AssetData>& asset, UpgradeRequest request, bool isVerbose)
bool Graph::UpgradeGraph(SourceHandle& asset, UpgradeRequest request, bool isVerbose)
{
m_upgradeSM.SetAsset(asset);
m_upgradeSM.SetVerbose(isVerbose);
@@ -6,7 +6,6 @@
*
*/
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/NamedEntityId.h>
@@ -14,6 +13,7 @@
#include <AzCore/Script/ScriptSystemBus.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/IdUtils.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
#include <AzCore/Serialization/Utils.h>
#include <AzFramework/Asset/AssetSystemBus.h>
#include <AzFramework/StringFunc/StringFunc.h>
@@ -21,23 +21,27 @@
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <Core/ScriptCanvasBus.h>
#include <Editor/Assets/ScriptCanvasAssetTrackerBus.h>
#include <LyViewPaneNames.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
#include <ScriptCanvas/Components/EditorScriptCanvasComponent.h>
#include <ScriptCanvas/Components/EditorScriptCanvasComponentSerializer.h>
#include <ScriptCanvas/Components/EditorUtils.h>
#include <ScriptCanvas/Core/Node.h>
#include <ScriptCanvas/PerformanceStatisticsBus.h>
namespace EditorScriptCanvasComponentCpp
{
enum Version
{
PrefabIntegration = 10,
InternalDev,
AddSourceHandle,
// add description above
Current
};
@@ -128,7 +132,7 @@ namespace ScriptCanvasEditor
}
ScriptCanvasBuilder::BuildVariableOverrides overrides;
overrides.m_source = AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>(assetHolder.GetAssetId(), assetHolder.GetAssetType(), assetHolder.GetAssetHint());;
overrides.m_source = SourceHandle(nullptr, assetHolder.GetAssetId().m_guid, {});
for (auto& variable : editableData.GetVariables())
{
@@ -142,6 +146,25 @@ namespace ScriptCanvasEditor
}
}
if (rootElement.GetVersion() < EditorScriptCanvasComponentCpp::Version::AddSourceHandle)
{
ScriptCanvasAssetHolder assetHolder;
if (!rootElement.FindSubElementAndGetData(AZ_CRC_CE("m_assetHolder"), assetHolder))
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: could not retrieve old 'm_assetHolder'");
return false;
}
auto assetId = assetHolder.GetAssetId();
auto path = assetHolder.GetAssetHint();
if (!rootElement.AddElementWithData(serializeContext, "runtimeDataOverrides", SourceHandle(nullptr, assetId.m_guid, path)))
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: failed to add 'sourceHandle'");
return false;
}
}
return true;
}
@@ -153,9 +176,9 @@ namespace ScriptCanvasEditor
serializeContext->Class<EditorScriptCanvasComponent, EditorComponentBase>()
->Version(EditorScriptCanvasComponentCpp::Version::Current, &EditorScriptCanvasComponentVersionConverter)
->Field("m_name", &EditorScriptCanvasComponent::m_name)
->Field("m_assetHolder", &EditorScriptCanvasComponent::m_scriptCanvasAssetHolder)
->Field("runtimeDataIsValid", &EditorScriptCanvasComponent::m_runtimeDataIsValid)
->Field("runtimeDataOverrides", &EditorScriptCanvasComponent::m_variableOverrides)
->Field("sourceHandle", &EditorScriptCanvasComponent::m_sourceHandle)
;
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
@@ -171,29 +194,34 @@ namespace ScriptCanvasEditor
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("UI", 0x27ff46b0))
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Level", 0x9aeacc13))
->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/scripting/script-canvas/")
->DataElement(AZ::Edit::UIHandlers::Default, &EditorScriptCanvasComponent::m_scriptCanvasAssetHolder, "Script Canvas Asset", "Script Canvas asset associated with this component")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &EditorScriptCanvasComponent::m_sourceHandle, "Script Canvas Source File", "Script Canvas source file associated with this component")
->Attribute("BrowseIcon", ":/stylesheet/img/UI20/browse-edit-select-files.svg")
->Attribute("EditButton", "")
->Attribute("EditDescription", "Open in Script Canvas Editor")
->Attribute("EditCallback", &EditorScriptCanvasComponent::OpenEditor)
->Attribute(AZ::Edit::Attributes::AssetPickerTitle, "Script Canvas")
->Attribute(AZ::Edit::Attributes::SourceAssetFilterPattern, "*.scriptcanvas")
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorScriptCanvasComponent::OnFileSelectionChanged)
->DataElement(AZ::Edit::UIHandlers::Default, &EditorScriptCanvasComponent::m_variableOverrides, "Properties", "Script Canvas Graph Properties")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
;
}
}
if (AZ::JsonRegistrationContext* jsonContext = azrtti_cast<AZ::JsonRegistrationContext*>(context))
{
jsonContext->Serializer<AZ::EditorScriptCanvasComponentSerializer>()->HandlesType<EditorScriptCanvasComponent>();
}
}
EditorScriptCanvasComponent::EditorScriptCanvasComponent()
: EditorScriptCanvasComponent(AZ::Data::Asset<ScriptCanvasAsset>())
: EditorScriptCanvasComponent(SourceHandle())
{
}
EditorScriptCanvasComponent::EditorScriptCanvasComponent(AZ::Data::Asset<ScriptCanvasAsset> asset)
: m_scriptCanvasAssetHolder()
EditorScriptCanvasComponent::EditorScriptCanvasComponent(const SourceHandle& sourceHandle)
: m_sourceHandle(sourceHandle)
{
if (asset.GetId().IsValid())
{
m_scriptCanvasAssetHolder.SetAsset(asset.GetId());
}
m_scriptCanvasAssetHolder.SetScriptChangedCB([this](AZ::Data::AssetId assetId) { OnScriptCanvasAssetChanged(assetId); });
}
EditorScriptCanvasComponent::~EditorScriptCanvasComponent()
@@ -209,50 +237,34 @@ namespace ScriptCanvasEditor
void EditorScriptCanvasComponent::UpdateName()
{
AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId();
if (assetId.IsValid())
SetName(m_sourceHandle.Path().Filename().Native());
}
void EditorScriptCanvasComponent::OpenEditor(const AZ::Data::AssetId&, const AZ::Data::AssetType&)
{
AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas);
AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
if (m_sourceHandle.IsDescriptionValid())
{
// Pathname from the asset doesn't seem to return a value unless the asset has been loaded up once(which isn't done until we try to show it).
// Using the Job system to determine the asset name instead.
AZ::Outcome<AzToolsFramework::AssetSystem::JobInfoContainer> jobOutcome = AZ::Failure();
AzToolsFramework::AssetSystemJobRequestBus::BroadcastResult(jobOutcome, &AzToolsFramework::AssetSystemJobRequestBus::Events::GetAssetJobsInfoByAssetID, assetId, false, false);
AZStd::string assetPath;
AZStd::string assetName;
if (jobOutcome.IsSuccess())
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, m_sourceHandle, Tracker::ScriptCanvasFileState::UNMODIFIED, -1);
if (!openOutcome)
{
AzToolsFramework::AssetSystem::JobInfoContainer& jobs = jobOutcome.GetValue();
// Get the asset relative path
if (!jobs.empty())
{
assetPath = jobs[0].m_sourceFile;
}
// Get the asset file name
assetName = assetPath;
if (!assetPath.empty())
{
AzFramework::StringFunc::Path::GetFileName(assetPath.c_str(), assetName);
SetName(assetName);
}
AZ_Warning("Script Canvas", openOutcome, "%s", openOutcome.GetError().data());
}
}
}
void EditorScriptCanvasComponent::OpenEditor()
{
m_scriptCanvasAssetHolder.OpenEditor();
}
void EditorScriptCanvasComponent::CloseGraph()
{
AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId();
if (assetId.IsValid())
else if (GetEntityId().IsValid())
{
GeneralRequestBus::Broadcast(&GeneralRequests::CloseScriptCanvasAsset, assetId);
AzToolsFramework::EntityIdList selectedEntityIds;
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(selectedEntityIds, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities);
// Going to bypass the multiple selected entities flow for right now.
if (selectedEntityIds.size() == 1)
{
GeneralRequestBus::Broadcast(&GeneralRequests::CreateScriptCanvasAssetFor, AZStd::make_pair(GetEntityId(), GetId()));
}
}
}
@@ -261,7 +273,11 @@ namespace ScriptCanvasEditor
EditorComponentBase::Init();
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
m_scriptCanvasAssetHolder.Init(GetEntityId(), GetId());
}
void EditorScriptCanvasComponent::InitializeSource(const SourceHandle& sourceHandle)
{
m_sourceHandle = sourceHandle;
}
//=========================================================================
@@ -269,6 +285,8 @@ namespace ScriptCanvasEditor
{
EditorComponentBase::Activate();
AzToolsFramework::AssetSystemBus::Handler::BusConnect();
AZ::EntityId entityId = GetEntityId();
EditorContextMenuRequestBus::Handler::BusConnect(entityId);
@@ -277,19 +295,13 @@ namespace ScriptCanvasEditor
EditorScriptCanvasComponentLoggingBus::Handler::BusConnect(entityId);
EditorLoggingComponentNotificationBus::Broadcast(&EditorLoggingComponentNotifications::OnEditorScriptCanvasComponentActivated, GetNamedEntityId(), GetGraphIdentifier());
AZ::Data::AssetId fileAssetId = m_scriptCanvasAssetHolder.GetAssetId();
if (fileAssetId.IsValid())
{
AssetTrackerNotificationBus::Handler::BusConnect(fileAssetId);
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
}
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
}
//=========================================================================
void EditorScriptCanvasComponent::Deactivate()
{
AssetTrackerNotificationBus::Handler::BusDisconnect();
AzToolsFramework::AssetSystemBus::Handler::BusDisconnect();
EditorScriptCanvasComponentLoggingBus::Handler::BusDisconnect();
EditorLoggingComponentNotificationBus::Broadcast(&EditorLoggingComponentNotifications::OnEditorScriptCanvasComponentDeactivated, GetNamedEntityId(), GetGraphIdentifier());
@@ -306,7 +318,7 @@ namespace ScriptCanvasEditor
m_runtimeDataIsValid = false;
auto assetTreeOutcome = LoadEditorAssetTree(m_scriptCanvasAssetHolder.GetAssetId(), m_scriptCanvasAssetHolder.GetAssetHint());
auto assetTreeOutcome = LoadEditorAssetTree(m_sourceHandle);
if (!assetTreeOutcome.IsSuccess())
{
AZ_Warning("ScriptCanvas", false, "EditorScriptCanvasComponent::BuildGameEntityData failed: %s", assetTreeOutcome.GetError().c_str());
@@ -344,7 +356,8 @@ namespace ScriptCanvasEditor
if (!m_runtimeDataIsValid)
{
AZ_Error("ScriptCanvasBuilder", false, "Runtime information did not build for ScriptCanvas Component using asset: %s", m_scriptCanvasAssetHolder.GetAssetId().ToString<AZStd::string>().c_str());
AZ_Error("ScriptCanvasBuilder", false, "Runtime information did not build for ScriptCanvas Component using asset: %s"
, m_sourceHandle.ToString().c_str());
return;
}
@@ -352,123 +365,66 @@ namespace ScriptCanvasEditor
runtimeComponent->TakeRuntimeDataOverrides(ConvertToRuntime(m_variableOverrides));
}
void EditorScriptCanvasComponent::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId)
{
if (m_removedCatalogId == assetId)
{
if (!m_scriptCanvasAssetHolder.GetAssetId().IsValid())
{
SetPrimaryAsset(assetId);
m_removedCatalogId.SetInvalid();
}
}
}
void EditorScriptCanvasComponent::OnCatalogAssetRemoved(const AZ::Data::AssetId& removedAssetId, const AZ::Data::AssetInfo& /*assetInfo*/)
{
AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId();
if (assetId == removedAssetId)
{
m_removedCatalogId = assetId;
SetPrimaryAsset({});
}
}
void EditorScriptCanvasComponent::SetPrimaryAsset(const AZ::Data::AssetId& assetId)
{
m_scriptCanvasAssetHolder.ClearAsset();
m_sourceHandle = SourceHandle(nullptr, assetId.m_guid, {});
if (assetId.IsValid())
auto completeAsset = CompleteDescription(m_sourceHandle);
if (completeAsset)
{
ScriptCanvasMemoryAsset::pointer memoryAsset;
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, assetId);
if (memoryAsset)
{
m_scriptCanvasAssetHolder.SetAsset(memoryAsset->GetFileAssetId());
OnScriptCanvasAssetChanged(memoryAsset->GetFileAssetId());
SetName(memoryAsset->GetTabName());
}
else
{
auto scriptCanvasAsset = AZ::Data::AssetManager::Instance().FindAsset(assetId, AZ::Data::AssetLoadBehavior::Default);
if (scriptCanvasAsset)
{
m_scriptCanvasAssetHolder.SetAsset(assetId);
}
}
m_sourceHandle = *completeAsset;
}
OnScriptCanvasAssetChanged(SourceChangeDescription::SelectionChanged);
SetName(m_sourceHandle.Path().Filename().Native());
AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues);
}
AZ::Data::AssetId EditorScriptCanvasComponent::GetAssetId() const
{
return m_scriptCanvasAssetHolder.GetAssetId();
return m_sourceHandle.Id();
}
AZ::EntityId EditorScriptCanvasComponent::GetGraphEntityId() const
AZ::u32 EditorScriptCanvasComponent::OnFileSelectionChanged()
{
AZ::EntityId scriptCanvasEntityId;
AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId();
if (assetId.IsValid())
{
AssetTrackerRequestBus::BroadcastResult(scriptCanvasEntityId, &AssetTrackerRequests::GetScriptCanvasId, assetId);
}
return scriptCanvasEntityId;
m_sourceHandle = SourceHandle(nullptr, m_sourceHandle.Path());
CompleteDescriptionInPlace(m_sourceHandle);
m_previousHandle = {};
m_removedHandle = {};
OnScriptCanvasAssetChanged(SourceChangeDescription::SelectionChanged);
return AZ::Edit::PropertyRefreshLevels::EntireTree;
}
void EditorScriptCanvasComponent::OnAssetReady(const ScriptCanvasMemoryAsset::pointer asset)
void EditorScriptCanvasComponent::OnScriptCanvasAssetChanged(SourceChangeDescription changeDescription)
{
OnScriptCanvasAssetReady(asset);
}
void EditorScriptCanvasComponent::OnAssetSaved(const ScriptCanvasMemoryAsset::pointer asset, bool isSuccessful)
{
if (isSuccessful)
{
OnScriptCanvasAssetReady(asset);
}
}
void EditorScriptCanvasComponent::OnAssetReloaded(const ScriptCanvasMemoryAsset::pointer asset)
{
OnScriptCanvasAssetReady(asset);
}
void EditorScriptCanvasComponent::OnScriptCanvasAssetChanged(AZ::Data::AssetId assetId)
{
AssetTrackerNotificationBus::Handler::BusDisconnect();
ScriptCanvas::GraphIdentifier newIdentifier = GetGraphIdentifier();
newIdentifier.m_assetId = assetId;
newIdentifier.m_assetId = m_sourceHandle.Id();
ScriptCanvas::GraphIdentifier oldIdentifier = GetGraphIdentifier();
oldIdentifier.m_assetId = m_previousAssetId;
oldIdentifier.m_assetId = m_previousHandle.Id();
EditorLoggingComponentNotificationBus::Broadcast(&EditorLoggingComponentNotifications::OnAssetSwitched, GetNamedEntityId(), newIdentifier, oldIdentifier);
m_previousAssetId = m_scriptCanvasAssetHolder.GetAssetId();
m_previousHandle = m_sourceHandle.Describe();
// Only clear our variables when we are given a new asset id
// or when the asset was explicitly set to empty.
//
// i.e. do not clear variables when we lose the catalog asset.
if ((assetId.IsValid() && assetId != m_removedCatalogId)
|| (!assetId.IsValid() && !m_removedCatalogId.IsValid()))
if (changeDescription == SourceChangeDescription::SelectionChanged)
{
ClearVariables();
}
if (assetId.IsValid())
if (m_sourceHandle.IsDescriptionValid())
{
AssetTrackerNotificationBus::Handler::BusConnect(assetId);
ScriptCanvasMemoryAsset::pointer memoryAsset;
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, assetId);
if (memoryAsset && memoryAsset->GetAsset().GetStatus() == AZ::Data::AssetData::AssetStatus::Ready)
if (!m_sourceHandle.Get())
{
OnScriptCanvasAssetReady(memoryAsset);
if (auto loaded = LoadFromFile(m_sourceHandle.Path().c_str()); loaded.IsSuccess())
{
m_sourceHandle = SourceHandle(loaded.TakeValue(), m_sourceHandle.Id(), m_sourceHandle.Path().c_str());
}
}
if (m_sourceHandle.Get())
{
UpdatePropertyDisplay(m_sourceHandle);
}
}
@@ -485,35 +441,66 @@ namespace ScriptCanvasEditor
AZ::ScriptSystemRequestBus::Broadcast(&AZ::ScriptSystemRequests::GarbageCollect);
}
void EditorScriptCanvasComponent::SetAssetId(const AZ::Data::AssetId& assetId)
void EditorScriptCanvasComponent::SetAssetId(const SourceHandle& assetId)
{
if (m_scriptCanvasAssetHolder.GetAssetId() != assetId)
if (m_sourceHandle.Describe() != assetId.Describe())
{
// Invalidate the previously removed catalog id if we are setting a new asset id
m_removedCatalogId.SetInvalid();
SetPrimaryAsset(assetId);
m_removedHandle = {};
SetPrimaryAsset(assetId.Id());
}
}
void EditorScriptCanvasComponent::SourceFileChanged([[maybe_unused]] AZStd::string relativePath
, [[maybe_unused]] AZStd::string scanFolder, [[maybe_unused]] AZ::Uuid fileAssetId)
{
if (fileAssetId == m_sourceHandle.Id())
{
if (auto handle = CompleteDescription(SourceHandle(nullptr, fileAssetId, {})))
{
m_sourceHandle = *handle;
// consider queueing on tick bus
OnScriptCanvasAssetChanged(SourceChangeDescription::Modified);
}
}
}
void EditorScriptCanvasComponent::SourceFileRemoved([[maybe_unused]] AZStd::string relativePath
, [[maybe_unused]] AZStd::string scanFolder, [[maybe_unused]] AZ::Uuid fileAssetId)
{
if (fileAssetId == m_sourceHandle.Id())
{
m_removedHandle = m_sourceHandle;
OnScriptCanvasAssetChanged(SourceChangeDescription::Removed);
}
}
void EditorScriptCanvasComponent::SourceFileFailed([[maybe_unused]] AZStd::string relativePath
, [[maybe_unused]] AZStd::string scanFolder, [[maybe_unused]] AZ::Uuid fileAssetId)
{
if (fileAssetId == m_sourceHandle.Id())
{
m_removedHandle = m_sourceHandle;
OnScriptCanvasAssetChanged(SourceChangeDescription::Error);
}
}
bool EditorScriptCanvasComponent::HasAssetId() const
{
return m_scriptCanvasAssetHolder.GetAssetId().IsValid();
return !m_sourceHandle.Id().IsNull();
}
ScriptCanvas::GraphIdentifier EditorScriptCanvasComponent::GetGraphIdentifier() const
{
// For now we don't want to deal with disambiguating duplicates of the same script running on one entity.
// Should that change we need to add the component id back into this.
return ScriptCanvas::GraphIdentifier(m_scriptCanvasAssetHolder.GetAssetId(), 0);
return ScriptCanvas::GraphIdentifier(m_sourceHandle.Id(), 0);
}
void EditorScriptCanvasComponent::OnScriptCanvasAssetReady(const ScriptCanvasMemoryAsset::pointer memoryAsset)
void EditorScriptCanvasComponent::UpdatePropertyDisplay(const SourceHandle& sourceHandle)
{
if (memoryAsset->GetFileAssetId() == m_scriptCanvasAssetHolder.GetAssetId())
if (sourceHandle.IsGraphValid())
{
auto assetData = memoryAsset->GetAsset();
[[maybe_unused]] AZ::Entity* scriptCanvasEntity = assetData->GetScriptCanvasEntity();
AZ_Assert(scriptCanvasEntity, "This graph must have a valid entity");
BuildGameEntityData();
UpdateName();
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
@@ -17,6 +17,7 @@ AZ_POP_DISABLE_WARNING
#include <ScriptCanvas/Libraries/Core/EBusEventHandler.h>
#include <ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h>
#include <ScriptCanvas/Utils/NodeUtils.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include <Editor/Include/ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
@@ -30,6 +31,62 @@ AZ_POP_DISABLE_WARNING
namespace ScriptCanvasEditor
{
AZStd::optional<SourceHandle> CompleteDescription(const SourceHandle& source)
{
if (source.IsDescriptionValid())
{
return source;
}
AzToolsFramework::AssetSystemRequestBus::Events* assetSystem = AzToolsFramework::AssetSystemRequestBus::FindFirstHandler();
if (assetSystem)
{
AZStd::string watchFolder;
AZ::Data::AssetInfo assetInfo;
if (!source.Id().IsNull())
{
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 (assetSystem->GetSourceInfoBySourcePath(fullPathHandle.Path().c_str(), assetInfo, watchFolder) && assetInfo.m_assetId.IsValid())
{
AZ_Warning("ScriptCanvas", assetInfo.m_assetId.m_guid == source.Id(), "SourceHandle completion produced conflicting AssetId.");
auto path = fullPathHandle.Path();
return SourceHandle(source, assetInfo.m_assetId.m_guid, path.MakePreferred());
}
}
}
if (!source.Path().empty())
{
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;
}
bool CompleteDescriptionInPlace(SourceHandle& source)
{
if (auto completed = CompleteDescription(source))
{
source = *completed;
return true;
}
else
{
return false;
}
}
//////////////////////////
// NodeIdentifierFactory
//////////////////////////
@@ -438,10 +438,11 @@ namespace ScriptCanvasEditor
if (nodeConfig.IsValid())
{
ScriptCanvas::NodeUpdateSlotReport nodeUpdateSlotReport;
auto nodeEntity = node->GetEntityId();
auto nodeOutcome = graph->ReplaceNodeByConfig(node, nodeConfig, nodeUpdateSlotReport);
if (nodeOutcome.IsSuccess())
{
ScriptCanvas::MergeUpdateSlotReport(node->GetEntityId(), sm->m_updateReport, nodeUpdateSlotReport);
ScriptCanvas::MergeUpdateSlotReport(nodeEntity, sm->m_updateReport, nodeUpdateSlotReport);
sm->m_allNodes.erase(node);
sm->m_outOfDateNodes.erase(node);
@@ -675,20 +676,20 @@ namespace ScriptCanvasEditor
RegisterState(ParseGraph);
}
void EditorGraphUpgradeMachine::SetAsset(const AZ::Data::Asset<AZ::Data::AssetData>& asset)
void EditorGraphUpgradeMachine::SetAsset(SourceHandle& asset)
{
if (m_asset != asset)
{
m_asset = asset;
SetDebugPrefix(asset.GetHint());
SetDebugPrefix(asset.Path().c_str());
}
}
void EditorGraphUpgradeMachine::OnComplete(IState::ExitStatus exitStatus)
{
UpgradeNotificationsBus::Broadcast(&UpgradeNotifications::OnGraphUpgradeComplete, m_asset, exitStatus == IState::ExitStatus::Skipped);
m_asset = {};
// releasing the asset at this stage of the system tick causes a memory crash
// m_asset = {};
}
//////////////////////////////////////////////////////////////////////
@@ -11,6 +11,7 @@
#include <AzCore/Script/ScriptSystemBus.h>
#include <Editor/Framework/ScriptCanvasTraceUtilities.h>
#include <Editor/Framework/ScriptCanvasReporter.h>
#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
namespace ScriptCanvas
{
@@ -75,7 +75,7 @@ namespace ScriptCanvasEditor
AZ_Assert(loadResult.m_runtimeAsset, "failed to load dependent asset");
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> luaAssetOutcome = AZ::Failure(AZStd::string("lua asset creation for function failed"));
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(luaAssetOutcome, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateLuaAsset, loadResult.m_editorAsset, loadResult.m_graphPath);
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(luaAssetOutcome, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateLuaAsset, loadResult.m_editorAsset, loadResult.m_editorAsset.Path().c_str());
AZ_Assert(luaAssetOutcome.IsSuccess(), "failed to create Lua asset");
AZStd::string modulePath = namespacePath[0].data();
@@ -112,18 +112,19 @@ namespace ScriptCanvasEditor
AZ_INLINE LoadTestGraphResult LoadTestGraph(AZStd::string_view graphPath)
{
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> editorAsset;
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(editorAsset, &ScriptCanvasEditor::EditorAssetConversionBusTraits::LoadAsset, graphPath);
if (editorAsset.GetData())
if (auto loadFileOutcome = LoadFromFile(graphPath); loadFileOutcome.IsSuccess())
{
AZ::Outcome< AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> assetOutcome = AZ::Failure(AZStd::string("asset creation failed"));
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(assetOutcome, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateRuntimeAsset, editorAsset);
auto& source = loadFileOutcome.GetValue();
auto testableSource = SourceHandle(source, AZ::Uuid::CreateRandom(), source.Path().c_str());
AZ::Outcome<AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> assetOutcome(AZ::Failure(AZStd::string("asset create failed")));
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(assetOutcome
, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateRuntimeAsset, testableSource);
if (assetOutcome.IsSuccess())
{
LoadTestGraphResult result;
result.m_graphPath = graphPath;
result.m_editorAsset = editorAsset;
result.m_editorAsset = AZStd::move(testableSource);
result.m_runtimeAsset = assetOutcome.GetValue();
result.m_entity = AZStd::make_unique<AZ::Entity>("Loaded Graph");
return result;
@@ -164,8 +165,7 @@ namespace ScriptCanvasEditor
reporter.SetExecutionMode(mode);
LoadTestGraphResult loadResult;
loadResult.m_graphPath = asset.GetHint().c_str();
loadResult.m_editorAsset = asset;
loadResult.m_editorAsset = SourceHandle(nullptr, assetId.m_guid, asset.GetHint());
AZ::EntityId scriptCanvasId;
loadResult.m_entity = AZStd::make_unique<AZ::Entity>("Loaded test graph");
loadResult.m_runtimeAsset = runtimeAsset;
@@ -206,7 +206,8 @@ namespace ScriptCanvasEditor
{
ScopedOutputSuppression outputSuppressor;
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> luaAssetOutcome = AZ::Failure(AZStd::string("lua asset creation failed"));
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(luaAssetOutcome, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateLuaAsset, loadResult.m_editorAsset, loadResult.m_graphPath);
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(luaAssetOutcome
, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateLuaAsset, loadResult.m_editorAsset, loadResult.m_editorAsset.Path().c_str());
reporter.MarkParseAttemptMade();
if (luaAssetOutcome.IsSuccess())
@@ -220,6 +221,8 @@ namespace ScriptCanvasEditor
{
RuntimeDataOverrides runtimeDataOverrides;
runtimeDataOverrides.m_runtimeAsset = loadResult.m_runtimeAsset;
runtimeDataOverrides.m_runtimeAsset.SetHint("original");
runtimeDataOverrides.m_runtimeAsset.Get()->m_runtimeData.m_script.SetHint("original");
#if defined(LINUX) //////////////////////////////////////////////////////////////////////////
// Temporarily disable testing on the Linux build until the file name casing discrepancy
@@ -265,6 +268,10 @@ namespace ScriptCanvasEditor
RuntimeDataOverrides dependencyRuntimeDataOverrides;
dependencyRuntimeDataOverrides.m_runtimeAsset = dependency.runtimeAsset;
AZStd::string dependencyHint = AZStd::string::format("dependency_%d", index);
dependencyRuntimeDataOverrides.m_runtimeAsset.SetHint(dependencyHint);
dependencyRuntimeDataOverrides.m_runtimeAsset.Get()->m_runtimeData.m_script.SetHint(dependencyHint);
runtimeDataOverrides.m_dependencies.push_back(dependencyRuntimeDataOverrides);
RuntimeData& dependencyData = dependencyDataBuffer[index];
@@ -27,6 +27,7 @@
#include <ScriptCanvas/Libraries/Logic/Logic.h>
#include <ScriptCanvas/Libraries/Math/Math.h>
#include <ScriptCanvas/Variable/VariableBus.h>
#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
namespace AZ
{
@@ -45,11 +46,10 @@ namespace ScriptCanvasEditor
struct LoadTestGraphResult
{
AZStd::string_view m_graphPath;
AZStd::unique_ptr<AZ::Entity> m_entity;
ScriptCanvas::RuntimeComponent* m_runtimeComponent = nullptr;
bool m_nativeFunctionFound = false;
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> m_editorAsset;
SourceHandle m_editorAsset;
AZ::Data::Asset<ScriptCanvas::RuntimeAsset> m_runtimeAsset;
AZ::Data::Asset<AZ::ScriptAsset> m_scriptAsset;
};
@@ -161,7 +161,7 @@ namespace ScriptCanvasEditor
struct ScopedOutputSuppression
{
ScopedOutputSuppression(bool suppressState = true)
ScopedOutputSuppression([[maybe_unused]] bool suppressState = true)
{
AZ::Debug::TraceMessageBus::BroadcastResult(m_oldSuppression, &AZ::Debug::TraceMessageEvents::OnOutput, "", "");
TraceSuppressionBus::Broadcast(&TraceSuppressionRequests::SuppressAllOutput, suppressState);
@@ -97,7 +97,8 @@ namespace ScriptCanvasEditor
}
AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, assetInfo.m_assetId, -1);
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset
, SourceHandle( nullptr, assetInfo.m_assetId.m_guid, {} ), Tracker::ScriptCanvasFileState::UNMODIFIED, -1);
return openOutcome.IsSuccess();
}
@@ -20,11 +20,6 @@ namespace AZ
namespace ScriptCanvasEditor
{
AZ::Outcome<void, AZStd::string> LoadScriptCanvasDataFromJson
( ScriptCanvas::ScriptCanvasData& dataTarget
, AZStd::string_view source
, AZ::SerializeContext& serializeContext);
/**
* Manages editor Script Canvas graph assets.
*/
@@ -7,17 +7,4 @@
*/
#include <ScriptCanvas/Assets/ScriptCanvasBaseAssetData.h>
#include <ScriptCanvas/Components/EditorGraph.h>
namespace ScriptCanvas
{
Graph* ScriptCanvasData::ModGraph()
{
return AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Graph>(m_scriptCanvasEntity.get());
}
const Graph* ScriptCanvasData::GetGraph() const
{
return AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Graph>(m_scriptCanvasEntity.get());
}
}
@@ -13,27 +13,5 @@
namespace ScriptCanvas
{
class ScriptCanvasData
{
public:
AZ_RTTI(ScriptCanvasData, "{1072E894-0C67-4091-8B64-F7DB324AD13C}");
AZ_CLASS_ALLOCATOR(ScriptCanvasData, AZ::SystemAllocator, 0);
ScriptCanvasData() {}
virtual ~ScriptCanvasData() {}
ScriptCanvasData(ScriptCanvasData&& other);
ScriptCanvasData& operator=(ScriptCanvasData&& other);
static void Reflect(AZ::ReflectContext* reflectContext);
AZ::Entity* GetScriptCanvasEntity() const { return m_scriptCanvasEntity.get(); }
Graph* ModGraph();
const Graph* GetGraph() const;
AZStd::unique_ptr<AZ::Entity> m_scriptCanvasEntity;
private:
ScriptCanvasData(const ScriptCanvasData&) = delete;
};
}
@@ -0,0 +1,54 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/Asset/AssetTypeInfoBus.h>
#include <AzCore/Serialization/ObjectStream.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
namespace AZ
{
class SerializeContext;
}
namespace ScriptCanvas
{
class ScriptCanvasData;
}
namespace ScriptCanvasEditor
{
class EditorAssetTree
{
public:
AZ_CLASS_ALLOCATOR(EditorAssetTree, AZ::SystemAllocator, 0);
EditorAssetTree* m_parent = nullptr;
AZStd::vector<EditorAssetTree> m_dependencies;
SourceHandle m_asset;
EditorAssetTree* ModRoot();
void SetParent(EditorAssetTree& parent);
AZStd::string ToString(size_t depth = 0) const;
};
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<EditorAssetTree, AZStd::string> LoadEditorAssetTree(SourceHandle handle, EditorAssetTree* parent = nullptr);
AZ::Outcome<void, AZStd::string> SaveToStream(const SourceHandle& source, AZ::IO::GenericStream& stream);
}
@@ -26,6 +26,8 @@
#include <ScriptCanvas/Variable/VariableCore.h>
#include <AzCore/Interface/Interface.h>
#include <ScriptCanvas/Core/Core.h>
namespace GraphCanvas
{
class GraphCanvasTreeItem;
@@ -70,7 +72,7 @@ namespace ScriptCanvasEditor
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = AZ::EntityId;
virtual void SetAssetId(const AZ::Data::AssetId& assetId) = 0;
virtual void SetAssetId(const SourceHandle& assetId) = 0;
virtual bool HasAssetId() const = 0;
};
@@ -89,40 +91,13 @@ namespace ScriptCanvasEditor
};
using EditorContextMenuRequestBus = AZ::EBus<EditorContextMenuRequests>;
class EditorScriptCanvasAssetNotifications : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = AZ::Data::AssetId;
//! Notification which fires after an EditorGraph has received it's on AssetReady callback
//! \param scriptCanvasAsset Script Canvas asset which is now ready for use in the Editor
virtual void OnScriptCanvasAssetReady(const AZ::Data::Asset<ScriptCanvas::ScriptCanvasAssetBase>& /*scriptCanvasAsset*/) {};
//! Notification which fires after an EditorGraph has received it's on AssetReloaded callback
//! \param scriptCanvasAsset Script Canvas asset which is now ready for use in the Editor
virtual void OnScriptCanvasAssetReloaded(const AZ::Data::Asset<ScriptCanvas::ScriptCanvasAssetBase>& /*scriptCanvaAsset */) {};
//! Notification which fires after an EditorGraph has received it's on AssetReady callback
//! \param AssetId AssetId of unloaded ScriptCanvas
virtual void OnScriptCanvasAssetUnloaded(const AZ::Data::AssetId& /*assetId*/) {};
//! Notification which fires after an EditorGraph has received an onAssetSaved callback
//! \param scriptCanvasAsset Script Canvas asset which was attempted to be saved
//! \param isSuccessful specified where the Script Canvas asset was successfully saved
virtual void OnScriptCanvasAssetSaved(const AZ::Data::AssetId) {};
};
using EditorScriptCanvasAssetNotificationBus = AZ::EBus<EditorScriptCanvasAssetNotifications>;
class EditorGraphRequests : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = ScriptCanvas::ScriptCanvasId;
virtual void SetAssetId(const AZ::Data::AssetId& assetId) = 0;
virtual void CreateGraphCanvasScene() = 0;
virtual void ClearGraphCanvasScene() = 0;
virtual GraphCanvas::GraphId GetGraphCanvasGraphId() const = 0;
@@ -225,7 +200,7 @@ namespace ScriptCanvasEditor
virtual void OnUpgradeStart() {}
virtual void OnUpgradeCancelled() {}
virtual void OnGraphUpgradeComplete(AZ::Data::Asset<AZ::Data::AssetData>&, bool skipped = false) { (void)skipped; }
virtual void OnGraphUpgradeComplete(SourceHandle&, bool skipped = false) { (void)skipped; }
};
using UpgradeNotificationsBus = AZ::EBus<UpgradeNotifications>;
@@ -8,18 +8,16 @@
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzCore/Component/EntityId.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Outcome/Outcome.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Component/EntityId.h>
#include <AzCore/EBus/EBus.h>
#include <AzCore/Math/Vector2.h>
#include <AzCore/Outcome/Outcome.h>
#include <GraphCanvas/Types/Types.h>
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
#include <ScriptCanvas/Bus/NodeIdPair.h>
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
#include <ScriptCanvas/Core/Core.h>
#include <ScriptCanvas/Data/Data.h>
class QLineEdit;
@@ -49,6 +47,17 @@ namespace ScriptCanvasEditor
struct CategoryInformation;
struct NodePaletteModelInformation;
namespace Tracker
{
enum class ScriptCanvasFileState : AZ::s32
{
NEW,
MODIFIED,
UNMODIFIED,
SOURCE_REMOVED,
INVALID = -1
};
}
namespace Widget
{
@@ -70,16 +79,16 @@ 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(AZ::Data::AssetId scriptCanvasAssetId, int tabIndex = -1) = 0;
virtual AZ::Outcome<int, AZStd::string> OpenScriptCanvasAssetId(const AZ::Data::AssetId& 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 AZ::Data::AssetId&) = 0;
virtual int CloseScriptCanvasAsset(const SourceHandle&) = 0;
virtual bool CreateScriptCanvasAssetFor(const TypeDefs::EntityComponentId& requestingComponent) = 0;
virtual bool IsScriptCanvasAssetOpen(const AZ::Data::AssetId& assetId) const = 0;
virtual bool IsScriptCanvasAssetOpen(const SourceHandle& assetId) const = 0;
virtual void OnChangeActiveGraphTab(AZ::Data::AssetId) {}
virtual void OnChangeActiveGraphTab(SourceHandle) {}
virtual void CreateNewRuntimeAsset() = 0;
@@ -103,12 +112,12 @@ namespace ScriptCanvasEditor
return ScriptCanvas::ScriptCanvasId();
}
virtual GraphCanvas::GraphId FindGraphCanvasGraphIdByAssetId([[maybe_unused]] const AZ::Data::AssetId& assetId) const
virtual GraphCanvas::GraphId FindGraphCanvasGraphIdByAssetId([[maybe_unused]] const SourceHandle& assetId) const
{
return GraphCanvas::GraphId();
}
virtual ScriptCanvas::ScriptCanvasId FindScriptCanvasIdByAssetId([[maybe_unused]] const AZ::Data::AssetId& assetId) const
virtual ScriptCanvas::ScriptCanvasId FindScriptCanvasIdByAssetId([[maybe_unused]] const SourceHandle& assetId) const
{
return ScriptCanvas::ScriptCanvasId();
}
@@ -126,7 +135,7 @@ namespace ScriptCanvasEditor
virtual void DisconnectEndpoints(const AZ::EntityId& /*sceneId*/, const AZStd::vector<GraphCanvas::Endpoint>& /*endpoints*/) {}
virtual void PostUndoPoint(ScriptCanvas::ScriptCanvasId) = 0;
virtual void SignalSceneDirty(AZ::Data::AssetId) = 0;
virtual void SignalSceneDirty(SourceHandle) = 0;
// Increment the value of the ignore undo point tracker
virtual void PushPreventUndoStateUpdate() = 0;
@@ -165,7 +174,7 @@ namespace ScriptCanvasEditor
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = AZ::Data::AssetId;
using BusIdType = SourceHandle;
virtual void OnAssetVisualized() {};
virtual void OnAssetUnloaded() {};
@@ -34,6 +34,7 @@
#include <GraphCanvas/Widgets/NodePropertyBus.h>
#include <Editor/Include/ScriptCanvas/Components/GraphUpgrade.h>
#include <Editor/Assets/ScriptCanvasUndoHelper.h>
namespace ScriptCanvas
{
@@ -101,6 +102,8 @@ namespace ScriptCanvasEditor
public:
AZ_COMPONENT(Graph, "{4D755CA9-AB92-462C-B24F-0B3376F19967}", ScriptCanvas::Graph);
static ScriptCanvas::DataPtr Create();
static void Reflect(AZ::ReflectContext* context);
Graph(const ScriptCanvas::ScriptCanvasId& scriptCanvasId = AZ::Entity::MakeId())
@@ -138,10 +141,6 @@ namespace ScriptCanvasEditor
void ReleaseVariableCounter(AZ::u32 variableCounter) override;
////
// RuntimeBus
AZ::Data::AssetId GetAssetId() const override { return m_assetId; }
////
// GraphCanvas::GraphModelRequestBus
void RequestUndoPoint() override;
@@ -221,9 +220,6 @@ namespace ScriptCanvasEditor
void OnGraphCanvasNodeCreated(const AZ::EntityId& nodeId) override;
///////////////////////////
// EditorGraphRequestBus
void SetAssetId(const AZ::Data::AssetId& assetId) override { m_assetId = assetId; }
void CreateGraphCanvasScene() override;
void ClearGraphCanvasScene() override;
void DisplayGraphCanvasScene() override;
@@ -235,7 +231,7 @@ namespace ScriptCanvasEditor
IfOutOfDate,
Forced
};
bool UpgradeGraph(const AZ::Data::Asset<AZ::Data::AssetData>& asset, UpgradeRequest request, bool isVerbose = true);
bool UpgradeGraph(SourceHandle& asset, UpgradeRequest request, bool isVerbose = true);
void ConnectGraphCanvasBuses();
void DisconnectGraphCanvasBuses();
///////
@@ -302,12 +298,13 @@ namespace ScriptCanvasEditor
void OnUndoRedoEnd() override;
////
void SetAssetType(AZ::Data::AssetType);
void ReportError(const ScriptCanvas::Node& node, const AZStd::string& errorSource, const AZStd::string& errorMessage) override;
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>
AZStd::vector<const NodeType*> GetNodesOfType() const
@@ -384,12 +381,15 @@ namespace ScriptCanvasEditor
GraphCanvas::NodeFocusCyclingHelper m_focusHelper;
GraphStatisticsHelper m_statisticsHelper;
UndoHelper m_undoHelper;
bool m_ignoreSaveRequests;
//! Defaults to true to signal that this graph does not have the GraphCanvas stuff intermingled
bool m_saveFormatConverted = true;
AZ::Data::AssetId m_assetId;
ScriptCanvasEditor::SourceHandle m_assetId;
// temporary step in cleaning up the graph / asset class structure. This reference is deliberately weak.
ScriptCanvas::ScriptCanvasData* m_owner;
};
}
@@ -17,6 +17,7 @@
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <ScriptCanvas/Execution/RuntimeComponent.h>
#include <ScriptCanvas/Variable/VariableBus.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
namespace ScriptCanvasEditor
{
@@ -34,9 +35,9 @@ namespace ScriptCanvasEditor
: public AzToolsFramework::Components::EditorComponentBase
, private EditorContextMenuRequestBus::Handler
, private AzFramework::AssetCatalogEventBus::Handler
, private AzToolsFramework::AssetSystemBus::Handler
, private EditorScriptCanvasComponentLoggingBus::Handler
, private EditorScriptCanvasComponentRequestBus::Handler
, private AssetTrackerNotificationBus::Handler
, private AzToolsFramework::EditorEntityContextNotificationBus::Handler
{
@@ -44,9 +45,12 @@ namespace ScriptCanvasEditor
AZ_COMPONENT(EditorScriptCanvasComponent, "{C28E2D29-0746-451D-A639-7F113ECF5D72}", AzToolsFramework::Components::EditorComponentBase);
EditorScriptCanvasComponent();
EditorScriptCanvasComponent(AZ::Data::Asset<ScriptCanvasAsset> asset);
EditorScriptCanvasComponent(const SourceHandle& sourceHandle);
~EditorScriptCanvasComponent() override;
// sets the soure but does not attempt to load anything;
void InitializeSource(const SourceHandle& sourceHandle);
//=====================================================================
// AZ::Component
void Init() override;
@@ -66,17 +70,16 @@ namespace ScriptCanvasEditor
ScriptCanvas::GraphIdentifier GetGraphIdentifier() const override;
//=====================================================================
void OpenEditor();
void CloseGraph();
void SetName(const AZStd::string& name) { m_name = name; }
void OpenEditor(const AZ::Data::AssetId&, const AZ::Data::AssetType&);
void SetName(AZStd::string_view name) { m_name = name; }
const AZStd::string& GetName() const;
AZ::EntityId GetEditorEntityId() const { return GetEntity() ? GetEntityId() : AZ::EntityId(); }
AZ::NamedEntityId GetNamedEditorEntityId() const { return GetEntity() ? GetNamedEntityId() : AZ::NamedEntityId(); }
//=====================================================================
// EditorScriptCanvasComponentRequestBus
void SetAssetId(const AZ::Data::AssetId& assetId) override;
void SetAssetId(const SourceHandle& assetId) override;
bool HasAssetId() const override;
//=====================================================================
@@ -84,14 +87,8 @@ namespace ScriptCanvasEditor
// EditorContextMenuRequestBus
AZ::Data::AssetId GetAssetId() const override;
//=====================================================================
AZ::EntityId GetGraphEntityId() const;
//=====================================================================
// AssetTrackerNotificationBus
void OnAssetReady(const ScriptCanvasMemoryAsset::pointer asset) override;
void OnAssetSaved(const ScriptCanvasMemoryAsset::pointer asset, bool isSuccessful) override;
void OnAssetReloaded(const ScriptCanvasMemoryAsset::pointer asset) override;
//=====================================================================
//=====================================================================
@@ -101,6 +98,14 @@ namespace ScriptCanvasEditor
void OnStopPlayInEditor() override;
protected:
enum class SourceChangeDescription : AZ::u8
{
Error,
Modified,
Removed,
SelectionChanged,
};
static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
@@ -118,25 +123,31 @@ namespace ScriptCanvasEditor
(void)incompatible;
}
void OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) override;
void OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& assetInfo) override;
void OnScriptCanvasAssetChanged(AZ::Data::AssetId assetId);
// 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;
AZ::u32 OnFileSelectionChanged();
void OnScriptCanvasAssetChanged(SourceChangeDescription changeDescription);
void UpdateName();
//=====================================================================
void OnScriptCanvasAssetReady(const ScriptCanvasMemoryAsset::pointer asset);
void UpdatePropertyDisplay(const SourceHandle& sourceHandle);
//=====================================================================
void BuildGameEntityData();
void ClearVariables();
private:
AZ::Data::AssetId m_removedCatalogId;
AZ::Data::AssetId m_previousAssetId;
AZStd::string m_name;
ScriptCanvasAssetHolder m_scriptCanvasAssetHolder;
bool m_runtimeDataIsValid = false;
ScriptCanvasBuilder::BuildVariableOverrides m_variableOverrides;
SourceHandle m_sourceHandle;
SourceHandle m_previousHandle;
SourceHandle m_removedHandle;
};
}
@@ -0,0 +1,55 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Components/EditorScriptCanvasComponentSerializer.h>
#include <ScriptCanvas/Components/EditorScriptCanvasComponent.h>
namespace AZ
{
AZ_CLASS_ALLOCATOR_IMPL(EditorScriptCanvasComponentSerializer, SystemAllocator, 0);
JsonSerializationResult::Result EditorScriptCanvasComponentSerializer::Load
( void* outputValue
, const Uuid& outputValueTypeId
, const rapidjson::Value& inputValue
, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
AZ_Assert(outputValueTypeId == azrtti_typeid<ScriptCanvasEditor::EditorScriptCanvasComponent>()
, "EditorScriptCanvasComponentSerializer Load against output typeID that was not EditorScriptCanvasComponent");
AZ_Assert(outputValue, "EditorScriptCanvasComponentSerializer Load against null output");
auto outputComponent = reinterpret_cast<ScriptCanvasEditor::EditorScriptCanvasComponent*>(outputValue);
JsonSerializationResult::ResultCode result = BaseJsonSerializer::Load(outputValue, outputValueTypeId, inputValue, context);
if (result.GetProcessing() != JSR::Processing::Halted)
{
auto assetHolderMember = inputValue.FindMember("m_assetHolder");
if (assetHolderMember != inputValue.MemberEnd())
{
ScriptCanvasEditor::ScriptCanvasAssetHolder assetHolder;
result.Combine
( ContinueLoading(&assetHolder
, azrtti_typeid<ScriptCanvasEditor::ScriptCanvasAssetHolder>(), assetHolderMember->value, context));
if (result.GetProcessing() != JSR::Processing::Halted)
{
outputComponent->InitializeSource
( ScriptCanvasEditor::SourceHandle(nullptr, assetHolder.GetAssetId().m_guid, assetHolder.GetAssetHint()));
}
}
}
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "EditorScriptCanvasComponentSerializer Load finished loading EditorScriptCanvasComponent"
: "EditorScriptCanvasComponentSerializer Load failed to load EditorScriptCanvasComponent");
}
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Memory/Memory.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace AZ
{
class EditorScriptCanvasComponentSerializer
: public BaseJsonSerializer
{
public:
AZ_RTTI(EditorScriptCanvasComponentSerializer, "{80B497B3-ABC1-4991-A3C4-047A8CB2C26C}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
private:
JsonSerializationResult::Result Load
( void* outputValue
, const Uuid& outputValueTypeId
, const rapidjson::Value& inputValue
, JsonDeserializerContext& context) override;
};
}
@@ -21,6 +21,13 @@ 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);
// if CompleteDescription() succeeds, sets the handle to the result, else does nothing
bool CompleteDescriptionInPlace(SourceHandle& source);
class Graph;
class NodePaletteModel;
@@ -184,9 +184,9 @@ namespace ScriptCanvasEditor
bool m_graphNeedsDirtying = false;
Graph* m_graph = nullptr;
AZ::Data::Asset<AZ::Data::AssetData> m_asset;
SourceHandle m_asset;
void SetAsset(const AZ::Data::Asset<AZ::Data::AssetData>& asset);
void SetAsset(SourceHandle& assetasset);
void OnComplete(IState::ExitStatus exitStatus) override;
@@ -393,7 +393,7 @@ namespace ScriptCanvasEditor::Nodes
if (methodNode->HasBusID() && busId == slot.GetId() && slot.GetDescriptor() == ScriptCanvas::SlotDescriptors::DataIn())
{
key = Translation::GlobalKeys::EBusSenderIDKey;
key = ::Translation::GlobalKeys::EBusSenderIDKey;
GraphCanvas::TranslationRequestBus::BroadcastResult(details, &GraphCanvas::TranslationRequests::GetDetails, key + ".details", details);
}
else
@@ -508,7 +508,7 @@ namespace ScriptCanvasEditor::Nodes
if (busNode->IsIDRequired() && slot->GetDescriptor() == ScriptCanvas::SlotDescriptors::DataIn())
{
GraphCanvas::TranslationKey key;
key << Translation::GlobalKeys::EBusHandlerIDKey << "details";
key << ::Translation::GlobalKeys::EBusHandlerIDKey << "details";
GraphCanvas::TranslationRequests::Details details;
details.m_name = slot->GetName();
details.m_tooltip = slot->GetToolTip();
@@ -726,7 +726,7 @@ namespace ScriptCanvasEditor::Nodes
if (busNode->IsIDRequired() && slot->GetDescriptor() == ScriptCanvas::SlotDescriptors::DataIn())
{
GraphCanvas::TranslationKey key;
key << Translation::GlobalKeys::EBusHandlerIDKey << "details";
key << ::Translation::GlobalKeys::EBusHandlerIDKey << "details";
GraphCanvas::TranslationRequests::Details details;
GraphCanvas::TranslationRequestBus::BroadcastResult(details, &GraphCanvas::TranslationRequests::GetDetails, key, details);
GraphCanvas::SlotRequestBus::Event(gcSlotId, &GraphCanvas::SlotRequests::SetDetails, details.m_name, details.m_tooltip);
+3 -1
View File
@@ -11,11 +11,13 @@ AZ_PUSH_DISABLE_WARNING(4251 4800 4244, "-Wunknown-warning-option")
#include <QMetaType>
AZ_POP_DISABLE_WARNING
#include <ScriptCanvas/Core/Core.h>
#include <ScriptCanvas/Data/Data.h>
#include <ScriptCanvas/Variable/VariableCore.h>
// VariableId is a UUID typedef for now. So we don't want to double reflect the UUID.
Q_DECLARE_METATYPE(AZ::Uuid);
Q_DECLARE_METATYPE(AZ::Data::AssetId);
Q_DECLARE_METATYPE(ScriptCanvas::Data::Type);
Q_DECLARE_METATYPE(ScriptCanvas::VariableId);
Q_DECLARE_METATYPE(ScriptCanvasEditor::SourceHandle);
@@ -31,6 +31,7 @@ namespace ScriptCanvasEditor
{
void ReflectComponent::Reflect(AZ::ReflectContext* context)
{
SourceHandle::Reflect(context);
ScriptCanvas::ScriptCanvasData::Reflect(context);
ScriptCanvasAssetHolder::Reflect(context);
EditorSettings::EditorWorkspace::Reflect(context);
+14 -11
View File
@@ -92,13 +92,11 @@ namespace ScriptCanvasEditor
// WorkspaceAssetSaveData
EditorWorkspace::WorkspaceAssetSaveData::WorkspaceAssetSaveData()
: m_assetType(azrtti_typeid<ScriptCanvasAsset>())
{
}
EditorWorkspace::WorkspaceAssetSaveData::WorkspaceAssetSaveData(const AZ::Data::AssetId& assetId)
EditorWorkspace::WorkspaceAssetSaveData::WorkspaceAssetSaveData(SourceHandle assetId)
: m_assetId(assetId)
, m_assetType(azrtti_typeid<ScriptCanvasAsset>())
{
}
@@ -108,7 +106,7 @@ namespace ScriptCanvasEditor
{
AZStd::vector<WorkspaceAssetSaveData> assetSaveData;
AZStd::vector<AZ::Data::AssetId> assetIds;
auto subElement = rootDataElementNode.FindSubElement(AZ_CRC("ActiveAssetIds", 0xe445268a));
auto subElement = rootDataElementNode.FindSubElement(AZ_CRC_CE("ActiveAssetIds"));
if (subElement)
{
@@ -117,15 +115,21 @@ namespace ScriptCanvasEditor
assetSaveData.reserve(assetIds.size());
for (const AZ::Data::AssetId& assetId : assetIds)
{
assetSaveData.emplace_back(assetId);
assetSaveData.emplace_back(SourceHandle( nullptr, assetId.m_guid, "" ));
}
}
}
rootDataElementNode.RemoveElementByName(AZ_CRC("ActiveAssetIds", 0xe445268a));
rootDataElementNode.RemoveElementByName(AZ_CRC_CE("ActiveAssetIds"));
rootDataElementNode.AddElementWithData(context, "ActiveAssetData", assetSaveData);
}
if (rootDataElementNode.GetVersion() < 4)
{
rootDataElementNode.RemoveElementByName(AZ_CRC_CE("ActiveAssetIds"));
rootDataElementNode.RemoveElementByName(AZ_CRC_CE("FocusedAssetId"));
}
return true;
}
@@ -135,13 +139,12 @@ namespace ScriptCanvasEditor
if (serialize)
{
serialize->Class<WorkspaceAssetSaveData>()
->Version(1)
->Version(2)
->Field("AssetId", &WorkspaceAssetSaveData::m_assetId)
->Field("AssetType", &WorkspaceAssetSaveData::m_assetType)
;
serialize->Class<EditorWorkspace>()
->Version(3, &EditorWorkspace::VersionConverter)
->Version(4, &EditorWorkspace::VersionConverter)
->Field("m_storedWindowState", &EditorWorkspace::m_storedWindowState)
->Field("m_windowGeometry", &EditorWorkspace::m_windowGeometry)
->Field("FocusedAssetId", &EditorWorkspace::m_focusedAssetId)
@@ -150,13 +153,13 @@ namespace ScriptCanvasEditor
}
}
void EditorWorkspace::ConfigureActiveAssets(AZ::Data::AssetId focussedAssetId, const AZStd::vector< WorkspaceAssetSaveData >& activeAssetData)
void EditorWorkspace::ConfigureActiveAssets(SourceHandle focussedAssetId, const AZStd::vector< WorkspaceAssetSaveData >& activeAssetData)
{
m_focusedAssetId = focussedAssetId;
m_activeAssetData = activeAssetData;
}
AZ::Data::AssetId EditorWorkspace::GetFocusedAssetId() const
SourceHandle EditorWorkspace::GetFocusedAssetId() const
{
return m_focusedAssetId;
}
+7 -7
View File
@@ -11,6 +11,7 @@
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Math/Uuid.h>
#include <AzCore/UserSettings/UserSettings.h>
#include <ScriptCanvas/Core/Core.h>
// qdatastream.h(173): warning C4251: 'QDataStream::d': class 'QScopedPointer<QDataStreamPrivate,QScopedPointerDeleter<T>>' needs to have dll-interface to be used by clients of class 'QDataStream'
// qwidget.h(858): warning C4800: 'uint': forcing value to bool 'true' or 'false' (performance warning)
@@ -53,11 +54,10 @@ namespace ScriptCanvasEditor
AZ_RTTI(WorkspaceAssetSaveData, "{927368CA-096F-4CF1-B2E0-1B9E4A93EA57}");
WorkspaceAssetSaveData();
WorkspaceAssetSaveData(const AZ::Data::AssetId& assetId);
WorkspaceAssetSaveData(SourceHandle assetId);
virtual ~WorkspaceAssetSaveData() = default;
AZ::Data::AssetId m_assetId;
AZ::Data::AssetType m_assetType;
SourceHandle m_assetId;
};
@@ -69,9 +69,9 @@ namespace ScriptCanvasEditor
EditorWorkspace() = default;
void ConfigureActiveAssets(AZ::Data::AssetId focusedAssetId, const AZStd::vector< WorkspaceAssetSaveData >& activeAssetIds);
void ConfigureActiveAssets(SourceHandle focusedAsset, const AZStd::vector< WorkspaceAssetSaveData >& activeAssetIds);
AZ::Data::AssetId GetFocusedAssetId() const;
SourceHandle GetFocusedAssetId() const;
AZStd::vector< WorkspaceAssetSaveData > GetActiveAssetData() const;
void Init(const QByteArray& windowState, const QByteArray& windowGeometry);
@@ -79,7 +79,7 @@ namespace ScriptCanvasEditor
void Clear()
{
m_focusedAssetId.SetInvalid();
m_focusedAssetId.Clear();
m_activeAssetData.clear();
}
@@ -91,7 +91,7 @@ namespace ScriptCanvasEditor
AZStd::vector<AZ::u8> m_windowGeometry;
AZStd::vector<AZ::u8> m_windowState;
AZ::Data::AssetId m_focusedAssetId;
SourceHandle m_focusedAssetId;
AZStd::vector< WorkspaceAssetSaveData > m_activeAssetData;
};
@@ -22,6 +22,7 @@
#include <Editor/SystemComponent.h>
#include <Editor/View/Dialogs/NewGraphDialog.h>
#include <Editor/View/Dialogs/SettingsDialog.h>
#include <Editor/View/Widgets/SourceHandlePropertyAssetCtrl.h>
#include <Editor/View/Windows/MainWindow.h>
#include <GraphCanvas/GraphCanvasBus.h>
#include <LyViewPaneNames.h>
@@ -119,6 +120,10 @@ namespace ScriptCanvasEditor
PopulateEditorCreatableTypes();
AzToolsFramework::RegisterGenericComboBoxHandler<ScriptCanvas::VariableId>();
if (AzToolsFramework::PropertyTypeRegistrationMessages::Bus::FindFirstHandler())
{
AzToolsFramework::PropertyTypeRegistrationMessages::Bus::Broadcast(&AzToolsFramework::PropertyTypeRegistrationMessages::RegisterPropertyType, aznew SourceHandlePropertyHandler());
}
SystemRequestBus::Handler::BusConnect();
ScriptCanvasExecutionBus::Handler::BusConnect();
@@ -173,13 +178,11 @@ namespace ScriptCanvasEditor
outCreatableTypes.insert(m_creatableTypes.begin(), m_creatableTypes.end());
}
void SystemComponent::CreateEditorComponentsOnEntity(AZ::Entity* entity, const AZ::Data::AssetType& assetType)
void SystemComponent::CreateEditorComponentsOnEntity(AZ::Entity* entity, [[maybe_unused]] const AZ::Data::AssetType& assetType)
{
if (entity)
{
auto graph = entity->CreateComponent<Graph>();
graph->SetAssetType(assetType);
entity->CreateComponent<EditorGraphVariableManagerComponent>(graph->GetScriptCanvasId());
}
}
@@ -248,23 +251,25 @@ namespace ScriptCanvasEditor
{
continue;
}
entityMenu->setEnabled(true);
usedIds.insert(assetId);
AZStd::string rootPath;
AZ::Data::AssetInfo assetInfo = AssetHelpers::GetAssetInfo(assetId, rootPath);
AZStd::string displayName;
AZ::StringFunc::Path::GetFileName(assetInfo.m_relativePath.c_str(), displayName);
action = entityMenu->addAction(QString("%1").arg(QString(displayName.c_str())));
QObject::connect(action, &QAction::triggered, [assetId]
{
AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas);
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAsset, assetId, -1);
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAsset
, SourceHandle(nullptr, assetId.m_guid, "")
, Tracker::ScriptCanvasFileState::UNMODIFIED, -1);
});
}
}
@@ -301,7 +306,10 @@ namespace ScriptCanvasEditor
return AzToolsFramework::AssetBrowser::SourceFileDetails();
}
void SystemComponent::AddSourceFileOpeners(const char* fullSourceFileName, [[maybe_unused]] const AZ::Uuid& sourceUUID, AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers)
void SystemComponent::AddSourceFileOpeners
( [[maybe_unused]] const char* fullSourceFileName
, [[maybe_unused]] const AZ::Uuid& sourceUUID
, [[maybe_unused]] AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers)
{
using namespace AzToolsFramework;
using namespace AzToolsFramework::AssetBrowser;
@@ -322,14 +330,16 @@ namespace ScriptCanvasEditor
if (fullDetails)
{
AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas);
AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::OpenViewPane, "Script Canvas");
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, sourceUUIDInCall, -1);
GeneralRequestBus::BroadcastResult(openOutcome
, &GeneralRequests::OpenScriptCanvasAsset
, SourceHandle(nullptr, sourceUUIDInCall, ""), Tracker::ScriptCanvasFileState::UNMODIFIED, -1);
}
};
openers.push_back({ "O3DE_ScriptCanvasEditor", "Open In Script Canvas Editor...", QIcon(), scriptCanvasEditorCallback });
}
}
}
void SystemComponent::OnUserSettingsActivated()
@@ -11,6 +11,7 @@
#include <AzCore/Serialization/Utils.h>
#include <ScriptCanvas/Core/Graph.h>
#include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/Variable/VariableBus.h>
#include <GraphCanvas/Components/SceneBus.h>
@@ -19,7 +20,6 @@
#include <Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <Editor/Assets/ScriptCanvasAssetTrackerBus.h>
#include <Editor/Assets/ScriptCanvasMemoryAsset.h>
namespace ScriptCanvasEditor
{
@@ -36,7 +36,7 @@ namespace ScriptCanvasEditor
{
}
void GraphItemCommand::Capture(ScriptCanvasMemoryAsset&, bool)
void GraphItemCommand::Capture(Graph*, bool)
{
}
@@ -105,10 +105,10 @@ namespace ScriptCanvasEditor
RestoreItem(m_redoState);
}
void GraphItemChangeCommand::Capture(ScriptCanvasMemoryAsset& memoryAsset, bool captureUndo)
void GraphItemChangeCommand::Capture(Graph* graph, bool captureUndo)
{
m_scriptCanvasId = memoryAsset.GetScriptCanvasId();
m_graphCanvasGraphId = memoryAsset.GetGraphId();
m_scriptCanvasId = graph->GetScriptCanvasId();
m_graphCanvasGraphId = graph->GetGraphCanvasGraphId();
UndoCache* undoCache = nullptr;
UndoRequestBus::EventResult(undoCache, m_scriptCanvasId, &UndoRequests::GetSceneUndoCache);
@@ -204,9 +204,9 @@ namespace ScriptCanvasEditor
RestoreItem(m_redoState);
}
void GraphItemAddCommand::Capture(ScriptCanvasMemoryAsset& memoryAsset, bool)
void GraphItemAddCommand::Capture(Graph* graph, bool)
{
GraphItemChangeCommand::Capture(memoryAsset, false);
GraphItemChangeCommand::Capture(graph, false);
}
//// Graph Item Removal Command
@@ -225,8 +225,8 @@ namespace ScriptCanvasEditor
RestoreItem(m_redoState);
}
void GraphItemRemovalCommand::Capture(ScriptCanvasMemoryAsset& memoryAsset, bool)
void GraphItemRemovalCommand::Capture(Graph* graph, bool)
{
GraphItemChangeCommand::Capture(memoryAsset, true);
GraphItemChangeCommand::Capture(graph, true);
}
}
@@ -46,7 +46,7 @@ namespace ScriptCanvasEditor
void Undo() override;
void Redo() override;
virtual void Capture(ScriptCanvasMemoryAsset& memoryAsset, bool captureUndo);
virtual void Capture(Graph* graph, bool captureUndo);
bool Changed() const override;
@@ -76,7 +76,7 @@ namespace ScriptCanvasEditor
void Undo() override;
void Redo() override;
void Capture(ScriptCanvasMemoryAsset& memoryAsset, bool captureUndo) override;
void Capture(Graph* graph, bool captureUndo) override;
void RestoreItem(const AZStd::vector<AZ::u8>& restoreBuffer) override;
@@ -103,7 +103,7 @@ namespace ScriptCanvasEditor
void Undo() override;
void Redo() override;
void Capture(ScriptCanvasMemoryAsset& memoryAsset, bool captureUndo) override;
void Capture(Graph* graph, bool captureUndo) override;
protected:
GraphItemAddCommand(const GraphItemAddCommand&) = delete;
@@ -124,7 +124,7 @@ namespace ScriptCanvasEditor
void Undo() override;
void Redo() override;
void Capture(ScriptCanvasMemoryAsset& memoryAsset, bool captureUndo) override;
void Capture(Graph* graph, bool captureUndo) override;
protected:
GraphItemRemovalCommand(const GraphItemRemovalCommand&) = delete;
@@ -28,9 +28,9 @@ namespace ScriptCanvasEditor
// SceneUndoState
SceneUndoState::SceneUndoState(AzToolsFramework::UndoSystem::IUndoNotify* undoNotify)
: m_undoStack(AZStd::make_unique<AzToolsFramework::UndoSystem::UndoStack>(c_undoLimit, undoNotify))
, m_undoCache(AZStd::make_unique<UndoCache>())
{
m_undoStack = AZStd::make_unique<AzToolsFramework::UndoSystem::UndoStack>(c_undoLimit, undoNotify);
m_undoCache = AZStd::make_unique<UndoCache>();
}
void SceneUndoState::BeginUndoBatch(AZStd::string_view label)
@@ -61,6 +61,7 @@ namespace ScriptCanvasEditor
public:
AZ_CLASS_ALLOCATOR(SceneUndoState, AZ::SystemAllocator, 0);
SceneUndoState() = default;
SceneUndoState(AzToolsFramework::UndoSystem::IUndoNotify* undoNotify);
~SceneUndoState();
@@ -15,7 +15,7 @@
namespace ScriptCanvasEditor
{
AZ::Data::AssetId ReadRecentAssetId()
SourceHandle ReadRecentAssetId()
{
QSettings settings(QSettings::IniFormat, QSettings::UserScope,
SCRIPTCANVASEDITOR_AZ_QCOREAPPLICATION_SETTINGS_ORGANIZATION_NAME);
@@ -26,20 +26,15 @@ namespace ScriptCanvasEditor
recentOpenFileLocation = settings.value(SCRIPTCANVASEDITOR_SETTINGS_RECENT_OPEN_FILE_LOCATION_KEY).toString();
settings.endGroup();
if (recentOpenFileLocation.isEmpty())
{
return {};
}
AZ::Data::AssetId assetId(recentOpenFileLocation.toUtf8().constData());
return assetId;
return { nullptr, {}, recentOpenFileLocation.toUtf8().constData() };
}
void SetRecentAssetId(const AZ::Data::AssetId& assetId)
void SetRecentAssetId(SourceHandle assetId)
{
QSettings settings(QSettings::IniFormat, QSettings::UserScope,
SCRIPTCANVASEDITOR_AZ_QCOREAPPLICATION_SETTINGS_ORGANIZATION_NAME);
AZStd::string guidStr = assetId.m_guid.ToString<AZStd::string>();
AZStd::string guidStr = assetId.Id().ToString<AZStd::string>();
settings.beginGroup(SCRIPTCANVASEDITOR_NAME_SHORT);
settings.setValue(SCRIPTCANVASEDITOR_SETTINGS_RECENT_OPEN_FILE_LOCATION_KEY,
@@ -8,10 +8,11 @@
#pragma once
#include <AzCore/Asset/AssetCommon.h>
#include <ScriptCanvas/Core/Core.h>
namespace ScriptCanvasEditor
{
AZ::Data::AssetId ReadRecentAssetId();
void SetRecentAssetId(const AZ::Data::AssetId& assetId);
SourceHandle ReadRecentAssetId();
void SetRecentAssetId(SourceHandle assetId);
void ClearRecentAssetId();
}
@@ -11,14 +11,16 @@
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Math/Uuid.h>
#include <AzCore/EBus/EBus.h>
#include <Core/Core.h>
namespace ScriptCanvasEditor
{
// #sc-editor-asset remove this
class AssetGraphScene : public AZ::EBusTraits
{
public:
virtual AZ::EntityId FindEditorNodeIdByAssetNodeId(const AZ::Data::AssetId& assetId, AZ::EntityId assetNodeId) const = 0;
virtual AZ::EntityId FindAssetNodeIdByEditorNodeId(const AZ::Data::AssetId& assetId, AZ::EntityId editorNodeId) const = 0;
virtual AZ::EntityId FindEditorNodeIdByAssetNodeId(const SourceHandle& assetId, AZ::EntityId assetNodeId) const = 0;
virtual AZ::EntityId FindAssetNodeIdByEditorNodeId(const SourceHandle& assetId, AZ::EntityId editorNodeId) const = 0;
};
using AssetGraphSceneBus = AZ::EBus<AssetGraphScene>;
@@ -36,7 +36,7 @@ namespace ScriptCanvasEditor
{
namespace Widget
{
CanvasWidget::CanvasWidget(const AZ::Data::AssetId& assetId, QWidget* parent)
CanvasWidget::CanvasWidget(const ScriptCanvasEditor::SourceHandle& assetId, QWidget* parent)
: QWidget(parent)
, ui(new Ui::CanvasWidget())
, m_attached(false)
@@ -69,25 +69,15 @@ namespace ScriptCanvasEditor
void CanvasWidget::ShowScene(const ScriptCanvas::ScriptCanvasId& scriptCanvasId)
{
EditorGraphRequests* editorGraphRequests = EditorGraphRequestBus::FindFirstHandler(scriptCanvasId);
editorGraphRequests->SetAssetId(m_assetId);
editorGraphRequests->CreateGraphCanvasScene();
AZ::EntityId graphCanvasSceneId = editorGraphRequests->GetGraphCanvasGraphId();
m_graphicsView->SetScene(graphCanvasSceneId);
m_scriptCanvasId = scriptCanvasId;
}
void CanvasWidget::SetAssetId(const AZ::Data::AssetId& assetId)
void CanvasWidget::SetAssetId(const ScriptCanvasEditor::SourceHandle& assetId)
{
m_assetId = assetId;
if (EditorGraphRequests* editorGraphRequests = EditorGraphRequestBus::FindFirstHandler(m_scriptCanvasId))
{
editorGraphRequests->SetAssetId(m_assetId);
}
}
const GraphCanvas::ViewId& CanvasWidget::GetViewId() const
@@ -21,6 +21,7 @@ AZ_POP_DISABLE_WARNING
#include <AzCore/Asset/AssetCommon.h>
#include <GraphCanvas/Components/ViewBus.h>
#include <ScriptCanvas/Core/Core.h>
#endif
class QVBoxLayout;
@@ -46,13 +47,13 @@ namespace ScriptCanvasEditor
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(CanvasWidget, AZ::SystemAllocator, 0);
CanvasWidget(const AZ::Data::AssetId& assetId, QWidget* parent = nullptr);
CanvasWidget(const ScriptCanvasEditor::SourceHandle& assetId, QWidget* parent = nullptr);
~CanvasWidget() override;
void SetDefaultBorderColor(AZ::Color defaultBorderColor);
void ShowScene(const ScriptCanvas::ScriptCanvasId& scriptCanvasId);
void SetAssetId(const AZ::Data::AssetId& assetId);
void SetAssetId(const ScriptCanvasEditor::SourceHandle& assetId);
const GraphCanvas::ViewId& GetViewId() const;
@@ -69,7 +70,7 @@ namespace ScriptCanvasEditor
void SetupGraphicsView();
AZ::Data::AssetId m_assetId;
ScriptCanvasEditor::SourceHandle m_assetId;
AZStd::unique_ptr<Ui::CanvasWidget> ui;
@@ -23,6 +23,8 @@
#include <ScriptCanvas/Asset/AssetDescription.h>
#include <Editor/Include/ScriptCanvas/Components/EditorGraph.h>
namespace ScriptCanvasEditor
{
namespace Widget
@@ -31,7 +33,7 @@ namespace ScriptCanvasEditor
// GraphTabBar
////////////////
GraphTabBar::GraphTabBar(QWidget* parent /*= nullptr*/)
GraphTabBar::GraphTabBar(QWidget* parent)
: AzQtComponents::TabBar(parent)
{
setTabsClosable(true);
@@ -44,49 +46,128 @@ namespace ScriptCanvasEditor
connect(this, &QTabBar::customContextMenuRequested, this, &GraphTabBar::OnContextMenu);
}
void GraphTabBar::AddGraphTab(const AZ::Data::AssetId& assetId)
void GraphTabBar::AddGraphTab(ScriptCanvasEditor::SourceHandle assetId, Tracker::ScriptCanvasFileState fileState)
{
InsertGraphTab(count(), assetId);
InsertGraphTab(count(), assetId, fileState);
}
int GraphTabBar::InsertGraphTab(int tabIndex, const AZ::Data::AssetId& assetId)
void GraphTabBar::ClearTabView(int tabIndex)
{
if (tabIndex < count())
{
if (QVariant tabDataVariant = tabData(tabIndex); tabDataVariant.isValid())
{
GraphTabMetadata replacement = tabDataVariant.value<GraphTabMetadata>();
if (replacement.m_canvasWidget)
{
delete replacement.m_canvasWidget;
replacement.m_canvasWidget = nullptr;
tabDataVariant.setValue(replacement);
setTabData(tabIndex, tabDataVariant);
}
}
}
}
CanvasWidget* GraphTabBar::ModOrCreateTabView(int tabIndex)
{
if (tabIndex < count())
{
if (QVariant tabDataVariant = tabData(tabIndex); tabDataVariant.isValid())
{
if (!tabDataVariant.value<GraphTabMetadata>().m_canvasWidget)
{
CanvasWidget* canvasWidget = new CanvasWidget(tabDataVariant.value<GraphTabMetadata>().m_assetId, this);
canvasWidget->SetDefaultBorderColor(ScriptCanvasAssetDescription().GetDisplayColorImpl());
GraphTabMetadata replacement = tabDataVariant.value<GraphTabMetadata>();
replacement.m_canvasWidget = canvasWidget;
tabDataVariant.setValue(replacement);
setTabData(tabIndex, tabDataVariant);
}
return tabDataVariant.value<GraphTabMetadata>().m_canvasWidget;
}
}
return nullptr;
}
CanvasWidget* GraphTabBar::ModTabView(int tabIndex)
{
if (tabIndex < count())
{
if (QVariant tabDataVariant = tabData(tabIndex); tabDataVariant.isValid())
{
return tabDataVariant.value<GraphTabMetadata>().m_canvasWidget;
}
}
return nullptr;
}
AZStd::optional<GraphTabMetadata> GraphTabBar::GetTabData(int tabIndex) const
{
if (tabIndex < count())
{
if (QVariant tabDataVariant = tabData(tabIndex); tabDataVariant.isValid())
{
return tabDataVariant.value<GraphTabMetadata>();
}
}
return AZStd::nullopt;
}
AZStd::optional<GraphTabMetadata> GraphTabBar::GetTabData(ScriptCanvasEditor::SourceHandle assetId) const
{
return GetTabData(FindTab(assetId));
}
void GraphTabBar::SetTabData(const GraphTabMetadata& metadata, int tabIndex)
{
if (tabIndex < count())
{
setTabData(tabIndex, QVariant::fromValue(metadata));
}
}
void GraphTabBar::SetTabData(const GraphTabMetadata& metadata, ScriptCanvasEditor::SourceHandle assetId)
{
auto index = FindTab(assetId);
auto replacement = GetTabData(assetId);
if (index >= 0 && replacement)
{
replacement->m_assetId = assetId;
SetTabData(metadata, index);
}
}
int GraphTabBar::InsertGraphTab(int tabIndex, ScriptCanvasEditor::SourceHandle assetId, Tracker::ScriptCanvasFileState fileState)
{
if (!SelectTab(assetId))
{
AZStd::shared_ptr<ScriptCanvasMemoryAsset> memoryAsset;
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, assetId);
QIcon tabIcon = QIcon(ScriptCanvasAssetDescription().GetIconPathImpl());
tabIndex = qobject_cast<AzQtComponents::TabWidget*>(parent())->insertTab(tabIndex, new QWidget(), tabIcon, "");
GraphTabMetadata metaData;
CanvasWidget* canvasWidget = new CanvasWidget(assetId, this);
canvasWidget->SetDefaultBorderColor(ScriptCanvasAssetDescription().GetDisplayColorImpl());
metaData.m_canvasWidget = canvasWidget;
metaData.m_assetId = assetId;
metaData.m_fileState = fileState;
AZStd::string tabName;
AzFramework::StringFunc::Path::GetFileName(assetId.Path().c_str(), tabName);
if (memoryAsset)
{
ScriptCanvas::AssetDescription assetDescription = memoryAsset->GetAsset().Get()->GetAssetDescription();
QIcon tabIcon = QIcon(assetDescription.GetIconPathImpl());
int newTabIndex = qobject_cast<AzQtComponents::TabWidget*>(parent())->insertTab(tabIndex, new QWidget(), tabIcon, "");
CanvasWidget* canvasWidget = memoryAsset->CreateView(this);
canvasWidget->SetDefaultBorderColor(assetDescription.GetDisplayColorImpl());
AZStd::string tabName;
AzFramework::StringFunc::Path::GetFileName(memoryAsset->GetAbsolutePath().c_str(), tabName);
ConfigureTab(newTabIndex, assetId, tabName);
// new graphs will need to use their in-memory assetid which we'll need to update
// upon saving the asset
if (!memoryAsset->GetFileAssetId().IsValid())
{
setTabData(newTabIndex, QVariant::fromValue(memoryAsset->GetId()));
}
return newTabIndex;
}
SetTabText(tabIndex, tabName.c_str(), fileState);
setTabData(tabIndex, QVariant::fromValue(metaData));
return tabIndex;
}
return -1;
}
bool GraphTabBar::SelectTab(const AZ::Data::AssetId& assetId)
bool GraphTabBar::SelectTab(ScriptCanvasEditor::SourceHandle assetId)
{
int tabIndex = FindTab(assetId);
if (-1 != tabIndex)
@@ -94,74 +175,119 @@ namespace ScriptCanvasEditor
setCurrentIndex(tabIndex);
return true;
}
return false;
}
void GraphTabBar::ConfigureTab(int tabIndex, AZ::Data::AssetId fileAssetId, const AZStd::string& tabName)
{
if (fileAssetId.IsValid())
{
QVariant tabDataVariant = tabData(tabIndex);
if (tabDataVariant.isValid())
{
auto tabAssetId = tabDataVariant.value<AZ::Data::AssetId>();
MemoryAssetNotificationBus::MultiHandler::BusDisconnect(tabAssetId);
}
setTabData(tabIndex, QVariant::fromValue(fileAssetId));
MemoryAssetNotificationBus::MultiHandler::BusConnect(fileAssetId);
}
Tracker::ScriptCanvasFileState fileState = Tracker::ScriptCanvasFileState::INVALID;
AssetTrackerRequestBus::BroadcastResult(fileState, &AssetTrackerRequests::GetFileState, fileAssetId);
SetTabText(tabIndex, tabName.c_str(), fileState);
}
int GraphTabBar::FindTab(const AZ::Data::AssetId& assetId) const
int GraphTabBar::FindTab(ScriptCanvasEditor::SourceHandle assetId) const
{
for (int tabIndex = 0; tabIndex < count(); ++tabIndex)
{
QVariant tabDataVariant = tabData(tabIndex);
if (tabDataVariant.isValid())
{
auto tabAssetId = tabDataVariant.value<AZ::Data::AssetId>();
if (tabAssetId == assetId)
auto tabAssetId = tabDataVariant.value<GraphTabMetadata>();
if (tabAssetId.m_assetId.AnyEquals(assetId))
{
return tabIndex;
}
}
}
return -1;
}
AZ::Data::AssetId GraphTabBar::FindAssetId(int tabIndex)
int GraphTabBar::FindTab(ScriptCanvasEditor::GraphPtrConst graph) const
{
for (int tabIndex = 0; tabIndex < count(); ++tabIndex)
{
QVariant tabDataVariant = tabData(tabIndex);
if (tabDataVariant.isValid())
{
auto tabAssetId = tabDataVariant.value<GraphTabMetadata>();
if (tabAssetId.m_assetId.Get() == graph)
{
return tabIndex;
}
}
}
return -1;
}
int GraphTabBar::FindSaveOverMatch(ScriptCanvasEditor::SourceHandle assetId) const
{
for (int tabIndex = 0; tabIndex < count(); ++tabIndex)
{
QVariant tabDataVariant = tabData(tabIndex);
if (tabDataVariant.isValid())
{
auto tabAssetId = tabDataVariant.value<GraphTabMetadata>();
if (tabAssetId.m_assetId.Get() != assetId.Get() && tabAssetId.m_assetId.PathEquals(assetId))
{
return tabIndex;
}
}
}
return -1;
}
ScriptCanvasEditor::SourceHandle GraphTabBar::FindTabByPath(AZStd::string_view path) const
{
ScriptCanvasEditor::SourceHandle candidate(nullptr, {}, path);
for (int index = 0; index < count(); ++index)
{
QVariant tabdata = tabData(index);
if (tabdata.isValid())
{
auto tabAssetId = tabdata.value<GraphTabMetadata>();
if (tabAssetId.m_assetId.AnyEquals(candidate))
{
return tabAssetId.m_assetId;
}
}
}
return {};
}
ScriptCanvasEditor::SourceHandle GraphTabBar::FindAssetId(int tabIndex)
{
QVariant dataVariant = tabData(tabIndex);
if (dataVariant.isValid())
{
auto tabAssetId = dataVariant.value<AZ::Data::AssetId>();
return tabAssetId;
auto tabAssetId = dataVariant.value<GraphTabMetadata>();
return tabAssetId.m_assetId;
}
return AZ::Data::AssetId();
return ScriptCanvasEditor::SourceHandle();
}
ScriptCanvas::ScriptCanvasId GraphTabBar::FindScriptCanvasIdFromGraphCanvasId(const GraphCanvas::GraphId& graphCanvasGraphId) const
{
for (int index = 0; index < count(); ++index)
{
QVariant tabdata = tabData(index);
if (tabdata.isValid())
{
auto tabAssetId = tabdata.value<GraphTabMetadata>();
if (tabAssetId.m_assetId.IsGraphValid()
&& tabAssetId.m_assetId.Get()->GetGraphCanvasGraphId() == graphCanvasGraphId)
{
return tabAssetId.m_assetId.Get()->GetScriptCanvasId();
}
}
}
return ScriptCanvas::ScriptCanvasId{};
}
void GraphTabBar::CloseTab(int index)
{
if (index >= 0 && index < count())
{
QVariant tabdata = tabData(index);
if (tabdata.isValid())
{
auto tabAssetId = tabdata.value<AZ::Data::AssetId>();
MemoryAssetNotificationBus::MultiHandler::BusDisconnect(tabAssetId);
AssetTrackerRequestBus::Broadcast(&AssetTrackerRequests::ClearView, tabAssetId);
}
qobject_cast<AzQtComponents::TabWidget*>(parent())->removeTab(index);
}
}
@@ -172,8 +298,6 @@ namespace ScriptCanvasEditor
{
Q_EMIT TabCloseNoButton(i);
}
MemoryAssetNotificationBus::MultiHandler::BusDisconnect();
}
void GraphTabBar::OnContextMenu(const QPoint& point)
@@ -187,11 +311,9 @@ namespace ScriptCanvasEditor
QVariant tabdata = tabData(tabIndex);
if (tabdata.isValid())
{
auto tabAssetId = tabdata.value<AZ::Data::AssetId>();
Tracker::ScriptCanvasFileState fileState;
AssetTrackerRequestBus::BroadcastResult(fileState , &AssetTrackerRequests::GetFileState, tabAssetId);
auto tabAssetId = tabdata.value<GraphTabMetadata>();
Tracker::ScriptCanvasFileState fileState = Tracker::ScriptCanvasFileState::INVALID;
isModified = fileState == Tracker::ScriptCanvasFileState::NEW || fileState == Tracker::ScriptCanvasFileState::MODIFIED;
}
@@ -263,23 +385,14 @@ namespace ScriptCanvasEditor
AzQtComponents::TabBar::mouseReleaseEvent(event);
}
void GraphTabBar::OnFileStateChanged(Tracker::ScriptCanvasFileState fileState)
{
const AZ::Data::AssetId* fileAssetId = MemoryAssetNotificationBus::GetCurrentBusId();
if (fileAssetId)
{
SetFileState((*fileAssetId), fileState);
if (FindTab((*fileAssetId)) == currentIndex())
{
Q_EMIT OnActiveFileStateChanged();
}
}
}
void GraphTabBar::SetTabText(int tabIndex, const QString& path, Tracker::ScriptCanvasFileState fileState)
{
QString safePath = path;
if (path.endsWith("^") || path.endsWith("*"))
{
safePath.chop(1);
}
if (tabIndex >= 0 && tabIndex < count())
{
const char* fileStateTag = "";
@@ -296,7 +409,7 @@ namespace ScriptCanvasEditor
break;
}
setTabText(tabIndex, QString("%1%2").arg(path).arg(fileStateTag));
setTabText(tabIndex, QString("%1%2").arg(safePath).arg(fileStateTag));
}
}
@@ -314,6 +427,23 @@ namespace ScriptCanvasEditor
Q_EMIT TabRemoved(index);
}
void GraphTabBar::UpdateFileState(const ScriptCanvasEditor::SourceHandle& assetId, Tracker::ScriptCanvasFileState fileState)
{
auto tabData = GetTabData(assetId);
if (tabData && tabData->m_fileState != fileState)
{
int index = FindTab(assetId);
tabData->m_fileState = fileState;
SetTabData(*tabData, assetId);
SetTabText(index, tabText(index), fileState);
if (index == currentIndex())
{
Q_EMIT OnActiveFileStateChanged();
}
}
}
void GraphTabBar::currentChangedTab(int index)
{
if (index < 0)
@@ -327,7 +457,7 @@ namespace ScriptCanvasEditor
return;
}
auto assetId = tabdata.value<AZ::Data::AssetId>();
auto assetId = tabdata.value<GraphTabMetadata>().m_assetId;
ScriptCanvasEditor::GeneralRequestBus::Broadcast(&ScriptCanvasEditor::GeneralRequests::OnChangeActiveGraphTab, assetId);
@@ -338,24 +468,6 @@ namespace ScriptCanvasEditor
}
}
void GraphTabBar::SetFileState(AZ::Data::AssetId assetId, Tracker::ScriptCanvasFileState fileState)
{
int index = FindTab(assetId);
if (index >= 0 && index < count())
{
QVariant tabdata = tabData(index);
if (tabdata.isValid())
{
auto tabAssetId = tabdata.value<AZ::Data::AssetId>();
AZStd::string tabName;
AssetTrackerRequestBus::BroadcastResult(tabName, &AssetTrackerRequests::GetTabName, tabAssetId);
SetTabText(index, tabName.c_str(), fileState);
}
}
}
#include <Editor/View/Widgets/moc_GraphTabBar.cpp>
}
}
@@ -16,7 +16,10 @@
#include <AzCore/Component/EntityId.h>
#include <AzCore/Asset/AssetCommon.h>
#include <ScriptCanvas/Core/Core.h>
#include <Editor/Assets/ScriptCanvasAssetTracker.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#endif
class QGraphicsView;
@@ -26,17 +29,18 @@ namespace ScriptCanvasEditor
{
namespace Widget
{
class CanvasWidget;
struct GraphTabMetadata
{
AZ::Data::AssetId m_assetId;
SourceHandle m_assetId;
QWidget* m_hostWidget = nullptr;
QString m_tabName;
CanvasWidget* m_canvasWidget = nullptr;
Tracker::ScriptCanvasFileState m_fileState = Tracker::ScriptCanvasFileState::INVALID;
};
class GraphTabBar
: public AzQtComponents::TabBar
, public MemoryAssetNotificationBus::MultiHandler
{
Q_OBJECT
@@ -45,30 +49,39 @@ namespace ScriptCanvasEditor
GraphTabBar(QWidget* parent = nullptr);
~GraphTabBar() override = default;
void AddGraphTab(const AZ::Data::AssetId& assetId);
int InsertGraphTab(int tabIndex, const AZ::Data::AssetId& assetId);
bool SelectTab(const AZ::Data::AssetId& assetId);
void ConfigureTab(int tabIndex, AZ::Data::AssetId fileAssetId, const AZStd::string& tabName);
int FindTab(const AZ::Data::AssetId& assetId) const;
AZ::Data::AssetId FindAssetId(int tabIndex);
AZStd::optional<GraphTabMetadata> GetTabData(int index) const;
AZStd::optional<GraphTabMetadata> GetTabData(ScriptCanvasEditor::SourceHandle assetId) const;
void SetTabData(const GraphTabMetadata& data, int index);
void SetTabData(const GraphTabMetadata& data, ScriptCanvasEditor::SourceHandle assetId);
void AddGraphTab(ScriptCanvasEditor::SourceHandle assetId, Tracker::ScriptCanvasFileState fileState);
void CloseTab(int index);
void CloseAllTabs();
int InsertGraphTab(int tabIndex, ScriptCanvasEditor::SourceHandle assetId, Tracker::ScriptCanvasFileState fileState);
bool SelectTab(ScriptCanvasEditor::SourceHandle assetId);
int FindTab(ScriptCanvasEditor::SourceHandle assetId) const;
int FindTab(ScriptCanvasEditor::GraphPtrConst graph) const;
int FindSaveOverMatch(ScriptCanvasEditor::SourceHandle assetId) const;
ScriptCanvasEditor::SourceHandle FindTabByPath(AZStd::string_view path) const;
ScriptCanvasEditor::SourceHandle FindAssetId(int tabIndex);
ScriptCanvas::ScriptCanvasId FindScriptCanvasIdFromGraphCanvasId(const GraphCanvas::GraphId& graphCanvasGraphId) const;
void ClearTabView(int tabIndex);
CanvasWidget* ModOrCreateTabView(int tabIndex);
CanvasWidget* ModTabView(int tabIndex);
void OnContextMenu(const QPoint& point);
void mouseReleaseEvent(QMouseEvent* event) override;
// MemoryAssetNotifications
void OnFileStateChanged(Tracker::ScriptCanvasFileState fileState) override;
////
// Updates the tab at the supplied index with the GraphTabMetadata
// The host widget field of the tabMetadata is not used and will not overwrite the tab data
void SetTabText(int tabIndex, const QString& path, Tracker::ScriptCanvasFileState fileState = Tracker::ScriptCanvasFileState::INVALID);
void UpdateFileState(const ScriptCanvasEditor::SourceHandle& assetId, Tracker::ScriptCanvasFileState fileState);
Q_SIGNALS:
void TabInserted(int index);
void TabRemoved(int index);
@@ -92,8 +105,6 @@ namespace ScriptCanvasEditor
// Called when the selected tab changes
void currentChangedTab(int index);
void SetFileState(AZ::Data::AssetId assetId, Tracker::ScriptCanvasFileState fileState);
int m_signalSaveOnChangeTo = -1;
};
}
@@ -256,7 +256,8 @@ namespace ScriptCanvasEditor
const AZ::Data::AssetId& assetId = executionItem->GetAssetId();
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAssetId, assetId);
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAssetId
, SourceHandle(nullptr, assetId.m_guid, {}), Tracker::ScriptCanvasFileState::UNMODIFIED);
}
}
}
@@ -270,12 +271,14 @@ namespace ScriptCanvasEditor
const AZ::Data::AssetId& assetId = executionItem->GetAssetId();
bool isAssetOpen = false;
GeneralRequestBus::BroadcastResult(isAssetOpen, &GeneralRequests::IsScriptCanvasAssetOpen, assetId);
GeneralRequestBus::BroadcastResult(isAssetOpen, &GeneralRequests::IsScriptCanvasAssetOpen, SourceHandle(nullptr, assetId.m_guid, {}));
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAssetId, assetId);
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAssetId
, SourceHandle(nullptr, assetId.m_guid, {}), Tracker::ScriptCanvasFileState::UNMODIFIED);
AZ::EntityId graphCanvasGraphId;
GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::FindGraphCanvasGraphIdByAssetId, assetId);
GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::FindGraphCanvasGraphIdByAssetId
, SourceHandle(nullptr, assetId.m_guid, {}));
if (isAssetOpen)
{
@@ -348,7 +351,7 @@ namespace ScriptCanvasEditor
GeneralRequestBus::BroadcastResult(activeGraphCanvasGraphId, &GeneralRequests::GetActiveGraphCanvasGraphId);
AZ::EntityId graphCanvasGraphId;
GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::FindGraphCanvasGraphIdByAssetId, m_assetId);
GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::FindGraphCanvasGraphIdByAssetId, SourceHandle(nullptr, m_assetId.m_guid, {}));
if (activeGraphCanvasGraphId == graphCanvasGraphId)
{
@@ -366,7 +369,7 @@ namespace ScriptCanvasEditor
GraphCanvas::FocusConfig focusConfig;
AZ::EntityId scriptCanvasNodeId;
AssetGraphSceneBus::BroadcastResult(scriptCanvasNodeId, &AssetGraphScene::FindEditorNodeIdByAssetNodeId, assetId, assetNodeId);
AssetGraphSceneBus::BroadcastResult(scriptCanvasNodeId, &AssetGraphScene::FindEditorNodeIdByAssetNodeId, SourceHandle(nullptr, assetId.m_guid, {}), assetNodeId);
GraphCanvas::NodeId graphCanvasNodeId;
SceneMemberMappingRequestBus::EventResult(graphCanvasNodeId, scriptCanvasNodeId, &SceneMemberMappingRequests::GetGraphCanvasEntityId);
@@ -403,12 +406,12 @@ namespace ScriptCanvasEditor
void LoggingWindowSession::HighlightElement(const AZ::Data::AssetId& assetId, const AZ::EntityId& assetNodeId)
{
AZ::EntityId graphCanvasGraphId;
GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::FindGraphCanvasGraphIdByAssetId, assetId);
GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::FindGraphCanvasGraphIdByAssetId, SourceHandle(nullptr, assetId.m_guid, {}));
if (graphCanvasGraphId.IsValid())
{
AZ::EntityId scriptCanvasNodeId;
AssetGraphSceneBus::BroadcastResult(scriptCanvasNodeId, &AssetGraphScene::FindEditorNodeIdByAssetNodeId, assetId, assetNodeId);
AssetGraphSceneBus::BroadcastResult(scriptCanvasNodeId, &AssetGraphScene::FindEditorNodeIdByAssetNodeId, SourceHandle(nullptr, assetId.m_guid, {}), assetNodeId);
GraphCanvas::NodeId graphCanvasNodeId;
SceneMemberMappingRequestBus::EventResult(graphCanvasNodeId, scriptCanvasNodeId, &SceneMemberMappingRequests::GetGraphCanvasEntityId);
@@ -447,7 +450,7 @@ namespace ScriptCanvasEditor
if (effectIter != m_highlightEffects.end())
{
AZ::EntityId graphCanvasGraphId;
GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::FindGraphCanvasGraphIdByAssetId, assetId);
GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::FindGraphCanvasGraphIdByAssetId, SourceHandle(nullptr, assetId.m_guid, {}));
if (graphCanvasGraphId.IsValid())
{
@@ -122,7 +122,11 @@ namespace ScriptCanvasEditor
{
}
ExecutionLogTreeItem* DebugLogRootItem::CreateExecutionItem(const LoggingDataId& loggingDataId, const ScriptCanvas::NodeTypeIdentifier& nodeType, const ScriptCanvas::GraphInfo& graphInfo, const ScriptCanvas::NamedNodeId& nodeId)
ExecutionLogTreeItem* DebugLogRootItem::CreateExecutionItem
( [[maybe_unused]] const LoggingDataId& loggingDataId
, [[maybe_unused]] const ScriptCanvas::NodeTypeIdentifier& nodeType
, [[maybe_unused]] const ScriptCanvas::GraphInfo& graphInfo
, [[maybe_unused]] const ScriptCanvas::NamedNodeId& nodeId)
{
ExecutionLogTreeItem* treeItem = nullptr;
@@ -133,15 +137,6 @@ namespace ScriptCanvasEditor
m_additionTimer.start();
}
}
if (m_updatePolicy == UpdatePolicy::SingleTime)
{
treeItem = CreateChildNodeWithoutAddSignal<ExecutionLogTreeItem>(loggingDataId, nodeType, graphInfo, nodeId);
}
else
{
treeItem = CreateChildNode<ExecutionLogTreeItem>(loggingDataId, nodeType, graphInfo, nodeId);
}
return treeItem;
}
@@ -185,7 +180,11 @@ namespace ScriptCanvasEditor
// ExecutionLogTreeItem
/////////////////////////
ExecutionLogTreeItem::ExecutionLogTreeItem(const LoggingDataId& loggingDataId, const ScriptCanvas::NodeTypeIdentifier& nodeType, const ScriptCanvas::GraphInfo& graphInfo, const ScriptCanvas::NamedNodeId& nodeId)
ExecutionLogTreeItem::ExecutionLogTreeItem
( const LoggingDataId& loggingDataId
, const ScriptCanvas::NodeTypeIdentifier& nodeType
, const SourceHandle& graphInfo
, const ScriptCanvas::NamedNodeId& nodeId)
: m_loggingDataId(loggingDataId)
, m_nodeType(nodeType)
, m_graphInfo(graphInfo)
@@ -196,7 +195,6 @@ namespace ScriptCanvasEditor
m_paletteConfiguration.SetColorPalette("MethodNodeTitlePalette");
AZ::NamedEntityId entityName;
LoggingDataRequestBus::EventResult(entityName, m_loggingDataId, &LoggingDataRequests::FindNamedEntityId, m_graphInfo.m_runtimeEntity);
m_sourceEntityName = entityName.ToString().c_str();
m_displayName = nodeId.m_name.c_str();
@@ -207,7 +205,7 @@ namespace ScriptCanvasEditor
m_inputName = "---";
m_outputName = "---";
GeneralAssetNotificationBus::Handler::BusConnect(GetAssetId());
GeneralAssetNotificationBus::Handler::BusConnect(graphInfo);
}
QVariant ExecutionLogTreeItem::Data(const QModelIndex& index, int role) const
@@ -502,12 +500,12 @@ namespace ScriptCanvasEditor
const ScriptCanvas::GraphIdentifier& ExecutionLogTreeItem::GetGraphIdentifier() const
{
return m_graphInfo.m_graphIdentifier;
return m_graphIdentifier;
}
const AZ::Data::AssetId& ExecutionLogTreeItem::GetAssetId() const
AZ::Data::AssetId ExecutionLogTreeItem::GetAssetId() const
{
return m_graphInfo.m_graphIdentifier.m_assetId;
return m_graphInfo.Id();
}
AZ::EntityId ExecutionLogTreeItem::GetScriptCanvasAssetNodeId() const
@@ -623,12 +621,14 @@ namespace ScriptCanvasEditor
{
if (!m_graphCanvasGraphId.IsValid())
{
GeneralRequestBus::BroadcastResult(m_graphCanvasGraphId, &GeneralRequests::FindGraphCanvasGraphIdByAssetId, GetAssetId());
GeneralRequestBus::BroadcastResult(m_graphCanvasGraphId
, &GeneralRequests::FindGraphCanvasGraphIdByAssetId, SourceHandle(nullptr, GetAssetId().m_guid, ""));
if (!EditorGraphNotificationBus::Handler::BusIsConnected())
{
ScriptCanvas::ScriptCanvasId scriptCanvasId;
GeneralRequestBus::BroadcastResult(scriptCanvasId, &GeneralRequests::FindScriptCanvasIdByAssetId, GetAssetId());
GeneralRequestBus::BroadcastResult(scriptCanvasId
, &GeneralRequests::FindScriptCanvasIdByAssetId, SourceHandle(nullptr, GetAssetId().m_guid, ""));
EditorGraphNotificationBus::Handler::BusConnect(scriptCanvasId);
}
@@ -638,7 +638,9 @@ namespace ScriptCanvasEditor
{
if (!m_graphCanvasNodeId.IsValid())
{
AssetGraphSceneBus::BroadcastResult(m_scriptCanvasNodeId, &AssetGraphScene::FindEditorNodeIdByAssetNodeId, GetAssetId(), m_scriptCanvasAssetNodeId);
AssetGraphSceneBus::BroadcastResult(m_scriptCanvasNodeId
, &AssetGraphScene::FindEditorNodeIdByAssetNodeId
, SourceHandle(nullptr, GetAssetId().m_guid, ""), m_scriptCanvasAssetNodeId);
SceneMemberMappingRequestBus::EventResult(m_graphCanvasNodeId, m_scriptCanvasNodeId, &SceneMemberMappingRequests::GetGraphCanvasEntityId);
}
@@ -806,7 +808,8 @@ namespace ScriptCanvasEditor
{
if (!m_graphCanvasGraphId.IsValid())
{
GeneralRequestBus::BroadcastResult(m_graphCanvasGraphId, &GeneralRequests::FindGraphCanvasGraphIdByAssetId, m_graphIdentifier.m_assetId);
GeneralRequestBus::BroadcastResult(m_graphCanvasGraphId
, &GeneralRequests::FindGraphCanvasGraphIdByAssetId, SourceHandle(nullptr, m_graphIdentifier.m_assetId.m_guid, ""));
}
ScrapeInputName();
@@ -828,7 +831,7 @@ namespace ScriptCanvasEditor
if (m_graphCanvasGraphId.IsValid() && m_assetInputEndpoint.IsValid())
{
AZ::EntityId scriptCanvasNodeId;
AssetGraphSceneBus::BroadcastResult(scriptCanvasNodeId, &AssetGraphScene::FindEditorNodeIdByAssetNodeId, GetAssetId(), m_assetInputEndpoint.GetNodeId());
AssetGraphSceneBus::BroadcastResult(scriptCanvasNodeId, &AssetGraphScene::FindEditorNodeIdByAssetNodeId, SourceHandle(nullptr, GetAssetId().m_guid, ""), m_assetInputEndpoint.GetNodeId());
GraphCanvas::NodeId graphCanvasNodeId;
SceneMemberMappingRequestBus::EventResult(graphCanvasNodeId, scriptCanvasNodeId, &SceneMemberMappingRequests::GetGraphCanvasEntityId);
@@ -851,8 +854,9 @@ namespace ScriptCanvasEditor
if (m_graphCanvasGraphId.IsValid() && m_assetOutputEndpoint.IsValid())
{
AZ::EntityId scriptCanvasNodeId;
AssetGraphSceneBus::BroadcastResult(scriptCanvasNodeId, &AssetGraphScene::FindEditorNodeIdByAssetNodeId, GetAssetId(), m_assetOutputEndpoint.GetNodeId());
AssetGraphSceneBus::BroadcastResult(scriptCanvasNodeId, &AssetGraphScene::FindEditorNodeIdByAssetNodeId
, SourceHandle(nullptr, GetAssetId().m_guid, ""), m_assetOutputEndpoint.GetNodeId());
GraphCanvas::NodeId graphCanvasNodeId;
SceneMemberMappingRequestBus::EventResult(graphCanvasNodeId, scriptCanvasNodeId, &SceneMemberMappingRequests::GetGraphCanvasEntityId);
@@ -131,7 +131,12 @@ namespace ScriptCanvasEditor
AZ_CLASS_ALLOCATOR(ExecutionLogTreeItem, AZ::SystemAllocator, 0);
AZ_RTTI(ExecutionLogTreeItem, "{71139142-A30C-4A16-81CC-D51314AEAF7D}", DebugLogTreeItem);
ExecutionLogTreeItem(const LoggingDataId& loggingDataId, const ScriptCanvas::NodeTypeIdentifier& nodeType, const ScriptCanvas::GraphInfo& graphInfo, const ScriptCanvas::NamedNodeId& nodeId);
ExecutionLogTreeItem
( const LoggingDataId& loggingDataId
, const ScriptCanvas::NodeTypeIdentifier& nodeType
, const SourceHandle& graphInfo
, const ScriptCanvas::NamedNodeId& nodeId);
~ExecutionLogTreeItem() override = default;
QVariant Data(const QModelIndex& index, int role) const override final;
@@ -163,7 +168,7 @@ namespace ScriptCanvasEditor
////
const ScriptCanvas::GraphIdentifier& GetGraphIdentifier() const;
const AZ::Data::AssetId& GetAssetId() const;
AZ::Data::AssetId GetAssetId() const;
AZ::EntityId GetScriptCanvasAssetNodeId() const;
GraphCanvas::NodeId GetGraphCanvasNodeId() const;
@@ -184,7 +189,8 @@ namespace ScriptCanvasEditor
LoggingDataId m_loggingDataId;
ScriptCanvas::NodeTypeIdentifier m_nodeType;
ScriptCanvas::GraphInfo m_graphInfo;
SourceHandle m_graphInfo;
ScriptCanvas::GraphIdentifier m_graphIdentifier;
QString m_sourceEntityName;
QString m_graphName;
QString m_relativeGraphPath;
@@ -406,15 +406,14 @@ namespace ScriptCanvasEditor
sourceIndex = proxyModel->mapToSource(modelIndex);
}
PivotTreeItem* pivotTreeItem = static_cast<PivotTreeItem*>(sourceIndex.internalPointer());
if (pivotTreeItem)
if (PivotTreeItem* pivotTreeItem = static_cast<PivotTreeItem*>(sourceIndex.internalPointer()))
{
PivotTreeGraphItem* graphItem = azrtti_cast<PivotTreeGraphItem*>(pivotTreeItem);
if (graphItem)
if (PivotTreeGraphItem* graphItem = azrtti_cast<PivotTreeGraphItem*>(pivotTreeItem))
{
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAssetId, graphItem->GetAssetId());
GeneralRequestBus::Broadcast
( &GeneralRequests::OpenScriptCanvasAssetId
, SourceHandle(nullptr, graphItem->GetAssetId().m_guid, "")
, Tracker::ScriptCanvasFileState::UNMODIFIED);
}
}
}
@@ -129,7 +129,10 @@ namespace ScriptCanvasEditor
{
if (row == NodePaletteTreeItem::Column::Customization)
{
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAsset, GetSourceAssetId(), -1);
GeneralRequestBus::Broadcast
( &GeneralRequests::OpenScriptCanvasAssetId
, SourceHandle(nullptr, GetSourceAssetId().m_guid, "")
, Tracker::ScriptCanvasFileState::UNMODIFIED);
}
}
@@ -137,7 +140,10 @@ namespace ScriptCanvasEditor
{
if (row != NodePaletteTreeItem::Column::Customization)
{
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAsset, GetSourceAssetId(), -1);
GeneralRequestBus::Broadcast
( &GeneralRequests::OpenScriptCanvasAssetId
, SourceHandle(nullptr, GetSourceAssetId().m_guid, "")
, Tracker::ScriptCanvasFileState::UNMODIFIED);
return true;
}
@@ -0,0 +1,166 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <ScriptCanvas/Components/EditorUtils.h>
#include <Editor/View/Widgets/SourceHandlePropertyAssetCtrl.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/UI/PropertyEditor/Model/AssetCompleterModel.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
namespace ScriptCanvasEditor
{
SourceHandlePropertyAssetCtrl::SourceHandlePropertyAssetCtrl(QWidget* parent)
: AzToolsFramework::PropertyAssetCtrl(parent)
{
}
AzToolsFramework::AssetBrowser::AssetSelectionModel SourceHandlePropertyAssetCtrl::GetAssetSelectionModel()
{
auto selectionModel = AssetSelectionModel::SourceAssetTypeSelection(m_sourceAssetFilterPattern);
selectionModel.SetTitle(m_title);
return selectionModel;
}
void SourceHandlePropertyAssetCtrl::PopupAssetPicker()
{
// Request the AssetBrowser Dialog and set a type filter
AssetSelectionModel selection = GetAssetSelectionModel();
selection.SetSelectedFilePath(m_selectedSourcePath.c_str());
AZStd::string defaultDirectory;
if (m_defaultDirectoryCallback)
{
m_defaultDirectoryCallback->Invoke(m_editNotifyTarget, defaultDirectory);
selection.SetDefaultDirectory(defaultDirectory);
}
AssetBrowserComponentRequestBus::Broadcast(&AssetBrowserComponentRequests::PickAssets, selection, parentWidget());
if (selection.IsValid())
{
const auto source = azrtti_cast<const SourceAssetBrowserEntry*>(selection.GetResult());
AZ_Assert(source, "Incorrect entry type selected. Expected source.");
if (source)
{
SetSelectedSourcePath(source->GetFullPath());
}
}
}
void SourceHandlePropertyAssetCtrl::ClearAssetInternal()
{
SetSelectedSourcePath("");
PropertyAssetCtrl::ClearAssetInternal();
}
void SourceHandlePropertyAssetCtrl::ConfigureAutocompleter()
{
if (m_completerIsConfigured)
{
return;
}
AzToolsFramework::PropertyAssetCtrl::ConfigureAutocompleter();
AssetSelectionModel selection = GetAssetSelectionModel();
m_model->SetFetchEntryType(AssetBrowserEntry::AssetEntryType::Source);
m_model->SetFilter(selection.GetDisplayFilter());
}
void SourceHandlePropertyAssetCtrl::SetSourceAssetFilterPattern(const QString& filterPattern)
{
m_sourceAssetFilterPattern = filterPattern;
}
AZ::IO::Path SourceHandlePropertyAssetCtrl::GetSelectedSourcePath() const
{
return m_selectedSourcePath;
}
void SourceHandlePropertyAssetCtrl::SetSelectedSourcePath(const AZ::IO::Path& sourcePath)
{
m_selectedSourcePath = sourcePath;
AZStd::string displayText;
if (!sourcePath.empty())
{
AzFramework::StringFunc::Path::GetFileName(sourcePath.c_str(), displayText);
}
m_browseEdit->setText(displayText.c_str());
// The AssetID gets ignored, the only important bit is triggering the change for the RequestWrite
emit OnAssetIDChanged(AZ::Data::AssetId());
}
void SourceHandlePropertyAssetCtrl::OnAutocomplete(const QModelIndex& index)
{
SetSelectedSourcePath(m_model->GetPathFromIndex(GetSourceIndex(index)));
}
QWidget* SourceHandlePropertyHandler::CreateGUI(QWidget* pParent)
{
SourceHandlePropertyAssetCtrl* newCtrl = aznew SourceHandlePropertyAssetCtrl(pParent);
connect(newCtrl, &SourceHandlePropertyAssetCtrl::OnAssetIDChanged, this, [newCtrl](AZ::Data::AssetId newAssetID)
{
(void)newAssetID;
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestWrite, newCtrl);
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::OnEditingFinished, newCtrl);
});
return newCtrl;
}
void SourceHandlePropertyHandler::ConsumeAttribute(SourceHandlePropertyAssetCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName)
{
// Let the AssetPropertyHandlerDefault handle all of the common attributes
AzToolsFramework::AssetPropertyHandlerDefault::ConsumeAttributeInternal(GUI, attrib, attrValue, debugName);
if (attrib == AZ::Edit::Attributes::SourceAssetFilterPattern)
{
AZStd::string filterPattern;
if (attrValue->Read<AZStd::string>(filterPattern))
{
GUI->SetSourceAssetFilterPattern(filterPattern.c_str());
}
}
}
void SourceHandlePropertyHandler::WriteGUIValuesIntoProperty(size_t index, SourceHandlePropertyAssetCtrl* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node)
{
(void)index;
(void)node;
auto sourceHandle = SourceHandle(nullptr, GUI->GetSelectedSourcePath());
auto completeSourceHandle = CompleteDescription(sourceHandle);
if (completeSourceHandle)
{
instance = property_t(*CompleteDescription(sourceHandle));
}
else
{
instance = property_t();
}
}
bool SourceHandlePropertyHandler::ReadValuesIntoGUI(size_t index, SourceHandlePropertyAssetCtrl* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node)
{
(void)index;
(void)node;
GUI->blockSignals(true);
GUI->SetSelectedSourcePath(instance.Path());
GUI->SetEditNotifyTarget(node->GetParent()->GetInstance(0));
GUI->blockSignals(false);
return false;
}
}
@@ -0,0 +1,71 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx>
#include <Core/Core.h>
#endif
namespace ScriptCanvasEditor
{
class SourceHandlePropertyAssetCtrl
: public AzToolsFramework::PropertyAssetCtrl
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(SourceHandlePropertyAssetCtrl, AZ::SystemAllocator, 0);
SourceHandlePropertyAssetCtrl(QWidget* parent = nullptr);
AzToolsFramework::AssetBrowser::AssetSelectionModel GetAssetSelectionModel() override;
void PopupAssetPicker() override;
void ClearAssetInternal() override;
void ConfigureAutocompleter() override;
void SetSourceAssetFilterPattern(const QString& filterPattern);
AZ::IO::Path GetSelectedSourcePath() const;
void SetSelectedSourcePath(const AZ::IO::Path& sourcePath);
public Q_SLOTS:
void OnAutocomplete(const QModelIndex& index) override;
private:
//! A regular expression pattern for filtering by source assets
//! If this is set, the PropertyAssetCtrl will be dealing with source assets
//! instead of a specific asset type
QString m_sourceAssetFilterPattern;
AZ::IO::Path m_selectedSourcePath;
};
class SourceHandlePropertyHandler
: QObject
, public AzToolsFramework::PropertyHandler<SourceHandle, SourceHandlePropertyAssetCtrl>
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(SourceHandlePropertyHandler, AZ::SystemAllocator, 0);
AZ::u32 GetHandlerName(void) const override { return AZ_CRC_CE("SourceHandle"); }
bool IsDefaultHandler() const override { return true; }
QWidget* GetFirstInTabOrder(SourceHandlePropertyAssetCtrl* widget) override { return widget->GetFirstInTabOrder(); }
QWidget* GetLastInTabOrder(SourceHandlePropertyAssetCtrl* widget) override { return widget->GetLastInTabOrder(); }
void UpdateWidgetInternalTabbing(SourceHandlePropertyAssetCtrl* widget) override { widget->UpdateTabOrder(); }
QWidget* CreateGUI(QWidget* pParent) override;
void ConsumeAttribute(SourceHandlePropertyAssetCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override;
void WriteGUIValuesIntoProperty(size_t index, SourceHandlePropertyAssetCtrl* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
bool ReadValuesIntoGUI(size_t index, SourceHandlePropertyAssetCtrl* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
};
}
@@ -257,7 +257,10 @@ namespace ScriptCanvasEditor
if (treeItem->GetAssetId().IsValid())
{
GeneralRequestBus::Broadcast(&GeneralRequests::OpenScriptCanvasAssetId, treeItem->GetAssetId());
GeneralRequestBus::Broadcast
( &GeneralRequests::OpenScriptCanvasAssetId
, SourceHandle(nullptr, treeItem->GetAssetId().m_guid, "")
, Tracker::ScriptCanvasFileState::UNMODIFIED);
}
}
}
@@ -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, sourceAssetId);
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAssetId
, ScriptCanvasEditor::SourceHandle(nullptr, sourceUuid, {})
, Tracker::ScriptCanvasFileState::UNMODIFIED);
if (!openOutcome)
{
AZ_Warning("Script Canvas", openOutcome, "%s", openOutcome.GetError().data());
@@ -716,10 +716,7 @@ namespace ScriptCanvasEditor
void GraphVariablesModel::SetActiveScene(const ScriptCanvas::ScriptCanvasId& scriptCanvasId)
{
ScriptCanvas::GraphVariableManagerNotificationBus::Handler::BusDisconnect();
m_assetType = AZ::Data::AssetType::CreateNull();
ScriptCanvas::GraphRequestBus::EventResult(m_assetType, scriptCanvasId, &ScriptCanvas::GraphRequests::GetAssetType);
m_assetType = azrtti_typeid<ScriptCanvasAsset>();
m_scriptCanvasId = scriptCanvasId;
if (m_scriptCanvasId.IsValid())
File diff suppressed because it is too large Load Diff
@@ -43,7 +43,6 @@
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <ScriptCanvas/Core/ScriptCanvasBus.h>
#include <ScriptCanvas/Debugger/ClientTransceiver.h>
#include <Editor/Assets/ScriptCanvasAssetHolder.h>
#include <Editor/Undo/ScriptCanvasGraphCommand.h>
#include <Editor/Utilities/RecentFiles.h>
@@ -53,6 +52,7 @@
#include <Editor/View/Widgets/AssetGraphSceneDataBus.h>
#include <Editor/View/Windows/Tools/UpgradeTool/Controller.h>
#include <Editor/View/Windows/Tools/UpgradeTool/FileSaver.h>
#if SCRIPTCANVAS_EDITOR
#include <Include/EditorCoreAPI.h>
@@ -153,7 +153,7 @@ namespace ScriptCanvasEditor
}
};
//! Manages the Save/Restore operations of the user's las topened and focused graphs
//! Manages the Save/Restore operations of the user's last opened and focused graphs
class Workspace
: AssetTrackerNotificationBus::MultiHandler
{
@@ -175,9 +175,9 @@ namespace ScriptCanvasEditor
private:
void OnAssetReady(const ScriptCanvasMemoryAsset::pointer asset) override;
void SignalAssetComplete(const AZ::Data::AssetId& fileAssetId);
void SignalAssetComplete(const ScriptCanvasEditor::SourceHandle& fileAssetId);
AZ::Data::AssetId GetSourceAssetId(const AZ::Data::AssetId& memoryAssetId) const;
ScriptCanvasEditor::SourceHandle GetSourceAssetId(const ScriptCanvasEditor::SourceHandle& memoryAssetId) const;
bool m_rememberOpenCanvases;
MainWindow* m_mainWindow;
@@ -185,10 +185,10 @@ namespace ScriptCanvasEditor
//! Setting focus is problematic unless it is done until after all currently loading graphs have finished loading
//! This vector is used to track the list of graphs being opened to restore the workspace and as assets are fully
//! ready and activated they are removed from this list.
AZStd::vector<AZ::Data::AssetId> m_loadingAssets;
AZStd::vector<ScriptCanvasEditor::SourceHandle> m_loadingAssets;
//! During restore we queue the asset Id to focus in order to do it last
AZ::Data::AssetId m_queuedAssetFocus;
ScriptCanvasEditor::SourceHandle m_queuedAssetFocus;
};
enum class UnsavedChangesOptions;
@@ -230,7 +230,6 @@ namespace ScriptCanvasEditor
, private VariablePaletteRequestBus::Handler
, private ScriptCanvas::BatchOperationNotificationBus::Handler
, private AssetGraphSceneBus::Handler
, private AssetTrackerNotificationBus::MultiHandler
#if SCRIPTCANVAS_EDITOR
//, public IEditorNotifyListener
#endif
@@ -239,6 +238,7 @@ namespace ScriptCanvasEditor
, private GraphCanvas::ViewNotificationBus::Handler
, public AZ::SystemTickBus::Handler
, private AzToolsFramework::ToolsApplicationNotificationBus::Handler
, private AzToolsFramework::AssetSystemBus::Handler
, private ScriptCanvas::ScriptCanvasSettingsRequestBus::Handler
{
Q_OBJECT
@@ -269,7 +269,7 @@ namespace ScriptCanvasEditor
// Undo Handlers
void PostUndoPoint(ScriptCanvas::ScriptCanvasId scriptCanvasId) override;
void SignalSceneDirty(AZ::Data::AssetId assetId) override;
void SignalSceneDirty(ScriptCanvasEditor::SourceHandle assetId) override;
void PushPreventUndoStateUpdate() override;
void PopPreventUndoStateUpdate() override;
@@ -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 AZ::Data::AssetId& assetId, const Callbacks::OnSave& saveCB);
bool SaveAssetAsImpl(const AZ::Data::AssetId& 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
@@ -415,30 +420,27 @@ namespace ScriptCanvasEditor
void CloseNextTab();
bool IsTabOpen(const AZ::Data::AssetId& assetId, int& outTabIndex) const;
QVariant GetTabData(const AZ::Data::AssetId& assetId);
bool IsTabOpen(const SourceHandle& assetId, int& outTabIndex) const;
QVariant GetTabData(const SourceHandle& assetId);
//! GeneralRequestBus
AZ::Outcome<int, AZStd::string> OpenScriptCanvasAssetId(const AZ::Data::AssetId& assetId) override;
AZ::Outcome<int, AZStd::string> OpenScriptCanvasAsset(AZ::Data::AssetId scriptCanvasAssetId, int tabIndex = -1) override;
AZ::Outcome<int, AZStd::string> OpenScriptCanvasAsset(const ScriptCanvasMemoryAsset& scriptCanvasAsset, int tabIndex = -1);
int CloseScriptCanvasAsset(const AZ::Data::AssetId& assetId) override;
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;
bool IsScriptCanvasAssetOpen(const AZ::Data::AssetId& assetId) const override;
bool IsScriptCanvasAssetOpen(const SourceHandle& assetId) const override;
const CategoryInformation* FindNodePaletteCategoryInformation(AZStd::string_view categoryPath) const override;
const NodePaletteModelInformation* FindNodePaletteModelInformation(const ScriptCanvas::NodeTypeIdentifier& nodeType) const override;
////
AZ::Outcome<int, AZStd::string> CreateScriptCanvasAsset(AZStd::string_view assetPath, AZ::Data::AssetType assetType, int tabIndex = -1);
AZ::Outcome<int, AZStd::string> UpdateScriptCanvasAsset(const AZ::Data::Asset<ScriptCanvas::ScriptCanvasAssetBase>& scriptCanvasAsset);
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 AZ::Data::AssetId& assetId);
void OnChangeActiveGraphTab(AZ::Data::AssetId) override;
void RemoveScriptCanvasAsset(const ScriptCanvasEditor::SourceHandle& assetId);
void OnChangeActiveGraphTab(ScriptCanvasEditor::SourceHandle) override;
void CreateNewRuntimeAsset() override { OnFileNew(); }
@@ -448,8 +450,8 @@ namespace ScriptCanvasEditor
GraphCanvas::GraphId GetGraphCanvasGraphId(const ScriptCanvas::ScriptCanvasId& scriptCanvasId) const override;
GraphCanvas::GraphId FindGraphCanvasGraphIdByAssetId(const AZ::Data::AssetId& assetId) const override;
ScriptCanvas::ScriptCanvasId FindScriptCanvasIdByAssetId(const AZ::Data::AssetId& assetId) const override;
GraphCanvas::GraphId FindGraphCanvasGraphIdByAssetId(const ScriptCanvasEditor::SourceHandle& assetId) const override;
ScriptCanvas::ScriptCanvasId FindScriptCanvasIdByAssetId(const ScriptCanvasEditor::SourceHandle& assetId) const override;
bool IsInUndoRedo(const AZ::EntityId& graphCanvasGraphId) const override;
bool IsScriptCanvasInUndoRedo(const ScriptCanvas::ScriptCanvasId& scriptCanvasId) const override;
@@ -517,17 +519,18 @@ namespace ScriptCanvasEditor
QObject* FindElementByName(QString elementName) override;
////
AZ::EntityId FindEditorNodeIdByAssetNodeId(const AZ::Data::AssetId& assetId, AZ::EntityId assetNodeId) const override;
AZ::EntityId FindAssetNodeIdByEditorNodeId(const AZ::Data::AssetId& assetId, AZ::EntityId editorNodeId) const override;
AZ::EntityId FindEditorNodeIdByAssetNodeId(const ScriptCanvasEditor::SourceHandle& assetId, AZ::EntityId assetNodeId) const override;
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;
/////////////////////////////////////////////////////////////////////////////////////////////
void UpdateWorkspaceStatus(const ScriptCanvasMemoryAsset& scriptCanvasAsset);
GraphCanvas::Endpoint HandleProposedConnection(const GraphCanvas::GraphId& graphId, const GraphCanvas::ConnectionId& connectionId, const GraphCanvas::Endpoint& endpoint, const GraphCanvas::NodeId& proposedNode, const QPoint& screenPoint);
//! UndoNotificationBus
@@ -543,29 +546,20 @@ 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 AZ::Data::AssetId& assetId, AZStd::string& filePath, AZStd::string& fileFilter);
void MarkAssetModified(const AZ::Data::AssetId& assetId);
void UpdateFileState(const ScriptCanvasEditor::SourceHandle& assetId, Tracker::ScriptCanvasFileState fileState);
// QMainWindow
void closeEvent(QCloseEvent *event) override;
UnsavedChangesOptions ShowSaveDialog(const QString& filename);
bool ActivateAndSaveAsset(const AZ::Data::AssetId& unsavedAssetId, const Callbacks::OnSave& onSave);
bool ActivateAndSaveAsset(const ScriptCanvasEditor::SourceHandle& unsavedAssetId);
void SaveNewAsset(AZStd::string_view path, AZ::Data::AssetId assetId, const Callbacks::OnSave& onSave);
void SaveAsset(AZ::Data::AssetId assetId, const Callbacks::OnSave& onSave);
void SaveAs(AZStd::string_view path, ScriptCanvasEditor::SourceHandle assetId);
void OpenFile(const char* fullPath);
void CreateMenus();
void SignalActiveSceneChanged(const AZ::Data::AssetId assetId);
void SaveWorkspace(bool updateAssetList = true);
void RestoreWorkspace();
void SignalActiveSceneChanged(const ScriptCanvasEditor::SourceHandle assetId);
void RunUpgradeTool();
@@ -593,29 +587,27 @@ namespace ScriptCanvasEditor
void UpdateMenuState(bool enabledState);
void OnWorkspaceRestoreStart();
void OnWorkspaceRestoreEnd(AZ::Data::AssetId lastFocusAsset);
void OnWorkspaceRestoreEnd(ScriptCanvasEditor::SourceHandle lastFocusAsset);
void UpdateAssignToSelectionState();
void UpdateUndoRedoState();
void UpdateSaveState();
void UpdateSaveState(bool enabled);
void CreateFunctionInput();
void CreateFunctionOutput();
void CreateFunctionDefinitionNode(int positionOffset);
int CreateAssetTab(const AZ::Data::AssetId& 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 AZ::Data::AssetId& assetId);
void SetActiveAsset(const ScriptCanvasEditor::SourceHandle& assetId);
void RefreshActiveAsset();
void ReconnectSceneBuses(AZ::Data::AssetId previousAssetId, AZ::Data::AssetId nextAssetId);
void SignalBatchOperationComplete(BatchOperatorTool* batchTool);
void ReconnectSceneBuses(ScriptCanvasEditor::SourceHandle previousAssetId, ScriptCanvasEditor::SourceHandle nextAssetId);
void PrepareActiveAssetForSave();
void PrepareAssetForSave(const AZ::Data::AssetId& asssetId);
void PrepareAssetForSave(const ScriptCanvasEditor::SourceHandle& asssetId);
void RestartAutoTimerSave(bool forceTimer = false);
@@ -626,24 +618,16 @@ namespace ScriptCanvasEditor
void AssignGraphToEntityImpl(const AZ::EntityId& entityId);
////
Tracker::ScriptCanvasFileState GetAssetFileState(AZ::Data::AssetId assetId) const;
Tracker::ScriptCanvasFileState GetAssetFileState(ScriptCanvasEditor::SourceHandle assetId) const;
AZ::Data::AssetId GetSourceAssetId(const AZ::Data::AssetId& memoryAssetId) const
ScriptCanvasEditor::SourceHandle GetSourceAssetId(const ScriptCanvasEditor::SourceHandle& memoryAssetId) const
{
ScriptCanvasMemoryAsset::pointer memoryAsset;
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, memoryAssetId);
if (memoryAsset)
{
return memoryAsset->GetFileAssetId();
}
return AZ::Data::AssetId();
return memoryAssetId;
}
int InsertTabForAsset(AZStd::string_view assetPath, AZ::Data::AssetId assetId, int tabIndex = -1);
int InsertTabForAsset(AZStd::string_view assetPath, ScriptCanvasEditor::SourceHandle assetId, int tabIndex = -1);
void UpdateUndoCache(AZ::Data::AssetId assetId);
void UpdateUndoCache(ScriptCanvasEditor::SourceHandle assetId);
bool HasSystemTickAction(SystemTickActionFlag action);
@@ -655,34 +639,9 @@ namespace ScriptCanvasEditor
void OpenNextFile();
template <typename GraphAssetType, typename AssetHandler>
void MakeNewFile()
{
static int scriptCanvasEditorDefaultNewNameCount = 0;
AZStd::string newAssetName = AZStd::string::format(ScriptCanvas::AssetDescription::GetAssetNamePattern<GraphAssetType>(), ++scriptCanvasEditorDefaultNewNameCount);
AZStd::array<char, AZ::IO::MaxPathLength> assetRootArray;
if (!AZ::IO::FileIOBase::GetInstance()->ResolvePath(ScriptCanvas::AssetDescription::GetSuggestedSavePath<GraphAssetType>(), assetRootArray.data(), assetRootArray.size()))
{
AZ_ErrorOnce("Script Canvas", false, "Unable to resolve @projectroot@ path");
}
AZStd::string assetPath;
AzFramework::StringFunc::Path::Join(assetRootArray.data(), (newAssetName + ScriptCanvas::AssetDescription::GetExtension<GraphAssetType>()).data(), assetPath);
auto createOutcome = CreateScriptCanvasAsset(assetPath, azrtti_typeid<GraphAssetType>());
if (createOutcome)
{
}
else
{
AZ_Warning("Script Canvas", createOutcome, "%s", createOutcome.GetError().data());
}
}
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;
@@ -741,22 +700,22 @@ namespace ScriptCanvasEditor
GraphCanvas::GraphCanvasEditorEmptyDockWidget* m_emptyCanvas; // Displayed when there is no open graph
QVBoxLayout* m_layout;
AZ::Data::AssetId m_activeAssetId;
ScriptCanvasEditor::SourceHandle m_activeGraph;
bool m_loadingNewlySavedFile;
AZStd::string m_newlySavedFile;
AZStd::string m_errorFilePath;
bool m_isClosingTabs;
AZ::Data::AssetId m_skipTabOnClose;
ScriptCanvasEditor::SourceHandle m_skipTabOnClose;
bool m_enterState;
bool m_ignoreSelection;
AZ::s32 m_preventUndoStateUpdateCount;
bool m_isRestoringWorkspace;
AZ::Data::AssetId m_queuedFocusOverride;
ScriptCanvasEditor::SourceHandle m_queuedFocusOverride;
Ui::MainWindow* ui;
AZStd::array<AZStd::pair<QAction*, QMetaObject::Connection>, c_scriptCanvasEditorSettingsRecentFilesCountMax> m_recentActions;
@@ -778,17 +737,17 @@ namespace ScriptCanvasEditor
AZStd::vector<AZ::EntityId> m_selectedVariableIds;
AZ::u32 m_systemTickActions;
AZStd::unordered_set< AZ::Data::AssetId > m_processedClosedAssetIds;
AZStd::unordered_set< ScriptCanvasEditor::SourceHandle > m_processedClosedAssetIds;
AZStd::unordered_set< AZ::Data::AssetId > m_loadingWorkspaceAssets;
AZStd::unordered_set< AZ::Data::AssetId > m_loadingAssets;
AZStd::unordered_set< ScriptCanvasEditor::SourceHandle > m_loadingWorkspaceAssets;
AZStd::unordered_set< ScriptCanvasEditor::SourceHandle > m_loadingAssets;
AZStd::unordered_set< AZ::Uuid > m_variablePaletteTypes;
AZStd::unordered_map< AZ::Crc32, QObject* > m_automationLookUpMap;
bool m_closeCurrentGraphAfterSave;
AZStd::unordered_map< AZ::Data::AssetId, TypeDefs::EntityComponentId > m_assetCreationRequests;
AZStd::unordered_map< ScriptCanvasEditor::SourceHandle, TypeDefs::EntityComponentId > m_assetCreationRequests;
ScriptCanvas::Debugger::ClientTransceiver m_clientTRX;
GraphCanvas::StyleManager m_styleManager;
@@ -797,6 +756,14 @@ namespace ScriptCanvasEditor
//! this object manages the Save/Restore operations
Workspace* m_workspace;
void OnSaveCallback(bool saveSuccess, AZ::Data::AssetPtr, AZ::Data::AssetId previousFileAssetId);
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;
};
}
@@ -53,7 +53,6 @@ namespace ScriptCanvasEditor
m_view->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn);
connect(m_view->scanButton, &QPushButton::pressed, this, &Controller::OnButtonPressScan);
connect(m_view->closeButton, &QPushButton::pressed, this, &Controller::OnButtonPressClose);
m_view->upgradeAllButton->setVisible(false);
connect(m_view->upgradeAllButton, &QPushButton::pressed, this, &Controller::OnButtonPressUpgrade);
m_view->progressBar->setValue(0);
m_view->progressBar->setVisible(false);
@@ -104,9 +103,9 @@ namespace ScriptCanvasEditor
}
}
QList<QTableWidgetItem*> Controller::FindTableItems(const AZ::Data::AssetInfo& info)
QList<QTableWidgetItem*> Controller::FindTableItems(const SourceHandle& info)
{
return m_view->tableWidget->findItems(info.m_relativePath.c_str(), Qt::MatchFlag::MatchExactly);
return m_view->tableWidget->findItems(info.Path().c_str(), Qt::MatchFlag::MatchExactly);
}
void Controller::OnButtonPressClose()
@@ -117,30 +116,20 @@ namespace ScriptCanvasEditor
void Controller::OnButtonPressScan()
{
// \todo move to another file
auto isUpToDate = [this](AZ::Data::Asset<AZ::Data::AssetData> asset)
auto isUpToDate = [this](const SourceHandle& asset)
{
AZ::Entity* scriptCanvasEntity = nullptr;
auto graphComponent = asset.Get();
if (asset.GetType() == azrtti_typeid<ScriptCanvasAsset>())
{
ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs<ScriptCanvasAsset>();
if (!scriptCanvasAsset)
{
AZ_Warning
(ScriptCanvas::k_VersionExplorerWindow.data()
, false
, "InspectAsset: %s, AsestData failed to return ScriptCanvasAsset"
, asset.GetHint().c_str());
return true;
}
AZ_Warning
( ScriptCanvas::k_VersionExplorerWindow.data()
, asset.Get() != nullptr
, "InspectAsset: %s, failed to load valid graph"
, asset.Path().c_str());
scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity();
AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity");
}
auto graphComponent = scriptCanvasEntity->FindComponent<ScriptCanvasEditor::Graph>();
AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component");
return !m_view->forceUpgrade->isChecked() && graphComponent->GetVersion().IsLatest();
return graphComponent
&& (!graphComponent->GetVersion().IsLatest() || m_view->forceUpgrade->isChecked())
? ScanConfiguration::Filter::Include
: ScanConfiguration::Filter::Exclude;
};
ScanConfiguration config;
@@ -156,59 +145,19 @@ namespace ScriptCanvasEditor
OnButtonPressUpgradeImplementation({});
}
void Controller::OnButtonPressUpgradeImplementation(const AZ::Data::AssetInfo& assetInfo)
void Controller::OnButtonPressUpgradeImplementation(const SourceHandle& assetInfo)
{
auto simpleUpdate = [this](AZ::Data::Asset<AZ::Data::AssetData> asset)
auto simpleUpdate = [this](SourceHandle& asset)
{
if (asset.GetType() == azrtti_typeid<ScriptCanvasAsset>())
AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), asset.Get() != nullptr
, "The Script Canvas asset must have a Graph component");
if (asset.Get())
{
ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs<ScriptCanvasAsset>();
AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s"
, azrtti_typeid<ScriptCanvasAsset>().template ToString<AZStd::string>().c_str());
if (!scriptCanvasAsset)
{
return;
}
AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity();
AZ_Assert(scriptCanvasEntity, "View::UpgradeGraph The Script Canvas asset must have a valid entity");
if (!scriptCanvasEntity)
{
return;
}
AZ::Entity* queryEntity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId());
if (queryEntity)
{
if (queryEntity->GetState() == AZ::Entity::State::Active)
{
queryEntity->Deactivate();
}
scriptCanvasEntity = queryEntity;
}
if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed)
{
scriptCanvasEntity->Init();
}
if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init)
{
scriptCanvasEntity->Activate();
}
AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active");
auto graphComponent = scriptCanvasEntity->FindComponent<ScriptCanvasEditor::Graph>();
AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component");
if (graphComponent)
{
graphComponent->UpgradeGraph
(asset
, m_view->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate
, m_view->verbose->isChecked());
}
asset.Mod()->UpgradeGraph
( asset
, m_view->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate
, m_view->verbose->isChecked());
}
};
@@ -216,7 +165,7 @@ namespace ScriptCanvasEditor
{
int result = QMessageBox::No;
QMessageBox mb
(QMessageBox::Warning
( QMessageBox::Warning
, QObject::tr("Failed to Save Upgraded File")
, QObject::tr("The upgraded file could not be saved because the file is read only.\n"
"Do you want to make it writeable and overwrite it?")
@@ -235,12 +184,12 @@ namespace ScriptCanvasEditor
ModelRequestsBus::Broadcast(&ModelRequestsTraits::Modify, config);
}
void Controller::OnButtonPressUpgradeSingle(const AZ::Data::AssetInfo& assetInfo)
void Controller::OnButtonPressUpgradeSingle(const SourceHandle& info)
{
OnButtonPressUpgradeImplementation(assetInfo);
OnButtonPressUpgradeImplementation(info);
}
void Controller::OnUpgradeModificationBegin([[maybe_unused]] const ModifyConfiguration& config, const AZ::Data::AssetInfo& info)
void Controller::OnUpgradeModificationBegin([[maybe_unused]] const ModifyConfiguration& config, const SourceHandle& info)
{
for (auto* item : FindTableItems(info))
{
@@ -252,16 +201,16 @@ namespace ScriptCanvasEditor
void Controller::OnUpgradeModificationEnd
( [[maybe_unused]] const ModifyConfiguration& config
, const AZ::Data::AssetInfo& info
, const SourceHandle& info
, ModificationResult result)
{
if (result.errorMessage.empty())
{
VE_LOG("Successfully modified %s", result.assetInfo.m_relativePath.c_str());
VE_LOG("Successfully modified %s", result.asset.Path().c_str());
}
else
{
VE_LOG("Failed to modify %s: %s", result.assetInfo.m_relativePath.c_str(), result.errorMessage.data());
VE_LOG("Failed to modify %s: %s", result.asset.Path().c_str(), result.errorMessage.data());
}
for (auto* item : FindTableItems(info))
@@ -289,12 +238,10 @@ namespace ScriptCanvasEditor
AddLogEntries();
}
void Controller::OnGraphUpgradeComplete(AZ::Data::Asset<AZ::Data::AssetData>& asset, bool skipped)
void Controller::OnGraphUpgradeComplete(ScriptCanvasEditor::SourceHandle& asset, bool skipped)
{
ModificationResult result;
result.asset = asset;
AZ::Data::AssetCatalogRequestBus::BroadcastResult
( result.assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, asset.GetId());
if (skipped)
{
@@ -342,19 +289,19 @@ namespace ScriptCanvasEditor
}
}
void Controller::OnScanFilteredGraph(const AZ::Data::AssetInfo& info)
void Controller::OnScanFilteredGraph(const SourceHandle& info)
{
OnScannedGraph(info, Filtered::Yes);
}
void Controller::OnScannedGraph(const AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] Filtered filtered)
void Controller::OnScannedGraph(const SourceHandle& assetInfo, [[maybe_unused]] Filtered filtered)
{
const int rowIndex = m_view->tableWidget->rowCount();
if (filtered == Filtered::No || !m_view->onlyShowOutdated->isChecked())
{
m_view->tableWidget->insertRow(rowIndex);
QTableWidgetItem* rowName = new QTableWidgetItem(tr(assetInfo.m_relativePath.c_str()));
QTableWidgetItem* rowName = new QTableWidgetItem(tr(assetInfo.Path().c_str()));
m_view->tableWidget->setItem(rowIndex, static_cast<int>(ColumnAsset), rowName);
SetRowSucceeded(rowIndex);
@@ -376,17 +323,11 @@ namespace ScriptCanvasEditor
m_view->tableWidget->setCellWidget(rowIndex, static_cast<int>(ColumnAction), upgradeButton);
}
char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 };
AZStd::string path = AZStd::string::format("@devroot@/%s", assetInfo.m_relativePath.c_str());
AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN);
AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path);
AZ::StringFunc::Path::Normalize(path);
bool result = false;
AZ::Data::AssetInfo info;
AZStd::string watchFolder;
QByteArray assetNameUtf8 = assetInfo.m_relativePath.c_str();
QByteArray assetNameUtf8 = assetInfo.Path().c_str();
AzToolsFramework::AssetSystemRequestBus::BroadcastResult
( result
, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath
@@ -413,41 +354,41 @@ namespace ScriptCanvasEditor
OnScannedGraphResult(assetInfo);
}
void Controller::OnScannedGraphResult([[maybe_unused]] const AZ::Data::AssetInfo& info)
void Controller::OnScannedGraphResult([[maybe_unused]] const SourceHandle& info)
{
m_view->progressBar->setValue(aznumeric_cast<int>(m_handledAssetCount));
++m_handledAssetCount;
AddLogEntries();
}
void Controller::OnScanLoadFailure(const AZ::Data::AssetInfo& info)
void Controller::OnScanLoadFailure(const SourceHandle& info)
{
const int rowIndex = m_view->tableWidget->rowCount();
m_view->tableWidget->insertRow(rowIndex);
QTableWidgetItem* rowName = new QTableWidgetItem
( tr(AZStd::string::format("Load Error: %s", info.m_relativePath.c_str()).c_str()));
( tr(AZStd::string::format("Load Error: %s", info.Path().c_str()).c_str()));
m_view->tableWidget->setItem(rowIndex, static_cast<int>(ColumnAsset), rowName);
SetRowFailed(rowIndex, "Load failed");
OnScannedGraphResult(info);
}
void Controller::OnScanUnFilteredGraph(const AZ::Data::AssetInfo& info)
void Controller::OnScanUnFilteredGraph(const SourceHandle& info)
{
OnScannedGraph(info, Filtered::No);
}
void Controller::OnUpgradeBegin
( const ModifyConfiguration& config
, [[maybe_unused]] const WorkingAssets& assets)
, [[maybe_unused]] const AZStd::vector<SourceHandle>& assets)
{
QString spinnerText = QStringLiteral("Upgrade in progress - ");
if (config.modifySingleAsset.m_assetId.IsValid())
if (!config.modifySingleAsset.Path().empty())
{
spinnerText.append(" single graph");
if (assets.size() == 1)
{
for (auto* item : FindTableItems(assets.front().info))
for (auto* item : FindTableItems(assets.front()))
{
int row = item->row();
SetRowBusy(row);
@@ -498,7 +439,7 @@ namespace ScriptCanvasEditor
m_view->scanButton->setEnabled(true);
}
void Controller::OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result)
void Controller::OnUpgradeDependenciesGathered(const SourceHandle& info, Result result)
{
for (auto* item : FindTableItems(info))
{
@@ -527,7 +468,7 @@ namespace ScriptCanvasEditor
void Controller::OnUpgradeDependencySortBegin
( [[maybe_unused]] const ModifyConfiguration& config
, const WorkingAssets& assets)
, const AZStd::vector<SourceHandle>& assets)
{
m_handledAssetCount = 0;
m_view->progressBar->setVisible(true);
@@ -553,7 +494,7 @@ namespace ScriptCanvasEditor
void Controller::OnUpgradeDependencySortEnd
( [[maybe_unused]] const ModifyConfiguration& config
, const WorkingAssets& assets
, const AZStd::vector<SourceHandle>& assets
, [[maybe_unused]] const AZStd::vector<size_t>& sortedOrder)
{
m_handledAssetCount = 0;
@@ -65,36 +65,36 @@ namespace ScriptCanvasEditor
void AddLogEntries();
void EnableAllUpgradeButtons();
QList<QTableWidgetItem*> FindTableItems(const AZ::Data::AssetInfo& assetInfo);
QList<QTableWidgetItem*> FindTableItems(const SourceHandle& assetInfo);
void OnButtonPressClose();
void OnButtonPressScan();
void OnButtonPressUpgrade();
void OnButtonPressUpgradeImplementation(const AZ::Data::AssetInfo& assetInfo);
void OnButtonPressUpgradeSingle(const AZ::Data::AssetInfo& assetInfo);
void OnButtonPressUpgradeImplementation(const SourceHandle& assetInfo);
void OnButtonPressUpgradeSingle(const SourceHandle& assetInfo);
void OnGraphUpgradeComplete(AZ::Data::Asset<AZ::Data::AssetData>&, bool skipped) override;
void OnGraphUpgradeComplete(SourceHandle&, bool skipped) override;
void OnScanBegin(size_t assetCount) override;
void OnScanComplete(const ScanResult& result) override;
void OnScanFilteredGraph(const AZ::Data::AssetInfo& info) override;
void OnScanLoadFailure(const AZ::Data::AssetInfo& info) override;
void OnScanUnFilteredGraph(const AZ::Data::AssetInfo& info) override;
void OnScanFilteredGraph(const SourceHandle& info) override;
void OnScanLoadFailure(const SourceHandle& info) override;
void OnScanUnFilteredGraph(const SourceHandle& info) override;
enum class Filtered { No, Yes };
void OnScannedGraph(const AZ::Data::AssetInfo& info, Filtered filtered);
void OnScannedGraphResult(const AZ::Data::AssetInfo& info);
void OnScannedGraph(const SourceHandle& info, Filtered filtered);
void OnScannedGraphResult(const SourceHandle& info);
// for single operation UI updates, just check the assets size, or note it on the request
void OnUpgradeBegin(const ModifyConfiguration& config, const WorkingAssets& assets) override;
void OnUpgradeBegin(const ModifyConfiguration& config, const AZStd::vector<SourceHandle>& assets) override;
void OnUpgradeComplete(const ModificationResults& results) override;
void OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result) override;
void OnUpgradeDependencySortBegin(const ModifyConfiguration& config, const WorkingAssets& assets) override;
void OnUpgradeDependenciesGathered(const SourceHandle& info, Result result) override;
void OnUpgradeDependencySortBegin(const ModifyConfiguration& config, const AZStd::vector<SourceHandle>& assets) override;
void OnUpgradeDependencySortEnd
( const ModifyConfiguration& config
, const WorkingAssets& assets
, const AZStd::vector<SourceHandle>& assets
, const AZStd::vector<size_t>& sortedOrder) override;
void OnUpgradeModificationBegin(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info) override;
void OnUpgradeModificationEnd(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info, ModificationResult result) override;
void OnUpgradeModificationBegin(const ModifyConfiguration& config, const SourceHandle& info) override;
void OnUpgradeModificationEnd(const ModifyConfiguration& config, const SourceHandle& info, ModificationResult result) override;
void SetLoggingPreferences();
void SetSpinnerIsBusy(bool isBusy);
@@ -15,6 +15,7 @@
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
#include <Editor/View/Windows/Tools/UpgradeTool/FileSaver.h>
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
namespace FileSaverCpp
{
@@ -58,6 +59,11 @@ namespace ScriptCanvasEditor
, m_onComplete(onComplete)
{}
const SourceHandle& FileSaver::GetSource() const
{
return m_source;
}
void FileSaver::PerformMove
( AZStd::string tmpFileName
, AZStd::string target
@@ -70,7 +76,7 @@ namespace ScriptCanvasEditor
AZ::SystemTickBus::QueueFunction([this, tmpFileName]()
{
FileSaveResult result;
result.fileSaveError = "Failed to move updated file from temporary location to tmpFileName destination";
result.fileSaveError = "Failed to move updated file from temporary location to original destination.";
result.tempFileRemovalError = RemoveTempFile(tmpFileName);
m_onComplete(result);
});
@@ -98,7 +104,9 @@ namespace ScriptCanvasEditor
auto streamer = AZ::Interface<AZ::IO::IStreamer>::Get();
AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str());
// Bump the slice asset up in the asset processor's queue.
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str());
AzFramework::AssetSystemRequestBus::Broadcast
(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str());
AZ::SystemTickBus::QueueFunction([this, tmpFileName]()
{
FileSaveResult result;
@@ -108,28 +116,29 @@ namespace ScriptCanvasEditor
}
else
{
AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to tmpFileName destination failed: %s, trying again", target.c_str());
AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false
, "moving converted file to tmpFileName destination failed: %s, trying again", target.c_str());
auto streamer = AZ::Interface<AZ::IO::IStreamer>::Get();
AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str());
streamer->SetRequestCompleteCallback(flushRequest, [this, tmpFileName, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request)
streamer->SetRequestCompleteCallback(flushRequest
, [this, tmpFileName, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request)
{
// Continue saving.
AZ::SystemTickBus::QueueFunction([this, tmpFileName, target, remainingAttempts]() { PerformMove(tmpFileName, target, remainingAttempts - 1); });
AZ::SystemTickBus::QueueFunction(
[this, tmpFileName, target, remainingAttempts]() { PerformMove(tmpFileName, target, remainingAttempts - 1); });
});
streamer->QueueRequest(flushRequest);
}
}
}
void FileSaver::OnSourceFileReleased(AZ::Data::Asset<AZ::Data::AssetData> asset)
void FileSaver::OnSourceFileReleased(const SourceHandle& source)
{
AZStd::string relativePath, fullPath;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId());
bool fullPathFound = false;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath);
AZStd::string fullPath = source.Path().c_str();
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.
// 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(fullPath.c_str(), tmpFileName))
{
FileSaveResult result;
@@ -138,23 +147,24 @@ namespace ScriptCanvasEditor
return;
}
bool tempSavedSucceeded = false;
AZStd::string saveError;
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>())
auto saveOutcome = ScriptCanvasEditor::SaveToStream(source, fileStream);
if (!saveOutcome.IsSuccess())
{
ScriptCanvasEditor::ScriptCanvasAssetHandler handler;
tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream);
saveError = saveOutcome.TakeError();
}
fileStream.Close();
}
if (!tempSavedSucceeded)
if (!saveError.empty())
{
FileSaveResult result;
result.fileSaveError = "Save asset data to temporary file failed";
result.fileSaveError = AZStd::string::format("Save asset data to temporary file failed: %s", saveError.c_str());
m_onComplete(result);
return;
}
@@ -164,26 +174,26 @@ namespace ScriptCanvasEditor
, fullPath.c_str()
, true
, [this, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info)
{
constexpr const size_t k_maxAttemps = 10;
{
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);
}
});
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)
@@ -191,7 +201,7 @@ namespace ScriptCanvasEditor
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,30 +212,30 @@ namespace ScriptCanvasEditor
return "";
}
void FileSaver::Save(AZ::Data::Asset<AZ::Data::AssetData> asset)
void FileSaver::Save(const SourceHandle& source)
{
AZStd::string relativePath, fullPath;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId());
bool fullPathFound = false;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult
(fullPathFound
, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath
, relativePath, fullPath);
m_source = source;
if (!fullPathFound)
if (source.Path().empty())
{
FileSaveResult result;
result.fileSaveError = "Full source path not found";
result.fileSaveError = "No save location specified";
m_onComplete(result);
}
else
{
auto streamer = AZ::Interface<AZ::IO::IStreamer>::Get();
AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath);
streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request)
AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(source.Path().c_str());
streamer->SetRequestCompleteCallback(flushRequest, [this]([[maybe_unused]] AZ::IO::FileRequestHandle request)
{
this->OnSourceFileReleased(asset);
AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
if (!m_sourceFileReleased)
{
m_sourceFileReleased = true;
AZ::SystemTickBus::QueueFunction([this]() { this->OnSourceFileReleased(m_source); });
}
});
streamer->QueueRequest(flushRequest);
}
}
@@ -29,14 +29,19 @@ namespace ScriptCanvasEditor
( AZStd::function<bool()> onReadOnlyFile
, AZStd::function<void(const FileSaveResult& result)> onComplete);
void Save(AZ::Data::Asset<AZ::Data::AssetData> asset);
const SourceHandle& GetSource() const;
void Save(const SourceHandle& source);
private:
AZStd::mutex m_mutex;
bool m_sourceFileReleased = false;
SourceHandle m_source;
AZStd::function<void(const FileSaveResult& result)> m_onComplete;
AZStd::function<bool()> m_onReadOnlyFile;
void OnSourceFileReleased(AZ::Data::Asset<AZ::Data::AssetData> asset);
void OnSourceFileReleased(const SourceHandle& source);
void PerformMove
( AZStd::string source
, AZStd::string target
@@ -101,7 +101,7 @@ namespace ScriptCanvasEditor
return;
}
if (modification.modifySingleAsset.m_assetId.IsValid())
if (!modification.modifySingleAsset.Path().empty())
{
const auto& results = m_scanner->GetResult();
auto iter = AZStd::find_if
@@ -109,7 +109,7 @@ namespace ScriptCanvasEditor
, results.m_unfiltered.end()
, [&modification](const auto& candidate)
{
return candidate.info.m_assetId == modification.modifySingleAsset.m_assetId;
return candidate.AnyEquals(modification.modifySingleAsset);
});
if (iter == results.m_unfiltered.end())
@@ -120,7 +120,7 @@ namespace ScriptCanvasEditor
m_state = State::ModifySingle;
m_modifier = AZStd::make_unique<Modifier>(modification, WorkingAssets{ *iter }, [this]() { OnModificationComplete(); });
m_modifier = AZStd::make_unique<Modifier>(modification, AZStd::vector<SourceHandle>{ *iter }, [this]() { OnModificationComplete(); });
}
else
{
@@ -9,53 +9,51 @@
#include <AzCore/EBus/EBus.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <ScriptCanvas/Core/Core.h>
namespace ScriptCanvasEditor
{
namespace VersionExplorer
{
struct WorkingAsset
{
AZ::Data::Asset<AZ::Data::AssetData> asset;
AZ::Data::AssetInfo info;
};
using WorkingAssets = AZStd::vector<WorkingAsset>;
struct ModifyConfiguration
{
AZStd::function<void(AZ::Data::Asset<AZ::Data::AssetData>)> modification;
AZStd::function<void(SourceHandle&)> modification;
AZStd::function<bool()> onReadOnlyFile;
AZ::Data::AssetInfo modifySingleAsset;
SourceHandle modifySingleAsset;
bool backupGraphBeforeModification = false;
bool successfulDependencyUpgradeRequired = true;
};
struct ModificationResult
{
AZ::Data::Asset<AZ::Data::AssetData> asset;
AZ::Data::AssetInfo assetInfo;
SourceHandle asset;
AZStd::string errorMessage;
};
struct ModificationResults
{
AZStd::vector<AZ::Data::AssetInfo> m_successes;
AZStd::vector<SourceHandle> m_successes;
AZStd::vector<ModificationResult> m_failures;
};
struct ScanConfiguration
{
AZStd::function<bool(AZ::Data::Asset<AZ::Data::AssetData>)> filter;
enum class Filter
{
Include,
Exclude
};
AZStd::function<Filter(const SourceHandle&)> filter;
bool reportFilteredGraphs = false;
};
struct ScanResult
{
AZStd::vector<AZ::Data::AssetInfo> m_catalogAssets;
WorkingAssets m_unfiltered;
AZStd::vector<AZ::Data::AssetInfo> m_filteredAssets;
AZStd::vector<AZ::Data::AssetInfo> m_loadErrors;
AZStd::vector<SourceHandle> m_catalogAssets;
AZStd::vector<SourceHandle> m_unfiltered;
AZStd::vector<SourceHandle> m_filteredAssets;
AZStd::vector<SourceHandle> m_loadErrors;
};
enum Result
@@ -88,20 +86,20 @@ namespace ScriptCanvasEditor
public:
virtual void OnScanBegin(size_t assetCount) = 0;
virtual void OnScanComplete(const ScanResult& result) = 0;
virtual void OnScanFilteredGraph(const AZ::Data::AssetInfo& info) = 0;
virtual void OnScanLoadFailure(const AZ::Data::AssetInfo& info) = 0;
virtual void OnScanUnFilteredGraph(const AZ::Data::AssetInfo& info) = 0;
virtual void OnScanFilteredGraph(const SourceHandle& info) = 0;
virtual void OnScanLoadFailure(const SourceHandle& info) = 0;
virtual void OnScanUnFilteredGraph(const SourceHandle& info) = 0;
virtual void OnUpgradeBegin(const ModifyConfiguration& config, const WorkingAssets& assets) = 0;
virtual void OnUpgradeBegin(const ModifyConfiguration& config, const AZStd::vector<SourceHandle>& assets) = 0;
virtual void OnUpgradeComplete(const ModificationResults& results) = 0;
virtual void OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result) = 0;
virtual void OnUpgradeDependencySortBegin(const ModifyConfiguration& config, const WorkingAssets& assets) = 0;
virtual void OnUpgradeDependenciesGathered(const SourceHandle& info, Result result) = 0;
virtual void OnUpgradeDependencySortBegin(const ModifyConfiguration& config, const AZStd::vector<SourceHandle>& assets) = 0;
virtual void OnUpgradeDependencySortEnd
( const ModifyConfiguration& config
, const WorkingAssets& assets
, const AZStd::vector<SourceHandle>& assets
, const AZStd::vector<size_t>& sortedOrder) = 0;
virtual void OnUpgradeModificationBegin(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info) = 0;
virtual void OnUpgradeModificationEnd(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info, ModificationResult result) = 0;
virtual void OnUpgradeModificationBegin(const ModifyConfiguration& config, const SourceHandle& info) = 0;
virtual void OnUpgradeModificationEnd(const ModifyConfiguration& config, const SourceHandle& info, ModificationResult result) = 0;
};
using ModelNotificationsBus = AZ::EBus<ModelNotificationsTraits>;
}
@@ -6,24 +6,21 @@
*
*/
#include <Editor/Include/ScriptCanvas/Components/EditorGraph.h>
#include <Editor/View/Windows/Tools/UpgradeTool/LogTraits.h>
#include <Editor/View/Windows/Tools/UpgradeTool/Modifier.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
#include <ScriptCanvas/Core/Graph.h>
namespace ModifierCpp
{
}
namespace ScriptCanvasEditor
{
namespace VersionExplorer
{
Modifier::Modifier
( const ModifyConfiguration& modification
, WorkingAssets&& assets
, AZStd::vector<SourceHandle>&& assets
, AZStd::function<void()> onComplete)
: m_state(State::GatheringDependencies)
, m_config(modification)
@@ -35,11 +32,12 @@ namespace ScriptCanvasEditor
AZ::SystemTickBus::Handler::BusConnect();
}
const AZ::Data::AssetInfo& Modifier::GetCurrentAsset() const
size_t Modifier::GetCurrentIndex() const
{
return m_state == State::GatheringDependencies
? m_assets[m_assetIndex].info
: m_assets[m_dependencyOrderedAssetIndicies[m_assetIndex]].info;
? m_assetIndex
: m_dependencyOrderedAssetIndicies[m_assetIndex];
}
AZStd::unordered_set<size_t>& Modifier::GetOrCreateDependencyIndexSet()
@@ -65,14 +63,10 @@ namespace ScriptCanvasEditor
AZ_Assert(serializeContext, "SerializeContext is required to enumerate dependent assets in the ScriptCanvas file");
bool anyFailures = false;
auto asset = LoadAsset();
if (asset
&& asset.GetAs<ScriptCanvasAsset>()
&& asset.GetAs<ScriptCanvasAsset>()->GetScriptCanvasGraph()
&& asset.GetAs<ScriptCanvasAsset>()->GetScriptCanvasGraph()->GetGraphData())
if (m_result.asset.Get() && m_result.asset.Mod()->GetGraphData())
{
auto graphData = asset.GetAs<ScriptCanvasAsset>()->GetScriptCanvasGraph()->GetGraphData();
auto graphData = m_result.asset.Mod()->GetGraphData();
auto dependencyGrabber = [this]
( void* instancePointer
@@ -107,71 +101,69 @@ namespace ScriptCanvasEditor
, nullptr))
{
anyFailures = true;
VE_LOG("Modifier: ERROR - Failed to gather dependencies from graph data: %s"
, GetCurrentAsset().m_relativePath.c_str())
VE_LOG("Modifier: ERROR - Failed to gather dependencies from graph data: %s"
, m_result.asset.Path().c_str())
}
}
else
{
anyFailures = true;
VE_LOG("Modifier: ERROR - Failed to load asset %s for modification, even though it scanned properly"
, GetCurrentAsset().m_relativePath.c_str());
, m_result.asset.Path().c_str());
}
ModelNotificationsBus::Broadcast
( &ModelNotificationsTraits::OnUpgradeDependenciesGathered
, GetCurrentAsset()
, m_result.asset
, anyFailures ? Result::Failure : Result::Success);
ReleaseCurrentAsset();
// Flush asset database events to ensure no asset references are held by closures queued on Ebuses.
AZ::Data::AssetManager::Instance().DispatchEvents();
}
AZ::Data::Asset<AZ::Data::AssetData> Modifier::LoadAsset()
void Modifier::LoadAsset()
{
AZ::Data::Asset<AZ::Data::AssetData> asset = AZ::Data::AssetManager::Instance().GetAsset
( GetCurrentAsset().m_assetId
, azrtti_typeid<ScriptCanvasAsset>()
, AZ::Data::AssetLoadBehavior::PreLoad);
asset.BlockUntilLoadComplete();
if (asset.IsReady())
auto& handle = m_result.asset;
if (!handle.IsGraphValid())
{
return asset;
}
else
{
return {};
auto outcome = LoadFromFile(handle.Path().c_str());
if (outcome.IsSuccess())
{
handle = outcome.TakeValue();
}
}
}
void Modifier::ModificationComplete(const ModificationResult& result)
{
m_result = result;
if (result.errorMessage.empty())
if (!result.errorMessage.empty())
{
SaveModifiedGraph(result);
ReportModificationError(result.errorMessage);
}
else if (m_result.asset.Describe() != result.asset.Describe())
{
ReportModificationError("Received modifiction complete notification for different result");
}
else
{
ReportModificationError(result.errorMessage);
SaveModifiedGraph(result);
}
}
void Modifier::ModifyCurrentAsset()
{
m_result = {};
m_result.assetInfo = GetCurrentAsset();
m_result.asset = m_assets[GetCurrentIndex()];
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeModificationBegin, m_config, m_result.asset);
LoadAsset();
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeModificationBegin, m_config, GetCurrentAsset());
if (auto asset = LoadAsset())
if (m_result.asset.IsGraphValid())
{
ModificationNotificationsBus::Handler::BusConnect();
m_modifyState = ModifyState::InProgress;
m_config.modification(asset);
m_config.modification(m_result.asset);
}
else
{
@@ -182,24 +174,30 @@ namespace ScriptCanvasEditor
void Modifier::ModifyNextAsset()
{
ModelNotificationsBus::Broadcast
( &ModelNotificationsTraits::OnUpgradeModificationEnd, m_config, GetCurrentAsset(), m_result);
( &ModelNotificationsTraits::OnUpgradeModificationEnd, m_config, m_result.asset, m_result);
ModificationNotificationsBus::Handler::BusDisconnect();
m_modifyState = ModifyState::Idle;
ReleaseCurrentAsset();
++m_assetIndex;
m_result = {};
}
void Modifier::ReleaseCurrentAsset()
{
m_result.asset = m_result.asset.Describe();
}
void Modifier::ReportModificationError(AZStd::string_view report)
{
m_result.asset = {};
m_result.errorMessage = report;
m_results.m_failures.push_back(m_result);
m_results.m_failures.push_back({ m_result.asset.Describe(), report });
ModifyNextAsset();
}
void Modifier::ReportModificationSuccess()
{
m_results.m_successes.push_back(m_result.assetInfo);
m_result.asset = m_result.asset.Describe();
m_results.m_successes.push_back({ m_result.asset.Describe(), {} });
ModifyNextAsset();
}
@@ -227,7 +225,7 @@ namespace ScriptCanvasEditor
{
VE_LOG
( "Temporary file not removed for %s: %s"
, m_result.assetInfo.m_relativePath.c_str()
, m_result.asset.Path().c_str()
, result.tempFileRemovalError.c_str());
}
@@ -259,7 +257,7 @@ namespace ScriptCanvasEditor
m_modifyState = ModifyState::Saving;
m_fileSaver = AZStd::make_unique<FileSaver>
( m_config.onReadOnlyFile
, [this](const FileSaveResult& result) { OnFileSaveComplete(result); });
, [this](const FileSaveResult& fileSaveResult) { OnFileSaveComplete(fileSaveResult); });
m_fileSaver->Save(result.asset);
}
@@ -287,7 +285,7 @@ namespace ScriptCanvasEditor
for (size_t index = 0; index != m_assets.size(); ++index)
{
m_assetInfoIndexById.insert({ m_assets[index].info.m_assetId.m_guid, index });
m_assetInfoIndexById.insert({ m_assets[index].Id(), index });
}
}
else
@@ -299,7 +297,7 @@ namespace ScriptCanvasEditor
m_dependencyOrderedAssetIndicies.push_back(index);
}
// go straight into ModifyinGraphs
// go straight into ModifyingGraphs
m_assetIndex = m_assets.size();
}
}
@@ -322,6 +320,7 @@ namespace ScriptCanvasEditor
else
{
GatherDependencies();
ReleaseCurrentAsset();
++m_assetIndex;
}
}
@@ -380,10 +379,10 @@ namespace ScriptCanvasEditor
if (markedTemporary.contains(index))
{
AZ_Error
(ScriptCanvas::k_VersionExplorerWindow.data()
(ScriptCanvas::k_VersionExplorerWindow.data()
, false
, "Modifier: Dependency sort has failed during, circular dependency detected for Asset: %s"
, modifier->GetCurrentAsset().m_relativePath.c_str());
, modifier->m_result.asset.Path().c_str());
return;
}
@@ -26,7 +26,7 @@ namespace ScriptCanvasEditor
Modifier
( const ModifyConfiguration& modification
, WorkingAssets&& assets
, AZStd::vector<SourceHandle>&& assets
, AZStd::function<void()> onComplete);
const ModificationResults& GetResult() const;
@@ -67,9 +67,10 @@ namespace ScriptCanvasEditor
State m_state = State::GatheringDependencies;
ModifyState m_modifyState = ModifyState::Idle;
size_t m_assetIndex = 0;
AZStd::function<void()> m_onComplete;
// asset infos in scanned order
WorkingAssets m_assets;
AZStd::vector<SourceHandle> m_assets;
// dependency sorted order indices into the asset vector
AZStd::vector<size_t> m_dependencyOrderedAssetIndicies;
// dependency indices by asset info index (only exist if graphs have them)
@@ -82,13 +83,14 @@ namespace ScriptCanvasEditor
AZStd::unique_ptr<FileSaver> m_fileSaver;
FileSaveResult m_fileSaveResult;
size_t GetCurrentIndex() const;
void GatherDependencies();
const AZ::Data::AssetInfo& GetCurrentAsset() const;
AZStd::unordered_set<size_t>& GetOrCreateDependencyIndexSet();
AZ::Data::Asset<AZ::Data::AssetData> LoadAsset();
void LoadAsset();
void ModifyCurrentAsset();
void ModifyNextAsset();
void ModificationComplete(const ModificationResult& result) override;
void ReleaseCurrentAsset();
void ReportModificationError(AZStd::string_view report);
void ReportModificationSuccess();
void ReportSaveResult();
@@ -6,9 +6,49 @@
*
*/
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
#include <Editor/View/Windows/Tools/UpgradeTool/LogTraits.h>
#include <Editor/View/Windows/Tools/UpgradeTool/Scanner.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <Editor/View/Windows/Tools/UpgradeTool/LogTraits.h>
#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
namespace ScannerCpp
{
void TraverseTree
( QModelIndex index
, AzToolsFramework::AssetBrowser::AssetBrowserFilterModel& model
, ScriptCanvasEditor::VersionExplorer::ScanResult& result)
{
QModelIndex sourceIndex = model.mapToSource(index);
AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry =
reinterpret_cast<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>(sourceIndex.internalPointer());
if (entry
&& entry->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Source
&& azrtti_istypeof<const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry*>(entry)
&& entry->GetFullPath().ends_with(".scriptcanvas"))
{
auto sourceEntry = azrtti_cast<const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry*>(entry);
AZStd::string fullPath = sourceEntry->GetFullPath();
AzFramework::StringFunc::Path::Normalize(fullPath);
result.m_catalogAssets.push_back(
ScriptCanvasEditor::SourceHandle(nullptr, sourceEntry->GetSourceUuid(), fullPath));
}
const int rowCount = model.rowCount(index);
for (int i = 0; i < rowCount; ++i)
{
TraverseTree(model.index(i, 0, index), model, result);
}
}
}
namespace ScriptCanvasEditor
{
@@ -18,60 +58,54 @@ namespace ScriptCanvasEditor
: m_config(config)
, m_onComplete(onComplete)
{
AZ::Data::AssetCatalogRequestBus::Broadcast
( &AZ::Data::AssetCatalogRequestBus::Events::EnumerateAssets
, nullptr
, [this](const AZ::Data::AssetId, const AZ::Data::AssetInfo& assetInfo)
{
if (assetInfo.m_assetType == azrtti_typeid<ScriptCanvasAsset>())
{
m_result.m_catalogAssets.push_back(assetInfo);
}
}
, nullptr);
AzToolsFramework::AssetBrowser::AssetBrowserModel* assetBrowserModel = nullptr;
AzToolsFramework::AssetBrowser::AssetBrowserComponentRequestBus::BroadcastResult
( assetBrowserModel, &AzToolsFramework::AssetBrowser::AssetBrowserComponentRequests::GetAssetBrowserModel);
if (assetBrowserModel)
{
auto stringFilter = new AzToolsFramework::AssetBrowser::StringFilter();
stringFilter->SetName("ScriptCanvas");
stringFilter->SetFilterString(".scriptcanvas");
stringFilter->SetFilterPropagation(AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter::PropagateDirection::Down);
AzToolsFramework::AssetBrowser::AssetBrowserFilterModel assetFilterModel;
assetFilterModel.SetFilter(AzToolsFramework::AssetBrowser::FilterConstType(stringFilter));
assetFilterModel.setSourceModel(assetBrowserModel);
ScannerCpp::TraverseTree(QModelIndex(), assetFilterModel, m_result);
}
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanBegin, m_result.m_catalogAssets.size());
AZ::SystemTickBus::Handler::BusConnect();
}
void Scanner::FilterAsset(AZ::Data::Asset<AZ::Data::AssetData> asset)
void Scanner::FilterAsset(SourceHandle asset)
{
if (m_config.filter && m_config.filter(asset))
if (m_config.filter && m_config.filter(asset) == ScanConfiguration::Filter::Exclude)
{
VE_LOG("Scanner: Excluded: %s ", GetCurrentAsset().m_relativePath.c_str());
m_result.m_filteredAssets.push_back(GetCurrentAsset());
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanFilteredGraph, GetCurrentAsset());
VE_LOG("Scanner: Excluded: %s ", ModCurrentAsset().Path().c_str());
m_result.m_filteredAssets.push_back(ModCurrentAsset().Describe());
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanFilteredGraph, ModCurrentAsset());
}
else
{
VE_LOG("Scanner: Included: %s ", GetCurrentAsset().m_relativePath.c_str());
m_result.m_unfiltered.push_back({ asset, GetCurrentAsset() });
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanUnFilteredGraph, GetCurrentAsset());
VE_LOG("Scanner: Included: %s ", ModCurrentAsset().Path().c_str());
m_result.m_unfiltered.push_back(ModCurrentAsset().Describe());
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanUnFilteredGraph, ModCurrentAsset());
}
}
const AZ::Data::AssetInfo& Scanner::GetCurrentAsset() const
{
return m_result.m_catalogAssets[m_catalogAssetIndex];
}
const ScanResult& Scanner::GetResult() const
{
return m_result;
}
AZ::Data::Asset<AZ::Data::AssetData> Scanner::LoadAsset()
SourceHandle Scanner::LoadAsset()
{
AZ::Data::Asset<AZ::Data::AssetData> asset = AZ::Data::AssetManager::Instance().GetAsset
( GetCurrentAsset().m_assetId
, azrtti_typeid<ScriptCanvasAsset>()
, AZ::Data::AssetLoadBehavior::PreLoad);
asset.BlockUntilLoadComplete();
if (asset.IsReady())
auto fileOutcome = LoadFromFile(ModCurrentAsset().Path().c_str());
if (fileOutcome.IsSuccess())
{
return asset;
return fileOutcome.GetValue();
}
else
{
@@ -79,6 +113,11 @@ namespace ScriptCanvasEditor
}
}
SourceHandle& Scanner::ModCurrentAsset()
{
return m_result.m_catalogAssets[m_catalogAssetIndex];
}
void Scanner::OnSystemTick()
{
if (m_catalogAssetIndex == m_result.m_catalogAssets.size())
@@ -93,19 +132,19 @@ namespace ScriptCanvasEditor
}
else
{
if (auto asset = LoadAsset())
if (auto asset = LoadAsset(); asset.IsGraphValid())
{
VE_LOG("Scanner: Loaded: %s ", GetCurrentAsset().m_relativePath.c_str());
VE_LOG("Scanner: Loaded: %s ", ModCurrentAsset().Path().c_str());
FilterAsset(asset);
}
else
{
VE_LOG("Scanner: Failed to load: %s ", GetCurrentAsset().m_relativePath.c_str());
m_result.m_loadErrors.push_back(GetCurrentAsset());
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanLoadFailure, GetCurrentAsset());
VE_LOG("Scanner: Failed to load: %s ", ModCurrentAsset().Path().c_str());
m_result.m_loadErrors.push_back(ModCurrentAsset().Describe());
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanLoadFailure, ModCurrentAsset());
}
VE_LOG("Scanner: scan of %s complete", GetCurrentAsset().m_relativePath.c_str());
VE_LOG("Scanner: scan of %s complete", ModCurrentAsset().Path().c_str());
++m_catalogAssetIndex;
}
}
@@ -33,9 +33,9 @@ namespace ScriptCanvasEditor
ScanConfiguration m_config;
ScanResult m_result;
void FilterAsset(AZ::Data::Asset<AZ::Data::AssetData>);
const AZ::Data::AssetInfo& GetCurrentAsset() const;
AZ::Data::Asset<AZ::Data::AssetData> LoadAsset();
void FilterAsset(SourceHandle);
SourceHandle LoadAsset();
SourceHandle& ModCurrentAsset();
void OnSystemTick() override;
};
}
@@ -55,26 +55,25 @@ namespace ScriptCanvasEditor
for (auto& failedUpdate : result->m_failures)
{
auto& assetInfo = failedUpdate.assetInfo;
auto assetId = assetInfo.m_assetId;
auto asset = failedUpdate.asset;
m_ui->tableWidget->insertRow(rows);
connect(m_ui->closeButton, &QPushButton::pressed, this, &QDialog::accept);
connect(m_ui->tableWidget, &QTableWidget::itemDoubleClicked, this, [this, rows, assetId](QTableWidgetItem* item)
connect(m_ui->tableWidget, &QTableWidget::itemDoubleClicked, this, [this, rows, asset](QTableWidgetItem* item)
{
if (item && item->data(Qt::UserRole).toInt() == rows)
{
OpenGraph(assetId);
OpenGraph(asset);
}
}
);
auto openGraph = [this, assetId] {
OpenGraph(assetId);
auto openGraph = [this, asset] {
OpenGraph(asset);
};
QTableWidgetItem* rowName = new QTableWidgetItem(tr(assetInfo.m_relativePath.c_str()));
QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.Path().c_str()));
rowName->setData(Qt::UserRole, rows);
m_ui->tableWidget->setItem(rows, 0, rowName);
@@ -91,15 +90,15 @@ namespace ScriptCanvasEditor
}
}
void UpgradeHelper::OpenGraph(AZ::Data::AssetId assetId)
void UpgradeHelper::OpenGraph(const SourceHandle& asset)
{
// Open the graph in SC editor
AzToolsFramework::OpenViewPane(/*LyViewPane::ScriptCanvas*/"Script Canvas");
AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
if (assetId.IsValid())
if (!asset.Path().empty())
{
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, assetId, -1);
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, asset, Tracker::ScriptCanvasFileState::UNMODIFIED, -1);
}
if (!openOutcome)
@@ -35,6 +35,8 @@ namespace Ui
namespace ScriptCanvasEditor
{
// class SourceHandle;
//! A tool that collects and upgrades all Script Canvas graphs in the asset catalog
class UpgradeHelper
: public AzQtComponents::StyledDialog
@@ -51,6 +53,6 @@ namespace ScriptCanvasEditor
AZStd::unique_ptr<Ui::UpgradeHelper> m_ui;
void OpenGraph(AZ::Data::AssetId assetId);
void OpenGraph(const SourceHandle& assetId);
};
}
@@ -8,16 +8,17 @@
#pragma once
#include <AzCore/std/smart_ptr/enable_shared_from_this.h>
#include <AzCore/Asset/AssetCommon.h>
#include <Editor/Include/ScriptCanvas/Assets/ScriptCanvasAssetBus.h>
#include <Editor/Include/ScriptCanvas/Assets/ScriptCanvasBaseAssetData.h>
#include <ScriptCanvas/Asset/AssetDescription.h>
namespace ScriptCanvas
{
class ScriptCanvasAssetBase
: public AZ::Data::AssetData
, public AZStd::enable_shared_from_this<ScriptCanvasAssetBase>
, ScriptCanvas::ScriptCanvasAssetBusRequestBus::Handler
{
@@ -6,15 +6,18 @@
*
*/
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/RTTI/AttributeReader.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <Editor/Include/ScriptCanvas/Assets/ScriptCanvasBaseAssetData.h>
#include "Core.h"
#include "Attributes.h"
#include "Core.h"
#include <Core/Graph.h>
namespace ScriptCanvas
{
@@ -182,5 +185,156 @@ namespace ScriptCanvas
serializeContext->RegisterType(typeId, AZStd::move(classData), EventPlaceholderAnyCreator);
}
}
namespace ScriptCanvasEditor
{
SourceHandle::SourceHandle()
: m_id(AZ::Uuid::CreateNull())
{}
SourceHandle::SourceHandle(const SourceHandle& data, const AZ::Uuid& id, const AZ::IO::Path& path)
: m_data(data.m_data)
, 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;
}
SourceHandle::SourceHandle(const SourceHandle& data, const AZ::IO::Path& path)
: m_data(data.m_data)
, m_id(AZ::Uuid::CreateNull())
, m_path(path)
{
m_path.MakePreferred();
}
SourceHandle::SourceHandle(ScriptCanvas::DataPtr graph, const AZ::IO::Path& path)
: m_data(graph)
, m_id(AZ::Uuid::CreateNull())
, m_path(path)
{
m_path.MakePreferred();
}
bool SourceHandle::AnyEquals(const SourceHandle& other) const
{
return m_data && m_data == other.m_data
|| !m_id.IsNull() && m_id == other.m_id
|| !m_path.empty() && m_path == other.m_path;
}
void SourceHandle::Clear()
{
m_data = nullptr;
m_id = AZ::Uuid::CreateNull();
m_path.clear();
}
// return a SourceHandle with only the Id and Path, but without a pointer to the data
SourceHandle SourceHandle::Describe() const
{
return SourceHandle(nullptr, m_id, m_path);
}
GraphPtrConst SourceHandle::Get() const
{
return m_data ? m_data->GetEditorGraph() : nullptr;
}
const AZ::Uuid& SourceHandle::Id() const
{
return m_id;
}
bool SourceHandle::IsDescriptionValid() const
{
return !m_id.IsNull() && !m_path.empty();
}
bool SourceHandle::IsGraphValid() const
{
return m_data != nullptr;
}
GraphPtr SourceHandle::Mod() const
{
return m_data ? m_data->ModEditorGraph() : nullptr;
}
bool SourceHandle::operator==(const SourceHandle& other) const
{
return m_data.get() == other.m_data.get()
&& m_id == other.m_id
&& m_path == other.m_path;
}
bool SourceHandle::operator!=(const SourceHandle& other) const
{
return !(*this == other);
}
const AZ::IO::Path& SourceHandle::Path() const
{
return m_path;
}
bool SourceHandle::PathEquals(const SourceHandle& other) const
{
return m_path == other.m_path;
}
void SourceHandle::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<SourceHandle>()
->Version(0)
->Field("id", &SourceHandle::m_id)
->Field("path", &SourceHandle::m_path)
;
}
}
AZStd::string SourceHandle::ToString() const
{
return AZStd::string::format
( "%s, %s, %s"
, IsGraphValid() ? "O" : "X"
, m_path.empty() ? m_path.c_str() : "<no name>"
, m_id.IsNull() ? "<null id>" : m_id.ToString<AZStd::string>().c_str());
}
}
namespace ScriptCanvas
{
const Graph* ScriptCanvasData::GetGraph() const
{
return AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Graph>(m_scriptCanvasEntity.get());
}
const ScriptCanvasEditor::Graph* ScriptCanvasData::GetEditorGraph() const
{
return reinterpret_cast<const ScriptCanvasEditor::Graph*>(GetGraph());
}
Graph* ScriptCanvasData::ModGraph()
{
return AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Graph>(m_scriptCanvasEntity.get());
}
ScriptCanvasEditor::Graph* ScriptCanvasData::ModEditorGraph()
{
return reinterpret_cast<ScriptCanvasEditor::Graph*>(ModGraph());
}
}

Some files were not shown because too many files have changed in this diff Show More