Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,162 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <ScriptCanvas/Assets/Functions/ScriptCanvasFunctionAssetHandler.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
#include <Core/ScriptCanvasBus.h>
#include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/Components/EditorScriptCanvasComponent.h>
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
#include <GraphCanvas/GraphCanvasBus.h>
#include <AzCore/IO/GenericStreams.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/Serialization/Utils.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/std/string/string_view.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <ScriptCanvas/Asset/Functions/ScriptCanvasFunctionAsset.h>
namespace ScriptCanvasEditor
{
ScriptCanvasFunctionAssetHandler::ScriptCanvasFunctionAssetHandler(AZ::SerializeContext* context)
: ScriptCanvasAssetHandler(context)
{
AZ::AssetTypeInfoBus::MultiHandler::BusConnect(azrtti_typeid<ScriptCanvas::ScriptCanvasFunctionAsset>());
}
ScriptCanvasFunctionAssetHandler::~ScriptCanvasFunctionAssetHandler()
{
AZ::AssetTypeInfoBus::MultiHandler::BusDisconnect();
}
AZ::Data::AssetPtr ScriptCanvasFunctionAssetHandler::CreateAsset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type)
{
AZ_UNUSED(type);
ScriptCanvas::ScriptCanvasFunctionAsset* assetData = aznew ScriptCanvas::ScriptCanvasFunctionAsset(id);
AZ::Entity* scriptCanvasEntity = aznew AZ::Entity(ScriptCanvas::AssetDescription::GetEntityName<ScriptCanvas::ScriptCanvasFunctionAsset>());
SystemRequestBus::Broadcast(&SystemRequests::CreateEditorComponentsOnEntity, scriptCanvasEntity, azrtti_typeid<ScriptCanvas::RuntimeFunctionAsset>());
assetData->m_cachedComponent = scriptCanvasEntity->CreateComponent<ScriptCanvas::ScriptCanvasFunctionDataComponent>();
assetData->SetScriptCanvasEntity(scriptCanvasEntity);
return assetData;
}
AZ::Data::AssetHandler::LoadResult ScriptCanvasFunctionAssetHandler::LoadAssetData(
const AZ::Data::Asset<AZ::Data::AssetData>& asset,
AZStd::shared_ptr<AZ::Data::AssetDataStream> stream,
const AZ::Data::AssetFilterCB& assetLoadFilterCB)
{
ScriptCanvas::ScriptCanvasFunctionAsset* scriptCanvasAsset = asset.GetAs<ScriptCanvas::ScriptCanvasFunctionAsset>();
AZ_Assert(m_serializeContext, "ScriptCanvasFunctionAssetHandler needs to be initialized with a SerializeContext");
if (scriptCanvasAsset)
{
stream->Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN);
bool loadSuccess = AZ::Utils::LoadObjectFromStreamInPlace(*stream, scriptCanvasAsset->GetScriptCanvasData(), m_serializeContext, AZ::ObjectStream::FilterDescriptor(assetLoadFilterCB, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES));
if (loadSuccess)
{
scriptCanvasAsset->m_cachedComponent = scriptCanvasAsset->GetScriptCanvasData().GetScriptCanvasEntity()->FindComponent<ScriptCanvas::ScriptCanvasFunctionDataComponent>();
}
return loadSuccess ? AZ::Data::AssetHandler::LoadResult::LoadComplete : AZ::Data::AssetHandler::LoadResult::Error;
}
return AZ::Data::AssetHandler::LoadResult::Error;
}
bool ScriptCanvasFunctionAssetHandler::SaveAssetData(const AZ::Data::Asset<AZ::Data::AssetData>& asset, AZ::IO::GenericStream* stream)
{
return SaveAssetData(asset.GetAs<ScriptCanvas::ScriptCanvasFunctionAsset>(), stream);
}
bool ScriptCanvasFunctionAssetHandler::SaveAssetData(const ScriptCanvas::ScriptCanvasFunctionAsset* assetData, AZ::IO::GenericStream* stream)
{
return SaveAssetData(assetData, stream, AZ::DataStream::ST_XML);
}
bool ScriptCanvasFunctionAssetHandler::SaveAssetData(const ScriptCanvas::ScriptCanvasFunctionAsset* assetData, AZ::IO::GenericStream* stream, AZ::DataStream::StreamType streamType)
{
if (assetData && m_serializeContext)
{
AZStd::vector<char> byteBuffer;
AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
AZ::ObjectStream* objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, streamType);
const ScriptCanvas::ScriptCanvasData& functionData = assetData->GetScriptCanvasData();
bool assetSaved = objStream->WriteClass(&functionData);
objStream->Finalize();
assetSaved = stream->Write(byteBuffer.size(), byteBuffer.data()) == byteBuffer.size() && assetSaved;
return assetSaved;
}
return false;
}
AZ::Data::AssetType ScriptCanvasFunctionAssetHandler::GetAssetType() const
{
return ScriptCanvasFunctionAssetHandler::GetAssetTypeStatic();
}
const char* ScriptCanvasFunctionAssetHandler::GetAssetTypeDisplayName() const
{
return ScriptCanvas::AssetDescription::GetAssetTypeDisplayName<ScriptCanvas::ScriptCanvasFunctionAsset>();
}
bool ScriptCanvasFunctionAssetHandler::CanCreateComponent([[maybe_unused]] const AZ::Data::AssetId& assetId) const
{
return false;
}
void ScriptCanvasFunctionAssetHandler::GetAssetTypeExtensions(AZStd::vector<AZStd::string>& extensions)
{
const AZ::Uuid& assetType = *AZ::AssetTypeInfoBus::GetCurrentBusId();
if (assetType == AZ::AzTypeInfo<ScriptCanvas::ScriptCanvasFunctionAsset>::Uuid())
{
extensions.push_back(ScriptCanvas::AssetDescription::GetExtension<ScriptCanvas::ScriptCanvasFunctionAsset>());
}
}
void ScriptCanvasFunctionAssetHandler::GetHandledAssetTypes(AZStd::vector<AZ::Data::AssetType>& assetTypes)
{
assetTypes.push_back(AZ::AzTypeInfo<ScriptCanvas::ScriptCanvasFunctionAsset>::Uuid());
}
AZ::Data::AssetType ScriptCanvasFunctionAssetHandler::GetAssetTypeStatic()
{
return azrtti_typeid<ScriptCanvas::ScriptCanvasFunctionAsset>();
}
const char* ScriptCanvasFunctionAssetHandler::GetGroup() const
{
return ScriptCanvas::AssetDescription::GetGroup<ScriptCanvas::ScriptCanvasFunctionAsset>();
}
const char* ScriptCanvasFunctionAssetHandler::GetBrowserIcon() const
{
return ScriptCanvas::AssetDescription::GetIconPath<ScriptCanvas::ScriptCanvasFunctionAsset>();
}
} // namespace ScriptCanvasEditor
@@ -0,0 +1,206 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <LyViewPaneNames.h>
#include <Editor/Assets/Functions/ScriptCanvasFunctionAssetHolder.h>
#include <ScriptCanvas/Asset/AssetRegistry.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
#include <ScriptCanvas/Core/ScriptCanvasBus.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Serialization/IdUtils.h>
#include <AzCore/Asset/AssetManager.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
namespace ScriptCanvasEditor
{
//=========================================================================
void ScriptCanvasFunctionAssetHolder::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<ScriptCanvasFunctionAssetHolder>()
->Version(1)
->Field("m_asset", &ScriptCanvasFunctionAssetHolder::m_scriptCanvasAssetId)
;
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
{
editContext->Class<ScriptCanvasFunctionAssetHolder>("Script Canvas", "Script Canvas Function Asset Holder")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasFunctionAssetHolder::m_scriptCanvasAssetId, "Script Canvas Function Asset", "Script Canvas asset associated with this component")
->Attribute(AZ::Edit::Attributes::ChangeNotify, &ScriptCanvasFunctionAssetHolder::OnScriptChanged)
->Attribute("EditButton", "Editor/Icons/PropertyEditor/open_in.png")
->Attribute("EditDescription", "Open in Script Canvas Editor")
->Attribute("EditCallback", &ScriptCanvasFunctionAssetHolder::LaunchScriptCanvasEditor)
;
}
}
}
ScriptCanvasFunctionAssetHolder::ScriptCanvasFunctionAssetHolder(AZ::Data::AssetId assetId, const ScriptChangedCB& scriptChangedCB)
: m_scriptCanvasAssetId(assetId)
, m_scriptNotifyCallback(scriptChangedCB)
{
}
ScriptCanvasFunctionAssetHolder::~ScriptCanvasFunctionAssetHolder()
{
AZ::Data::AssetBus::Handler::BusDisconnect();
}
void ScriptCanvasFunctionAssetHolder::Init(AZ::EntityId ownerId)
{
m_ownerId = ownerId;
if (m_scriptCanvasAssetId.IsValid())
{
AZ::Data::AssetBus::Handler::BusDisconnect();
AZ::Data::AssetBus::Handler::BusConnect(m_scriptCanvasAssetId);
}
}
void ScriptCanvasFunctionAssetHolder::LaunchScriptCanvasEditor(const AZ::Data::AssetId&, const AZ::Data::AssetType&) const
{
OpenEditor();
}
void ScriptCanvasFunctionAssetHolder::OpenEditor() const
{
AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas);
AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
if (m_scriptCanvasAssetId.IsValid())
{
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, m_scriptCanvasAssetId, -1);
if (!openOutcome)
{
AZ_Warning("Script Canvas", openOutcome, "%s", openOutcome.GetError().data());
}
}
else if (m_ownerId.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);
}
}
}
AZ::EntityId ScriptCanvasFunctionAssetHolder::GetGraphId() const
{
AZ::EntityId graphId;
if (m_scriptCanvasAsset.IsReady())
{
ScriptCanvas::SystemRequestBus::BroadcastResult(graphId, &ScriptCanvas::SystemRequests::FindGraphId, m_scriptCanvasAsset.Get()->GetScriptCanvasEntity());
}
return graphId;
}
void ScriptCanvasFunctionAssetHolder::SetScriptChangedCB(const ScriptChangedCB& scriptChangedCB)
{
m_scriptNotifyCallback = scriptChangedCB;
}
void ScriptCanvasFunctionAssetHolder::Load(bool loadBlocking)
{
if (!m_scriptCanvasAsset.IsReady())
{
AZ::Data::AssetInfo assetInfo;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, m_scriptCanvasAsset.GetId());
if (assetInfo.m_assetId.IsValid())
{
const AZ::Data::AssetType assetTypeId = azrtti_typeid<ScriptCanvasAsset>();
auto& assetManager = AZ::Data::AssetManager::Instance();
m_scriptCanvasAsset = assetManager.GetAsset(m_scriptCanvasAsset.GetId(), azrtti_typeid<ScriptCanvasAsset>(), true, nullptr, loadBlocking);
}
}
}
AZ::u32 ScriptCanvasFunctionAssetHolder::OnScriptChanged()
{
SetAsset(m_scriptCanvasAsset.GetId());
Load(false);
if (m_scriptNotifyCallback)
{
m_scriptNotifyCallback(m_scriptCanvasAsset);
}
return AZ::Edit::PropertyRefreshLevels::EntireTree;
}
void ScriptCanvasFunctionAssetHolder::OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset)
{
SetAsset(asset.GetId());
EditorScriptCanvasAssetNotificationBus::Event(m_scriptCanvasAsset.GetId(), &EditorScriptCanvasAssetNotifications::OnScriptCanvasAssetReady, m_scriptCanvasAsset);
}
void ScriptCanvasFunctionAssetHolder::OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset)
{
SetAsset(asset.GetId());
EditorScriptCanvasAssetNotificationBus::Event(m_scriptCanvasAsset.GetId(), &EditorScriptCanvasAssetNotifications::OnScriptCanvasAssetReloaded, m_scriptCanvasAsset);
}
void ScriptCanvasFunctionAssetHolder::OnAssetUnloaded(const AZ::Data::AssetId assetId, const AZ::Data::AssetType)
{
EditorScriptCanvasAssetNotificationBus::Event(assetId, &EditorScriptCanvasAssetNotifications::OnScriptCanvasAssetUnloaded, assetId);
}
void ScriptCanvasFunctionAssetHolder::OnAssetSaved(AZ::Data::Asset<AZ::Data::AssetData> asset, bool isSuccessful)
{
SetAsset(asset.GetId());
auto currentBusId = AZ::Data::AssetBus::GetCurrentBusId();
if (currentBusId)
{
EditorScriptCanvasAssetNotificationBus::Event(*currentBusId, &EditorScriptCanvasAssetNotifications::OnScriptCanvasAssetSaved, asset.GetId());
}
}
void ScriptCanvasFunctionAssetHolder::SetAsset(AZ::Data::AssetId assetId)
{
m_scriptCanvasAssetId = assetId;
if (!AZ::Data::AssetBus::Handler::BusIsConnectedId(m_scriptCanvasAssetId))
{
AZ::Data::AssetBus::Handler::BusDisconnect();
if (m_scriptCanvasAssetId.IsValid())
{
AZ::Data::AssetBus::Handler::BusConnect(m_scriptCanvasAssetId);
}
}
}
//AZ::Data::Asset<ScriptCanvasAsset> ScriptCanvasFunctionAssetHolder::GetAsset() const
//{
// return m_scriptCanvasAsset;
//}
AZ::Data::AssetId ScriptCanvasFunctionAssetHolder::GetAssetId() const
{
return m_scriptCanvasAssetId;
}
}
@@ -0,0 +1,80 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/EntityId.h>
#include <AzCore/Asset/AssetCommon.h>
namespace ScriptCanvas
{
class ScriptCanvasFunctionAsset;
}
namespace ScriptCanvasEditor
{
class ScriptCanvasFunctionAsset;
/*! ScriptCanvasAssetHolder
Wraps a ScriptCanvasAsset reference and registers for the individual AssetBus events
for saving, loading and unloading the asset.
The ScriptCanvasAsset Holder contains functionality for activating the ScriptCanvasEntity stored on the reference asset
as well as attempting to open the ScriptCanvasAsset within the ScriptCanvas Editor.
It also provides the EditContext reflection for opening the asset in the ScriptCanvas Editor via a button
*/
class ScriptCanvasFunctionAssetHolder
: private AZ::Data::AssetBus::Handler
{
public:
AZ_RTTI(ScriptCanvasFunctionAssetHolder, "{21693AFA-5664-4AAE-9213-8B944A398BA1}");
AZ_CLASS_ALLOCATOR(ScriptCanvasFunctionAssetHolder, AZ::SystemAllocator, 0);
using ScriptChangedCB = AZStd::function<void(const AZ::Data::Asset<ScriptCanvasAsset>&)>;
ScriptCanvasFunctionAssetHolder() = default;
ScriptCanvasFunctionAssetHolder(AZ::Data::AssetId assetId, const ScriptChangedCB& = {});
~ScriptCanvasFunctionAssetHolder() override;
static void Reflect(AZ::ReflectContext* context);
void Init(AZ::EntityId ownerId = AZ::EntityId());
void SetAsset(AZ::Data::AssetId assetId);
AZ::Data::AssetId GetAssetId() const;
AZ::EntityId GetGraphId() const;
void LaunchScriptCanvasEditor(const AZ::Data::AssetId&, const AZ::Data::AssetType&) const;
void OpenEditor() const;
void SetScriptChangedCB(const ScriptChangedCB&);
void Load(bool loadBlocking = false);
protected:
//=====================================================================
// AZ::Data::AssetBus
void OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
void OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
void OnAssetUnloaded(const AZ::Data::AssetId assetId, const AZ::Data::AssetType assetType) override;
void OnAssetSaved(AZ::Data::Asset<AZ::Data::AssetData> asset, bool isSuccessful) override;
//=====================================================================
//! Reloads the Script From the AssetData if it has changed
AZ::u32 OnScriptChanged();
AZ::Data::AssetId m_scriptCanvasAssetId;
AZ::Data::Asset<ScriptCanvas::ScriptCanvasFunctionAsset> m_scriptCanvasAsset;
AZ::EntityId m_ownerId; // Id of Entity which stores this AssetHolder object
ScriptChangedCB m_scriptNotifyCallback;
};
}
@@ -0,0 +1,129 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/Serialization/Utils.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
#include <ScriptCanvas/Core/ScriptCanvasBus.h>
#include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
namespace ScriptCanvas
{
ScriptCanvasData::ScriptCanvasData(ScriptCanvasData&& other)
: m_scriptCanvasEntity(AZStd::move(other.m_scriptCanvasEntity))
{
}
ScriptCanvasData& ScriptCanvasData::operator=(ScriptCanvasData&& other)
{
m_scriptCanvasEntity = AZStd::move(other.m_scriptCanvasEntity);
return *this;
}
static bool ScriptCanvasDataVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& rootDataElementNode)
{
if (rootDataElementNode.GetVersion() == 0)
{
int scriptCanvasEntityIndex = rootDataElementNode.FindElement(AZ_CRC("m_scriptCanvas", 0xfcd20d85));
if (scriptCanvasEntityIndex == -1)
{
AZ_Error("Script Canvas", false, "Version Converter failed, The Script Canvas Entity is missing");
return false;
}
auto scComponentElements = AZ::Utils::FindDescendantElements(context, rootDataElementNode, AZStd::vector<AZ::Crc32>{AZ_CRC("m_scriptCanvas", 0xfcd20d85),
AZ_CRC("element", 0x41405e39), AZ_CRC("Components", 0xee48f5fd)});
if (!scComponentElements.empty())
{
scComponentElements.front()->AddElementWithData(context, "element", ScriptCanvasEditor::EditorGraphVariableManagerComponent());
}
}
if (rootDataElementNode.GetVersion() < 4)
{
auto scEntityElements = AZ::Utils::FindDescendantElements(context, rootDataElementNode,
AZStd::vector<AZ::Crc32>{AZ_CRC("m_scriptCanvas", 0xfcd20d85), AZ_CRC("element", 0x41405e39)});
if (scEntityElements.empty())
{
AZ_Error("Script Canvas", false, "Version Converter failed, The Script Canvas Entity is missing");
return false;
}
auto& scEntityDataElement = *scEntityElements.front();
AZ::Entity scEntity;
if (!scEntityDataElement.GetData(scEntity))
{
AZ_Error("Script Canvas", false, "Unable to retrieve entity data from the Data Element");
return false;
}
auto graph = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Graph>(&scEntity);
if (!graph)
{
AZ_Error("Script Canvas", false, "Script Canvas graph component could not be found on Script Canvas Entity for ScriptCanvasData version %u", rootDataElementNode.GetVersion());
return false;
}
auto variableManager = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::GraphVariableManagerComponent>(&scEntity);
if (!variableManager)
{
AZ_Error("Script Canvas", false, "Script Canvas variable manager component could not be found on Script Canvas Entity for ScriptCanvasData version %u", rootDataElementNode.GetVersion());
return false;
}
variableManager->ConfigureScriptCanvasId(graph->GetScriptCanvasId());
if (!scEntityDataElement.SetData(context, scEntity))
{
AZ_Error("Script Canvas", false, "Failed to set converted Script Canvas Entity back on data element node when transitioning from version %u to version 4", rootDataElementNode.GetVersion());
return false;
}
}
return true;
}
void ScriptCanvasData::Reflect(AZ::ReflectContext* reflectContext)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext))
{
serializeContext->Class<ScriptCanvasData>()
->Version(4, &ScriptCanvasDataVersionConverter)
->Field("m_scriptCanvas", &ScriptCanvasData::m_scriptCanvasEntity)
;
}
}
}
namespace ScriptCanvasEditor
{
ScriptCanvas::Graph* ScriptCanvasAsset::GetScriptCanvasGraph() const
{
return AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Graph>(m_data->m_scriptCanvasEntity.get());
}
ScriptCanvas::ScriptCanvasData& ScriptCanvasAsset::GetScriptCanvasData()
{
return *m_data;
}
const ScriptCanvas::ScriptCanvasData& ScriptCanvasAsset::GetScriptCanvasData() const
{
return *m_data;
}
}
@@ -0,0 +1,200 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
#include <Core/ScriptCanvasBus.h>
#include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/Components/EditorScriptCanvasComponent.h>
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
#include <GraphCanvas/GraphCanvasBus.h>
#include <AzCore/IO/GenericStreams.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/Serialization/Utils.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/std/string/string_view.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
namespace ScriptCanvasEditor
{
ScriptCanvasAssetHandler::ScriptCanvasAssetHandler(AZ::SerializeContext* context)
{
SetSerializeContext(context);
AZ::AssetTypeInfoBus::MultiHandler::BusConnect(GetAssetType());
}
ScriptCanvasAssetHandler::~ScriptCanvasAssetHandler()
{
AZ::AssetTypeInfoBus::MultiHandler::BusDisconnect();
}
AZ::Data::AssetPtr ScriptCanvasAssetHandler::CreateAsset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type)
{
(void)type;
auto assetData = aznew ScriptCanvasAsset(id);
AZ::Entity* scriptCanvasEntity = aznew AZ::Entity("Script Canvas Graph");
SystemRequestBus::Broadcast(&SystemRequests::CreateEditorComponentsOnEntity, scriptCanvasEntity, azrtti_typeid<ScriptCanvas::RuntimeAsset>());
assetData->SetScriptCanvasEntity(scriptCanvasEntity);
return assetData;
}
// Override the stream info to force source assets to load into the Editor instead of cached, processed assets.
void ScriptCanvasAssetHandler::GetCustomAssetStreamInfoForLoad(AZ::Data::AssetStreamInfo& streamInfo)
{
//ScriptCanvas files are source assets and should be placed in a source asset directory
const char* assetPath = streamInfo.m_streamName.c_str();
if (AzFramework::StringFunc::Path::IsRelative(assetPath))
{
AZStd::string watchFolder;
bool sourceInfoFound{};
AZ::Data::AssetInfo assetInfo;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetPath, assetInfo, watchFolder);
if (sourceInfoFound)
{
AzFramework::StringFunc::Path::Join(watchFolder.data(), assetInfo.m_relativePath.data(), streamInfo.m_streamName);
}
}
}
AZ::Data::AssetHandler::LoadResult ScriptCanvasAssetHandler::LoadAssetData(
const AZ::Data::Asset<AZ::Data::AssetData>& asset,
AZStd::shared_ptr<AZ::Data::AssetDataStream> stream,
const AZ::Data::AssetFilterCB& assetLoadFilterCB)
{
auto* scriptCanvasAsset = asset.GetAs<ScriptCanvasAsset>();
AZ_Assert(scriptCanvasAsset, "This should be an scene slice asset, as this is the only type we process!");
if (scriptCanvasAsset && m_serializeContext)
{
stream->Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN);
// tolerate unknown classes in the editor. Let the asset processor warn about bad nodes...
bool loadSuccess = AZ::Utils::LoadObjectFromStreamInPlace(*stream, scriptCanvasAsset->GetScriptCanvasData(), m_serializeContext, AZ::ObjectStream::FilterDescriptor(assetLoadFilterCB, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES));
return loadSuccess ? AZ::Data::AssetHandler::LoadResult::LoadComplete : AZ::Data::AssetHandler::LoadResult::Error;
}
return AZ::Data::AssetHandler::LoadResult::Error;
}
bool ScriptCanvasAssetHandler::SaveAssetData(const AZ::Data::Asset<AZ::Data::AssetData>& asset, AZ::IO::GenericStream* stream)
{
return SaveAssetData(asset.GetAs<ScriptCanvasAsset>(), stream);
}
bool ScriptCanvasAssetHandler::SaveAssetData(const ScriptCanvasAsset* assetData, AZ::IO::GenericStream* stream)
{
return SaveAssetData(assetData, stream, AZ::DataStream::ST_XML);
}
bool ScriptCanvasAssetHandler::SaveAssetData(const ScriptCanvasAsset* assetData, AZ::IO::GenericStream* stream, AZ::DataStream::StreamType streamType)
{
if (assetData && m_serializeContext)
{
AZStd::vector<char> byteBuffer;
AZ::IO::ByteContainerStream<decltype(byteBuffer)> byteStream(&byteBuffer);
AZ::ObjectStream* objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, streamType);
bool scriptCanvasAssetSaved = objStream->WriteClass(&assetData->GetScriptCanvasData());
objStream->Finalize();
scriptCanvasAssetSaved = stream->Write(byteBuffer.size(), byteBuffer.data()) == byteBuffer.size() && scriptCanvasAssetSaved;
return scriptCanvasAssetSaved;
}
return false;
}
void ScriptCanvasAssetHandler::DestroyAsset(AZ::Data::AssetPtr ptr)
{
delete ptr;
}
//=========================================================================
// GetSerializeContext
//=========================================================================.
AZ::SerializeContext* ScriptCanvasAssetHandler::GetSerializeContext() const
{
return m_serializeContext;
}
//=========================================================================
// SetSerializeContext
//=========================================================================.
void ScriptCanvasAssetHandler::SetSerializeContext(AZ::SerializeContext* context)
{
m_serializeContext = context;
if (m_serializeContext == nullptr)
{
// use the default app serialize context
EBUS_EVENT_RESULT(m_serializeContext, AZ::ComponentApplicationBus, GetSerializeContext);
if (!m_serializeContext)
{
AZ_Error("Script Canvas", false, "ScriptCanvasAssetHandler: No serialize context provided! We will not be able to process Graph Asset type");
}
}
}
//=========================================================================
// GetHandledAssetTypes
//=========================================================================.
void ScriptCanvasAssetHandler::GetHandledAssetTypes(AZStd::vector<AZ::Data::AssetType>& assetTypes)
{
assetTypes.push_back(GetAssetType());
}
//=========================================================================
// GetAssetType
//=========================================================================.
AZ::Data::AssetType ScriptCanvasAssetHandler::GetAssetType() const
{
return ScriptCanvasAssetHandler::GetAssetTypeStatic();
}
const char* ScriptCanvasAssetHandler::GetAssetTypeDisplayName() const
{
return "Script Canvas";
}
AZ::Data::AssetType ScriptCanvasAssetHandler::GetAssetTypeStatic()
{
return azrtti_typeid<ScriptCanvasAsset>();
}
//=========================================================================
// GetAssetTypeExtensions
//=========================================================================.
void ScriptCanvasAssetHandler::GetAssetTypeExtensions(AZStd::vector<AZStd::string>& extensions)
{
ScriptCanvasAsset::Description description;
extensions.push_back(description.GetExtensionImpl());
}
AZ::Uuid ScriptCanvasAssetHandler::GetComponentTypeId() const
{
return azrtti_typeid<EditorScriptCanvasComponent>();
}
} // namespace ScriptCanvasEditor
@@ -0,0 +1,155 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Editor/Assets/ScriptCanvasAssetHelpers.h>
namespace ScriptCanvasEditor
{
namespace AssetHelpers
{
// Simplified function to trace messages
void PrintInfo(const char* format, ...)
{
// TODO: Turn into something nice with enable_if
static bool s_enabled = false;
if (s_enabled)
{
char sBuffer[1024];
va_list ArgList;
va_start(ArgList, format);
azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList);
sBuffer[sizeof(sBuffer) - 1] = '\0';
va_end(ArgList);
AZ_TracePrintf("Script Canvas", "%s\n", sBuffer);
}
}
// Given the full path to the asset, attempt to get the AssetInfo
bool GetAssetInfo(AZStd::string_view fullPath, AZ::Data::AssetInfo& outAssetInfo)
{
AZStd::string watchFolder;
AZ::Data::AssetInfo catalogAssetInfo;
bool sourceInfoFound{};
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, fullPath.data(), catalogAssetInfo, watchFolder);
auto saveAssetId = sourceInfoFound ? catalogAssetInfo.m_assetId : AZ::Data::AssetId(AZ::Uuid::CreateRandom());
if (sourceInfoFound)
{
outAssetInfo = catalogAssetInfo;
return true;
}
return false;
}
// Given the AssetId to the asset, attempt to get the AssetInfo
AZ::Data::AssetInfo GetAssetInfo(AZ::Data::AssetId assetId)
{
AZ::Data::AssetInfo assetInfo;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, assetId);
return assetInfo;
}
// Find the AssetType for a given asset by path
AZ::Data::AssetType GetAssetType(const char* assetPath)
{
AZStd::string watchFolder;
AZ::Data::AssetInfo assetInfo;
bool sourceInfoFound{};
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetPath, assetInfo, watchFolder);
if (sourceInfoFound)
{
return GetAssetType(assetInfo.m_assetId);
}
return AZ::Data::AssetType::CreateNull();
}
// Get AssetInfo from the AssetSystem as opposed to the catalog
AZ::Data::AssetInfo GetAssetInfo(AZ::Data::AssetId assetId, AZStd::string& rootFilePath)
{
AZ::Data::AssetInfo assetInfo;
const AZStd::string platformName = ""; // Empty for default
AzToolsFramework::AssetSystemRequestBus::Broadcast(&AzToolsFramework::AssetSystemRequestBus::Events::GetAssetInfoById, assetId, GetAssetType(assetId), platformName, assetInfo, rootFilePath);
return assetInfo;
}
AZ::Data::AssetInfo GetSourceInfo(const AZStd::string& sourceFilePath, AZStd::string& watchFolder)
{
AZ::Data::AssetInfo assetInfo;
AzToolsFramework::AssetSystemRequestBus::Broadcast(&AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, sourceFilePath.c_str(), assetInfo, watchFolder);
return assetInfo;
}
AZ::Data::AssetInfo GetSourceInfoByProductId(AZ::Data::AssetId assetId, AZ::Data::AssetType assetType)
{
bool infoFound = false;
AZStd::string watchFolder;
AZ::Data::AssetInfo assetInfo;
const AZStd::string platformName = ""; // Empty for default
AzToolsFramework::AssetSystemRequestBus::Events* assetSystem = AzToolsFramework::AssetSystemRequestBus::FindFirstHandler();
if (assetSystem == nullptr)
{
return AZ::Data::AssetInfo();
}
if (!assetSystem->GetAssetInfoById(assetId, assetType, platformName, assetInfo, watchFolder))
{
return AZ::Data::AssetInfo();
}
AZStd::string sourcePath;
if (!assetSystem->GetFullSourcePathFromRelativeProductPath(assetInfo.m_relativePath, sourcePath))
{
return AZ::Data::AssetInfo();
}
if (!assetSystem->GetSourceInfoBySourcePath(sourcePath.c_str(), assetInfo, watchFolder))
{
return AZ::Data::AssetInfo();
}
return assetInfo;
}
void DumpAssetInfo(AZ::Data::AssetId assetId, [[maybe_unused]] const char* extra)
{
static bool s_enabled = false;
if (!s_enabled)
{
return;
}
AZ::Data::AssetInfo assetInfo = GetAssetInfo(assetId);
if (assetInfo.m_assetId.IsValid())
{
AZ_TracePrintf("Script Canvas", "-------------------------------------\n");
AZ_TracePrintf("Script Canvas", "AssetId: %s", AssetIdToString(assetId).c_str());
AZ_TracePrintf("Script Canvas", AZStd::string::format("AssetType: %s", assetInfo.m_assetType.ToString<AZStd::string>().c_str()).c_str());
AZ_TracePrintf("Script Canvas", AZStd::string::format("RelativePath: %s", assetInfo.m_relativePath.c_str()).c_str());
AZ_TracePrintf("Script Canvas", AZStd::string::format("Size in Byes: %llu", assetInfo.m_sizeBytes).c_str());
AZ_TracePrintf("Script Canvas", AZStd::string::format("%s\n", extra).c_str());
AZ_TracePrintf("Script Canvas", "-------------------------------------\n");
}
else
{
AZ_TracePrintf("Script Canvas", "Cannot DumpAssetInfo for Asset with ID: %s\n", AssetIdToString(assetId).c_str());
}
}
}
}
@@ -0,0 +1,54 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzCore/Component/EntityUtils.h>
#include <cinttypes>
namespace ScriptCanvasEditor
{
namespace AssetHelpers
{
// Simplified function to trace messages
void PrintInfo(const char* format, ...);
// Simplifies the conversion of an AssetId to a string to avoid overly verbose trace calls
inline AZStd::string AssetIdToString(AZ::Data::AssetId assetId) { return assetId.ToString<AZStd::string>(); }
// Given the full path to the asset, attempt to get the AssetInfo
bool GetAssetInfo(AZStd::string_view fullPath, AZ::Data::AssetInfo& outAssetInfo);
// Given the AssetId to the asset, attempt to get the AssetInfo
AZ::Data::AssetInfo GetAssetInfo(AZ::Data::AssetId assetId);
// Find the AssetType for a given asset
inline AZ::Data::AssetType GetAssetType(AZ::Data::AssetId assetId)
{
AZ::Data::AssetInfo assetInfo = GetAssetInfo(assetId);
return assetInfo.m_assetType;
}
// Find the AssetType for a given asset by path
AZ::Data::AssetType GetAssetType(const char* assetPath);
// Get AssetInfo from the AssetSystem as opposed to the catalog
AZ::Data::AssetInfo GetAssetInfo(AZ::Data::AssetId assetId, AZStd::string& rootFilePath);
AZ::Data::AssetInfo GetSourceInfo(const AZStd::string& sourceFilePath, AZStd::string& watchFolder);
AZ::Data::AssetInfo GetSourceInfoByProductId(AZ::Data::AssetId assetId, AZ::Data::AssetType assetType);
void DumpAssetInfo(AZ::Data::AssetId assetId, const char* extra);
}
}
@@ -0,0 +1,224 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <LyViewPaneNames.h>
#include <Editor/Assets/ScriptCanvasAssetHolder.h>
#include <ScriptCanvas/Asset/AssetRegistry.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
#include <ScriptCanvas/Core/ScriptCanvasBus.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Serialization/IdUtils.h>
#include <AzCore/Asset/AssetManager.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <Editor/Assets/ScriptCanvasAssetTrackerBus.h>
#include <Editor/Assets/ScriptCanvasAssetTracker.h>
#include <Editor/Assets/ScriptCanvasAssetTrackerDefinitions.h>
namespace ScriptCanvasEditor
{
//=========================================================================
void ScriptCanvasAssetHolder::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<ScriptCanvasAssetHolder>()
->Version(1)
->Field("m_asset", &ScriptCanvasAssetHolder::m_scriptCanvasAsset)
;
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
{
editContext->Class<ScriptCanvasAssetHolder>("Script Canvas", "Script Canvas Asset Holder")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasAssetHolder::m_scriptCanvasAsset, "Script Canvas Asset", "Script Canvas asset associated with this component")
->Attribute(AZ::Edit::Attributes::ChangeNotify, &ScriptCanvasAssetHolder::OnScriptChanged)
->Attribute("BrowseIcon", ":/stylesheet/img/UI20/browse-edit-select-files.svg")
->Attribute("EditButton", "")
->Attribute("EditDescription", "Open in Script Canvas Editor")
->Attribute("EditCallback", &ScriptCanvasAssetHolder::LaunchScriptCanvasEditor)
;
}
}
}
ScriptCanvasAssetHolder::~ScriptCanvasAssetHolder()
{
}
void ScriptCanvasAssetHolder::Init(AZ::EntityId ownerId, AZ::ComponentId componentId)
{
m_ownerId = AZStd::make_pair(ownerId, componentId);
if (!m_scriptCanvasAsset || !m_scriptCanvasAsset.IsReady())
{
AssetTrackerNotificationBus::Handler::BusConnect(m_scriptCanvasAsset.GetId());
Callbacks::OnAssetReadyCallback onAssetReady = [this](ScriptCanvasMemoryAsset& asset)
{
AssetHelpers::DumpAssetInfo(asset.GetFileAssetId(), "ScriptCanvasAssetHolder::Init");
};
AssetTrackerRequestBus::Broadcast(&AssetTrackerRequests::Load, m_scriptCanvasAsset.GetId(), azrtti_typeid<ScriptCanvasAsset>(), onAssetReady);
}
}
void ScriptCanvasAssetHolder::LaunchScriptCanvasEditor(const AZ::Data::AssetId&, const AZ::Data::AssetType&) const
{
OpenEditor();
}
void ScriptCanvasAssetHolder::OpenEditor() const
{
AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas);
AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
if (m_scriptCanvasAsset.GetId().IsValid())
{
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
{
ScriptCanvas::ScriptCanvasId graphId;
if (m_scriptCanvasAsset.IsReady())
{
ScriptCanvas::SystemRequestBus::BroadcastResult(graphId, &ScriptCanvas::SystemRequests::FindScriptCanvasId, m_scriptCanvasAsset.Get()->GetScriptCanvasEntity());
}
return graphId;
}
void ScriptCanvasAssetHolder::SetScriptChangedCB(const ScriptChangedCB& scriptChangedCB)
{
m_scriptNotifyCallback = scriptChangedCB;
}
void ScriptCanvasAssetHolder::Load(AZ::Data::AssetId fileAssetId)
{
if (!m_scriptCanvasAsset.IsReady())
{
auto asset = AZ::Data::AssetManager::Instance().FindAsset(fileAssetId, AZ::Data::AssetLoadBehavior::Default);
if (!asset)
{
ScriptCanvasMemoryAsset::pointer memoryAsset;
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, fileAssetId);
if (!memoryAsset)
{
Callbacks::OnAssetReadyCallback onAssetReady = [this](ScriptCanvasMemoryAsset& asset)
{
m_memoryScriptCanvasAsset = asset.GetAsset();
AssetHelpers::DumpAssetInfo(asset.GetFileAssetId(), "ScriptCanvasAssetHolder::Load onAssetReady");
};
AssetTrackerRequestBus::Broadcast(&AssetTrackerRequests::Load, fileAssetId, azrtti_typeid<ScriptCanvasAsset>(), onAssetReady);
}
else
{
AssetHelpers::DumpAssetInfo(fileAssetId, "ScriptCanvasAssetHolder::Load isLoaded");
m_scriptCanvasAsset = AZ::Data::AssetManager::Instance().GetAsset(fileAssetId, azrtti_typeid<ScriptCanvasAsset>(), m_scriptCanvasAsset.GetAutoLoadBehavior());
}
}
}
}
AZ::u32 ScriptCanvasAssetHolder::OnScriptChanged()
{
AssetTrackerNotificationBus::Handler::BusDisconnect();
if (m_scriptCanvasAsset.GetId().IsValid())
{
AssetTrackerNotificationBus::Handler::BusConnect(m_scriptCanvasAsset.GetId());
Load(m_scriptCanvasAsset.GetId());
}
else
{
m_scriptCanvasAsset = {};
}
if (m_scriptNotifyCallback)
{
m_scriptNotifyCallback(m_scriptCanvasAsset.GetId());
}
return AZ::Edit::PropertyRefreshLevels::EntireTree;
}
void ScriptCanvasAssetHolder::OnAssetReady(const ScriptCanvasMemoryAsset::pointer asset)
{
if (asset->GetFileAssetId() == m_scriptCanvasAsset.GetId())
{
AssetTrackerNotificationBus::Handler::BusDisconnect(m_scriptCanvasAsset.GetId());
m_scriptCanvasAsset = AZ::Data::AssetManager::Instance().FindAsset(asset->GetFileAssetId(), m_scriptCanvasAsset.GetAutoLoadBehavior());
m_memoryScriptCanvasAsset = asset->GetAsset();
}
}
void ScriptCanvasAssetHolder::SetAsset(AZ::Data::AssetId fileAssetId)
{
AssetTrackerNotificationBus::Handler::BusDisconnect();
m_scriptCanvasAsset = AZ::Data::AssetManager::Instance().FindAsset(fileAssetId, m_scriptCanvasAsset.GetAutoLoadBehavior());
if (!m_scriptCanvasAsset)
{
m_scriptCanvasAsset = AZ::Data::AssetManager::Instance().GetAsset(fileAssetId, azrtti_typeid<ScriptCanvasAsset>(), m_scriptCanvasAsset.GetAutoLoadBehavior());
}
if (m_scriptCanvasAsset)
{
AssetTrackerNotificationBus::Handler::BusConnect(m_scriptCanvasAsset.GetId());
}
}
const AZ::Data::AssetType& ScriptCanvasAssetHolder::GetAssetType() const
{
return m_scriptCanvasAsset.GetType();
}
void ScriptCanvasAssetHolder::ClearAsset()
{
m_scriptCanvasAsset = {};
}
AZ::Data::AssetId ScriptCanvasAssetHolder::GetAssetId() const
{
return m_scriptCanvasAsset.GetId();
}
}
@@ -0,0 +1,80 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/EntityId.h>
#include <AzCore/Asset/AssetCommon.h>
#include <Editor/Assets/ScriptCanvasAssetTrackerBus.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/Core/Core.h>
namespace ScriptCanvasEditor
{
class ScriptCanvasAsset;
/*! ScriptCanvasAssetHolder
Wraps a ScriptCanvasAsset reference and registers for the individual AssetBus events
for saving, loading and unloading the asset.
The ScriptCanvasAsset Holder contains functionality for activating the ScriptCanvasEntity stored on the reference asset
as well as attempting to open the ScriptCanvasAsset within the ScriptCanvas Editor.
It also provides the EditContext reflection for opening the asset in the ScriptCanvas Editor via a button
*/
class ScriptCanvasAssetHolder
: AssetTrackerNotificationBus::Handler
{
public:
AZ_RTTI(ScriptCanvasAssetHolder, "{3E80CEE3-2932-4DC1-AADF-398FDDC6DEFE}");
AZ_CLASS_ALLOCATOR(ScriptCanvasAssetHolder, AZ::SystemAllocator, 0);
using ScriptChangedCB = AZStd::function<void(AZ::Data::AssetId)>;
ScriptCanvasAssetHolder() = default;
~ScriptCanvasAssetHolder() override;
static void Reflect(AZ::ReflectContext* context);
void Init(AZ::EntityId ownerId = AZ::EntityId(), AZ::ComponentId componentId = AZ::ComponentId());
const AZ::Data::AssetType& GetAssetType() const;
void ClearAsset();
void SetAsset(AZ::Data::AssetId fileAssetId);
AZ::Data::AssetId GetAssetId() const;
ScriptCanvas::ScriptCanvasId GetScriptCanvasId() const;
void LaunchScriptCanvasEditor(const AZ::Data::AssetId&, const AZ::Data::AssetType&) const;
void OpenEditor() const;
void SetScriptChangedCB(const ScriptChangedCB&);
void Load(AZ::Data::AssetId fileAssetId);
protected:
//=====================================================================
// AssetTrackerNotificationBus
void OnAssetReady(const ScriptCanvasMemoryAsset::pointer asset) override;
//=====================================================================
//! Reloads the Script From the AssetData if it has changed
AZ::u32 OnScriptChanged();
AZ::Data::Asset<ScriptCanvasAsset> m_scriptCanvasAsset;
AZ::Data::Asset<ScriptCanvasAsset> m_memoryScriptCanvasAsset;
TypeDefs::EntityComponentId m_ownerId; // Id of Entity which stores this AssetHolder object
ScriptChangedCB m_scriptNotifyCallback;
};
}
@@ -0,0 +1,159 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Component/Entity.h>
#include <AzCore/Serialization/IdUtils.h>
#include <Editor/Assets/ScriptCanvasAssetInstance.h>
namespace ScriptCanvasEditor
{
ScriptCanvasAssetInstance::~ScriptCanvasAssetInstance()
{
}
void ScriptCanvasAssetInstance::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<ScriptCanvasAssetInstance>()
// TODO: This results in more data being saved per instance, but is needed to make Id remapping transparent.
// Allow a way to enumerate the elements for Id Remapping, while disallowing serialization
->Field("m_data", &ScriptCanvasAssetInstance::m_scriptCanvasData)
->Field("m_assetRef", &ScriptCanvasAssetInstance::m_assetRef)
->Field("m_entityInstanceMap", &ScriptCanvasAssetInstance::m_baseToInstanceMap)
->Field("m_dataFlags", &ScriptCanvasAssetInstance::m_entityToDataFlags)
->Field("m_dataPatch", &ScriptCanvasAssetInstance::m_dataPatch)
;
}
}
ScriptCanvasAssetReference& ScriptCanvasAssetInstance::GetReference()
{
return m_assetRef;
}
const ScriptCanvasAssetReference& ScriptCanvasAssetInstance::GetReference() const
{
return m_assetRef;
}
ScriptCanvas::ScriptCanvasData& ScriptCanvasAssetInstance::GetScriptCanvasData()
{
return m_scriptCanvasData;
}
const ScriptCanvas::ScriptCanvasData& ScriptCanvasAssetInstance::GetScriptCanvasData() const
{
return m_scriptCanvasData;
}
void ScriptCanvasAssetInstance::ComputeDataPatch()
{
if (!m_assetRef.GetAsset().IsReady())
{
return;
}
ScriptCanvas::ScriptCanvasData& baseData = m_assetRef.GetAsset().Get()->GetScriptCanvasData();
AZ::SerializeContext* serializeContext{};
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
decltype(m_baseToInstanceMap) entityIdReverseLookUp;
for (const auto& baseToInstancePair : m_baseToInstanceMap)
{
entityIdReverseLookUp.emplace(baseToInstancePair.second, baseToInstancePair.first);
}
// remap entity ids to the "original"
AZ::IdUtils::Remapper<AZ::EntityId>::ReplaceIdsAndIdRefs(&m_scriptCanvasData, [&entityIdReverseLookUp](AZ::EntityId sourceId, [[maybe_unused]] bool isEntityId, const AZ::IdUtils::Remapper<AZ::EntityId>::IdGenerator&) -> AZ::EntityId
{
auto findIt = entityIdReverseLookUp.find(sourceId);
return findIt != entityIdReverseLookUp.end() ? findIt->second : sourceId;
}, serializeContext);
// compute the delta (what we changed from the base slice)
m_dataPatch.Create(&baseData, &m_scriptCanvasData, AZ::DataPatch::FlagsMap(), GetDataFlagsForPatching(), serializeContext);
// remap entity ids back to the "instance onces"
AZ::IdUtils::Remapper<AZ::EntityId>::ReplaceIdsAndIdRefs(&m_scriptCanvasData, [this](AZ::EntityId sourceId, [[maybe_unused]] bool isEntityId, const AZ::IdUtils::Remapper<AZ::EntityId>::IdGenerator&) -> AZ::EntityId {
auto findIt = m_baseToInstanceMap.find(sourceId);
return findIt != m_baseToInstanceMap.end() ? findIt->second : sourceId;
}, serializeContext);
}
void ScriptCanvasAssetInstance::ApplyDataPatch()
{
if (!m_assetRef.GetAsset().IsReady())
{
return;
}
ScriptCanvas::ScriptCanvasData& baseData = m_assetRef.GetAsset().Get()->GetScriptCanvasData();
AZ::SerializeContext* serializeContext{};
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
// An empty map indicates its a fresh instance (i.e. has never be instantiated and then serialized).
if (m_baseToInstanceMap.empty())
{
// Generate new Ids and populate the map.
AZ_Assert(!m_dataPatch.IsValid(), "Data patch is valid for scene slice instance, but base scene to instantiated scene Id map is not!");
serializeContext->CloneObjectInplace(m_scriptCanvasData, &baseData);
AZ::IdUtils::Remapper<AZ::EntityId>::GenerateNewIdsAndFixRefs(&m_scriptCanvasData, m_baseToInstanceMap);
}
else
{
// Clone entities while applying any data patches.
AZ_Assert(m_dataPatch.IsValid(), "Data patch is not valid for existing scene slice instance!");
ScriptCanvas::ScriptCanvasData* patchedSceneData = m_dataPatch.Apply(&baseData, serializeContext);
// Remap Ids & references.
AZ::IdUtils::Remapper<AZ::EntityId>::GenerateNewIdsAndFixRefs(patchedSceneData, m_baseToInstanceMap);
serializeContext->CloneObjectInplace(m_scriptCanvasData, patchedSceneData);
}
}
AZ::DataPatch::FlagsMap ScriptCanvasAssetInstance::GetDataFlagsForPatching() const
{
// Collect all entities' data flags
AZ::DataPatch::FlagsMap dataFlags;
for (auto& baseIdInstanceIdPair : m_baseToInstanceMap)
{
// Make the addressing relative to InstantiatedContainer (m_dataFlags stores flags relative to the individual entity)
AZ::DataPatch::AddressType addressPrefix;
addressPrefix.push_back(AZ_CRC("Entities", 0x50ec64e5));
addressPrefix.push_back(static_cast<AZ::u64>(baseIdInstanceIdPair.first));
auto findIt = m_entityToDataFlags.find(baseIdInstanceIdPair.second);
if (findIt != m_entityToDataFlags.end())
{
for (auto& addressDataFlagsPair : findIt->second)
{
const AZ::DataPatch::AddressType& originalAddress = addressDataFlagsPair.first;
AZ::DataPatch::AddressType prefixedAddress;
prefixedAddress.reserve(addressPrefix.size() + originalAddress.size());
prefixedAddress.insert(prefixedAddress.end(), addressPrefix.begin(), addressPrefix.end());
prefixedAddress.insert(prefixedAddress.end(), originalAddress.begin(), originalAddress.end());
dataFlags.emplace(AZStd::move(prefixedAddress), addressDataFlagsPair.second);
}
}
}
return dataFlags;
}
} // namespace ScriptCanvasEditor
@@ -0,0 +1,51 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <Editor/Assets/ScriptCanvasAssetReference.h>
namespace ScriptCanvasEditor
{
class ScriptCanvasAssetInstance
{
public:
AZ_TYPE_INFO(ScriptCanvasAssetInstance, "{96B16AAB-DB63-4D32-9FC9-7A5DE440B0B7}");
AZ_CLASS_ALLOCATOR(ScriptCanvasAssetInstance, AZ::SystemAllocator, 0);
ScriptCanvasAssetInstance() = default;
~ScriptCanvasAssetInstance();
static void Reflect(AZ::ReflectContext* context);
const AZStd::unordered_map<AZ::EntityId, AZ::EntityId>& GetBaseToInstanceMap() const { return m_baseToInstanceMap; }
ScriptCanvasAssetReference& GetReference();
const ScriptCanvasAssetReference& GetReference() const;
ScriptCanvas::ScriptCanvasData& GetScriptCanvasData();
const ScriptCanvas::ScriptCanvasData& GetScriptCanvasData() const;
void ComputeDataPatch();
void ApplyDataPatch();
private:
ScriptCanvasAssetInstance(const ScriptCanvasAssetInstance&) = delete;
AZ::DataPatch::FlagsMap GetDataFlagsForPatching() const;
ScriptCanvas::ScriptCanvasData m_scriptCanvasData;
ScriptCanvasAssetReference m_assetRef;
AZStd::unordered_map<AZ::EntityId, AZ::EntityId> m_baseToInstanceMap;
AZStd::unordered_map<AZ::EntityId, AZ::DataPatch::FlagsMap> m_entityToDataFlags;
AZ::DataPatch m_dataPatch;
bool m_canApplyPatch;
};
}
@@ -0,0 +1,62 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Serialization/IdUtils.h>
#include <Editor/Assets/ScriptCanvasAssetReference.h>
#include <Editor/Assets/ScriptCanvasAssetReferenceContainer.h>
namespace ScriptCanvasEditor
{
void ScriptCanvasAssetReference::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<ScriptCanvasAssetReference>()
->DataContainer<ScriptCanvasAssetReferenceContainer>()
;
}
}
ScriptCanvasAssetReference::ScriptCanvasAssetReference(AZ::Data::Asset<ScriptCanvasAsset> sliceAsset, bool storeInObjectStream)
{
SetAsset(sliceAsset);
SetAssetDataStoredInternally(storeInObjectStream);
}
void ScriptCanvasAssetReference::SetAsset(AZ::Data::Asset<ScriptCanvasAsset> sliceAsset)
{
m_asset = sliceAsset;
}
const AZ::Data::Asset<ScriptCanvasAsset>& ScriptCanvasAssetReference::GetAsset() const
{
return m_asset;
}
AZ::Data::Asset<ScriptCanvasAsset>& ScriptCanvasAssetReference::GetAsset()
{
return m_asset;
}
void ScriptCanvasAssetReference::SetAssetDataStoredInternally(bool storeInObjectStream)
{
m_storeInObjectStream = storeInObjectStream;
}
bool ScriptCanvasAssetReference::GetAssetDataStoredInternally() const
{
return m_storeInObjectStream;
}
} // namespace ScriptCanvasEditor
@@ -0,0 +1,75 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Serialization/DataPatch.h>
#include <AzCore/Asset/AssetCommon.h>
namespace ScriptCanvas
{
class ScriptCanvasData;
}
namespace ScriptCanvasEditor
{
class ScriptCanvasAsset;
class ScriptCanvasAssetReference
{
public:
AZ_TYPE_INFO(ScriptCanvasAssetReference, "{C1B24507-887C-4E20-A259-BFEEDD7EDF9D}");
AZ_CLASS_ALLOCATOR(ScriptCanvasAssetReference, AZ::SystemAllocator, 0);
ScriptCanvasAssetReference() = default;
ScriptCanvasAssetReference(AZ::Data::Asset<ScriptCanvasAsset> scriptCanvasAsset, bool storeInObjectStream = false);
static void Reflect(AZ::ReflectContext* context);
/*!
\param scriptCanvasAsset asset reference to store
\param storeInObjectStream bool which determines if the asset data will serialized out as part of the ObjectStream when serializing
*/
void SetAsset(AZ::Data::Asset<ScriptCanvasAsset> scriptCanvasAsset);
const AZ::Data::Asset<ScriptCanvasAsset>& GetAsset() const;
AZ::Data::Asset<ScriptCanvasAsset>& GetAsset();
/*!
\param storeInObjectStream bool which determines if the asset data will serialized out as part of the ObjectStream when serializing
*/
void SetAssetDataStoredInternally(bool storeInObjectStream);
/*!
Indicates if this scriptCanvas reference contains an asset whose data is stored internally in this class.
\return true if the asset is asset data is serialize as part of this class object stream
*/
bool GetAssetDataStoredInternally() const;
private:
bool m_storeInObjectStream = false; ///< If true the asset data is stored in the object stream with this class
AZ::Data::Asset<ScriptCanvasAsset> m_asset;
friend class ScriptCanvasAssetReferenceContainer;
};
}
namespace AZStd
{
template<>
struct hash<ScriptCanvasEditor::ScriptCanvasAssetReference>
{
using argument_type = ScriptCanvasEditor::ScriptCanvasAssetReference;
using result_type = AZStd::size_t;
AZ_FORCE_INLINE size_t operator()(const argument_type& key) const
{
AZStd::hash<AZ::Data::AssetId> hasher;
return hasher(key.GetAsset().GetId());
}
};
} // namespace AZStd
@@ -0,0 +1,239 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Asset/AssetManager.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <Editor/Assets/ScriptCanvasAssetReference.h>
namespace ScriptCanvasEditor
{
class ScriptCanvasAssetReferenceContainer
: public AZ::SerializeContext::IDataContainer
{
public:
ScriptCanvasAssetReferenceContainer()
{
m_storeInObjectStreamElement.m_name = "m_storeInObjectStream";
m_storeInObjectStreamElement.m_nameCrc = AZ_CRC("m_storeInObjectStream", 0xf5a45371);
m_storeInObjectStreamElement.m_typeId = azrtti_typeid<bool>();
m_storeInObjectStreamElement.m_offset = 0;
m_storeInObjectStreamElement.m_dataSize = sizeof(bool);
m_storeInObjectStreamElement.m_azRtti = nullptr;
m_storeInObjectStreamElement.m_genericClassInfo = AZ::SerializeGenericTypeInfo<bool>::GetGenericInfo();
m_storeInObjectStreamElement.m_editData = nullptr;
m_storeInObjectStreamElement.m_flags = 0;
m_assetElement.m_name = "m_asset";
m_assetElement.m_nameCrc = AZ_CRC("m_asset", 0x4e58e538);
m_assetElement.m_typeId = AZ::SerializeGenericTypeInfo<AZ::Data::Asset<ScriptCanvasAsset>>::GetClassTypeId();
m_assetElement.m_offset = m_storeInObjectStreamElement.m_dataSize;
m_assetElement.m_dataSize = sizeof(AZ::Data::Asset<ScriptCanvasAsset>);
m_assetElement.m_azRtti = AZ::GetRttiHelper<AZ::Data::Asset<ScriptCanvasAsset>>();
m_assetElement.m_genericClassInfo = AZ::SerializeGenericTypeInfo<AZ::Data::Asset<ScriptCanvasAsset>>::GetGenericInfo();
m_assetElement.m_editData = nullptr;
m_assetElement.m_flags = 0;
m_baseDataElement.m_name = "m_scriptCanvasData";
m_baseDataElement.m_nameCrc = AZ_CRC("m_scriptCanvasData", 0x78a93f93);
m_baseDataElement.m_typeId = AZ::SerializeGenericTypeInfo<ScriptCanvas::ScriptCanvasData>::GetClassTypeId();
m_baseDataElement.m_offset = m_assetElement.m_offset + m_assetElement.m_dataSize;
m_baseDataElement.m_dataSize = sizeof(ScriptCanvas::ScriptCanvasData);
m_baseDataElement.m_azRtti = AZ::GetRttiHelper<ScriptCanvas::ScriptCanvasData>();
m_baseDataElement.m_genericClassInfo = AZ::SerializeGenericTypeInfo<ScriptCanvas::ScriptCanvasData>::GetGenericInfo();
m_baseDataElement.m_editData = nullptr;
m_baseDataElement.m_flags = 0;
}
/// Null if element with this name can't be found.
const AZ::SerializeContext::ClassElement* GetElement(AZ::u32 elementNameCrc) const override
{
if (m_storeInObjectStreamElement.m_nameCrc == elementNameCrc)
{
return &m_storeInObjectStreamElement;
}
if (m_assetElement.m_nameCrc == elementNameCrc)
{
return &m_assetElement;
}
if (m_baseDataElement.m_nameCrc == elementNameCrc)
{
return &m_baseDataElement;
}
return nullptr;
}
bool GetElement(AZ::SerializeContext::ClassElement& classElement, const AZ::SerializeContext::DataElement& dataElement) const override
{
if (m_storeInObjectStreamElement.m_nameCrc == dataElement.m_nameCrc)
{
classElement = m_storeInObjectStreamElement;
return true;
}
if (m_assetElement.m_nameCrc == dataElement.m_nameCrc)
{
classElement = m_assetElement;
return true;
}
if (m_baseDataElement.m_nameCrc == dataElement.m_nameCrc)
{
classElement = m_baseDataElement;
return true;
}
return false;
}
/// Enumerate elements in the array.
void EnumElements(void* instance, const ElementCB& cb) override
{
auto assetRef = reinterpret_cast<ScriptCanvasAssetReference*>(instance);
if (!cb(&assetRef->m_storeInObjectStream, m_storeInObjectStreamElement.m_typeId, m_storeInObjectStreamElement.m_genericClassInfo ? m_storeInObjectStreamElement.m_genericClassInfo->GetClassData() : nullptr, &m_storeInObjectStreamElement))
{
return;
}
if (!cb(&assetRef->m_asset, m_assetElement.m_typeId, m_assetElement.m_genericClassInfo ? m_assetElement.m_genericClassInfo->GetClassData() : nullptr, &m_assetElement))
{
return;
}
if (assetRef->m_storeInObjectStream && assetRef->m_asset.Get())
{
cb(&assetRef->m_asset.Get()->GetScriptCanvasData(), m_baseDataElement.m_typeId, m_baseDataElement.m_genericClassInfo ? m_baseDataElement.m_genericClassInfo->GetClassData() : nullptr, &m_baseDataElement);
}
}
void EnumTypes(const ElementTypeCB& cb) override
{
cb(m_storeInObjectStreamElement.m_typeId, &m_storeInObjectStreamElement);
cb(m_assetElement.m_typeId, &m_assetElement);
cb(m_baseDataElement.m_typeId, &m_baseDataElement);
}
/// Return number of elements in the container.
size_t Size(void* instance) const override
{
auto assetRef = reinterpret_cast<ScriptCanvasAssetReference*>(instance);
return assetRef->m_storeInObjectStream && assetRef->m_asset.Get() ? m_numClassElements : m_numClassElements - 1;
}
/// Returns the capacity of the container. Returns 0 for objects without fixed capacity.
size_t Capacity(void*) const override
{
return m_numClassElements;
}
/// Returns true if elements pointers don't change on add/remove. If false you MUST enumerate all elements.
bool IsStableElements() const override { return true; }
/// Returns true if the container is fixed size, otherwise false.
bool IsFixedSize() const override { return false; }
/// Returns if the container is fixed capacity, otherwise false
bool IsFixedCapacity() const override { return true; }
/// Returns true if the container is a smart pointer.
bool IsSmartPointer() const override { return false; }
/// Returns true if elements can be retrieved by index.
bool CanAccessElementsByIndex() const override { return false; }
/// Reserve element
void* ReserveElement(void* instance, const AZ::SerializeContext::ClassElement* classElement) override
{
auto assetRef = reinterpret_cast<ScriptCanvasAssetReference*>(instance);
if (classElement->m_nameCrc == m_storeInObjectStreamElement.m_nameCrc)
{
return &assetRef->m_storeInObjectStream;
}
if (classElement->m_nameCrc == m_assetElement.m_nameCrc)
{
if (assetRef->m_storeInObjectStream)
{
assetRef->m_asset.SetFlags(static_cast<AZ::u8>(AZ::Data::AssetLoadBehavior::NoLoad));
}
return &assetRef->m_asset;
}
if (assetRef->m_storeInObjectStream && classElement->m_nameCrc == m_baseDataElement.m_nameCrc)
{
auto* scriptCanvasAsset = aznew ScriptCanvasAsset(assetRef->m_asset.GetId(), AZ::Data::AssetData::AssetStatus::Ready);
assetRef->m_asset = { scriptCanvasAsset, AZ::Data::AssetLoadBehavior::Default };
return &assetRef->m_asset.Get()->GetScriptCanvasData();
}
return instance;
}
/// Get an element's address by its index (called before the element is loaded).
void* GetElementByIndex(void*, const AZ::SerializeContext::ClassElement*, size_t) override
{
return nullptr;
}
/// Store element
void StoreElement(void* instance, void* element) override
{
auto assetRef = reinterpret_cast<ScriptCanvasAssetReference*>(instance);
if (assetRef->m_storeInObjectStream && assetRef->m_asset.Get() && element == &assetRef->m_asset.Get()->GetScriptCanvasData())
{
auto existingAsset = AZ::Data::AssetManager::Instance().FindAsset<ScriptCanvasAsset>(assetRef->m_asset.GetId(), assetRef->m_asset.GetAutoLoadBehavior());
if (existingAsset.IsReady())
{
assetRef->m_asset = existingAsset;
}
}
}
/// Remove element in the container.
bool RemoveElement(void* instance, const void* element, AZ::SerializeContext* deletePointerDataContext) override
{
if (deletePointerDataContext)
{
auto assetRef = reinterpret_cast<ScriptCanvasAssetReference*>(instance);
if (&assetRef->m_storeInObjectStream == element)
{
DeletePointerData(deletePointerDataContext, &m_storeInObjectStreamElement, &assetRef->m_storeInObjectStream);
}
else if (&assetRef->m_asset == element)
{
DeletePointerData(deletePointerDataContext, &m_assetElement, &assetRef->m_asset);
}
}
return false;
}
/// Remove elements (removed array of elements) regardless if the container is Stable or not (IsStableElements)
size_t RemoveElements(void* instance, const void** elements, size_t numElements, AZ::SerializeContext* deletePointerDataContext) override
{
if (deletePointerDataContext)
{
for (size_t i = 0; i < numElements; ++i)
{
RemoveElement(instance, elements[i], deletePointerDataContext);
}
}
return 0;
}
/// Clear elements in the instance.
void ClearElements(void*, AZ::SerializeContext*) override
{
}
AZ::SerializeContext::ClassElement m_storeInObjectStreamElement;
AZ::SerializeContext::ClassElement m_assetElement;
AZ::SerializeContext::ClassElement m_baseDataElement;
const size_t m_numClassElements = 3;
};
} // namespace GraphCanvas
@@ -0,0 +1,562 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include "ScriptCanvasAssetTracker.h"
#include <AzCore/IO/FileIO.h>
#include <AzCore/Component/TickBus.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
#include <AzToolsFramework/AssetBrowser/Entries/ProductAssetBrowserEntry.h>
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
#include <Editor/Assets/ScriptCanvasAssetHelpers.h>
#include <Editor/Assets/ScriptCanvasMemoryAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Asset/Functions/ScriptCanvasFunctionAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
#include <ScriptCanvas/Core/ScriptCanvasBus.h>
#include <AzCore/std/smart_ptr/make_shared.h>
namespace ScriptCanvasEditor
{
/////////////////
// AssetTracker
/////////////////
AZ::Data::AssetId AssetTracker::Create(AZStd::string_view assetAbsolutePath, AZ::Data::AssetType assetType, Callbacks::OnAssetCreatedCallback onAssetCreatedCallback)
{
AZ::Data::AssetId newAssetId = AZ::Uuid::CreateRandom();
MemoryAssetMapIterator iterator = m_assetsInUse.emplace(newAssetId, AZStd::make_shared<ScriptCanvasMemoryAsset>());
ScriptCanvasMemoryAsset::pointer memoryAsset = iterator.first->second;
memoryAsset->Create(newAssetId, assetAbsolutePath, assetType, onAssetCreatedCallback);
return newAssetId;
}
bool AssetTracker::IsSaving(AZ::Data::AssetId assetId) const
{
assetId = CheckAssetId(assetId);
return m_savingAssets.find(assetId) != m_savingAssets.end();
}
void AssetTracker::Save(AZ::Data::AssetId assetId, Callbacks::OnSave onSaveCallback)
{
SaveAs(assetId, {}, 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::Asset<ScriptCanvas::ScriptCanvasAssetBase> 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(), 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(), 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)
{
if (!fileAssetId.IsValid())
{
return false;
}
auto assetIter = m_assetsInUse.find(fileAssetId);
if (assetIter != m_assetsInUse.end())
{
if (!assetIter->second->IsSourceInError())
{
if (onAssetReadyCallback)
{
// The asset is already loaded and tracked
AZStd::invoke(onAssetReadyCallback, *m_assetsInUse[fileAssetId]);
AssetTrackerNotificationBus::Event(fileAssetId, &AssetTrackerNotifications::OnAssetReady, m_assetsInUse[fileAssetId]);
}
return true;
}
else
{
m_assetsInUse.erase(assetIter);
}
}
m_assetsInUse[fileAssetId] = AZStd::make_shared<ScriptCanvasMemoryAsset>();
m_onAssetReadyCallback = onAssetReadyCallback;
auto onReady = [this, fileAssetId](ScriptCanvasMemoryAsset& asset)
{
m_remappedAsset[asset.GetId()] = fileAssetId;
if (m_onAssetReadyCallback)
{
AZStd::invoke(m_onAssetReadyCallback, *m_assetsInUse[fileAssetId]);
}
};
// If we failed to load the asset, signal back as much
if (!m_assetsInUse[fileAssetId]->Load(fileAssetId, assetType, onReady))
{
m_assetsInUse.erase(fileAssetId);
return false;
}
return true;
}
void AssetTracker::Close(AZ::Data::AssetId assetId)
{
assetId = CheckAssetId(assetId);
if (m_assetsInUse.find(assetId) == m_assetsInUse.end())
{
return;
}
if (m_savingAssets.find(assetId) == m_savingAssets.end())
{
m_assetsInUse.erase(assetId);
}
else
{
m_queuedCloses.insert(assetId);
}
}
void AssetTracker::ClearView(AZ::Data::AssetId assetId)
{
assetId = CheckAssetId(assetId);
if (m_assetsInUse.find(assetId) != m_assetsInUse.end())
{
m_assetsInUse[assetId]->ClearView();
}
}
void AssetTracker::UntrackAsset(AZ::Data::AssetId assetId)
{
assetId = CheckAssetId(assetId);
m_assetsInUse.erase(assetId);
}
void AssetTracker::CreateView(AZ::Data::AssetId assetId, QWidget* parent)
{
assetId = CheckAssetId(assetId);
if (m_assetsInUse.find(assetId) != m_assetsInUse.end())
{
m_assetsInUse[assetId]->CreateView(parent);
}
}
ScriptCanvasMemoryAsset::pointer AssetTracker::GetAsset(AZ::Data::AssetId assetId)
{
if (!assetId.IsValid())
{
return nullptr;
}
assetId = CheckAssetId(assetId);
if (m_assetsInUse.find(assetId) == m_assetsInUse.end())
{
auto asset = AZ::Data::AssetManager::Instance().FindAsset(assetId, AZ::Data::AssetLoadBehavior::Default);
if (asset)
{
auto insertResult = m_assetsInUse.emplace(AZStd::make_pair(assetId, AZStd::make_shared<ScriptCanvasMemoryAsset>()));
auto onReady = [this, assetId](ScriptCanvasMemoryAsset& asset)
{
m_remappedAsset[asset.GetId()] = assetId;
};
insertResult.first->second->Load(assetId, AZ::Data::AssetType::CreateNull(), onReady);
insertResult.first->second->ActivateAsset();
return insertResult.first->second;
}
// Handle the weird case of saving out a file you can't load because of pathing issues.
for (auto assetPair : m_assetsInUse)
{
if (assetPair.second->GetFileAssetId() == assetId)
{
return assetPair.second;
}
}
return nullptr;
}
if (m_assetsInUse.find(assetId) != m_assetsInUse.end())
{
return m_assetsInUse[assetId];
}
return nullptr;
}
AZ::Data::AssetId AssetTracker::GetAssetId(ScriptCanvas::ScriptCanvasId scriptCanvasSceneId)
{
for (const auto& asset : m_assetsInUse)
{
if (asset.second && asset.second->GetScriptCanvasId() == scriptCanvasSceneId)
{
AZ::Data::AssetId assetId = asset.second->GetAsset().GetId();
return assetId;
}
}
return {};
}
AZ::Data::AssetType AssetTracker::GetAssetType(ScriptCanvas::ScriptCanvasId scriptCanvasSceneId)
{
for (const auto& asset : m_assetsInUse)
{
if (asset.second && asset.second->GetScriptCanvasId() == scriptCanvasSceneId)
{
return asset.second->GetAssetType();
}
}
return AZ::Data::AssetType::CreateNull();
}
ScriptCanvas::ScriptCanvasId AssetTracker::GetScriptCanvasId(AZ::Data::AssetId assetId)
{
assetId = CheckAssetId(assetId);
if (m_assetsInUse.find(assetId) != m_assetsInUse.end())
{
return m_assetsInUse[assetId]->GetScriptCanvasId();
}
return ScriptCanvas::ScriptCanvasId();
}
AZ::EntityId AssetTracker::GetGraphCanvasId(AZ::EntityId scriptCanvasEntityId)
{
if (scriptCanvasEntityId.IsValid())
{
for (auto& asset : m_assetsInUse)
{
if (asset.second && asset.second->GetScriptCanvasId() == scriptCanvasEntityId)
{
return asset.second->GetGraphId();
}
}
}
return AZ::EntityId();
}
ScriptCanvas::ScriptCanvasId AssetTracker::GetScriptCanvasIdFromGraphId(AZ::EntityId graphId)
{
if (graphId.IsValid())
{
for (auto& asset : m_assetsInUse)
{
if (asset.second && asset.second->GetGraphId() == graphId)
{
return asset.second->GetScriptCanvasId();
}
}
}
return AZ::EntityId();
}
ScriptCanvas::ScriptCanvasId AssetTracker::GetGraphId(AZ::Data::AssetId assetId)
{
if (assetId.IsValid())
{
assetId = CheckAssetId(assetId);
if (m_assetsInUse.find(assetId) != m_assetsInUse.end())
{
return m_assetsInUse[assetId]->GetGraphId();
}
}
return ScriptCanvas::ScriptCanvasId();
}
AZStd::string AssetTracker::GetTabName(AZ::Data::AssetId assetId)
{
assetId = CheckAssetId(assetId);
if (m_assetsInUse.find(assetId) != m_assetsInUse.end())
{
return m_assetsInUse[assetId]->GetTabName();
}
return {};
}
ScriptCanvasEditor::Tracker::ScriptCanvasFileState AssetTracker::GetFileState(AZ::Data::AssetId assetId)
{
assetId = CheckAssetId(assetId);
if (m_assetsInUse.find(assetId) != m_assetsInUse.end())
{
return m_assetsInUse[assetId]->GetFileState();
}
return Tracker::ScriptCanvasFileState::INVALID;
}
void AssetTracker::SignalSaveComplete(const AZ::Data::AssetId& fileAssetId)
{
size_t eraseCount = m_savingAssets.erase(fileAssetId);
if (eraseCount > 0)
{
if (m_queuedCloses.erase(fileAssetId) > 0)
{
Close(fileAssetId);
}
}
}
AZ::Data::AssetId AssetTracker::CheckAssetId(AZ::Data::AssetId assetId) const
{
auto remappedIter = m_remappedAsset.find(assetId);
if (remappedIter != m_remappedAsset.end())
{
assetId = remappedIter->second;
}
return assetId;
}
ScriptCanvasEditor::ScriptCanvasAssetHandler* AssetTracker::GetAssetHandlerForType(AZ::Data::AssetType assetType)
{
ScriptCanvasAssetHandler* assetHandler = nullptr;
AZ::EBusAggregateResults<AZ::Data::AssetHandler*> foundAssetHandlers;
ScriptCanvas::AssetRegistryRequestBus::BroadcastResult(foundAssetHandlers, &ScriptCanvas::AssetRegistryRequests::GetAssetHandler);
for (auto handler : foundAssetHandlers.values)
{
if (handler != nullptr)
{
ScriptCanvasAssetHandler* theHandler = azrtti_cast<ScriptCanvasAssetHandler*>(handler);
if (theHandler != nullptr && theHandler->GetAssetType() == assetType)
{
assetHandler = theHandler;
break;
}
}
}
AZ_Assert(assetHandler, "The specified asset type does not have a registered asset handler.");
return assetHandler;
}
void AssetTracker::UpdateFileState(AZ::Data::AssetId assetId, Tracker::ScriptCanvasFileState state)
{
assetId = CheckAssetId(assetId);
if (m_assetsInUse.find(assetId) != m_assetsInUse.end())
{
m_assetsInUse[assetId]->SetFileState(state);
}
}
AssetTrackerRequests::AssetList AssetTracker::GetUnsavedAssets()
{
auto pred = [](ScriptCanvasMemoryAsset::pointer asset)
{
auto fileState = asset->GetFileState();
if (fileState == Tracker::ScriptCanvasFileState::NEW || fileState == Tracker::ScriptCanvasFileState::MODIFIED)
{
return true;
}
return false;
};
return GetAssetsIf(pred);
}
AssetTrackerRequests::AssetList AssetTracker::GetAssets()
{
return GetAssetsIf([](ScriptCanvasMemoryAsset::pointer) { return true; });
}
AssetTrackerRequests::AssetList AssetTracker::GetAssetsIf(AZStd::function<bool(ScriptCanvasMemoryAsset::pointer asset)> pred)
{
AZStd::vector<ScriptCanvasMemoryAsset::pointer> unsavedAssets;
for (auto& assetIterator : m_assetsInUse)
{
auto testAsset = assetIterator.second;
if (AZStd::invoke(pred, testAsset) == true)
{
unsavedAssets.push_back(testAsset);
}
}
return unsavedAssets;
}
AZ::EntityId AssetTracker::GetSceneEntityIdFromEditorEntityId(AZ::Data::AssetId assetId, AZ::EntityId editorEntityId)
{
assetId = CheckAssetId(assetId);
if (m_assetsInUse.find(assetId) != m_assetsInUse.end())
{
return m_assetsInUse[assetId]->GetSceneEntityIdFromEditorEntityId(editorEntityId);
}
return AZ::EntityId();
}
AZ::EntityId AssetTracker::GetEditorEntityIdFromSceneEntityId(AZ::Data::AssetId assetId, AZ::EntityId sceneEntityId)
{
assetId = CheckAssetId(assetId);
if (m_assetsInUse.find(assetId) != m_assetsInUse.end())
{
return m_assetsInUse[assetId]->GetEditorEntityIdFromSceneEntityId(sceneEntityId);
}
return AZ::EntityId();
}
void AssetTracker::OnAssetReady(const ScriptCanvasMemoryAsset* asset)
{
AZ::Data::AssetId assetId = CheckAssetId(asset->GetId());
AssetTrackerNotificationBus::Broadcast(&AssetTrackerNotifications::OnAssetReady, m_assetsInUse[assetId]);
}
void AssetTracker::OnAssetReloaded(const ScriptCanvasMemoryAsset* asset)
{
AZ::Data::AssetId assetId = CheckAssetId(asset->GetId());
AssetTrackerNotificationBus::Broadcast(&AssetTrackerNotifications::OnAssetReloaded, m_assetsInUse[assetId]);
}
void AssetTracker::OnAssetSaved(const ScriptCanvasMemoryAsset* asset, bool isSuccessful)
{
AZ::Data::AssetId assetId = CheckAssetId(asset->GetId());
AssetTrackerNotificationBus::Broadcast(&AssetTrackerNotifications::OnAssetSaved, m_assetsInUse[assetId], isSuccessful);
}
void AssetTracker::OnAssetError(const ScriptCanvasMemoryAsset* asset)
{
AZ::Data::AssetId assetId = CheckAssetId(asset->GetId());
AssetTrackerNotificationBus::Broadcast(&AssetTrackerNotifications::OnAssetError, m_assetsInUse[assetId]);
}
}
@@ -0,0 +1,131 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/string/string.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h>
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
#include <Editor/Assets/ScriptCanvasAssetTrackerBus.h>
#include <GraphCanvas/Editor/EditorTypes.h>
namespace ScriptCanvasEditor
{
class ScriptCanvasMemoryAsset;
// This class tracks all things related to the assets that the Script Canvas editor
// has in play. It also provides helper functionality to quickly getting asset information
// from GraphCanvas
//
// The AssetTracker will be the ONLY allowed place to connect Script Canvas to the Asset System and any of its buses.
//
// The goal is to centralize all of the asset operations to a single place in order to simplify Script Canvas'
// interactions with the asset system as well as keeping any transient cache of information that is
// only important while Script Canvas graphs are open.
class AssetTracker
: AssetTrackerRequestBus::Handler
, Internal::MemoryAssetNotificationBus::Handler
{
public:
AssetTracker() = default;
~AssetTracker() = default;
void Activate()
{
AssetTrackerRequestBus::Handler::BusConnect();
Internal::MemoryAssetNotificationBus::Handler::BusConnect();
}
void Deactivate()
{
Internal::MemoryAssetNotificationBus::Handler::BusDisconnect();
AssetTrackerRequestBus::Handler::BusDisconnect();
}
// AssetTrackerRequestBus
AZ::Data::AssetId Create(AZStd::string_view assetAbsolutePath, AZ::Data::AssetType assetType, Callbacks::OnAssetCreatedCallback onAssetCreatedCallback) override;
bool IsSaving(AZ::Data::AssetId assetId) const override;
void Save(AZ::Data::AssetId assetId, Callbacks::OnSave onSaveCallback) override;
void SaveAs(AZ::Data::AssetId assetId, const AZStd::string& path, Callbacks::OnSave onSaveCallback) override;
bool Load(AZ::Data::AssetId assetId, AZ::Data::AssetType assetType, Callbacks::OnAssetReadyCallback onAssetReadyCallback) override;
void Close(AZ::Data::AssetId assetId) override;
void CreateView(AZ::Data::AssetId assetId, QWidget* parent) override;
void ClearView(AZ::Data::AssetId assetId) override;
void UntrackAsset(AZ::Data::AssetId assetId) override;
// Getters
// Given the assetId it returns a reference to the in-memory asset, returns false if the asset is not tracked
ScriptCanvasMemoryAsset::pointer GetAsset(AZ::Data::AssetId assetId) override;
// Given a ScriptCanvas EntityId it will lookup the AssetId
AZ::Data::AssetId GetAssetId(ScriptCanvas::ScriptCanvasId scriptCanvasSceneId) override;
// Given a ScriptCanvas EntityId it will lookup the asset's type
AZ::Data::AssetType GetAssetType(ScriptCanvas::ScriptCanvasId scriptCanvasSceneId) override;
// Retrieves the ScriptCanvasEntity for a given asset
ScriptCanvas::ScriptCanvasId GetScriptCanvasId(AZ::Data::AssetId assetId) override;
// Retrieves the Graph Canvas scene Id for a given asset
AZ::EntityId GetGraphCanvasId(AZ::EntityId scriptCanvasEntityId) override;
ScriptCanvas::ScriptCanvasId GetScriptCanvasIdFromGraphId(AZ::EntityId graphId) override;
ScriptCanvas::ScriptCanvasId GetGraphId(AZ::Data::AssetId assetId) override;
Tracker::ScriptCanvasFileState GetFileState(AZ::Data::AssetId assetId) override;
AZStd::string GetTabName(AZ::Data::AssetId assetId) override;
ScriptCanvasEditor::ScriptCanvasAssetHandler* GetAssetHandlerForType(AZ::Data::AssetType assetType) override;
void UpdateFileState(AZ::Data::AssetId assetId, Tracker::ScriptCanvasFileState state) override;
AssetTrackerRequests::AssetList GetUnsavedAssets() override;
AssetTrackerRequests::AssetList GetAssets();
AssetTrackerRequests::AssetList GetAssetsIf(AZStd::function<bool(ScriptCanvasMemoryAsset::pointer asset)> pred = []() { return true; }) override;
AZ::EntityId GetSceneEntityIdFromEditorEntityId(AZ::Data::AssetId assetId, AZ::EntityId editorEntityId) override;
AZ::EntityId GetEditorEntityIdFromSceneEntityId(AZ::Data::AssetId assetId, AZ::EntityId sceneEntityId) override;
//
private:
void SignalSaveComplete(const AZ::Data::AssetId& fileAssetId);
// Verifies if an asset Id has been remapped, this happens when we save a new graph because the AssetId will
// change on save, but there may be some UX elements still referring to the initial asset Id, this ensures
// we are getting the right key into m_assetsInUse
AZ::Data::AssetId CheckAssetId(AZ::Data::AssetId assetId) const;
// Map of all the currently tracked in-memory assets
using MemoryAssetMap = AZStd::unordered_map<AZ::Data::AssetId, ScriptCanvasMemoryAsset::pointer>;
using MemoryAssetMapIterator = AZStd::pair<AZStd::list_iterator<AZStd::pair<AZ::Data::AssetId, ScriptCanvasMemoryAsset::pointer>>, bool>;
AZStd::unordered_set<AZ::Data::AssetId> m_savingAssets;
AZStd::unordered_set<AZ::Data::AssetId> m_queuedCloses;
// Map of all assets being tracked
MemoryAssetMap m_assetsInUse;
// When a graph has been saved to file, its Id will change but it may still have external references with the old Id, this maps the file Id to the in-memory Id
AZStd::unordered_map<AZ::Data::AssetId, AZ::Data::AssetId> m_remappedAsset;
// 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;
};
}
@@ -0,0 +1,160 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <QWidget>
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/Component/EntityId.h>
#include <AzCore/EBus/EBus.h>
#include <AzCore/std/containers/vector.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <Editor/Assets/ScriptCanvasAssetTrackerDefinitions.h>
#include <Editor/Assets/ScriptCanvasMemoryAsset.h>
namespace AZ
{
class EntityId;
}
namespace ScriptCanvas
{
class ScriptCanvasAssetBase;
}
namespace ScriptCanvasEditor
{
class ScriptCanvasAssetHandler;
class AssetTrackerRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//! Callback used to know when a save operation failed or succeeded
using OnSave = AZStd::function<void(bool saveSuccess, AZ::Data::Asset<ScriptCanvas::ScriptCanvasAssetBase>)>;
//! Callback used when the asset has been loaded and is ready for use
using OnAssetReadyCallback = AZStd::function<void(ScriptCanvasMemoryAsset&)>;
//! Callback used when the asset is newly created
using OnAssetCreatedCallback = OnAssetReadyCallback;
// Operations
//! Creates a new Script Canvas asset and tracks it
virtual AZ::Data::AssetId Create([[maybe_unused]] AZStd::string_view assetAbsolutePath, [[maybe_unused]] AZ::Data::AssetType assetType, Callbacks::OnAssetCreatedCallback onAssetCreatedCallback) { return AZ::Data::AssetId(); }
//! Saves a Script Canvas asset to a new file, once the save is complete it will use the source Id (not the Id of the in-memory asset)
virtual void SaveAs([[maybe_unused]] AZ::Data::AssetId assetId, [[maybe_unused]] const AZStd::string& path, Callbacks::OnSave onSaveCallback) {}
//! Saves a previously loaded Script Canvas asset to file
virtual void Save([[maybe_unused]] AZ::Data::AssetId assetId, Callbacks::OnSave onSaveCallback) {}
//! Returns whether or not the specified asset is currently saving
virtual bool IsSaving([[maybe_unused]] AZ::Data::AssetId assetId) const { return false; }
//! Loads a Script Canvas graph
virtual bool Load([[maybe_unused]] AZ::Data::AssetId assetId, [[maybe_unused]] AZ::Data::AssetType assetType, Callbacks::OnAssetReadyCallback onAssetReadyCallback) { return false; }
//! Closes and unloads a Script Canvas graph from the tracker
virtual void Close([[maybe_unused]] AZ::Data::AssetId assetId) {}
//! Creates the asset's view
virtual void CreateView([[maybe_unused]] AZ::Data::AssetId assetId, [[maybe_unused]] QWidget* parent) {}
//! Releases the asset's view
virtual void ClearView([[maybe_unused]] AZ::Data::AssetId assetId) {}
//! Used to make sure assets that are unloaded also get removed from tracking
virtual void UntrackAsset([[maybe_unused]] AZ::Data::AssetId assetId) {}
using AssetList = AZStd::vector<ScriptCanvasMemoryAsset::pointer>;
// Accessors
virtual ScriptCanvasMemoryAsset::pointer GetAsset([[maybe_unused]] AZ::Data::AssetId assetId) { return nullptr; }
virtual ScriptCanvas::ScriptCanvasId GetScriptCanvasId([[maybe_unused]] AZ::Data::AssetId assetId) { return AZ::EntityId(); }
virtual ScriptCanvas::ScriptCanvasId GetScriptCanvasIdFromGraphId([[maybe_unused]] AZ::EntityId graphId) { return AZ::EntityId(); }
virtual ScriptCanvas::ScriptCanvasId GetGraphCanvasId(AZ::EntityId) { return AZ::EntityId(); }
virtual ScriptCanvas::ScriptCanvasId GetGraphId([[maybe_unused]] AZ::Data::AssetId assetId) { return ScriptCanvas::ScriptCanvasId(); }
virtual Tracker::ScriptCanvasFileState GetFileState([[maybe_unused]] AZ::Data::AssetId assetId) { return Tracker::ScriptCanvasFileState::INVALID; }
virtual AZ::Data::AssetId GetAssetId([[maybe_unused]] ScriptCanvas::ScriptCanvasId scriptCanvasSceneId) { return {}; }
virtual AZ::Data::AssetType GetAssetType([[maybe_unused]] ScriptCanvas::ScriptCanvasId scriptCanvasSceneId) { return {}; }
virtual AZStd::string GetTabName([[maybe_unused]] AZ::Data::AssetId assetId) { return {}; }
virtual AssetList GetUnsavedAssets() { return {}; }
virtual AssetList GetAssets() { return {}; }
virtual AssetList GetAssetsIf(AZStd::function<bool(ScriptCanvasMemoryAsset::pointer asset)>) { return {}; }
virtual AZ::EntityId GetSceneEntityIdFromEditorEntityId([[maybe_unused]] AZ::Data::AssetId assetId, [[maybe_unused]] AZ::EntityId editorEntityId) { return AZ::EntityId(); }
virtual AZ::EntityId GetEditorEntityIdFromSceneEntityId([[maybe_unused]] AZ::Data::AssetId assetId, [[maybe_unused]] AZ::EntityId sceneEntityId) { return AZ::EntityId(); }
// Setters / Updates
virtual void UpdateFileState([[maybe_unused]] AZ::Data::AssetId assetId, [[maybe_unused]] Tracker::ScriptCanvasFileState state) {}
// Helpers
virtual ScriptCanvasAssetHandler* GetAssetHandlerForType([[maybe_unused]] AZ::Data::AssetType assetType) { return nullptr; }
};
using AssetTrackerRequestBus = AZ::EBus<AssetTrackerRequests>;
//! These are the notifications sent by the AssetTracker only.
//! We use these to communicate the asset status, do not use the AssetBus directly, all Script Canvas
//! assets are managed by the AssetTracker
class AssetTrackerNotifications
: 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;
// These will be forwarded as a result of the Asset System's events
// this is deliberate in order to keep the AssetTracker as the only
// place that interacts directly with the asset bus, but allowing
// other systems to know the status of tracked assets
virtual void OnAssetReady(const ScriptCanvasMemoryAsset::pointer asset) {}
virtual void OnAssetReloaded(const ScriptCanvasMemoryAsset::pointer asset) {}
virtual void OnAssetUnloaded([[maybe_unused]] const AZ::Data::AssetId assetId, [[maybe_unused]] const AZ::Data::AssetType assetType) {}
virtual void OnAssetSaved(const ScriptCanvasMemoryAsset::pointer asset, [[maybe_unused]] bool isSuccessful) {}
virtual void OnAssetError(const ScriptCanvasMemoryAsset::pointer asset) {}
};
using AssetTrackerNotificationBus = AZ::EBus<AssetTrackerNotifications>;
namespace Internal
{
class MemoryAssetNotifications
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual void OnAssetReady([[maybe_unused]] const ScriptCanvasMemoryAsset* asset) {}
virtual void OnAssetReloaded([[maybe_unused]] const ScriptCanvasMemoryAsset* asset) {}
virtual void OnAssetSaved([[maybe_unused]] const ScriptCanvasMemoryAsset* asset, [[maybe_unused]] bool isSuccessful) {}
virtual void OnAssetError([[maybe_unused]] const ScriptCanvasMemoryAsset* asset) {}
};
using MemoryAssetNotificationBus = AZ::EBus<MemoryAssetNotifications>;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
}
@@ -0,0 +1,42 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/std/function/function_base.h>
#include <ScriptCanvas/Asset/ScriptCanvasAssetBase.h>
namespace ScriptCanvasEditor
{
class ScriptCanvasMemoryAsset;
namespace Callbacks
{
//! Callback used to know when a save operation failed or succeeded
using OnSave = AZStd::function<void(bool saveSuccess, AZ::Data::Asset<ScriptCanvas::ScriptCanvasAssetBase>, AZ::Data::AssetId previousFileAssetId)>;
using OnAssetReadyCallback = AZStd::function<void(ScriptCanvasMemoryAsset&)>;
using OnAssetCreatedCallback = OnAssetReadyCallback;
}
namespace Tracker
{
enum class ScriptCanvasFileState : AZ::s32
{
NEW,
MODIFIED,
UNMODIFIED,
INVALID = -1
};
}
}
@@ -0,0 +1,823 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include "ScriptCanvasMemoryAsset.h"
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
#include <AzCore/std/smart_ptr/make_shared.h>
#include <ScriptCanvas/Asset/ScriptCanvasAssetBase.h>
#include <ScriptCanvas/Components/EditorGraph.h>
#include <Editor/Assets/ScriptCanvasAssetTrackerBus.h>
namespace ScriptCanvasEditor
{
ScriptCanvasMemoryAsset::ScriptCanvasMemoryAsset()
: m_sourceInError(false)
, m_triggerSaveCallback(false)
{
m_undoState = AZStd::make_unique<SceneUndoState>(this);
}
ScriptCanvasMemoryAsset::~ScriptCanvasMemoryAsset()
{
AssetTrackerRequestBus::Broadcast(&AssetTrackerRequests::UntrackAsset, m_inMemoryAssetId);
AssetHelpers::PrintInfo(AZStd::string::format("ScriptCanvasMemoryAsset went out of scope and has been released and untracked: %s", m_absolutePath.c_str()).c_str());
if (m_inMemoryAsset.IsReady() && !m_inMemoryAsset.Release())
{
// Something else is holding on to it
AZ_Assert(false, "Unable to release in memory asset");
}
}
const AZStd::string ScriptCanvasMemoryAsset::GetTabName() const
{
AZStd::string tabName;
AzFramework::StringFunc::Path::GetFileName(m_absolutePath.c_str(), tabName);
return tabName;
}
AZ::EntityId ScriptCanvasMemoryAsset::GetGraphId()
{
if (!m_graphId.IsValid())
{
EditorGraphRequestBus::EventResult(m_graphId, m_scriptCanvasId, &EditorGraphRequests::GetGraphCanvasGraphId);
}
return m_graphId;
}
void ScriptCanvasMemoryAsset::CloneTo(ScriptCanvasMemoryAsset& memoryAsset)
{
if (m_assetType == azrtti_typeid<ScriptCanvasAsset>())
{
AZ::Data::Asset<ScriptCanvasAsset> newAsset = Clone<ScriptCanvasAsset>();
memoryAsset.m_inMemoryAsset = newAsset;
}
else if (m_assetType == azrtti_typeid<ScriptCanvas::ScriptCanvasFunctionAsset>())
{
AZ::Data::Asset<ScriptCanvas::ScriptCanvasFunctionAsset> newAsset = Clone<ScriptCanvas::ScriptCanvasFunctionAsset>();
memoryAsset.m_inMemoryAsset = newAsset;
}
else
{
AZ_Assert(false, "Unsupported Script Canvas Asset Type");
}
memoryAsset.m_sourceAsset = m_sourceAsset;
}
void ScriptCanvasMemoryAsset::Create(AZ::Data::AssetId assetId, AZStd::string_view assetAbsolutePath, AZ::Data::AssetType assetType, Callbacks::OnAssetCreatedCallback onAssetCreatedCallback)
{
m_inMemoryAssetId = assetId;
m_absolutePath = assetAbsolutePath;
m_assetType = assetType;
m_fileState = Tracker::ScriptCanvasFileState::NEW;
ScriptCanvasAssetHandler* assetHandler = GetAssetHandlerForType(assetType);
AZ::Data::Asset<AZ::Data::AssetData> asset;
if (assetType == azrtti_typeid<ScriptCanvasAsset>())
{
asset = { assetHandler->CreateAsset(assetId, azrtti_typeid<ScriptCanvasAsset>()), AZ::Data::AssetLoadBehavior::Default };
}
else if (assetType == azrtti_typeid<ScriptCanvas::ScriptCanvasFunctionAsset>())
{
asset = { assetHandler->CreateAsset(assetId, azrtti_typeid<ScriptCanvas::ScriptCanvasFunctionAsset>()), AZ::Data::AssetLoadBehavior::Default };
}
m_inMemoryAsset = asset;
ActivateAsset();
// For new assets, we directly set its status as "Ready" in order to make it usable.
ScriptCanvas::ScriptCanvasAssetBusRequestBus::Event(assetId, &ScriptCanvas::ScriptCanvasAssetBusRequests::SetAsNewAsset);
Internal::MemoryAssetNotificationBus::Broadcast(&Internal::MemoryAssetNotifications::OnAssetReady, this);
AssetHelpers::PrintInfo("Newly created Script Canvas asset is now tracked: %s", AssetHelpers::AssetIdToString(assetId).c_str());
if (onAssetCreatedCallback)
{
AZStd::invoke(onAssetCreatedCallback, *this);
}
}
void ScriptCanvasMemoryAsset::Save(Callbacks::OnSave onSaveCallback)
{
if (m_fileState == Tracker::ScriptCanvasFileState::UNMODIFIED)
{
// The file hasn't changed, don't save it
return;
}
SaveAs({}, onSaveCallback);
}
void ScriptCanvasMemoryAsset::SaveAs(const AZStd::string& path, Callbacks::OnSave onSaveCallback)
{
if (!path.empty())
{
m_saveAsPath = path;
}
else
{
m_saveAsPath = m_absolutePath;
}
AZ::Data::AssetStreamInfo streamInfo;
streamInfo.m_streamFlags = AZ::IO::OpenMode::ModeWrite;
streamInfo.m_streamName = m_saveAsPath;
ScriptCanvas::ScriptCanvasDataRequestBus::Event(GetScriptCanvasId(), &ScriptCanvas::ScriptCanvasDataRequests::SetPrettyName, GetTabName().c_str());
if (!streamInfo.IsValid())
{
return;
}
bool sourceControlActive = false;
AzToolsFramework::SourceControlConnectionRequestBus::BroadcastResult(sourceControlActive, &AzToolsFramework::SourceControlConnectionRequests::IsActive);
// If Source Control is active then use it to check out the file before saving otherwise query the file info and save only if the file is not read-only
if (sourceControlActive)
{
AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit,
streamInfo.m_streamName.c_str(),
true,
[this, streamInfo, onSaveCallback](bool success, AzToolsFramework::SourceControlFileInfo info) { FinalizeAssetSave(success, info, streamInfo, onSaveCallback); }
);
}
else
{
AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::GetFileInfo,
streamInfo.m_streamName.c_str(),
[this, streamInfo, onSaveCallback](bool success, AzToolsFramework::SourceControlFileInfo info) { FinalizeAssetSave(success, info, streamInfo, onSaveCallback); }
);
}
}
void ScriptCanvasMemoryAsset::Set(AZ::Data::AssetId fileAssetId)
{
Callbacks::OnAssetReadyCallback onAssetReady = [](ScriptCanvasMemoryAsset&) {};
Load(fileAssetId, AZ::Data::AssetType::CreateNull(), onAssetReady);
ActivateAsset();
}
bool ScriptCanvasMemoryAsset::Load(AZ::Data::AssetId assetId, AZ::Data::AssetType assetType, Callbacks::OnAssetReadyCallback onAssetReadyCallback)
{
AZStd::string rootPath;
AZ::Data::AssetInfo assetInfo = AssetHelpers::GetAssetInfo(assetId, rootPath);
AzFramework::StringFunc::Path::Join(rootPath.c_str(), assetInfo.m_relativePath.c_str(), m_absolutePath);
if (assetInfo.m_assetType.IsNull())
{
// Try to find the asset type from the source file asset
assetInfo.m_assetType = AssetHelpers::GetAssetType(AZStd::string::format("%s/%s", rootPath.c_str(), assetInfo.m_relativePath.c_str()).c_str());
}
if (!assetType.IsNull() && assetInfo.m_assetType.IsNull())
{
assetInfo.m_assetType = assetType;
}
else
{
AZ_Assert(assetInfo.m_assetId.IsValid(), "Failed to get the asset info properly from the asset system");
}
m_fileAssetId = assetId;
auto asset = AZ::Data::AssetManager::Instance().FindAsset<ScriptCanvasAsset>(assetId, m_sourceAsset.GetAutoLoadBehavior());
if (!asset || !asset.IsReady())
{
AZ::Data::AssetBus::MultiHandler::BusConnect(assetId);
}
if (assetInfo.m_assetType == azrtti_typeid<ScriptCanvasAsset>())
{
m_inMemoryAsset = AZ::Data::AssetManager::Instance().GetAsset<ScriptCanvasAsset>(assetId, m_sourceAsset.GetAutoLoadBehavior());
}
else if (assetInfo.m_assetType == azrtti_typeid<ScriptCanvas::ScriptCanvasFunctionAsset>())
{
m_inMemoryAsset = AZ::Data::AssetManager::Instance().GetAsset<ScriptCanvas::ScriptCanvasFunctionAsset>(assetId, m_sourceAsset.GetAutoLoadBehavior());
}
m_sourceAsset = m_inMemoryAsset;
m_assetType = m_inMemoryAsset.GetType();
AZ_Assert(m_inMemoryAsset.GetId() == assetId, "The asset IDs must match");
m_onAssetReadyCallback = onAssetReadyCallback;
if (m_inMemoryAsset.IsReady())
{
OnAssetReady(m_inMemoryAsset);
}
return !m_inMemoryAsset.IsError();
}
void ScriptCanvasMemoryAsset::ActivateAsset()
{
ScriptCanvas::ScriptCanvasAssetBase* assetData = m_inMemoryAsset.Get();
AZ_Assert(assetData, "ActivateAsset should have a valid asset of type %s", AssetHelpers::AssetIdToString(azrtti_typeid<ScriptCanvas::ScriptCanvasAssetBase>()).c_str());
if (assetData == nullptr)
{
return;
}
AZ::Entity* scriptCanvasEntity = assetData->GetScriptCanvasEntity();
AZ_Assert(scriptCanvasEntity, "ActivateAsset should have a valid ScriptCanvas Entity");
// Only activate the entity for assets that have been saved
if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed)
{
scriptCanvasEntity->Init();
}
if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init)
{
scriptCanvasEntity->Activate();
}
const AZStd::string& assetPath = m_absolutePath;
AZStd::string graphName;
AzFramework::StringFunc::Path::GetFileName(assetPath.c_str(), graphName);
if (!graphName.empty())
{
scriptCanvasEntity->SetName(graphName);
}
Graph* editorGraph = AZ::EntityUtils::FindFirstDerivedComponent<Graph>(scriptCanvasEntity);
AZ_Assert(editorGraph, "Script Canvas entity must have a Graph component");
if (editorGraph == nullptr)
{
return;
}
m_scriptCanvasId = editorGraph->GetScriptCanvasId();
ScriptCanvas::ScriptCanvasDataRequestBus::Event(m_scriptCanvasId, &ScriptCanvas::ScriptCanvasDataRequests::SetPrettyName, GetTabName().c_str());
EditorGraphNotificationBus::Handler::BusDisconnect();
EditorGraphNotificationBus::Handler::BusConnect(m_scriptCanvasId);
m_undoHelper = AZStd::make_unique<UndoHelper>(*this);
}
ScriptCanvasEditor::Widget::CanvasWidget* ScriptCanvasMemoryAsset::CreateView(QWidget* parent)
{
m_canvasWidget = new Widget::CanvasWidget(m_fileAssetId, parent);
return m_canvasWidget;
}
void ScriptCanvasMemoryAsset::ClearView()
{
delete m_canvasWidget;
m_canvasWidget = nullptr;
}
void ScriptCanvasMemoryAsset::UndoStackChange()
{
OnUndoStackChanged();
}
bool ScriptCanvasMemoryAsset::IsSourceInError() const
{
return m_sourceInError;
}
void ScriptCanvasMemoryAsset::OnSystemTick()
{
if (m_triggerSaveCallback && m_onSaveCallback)
{
AZ::SystemTickBus::Handler::BusDisconnect();
m_onSaveCallback(false, m_inMemoryAsset, AZ::Data::AssetId());
m_triggerSaveCallback = false;
}
}
void ScriptCanvasMemoryAsset::OnGraphCanvasSceneDisplayed()
{
// We need to wait until this event in order the get the m_graphId which represents the GraphCanvas scene Id
EditorGraphRequestBus::EventResult(m_graphId, m_scriptCanvasId, &EditorGraphRequests::GetGraphCanvasGraphId);
EditorGraphNotificationBus::Handler::BusDisconnect();
}
void ScriptCanvasMemoryAsset::OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset)
{
AZ::Data::AssetBus::MultiHandler::BusDisconnect(m_fileAssetId);
AZStd::string rootPath;
AZ::Data::AssetInfo assetInfo = AssetHelpers::GetAssetInfo(m_fileAssetId, rootPath);
AZStd::string absolutePath;
AzFramework::StringFunc::Path::Join(rootPath.c_str(), assetInfo.m_relativePath.c_str(), absolutePath);
m_absolutePath = absolutePath;
m_fileState = Tracker::ScriptCanvasFileState::UNMODIFIED;
m_assetType = asset.GetType();
// Keep the canonical asset's Id, we will need it when we want to save the asset back to file
m_fileAssetId = asset.GetId();
// The source file is ready, we need to make the an in-memory version of it.
AZ::Data::AssetId inMemoryAssetId = AZ::Uuid::CreateRandom();
m_inMemoryAsset = AZStd::move(CloneAssetData(inMemoryAssetId));
AZ_Assert(m_inMemoryAsset, "Asset should have been successfully cloned.");
AZ_Assert(m_inMemoryAsset.GetId() == inMemoryAssetId, "Asset Id should match to the newly created one");
m_inMemoryAssetId = m_inMemoryAsset.GetId();
ActivateAsset();
if (m_onAssetReadyCallback)
{
AZStd::invoke(m_onAssetReadyCallback, *this);
}
Internal::MemoryAssetNotificationBus::Broadcast(&Internal::MemoryAssetNotifications::OnAssetReady, this);
}
void ScriptCanvasMemoryAsset::OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset)
{
if (m_fileAssetId == asset.GetId())
{
// The source file was reloaded, but we have an in-memory version of it.
// We need to handle this.
}
else
{
AZ::Data::AssetId assetId = asset.GetId();
Internal::MemoryAssetNotificationBus::Broadcast(&Internal::MemoryAssetNotifications::OnAssetReloaded, this);
}
}
void ScriptCanvasMemoryAsset::OnAssetError(AZ::Data::Asset<AZ::Data::AssetData> asset)
{
if (m_fileAssetId == asset.GetId())
{
m_sourceInError = true;
if (m_onAssetReadyCallback)
{
AZStd::invoke(m_onAssetReadyCallback, *this);
}
}
else
{
AZ::Data::AssetId assetId = asset.GetId();
Internal::MemoryAssetNotificationBus::Broadcast(&Internal::MemoryAssetNotifications::OnAssetError, this);
}
}
void ScriptCanvasMemoryAsset::OnAssetUnloaded(const AZ::Data::AssetId assetId, const AZ::Data::AssetType assetType)
{
AssetTrackerNotificationBus::Event(assetId, &AssetTrackerNotifications::OnAssetUnloaded, assetId, assetType);
}
void ScriptCanvasMemoryAsset::SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid sourceAssetId)
{
// This updates the asset Id with the canonical assetId on SourceFileChanged
// This occurs for new ScriptCanvas assets because before the SC asset is saved to disk, the asset database
// has no asset Id associated with it, so this uses the supplied source path to find the asset Id registered
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())
{
AZ::SystemTickBus::Handler::BusDisconnect();
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
m_fileAssetId = sourceAssetId;
}
else if (!m_fileAssetId.IsValid())
{
m_fileAssetId = sourceAssetId;
}
m_formerGraphIdPair = AZStd::make_pair(m_scriptCanvasId, m_graphId);
m_fileState = Tracker::ScriptCanvasFileState::UNMODIFIED;
// Connect to the source asset's bus to monitor for situations we may need to handle
AZ::Data::AssetBus::MultiHandler::BusConnect(m_inMemoryAsset.GetId());
m_pendingSave.erase(assetPathIdIt);
if (m_onSaveCallback)
{
m_onSaveCallback(true, m_inMemoryAsset, previousFileAssetId);
}
}
}
void ScriptCanvasMemoryAsset::SourceFileRemoved(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid fileAssetId)
{
AZ_UNUSED(relativePath);
AZ_UNUSED(scanFolder);
AZ_UNUSED(fileAssetId);
}
void ScriptCanvasMemoryAsset::SourceFileFailed(AZStd::string relativePath, AZStd::string scanFolder, [[maybe_unused]] AZ::Uuid fileAssetId)
{
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())
{
m_pendingSave.erase(assetPathIdIt);
if (m_onSaveCallback)
{
m_onSaveCallback(false, m_inMemoryAsset, AZ::Data::AssetId());
}
}
}
void ScriptCanvasMemoryAsset::FinalizeAssetSave(bool, const AzToolsFramework::SourceControlFileInfo& fileInfo, const AZ::Data::AssetStreamInfo& saveInfo, Callbacks::OnSave onSaveCallback)
{
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(onSaveCallback, false, m_inMemoryAsset, m_fileAssetId);
return;
}
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(onSaveCallback, false, m_inMemoryAsset, m_fileAssetId);
return;
}
AZStd::string normPath = saveInfo.m_streamName;
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::NormalizePath, normPath);
m_pendingSave.emplace_back(normPath);
ScriptCanvasEditor::SystemRequestBus::Broadcast(&ScriptCanvasEditor::SystemRequests::AddAsyncJob, [this, saveInfo, onSaveCallback]()
{
// ScriptCanvas Asset must be saved to a temporary location as the FileWatcher will pick up the file immediately if it detects any changes
// and attempt to reload it
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::ScriptCanvas);
const AZStd::string tempPath = MakeTemporaryFilePathForSave(saveInfo.m_streamName);
AZ::IO::FileIOStream stream(tempPath.data(), saveInfo.m_streamFlags);
if (stream.IsOpen())
{
ScriptCanvasAssetHandler* assetHandler = nullptr;
AssetTrackerRequestBus::BroadcastResult(assetHandler, &AssetTrackerRequests::GetAssetHandlerForType, m_inMemoryAsset.GetType());
AZ_Assert(assetHandler, "An asset handler must be found for an asset of type %s", AssetHelpers::AssetIdToString(m_inMemoryAsset.GetId()).c_str());
bool savedSuccess;
{
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::ScriptCanvas, "ScriptCanvasAssetHandler::SaveAssetData");
savedSuccess = assetHandler->SaveAssetData(m_inMemoryAsset, &stream);
}
stream.Close();
if (savedSuccess)
{
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::ScriptCanvas, "AssetTracker::SaveAssetPostSourceControl : TempToTargetFileReplacement");
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
const bool targetFileExists = fileIO->Exists(saveInfo.m_streamName.data());
bool removedTargetFile;
{
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::ScriptCanvas, "AssetTracker::SaveAssetPostSourceControl : TempToTargetFileReplacement : RemoveTarget");
removedTargetFile = fileIO->Remove(saveInfo.m_streamName.data());
}
if (targetFileExists && !removedTargetFile)
{
savedSuccess = false;
}
else
{
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::ScriptCanvas, "AssetTracker::SaveAssetPostSourceControl : TempToTargetFileReplacement : RenameTempFile");
AZ::IO::Result renameResult = fileIO->Rename(tempPath.data(), saveInfo.m_streamName.data());
if (!renameResult)
{
savedSuccess = false;
}
}
}
// Store the onSave callback so that we can call it from the proper place
m_onSaveCallback = onSaveCallback;
if (savedSuccess)
{
AZStd::string watchFolder;
AZ::Data::AssetInfo assetInfo;
bool sourceInfoFound{};
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, saveInfo.m_streamName.data(), assetInfo, watchFolder);
if (sourceInfoFound)
{
AZ_TracePrintf("Script Canvas", "Script Canvas successfully saved as Asset \"%s\"", saveInfo.m_streamName.data());
m_absolutePath = m_saveAsPath;
}
else
{
AZ_TracePrintf("Script Canvas", "Script Canvas successfully saved as Asset \"%s\" but is outside of project scope and cannot be loaded.", saveInfo.m_streamName.data());
m_triggerSaveCallback = true;
}
m_saveAsPath.clear();
}
}
});
// Because this is connecting from within the lambda, the this is necessary. Otherwise it 'connects' but won't actually trigger.
AZ::SystemTickBus::Handler::BusConnect();
}
AZ::Data::Asset<AZ::Data::AssetData> ScriptCanvasMemoryAsset::CloneAssetData(AZ::Data::AssetId newAssetId)
{
if (m_assetType == azrtti_typeid<ScriptCanvasAsset>())
{
return CloneAssetData<ScriptCanvasAsset>(newAssetId);
}
else if (m_assetType == azrtti_typeid<ScriptCanvas::ScriptCanvasFunctionAsset>())
{
return CloneAssetData<ScriptCanvas::ScriptCanvasFunctionAsset>(newAssetId);
}
AZ_Assert(false, "The provides asset type is not supported as a valid Script Canvas memory asset");
return AZ::Data::Asset<AZ::Data::AssetData>();
}
void ScriptCanvasMemoryAsset::OnUndoStackChanged()
{
UndoNotificationBus::Broadcast(&UndoNotifications::OnCanUndoChanged, m_undoState->m_undoStack->CanUndo());
UndoNotificationBus::Broadcast(&UndoNotifications::OnCanRedoChanged, m_undoState->m_undoStack->CanRedo());
}
AZStd::string ScriptCanvasMemoryAsset::MakeTemporaryFilePathForSave(AZStd::string_view targetFilename)
{
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
AZ_Assert(fileIO, "File IO is not initialized.");
AZStd::string tempFilename;
AzFramework::StringFunc::Path::GetFullFileName(targetFilename.data(), tempFilename);
AZStd::string tempPath = AZStd::string::format("@cache@/scriptcanvas/%s.temp", tempFilename.data());
AZStd::array<char, AZ::IO::MaxPathLength> resolvedPath{};
AZ::IO::FileIOBase::GetInstance()->ResolvePath(tempPath.data(), resolvedPath.data(), resolvedPath.size());
return resolvedPath.data();
}
ScriptCanvasAssetHandler* ScriptCanvasMemoryAsset::GetAssetHandlerForType(AZ::Data::AssetType assetType)
{
ScriptCanvasAssetHandler* assetHandler = nullptr;
AZ::EBusAggregateResults<AZ::Data::AssetHandler*> foundAssetHandlers;
ScriptCanvas::AssetRegistryRequestBus::BroadcastResult(foundAssetHandlers, &ScriptCanvas::AssetRegistryRequests::GetAssetHandler);
for (auto handler : foundAssetHandlers.values)
{
if (handler != nullptr)
{
ScriptCanvasAssetHandler* theHandler = azrtti_cast<ScriptCanvasAssetHandler*>(handler);
if (theHandler != nullptr && theHandler->GetAssetType() == assetType)
{
assetHandler = theHandler;
break;
}
}
}
AZ_Assert(assetHandler, "The specified asset type does not have a registered asset handler.");
return assetHandler;
}
AZ::EntityId ScriptCanvasMemoryAsset::GetEditorEntityIdFromSceneEntityId(AZ::EntityId sceneEntityId)
{
if (m_editorEntityIdMap.find(sceneEntityId) != m_editorEntityIdMap.end())
{
return m_editorEntityIdMap[sceneEntityId];
}
return AZ::EntityId();
}
AZ::EntityId ScriptCanvasMemoryAsset::GetSceneEntityIdFromEditorEntityId(AZ::EntityId editorEntityId)
{
for (auto mapEntry : m_editorEntityIdMap)
{
if (mapEntry.second == editorEntityId)
{
return mapEntry.first;
}
}
return AZ::EntityId();
}
///////////////
// UndoHelper
///////////////
UndoHelper::UndoHelper(ScriptCanvasMemoryAsset& memoryAsset)
: m_memoryAsset(memoryAsset)
{
UndoRequestBus::Handler::BusConnect(memoryAsset.GetScriptCanvasId());
}
UndoHelper::~UndoHelper()
{
UndoRequestBus::Handler::BusDisconnect();
}
ScriptCanvasEditor::UndoCache* UndoHelper::GetSceneUndoCache()
{
return m_memoryAsset.GetUndoState()->m_undoCache.get();
}
ScriptCanvasEditor::UndoData UndoHelper::CreateUndoData()
{
AZ::EntityId graphCanvasGraphId = m_memoryAsset.GetGraphId();
ScriptCanvas::ScriptCanvasId scriptCanvasId = m_memoryAsset.GetScriptCanvasId();
GraphCanvas::GraphModelRequestBus::Event(graphCanvasGraphId, &GraphCanvas::GraphModelRequests::OnSaveDataDirtied, graphCanvasGraphId);
UndoData undoData;
ScriptCanvas::GraphData* graphData{};
ScriptCanvas::GraphRequestBus::EventResult(graphData, scriptCanvasId, &ScriptCanvas::GraphRequests::GetGraphData);
const ScriptCanvas::VariableData* varData{};
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(varData, scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::GetVariableDataConst);
if (graphData && varData)
{
undoData.m_graphData = *graphData;
undoData.m_variableData = *varData;
EditorGraphRequestBus::EventResult(undoData.m_visualSaveData, scriptCanvasId, &EditorGraphRequests::GetGraphCanvasSaveData);
}
return undoData;
}
void UndoHelper::BeginUndoBatch(AZStd::string_view label)
{
m_memoryAsset.GetUndoState()->BeginUndoBatch(label);
}
void UndoHelper::EndUndoBatch()
{
m_memoryAsset.GetUndoState()->EndUndoBatch();
}
void UndoHelper::AddUndo(AzToolsFramework::UndoSystem::URSequencePoint* sequencePoint)
{
if (SceneUndoState * sceneUndoState = m_memoryAsset.GetUndoState())
{
if (!sceneUndoState->m_currentUndoBatch)
{
sceneUndoState->m_undoStack->Post(sequencePoint);
}
else
{
sequencePoint->SetParent(sceneUndoState->m_currentUndoBatch);
}
}
}
void UndoHelper::AddGraphItemChangeUndo(AZStd::string_view undoLabel)
{
GraphItemChangeCommand* command = aznew GraphItemChangeCommand(undoLabel);
command->Capture(m_memoryAsset, true);
command->Capture(m_memoryAsset, false);
AddUndo(command);
}
void UndoHelper::AddGraphItemAdditionUndo(AZStd::string_view undoLabel)
{
GraphItemAddCommand* command = aznew GraphItemAddCommand(undoLabel);
command->Capture(m_memoryAsset, false);
AddUndo(command);
}
void UndoHelper::AddGraphItemRemovalUndo(AZStd::string_view undoLabel)
{
GraphItemRemovalCommand* command = aznew GraphItemRemovalCommand(undoLabel);
command->Capture(m_memoryAsset, true);
AddUndo(command);
}
void UndoHelper::Undo()
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::ScriptCanvas);
SceneUndoState* sceneUndoState = m_memoryAsset.GetUndoState();
if (sceneUndoState)
{
AZ_Warning("Script Canvas", !sceneUndoState->m_currentUndoBatch, "Script Canvas Editor has an open undo batch when performing a redo operation");
if (sceneUndoState->m_undoStack->CanUndo())
{
m_status = Status::InUndo;
sceneUndoState->m_undoStack->Undo();
m_status = Status::Idle;
UpdateCache();
}
}
}
void UndoHelper::Redo()
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::ScriptCanvas);
SceneUndoState* sceneUndoState = m_memoryAsset.GetUndoState();
if (sceneUndoState)
{
AZ_Warning("Script Canvas", !sceneUndoState->m_currentUndoBatch, "Script Canvas Editor has an open undo batch when performing a redo operation");
if (sceneUndoState->m_undoStack->CanRedo())
{
m_status = Status::InUndo;
sceneUndoState->m_undoStack->Redo();
m_status = Status::Idle;
UpdateCache();
}
}
}
void UndoHelper::Reset()
{
if (SceneUndoState* sceneUndoState = m_memoryAsset.GetUndoState())
{
AZ_Warning("Script Canvas", !sceneUndoState->m_currentUndoBatch, "Script Canvas Editor has an open undo batch when reseting the undo stack");
sceneUndoState->m_undoStack->Reset();
}
}
bool UndoHelper::IsIdle()
{
return m_status == Status::Idle;
}
bool UndoHelper::IsActive()
{
return m_status != Status::Idle;
}
bool UndoHelper::CanUndo() const
{
return m_memoryAsset.GetUndoState()->m_undoStack->CanUndo();
}
bool UndoHelper::CanRedo() const
{
return m_memoryAsset.GetUndoState()->m_undoStack->CanRedo();
}
void UndoHelper::UpdateCache()
{
ScriptCanvas::ScriptCanvasId scriptCanvasId = m_memoryAsset.GetScriptCanvasId();
UndoCache* undoCache = nullptr;
UndoRequestBus::EventResult(undoCache, scriptCanvasId, &UndoRequests::GetSceneUndoCache);
if (undoCache)
{
undoCache->UpdateCache(scriptCanvasId);
}
}
}
@@ -0,0 +1,337 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/TickBus.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/std/smart_ptr/enable_shared_from_this.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
#include <Editor/Assets/ScriptCanvasAssetHelpers.h>
#include <Editor/Assets/ScriptCanvasAssetTrackerDefinitions.h>
#include <ScriptCanvas/Asset/ScriptCanvasAssetBase.h>
#include <ScriptCanvas/Asset/Functions/ScriptCanvasFunctionAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <Editor/View/Widgets/CanvasWidget.h>
#include <Editor/Undo/ScriptCanvasUndoManager.h>
namespace ScriptCanvasEditor
{
class ScriptCanvasAssetHandler;
template <typename BaseAssetType>
class MemoryAsset
: protected AZ::Data::AssetBus::MultiHandler
, protected AzToolsFramework::AssetSystemBus::Handler
, public AzToolsFramework::UndoSystem::IUndoNotify
{
public:
MemoryAsset()
{
AzToolsFramework::AssetSystemBus::Handler::BusConnect();
}
~MemoryAsset()
{
AZ::Data::AssetBus::MultiHandler::BusDisconnect();
AzToolsFramework::AssetSystemBus::Handler::BusDisconnect();
}
using AssetType = BaseAssetType;
virtual void Create(AZ::Data::AssetId assetId, AZStd::string_view assetAbsolutePath, AZ::Data::AssetType assetType, Callbacks::OnAssetCreatedCallback onAssetCreatedCallback) = 0;
virtual void SaveAs(const AZStd::string& path, Callbacks::OnSave onSaveCallback) = 0;
virtual void Save(Callbacks::OnSave onSaveCallback) = 0;
virtual bool Load(AZ::Data::AssetId assetId, AZ::Data::AssetType assetType, Callbacks::OnAssetReadyCallback onAssetReadyCallback) = 0;
};
class UndoHelper;
// Script Canvas primarily works with an in-memory copy of an asset.
// There are two situations, the first is, when a new asset is created and not yet saved.
// Once saved, we will create a new asset on file, however, and this is important
// once the file is saved to file, its asset ID will be changed, if the file is to remain
// open, we need to update the source AssetId to correspond to the file asset.
//
// The other is when an asset is loaded, we clone the asset from file and use an in-memory
// version of the asset until it is time to save, at that moment we need to save to the
// source file
class ScriptCanvasMemoryAsset
: public MemoryAsset<ScriptCanvas::ScriptCanvasAssetBase>
, public AZStd::enable_shared_from_this<ScriptCanvasMemoryAsset>
, EditorGraphNotificationBus::Handler
, public AZ::SystemTickBus::Handler
{
public:
ScriptCanvasMemoryAsset();
~ScriptCanvasMemoryAsset() override;
ScriptCanvasMemoryAsset(const ScriptCanvasMemoryAsset& rhs) = delete;
ScriptCanvasMemoryAsset& operator = (const ScriptCanvasMemoryAsset& rhs) = delete;
using pointer = AZStd::shared_ptr<ScriptCanvasMemoryAsset>;
void Create(AZ::Data::AssetId assetId, AZStd::string_view assetAbsolutePath, AZ::Data::AssetType assetType, Callbacks::OnAssetCreatedCallback onAssetCreatedCallback) override;
void SaveAs(const AZStd::string& path, Callbacks::OnSave onSaveCallback) override;
void Save(Callbacks::OnSave onSaveCallback) override;
bool Load(AZ::Data::AssetId assetId, AZ::Data::AssetType assetType, Callbacks::OnAssetReadyCallback onAssetReadyCallback) override;
void Set(AZ::Data::AssetId assetId);
const AZ::Data::AssetId& GetId() const { return m_inMemoryAssetId; }
const AZ::Data::AssetId& GetFileAssetId() const { return m_fileAssetId; }
const AZ::Data::AssetType GetAssetType() const { return m_assetType; }
AZ::Data::Asset<AssetType> GetAsset() { return m_inMemoryAsset; }
const AZ::Data::Asset<AssetType>& GetAsset() const { return m_inMemoryAsset; }
const AZStd::string GetTabName() const;
const AZStd::string& GetAbsolutePath() const { return m_absolutePath; }
AZ::EntityId GetScriptCanvasId() const { return m_scriptCanvasId; }
AZ::EntityId GetGraphId();
Tracker::ScriptCanvasFileState GetFileState() const { return m_fileState; }
void SetFileState(Tracker::ScriptCanvasFileState fileState) { m_fileState = fileState; }
void CloneTo(ScriptCanvasMemoryAsset& memoryAsset);
void ActivateAsset();
Widget::CanvasWidget* GetView() { return m_canvasWidget; }
Widget::CanvasWidget* CreateView(QWidget* parent);
void ClearView();
void UndoStackChange();
SceneUndoState* GetUndoState() { return m_undoState.get(); }
bool IsSourceInError() const;
// SystemTickBus
void OnSystemTick() override;
////
private:
template <typename T>
AZ::Data::Asset<T> Clone()
{
AZ::Data::AssetId assetId = AZ::Uuid::CreateRandom();
AZ::Data::Asset<T> newAsset = m_inMemoryAsset;
newAsset = { aznew T(assetId, AZ::Data::AssetData::AssetStatus::Ready), AZ::Data::AssetLoadBehavior::Default };
auto serializeContext = AZ::EntityUtils::GetApplicationSerializeContext();
serializeContext->CloneObjectInplace(newAsset.Get()->GetScriptCanvasData(), &m_inMemoryAsset.Get()->GetScriptCanvasData());
m_editorEntityIdMap.clear();
AZ::IdUtils::Remapper<AZ::EntityId>::GenerateNewIdsAndFixRefs(&newAsset.Get()->GetScriptCanvasData(), m_editorEntityIdMap, serializeContext);
return newAsset;
}
// EditorGraphNotificationBus
void OnGraphCanvasSceneDisplayed() override;
///
//! AZ::Data::AssetBus
void OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
void OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
void OnAssetError(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
void OnAssetUnloaded(const AZ::Data::AssetId assetId, const AZ::Data::AssetType assetType) override;
///////////////////////
// AzToolsFramework::AssetSystemBus::Handler
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 SourceFileFailed(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid fileAssetId) override;
///
void FinalizeAssetSave(bool, const AzToolsFramework::SourceControlFileInfo& fileInfo, const AZ::Data::AssetStreamInfo& saveInfo, Callbacks::OnSave onSaveCallback);
template <typename T>
void StartAssetLoad(AZ::Data::AssetId assetId, AZ::Data::Asset<T>& asset)
{
asset = AZ::Data::AssetManager::Instance().GetAsset<T>(assetId, asset.GetAutoLoadBehavior());
}
template <typename AssetType>
AZ::Data::Asset<AZ::Data::AssetData> CloneAssetData(AZ::Data::AssetId newAssetId)
{
AssetType* assetData = aznew AssetType(newAssetId, AZ::Data::AssetData::AssetStatus::Ready);
auto& scriptCanvasData = assetData->GetScriptCanvasData();
// Clone asset data into SC Editor asset
auto serializeContext = AZ::EntityUtils::GetApplicationSerializeContext();
serializeContext->CloneObjectInplace(scriptCanvasData, &m_inMemoryAsset.Get()->GetScriptCanvasData());
m_editorEntityIdMap.clear();
AZ::IdUtils::Remapper<AZ::EntityId>::GenerateNewIdsAndFixRefs(&scriptCanvasData, m_editorEntityIdMap, serializeContext);
// Upon doing this move, the canonical asset will be unloaded
m_inMemoryAsset = { AZStd::move(assetData), AZ::Data::AssetLoadBehavior::Default };
return m_inMemoryAsset;
}
// Upon loading a graph, we clone the source data and we replace the loaded asset with
// a clone, this is to prevent modifications to the source data and it gives us some
// flexibility if we need to load the source asset again
AZ::Data::Asset<AZ::Data::AssetData> CloneAssetData(AZ::Data::AssetId newAssetId);
// IUndoNotify
void OnUndoStackChanged() override;
//
private:
AZStd::string MakeTemporaryFilePathForSave(AZStd::string_view targetFilename);
//! Finds the appropriate asset handler for the type of Script Canvas asset given
ScriptCanvasAssetHandler* GetAssetHandlerForType(AZ::Data::AssetType assetType);
//! The asset type, we need it to make sure we call the correct factory methods
AZ::Data::AssetType m_assetType;
//! The in-memory asset
AZ::Data::Asset<AssetType> m_inMemoryAsset;
AZ::Data::Asset<AssetType> m_sourceAsset;
//! Whether we are making a new asset or loading one, we should always have its absolute path
AZStd::string m_absolutePath;
AZStd::string m_saveAsPath;
//! The AssetId of the canonical asset on file, if the asset has never been saved to file, it is Invalid
AZ::Data::AssetId m_fileAssetId;
//! The AssetId that represents this asset, it will always be the in-memory asset Id and never the file asset Id
AZ::Data::AssetId m_inMemoryAssetId;
//! When a new asset is saved, we need to keep it's previous internal Ids in order for the front end to remap to the new Ids
using FormerGraphIdPair = AZStd::pair<AZ::EntityId /*scriptCanvasEntityId*/, AZ::EntityId /* graphId */>;
FormerGraphIdPair m_formerGraphIdPair;
//! The EntityId of the ScriptCanvasEntity owned by the ScriptCanvasAsset
ScriptCanvas::ScriptCanvasId m_scriptCanvasId;
//! The EntityId that represents the ScriptCanvas graph
AZ::EntityId m_graphId;
//! Gives the ability to provide a lambda invoked when the asset is ready
Callbacks::OnAssetReadyCallback m_onAssetReadyCallback;
//! The Save is officially complete after SourceFileChange is handled.
Callbacks::OnSave m_onSaveCallback;
Tracker::ScriptCanvasFileState m_fileState = Tracker::ScriptCanvasFileState::INVALID;
//! We need to track the filename of the file being saved because we need to match it when we handle SourceFileChange (see SourceFileChange for details)
AZStd::vector<AZStd::string> m_pendingSave;
//! Each memory asset owns its view widget
Widget::CanvasWidget* m_canvasWidget = nullptr;
//! Utility cache of remapped entityIds
using EditorEntityIdMap = AZStd::unordered_map<AZ::EntityId, AZ::EntityId>;
//! Cached mapping of Scene Entity ID to Asset Id, used by the debugger
EditorEntityIdMap m_editorEntityIdMap;
//! Each asset keeps track of its undo state
AZStd::unique_ptr<SceneUndoState> m_undoState;
//! The undo helper is an object that implements the Undo behaviors
AZStd::unique_ptr<UndoHelper> m_undoHelper;
bool m_sourceInError;
bool m_triggerSaveCallback;
public:
//! Given a scene EntityId, find the respective editor EntityId
AZ::EntityId GetEditorEntityIdFromSceneEntityId(AZ::EntityId sceneEntityId);
//! Given an editor EntityId, find the respective scene EntityId
AZ::EntityId GetSceneEntityIdFromEditorEntityId(AZ::EntityId editorEntityId);
//! When a new asset is saved, we need to keep it's previous internal Ids in order for the front end to remap to the new Ids
const FormerGraphIdPair& GetFormerGraphIds() const { return m_formerGraphIdPair; }
};
// Helper class that provides the implementation for UndoRequestBus
class UndoHelper : UndoRequestBus::Handler
{
public:
UndoHelper(ScriptCanvasMemoryAsset& memoryAsset);
~UndoHelper();
UndoCache* GetSceneUndoCache() override;
UndoData CreateUndoData() override;
void BeginUndoBatch(AZStd::string_view label) override;
void EndUndoBatch() override;
void AddUndo(AzToolsFramework::UndoSystem::URSequencePoint* seqPoint) override;
void AddGraphItemChangeUndo(AZStd::string_view undoLabel) override;
void AddGraphItemAdditionUndo(AZStd::string_view undoLabel) override;
void AddGraphItemRemovalUndo(AZStd::string_view undoLabel) override;
void Undo() override;
void Redo() override;
void Reset() override;
bool IsActive() override;
bool IsIdle() override;
bool CanUndo() const override;
bool CanRedo() const override;
private:
void UpdateCache();
enum class Status
{
Idle,
InUndo
};
Status m_status = Status::Idle;
ScriptCanvasMemoryAsset& m_memoryAsset;
};
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,166 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <qstring.h>
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
namespace ScriptCanvasEditor
{
/////////////////////////////////
// EditorGraphVariableItemModel
/////////////////////////////////
void EditorGraphVariableItemModel::Activate(const ScriptCanvas::ScriptCanvasId& busId)
{
m_busId = busId;
ScriptCanvas::GraphVariableManagerNotificationBus::Handler::BusConnect(m_busId);
removeRows(0, static_cast<int>(m_variableIds.size()));
m_variableIds.clear();
const ScriptCanvas::GraphVariableMapping* variableMapping = nullptr;
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(variableMapping, m_busId, &ScriptCanvas::GraphVariableManagerRequests::GetVariables);
if (variableMapping)
{
beginInsertRows(QModelIndex(), 0, static_cast<int>(variableMapping->size()));
m_variableIds.reserve(variableMapping->size());
for (const auto& mapPair : (*variableMapping))
{
m_variableIds.emplace_back(mapPair.first);
}
endInsertRows();
}
}
ScriptCanvas::VariableId EditorGraphVariableItemModel::FindVariableIdForIndex(const QModelIndex& modelIndex) const
{
ScriptCanvas::VariableId variableId;
if (modelIndex.row() >= 0 && modelIndex.row() < m_variableIds.size())
{
variableId = m_variableIds[modelIndex.row()];
}
return variableId;
}
QModelIndex EditorGraphVariableItemModel::index(int row, int column, [[maybe_unused]] const QModelIndex& parent) const
{
return createIndex(row, column);
}
QModelIndex EditorGraphVariableItemModel::parent(const QModelIndex&) const
{
return QModelIndex();
}
int EditorGraphVariableItemModel::columnCount([[maybe_unused]] const QModelIndex& parent) const
{
return 1;
}
int EditorGraphVariableItemModel::rowCount([[maybe_unused]] const QModelIndex& parent) const
{
return static_cast<int>(m_variableIds.size());
}
QVariant EditorGraphVariableItemModel::data(const QModelIndex& index, int role) const
{
ScriptCanvas::VariableId variableId = FindVariableIdForIndex(index);
if (!variableId.IsValid())
{
return QVariant();
}
if (role == Qt::DisplayRole
|| role == Qt::EditRole)
{
AZStd::string variableName;
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(variableName, m_busId, &ScriptCanvas::GraphVariableManagerRequests::GetVariableName, variableId);
return QVariant(variableName.c_str());
}
return QVariant();
}
void EditorGraphVariableItemModel::OnVariableAddedToGraph(const ScriptCanvas::VariableId& variableId, AZStd::string_view /*variableName*/)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_variableIds.emplace_back(variableId);
endInsertRows();
}
void EditorGraphVariableItemModel::OnVariableRemovedFromGraph(const ScriptCanvas::VariableId& variableId, AZStd::string_view /*variableName*/)
{
int index = -1;
for (unsigned int i = 0; i < m_variableIds.size(); ++i)
{
if (m_variableIds[i] == variableId)
{
index = i;
break;
}
}
if (index >= 0)
{
beginRemoveRows(QModelIndex(), index, index);
m_variableIds.erase(m_variableIds.begin() + index);
endRemoveRows();
}
else
{
AZ_Error("Script Canvas", false, "Failed to find index which contains variable id %s. This indicates that the GraphVariableManagerNotification::OnVariableRemoved function"
" was invoked twice for the same variable without it being added back to the GraphVariableManager. This should not occur and likely indicates an issue in the GraphVariableManager",
variableId.ToString().data());
}
}
////////////////////////////////////////
// EditorGraphVariableManagerComponent
////////////////////////////////////////
void EditorGraphVariableManagerComponent::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<EditorGraphVariableManagerComponent, ScriptCanvas::GraphVariableManagerComponent>()
->Version(0)
;
}
}
EditorGraphVariableManagerComponent::EditorGraphVariableManagerComponent(ScriptCanvas::ScriptCanvasId graphScopeId)
: GraphVariableManagerComponent(graphScopeId)
{
}
void EditorGraphVariableManagerComponent::ConfigureScriptCanvasId(const ScriptCanvas::ScriptCanvasId& executionId)
{
ScriptCanvas::GraphVariableManagerComponent::ConfigureScriptCanvasId(executionId);
m_variableModel.Activate(GetScriptCanvasId());
EditorSceneVariableManagerRequestBus::Handler::BusConnect(GetScriptCanvasId());
}
QAbstractItemModel* EditorGraphVariableManagerComponent::GetVariableItemModel()
{
return &m_variableModel;
}
}
@@ -0,0 +1,551 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <ScriptCanvas/Components/EditorScriptCanvasComponent.h>
#include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
#include <ScriptCanvas/Core/Node.h>
#include <ScriptCanvas/Execution/RuntimeComponent.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <Core/ScriptCanvasBus.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Serialization/IdUtils.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/Serialization/Utils.h>
#include <AzCore/Component/NamedEntityId.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <Editor/Assets/ScriptCanvasAssetTrackerBus.h>
namespace ScriptCanvasEditor
{
static bool EditorScriptCanvasComponentVersionConverter(AZ::SerializeContext& serializeContext, AZ::SerializeContext::DataElementNode& rootElement)
{
if (rootElement.GetVersion() <= 4)
{
int assetElementIndex = rootElement.FindElement(AZ::Crc32("m_asset"));
if (assetElementIndex == -1)
{
return false;
}
auto assetElement = rootElement.GetSubElement(assetElementIndex);
AZ::Data::Asset<ScriptCanvasAsset> scriptCanvasAsset;
if (!assetElement.GetData(scriptCanvasAsset))
{
AZ_Error("Script Canvas", false, "Unable to find Script Canvas Asset on a Version %u Editor ScriptCanvas Component", rootElement.GetVersion());
return false;
}
ScriptCanvasAssetHolder assetHolder;
assetHolder.SetAsset(scriptCanvasAsset.GetId());
if (!rootElement.AddElementWithData(serializeContext, "m_assetHolder", assetHolder))
{
AZ_Error("Script Canvas", false, "Unable to add ScriptCanvas Asset Holder element when converting from version %u", rootElement.GetVersion())
}
rootElement.RemoveElementByName(AZ_CRC("m_asset", 0x4e58e538));
rootElement.RemoveElementByName(AZ_CRC("m_openEditorButton", 0x9bcb3d5b));
}
if (rootElement.GetVersion() <= 6)
{
rootElement.RemoveElementByName(AZ_CRC("m_originalData", 0x2aee5989));
}
return true;
}
//=========================================================================
void EditorScriptCanvasComponent::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<EditorScriptCanvasComponent, EditorComponentBase>()
->Version(7, &EditorScriptCanvasComponentVersionConverter)
->Field("m_name", &EditorScriptCanvasComponent::m_name)
->Field("m_assetHolder", &EditorScriptCanvasComponent::m_scriptCanvasAssetHolder)
->Field("m_variableData", &EditorScriptCanvasComponent::m_editableData)
->Field("m_variableEntityIdMap", &EditorScriptCanvasComponent::m_variableEntityIdMap)
;
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
{
editContext->Class<EditorScriptCanvasComponent>("Script Canvas", "The Script Canvas component allows you to add a Script Canvas asset to a component, and have it execute on the specified entity.")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Category, "Scripting")
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/ScriptCanvas/ScriptCanvas.svg")
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/ScriptCanvas/Viewport/ScriptCanvas.png")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::PrimaryAssetType, ScriptCanvasAssetHandler::GetAssetTypeStatic())
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("UI", 0x27ff46b0))
->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-script-canvas.html")
->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_editableData, "Properties", "Script Canvas Graph Properties")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
;
}
}
}
EditorScriptCanvasComponent::EditorScriptCanvasComponent()
: EditorScriptCanvasComponent(AZ::Data::Asset<ScriptCanvasAsset>())
{
}
EditorScriptCanvasComponent::EditorScriptCanvasComponent(AZ::Data::Asset<ScriptCanvasAsset> asset)
: m_scriptCanvasAssetHolder()
{
if (asset.GetId().IsValid())
{
m_scriptCanvasAssetHolder.SetAsset(asset.GetId());
}
m_scriptCanvasAssetHolder.SetScriptChangedCB([this](AZ::Data::AssetId assetId) { OnScriptCanvasAssetChanged(assetId); });
}
EditorScriptCanvasComponent::~EditorScriptCanvasComponent()
{
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
}
void EditorScriptCanvasComponent::UpdateName()
{
AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId();
if (assetId.IsValid())
{
// 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())
{
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);
}
}
}
}
void EditorScriptCanvasComponent::OpenEditor()
{
m_scriptCanvasAssetHolder.OpenEditor();
}
void EditorScriptCanvasComponent::CloseGraph()
{
AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId();
if (assetId.IsValid())
{
GeneralRequestBus::Broadcast(&GeneralRequests::CloseScriptCanvasAsset, assetId);
}
}
void EditorScriptCanvasComponent::Init()
{
EditorComponentBase::Init();
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
m_scriptCanvasAssetHolder.Init(GetEntityId(), GetId());
}
//=========================================================================
void EditorScriptCanvasComponent::Activate()
{
EditorComponentBase::Activate();
AZ::EntityId entityId = GetEntityId();
EditorContextMenuRequestBus::Handler::BusConnect(entityId);
EditorScriptCanvasComponentRequestBus::Handler::BusConnect(entityId);
EditorScriptCanvasComponentLoggingBus::Handler::BusConnect(entityId);
EditorLoggingComponentNotificationBus::Broadcast(&EditorLoggingComponentNotifications::OnEditorScriptCanvasComponentActivated, GetNamedEntityId(), GetGraphIdentifier());
AZ::Data::AssetId fileAssetId = m_scriptCanvasAssetHolder.GetAssetId();
if (fileAssetId.IsValid())
{
AssetTrackerNotificationBus::Handler::BusConnect(fileAssetId);
ScriptCanvasMemoryAsset::pointer memoryAsset;
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, fileAssetId);
if (memoryAsset && memoryAsset->GetAsset().GetStatus() == AZ::Data::AssetData::AssetStatus::Ready)
{
OnScriptCanvasAssetReady(memoryAsset);
}
else
{
AssetTrackerRequestBus::Broadcast(&AssetTrackerRequests::Load, m_scriptCanvasAssetHolder.GetAssetId(), m_scriptCanvasAssetHolder.GetAssetType(), nullptr);
}
}
}
//=========================================================================
void EditorScriptCanvasComponent::Deactivate()
{
AssetTrackerNotificationBus::Handler::BusDisconnect();
EditorScriptCanvasComponentLoggingBus::Handler::BusDisconnect();
EditorLoggingComponentNotificationBus::Broadcast(&EditorLoggingComponentNotifications::OnEditorScriptCanvasComponentDeactivated, GetNamedEntityId(), GetGraphIdentifier());
EditorComponentBase::Deactivate();
//EditorScriptCanvasAssetNotificationBus::Handler::BusDisconnect();
EditorScriptCanvasComponentRequestBus::Handler::BusDisconnect();
EditorContextMenuRequestBus::Handler::BusDisconnect();
}
//=========================================================================
void EditorScriptCanvasComponent::BuildGameEntity(AZ::Entity* gameEntity)
{
AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId();
AZ::Data::AssetId runtimeAssetId(assetId.m_guid, AZ_CRC("RuntimeData", 0x163310ae));
AZ::Data::Asset<ScriptCanvas::RuntimeAsset> runtimeAsset(runtimeAssetId, azrtti_typeid<ScriptCanvas::RuntimeAsset>());
auto executionComponent = gameEntity->CreateComponent<ScriptCanvas::RuntimeComponent>(runtimeAsset);
ScriptCanvas::VariableData varData;
for (const auto& varConfig : m_editableData.GetVariables())
{
if (varConfig.m_graphVariable.GetDatum()->Empty())
{
AZ_Error("ScriptCanvas", false, "Data loss detected for GraphVariable ('%s') on Entity ('%s' - '%s') Graph ('%s')"
, varConfig.m_graphVariable.GetVariableName().data()
, gameEntity->GetName().c_str()
, GetEntityId().ToString().c_str()
, GetName().c_str());
}
else
{
varData.AddVariable(varConfig.m_graphVariable.GetVariableName(), varConfig.m_graphVariable);
}
}
executionComponent->SetVariableOverrides(varData);
executionComponent->SetVariableEntityIdMap(m_variableEntityIdMap);
}
void EditorScriptCanvasComponent::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId)
{
// If we removed out asset due to the catalog removing. Just set it back.
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 the Asset gets removed from disk while the Editor is loaded clear out the asset reference.
if (assetId == removedAssetId)
{
m_removedCatalogId = assetId;
SetPrimaryAsset({});
}
}
void EditorScriptCanvasComponent::SetPrimaryAsset(const AZ::Data::AssetId& assetId)
{
m_scriptCanvasAssetHolder.ClearAsset();
if (assetId.IsValid())
{
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);
}
}
}
AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues);
}
AZ::Data::AssetId EditorScriptCanvasComponent::GetAssetId() const
{
return m_scriptCanvasAssetHolder.GetAssetId();
}
AZ::EntityId EditorScriptCanvasComponent::GetGraphEntityId() const
{
AZ::EntityId scriptCanvasEntityId;
AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId();
if (assetId.IsValid())
{
AssetTrackerRequestBus::BroadcastResult(scriptCanvasEntityId, &AssetTrackerRequests::GetScriptCanvasId, assetId);
}
return scriptCanvasEntityId;
}
void EditorScriptCanvasComponent::OnAssetReady(const ScriptCanvasMemoryAsset::pointer asset)
{
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;
ScriptCanvas::GraphIdentifier oldIdentifier = GetGraphIdentifier();
oldIdentifier.m_assetId = m_previousAssetId;
EditorLoggingComponentNotificationBus::Broadcast(&EditorLoggingComponentNotifications::OnAssetSwitched, GetNamedEntityId(), newIdentifier, oldIdentifier);
m_previousAssetId = m_scriptCanvasAssetHolder.GetAssetId();
// 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()))
{
ClearVariables();
}
if (assetId.IsValid())
{
AssetTrackerNotificationBus::Handler::BusConnect(assetId);
ScriptCanvasMemoryAsset::pointer memoryAsset;
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, assetId);
if (memoryAsset && memoryAsset->GetAsset().GetStatus() == AZ::Data::AssetData::AssetStatus::Ready)
{
OnScriptCanvasAssetReady(memoryAsset);
}
}
}
void EditorScriptCanvasComponent::SetAssetId(const AZ::Data::AssetId& assetId)
{
if (m_scriptCanvasAssetHolder.GetAssetId() != assetId)
{
// Invalidate the previously removed catalog id if we are setting a new asset id
m_removedCatalogId.SetInvalid();
SetPrimaryAsset(assetId);
}
}
bool EditorScriptCanvasComponent::HasAssetId() const
{
return m_scriptCanvasAssetHolder.GetAssetId().IsValid();
}
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);
}
void EditorScriptCanvasComponent::OnScriptCanvasAssetReady(const ScriptCanvasMemoryAsset::pointer memoryAsset)
{
if (memoryAsset->GetFileAssetId() == m_scriptCanvasAssetHolder.GetAssetId())
{
LoadVariables(memoryAsset);
UpdateName();
}
}
/*! Start Variable Block Implementation */
void EditorScriptCanvasComponent::AddVariable(AZStd::string_view varName, const ScriptCanvas::GraphVariable& graphVariable)
{
bool exposeVariableToComponent = graphVariable.IsInScope(ScriptCanvas::VariableFlags::Scope::Input);
if (!exposeVariableToComponent)
{
return;
}
const auto& variableId = graphVariable.GetVariableId();
ScriptCanvas::EditableVariableConfiguration* originalVarNameValuePair = m_editableData.FindVariable(variableId);
if (!originalVarNameValuePair)
{
m_editableData.AddVariable(varName, graphVariable);
originalVarNameValuePair = m_editableData.FindVariable(variableId);
}
if (!originalVarNameValuePair)
{
AZ_Error("Script Canvas", false, "Unable to find variable with id %s and name %s on the ScriptCanvas Component. There is an issue in AddVariable",
variableId.ToString().data(), varName.data());
return;
}
// Update the variable name as it may have changed
originalVarNameValuePair->m_graphVariable.SetVariableName(varName);
originalVarNameValuePair->m_graphVariable.SetExposureCategory(graphVariable.GetExposureCategory());
originalVarNameValuePair->m_graphVariable.SetScriptInputControlVisibility(AZ::Edit::PropertyVisibility::Hide);
originalVarNameValuePair->m_graphVariable.SetAllowSignalOnChange(false);
}
void EditorScriptCanvasComponent::AddNewVariables(const ScriptCanvas::VariableData& graphVarData)
{
for (auto&& variablePair : graphVarData.GetVariables())
{
AddVariable(variablePair.second.GetVariableName(), variablePair.second);
}
}
void EditorScriptCanvasComponent::RemoveVariable(const ScriptCanvas::VariableId& varId)
{
m_editableData.RemoveVariable(varId);
}
void EditorScriptCanvasComponent::RemoveOldVariables(const ScriptCanvas::VariableData& graphVarData)
{
AZStd::vector<ScriptCanvas::VariableId> oldVariableIds;
for (auto varConfig : m_editableData.GetVariables())
{
const auto& variableId = varConfig.m_graphVariable.GetVariableId();
auto graphVariable = graphVarData.FindVariable(variableId);
if (!graphVariable || !graphVariable->IsInScope(ScriptCanvas::VariableFlags::Scope::Input))
{
oldVariableIds.push_back(variableId);
}
}
for (const auto& oldVariableId : oldVariableIds)
{
RemoveVariable(oldVariableId);
}
}
bool EditorScriptCanvasComponent::UpdateVariable(const ScriptCanvas::GraphVariable& graphDatum, ScriptCanvas::GraphVariable& updateDatum, ScriptCanvas::GraphVariable& originalDatum)
{
// If the editable datum is the different than the original datum, then the "variable value" has been overridden on this component
// Variable values only propagate from the Script Canvas graph to this component if the original "variable value" has not been overridden
// by the editable "variable value" on this component and the "variable value" on the graph is different than the variable value on this component
auto isNotOverridden = (*updateDatum.GetDatum()) == (*originalDatum.GetDatum());
auto scGraphIsModified = (*originalDatum.GetDatum()) != (*graphDatum.GetDatum());
if (isNotOverridden && scGraphIsModified)
{
ScriptCanvas::ModifiableDatumView originalDatumView;
originalDatum.ConfigureDatumView(originalDatumView);
originalDatumView.AssignToDatum((*graphDatum.GetDatum()));
ScriptCanvas::ModifiableDatumView updatedDatumView;
updateDatum.ConfigureDatumView(updatedDatumView);
updatedDatumView.AssignToDatum((*graphDatum.GetDatum()));
return true;
}
return false;
}
void EditorScriptCanvasComponent::LoadVariables(const ScriptCanvasMemoryAsset::pointer memoryAsset)
{
auto assetData = memoryAsset->GetAsset();
AZ::Entity* scriptCanvasEntity = assetData->GetScriptCanvasEntity();
AZ_Assert(scriptCanvasEntity, "This graph must have a valid entity");
auto variableComponent = scriptCanvasEntity ? AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::GraphVariableManagerComponent>(scriptCanvasEntity) : nullptr;
if (variableComponent)
{
m_variableEntityIdMap.clear();
for (const auto& varIdToVariablePair : variableComponent->GetVariableData()->GetVariables())
{
if (const AZ::EntityId* entityIdVariable = varIdToVariablePair.second.GetDatum()->GetAs<AZ::EntityId>())
{
if (entityIdVariable->IsValid() && (*entityIdVariable) != ScriptCanvas::GraphOwnerId)
{
m_variableEntityIdMap.emplace(static_cast<AZ::u64>(*entityIdVariable), *entityIdVariable);
}
}
}
// Add properties from the SC Asset to the SC Component if they do not exist on the SC Component
AddNewVariables(*variableComponent->GetVariableData());
RemoveOldVariables(*variableComponent->GetVariableData());
}
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
}
void EditorScriptCanvasComponent::ClearVariables()
{
m_editableData.Clear();
}
/* End Variable Block Implementation*/
}
@@ -0,0 +1,201 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <precompiled.h>
#include <AzCore/Serialization/SerializeContext.h>
AZ_PUSH_DISABLE_WARNING(4251 4800 4244, "-Wunknown-warning-option")
#include <ScriptCanvas/Components/EditorUtils.h>
AZ_POP_DISABLE_WARNING
#include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/GraphCanvas/MappingBus.h>
#include <ScriptCanvas/Libraries/Core/EBusEventHandler.h>
#include <ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h>
#include <ScriptCanvas/Utils/NodeUtils.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include <Editor/Include/ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
#include <Editor/View/Widgets/NodePalette/EBusNodePaletteTreeItemTypes.h>
#include <Editor/View/Widgets/NodePalette/FunctionNodePaletteTreeItemTypes.h>
#include <Editor/View/Widgets/NodePalette/ScriptEventsNodePaletteTreeItemTypes.h>
#include <Editor/View/Widgets/NodePalette/GeneralNodePaletteTreeItemTypes.h>
#include <Editor/View/Widgets/NodePalette/NodePaletteModel.h>
#include <Editor/View/Widgets/NodePalette/SpecializedNodePaletteTreeItemTypes.h>
#include <Editor/View/Widgets/NodePalette/VariableNodePaletteTreeItemTypes.h>
namespace ScriptCanvasEditor
{
//////////////////////////
// NodeIdentifierFactory
//////////////////////////
ScriptCanvas::NodeTypeIdentifier NodeIdentifierFactory::ConstructNodeIdentifier(const GraphCanvas::GraphCanvasTreeItem* treeItem)
{
ScriptCanvas::NodeTypeIdentifier resultHash = 0;
if (auto getVariableMethodTreeItem = azrtti_cast<const GetVariableNodePaletteTreeItem*>(treeItem))
{
resultHash = ScriptCanvas::NodeUtils::ConstructGetVariableNodeIdentifier(getVariableMethodTreeItem->GetVariableId());
}
else if (auto setVariableMethodTreeItem = azrtti_cast<const SetVariableNodePaletteTreeItem*>(treeItem))
{
resultHash = ScriptCanvas::NodeUtils::ConstructSetVariableNodeIdentifier(setVariableMethodTreeItem->GetVariableId());
}
else if (auto classMethodTreeItem = azrtti_cast<const ClassMethodEventPaletteTreeItem*>(treeItem))
{
resultHash = ScriptCanvas::NodeUtils::ConstructMethodNodeIdentifier(classMethodTreeItem->GetClassMethodName(), classMethodTreeItem->GetMethodName());
}
else if (auto customNodeTreeItem = azrtti_cast<const CustomNodePaletteTreeItem*>(treeItem))
{
resultHash = ScriptCanvas::NodeUtils::ConstructCustomNodeIdentifier(customNodeTreeItem->GetTypeId());
}
else if (auto sendEbusEventTreeItem = azrtti_cast<const EBusSendEventPaletteTreeItem*>(treeItem))
{
resultHash = ScriptCanvas::NodeUtils::ConstructEBusEventSenderIdentifier(sendEbusEventTreeItem->GetBusId(), sendEbusEventTreeItem->GetEventId());
}
else if (auto handleEbusEventTreeItem = azrtti_cast<const EBusHandleEventPaletteTreeItem*>(treeItem))
{
resultHash = ScriptCanvas::NodeUtils::ConstructEBusEventReceiverIdentifier(handleEbusEventTreeItem->GetBusId(), handleEbusEventTreeItem->GetEventId());
}
else if (auto functionTreeItem = azrtti_cast<const FunctionPaletteTreeItem*>(treeItem))
{
resultHash = ScriptCanvas::NodeUtils::ConstructFunctionNodeIdentifier(functionTreeItem->GetSourceAssetId());
}
return resultHash;
}
AZStd::vector< ScriptCanvas::NodeTypeIdentifier > NodeIdentifierFactory::ConstructNodeIdentifiers(const GraphCanvas::GraphCanvasTreeItem* treeItem)
{
AZStd::vector< ScriptCanvas::NodeTypeIdentifier > nodeIdentifiers;
if (auto scriptEventTreeItem = azrtti_cast<const ScriptEventsEventNodePaletteTreeItem*>(treeItem))
{
nodeIdentifiers.emplace_back(ScriptCanvas::NodeUtils::ConstructScriptEventReceiverIdentifier(scriptEventTreeItem->GetBusIdentifier(), scriptEventTreeItem->GetEventIdentifier()));
nodeIdentifiers.emplace_back(ScriptCanvas::NodeUtils::ConstructSendScriptEventIdentifier(scriptEventTreeItem->GetBusIdentifier(), scriptEventTreeItem->GetEventIdentifier()));
}
else
{
nodeIdentifiers.emplace_back(ConstructNodeIdentifier(treeItem));
}
return nodeIdentifiers;
}
//////////////////////////
// GraphStatisticsHelper
//////////////////////////
void GraphStatisticsHelper::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<GraphStatisticsHelper>()
->Version(1)
->Field("InstanceCounter", &GraphStatisticsHelper::m_nodeIdentifierCount)
;
}
}
void GraphStatisticsHelper::PopulateStatisticData(const Graph* editorGraph)
{
// Opportunistically use this time to refresh out node count array.
m_nodeIdentifierCount.clear();
for (auto* nodeEntity : editorGraph->GetNodeEntities())
{
auto nodeComponent = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Node>(nodeEntity);
if (nodeComponent)
{
if (auto ebusHandlerNode = azrtti_cast<ScriptCanvas::Nodes::Core::EBusEventHandler*>(nodeComponent))
{
GraphCanvas::NodeId graphCanvasNodeId;
SceneMemberMappingRequestBus::EventResult(graphCanvasNodeId, nodeEntity->GetId(), &SceneMemberMappingRequests::GetGraphCanvasEntityId);
const ScriptCanvas::Nodes::Core::EBusEventHandler::EventMap& events = ebusHandlerNode->GetEvents();
ScriptCanvas::EBusBusId busId = ebusHandlerNode->GetEBusId();
for (const auto& eventPair : events)
{
bool hasEvent = false;
EBusHandlerNodeDescriptorRequestBus::EventResult(hasEvent, graphCanvasNodeId, &EBusHandlerNodeDescriptorRequests::ContainsEvent, eventPair.second.m_eventId);
// In case we are populating from an uncreated scene if we don't have a valid graph canvas node id
// just accept everything. We can overreport on unknown data for now.
if (hasEvent || !graphCanvasNodeId.IsValid())
{
RegisterNodeType(ScriptCanvas::NodeUtils::ConstructEBusEventReceiverIdentifier(busId, eventPair.second.m_eventId));
}
}
}
else if (auto scriptEventHandler = azrtti_cast<ScriptCanvas::Nodes::Core::ReceiveScriptEvent*>(nodeComponent))
{
GraphCanvas::NodeId graphCanvasNodeId;
SceneMemberMappingRequestBus::EventResult(graphCanvasNodeId, nodeEntity->GetId(), &SceneMemberMappingRequests::GetGraphCanvasEntityId);
EBusHandlerNodeDescriptorRequests* ebusDescriptorRequests = EBusHandlerNodeDescriptorRequestBus::FindFirstHandler(graphCanvasNodeId);
if (ebusDescriptorRequests == nullptr)
{
continue;
}
AZStd::vector< HandlerEventConfiguration > eventConfigurations = ebusDescriptorRequests->GetEventConfigurations();
ScriptCanvas::EBusBusId busId = scriptEventHandler->GetBusId();
for (const auto& eventConfiguration : eventConfigurations)
{
bool hasEvent = ebusDescriptorRequests->ContainsEvent(eventConfiguration.m_eventId);
// In case we are populating from an uncreated scene if we don't have a valid graph canvas node id
// just accept everything. We can overreport on unknown data for now.
if (hasEvent)
{
RegisterNodeType(ScriptCanvas::NodeUtils::ConstructScriptEventReceiverIdentifier(busId, eventConfiguration.m_eventId));
}
}
}
else
{
ScriptCanvas::NodeTypeIdentifier nodeType = nodeComponent->GetNodeType();
// Fallback in case something isn't initialized for whatever reason
if (nodeType == 0)
{
nodeType = ScriptCanvas::NodeUtils::ConstructNodeType(nodeComponent);
}
RegisterNodeType(nodeType);
}
}
}
}
void GraphStatisticsHelper::RegisterNodeType(const ScriptCanvas::NodeTypeIdentifier& nodeTypeIdentifier)
{
auto nodeIter = m_nodeIdentifierCount.find(nodeTypeIdentifier);
if (nodeIter == m_nodeIdentifierCount.end())
{
m_nodeIdentifierCount.emplace(AZStd::make_pair(nodeTypeIdentifier, 1));
}
else
{
nodeIter->second++;
}
}
}
@@ -0,0 +1,122 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include "IconComponent.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContextConstants.inl>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Component/ComponentApplicationBus.h>
namespace ScriptCanvasEditor
{
AZStd::string IconComponent::LookupClassIcon(const AZ::Uuid& classId)
{
AZStd::string iconPath = "Editor/Icons/ScriptCanvas/Placeholder.png";
AZ::SerializeContext* serializeContext = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
AZ_Assert(serializeContext, "Failed to acquire application serialize context.");
const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(classId);
// Find the icon's path in the editor data attributes
if (classData && classData->m_editData)
{
auto editorElementData = classData->m_editData->FindElementData(AZ::Edit::ClassElements::EditorData);
if (editorElementData)
{
if (auto iconAttribute = editorElementData->FindAttribute(AZ::Edit::Attributes::Icon))
{
if (auto iconAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<const char*>*>(iconAttribute))
{
AZStd::string iconAttributeValue = iconAttributeData->Get(nullptr);
if (!iconAttributeValue.empty())
{
iconPath = AZStd::move(iconAttributeValue);
}
}
}
}
}
return iconPath;
}
IconComponent::IconComponent(const AZ::Uuid& classId)
{
m_iconPath = LookupClassIcon(classId);
}
void IconComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<IconComponent, AZ::Component>()
->Version(1)
->Field("m_iconPath", &IconComponent::m_iconPath)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<IconComponent>("Icon", "Represents a icon path")
->ClassElement(AZ::Edit::ClassElements::EditorData, "Icon Components class attributes")
;
}
}
}
void IconComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC("GraphCanvas_IconService", 0x2037454a));
}
void IconComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC("GraphCanvas_IconService", 0x2037454a));
}
void IconComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
{
(void)dependent;
}
void IconComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
(void)required;
}
void IconComponent::Init()
{
}
void IconComponent::Activate()
{
IconBus::Handler::BusConnect(GetEntityId());
}
void IconComponent::Deactivate()
{
IconBus::Handler::BusDisconnect();
}
AZStd::string IconComponent::GetIconPath() const
{
return m_iconPath;
}
} // namespace ScriptCanvasEditor
@@ -0,0 +1,51 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Math/Uuid.h>
#include <AzCore/Component/Component.h>
#include <Editor/Include/ScriptCanvas/Bus/IconBus.h>
namespace ScriptCanvasEditor
{
class IconComponent
: public AZ::Component
, public IconBus::Handler
{
public:
AZ_COMPONENT(IconComponent, "{242FEF0E-1E3D-4F49-877F-F83E6B70F138}");
static AZStd::string LookupClassIcon(const AZ::Uuid& classId);
IconComponent() = default;
IconComponent(const AZ::Uuid& classId);
~IconComponent() = default;
static void Reflect(AZ::ReflectContext* serialize);
// AZ::Component
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
void Init() override;
void Activate() override;
void Deactivate() override;
// IconBus
AZStd::string GetIconPath() const override;
private:
AZStd::string m_iconPath;
};
}
@@ -0,0 +1,13 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
@@ -0,0 +1,18 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
namespace DragonUI
{
}
@@ -0,0 +1,460 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/UserSettings/UserSettingsProvider.h>
#include <AzQtComponents/Components/FancyDocking.h>
#include <GraphCanvas/Components/Nodes/Comment/CommentBus.h>
#include "Settings.h"
#include <ScriptCanvas/Data/Data.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include <Editor/View/Widgets/VariablePanel/GraphVariablesTableView.h>
#include <Editor/View/Windows/MainWindow.h>
namespace ScriptCanvasEditor
{
namespace EditorSettings
{
/////////////////////////////////
// ScriptCanvasConstructPresets
/////////////////////////////////
ScriptCanvasConstructPresets::ScriptCanvasConstructPresets()
{
}
void ScriptCanvasConstructPresets::InitializeConstructType(GraphCanvas::ConstructType constructType)
{
if (constructType == GraphCanvas::ConstructType::NodeGroup)
{
GraphCanvas::NodeGroupPresetBucket* nodeGroupPresetBucket = static_cast<GraphCanvas::NodeGroupPresetBucket*>(ModPresetBuckket(GraphCanvas::ConstructType::NodeGroup));
if (nodeGroupPresetBucket)
{
nodeGroupPresetBucket->ClearPresets();
AZStd::vector< AZStd::pair< AZStd::string, AZ::Color > > defaultGroupPresets = {
{ "Initialization", AZ::Color(0.188f, 0.972f, 0.243f, 1.0f) },
{ "UI", AZ::Color(0.741f, 0.372f, 0.545f, 1.0f) },
{ "AI", AZ::Color(0.396f, 0.788f, 0.788f, 1.0f) },
{ "Physics", AZ::Color(0.866f, 0.498f, 0.427f, 1.0f) },
{ "Input", AZ::Color(0.396f, 0.788f, 0.549f, 1.0f) }
};
for (auto groupPairing : defaultGroupPresets)
{
AZStd::shared_ptr< GraphCanvas::ConstructPreset > initializaitonGroupPreset = nodeGroupPresetBucket->CreateNewPreset(groupPairing.first);
if (initializaitonGroupPreset)
{
const auto& presetSaveData = initializaitonGroupPreset->GetPresetData();
GraphCanvas::CommentNodeTextSaveData* saveData = presetSaveData.FindSaveDataAs<GraphCanvas::CommentNodeTextSaveData>();
if (saveData)
{
saveData->m_backgroundColor = groupPairing.second;
}
}
}
}
}
else if (constructType == GraphCanvas::ConstructType::CommentNode)
{
GraphCanvas::CommentPresetBucket* commentPresetBucket = static_cast<GraphCanvas::CommentPresetBucket*>(ModPresetBuckket(GraphCanvas::ConstructType::CommentNode));
commentPresetBucket->ClearPresets();
}
}
////////////////////
// EditorWorkspace
////////////////////
void EditorWorkspace::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
if (serialize)
{
serialize->Class<EditorWorkspace>()
->Version(2)
->Field("m_storedWindowState", &EditorWorkspace::m_storedWindowState)
->Field("m_windowGeometry", &EditorWorkspace::m_windowGeometry)
->Field("FocusedAssetId", &EditorWorkspace::m_focusedAssetId)
->Field("ActiveAssetIds", &EditorWorkspace::m_activeAssetIds)
;
}
}
void EditorWorkspace::ConfigureActiveAssets(AZ::Data::AssetId focussedAssetId, const AZStd::vector< AZ::Data::AssetId >& activeAssetIds)
{
m_focusedAssetId = focussedAssetId;
m_activeAssetIds = activeAssetIds;
}
AZ::Data::AssetId EditorWorkspace::GetFocusedAssetId() const
{
return m_focusedAssetId;
}
AZStd::vector< AZ::Data::AssetId > EditorWorkspace::GetActiveAssetIds() const
{
return m_activeAssetIds;
}
void EditorWorkspace::Init(const QByteArray& windowState)
{
m_storedWindowState.clear();
m_windowState.assign((AZ::u8*)windowState.begin(), (AZ::u8*)windowState.end());
m_storedWindowState.assign((AZ::u8*)windowState.begin(), (AZ::u8*)windowState.end());
}
void EditorWorkspace::Restore(MainWindow* window)
{
AZ_Assert(window, "A valid window must be provided to restore its state.");
QByteArray windowStateData((const char*)GetWindowState().data(), (int)GetWindowState().size());
window->restoreState(windowStateData);
}
const AZStd::vector<AZ::u8>& EditorWorkspace::GetWindowState()
{
m_windowState.clear();
m_windowState.assign(m_storedWindowState.begin(), m_storedWindowState.end());
return m_windowState;
}
////////////////////
// StylingSettings
////////////////////
void StylingSettings::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<StylingSettings>()
->Version(1)
->Field("ConnectionCurveType", &StylingSettings::m_connectionCurveType)
->Field("DataConnectionCurveType", &StylingSettings::m_dataConnectionCurveType)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<StylingSettings>("StylingSettings", "All of the styling configurations that can be customized per user.")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::ComboBox, &StylingSettings::m_connectionCurveType, "Connection Curve Type", "Controls the curve style of general connections.")
->EnumAttribute(GraphCanvas::Styling::ConnectionCurveType::Straight, "Straight")
->EnumAttribute(GraphCanvas::Styling::ConnectionCurveType::Curved, "Curved")
->DataElement(AZ::Edit::UIHandlers::ComboBox, &StylingSettings::m_dataConnectionCurveType, "Data Connection Curve Type", "Controls the curve style of data connections.")
->EnumAttribute(GraphCanvas::Styling::ConnectionCurveType::Straight, "Straight")
->EnumAttribute(GraphCanvas::Styling::ConnectionCurveType::Curved, "Curved")
;
}
}
}
///////////////////////////////
// ScriptCanvasEditorSettings
///////////////////////////////
bool ScriptCanvasEditorSettings::VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
{
if (classElement.GetVersion() <= 5)
{
AZ::Crc32 dragCouplingEnabledId = AZ_CRC("m_enableNodeDragCoupling", 0x3edd74aa);
AZ::Crc32 dragCouplingTimeId = AZ_CRC("m_dragNodeCouplingTime", 0xe6f213ae);
AZ::Crc32 dragSplicingEnabledId = AZ_CRC("m_enableNodeDragConnectionSplicing", 0x77957b8f);
AZ::Crc32 dragSplicingTimeId = AZ_CRC("m_dragNodeConnectionSplicingTime", 0x3e3742fb);
AZ::Crc32 dropSplicingEnabledId = AZ_CRC("m_enableNodeDropConnectionSplicing", 0x371180a9);
AZ::Crc32 dropSplicingTimeId = AZ_CRC("m_dropNodeConnectionSplicingTime", 0xba85498e);
ToggleableConfiguration dragCouplingConfiguration(false,1000);
ToggleableConfiguration dragSplicingConfiguration(true, 1000);
ToggleableConfiguration dropSplicingConfiguration(true, 1000);
// Drag Coupling
AZ::SerializeContext::DataElementNode* dataNode = classElement.FindSubElement(dragCouplingEnabledId);
if (dataNode)
{
dataNode->GetData(dragCouplingConfiguration.m_enabled);
}
classElement.RemoveElementByName(dragCouplingEnabledId);
dataNode = classElement.FindSubElement(dragCouplingTimeId);
if (dataNode)
{
dataNode->GetData(dragCouplingConfiguration.m_timeMS);
}
classElement.RemoveElementByName(dragCouplingTimeId);
// Drag Splicing
dataNode = classElement.FindSubElement(dragSplicingEnabledId);
if (dataNode)
{
dataNode->GetData(dragSplicingConfiguration.m_timeMS);
}
classElement.RemoveElementByName(dragSplicingEnabledId);
dataNode = classElement.FindSubElement(dragSplicingTimeId);
if (dataNode)
{
dataNode->GetData(dragSplicingConfiguration.m_timeMS);
}
classElement.RemoveElementByName(dragSplicingTimeId);
// Drop Splicing
dataNode = classElement.FindSubElement(dropSplicingEnabledId);
if (dataNode)
{
dataNode->GetData(dropSplicingConfiguration.m_timeMS);
}
classElement.RemoveElementByName(dropSplicingEnabledId);
dataNode = classElement.FindSubElement(dropSplicingTimeId);
if (dataNode)
{
dataNode->GetData(dropSplicingConfiguration.m_timeMS);
}
classElement.RemoveElementByName(dropSplicingTimeId);
classElement.AddElementWithData(context, "DragCouplingConfiguration", dragCouplingConfiguration);
classElement.AddElementWithData(context, "DragSplicingConfiguration", dragSplicingConfiguration);
classElement.AddElementWithData(context, "DropSplicingConfiguration", dropSplicingConfiguration);
}
if (classElement.GetVersion() <= 11)
{
classElement.RemoveElementByName(AZ::Crc32("ConstructPresets"));
}
if (classElement.GetVersion() <= 14)
{
classElement.RemoveElementByName(AZ_CRC("m_showPreviewMessage", 0x375b279b));
classElement.RemoveElementByName(AZ_CRC("m_showExcludedNodes", 0x4c802d0c));
}
return true;
}
void ScriptCanvasEditorSettings::Reflect(AZ::ReflectContext* context)
{
StylingSettings::Reflect(context);
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
if (serialize)
{
serialize->Class<ScriptCanvasConstructPresets, GraphCanvas::EditorConstructPresets>()
->Version(1)
;
serialize->Class<ToggleableConfiguration>()
->Version(1)
->Field("Enabled", &ToggleableConfiguration::m_enabled)
->Field("TimeMS", &ToggleableConfiguration::m_timeMS)
;
serialize->Class<AutoSaveSettings>()
->Version(1)
->Field("Enabled", &AutoSaveSettings::m_enabled)
->Field("TimeSeconds", &AutoSaveSettings::m_timeSeconds)
;
serialize->Class<ShakeToDespliceSettings>()
->Version(1)
->Field("Enabled", &ShakeToDespliceSettings::m_enabled)
->Field("ShakeCount", &ShakeToDespliceSettings::m_shakeCount)
->Field("ShakeLength", &ShakeToDespliceSettings::m_minimumShakeLengthPercent)
->Field("DeadZone", &ShakeToDespliceSettings::m_deadZonePercent)
->Field("ShakeTime", &ShakeToDespliceSettings::m_maximumShakeTimeMS)
->Field("Straightness", &ShakeToDespliceSettings::m_straightnessPercent)
;
serialize->Class<EdgePanningSettings>()
->Version(1)
->Field("EdgePercent", &EdgePanningSettings::m_edgeScrollPercent)
->Field("ScrollSpeed", &EdgePanningSettings::m_edgeScrollSpeed)
;
serialize->Class<ZoomSettings>()
->Version(2)
->Field("MinZoom", &ZoomSettings::m_zoomInSetting)
;
serialize->Class<ScriptCanvasEditorSettings>()
->Version(16, ScriptCanvasEditorSettings::VersionConverter)
->Field("m_snapDistance", &ScriptCanvasEditorSettings::m_snapDistance)
->Field("m_pinnedDataTypes", &ScriptCanvasEditorSettings::m_pinnedDataTypes)
->Field("m_allowBookmarkViewpointControl", &ScriptCanvasEditorSettings::m_allowBookmarkViewpointControl)
->Field("DragCouplingConfiguration", &ScriptCanvasEditorSettings::m_dragNodeCouplingConfig)
->Field("DragSplicingConfiguration", &ScriptCanvasEditorSettings::m_dragNodeSplicingConfig)
->Field("DropSplicingConfiguration", &ScriptCanvasEditorSettings::m_dropNodeSplicingConfig)
->Field("AutoSaveConfiguration", &ScriptCanvasEditorSettings::m_autoSaveConfig)
->Field("ShakeToDespliceConfiguration", &ScriptCanvasEditorSettings::m_shakeDespliceConfig)
->Field("VariableColumnSorting", &ScriptCanvasEditorSettings::m_variablePanelSorting)
->Field("ShowWarnings", &ScriptCanvasEditorSettings::m_showValidationWarnings)
->Field("ShowErrors", &ScriptCanvasEditorSettings::m_showValidationErrors)
->Field("AllowNodeNudging", &ScriptCanvasEditorSettings::m_allowNodeNudging)
->Field("AlignmentTime", &ScriptCanvasEditorSettings::m_alignmentTimeMS)
->Field("EdgePanningSettings", &ScriptCanvasEditorSettings::m_edgePanningSettings)
->Field("ConstructPresets", &ScriptCanvasEditorSettings::m_constructPresets)
->Field("StylingSettings", &ScriptCanvasEditorSettings::m_stylingSettings)
->Field("RememberOpenCanvases", &ScriptCanvasEditorSettings::m_rememberOpenCanvases)
->Field("ZoomSettings", &ScriptCanvasEditorSettings::m_zoomSettings)
;
AZ::EditContext* editContext = serialize->GetEditContext();
if (editContext)
{
editContext->Class<ToggleableConfiguration>("Configuration", "A pair of configuration values for actions that can be enabled/disabled and occur after a certain amount of time.")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &ToggleableConfiguration::m_enabled, "Enabled", "Controls whether or not the action is Enabled.")
->DataElement(AZ::Edit::UIHandlers::Default, &ToggleableConfiguration::m_timeMS, "Time MS", "Controls how long until the action takes place.")
->Attribute(AZ::Edit::Attributes::Suffix, "ms")
->Attribute(AZ::Edit::Attributes::Min, 1)
;
editContext->Class<AutoSaveSettings>("Auto Save Configuration", "A pair of configuration values for actions that can be enabled/disabled and occur after a certain amount of time.")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &AutoSaveSettings::m_enabled, "Enabled", "Controls whether or not the action is Enabled.")
->DataElement(AZ::Edit::UIHandlers::Default, &AutoSaveSettings::m_timeSeconds, "Time Seconds", "Controls how long until the action takes place.")
->Attribute(AZ::Edit::Attributes::Suffix, "seconds")
->Attribute(AZ::Edit::Attributes::Min, 10)
;
editContext->Class<ShakeToDespliceSettings>("Shake To Desplice", "Settings that control various parameters of the shake to desplice feature")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &ShakeToDespliceSettings::m_enabled, "Enabled", "Controls whether or not this feature is enabled")
->DataElement(AZ::Edit::UIHandlers::Default, &ShakeToDespliceSettings::m_shakeCount, "Shake Count", "Controls the number of shakes that must occur in order to trigger the splice")
->DataElement(AZ::Edit::UIHandlers::Slider, &ShakeToDespliceSettings::m_minimumShakeLengthPercent, "Shake Length", "Controls how long each motion must be in order to be registered as a shake.")
->Attribute(AZ::Edit::Attributes::Min, 0.0)
->Attribute(AZ::Edit::Attributes::Max, 100.0)
->Attribute(AZ::Edit::Attributes::Step, 1.0)
->DataElement(AZ::Edit::UIHandlers::Slider, &ShakeToDespliceSettings::m_deadZonePercent, "Dead Zone", "Controls how far the cursor must move before a check is initiated.")
->Attribute(AZ::Edit::Attributes::Min, 0.0)
->Attribute(AZ::Edit::Attributes::Max, 100.0)
->Attribute(AZ::Edit::Attributes::Step, 1.0)
->DataElement(AZ::Edit::UIHandlers::Default, &ShakeToDespliceSettings::m_maximumShakeTimeMS, "Maximmum Shake Time", "Sets a cap on how long it consider a series of actions as a single shake gesture")
->Attribute(AZ::Edit::Attributes::Suffix, "ms")
->Attribute(AZ::Edit::Attributes::Min, 1)
->DataElement(AZ::Edit::UIHandlers::Slider, &ShakeToDespliceSettings::m_straightnessPercent, "Straightness Percent", "Controls how aligned the individual motions must be in order to qualify as a shake")
->Attribute(AZ::Edit::Attributes::Min, 0.0)
->Attribute(AZ::Edit::Attributes::Max, 100.0)
->Attribute(AZ::Edit::Attributes::Step, 1.0)
;
editContext->Class<EdgePanningSettings>("Edge Panning Settings", "Settings that control various parameters of the edge panning feature")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Slider, &EdgePanningSettings::m_edgeScrollPercent, "Percentage from Edge", "The percentage of the visible area to start scrolling when the mouse cursor is dragged into.")
->Attribute(AZ::Edit::Attributes::Min, 0.0)
->Attribute(AZ::Edit::Attributes::Max, 50.0)
->Attribute(AZ::Edit::Attributes::Step, 1.0)
->DataElement(AZ::Edit::UIHandlers::Default, &EdgePanningSettings::m_edgeScrollSpeed, "Scroll Speed", "How fast the scene will scroll when scrolling")
->Attribute(AZ::Edit::Attributes::Min, 1.0)
;
editContext->Class<ZoomSettings>("Zoom Settings", "Settings that control the degree to which the scene can be zoomed in or out.")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Slider, &ZoomSettings::m_zoomInSetting, "Maximum Zoom In", "Controls the maximum magnification for zooming in")
->Attribute(AZ::Edit::Attributes::Min, 1.0)
->Attribute(AZ::Edit::Attributes::Max, 5.0)
->Attribute(AZ::Edit::Attributes::Step, 0.1)
->Attribute(AZ::Edit::Attributes::Suffix, "X")
;
editContext->Class<ScriptCanvasEditorSettings>("Script Canvas Editor Preferences", "Preferences relating to the Script Canvas editor.")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20))
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasEditorSettings::m_snapDistance, "Connection Snap Distance", "The distance from a slot under which connections will snap to it.")
->Attribute(AZ::Edit::Attributes::Min, 10.0)
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasEditorSettings::m_allowBookmarkViewpointControl, "Bookmark Zooming", "Will cause the bookmarks to force the viewport into the state determined by the bookmark type\nBookmark Anchors - The viewport that exists when the bookmark is created.\nNode Groups - The area the Node Group covers")
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasEditorSettings::m_dragNodeCouplingConfig, "Node Coupling Configuration", "Controls for managing Node Coupling.\nNode Coupling is when you are dragging a node and leave it hovered over another Node, we will try to connect the sides you overlapped with each other.")
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasEditorSettings::m_dragNodeSplicingConfig, "Drag Node Splicing Configuration", "Controls for managing Node Splicing on a Drag.\nNode Splicing on a Drag will let you drag a node onto a connection, and splice that node onto the specified connection.")
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasEditorSettings::m_dropNodeSplicingConfig, "Drop Node Splicing Configuration", "Controls for managing Node Splicing on a Drag.\nNode Splicing on a drop will let you drop a node onto a connection from the Node Palette, and splice that node onto the specified connection.")
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasEditorSettings::m_autoSaveConfig, "AutoSave Configuration", "Controls for managing Auto Saving.\nAuto Saving will occur after the specified time of inactivity on a graph.")
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasEditorSettings::m_shakeDespliceConfig, "Shake To Desplice", "Settings that controls various parameters of the Shake to Desplice feature")
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasEditorSettings::m_allowNodeNudging, "Allow Node Nudging", "Controls whether or not nodes will attempt to nudge each other out of the way under various interactions.")
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasEditorSettings::m_alignmentTimeMS, "Alignment Time", "Controls the amount of time nodes will take to slide into place when performing alignment commands")
->Attribute(AZ::Edit::Attributes::Min, 0)
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasEditorSettings::m_edgePanningSettings, "Edge Panning Settings", "Settings that control how the panning at the edge of the scene will be handled.")
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasEditorSettings::m_zoomSettings, "Zoom Settings", "Settings that will control the boundaries of the zoom settings")
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasEditorSettings::m_rememberOpenCanvases, "Remember Open Canvases", "Determines whether or ScriptCanvses that were open when the editor is closed will be re-opened on the next open.")
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptCanvasEditorSettings::m_stylingSettings, "Styling Settings", "Settings that will control various visual styling aspects of the Script Canvas Scene")
;
}
}
}
ScriptCanvasEditorSettings::ScriptCanvasEditorSettings()
: m_snapDistance(10.0)
, m_allowBookmarkViewpointControl(true)
, m_allowNodeNudging(true)
, m_rememberOpenCanvases(true)
, m_dragNodeCouplingConfig(true, 750)
, m_dragNodeSplicingConfig(true, 1000)
, m_dropNodeSplicingConfig(true, 1000)
, m_autoSaveConfig(false, 10)
, m_pinnedDataTypes({
ScriptCanvas::Data::ToAZType(ScriptCanvas::Data::Type::Number()),
ScriptCanvas::Data::ToAZType(ScriptCanvas::Data::Type::Boolean()),
ScriptCanvas::Data::ToAZType(ScriptCanvas::Data::Type::String()),
ScriptCanvas::Data::ToAZType(ScriptCanvas::Data::Type::Color()),
ScriptCanvas::Data::ToAZType(ScriptCanvas::Data::Type::EntityID()),
ScriptCanvas::Data::ToAZType(ScriptCanvas::Data::Type::Transform()),
ScriptCanvas::Data::ToAZType(ScriptCanvas::Data::Type::Vector2()),
ScriptCanvas::Data::ToAZType(ScriptCanvas::Data::Type::Vector3()),
ScriptCanvas::Data::ToAZType(ScriptCanvas::Data::Type::Vector4())
})
, m_variablePanelSorting(GraphVariablesModel::Name)
, m_showValidationWarnings(true)
, m_showValidationErrors(true)
, m_alignmentTimeMS(250)
{
GraphCanvas::AssetEditorPresetNotificationBus::Handler::BusConnect(ScriptCanvasEditor::AssetEditorId);
}
void ScriptCanvasEditorSettings::OnConstructPresetsChanged([[maybe_unused]] GraphCanvas::ConstructType constructType)
{
AZ::UserSettingsOwnerRequestBus::Event(AZ::UserSettings::CT_LOCAL, &AZ::UserSettingsOwnerRequests::SaveSettings);
}
}
}
@@ -0,0 +1,33 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Editor/Framework/ScriptCanvasTraceUtilities.h>
#include <Editor/Framework/ScriptCanvasReporter.h>
namespace ScriptCanvas
{
class RuntimeAsset;
class RuntimeComponent;
}
namespace ScriptCanvasEditor
{
inline void RunGraph(AZStd::string_view graphPath, ScriptCanvas::ExecutionMode execution, const DurationSpec& /*duration*/, Reporter& reporter);
inline Reporter RunGraph(AZStd::string_view graphPath, ScriptCanvas::ExecutionMode execution, const DurationSpec& /*duration*/);
inline Reporter RunGraph(AZStd::string_view graphPath, const DurationSpec& duration);
inline Reporter RunGraph(AZStd::string_view graphPath, ScriptCanvas::ExecutionMode execution);
inline LoadTestGraphResult LoadTestGraph(AZStd::string_view path);
} // ScriptCanvasEditor
#include <Editor/Framework/ScriptCanvasGraphUtilities.inl>
@@ -0,0 +1,89 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Asset/EditorAssetSystemComponent.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/FileIOEventBus.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Asset/RuntimeAssetHandler.h>
#include <ScriptCanvas/Execution/RuntimeComponent.h>
#include <Editor/Framework/ScriptCanvasTraceUtilities.h>
#include <Editor/Framework/ScriptCanvasReporter.h>
namespace ScriptCanvasEditor
{
using namespace ScriptCanvas;
inline void RunGraph(AZStd::string_view graphPath, [[maybe_unused]] ScriptCanvas::ExecutionMode execution, [[maybe_unused]] const DurationSpec& duration, Reporter& reporter)
{
TraceSuppressionBus::Broadcast(&TraceSuppressionRequests::SuppressPrintf, true);
LoadTestGraphResult loadResult = LoadTestGraph(graphPath);
TraceSuppressionBus::Broadcast(&TraceSuppressionRequests::SuppressPrintf, false);
if (loadResult.m_graph)
{
reporter.SetGraph(loadResult.m_graph->GetScriptCanvasId(), loadResult.m_graph->GetEntityId());
loadResult.m_graphEntity->Init();
TraceSuppressionBus::Broadcast(&TraceSuppressionRequests::SuppressPrintf, true);
loadResult.m_graphEntity->Activate();
TraceSuppressionBus::Broadcast(&TraceSuppressionRequests::SuppressPrintf, false);
loadResult.m_graphEntity->Deactivate();
reporter.FinishReport(loadResult.m_graph->IsInErrorState());
loadResult.m_graphEntity.reset();
}
else
{
reporter.FinishReport();
}
}
inline Reporter RunGraph(AZStd::string_view graphPath, ExecutionMode execution, const DurationSpec& duration)
{
Reporter reporter;
RunGraph(graphPath, execution, duration, reporter);
return reporter;
}
inline Reporter RunGraph(AZStd::string_view graphPath, const DurationSpec& duration)
{
return RunGraph(graphPath, ExecutionMode::Interpreted, duration);
}
inline Reporter RunGraph(AZStd::string_view graphPath, ExecutionMode execution)
{
return RunGraph(graphPath, execution, DurationSpec());
}
inline LoadTestGraphResult LoadTestGraph(AZStd::string_view graphPath)
{
AZ::Outcome< AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> assetOutcome = AZ::Failure(AZStd::string("asset creation failed"));
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(assetOutcome, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateRuntimeAsset, graphPath);
if (assetOutcome.IsSuccess())
{
LoadTestGraphResult result;
result.m_asset = assetOutcome.GetValue();
result.m_graphEntity = AZStd::make_unique<AZ::Entity>("Loaded Graph");
result.m_graph = result.m_graphEntity->CreateComponent<ScriptCanvas::RuntimeComponent>(result.m_asset);
return result;
}
return {};
}
} // namespace ScriptCanvasEditor
@@ -0,0 +1,127 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/Entity.h>
#include <AzCore/Component/EntityBus.h>
#include <AzCore/Component/EntityId.h>
#include <ScriptCanvas/Data/Data.h>
#include <ScriptCanvas/Libraries/UnitTesting/UnitTestBus.h>
#include <ScriptCanvas/Execution/RuntimeComponent.h>
#define SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_EQ(LHS, RHS)\
if(!(LHS == RHS)) { AddFailure(AZStd::string::format("Error | Expected (candidate) == (reference).\n%s", report.data())); }
#define SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_NE(LHS, RHS)\
if(!(LHS != RHS)) { AddFailure(AZStd::string::format("Error | Expected (candidate) != (reference).\n%s", report.data())); }
#define SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_GT(LHS, RHS)\
if(!(LHS > RHS)) { AddFailure(AZStd::string::format("Error | Expected (candidate) > (reference).\n%s", report.data())); }
#define SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_GE(LHS, RHS)\
if(!(LHS >= RHS)) { AddFailure(AZStd::string::format("Error | Expected (candidate) >= (reference).\n%s", report.data())); }
#define SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_LT(LHS, RHS)\
if(!(LHS < RHS)) { AddFailure(AZStd::string::format("Error | Expected (candidate) < (reference).\n%s", report.data())); }
#define SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_LE(LHS, RHS)\
if(!(LHS <= RHS)) { AddFailure(AZStd::string::format("Error | Expected (candidate) <= (reference).\n%s", report.data())); }
namespace ScriptCanvasEditor
{
using namespace ScriptCanvas;
using namespace ScriptCanvas::UnitTesting;
class Reporter
: public Bus::Handler
, public AZ::EntityBus::Handler
{
public:
Reporter();
Reporter(const ScriptCanvasId& graphID, const AZ::EntityId& entityID);
~Reporter();
void FinishReport();
void FinishReport(const bool inErrorState);
const AZStd::vector<Report>& GetCheckpoints() const;
const AZStd::vector<Report>& GetFailure() const;
const ScriptCanvasId& GetScriptCanvasId() const;
const AZStd::vector<Report>& GetSuccess() const;
bool IsActivated() const;
bool IsComplete() const;
bool IsDeactivated() const;
bool IsErrorFree() const;
bool IsReportFinished() const;
bool operator==(const Reporter& other) const;
void Reset();
void SetGraph(const ScriptCanvasId& graphID, const AZ::EntityId& entityID);
// Bus::Handler
void AddFailure(const Report& report) override;
void AddSuccess(const Report& report) override;
void Checkpoint(const Report& report) override;
void ExpectFalse(const bool value, const Report& report) override;
void ExpectTrue(const bool value, const Report& report) override;
void MarkComplete(const Report& report) override;
SCRIPT_CANVAS_UNIT_TEST_EQUALITY_OVERLOAD_OVERRIDES(ExpectEqual);
SCRIPT_CANVAS_UNIT_TEST_EQUALITY_OVERLOAD_OVERRIDES(ExpectNotEqual);
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_OVERRIDES(ExpectGreaterThan);
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_OVERRIDES(ExpectGreaterThanEqual);
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_OVERRIDES(ExpectLessThan);
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_OVERRIDES(ExpectLessThanEqual);
protected:
void OnEntityActivated(const AZ::EntityId&) override;
void OnEntityDeactivated(const AZ::EntityId&) override;
private:
bool m_graphIsActivated = false;
bool m_graphIsDeactivated = false;
bool m_graphIsComplete = false;
bool m_graphIsErrorFree = false;
bool m_isReportFinished = false;
ScriptCanvasId m_scriptCanvasId;
AZ::EntityId m_entityId;
AZStd::vector<Report> m_checkpoints;
AZStd::vector<Report> m_failures;
AZStd::vector<Report> m_successes;
}; // class Reporter
} // namespace ScriptCanvasEditor
#include "ScriptCanvasReporter.inl"
@@ -0,0 +1,311 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
namespace ScriptCanvasEditor
{
using namespace ScriptCanvas;
inline Reporter::Reporter()
{
}
inline Reporter::Reporter(const ScriptCanvasId& scriptCanvasId, const AZ::EntityId& entityID) : Reporter()
{
SetGraph(scriptCanvasId, entityID);
}
inline Reporter::~Reporter()
{
Reset();
}
inline void Reporter::Checkpoint(const Report& report)
{
if (m_isReportFinished)
{
return;
}
m_checkpoints.push_back(report);
}
inline const AZStd::vector<Report>& Reporter::GetCheckpoints() const
{
if (!m_isReportFinished)
{
AZ_Error("ScriptCanvas", false, "The report must be finished before evaluation");
}
return m_checkpoints;
}
inline const AZStd::vector<Report>& Reporter::GetFailure() const
{
if (!m_isReportFinished)
{
AZ_Error("ScriptCanvas", false, "The report must be finished before evaluation");
}
return m_failures;
}
inline const ScriptCanvasId& Reporter::GetScriptCanvasId() const
{
return m_scriptCanvasId;
}
inline const AZStd::vector<Report>& Reporter::GetSuccess() const
{
if (!m_isReportFinished)
{
AZ_Error("ScriptCanvas", false, "The report must be finished before evaluation");
}
return m_successes;
}
inline bool Reporter::IsActivated() const
{
return m_graphIsActivated;
}
inline bool Reporter::IsComplete() const
{
return m_graphIsComplete;
}
inline bool Reporter::IsDeactivated() const
{
if (!m_isReportFinished)
{
AZ_Error("ScriptCanvas", false, "The report must be finished before evaluation");
}
return m_graphIsDeactivated;
}
inline bool Reporter::IsErrorFree() const
{
if (!m_isReportFinished)
{
AZ_Error("ScriptCanvas", false, "The report must be finished before evaluation");
}
return m_graphIsErrorFree;
}
inline bool Reporter::IsReportFinished() const
{
return m_isReportFinished;
}
inline void Reporter::FinishReport()
{
if (m_isReportFinished)
{
AZ_Error("ScriptCanvas", false, "The report is already finished");
}
m_isReportFinished = true;
}
inline void Reporter::FinishReport(const bool inErrorState)
{
if (m_isReportFinished)
{
AZ_Error("ScriptCanvas", false, "The report is already finished");
}
else
{
Bus::Handler::BusDisconnect(m_scriptCanvasId);
AZ::EntityBus::Handler::BusDisconnect(m_entityId);
m_graphIsErrorFree = !inErrorState;
m_isReportFinished = true;
}
}
inline bool Reporter::operator==(const Reporter& other) const
{
if (m_isReportFinished)
{
AZ_Error("ScriptCanvas", false, "The report is already finished");
}
return m_graphIsActivated == other.m_graphIsActivated
&& m_graphIsDeactivated == other.m_graphIsDeactivated
&& m_graphIsComplete == other.m_graphIsComplete
&& m_graphIsErrorFree == other.m_graphIsErrorFree
&& m_isReportFinished == other.m_isReportFinished
&& m_failures == other.m_failures
&& m_successes == other.m_successes;
}
inline void Reporter::OnEntityActivated(const AZ::EntityId& entity)
{
if (m_entityId != entity)
{
AZ_Error("ScriptCanvas", false, "This reporter is listening to the wrong entity");
}
if (m_isReportFinished)
{
return;
}
m_graphIsActivated = true;
}
inline void Reporter::OnEntityDeactivated(const AZ::EntityId& entity)
{
if (m_entityId != entity)
{
AZ_Error("ScriptCanvas", false, "This reporter is listening to the wrong entity");
}
if (m_isReportFinished)
{
return;
}
m_graphIsDeactivated = true;
}
inline void Reporter::Reset()
{
Bus::Handler::BusDisconnect();
AZ::EntityBus::Handler::BusDisconnect();
m_graphIsActivated = false;
m_graphIsComplete = false;
m_graphIsErrorFree = false;
m_isReportFinished = false;
m_scriptCanvasId = ScriptCanvasId{};
m_entityId = AZ::EntityId{};
m_failures.clear();
}
inline void Reporter::SetGraph(const ScriptCanvasId& scriptCanvasId, const AZ::EntityId& entityID)
{
Reset();
m_scriptCanvasId = scriptCanvasId;
m_entityId = entityID;
Bus::Handler::BusConnect(m_scriptCanvasId);
AZ::EntityBus::Handler::BusConnect(m_entityId);
}
// Handler
inline void Reporter::MarkComplete(const Report& report)
{
if (m_isReportFinished)
{
return;
}
if (!report.empty())
{
Checkpoint(AZStd::string::format("MarkComplete: %s", report.data()));
}
if (m_graphIsComplete)
{
AddFailure("MarkComplete was called twice!");
}
else
{
m_graphIsComplete = true;
}
}
inline void Reporter::AddFailure(const Report& report)
{
if (m_isReportFinished)
{
return;
}
m_failures.push_back(report);
Checkpoint(AZStd::string::format("AddFailure: %s", report.data()));
}
inline void Reporter::AddSuccess(const Report& report)
{
if (m_isReportFinished)
{
return;
}
m_successes.push_back(report);
if (!report.empty())
{
Checkpoint(AZStd::string::format("AddSuccess: %s", report.data()));
}
}
inline void Reporter::ExpectFalse(const bool value, const Report& report)
{
if (value)
{
AddFailure(AZStd::string::format("Error | Expected false.\n%s", report.data()));
}
if (!report.empty())
{
Checkpoint(AZStd::string::format("ExpectFalse: %s", report.data()));
}
}
inline void Reporter::ExpectTrue(const bool value, const Report& report)
{
if (!value)
{
AddFailure(AZStd::string::format("Error | Expected true.\n%s", report.data()));
}
if (!report.empty())
{
Checkpoint(AZStd::string::format("ExpectTrue: %s", report.data()));
}
}
inline void Reporter::ExpectEqualNumber(const Data::NumberType lhs, const Data::NumberType rhs, const Report& report)
{
if (!AZ::IsClose(lhs, rhs, 0.001))
{
AddFailure(AZStd::string::format("Error | Expected near value.\n%s", report.data()));
}
if (!report.empty())
{
Checkpoint(AZStd::string::format("ExpectEqualNumber: %s", report.data()));
}
}
inline void Reporter::ExpectNotEqualNumber(const Data::NumberType lhs, const Data::NumberType rhs, const Report& report)
{
SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_NE(lhs, rhs)
if (!report.empty())
{
Checkpoint(AZStd::string::format("ExpectNotEqualNumber: %s", report.data()));
}
}
SCRIPT_CANVAS_UNIT_TEST_EQUALITY_OVERLOAD_IMPLEMENTATIONS(Reporter, ExpectEqual, SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_EQ)
SCRIPT_CANVAS_UNIT_TEST_EQUALITY_OVERLOAD_IMPLEMENTATIONS(Reporter, ExpectNotEqual, SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_NE)
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_IMPLEMENTATIONS(Reporter, ExpectGreaterThan, SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_GT)
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_IMPLEMENTATIONS(Reporter, ExpectGreaterThanEqual, SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_GE)
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_IMPLEMENTATIONS(Reporter, ExpectLessThan, SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_LT)
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_IMPLEMENTATIONS(Reporter, ExpectLessThanEqual, SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_LE)
} // namespace ScriptCanvasEditor
@@ -0,0 +1,172 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/Entity.h>
#include <AzCore/Component/EntityId.h>
#include <AzCore/Debug/TraceMessageBus.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzFramework/Entity/EntityContextBus.h>
#include <AzFramework/Entity/SliceEntityOwnershipServiceBus.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Asset/RuntimeAssetHandler.h>
#include <ScriptCanvas/Core/Core.h>
#include <ScriptCanvas/Core/Graph.h>
#include <ScriptCanvas/Core/ScriptCanvasBus.h>
#include <ScriptCanvas/Data/Data.h>
#include <ScriptCanvas/Libraries/Comparison/Comparison.h>
#include <ScriptCanvas/Libraries/Core/BehaviorContextObjectNode.h>
#include <ScriptCanvas/Libraries/Core/BinaryOperator.h>
#include <ScriptCanvas/Libraries/Core/CoreNodes.h>
#include <ScriptCanvas/Libraries/Entity/EntityRef.h>
#include <ScriptCanvas/Libraries/Libraries.h>
#include <ScriptCanvas/Libraries/Logic/Logic.h>
#include <ScriptCanvas/Libraries/Math/Math.h>
#include <ScriptCanvas/Variable/VariableBus.h>
namespace ScriptCanvas
{
class RuntimeAsset;
class RuntimeComponent;
}
namespace ScriptCanvasEditor
{
struct LoadTestGraphResult
{
AZ::Data::Asset<ScriptCanvas::RuntimeAsset> m_asset;
AZStd::unique_ptr<AZ::Entity> m_graphEntity;
ScriptCanvas::RuntimeComponent* m_graph = nullptr;
};
// how long a unit test should be allowed to execute
enum class eDuration
{
Instant = 0, // kill the test as soon as control returns from the graph
MaxSecondsOrTicks, // wait for the test for as long as ticks or seconds remain
MinSecondsOrTicks, // wait for the test until either ticks or seconds are zero
Seconds, // wait for the specified amount of seconds, regardless of ticks
Ticks, // wait for the the specified amount of ticks, regardless of seconds
};
struct DurationSpec
{
eDuration m_spec = eDuration::Instant;
size_t m_ticks = 0;
float m_seconds = 0.0f;
};
class TraceSuppressionRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
virtual void SuppressPreAssert(bool suppress) = 0;
virtual void SuppressAssert(bool suppress) = 0;
virtual void SuppressException(bool suppress) = 0;
virtual void SuppressPreError(bool suppress) = 0;
virtual void SuppressError(bool suppress) = 0;
virtual void SuppressPreWarning(bool suppress) = 0;
virtual void SuppressWarning(bool suppress) = 0;
virtual void SuppressPrintf(bool suppress) = 0;
virtual void SuppressAllOutput(bool suppress) = 0;
};
using TraceSuppressionBus = AZ::EBus<TraceSuppressionRequests>;
class TraceMessageComponent
: public AZ::Component
, protected AZ::Debug::TraceMessageBus::Handler
, protected TraceSuppressionBus::Handler
{
public:
AZ_COMPONENT(TraceMessageComponent, "{E12144CE-809D-4056-9735-4384D7DBCCDC}");
TraceMessageComponent() = default;
~TraceMessageComponent() override = default;
void Activate() override
{
AZ::Debug::TraceMessageBus::Handler::BusConnect();
TraceSuppressionBus::Handler::BusConnect();
}
void Deactivate() override
{
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
TraceSuppressionBus::Handler::BusDisconnect();
}
private:
/// \ref ComponentDescriptor::Reflect
static void Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<TraceMessageComponent, AZ::Component>()
->Version(0)
;
}
}
bool OnPreAssert(const char*, int, const char*, const char*) { return suppressPreAssert; }
bool OnAssert(const char*) { return suppressAssert; }
bool OnException(const char*) { return suppressException; }
bool OnPreError(const char*, const char*, int, const char*, const char*) { return suppressPreError; }
bool OnError(const char*, const char*) { return suppressError; }
bool OnPreWarning(const char*, const char*, int, const char*, const char*) { return suppressPreWarning; }
bool OnWarning(const char*, const char*) { return suppressWarning; }
bool OnPrintf(const char*, const char*) { return suppressPrintf; }
bool OnOutput(const char*, const char*) { return suppressAllOutput; }
void SuppressPreAssert(bool suppress) override { suppressPreAssert = suppress; }
void SuppressAssert(bool suppress)override { suppressAssert = suppress; }
void SuppressException(bool suppress) override { suppressException = suppress; }
void SuppressPreError(bool suppress) override { suppressPreError = suppress; }
void SuppressError(bool suppress) override { suppressPreError = suppress; }
void SuppressPreWarning(bool suppress) override { suppressPreWarning = suppress; }
void SuppressWarning(bool suppress) override { suppressWarning = suppress; }
void SuppressPrintf(bool suppress) override { suppressPrintf = suppress; }
void SuppressAllOutput(bool suppress) override { suppressAllOutput = suppress; }
bool suppressPreAssert = false;
bool suppressAssert = false;
bool suppressException = false;
bool suppressPreError = false;
bool suppressError = false;
bool suppressPreWarning = false;
bool suppressWarning = false;
bool suppressPrintf = false;
bool suppressAllOutput = false;
};
struct ScopedOutputSuppression
{
ScopedOutputSuppression(bool suppressState = true)
{
AZ::Debug::TraceMessageBus::BroadcastResult(m_oldSuppression, &AZ::Debug::TraceMessageEvents::OnOutput, "", "");
TraceSuppressionBus::Broadcast(&TraceSuppressionRequests::SuppressAllOutput, suppressState);
}
~ScopedOutputSuppression()
{
TraceSuppressionBus::Broadcast(&TraceSuppressionRequests::SuppressAllOutput, m_oldSuppression);
}
private:
bool m_oldSuppression = false;
};
} // ScriptCanvasEditor
@@ -0,0 +1,119 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <ScriptCanvas/Core/Slot.h>
#include <Editor/GraphCanvas/Components/DynamicOrderingDynamicSlotComponent.h>
#include <Editor/Include/ScriptCanvas/GraphCanvas/MappingBus.h>
namespace ScriptCanvasEditor
{
////////////////////////////////////////
// DynamicOrderingDynamicSlotComponent
////////////////////////////////////////
void DynamicOrderingDynamicSlotComponent::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<DynamicOrderingDynamicSlotComponent, DynamicSlotComponent>()
->Version(0)
;
}
}
DynamicOrderingDynamicSlotComponent::DynamicOrderingDynamicSlotComponent()
: DynamicSlotComponent()
, m_deserialized(false)
{
}
DynamicOrderingDynamicSlotComponent::DynamicOrderingDynamicSlotComponent(GraphCanvas::SlotGroup slotGroup)
: DynamicSlotComponent(slotGroup)
, m_deserialized(false)
{
}
void DynamicOrderingDynamicSlotComponent::OnSystemTick()
{
if (GetScriptCanvasNodeId().IsValid())
{
SlotMappingRequests* requestInterface = SlotMappingRequestBus::FindFirstHandler(GetEntityId());
if (requestInterface)
{
AZStd::vector< const ScriptCanvas::Slot* > scriptSlots;
ScriptCanvas::NodeRequestBus::EventResult(scriptSlots, GetScriptCanvasNodeId(), &ScriptCanvas::NodeRequests::GetAllSlots);
for (int i = 0; i < scriptSlots.size(); ++i)
{
// Higher means it goes first. So we need to inverse our number.
int priority = static_cast<int>(scriptSlots.size()) - i;
ScriptCanvas::SlotId scriptCanvasSlotId = scriptSlots[i]->GetId();
GraphCanvas::SlotId graphCanvasSlotId = requestInterface->MapToGraphCanvasId(scriptCanvasSlotId);
if (graphCanvasSlotId.IsValid())
{
GraphCanvas::SlotRequestBus::Event(graphCanvasSlotId, &GraphCanvas::SlotRequests::SetLayoutPriority, priority);
}
}
}
}
AZ::SystemTickBus::Handler::BusDisconnect();
}
void DynamicOrderingDynamicSlotComponent::OnSceneSet(const AZ::EntityId& sceneId)
{
DynamicSlotComponent::OnSceneSet(sceneId);
if (m_deserialized)
{
AZ::SystemTickBus::Handler::BusConnect();
}
}
void DynamicOrderingDynamicSlotComponent::OnSceneMemberDeserialized(const AZ::EntityId& graphId, const GraphCanvas::GraphSerialization& serializationTarget)
{
DynamicSlotComponent::OnSceneMemberDeserialized(graphId, serializationTarget);
m_deserialized = true;
}
void DynamicOrderingDynamicSlotComponent::OnSlotsReordered()
{
DynamicSlotComponent::OnSlotsReordered();
AZ::SystemTickBus::Handler::BusConnect();
}
void DynamicOrderingDynamicSlotComponent::StopQueueSlotUpdates()
{
DynamicSlotComponent::StopQueueSlotUpdates();
if (GetScriptCanvasNodeId().IsValid())
{
OnSystemTick();
}
}
void DynamicOrderingDynamicSlotComponent::ConfigureGraphCanvasSlot([[maybe_unused]] const ScriptCanvas::Slot* slot, [[maybe_unused]] const GraphCanvas::SlotId& graphCanvasSlotId)
{
AZ::SystemTickBus::Handler::BusConnect();
}
}
@@ -0,0 +1,59 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Editor/GraphCanvas/Components/DynamicSlotComponent.h>
namespace ScriptCanvasEditor
{
// Should be used when the order of slots might be re-arranged at edit time.
// Will handle synchronizing and updating the various slots.
//
// Will do extra work, so should not be used all the time
class DynamicOrderingDynamicSlotComponent
: public DynamicSlotComponent
, public AZ::SystemTickBus::Handler
{
public:
AZ_COMPONENT(DynamicOrderingDynamicSlotComponent, "{90205620-E77B-4F09-8891-A0B1AE5E83EA}", DynamicSlotComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
DynamicOrderingDynamicSlotComponent();
DynamicOrderingDynamicSlotComponent(GraphCanvas::SlotGroup slotGroup);
~DynamicOrderingDynamicSlotComponent() override = default;
// AZ::SystemTickBus
void OnSystemTick() override;
////
// SceneMemberNotificationBus
void OnSceneSet(const AZ::EntityId& sceneId) override;
void OnSceneMemberDeserialized(const AZ::EntityId& graphId, const GraphCanvas::GraphSerialization& serializationTarget) override;
////
// NodeNotifications
void OnSlotsReordered() override;
////
// DynamicRequestBus
void StopQueueSlotUpdates() override;
////
protected:
void ConfigureGraphCanvasSlot(const ScriptCanvas::Slot* slot, const GraphCanvas::SlotId& graphCanvasSlotId) override;
private:
bool m_deserialized;
};
}
@@ -0,0 +1,213 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/any.h>
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
#include <Editor/GraphCanvas/Components/DynamicSlotComponent.h>
#include <Editor/Nodes/NodeUtils.h>
#include <Editor/Include/ScriptCanvas/GraphCanvas/MappingBus.h>
namespace ScriptCanvasEditor
{
/////////////////////////
// DynamicSlotComponent
/////////////////////////
void DynamicSlotComponent::Reflect(AZ::ReflectContext* reflectionContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectionContext);
if (serializeContext)
{
serializeContext->Class<DynamicSlotComponent, AZ::Component>()
->Version(1)
->Field("SlotGroup", &DynamicSlotComponent::m_slotGroup)
;
}
}
DynamicSlotComponent::DynamicSlotComponent()
: m_slotGroup(GraphCanvas::SlotGroups::Invalid)
, m_queueUpdates(false)
{
}
DynamicSlotComponent::DynamicSlotComponent(GraphCanvas::SlotGroup slotGroup)
: m_slotGroup(slotGroup)
, m_queueUpdates(false)
{
}
void DynamicSlotComponent::Init()
{
}
void DynamicSlotComponent::Activate()
{
GraphCanvas::SceneMemberNotificationBus::Handler::BusConnect(GetEntityId());
DynamicSlotRequestBus::Handler::BusConnect(GetEntityId());
}
void DynamicSlotComponent::Deactivate()
{
GraphCanvas::SceneMemberNotificationBus::Handler::BusDisconnect();
}
void DynamicSlotComponent::OnSceneSet(const AZ::EntityId&)
{
OnUserDataChanged();
GraphCanvas::SceneMemberNotificationBus::Handler::BusDisconnect();
}
void DynamicSlotComponent::OnSlotAdded(const ScriptCanvas::SlotId& slotId)
{
// For EBuses we need to be a little tricky. Since we are going to be pointing at a single node from
// multiple graph canvas nodes. So we want to convert the script canvas id into a graph canvas id
//
// Then check to see if we are the correct node for that particular event.
const AZ::EntityId* scriptCanvasNodeId = ScriptCanvas::NodeNotificationsBus::GetCurrentBusId();
if (scriptCanvasNodeId == nullptr)
{
return;
}
ScriptCanvas::Endpoint endpoint((*scriptCanvasNodeId), slotId);
if (m_queueUpdates)
{
m_queuedEndpoints.insert(endpoint);
return;
}
HandleSlotAdded(endpoint);
}
void DynamicSlotComponent::OnSlotRemoved(const ScriptCanvas::SlotId& slotId)
{
if (m_queueUpdates)
{
const AZ::EntityId* scriptCanvasNodeId = ScriptCanvas::NodeNotificationsBus::GetCurrentBusId();
if (scriptCanvasNodeId)
{
ScriptCanvas::Endpoint endpoint((*scriptCanvasNodeId), slotId);
m_queuedEndpoints.erase(endpoint);
}
}
AZStd::vector< AZ::EntityId > slotIds;
GraphCanvas::NodeRequestBus::EventResult(slotIds, GetEntityId(), &GraphCanvas::NodeRequests::GetSlotIds);
for (AZ::EntityId entityId : slotIds)
{
AZStd::any* userData = nullptr;
GraphCanvas::SlotRequestBus::EventResult(userData, entityId, &GraphCanvas::SlotRequests::GetUserData);
if (userData)
{
ScriptCanvas::SlotId* testId = AZStd::any_cast<ScriptCanvas::SlotId>(userData);
if (testId && (*testId) == slotId)
{
GraphCanvas::NodeRequestBus::Event(GetEntityId(), &GraphCanvas::NodeRequests::RemoveSlot, entityId);
}
}
}
}
void DynamicSlotComponent::OnUserDataChanged()
{
AZStd::any* userData = nullptr;
GraphCanvas::NodeRequestBus::EventResult(userData, GetEntityId(), &GraphCanvas::NodeRequests::GetUserData);
if (userData)
{
AZ::EntityId* entityId = AZStd::any_cast<AZ::EntityId>(userData);
if (entityId)
{
m_scriptCanvasNodeId = (*entityId);
ScriptCanvas::NodeNotificationsBus::Handler::BusDisconnect();
ScriptCanvas::NodeNotificationsBus::Handler::BusConnect(m_scriptCanvasNodeId);
}
}
}
void DynamicSlotComponent::StartQueueSlotUpdates()
{
if (!m_queueUpdates)
{
m_queueUpdates = true;
m_queuedEndpoints.clear();
}
}
void DynamicSlotComponent::StopQueueSlotUpdates()
{
if (m_queueUpdates)
{
m_queueUpdates = false;
for (auto endpoint : m_queuedEndpoints)
{
HandleSlotAdded(endpoint);
}
m_queuedEndpoints.clear();
}
}
void DynamicSlotComponent::ConfigureGraphCanvasSlot(const ScriptCanvas::Slot* slot, const GraphCanvas::SlotId& graphCanvasSlotId)
{
// By default no further configuration is necessary
AZ_UNUSED(slot);
AZ_UNUSED(graphCanvasSlotId);
}
void DynamicSlotComponent::HandleSlotAdded(const ScriptCanvas::Endpoint& endpoint)
{
AZ::EntityId graphCanvasNodeId;
SceneMemberMappingRequestBus::EventResult(graphCanvasNodeId, endpoint.GetNodeId(), &SceneMemberMappingRequests::GetGraphCanvasEntityId);
bool isEBusNode = false;
NodeDescriptorRequestBus::EventResult(isEBusNode, graphCanvasNodeId, &NodeDescriptorRequests::IsType, NodeDescriptorType::EBusHandler);
if (isEBusNode)
{
AZ::EntityId targetEventReceiverNode;
EBusHandlerNodeDescriptorRequestBus::EventResult(targetEventReceiverNode, graphCanvasNodeId, &EBusHandlerNodeDescriptorRequests::FindGraphCanvasNodeIdForSlot, endpoint.GetSlotId());
if (targetEventReceiverNode != GetEntityId())
{
return;
}
}
const ScriptCanvas::Slot* slot = nullptr;
ScriptCanvas::NodeRequestBus::EventResult(slot, endpoint.GetNodeId(), &ScriptCanvas::NodeRequests::GetSlot, endpoint.GetSlotId());
if (slot != nullptr)
{
AZ::EntityId graphCanvasSlotId = Nodes::DisplayScriptCanvasSlot(GetEntityId(), (*slot), m_slotGroup);
ConfigureGraphCanvasSlot(slot, graphCanvasSlotId);
}
}
}
@@ -0,0 +1,77 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/Component.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/SceneBus.h>
#include <ScriptCanvas/Core/Endpoint.h>
#include <ScriptCanvas/Core/NodeBus.h>
#include <ScriptCanvas/GraphCanvas/DynamicSlotBus.h>
namespace ScriptCanvasEditor
{
class DynamicSlotComponent
: public AZ::Component
, public GraphCanvas::SceneMemberNotificationBus::Handler
, public ScriptCanvas::NodeNotificationsBus::Handler
, public DynamicSlotRequestBus::Handler
{
public:
AZ_COMPONENT(DynamicSlotComponent, "{977152B6-1A7D-49A4-8E70-644AFAD1586A}");
static void Reflect(AZ::ReflectContext* serializeContext);
DynamicSlotComponent();
DynamicSlotComponent(GraphCanvas::SlotGroup slotGroup);
~DynamicSlotComponent() override = default;
// AZ::Component
void Init();
void Activate();
void Deactivate();
////
// GraphCanvas::SceneMemberNotificationBus
void OnSceneSet(const AZ::EntityId& sceneId) override;
////
// ScriptCanvas::EditorNodeNotificationBus
void OnSlotAdded(const ScriptCanvas::SlotId& slotId) override;
void OnSlotRemoved(const ScriptCanvas::SlotId& slotId) override;
////
// DynamicSlotRequestBus
void OnUserDataChanged() override;
void StartQueueSlotUpdates() override;
void StopQueueSlotUpdates() override;
////
protected:
virtual void ConfigureGraphCanvasSlot(const ScriptCanvas::Slot* slot, const GraphCanvas::SlotId& graphCanvasSlotId);
const AZ::EntityId& GetScriptCanvasNodeId() const { return m_scriptCanvasNodeId; }
private:
void HandleSlotAdded(const ScriptCanvas::Endpoint& endpoint);
GraphCanvas::SlotGroup m_slotGroup;
AZ::EntityId m_scriptCanvasNodeId;
bool m_queueUpdates;
AZStd::unordered_set<ScriptCanvas::Endpoint> m_queuedEndpoints;
};
}
@@ -0,0 +1,270 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/Slots/Data/DataSlotBus.h>
#include <GraphCanvas/Components/Nodes/Wrapper/WrapperNodeBus.h>
#include <Editor/GraphCanvas/Components/MappingComponent.h>
#include <Editor/Include/ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/Core/Slot.h>
#include <ScriptCanvas/Core/Node.h>
#include <ScriptCanvas/Variable/GraphVariable.h>
#include <ScriptCanvas/Variable/VariableBus.h>
#include <GraphCanvas/Components/Nodes/NodeTitleBus.h>
namespace ScriptCanvasEditor
{
////////////////////////////////
// SceneMemberMappingComponent
////////////////////////////////
void SceneMemberMappingComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<SceneMemberMappingComponent, AZ::Component>()
->Field("SourceId", &SceneMemberMappingComponent::m_sourceId)
->Version(1)
;
}
}
SceneMemberMappingComponent::SceneMemberMappingComponent(const AZ::EntityId& sourceId)
: m_sourceId(sourceId)
{
}
void SceneMemberMappingComponent::Activate()
{
GraphCanvas::NodeNotificationBus::Handler::BusConnect(GetEntityId());
SceneMemberMappingConfigurationRequestBus::Handler::BusConnect(GetEntityId());
ConfigureMapping(m_sourceId);
}
void SceneMemberMappingComponent::Deactivate()
{
SceneMemberMappingRequestBus::Handler::BusDisconnect();
SceneMemberMappingConfigurationRequestBus::Handler::BusDisconnect();
GraphCanvas::NodeNotificationBus::Handler::BusDisconnect();
}
void SceneMemberMappingComponent::ConfigureMapping(const AZ::EntityId& scriptCanvasMemberId)
{
if (m_sourceId.IsValid())
{
SceneMemberMappingRequestBus::Handler::BusDisconnect();
}
m_sourceId = scriptCanvasMemberId;
if (m_sourceId.IsValid())
{
SceneMemberMappingRequestBus::Handler::BusConnect(m_sourceId);
}
}
AZ::EntityId SceneMemberMappingComponent::GetGraphCanvasEntityId() const
{
return GetEntityId();
}
void SceneMemberMappingComponent::OnBatchedConnectionManipulationBegin()
{
ScriptCanvas::NodeRequestBus::Event(m_sourceId, &ScriptCanvas::NodeRequests::SignalBatchedConnectionManipulationBegin);
}
void SceneMemberMappingComponent::OnBatchedConnectionManipulationEnd()
{
ScriptCanvas::NodeRequestBus::Event(m_sourceId, &ScriptCanvas::NodeRequests::SignalBatchedConnectionManipulationEnd);
}
/////////////////////////
// SlotMappingComponent
/////////////////////////
void SlotMappingComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<SlotMappingComponent, AZ::Component>()
->Version(1)
->Field("SourceId", &SlotMappingComponent::m_sourceId)
;
}
}
SlotMappingComponent::SlotMappingComponent(const AZ::EntityId& sourceId)
: m_sourceId(sourceId)
{
}
void SlotMappingComponent::Activate()
{
m_slotMapping.clear();
GraphCanvas::NodeNotificationBus::Handler::BusConnect(GetEntityId());
SceneMemberMappingConfigurationRequestBus::Handler::BusConnect(GetEntityId());
ConfigureMapping(m_sourceId);
}
void SlotMappingComponent::Deactivate()
{
GraphCanvas::NodeNotificationBus::Handler::BusDisconnect();
SlotMappingRequestBus::MultiHandler::BusDisconnect();
}
void SlotMappingComponent::OnAddedToScene(const AZ::EntityId&)
{
AZStd::vector< AZ::EntityId > slotIds;
GraphCanvas::NodeRequestBus::EventResult(slotIds, GetEntityId(), &GraphCanvas::NodeRequests::GetSlotIds);
for (const AZ::EntityId& slotId : slotIds)
{
OnSlotAddedToNode(slotId);
}
SlotMappingRequestBus::MultiHandler::BusConnect(GetEntityId());
SlotMappingRequestBus::MultiHandler::BusConnect(m_sourceId);
}
void SlotMappingComponent::OnSlotAddedToNode(const AZ::EntityId& slotId)
{
AZStd::any* userData = nullptr;
GraphCanvas::SlotRequestBus::EventResult(userData, slotId, &GraphCanvas::SlotRequests::GetUserData);
AZStd::string displayTitle;
GraphCanvas::NodeTitleRequestBus::EventResult(displayTitle, GetEntityId(), &GraphCanvas::NodeTitleRequests::GetTitle);
if (userData && userData->is<ScriptCanvas::SlotId>())
{
m_slotMapping[(*AZStd::any_cast<ScriptCanvas::SlotId>(userData))] = slotId;
}
}
void SlotMappingComponent::OnSlotRemovedFromNode(const AZ::EntityId& slotId)
{
AZStd::any* userData = nullptr;
GraphCanvas::SlotRequestBus::EventResult(userData, slotId, &GraphCanvas::SlotRequests::GetUserData);
if (userData && userData->is<ScriptCanvas::SlotId>())
{
m_slotMapping.erase((*AZStd::any_cast<ScriptCanvas::SlotId>(userData)));
}
}
AZ::EntityId SlotMappingComponent::MapToGraphCanvasId(const ScriptCanvas::SlotId& slotId)
{
AZ::EntityId mappedId;
auto mapIter = m_slotMapping.find(slotId);
if (mapIter != m_slotMapping.end())
{
mappedId = mapIter->second;
}
else
{
if (GraphCanvas::GraphUtils::IsWrapperNode(GetEntityId()))
{
AZStd::vector< AZ::EntityId > wrappedNodes;
GraphCanvas::WrapperNodeRequestBus::EventResult(wrappedNodes, GetEntityId(), &GraphCanvas::WrapperNodeRequests::GetWrappedNodeIds);
for (const auto& wrappedId : wrappedNodes)
{
SlotMappingRequestBus::EventResult(mappedId, wrappedId, &SlotMappingRequests::MapToGraphCanvasId, slotId);
if (mappedId.IsValid())
{
break;
}
}
}
}
return mappedId;
}
void SlotMappingComponent::OnSlotRenamed(const ScriptCanvas::SlotId& slotId, AZStd::string_view newName)
{
AZ::EntityId graphCanvasSlotId = MapToGraphCanvasId(slotId);
if (graphCanvasSlotId.IsValid())
{
GraphCanvas::SlotRequestBus::Event(graphCanvasSlotId, &GraphCanvas::SlotRequests::SetName, newName);
}
}
void SlotMappingComponent::OnSlotDisplayTypeChanged(const ScriptCanvas::SlotId& slotId, const ScriptCanvas::Data::Type& slotType)
{
AZ::EntityId graphCanvasSlotId = MapToGraphCanvasId(slotId);
if (graphCanvasSlotId.IsValid())
{
GraphCanvas::DataValueType valueType = GraphCanvas::DataValueType::Primitive;
AZ::Uuid typeId = ScriptCanvas::Data::ToAZType(slotType);
if (ScriptCanvas::Data::IsContainerType(typeId))
{
valueType = GraphCanvas::DataValueType::Container;
}
else if (typeId.IsNull())
{
ScriptCanvas::Slot* slot = nullptr;
ScriptCanvas::NodeRequestBus::EventResult(slot, m_sourceId, &ScriptCanvas::NodeRequests::GetSlot, slotId);
if (slot && slot->IsDynamicSlot())
{
auto dynamicSlotType = slot->GetDynamicDataType();
if (dynamicSlotType == ScriptCanvas::DynamicDataType::Container)
{
valueType = GraphCanvas::DataValueType::Container;
}
}
}
GraphCanvas::DataSlotRequestBus::Event(graphCanvasSlotId, &GraphCanvas::DataSlotRequests::SetDataAndContainedTypeIds, typeId, ScriptCanvas::Data::GetContainedTypes(typeId), valueType);
}
}
void SlotMappingComponent::ConfigureMapping(const AZ::EntityId& scriptCanvasMemberId)
{
if (m_sourceId.IsValid())
{
ScriptCanvas::NodeNotificationsBus::Handler::BusDisconnect();
SlotMappingRequestBus::MultiHandler::BusDisconnect(m_sourceId);
}
m_sourceId = scriptCanvasMemberId;
if (m_sourceId.IsValid())
{
ScriptCanvas::NodeNotificationsBus::Handler::BusConnect(m_sourceId);
SlotMappingRequestBus::MultiHandler::BusConnect(m_sourceId);
}
}
}
@@ -0,0 +1,105 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/Component.h>
#include <AzCore/std/containers/unordered_map.h>
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <Editor/Include/ScriptCanvas/GraphCanvas/MappingBus.h>
#include <ScriptCanvas/Core/NodeBus.h>
namespace ScriptCanvasEditor
{
class SceneMemberMappingComponent
: public AZ::Component
, public SceneMemberMappingRequestBus::Handler
, public SceneMemberMappingConfigurationRequestBus::Handler
, public GraphCanvas::NodeNotificationBus::Handler
{
public:
AZ_COMPONENT(SceneMemberMappingComponent, "{145667DE-EBD6-4EC5-B630-7C9B1A5ACFF0}");
static void Reflect(AZ::ReflectContext* context);
SceneMemberMappingComponent() = default;
SceneMemberMappingComponent(const AZ::EntityId& sourceId);
~SceneMemberMappingComponent() = default;
void Activate();
void Deactivate();
// SceneMemberMappingConfigurationRequestBus
void ConfigureMapping(const AZ::EntityId& scriptCanvasMemberId) override;
////
// SceneMemberMappingRequestBus
AZ::EntityId GetGraphCanvasEntityId() const override;
////
// NodeNotificationBus
void OnBatchedConnectionManipulationBegin() override;
void OnBatchedConnectionManipulationEnd() override;
////
private:
AZ::EntityId m_sourceId;
};
class SlotMappingComponent
: public AZ::Component
, public GraphCanvas::NodeNotificationBus::Handler
, public SlotMappingRequestBus::MultiHandler
, public ScriptCanvas::NodeNotificationsBus::Handler
, public SceneMemberMappingConfigurationRequestBus::Handler
{
public:
AZ_COMPONENT(SlotMappingComponent, "{94DBC04C-964D-46A0-AD66-6A779FE4DC61}");
static void Reflect(AZ::ReflectContext* context);
SlotMappingComponent() = default;
SlotMappingComponent(const AZ::EntityId& sourceId);
~SlotMappingComponent() = default;
void Activate();
void Deactivate();
// GraphCanvas::NodeNotificationBus
void OnAddedToScene(const AZ::EntityId&) override;
void OnSlotAddedToNode(const AZ::EntityId& slotId) override;
void OnSlotRemovedFromNode(const AZ::EntityId& slotId) override;
////
// ScriptCanvasSlotRemappingBus
AZ::EntityId MapToGraphCanvasId(const ScriptCanvas::SlotId& slotId) override;
////
// ScriptCanvas::NodeNotificationBus::Handler
void OnSlotRenamed(const ScriptCanvas::SlotId& slotId, AZStd::string_view newName) override;
void OnSlotDisplayTypeChanged(const ScriptCanvas::SlotId& slotId, const ScriptCanvas::Data::Type& slotType) override;
////
// SceneMemberMappingConfigurationRequestBus
void ConfigureMapping(const AZ::EntityId& scriptCanvasMemberId) override;
////
private:
AZ::EntityId m_sourceId;
AZStd::unordered_map< ScriptCanvas::SlotId, AZ::EntityId > m_slotMapping;
AZStd::unordered_set< ScriptCanvas::SlotId > m_ignoreRenameSlots;
};
}
@@ -0,0 +1,40 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Serialization/SerializeContext.h>
#include "ClassMethodNodeDescriptorComponent.h"
namespace ScriptCanvasEditor
{
///////////////////////////////////////
// ClassMethodNodeDescriptorComponent
///////////////////////////////////////
void ClassMethodNodeDescriptorComponent::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<ClassMethodNodeDescriptorComponent, NodeDescriptorComponent>()
->Version(2)
;
}
}
ClassMethodNodeDescriptorComponent::ClassMethodNodeDescriptorComponent()
: NodeDescriptorComponent(NodeDescriptorType::ClassMethod)
{
}
}
@@ -0,0 +1,28 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include "Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h"
namespace ScriptCanvasEditor
{
class ClassMethodNodeDescriptorComponent
: public NodeDescriptorComponent
{
public:
AZ_COMPONENT(ClassMethodNodeDescriptorComponent, "{853F137F-C2E8-4D7D-8A1C-D99D167BD569}", NodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
ClassMethodNodeDescriptorComponent();
~ClassMethodNodeDescriptorComponent() = default;
};
}
@@ -0,0 +1,361 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/GeometryBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/EBusHandlerEventNodeDescriptorComponent.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/Core/NodeBus.h>
#include <ScriptCanvas/Core/EBusNodeBus.h>
#include <ScriptCanvas/Libraries/Core/EBusEventHandler.h>
#include <Editor/Nodes/NodeUtils.h>
#include <Editor/View/Widgets/NodePalette/EBusNodePaletteTreeItemTypes.h>
#include <Editor/Translation/TranslationHelper.h>
namespace ScriptCanvasEditor
{
////////////////////////////////////////////
// EBusHandlerEventNodeDescriptorComponent
////////////////////////////////////////////
static bool EBusHandlerEventNodeDescriptorComponentVersionConverter(AZ::SerializeContext& serializeContext, AZ::SerializeContext::DataElementNode& rootElement)
{
if (rootElement.GetVersion() <= 1)
{
auto element = rootElement.FindSubElement(AZ_CRC("EventName", 0x0287a22f));
AZStd::string eventName;
if (element->GetData(eventName))
{
AZ::Crc32 eventId = AZ::Crc32(eventName.c_str());
if (rootElement.AddElementWithData(serializeContext, "EventId", eventId) == -1)
{
return false;
}
}
}
return true;
}
void EBusHandlerEventNodeDescriptorComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<EBusHandlerEventNodeDescriptorComponent, NodeDescriptorComponent>()
->Version(2, EBusHandlerEventNodeDescriptorComponentVersionConverter)
->Field("BusName", &EBusHandlerEventNodeDescriptorComponent::m_busName)
->Field("EventName", &EBusHandlerEventNodeDescriptorComponent::m_eventName)
->Field("EventId", &EBusHandlerEventNodeDescriptorComponent::m_eventId)
;
}
}
EBusHandlerEventNodeDescriptorComponent::EBusHandlerEventNodeDescriptorComponent()
: NodeDescriptorComponent(NodeDescriptorType::EBusHandlerEvent)
{
}
EBusHandlerEventNodeDescriptorComponent::EBusHandlerEventNodeDescriptorComponent(const AZStd::string& busName, const AZStd::string& eventName, ScriptCanvas::EBusEventId eventId)
: NodeDescriptorComponent(NodeDescriptorType::EBusHandlerEvent)
, m_busName(busName)
, m_eventName(eventName)
, m_eventId(eventId)
{
}
void EBusHandlerEventNodeDescriptorComponent::Activate()
{
NodeDescriptorComponent::Activate();
EBusHandlerEventNodeDescriptorRequestBus::Handler::BusConnect(GetEntityId());
GraphCanvas::ForcedWrappedNodeRequestBus::Handler::BusConnect(GetEntityId());
GraphCanvas::SceneMemberNotificationBus::Handler::BusConnect(GetEntityId());
}
void EBusHandlerEventNodeDescriptorComponent::Deactivate()
{
NodeDescriptorComponent::Deactivate();
GraphCanvas::SceneMemberNotificationBus::Handler::BusDisconnect();
GraphCanvas::ForcedWrappedNodeRequestBus::Handler::BusDisconnect();
EBusHandlerEventNodeDescriptorRequestBus::Handler::BusDisconnect();
}
AZStd::string_view EBusHandlerEventNodeDescriptorComponent::GetBusName() const
{
return m_busName;
}
AZStd::string_view EBusHandlerEventNodeDescriptorComponent::GetEventName() const
{
return m_eventName;
}
ScriptCanvas::EBusEventId EBusHandlerEventNodeDescriptorComponent::GetEventId() const
{
return m_eventId;
}
void EBusHandlerEventNodeDescriptorComponent::SetHandlerAddress(const ScriptCanvas::Datum& idDatum)
{
if (m_ebusWrapper.m_scriptCanvasId.IsValid())
{
GraphCanvas::GraphId graphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
ScriptCanvas::ScriptCanvasId canvasId;
GeneralRequestBus::BroadcastResult(canvasId, &GeneralRequests::GetScriptCanvasId, graphId);
ScriptCanvas::GraphScopedNodeId scopedNodeId(canvasId, m_ebusWrapper.m_scriptCanvasId);
ScriptCanvas::EBusHandlerNodeRequestBus::Event(scopedNodeId, &ScriptCanvas::EBusHandlerNodeRequests::SetAddressId, AZStd::move(idDatum));
m_queuedId = AZStd::move(ScriptCanvas::Datum());
}
else
{
m_queuedId.DeepCopyDatum(idDatum);
}
}
void EBusHandlerEventNodeDescriptorComponent::OnNodeWrapped(const AZ::EntityId& wrappingNode)
{
bool isValid = false;
AZStd::any* userData = nullptr;
GraphCanvas::NodeRequestBus::EventResult(userData, wrappingNode, &GraphCanvas::NodeRequests::GetUserData);
if (userData && userData->is<AZ::EntityId>())
{
AZ_Warning("ScriptCanvas", !m_ebusWrapper.m_graphCanvasId.IsValid() && !m_ebusWrapper.m_scriptCanvasId.IsValid(), "Wrapping the same ebus event node twice without unwrapping it.");
AZ::EntityId scriptCanvasId = (*AZStd::any_cast<AZ::EntityId>(userData));
m_ebusWrapper.m_graphCanvasId = wrappingNode;
m_ebusWrapper.m_scriptCanvasId = scriptCanvasId;
AZ::Entity* entity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationBus::Events::FindEntity, scriptCanvasId);
AZStd::string ebusContextName = TranslationHelper::GetEbusHandlerContext(m_busName);
if (entity)
{
ScriptCanvas::Nodes::Core::EBusEventHandler* eventHandler = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::EBusEventHandler>(entity);
if (eventHandler)
{
AZStd::vector< AZ::EntityId > graphCanvasSlotIds;
GraphCanvas::NodeRequestBus::EventResult(graphCanvasSlotIds, GetEntityId(), &GraphCanvas::NodeRequests::GetSlotIds);
const ScriptCanvas::Nodes::Core::EBusEventHandler::EventMap& events = eventHandler->GetEvents();
ScriptCanvas::Nodes::Core::EBusEventEntry myEvent;
for (const auto& event : events)
{
if (event.second.m_eventName.compare(m_eventName) == 0)
{
myEvent = event.second;
break;
}
}
const int numEventSlots = 1;
const int numResultSlots = myEvent.m_resultSlotId.IsValid() ? 1 : 0;
const int totalSlots = (myEvent.m_numExpectedArguments + numEventSlots + numResultSlots);
// Potentially overly simplistic way of detecting if we need to refresh our Slot information.
if (totalSlots != graphCanvasSlotIds.size())
{
// Remove the previous slots
for (const auto& graphCanvasSlotId : graphCanvasSlotIds)
{
GraphCanvas::NodeRequestBus::Event(GetEntityId(), &GraphCanvas::NodeRequests::RemoveSlot, graphCanvasSlotId);
}
// Then from a clean slate, fully regenerate all of our slots.
ScriptCanvas::Slot* scriptCanvasSlot = eventHandler->GetSlot(myEvent.m_eventSlotId);
if (scriptCanvasSlot)
{
AZ::EntityId slotId = Nodes::DisplayScriptCanvasSlot(GetEntityId(), (*scriptCanvasSlot));
GraphCanvas::SlotRequestBus::Event(slotId, &GraphCanvas::SlotRequests::SetTranslationKeyedName, TranslationHelper::GetEBusHandlerOnEventTriggeredNameKey());
GraphCanvas::SlotRequestBus::Event(slotId, &GraphCanvas::SlotRequests::SetTranslationKeyedTooltip, TranslationHelper::GetEBusHandlerOnEventTriggeredTooltipKey());
}
//
// inputCount and outputCount work because the order of the slots is maintained from the BehaviorContext, if this changes
// in the future then we should consider storing the actual offset or key name at that time.
//
int inputCount = 0;
int outputCount = 0;
for (const auto& slotId : myEvent.m_parameterSlotIds)
{
scriptCanvasSlot = eventHandler->GetSlot(slotId);
if (scriptCanvasSlot)
{
AZ::EntityId graphCanvasSlotId = Nodes::DisplayScriptCanvasSlot(GetEntityId(), (*scriptCanvasSlot));
TranslationItemType itemType = TranslationHelper::GetItemType(scriptCanvasSlot->GetDescriptor());
GraphCanvas::TranslationKeyedString slotNameKeyedString(scriptCanvasSlot->GetName());
slotNameKeyedString.m_context = ebusContextName;
GraphCanvas::TranslationKeyedString slotTooltipKeyedString(scriptCanvasSlot->GetToolTip());
slotTooltipKeyedString.m_context = ebusContextName;
slotNameKeyedString.SetFallback(scriptCanvasSlot->GetName());
slotTooltipKeyedString.SetFallback(scriptCanvasSlot->GetToolTip());
if (scriptCanvasSlot->GetDescriptor() == ScriptCanvas::SlotDescriptors::DataOut())
{
slotNameKeyedString.m_key = TranslationHelper::GetEBusHandlerSlotKey(m_busName, m_eventName, itemType, TranslationKeyId::Name, outputCount);
slotTooltipKeyedString.m_key = TranslationHelper::GetEBusHandlerSlotKey(m_busName, m_eventName, itemType, TranslationKeyId::Tooltip, outputCount);
++outputCount;
}
else
{
slotNameKeyedString.m_key = TranslationHelper::GetEBusHandlerSlotKey(m_busName, m_eventName, itemType, TranslationKeyId::Name, inputCount);
slotTooltipKeyedString.m_key = TranslationHelper::GetEBusHandlerSlotKey(m_busName, m_eventName, itemType, TranslationKeyId::Tooltip, inputCount);
++inputCount;
}
GraphCanvas::SlotRequestBus::Event(graphCanvasSlotId, &GraphCanvas::SlotRequests::SetTranslationKeyedName, slotNameKeyedString);
GraphCanvas::SlotRequestBus::Event(graphCanvasSlotId, &GraphCanvas::SlotRequests::SetTranslationKeyedTooltip, slotTooltipKeyedString);
}
}
if (myEvent.m_resultSlotId.IsValid())
{
scriptCanvasSlot = eventHandler->GetSlot(myEvent.m_resultSlotId);
if (scriptCanvasSlot)
{
AZ::EntityId graphCanvasSlotId = Nodes::DisplayScriptCanvasSlot(GetEntityId(), (*scriptCanvasSlot));
TranslationItemType itemType = TranslationHelper::GetItemType(scriptCanvasSlot->GetDescriptor());
GraphCanvas::TranslationKeyedString slotNameKeyedString(scriptCanvasSlot->GetName(), ebusContextName);
slotNameKeyedString.m_key = slotNameKeyedString.m_key = TranslationHelper::GetKey(TranslationContextGroup::EbusHandler, m_busName, m_eventName, itemType, TranslationKeyId::Name);
GraphCanvas::TranslationKeyedString slotTooltipKeyedString(TranslationHelper::GetSafeTypeName(scriptCanvasSlot->GetDataType()), ebusContextName);
slotTooltipKeyedString.m_key = TranslationHelper::GetKey(TranslationContextGroup::EbusHandler, m_busName, m_eventName, itemType, TranslationKeyId::Tooltip);
GraphCanvas::SlotRequestBus::Event(graphCanvasSlotId, &GraphCanvas::SlotRequests::SetTranslationKeyedName, slotNameKeyedString);
GraphCanvas::SlotRequestBus::Event(graphCanvasSlotId, &GraphCanvas::SlotRequests::SetTranslationKeyedTooltip, slotTooltipKeyedString);
}
}
GraphCanvas::NodeRequestBus::EventResult(graphCanvasSlotIds, GetEntityId(), &GraphCanvas::NodeRequests::GetSlotIds);
}
isValid = (totalSlots == graphCanvasSlotIds.size());
}
if (m_queuedId.GetType().IsValid())
{
SetHandlerAddress(m_queuedId);
}
}
}
if (!isValid)
{
AZ::EntityId sceneId;
GraphCanvas::SceneMemberRequestBus::EventResult(sceneId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
if (sceneId.IsValid())
{
AZ_Error("GraphCanvas", false, "Failed to find valid configuration for EBusEventNode(%s::%s). Deleting Node", m_busName.c_str(), m_eventName.c_str());
AZStd::unordered_set<AZ::EntityId> deleteNodes;
deleteNodes.insert(GetEntityId());
GraphCanvas::SceneRequestBus::Event(sceneId, &GraphCanvas::SceneRequests::Delete, deleteNodes);
}
}
}
void EBusHandlerEventNodeDescriptorComponent::OnSceneMemberAboutToSerialize(GraphCanvas::GraphSerialization& sceneSerialization)
{
AZ::Entity* wrapperEntity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(wrapperEntity, &AZ::ComponentApplicationRequests::FindEntity, m_ebusWrapper.m_graphCanvasId);
if (wrapperEntity)
{
sceneSerialization.GetGraphData().m_nodes.insert(wrapperEntity);
}
}
AZ::Crc32 EBusHandlerEventNodeDescriptorComponent::GetWrapperType() const
{
return AZ::Crc32(m_busName.c_str());
}
AZ::Crc32 EBusHandlerEventNodeDescriptorComponent::GetIdentifier() const
{
return AZ::Crc32(m_eventName.c_str());
}
AZ::EntityId EBusHandlerEventNodeDescriptorComponent::CreateWrapperNode(const AZ::EntityId& sceneId, const AZ::Vector2& nodePosition)
{
CreateEBusHandlerMimeEvent createEbusMimeEvent(m_busName);
AZ::EntityId wrapperNode;
AZ::Vector2 dummyPosition = nodePosition;
if (createEbusMimeEvent.ExecuteEvent(nodePosition, dummyPosition, sceneId))
{
const NodeIdPair& nodePair = createEbusMimeEvent.GetCreatedPair();
wrapperNode = nodePair.m_graphCanvasId;
}
return wrapperNode;
}
void EBusHandlerEventNodeDescriptorComponent::OnAddedToGraphCanvasGraph(const GraphCanvas::GraphId&, const AZ::EntityId&)
{
AZStd::vector< AZ::EntityId > slotIds;
GraphCanvas::NodeRequestBus::EventResult(slotIds, GetEntityId(), &GraphCanvas::NodeRequests::GetSlotIds);
for (const auto& slotId : slotIds)
{
GraphCanvas::SlotType slotType;
GraphCanvas::SlotRequestBus::EventResult(slotType, slotId, &GraphCanvas::SlotRequests::GetSlotType);
if (slotType == GraphCanvas::SlotTypes::ExecutionSlot)
{
GraphCanvas::ConnectionType connectionType = GraphCanvas::ConnectionType::CT_None;
GraphCanvas::SlotRequestBus::EventResult(connectionType, slotId, &GraphCanvas::SlotRequests::GetConnectionType);
if (connectionType == GraphCanvas::ConnectionType::CT_Output)
{
GraphCanvas::SlotRequestBus::Event(slotId, &GraphCanvas::SlotRequests::SetTranslationKeyedName, TranslationHelper::GetEBusHandlerOnEventTriggeredNameKey());
GraphCanvas::SlotRequestBus::Event(slotId, &GraphCanvas::SlotRequests::SetTranslationKeyedTooltip, TranslationHelper::GetEBusHandlerOnEventTriggeredTooltipKey());
break;
}
}
}
}
}
@@ -0,0 +1,77 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include "Editor/Include/ScriptCanvas/Bus/NodeIdPair.h"
#include "Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h"
namespace ScriptCanvasEditor
{
class EBusHandlerEventNodeDescriptorComponent
: public NodeDescriptorComponent
, public EBusHandlerEventNodeDescriptorRequestBus::Handler
, public GraphCanvas::ForcedWrappedNodeRequestBus::Handler
, public GraphCanvas::SceneMemberNotificationBus::Handler
{
public:
AZ_COMPONENT(EBusHandlerEventNodeDescriptorComponent, "{F08F673C-0815-4CCA-AB9D-21965E9A14F2}", NodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
EBusHandlerEventNodeDescriptorComponent();
EBusHandlerEventNodeDescriptorComponent(const AZStd::string& busName, const AZStd::string& methodName, ScriptCanvas::EBusEventId eventId);
~EBusHandlerEventNodeDescriptorComponent() = default;
void Activate() override;
void Deactivate() override;
// EBusHandlerEventNodeDescriptorRequestBus
AZStd::string_view GetBusName() const override;
AZStd::string_view GetEventName() const override;
ScriptCanvas::EBusEventId GetEventId() const override;
void SetHandlerAddress(const ScriptCanvas::Datum& idDatum) override;
////
// NodeNotificationBus::Handler
void OnNodeWrapped(const AZ::EntityId& wrappingNode) override;
////
// SceneMemberNotifications
void OnSceneMemberAboutToSerialize(GraphCanvas::GraphSerialization& graphSerialization) override;
////
// ForcedWrappedNodeRequestBus
AZ::Crc32 GetWrapperType() const override;
AZ::Crc32 GetIdentifier() const override;
AZ::EntityId CreateWrapperNode(const AZ::EntityId& sceneId, const AZ::Vector2& nodePosition) override;
////
protected:
void OnAddedToGraphCanvasGraph(const GraphCanvas::GraphId& sceneId, const AZ::EntityId& scriptCanvasNodeId) override;
private:
NodeIdPair m_ebusWrapper;
AZStd::string m_busName;
AZStd::string m_eventName;
ScriptCanvas::EBusEventId m_eventId;
ScriptCanvas::Datum m_queuedId;
};
}
@@ -0,0 +1,605 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <qstring.h>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/Slots/Data/DataSlotBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/EBusHandlerNodeDescriptorComponent.h>
#include <ScriptCanvas/Libraries/Core/EBusEventHandler.h>
#include <ScriptCanvas/GraphCanvas/DynamicSlotBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/EBusHandlerEventNodeDescriptorComponent.h>
#include <Editor/GraphCanvas/PropertySlotIds.h>
#include <Editor/Translation/TranslationHelper.h>
#include <Editor/Nodes/NodeUtils.h>
#include <Editor/Include/ScriptCanvas/GraphCanvas/MappingBus.h>
#include <Editor/View/Widgets/PropertyGridBus.h>
#include <Editor/Include/ScriptCanvas/Bus/RequestBus.h>
namespace ScriptCanvasEditor
{
//////////////////////////////////////
// EBusHandlerNodeDescriptorSaveData
//////////////////////////////////////
bool EBusHandlerNodeDescriptorSaveDataVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
{
if (classElement.GetVersion() < 2)
{
AZStd::vector< AZStd::string > eventNames;
auto subElement = classElement.FindSubElement(AZ_CRC("EventNames", 0xb0dd75f0));
if (subElement)
{
if (!subElement->GetData(eventNames))
{
return false;
}
}
AZStd::vector< ScriptCanvas::EBusEventId > handlerEventIds;
handlerEventIds.reserve(eventNames.size());
for (const AZStd::string& eventName : eventNames)
{
handlerEventIds.emplace_back(eventName.c_str());
}
classElement.RemoveElementByName(AZ_CRC("EventNames", 0xb0dd75f0));
classElement.AddElementWithData(context, "EventIds", handlerEventIds);
}
return true;
}
EBusHandlerNodeDescriptorComponent::EBusHandlerNodeDescriptorSaveData::EBusHandlerNodeDescriptorSaveData()
: m_displayConnections(false)
, m_callback(nullptr)
{
}
EBusHandlerNodeDescriptorComponent::EBusHandlerNodeDescriptorSaveData::EBusHandlerNodeDescriptorSaveData(EBusHandlerNodeDescriptorComponent* component)
: m_displayConnections(false)
, m_callback(component)
{
}
void EBusHandlerNodeDescriptorComponent::EBusHandlerNodeDescriptorSaveData::operator=(const EBusHandlerNodeDescriptorSaveData& other)
{
// Purposefully skipping over the callback
m_displayConnections = other.m_displayConnections;
m_enabledEvents = other.m_enabledEvents;
}
void EBusHandlerNodeDescriptorComponent::EBusHandlerNodeDescriptorSaveData::OnDisplayConnectionsChanged()
{
if (m_callback)
{
m_callback->OnDisplayConnectionsChanged();
SignalDirty();
}
}
///////////////////////////////////////
// EBusHandlerNodeDescriptorComponent
///////////////////////////////////////
bool EBusHandlerDescriptorVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
{
if (classElement.GetVersion() <= 1)
{
AZ::Crc32 displayConnectionId = AZ_CRC("DisplayConnections", 0x710635cc);
EBusHandlerNodeDescriptorComponent::EBusHandlerNodeDescriptorSaveData saveData;
AZ::SerializeContext::DataElementNode* dataNode = classElement.FindSubElement(displayConnectionId);
if (dataNode)
{
dataNode->GetData(saveData.m_displayConnections);
}
classElement.RemoveElementByName(displayConnectionId);
classElement.RemoveElementByName(AZ_CRC("BusName", 0x1bbf25c5));
classElement.AddElementWithData(context, "SaveData", saveData);
}
return true;
}
void EBusHandlerNodeDescriptorComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<EBusHandlerNodeDescriptorSaveData, GraphCanvas::ComponentSaveData>()
->Version(2, &EBusHandlerNodeDescriptorSaveDataVersionConverter)
->Field("DisplayConnections", &EBusHandlerNodeDescriptorSaveData::m_displayConnections)
->Field("EventIds", &EBusHandlerNodeDescriptorSaveData::m_enabledEvents)
;
serializeContext->Class<EBusHandlerNodeDescriptorComponent, NodeDescriptorComponent>()
->Version(3, &EBusHandlerDescriptorVersionConverter)
->Field("SaveData", &EBusHandlerNodeDescriptorComponent::m_saveData)
->Field("BusName", &EBusHandlerNodeDescriptorComponent::m_busName)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<EBusHandlerNodeDescriptorSaveData>("SaveData", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "Properties")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &EBusHandlerNodeDescriptorSaveData::m_displayConnections, "Display Connection Controls", "Controls whether or not manual connection controls are visible for this node.")
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EBusHandlerNodeDescriptorSaveData::OnDisplayConnectionsChanged)
;
editContext->Class<EBusHandlerNodeDescriptorComponent>("Event Handler", "Configuration values for the EBus node.")
->ClassElement(AZ::Edit::ClassElements::EditorData, "Properties")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &EBusHandlerNodeDescriptorComponent::m_saveData, "SaveData", "The modifiable information about this comment.")
;
}
}
}
EBusHandlerNodeDescriptorComponent::EBusHandlerNodeDescriptorComponent()
: NodeDescriptorComponent(NodeDescriptorType::EBusHandler)
, m_saveData(this)
, m_loadingEvents(false)
{
}
EBusHandlerNodeDescriptorComponent::EBusHandlerNodeDescriptorComponent(const AZStd::string& busName)
: NodeDescriptorComponent(NodeDescriptorType::EBusHandler)
, m_saveData(this)
, m_busName(busName)
, m_loadingEvents(false)
{
}
void EBusHandlerNodeDescriptorComponent::Activate()
{
NodeDescriptorComponent::Activate();
EBusHandlerNodeDescriptorRequestBus::Handler::BusConnect(GetEntityId());
GraphCanvas::WrapperNodeNotificationBus::Handler::BusConnect(GetEntityId());
GraphCanvas::GraphCanvasPropertyBusHandler::OnActivate(GetEntityId());
GraphCanvas::WrapperNodeConfigurationRequestBus::Handler::BusConnect(GetEntityId());
GraphCanvas::EntitySaveDataRequestBus::Handler::BusConnect(GetEntityId());
GraphCanvas::SceneMemberNotificationBus::Handler::BusConnect(GetEntityId());
}
void EBusHandlerNodeDescriptorComponent::Deactivate()
{
NodeDescriptorComponent::Deactivate();
GraphCanvas::SceneMemberNotificationBus::Handler::BusDisconnect();
GraphCanvas::EntitySaveDataRequestBus::Handler::BusDisconnect();
GraphCanvas::WrapperNodeConfigurationRequestBus::Handler::BusDisconnect();
GraphCanvas::GraphCanvasPropertyBusHandler::OnDeactivate();
GraphCanvas::WrapperNodeNotificationBus::Handler::BusDisconnect();
EBusHandlerNodeDescriptorRequestBus::Handler::BusDisconnect();
}
void EBusHandlerNodeDescriptorComponent::OnNodeActivated()
{
GraphCanvas::WrapperNodeRequestBus::Event(GetEntityId(), &GraphCanvas::WrapperNodeRequests::SetWrapperType, AZ::Crc32(m_busName.c_str()));
}
void EBusHandlerNodeDescriptorComponent::OnMemberSetupComplete()
{
m_loadingEvents = true;
AZ::EntityId graphCanvasGraphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphCanvasGraphId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
AZStd::vector< HandlerEventConfiguration > eventConfigurations = GetEventConfigurations();
for (const ScriptCanvas::EBusEventId& eventId : m_saveData.m_enabledEvents)
{
if (m_eventTypeToId.find(eventId) == m_eventTypeToId.end())
{
AZStd::string eventName;
for (const HandlerEventConfiguration& testEventConfiguration : eventConfigurations)
{
if (testEventConfiguration.m_eventId == eventId)
{
eventName = testEventConfiguration.m_eventName;
}
}
AZ::EntityId internalNode = Nodes::DisplayEbusEventNode(graphCanvasGraphId, m_busName, eventName, eventId);
if (internalNode.IsValid())
{
GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::Add, internalNode);
GraphCanvas::WrappedNodeConfiguration configuration = GetEventConfiguration(eventId);
GraphCanvas::WrapperNodeRequestBus::Event(GetEntityId(), &GraphCanvas::WrapperNodeRequests::WrapNode, internalNode, configuration);
}
}
}
m_loadingEvents = false;
m_saveData.RegisterIds(GetEntityId(), graphCanvasGraphId);
}
void EBusHandlerNodeDescriptorComponent::OnSceneMemberDeserialized(const AZ::EntityId&, const GraphCanvas::GraphSerialization&)
{
m_saveData.m_enabledEvents.clear();
}
void EBusHandlerNodeDescriptorComponent::WriteSaveData(GraphCanvas::EntitySaveDataContainer& saveDataContainer) const
{
EBusHandlerNodeDescriptorSaveData* saveData = saveDataContainer.FindCreateSaveData<EBusHandlerNodeDescriptorSaveData>();
if (saveData)
{
(*saveData) = m_saveData;
}
}
void EBusHandlerNodeDescriptorComponent::ReadSaveData(const GraphCanvas::EntitySaveDataContainer& saveDataContainer)
{
const EBusHandlerNodeDescriptorSaveData* saveData = saveDataContainer.FindSaveDataAs<EBusHandlerNodeDescriptorSaveData>();
if (saveData)
{
m_saveData = (*saveData);
}
}
AZStd::string_view EBusHandlerNodeDescriptorComponent::GetBusName() const
{
return m_busName;
}
GraphCanvas::WrappedNodeConfiguration EBusHandlerNodeDescriptorComponent::GetEventConfiguration(const ScriptCanvas::EBusEventId& eventId) const
{
AZ_Warning("ScriptCanvas", m_scriptCanvasId.IsValid(), "Trying to query event list before the node is added to the scene.");
AZ::Entity* entity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationBus::Events::FindEntity, m_scriptCanvasId);
GraphCanvas::WrappedNodeConfiguration wrappedConfiguration;
if (entity)
{
ScriptCanvas::Nodes::Core::EBusEventHandler* eventHandler = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::EBusEventHandler>(entity);
if (eventHandler)
{
const ScriptCanvas::Nodes::Core::EBusEventHandler::EventMap& events = eventHandler->GetEvents();
AZ::u32 i = 0;
for (const auto& event : events)
{
if (event.second.m_eventId == eventId)
{
wrappedConfiguration.m_layoutOrder = i;
break;
}
++i;
}
}
}
return wrappedConfiguration;
}
bool EBusHandlerNodeDescriptorComponent::ContainsEvent(const ScriptCanvas::EBusEventId& eventId) const
{
return m_eventTypeToId.find(eventId) != m_eventTypeToId.end();
}
AZStd::vector< HandlerEventConfiguration > EBusHandlerNodeDescriptorComponent::GetEventConfigurations() const
{
AZ_Warning("ScriptCanvas", m_scriptCanvasId.IsValid(), "Trying to query event list before the node is added to the scene.");
AZStd::vector< HandlerEventConfiguration > eventConfigurations;
AZ::Entity* entity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationBus::Events::FindEntity, m_scriptCanvasId);
if (entity)
{
ScriptCanvas::Nodes::Core::EBusEventHandler* eventHandler = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::EBusEventHandler>(entity);
if (eventHandler)
{
const ScriptCanvas::Nodes::Core::EBusEventHandler::EventMap& events = eventHandler->GetEvents();
eventConfigurations.reserve(events.size());
for (const auto& eventEntry : events)
{
HandlerEventConfiguration configuration;
configuration.m_eventName = eventEntry.second.m_eventName;
configuration.m_eventId = eventEntry.second.m_eventId;
eventConfigurations.emplace_back(configuration);
}
}
}
return eventConfigurations;
}
AZ::EntityId EBusHandlerNodeDescriptorComponent::FindEventNodeId(const ScriptCanvas::EBusEventId& eventId) const
{
AZ::EntityId retVal;
auto iter = m_eventTypeToId.find(eventId);
if (iter != m_eventTypeToId.end())
{
retVal = iter->second;
}
return retVal;
}
AZ::EntityId EBusHandlerNodeDescriptorComponent::FindGraphCanvasNodeIdForSlot(const ScriptCanvas::SlotId& slotId) const
{
ScriptCanvas::Nodes::Core::EBusEventHandler* eventHandler = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::EBusEventHandler>(m_scriptCanvasId);
if (eventHandler)
{
auto nonEventSlotIds = eventHandler->GetNonEventSlotIds();
bool isNonEventSlot = (AZStd::find(nonEventSlotIds.begin(), nonEventSlotIds.end(), slotId) != nonEventSlotIds.end());
if (isNonEventSlot)
{
return GetEntityId();
}
auto scriptEvents = eventHandler->GetEvents();
ScriptCanvas::EBusEventId foundEventId = ScriptCanvas::EBusEventId();
for (auto scriptEventPair : scriptEvents)
{
const auto& scriptEvent = scriptEventPair.second;
bool foundResult = scriptEvent.m_eventSlotId == slotId;
foundResult = foundResult || scriptEvent.m_resultSlotId == slotId;
foundResult = foundResult || (AZStd::find(scriptEvent.m_parameterSlotIds.begin(), scriptEvent.m_parameterSlotIds.end(), slotId) != nonEventSlotIds.end());
if (foundResult)
{
foundEventId = scriptEventPair.first;
break;
}
}
if (foundEventId != ScriptCanvas::EBusEventId())
{
return FindEventNodeId(foundEventId);
}
}
return AZ::EntityId();
}
GraphCanvas::Endpoint EBusHandlerNodeDescriptorComponent::MapSlotToGraphCanvasEndpoint(const ScriptCanvas::SlotId& scriptCanvasSlotId) const
{
GraphCanvas::Endpoint endpoint;
AZ::EntityId graphCanvasSlotId;
SlotMappingRequestBus::EventResult(graphCanvasSlotId, GetEntityId(), &SlotMappingRequests::MapToGraphCanvasId, scriptCanvasSlotId);
if (!graphCanvasSlotId.IsValid())
{
for (auto& mapPair : m_eventTypeToId)
{
SlotMappingRequestBus::EventResult(graphCanvasSlotId, mapPair.second, &SlotMappingRequests::MapToGraphCanvasId, scriptCanvasSlotId);
if (graphCanvasSlotId.IsValid())
{
endpoint = GraphCanvas::Endpoint(mapPair.second, graphCanvasSlotId);
break;
}
}
}
else
{
endpoint = GraphCanvas::Endpoint(GetEntityId(), graphCanvasSlotId);
}
return endpoint;
}
void EBusHandlerNodeDescriptorComponent::OnWrappedNode(const AZ::EntityId& wrappedNode)
{
ScriptCanvas::EBusEventId eventId;
EBusHandlerEventNodeDescriptorRequestBus::EventResult(eventId, wrappedNode, &EBusHandlerEventNodeDescriptorRequests::GetEventId);
if (eventId == ScriptCanvas::EBusEventId())
{
AZ_Warning("ScriptCanvas", false, "Trying to wrap an event node without an event name being specified.");
return;
}
auto emplaceResult = m_eventTypeToId.emplace(eventId, wrappedNode);
if (emplaceResult.second)
{
m_idToEventType.emplace(wrappedNode, eventId);
AZStd::any* userData = nullptr;
GraphCanvas::NodeRequestBus::EventResult(userData, wrappedNode, &GraphCanvas::NodeRequests::GetUserData);
if (userData)
{
(*userData) = m_scriptCanvasId;
DynamicSlotRequestBus::Event(wrappedNode, &DynamicSlotRequests::OnUserDataChanged);
GraphCanvas::NodeDataSlotRequestBus::Event(wrappedNode, &GraphCanvas::NodeDataSlotRequests::RecreatePropertyDisplay);
}
if (!m_loadingEvents)
{
m_saveData.m_enabledEvents.emplace_back(eventId);
m_saveData.SignalDirty();
}
}
// If we are wrapping the same node twice for just ignore it and log a message
else if (emplaceResult.first->second != wrappedNode)
{
AZ_Error("ScriptCanvas", false, "Trying to wrap two identically named methods under the same EBus Handler. Deleting the second node.");
AZ::EntityId sceneId;
GraphCanvas::SceneMemberRequestBus::EventResult(sceneId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
AZStd::unordered_set<AZ::EntityId> deleteNodes;
deleteNodes.insert(wrappedNode);
GraphCanvas::SceneRequestBus::Event(sceneId, &GraphCanvas::SceneRequests::Delete, deleteNodes);
}
else
{
AZ_Warning("ScriptCanvas", false, "Trying to wrap the same node twice.");
}
}
void EBusHandlerNodeDescriptorComponent::OnUnwrappedNode(const AZ::EntityId& unwrappedNode)
{
auto iter = m_idToEventType.find(unwrappedNode);
if (iter != m_idToEventType.end())
{
ScriptCanvas::EBusEventId eventId = iter->second;
m_eventTypeToId.erase(eventId);
m_idToEventType.erase(iter);
for (auto eventIter = m_saveData.m_enabledEvents.begin(); eventIter != m_saveData.m_enabledEvents.end(); ++eventIter)
{
if ((*eventIter) == eventId)
{
m_saveData.m_enabledEvents.erase(eventIter);
m_saveData.SignalDirty();
break;
}
}
}
}
GraphCanvas::WrappedNodeConfiguration EBusHandlerNodeDescriptorComponent::GetWrappedNodeConfiguration(const AZ::EntityId& wrappedNodeId) const
{
ScriptCanvas::EBusEventId eventId;
EBusHandlerEventNodeDescriptorRequestBus::EventResult(eventId, wrappedNodeId, &EBusHandlerEventNodeDescriptorRequests::GetEventId);
return GetEventConfiguration(eventId);
}
AZ::Component* EBusHandlerNodeDescriptorComponent::GetPropertyComponent()
{
return this;
}
void EBusHandlerNodeDescriptorComponent::OnAddedToGraphCanvasGraph([[maybe_unused]] const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId)
{
m_scriptCanvasId = scriptCanvasNodeId;
GraphCanvas::WrapperNodeRequestBus::Event(GetEntityId(), &GraphCanvas::WrapperNodeRequests::SetActionString, "Add/Remove Events");
GraphCanvas::SlotLayoutRequestBus::Event(GetEntityId(), &GraphCanvas::SlotLayoutRequests::SetSlotGroupVisible, SlotGroups::EBusConnectionSlotGroup, m_saveData.m_displayConnections);
if (m_scriptCanvasId.IsValid())
{
AZ::Entity* entity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, m_scriptCanvasId);
if (entity)
{
ScriptCanvas::Nodes::Core::EBusEventHandler* eventHandler = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::EBusEventHandler>(entity);
if (eventHandler && eventHandler->IsIDRequired())
{
AZStd::vector< AZ::EntityId > slotIds;
GraphCanvas::NodeRequestBus::EventResult(slotIds, GetEntityId(), &GraphCanvas::NodeRequests::GetSlotIds);
// Should be exactly one data slot on ourselves. And that is the BusId
for (const AZ::EntityId& testSlotId : slotIds)
{
GraphCanvas::SlotType slotType;
GraphCanvas::SlotRequestBus::EventResult(slotType, testSlotId, &GraphCanvas::SlotRequests::GetSlotType);
if (slotType == GraphCanvas::SlotTypes::DataSlot)
{
GraphCanvas::SlotRequestBus::Event(testSlotId, &GraphCanvas::SlotRequests::SetTranslationKeyedName, TranslationHelper::GetEBusHandlerBusIdNameKey());
GraphCanvas::SlotRequestBus::Event(testSlotId, &GraphCanvas::SlotRequests::SetTranslationKeyedTooltip, TranslationHelper::GetEBusHandlerBusIdTooltipKey());
break;
}
}
}
}
}
}
void EBusHandlerNodeDescriptorComponent::OnDisplayConnectionsChanged()
{
// If we are hiding the connections, we need to confirm that
// everything will be ok(i.e. no active connections)
if (!m_saveData.m_displayConnections)
{
AZ::Entity* entity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationBus::Events::FindEntity, m_scriptCanvasId);
if (entity)
{
ScriptCanvas::Nodes::Core::EBusEventHandler* eventHandler = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::EBusEventHandler>(entity);
if (eventHandler)
{
AZStd::vector< ScriptCanvas::SlotId > scriptCanvasSlots = eventHandler->GetNonEventSlotIds();
bool allowChange = true;
for (const auto& slotId : scriptCanvasSlots)
{
ScriptCanvas::Slot* slot = eventHandler->GetSlot(slotId);
if (slot->IsExecution() && eventHandler->IsConnected((*slot)))
{
allowChange = false;
break;
}
}
if (!allowChange)
{
AZ_Warning("Script Canvas", false, "Cannot hide EBus Connection Controls because one ore more slots are currently connected. Please disconnect all slots to hide.");
m_saveData.m_displayConnections = true;
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
// If we are displaying the connection options, do not auto connect the graph as it's expected
// that the user will manage it.
eventHandler->SetAutoConnectToGraphOwner(!m_saveData.m_displayConnections);
}
}
}
GraphCanvas::SlotLayoutRequestBus::Event(GetEntityId(), &GraphCanvas::SlotLayoutRequests::SetSlotGroupVisible, SlotGroups::EBusConnectionSlotGroup, m_saveData.m_displayConnections);
}
}
@@ -0,0 +1,128 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <GraphCanvas/Components/Nodes/Wrapper/WrapperNodeBus.h>
#include <GraphCanvas/Components/GraphCanvasPropertyBus.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/EntitySaveDataBus.h>
#include <GraphCanvas/Types/EntitySaveData.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h>
namespace ScriptCanvasEditor
{
class EBusHandlerNodeDescriptorComponent
: public NodeDescriptorComponent
, public EBusHandlerNodeDescriptorRequestBus::Handler
, public GraphCanvas::WrapperNodeNotificationBus::Handler
, public GraphCanvas::GraphCanvasPropertyBusHandler
, public GraphCanvas::WrapperNodeConfigurationRequestBus::Handler
, public GraphCanvas::EntitySaveDataRequestBus::Handler
, public GraphCanvas::SceneMemberNotificationBus::Handler
{
public:
class EBusHandlerNodeDescriptorSaveData
: public GraphCanvas::ComponentSaveData
{
public:
AZ_RTTI(EBusHandlerNodeDescriptorSaveData, "{9E81C95F-89C0-4476-8E82-63CCC4E52E04}", GraphCanvas::ComponentSaveData);
AZ_CLASS_ALLOCATOR(EBusHandlerNodeDescriptorSaveData, AZ::SystemAllocator, 0);
EBusHandlerNodeDescriptorSaveData();
EBusHandlerNodeDescriptorSaveData(EBusHandlerNodeDescriptorComponent* component);
~EBusHandlerNodeDescriptorSaveData() = default;
void operator=(const EBusHandlerNodeDescriptorSaveData& other);
void OnDisplayConnectionsChanged();
bool m_displayConnections;
AZStd::vector< ScriptCanvas::EBusEventId > m_enabledEvents;
private:
EBusHandlerNodeDescriptorComponent* m_callback;
};
friend class EBusHandlerNodeDescriptorSaveData;
AZ_COMPONENT(EBusHandlerNodeDescriptorComponent, "{A93B4B22-DBB8-4F18-B741-EB041BFEA4F6}", NodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
EBusHandlerNodeDescriptorComponent();
EBusHandlerNodeDescriptorComponent(const AZStd::string& busName);
~EBusHandlerNodeDescriptorComponent() = default;
void Activate() override;
void Deactivate() override;
// NodeNotifications
void OnNodeActivated() override;
////
// SceneMemberNotifications
void OnMemberSetupComplete() override;
void OnSceneMemberDeserialized(const AZ::EntityId& graphId, const GraphCanvas::GraphSerialization&) override;
////
// GraphCanvas::EntitySaveDataRequestBus::Handler
void WriteSaveData(GraphCanvas::EntitySaveDataContainer& saveDataContainer) const override;
void ReadSaveData(const GraphCanvas::EntitySaveDataContainer& saveDataContainer) override;
////
// EBusNodeDescriptorRequestBus
AZStd::string_view GetBusName() const override;
bool ContainsEvent(const ScriptCanvas::EBusEventId& eventId) const override;
GraphCanvas::WrappedNodeConfiguration GetEventConfiguration(const ScriptCanvas::EBusEventId& eventName) const override;
AZStd::vector< HandlerEventConfiguration > GetEventConfigurations() const override;
AZ::EntityId FindEventNodeId(const ScriptCanvas::EBusEventId& eventId) const override;
AZ::EntityId FindGraphCanvasNodeIdForSlot(const ScriptCanvas::SlotId& eventName) const override;
GraphCanvas::Endpoint MapSlotToGraphCanvasEndpoint(const ScriptCanvas::SlotId& eventName) const override;
////
// WrapperNodeNotificationBus
void OnWrappedNode(const AZ::EntityId& wrappedNode) override;
void OnUnwrappedNode(const AZ::EntityId& unwrappedNode) override;
////
// WrapperNodeConfigurationRequests
GraphCanvas::WrappedNodeConfiguration GetWrappedNodeConfiguration(const AZ::EntityId& wrappedNodeId) const override;
////
// GraphCanvasPropertyBus
AZ::Component* GetPropertyComponent() override;
////
protected:
void OnAddedToGraphCanvasGraph(const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId);
private:
void OnDisplayConnectionsChanged();
EBusHandlerNodeDescriptorSaveData m_saveData;
AZStd::string m_busName;
bool m_loadingEvents;
AZ::EntityId m_scriptCanvasId;
AZStd::unordered_map< ScriptCanvas::EBusEventId, AZ::EntityId > m_eventTypeToId;
AZStd::unordered_map< AZ::EntityId, ScriptCanvas::EBusEventId > m_idToEventType;
};
}
@@ -0,0 +1,87 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include "EBusSenderNodeDescriptorComponent.h"
#include "Editor/Translation/TranslationHelper.h"
#include "ScriptCanvas/Libraries/Core/Method.h"
namespace ScriptCanvasEditor
{
//////////////////////////////////////
// EBusSenderNodeDescriptorComponent
//////////////////////////////////////
void EBusSenderNodeDescriptorComponent::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<EBusSenderNodeDescriptorComponent, NodeDescriptorComponent>()
->Version(2)
;
}
}
EBusSenderNodeDescriptorComponent::EBusSenderNodeDescriptorComponent()
: NodeDescriptorComponent(NodeDescriptorType::EBusSender)
{
}
void EBusSenderNodeDescriptorComponent::OnAddedToGraphCanvasGraph([[maybe_unused]] const GraphCanvas::GraphId& sceneId, const AZ::EntityId& scriptCanvasNodeId)
{
AZ::Entity* entity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasNodeId);
if (entity)
{
ScriptCanvas::Nodes::Core::Method* method = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::Method>(entity);
if (method)
{
if (method->HasBusID())
{
ScriptCanvas::SlotId slotId = method->GetBusSlotId();
AZStd::vector< AZ::EntityId > graphCanvasSlots;
GraphCanvas::NodeRequestBus::EventResult(graphCanvasSlots, GetEntityId(), &GraphCanvas::NodeRequests::GetSlotIds);
for (const AZ::EntityId& graphCanvasId : graphCanvasSlots)
{
AZStd::any* slotData = nullptr;
GraphCanvas::SlotRequestBus::EventResult(slotData, graphCanvasId, &GraphCanvas::SlotRequests::GetUserData);
if (slotData
&& slotData->is< ScriptCanvas::SlotId >())
{
ScriptCanvas::SlotId currentSlotId = (*AZStd::any_cast<ScriptCanvas::SlotId>(slotData));
if (currentSlotId == slotId)
{
GraphCanvas::SlotRequestBus::Event(graphCanvasId, &GraphCanvas::SlotRequests::SetTranslationKeyedName, TranslationHelper::GetEBusSenderBusIdNameKey());
GraphCanvas::SlotRequestBus::Event(graphCanvasId, &GraphCanvas::SlotRequests::SetTranslationKeyedTooltip, TranslationHelper::GetEBusSenderBusIdTooltipKey());
break;
}
}
}
}
}
}
}
}
@@ -0,0 +1,33 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include "Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h"
namespace ScriptCanvasEditor
{
class EBusSenderNodeDescriptorComponent
: public NodeDescriptorComponent
{
public:
AZ_COMPONENT(EBusSenderNodeDescriptorComponent, "{6B646A3A-CB7F-49C4-8146-D848F418E0B1}", NodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
EBusSenderNodeDescriptorComponent();
~EBusSenderNodeDescriptorComponent() = default;
protected:
void OnAddedToGraphCanvasGraph(const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId) override;
};
}
@@ -0,0 +1,131 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <GraphCanvas/Components/Nodes/NodeTitleBus.h>
#include "EntityRefNodeDescriptorComponent.h"
#include "ScriptCanvas/Core/Datum.h"
#include "ScriptCanvas/Core/PureData.h"
#include "ScriptCanvas/Core/Slot.h"
namespace ScriptCanvasEditor
{
/////////////////////////////////////
// EntityRefNodeDescriptorComponent
/////////////////////////////////////
void EntityRefNodeDescriptorComponent::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<EntityRefNodeDescriptorComponent, NodeDescriptorComponent>()
->Version(1)
;
}
}
EntityRefNodeDescriptorComponent::EntityRefNodeDescriptorComponent()
: NodeDescriptorComponent(NodeDescriptorType::EntityRef)
{
}
void EntityRefNodeDescriptorComponent::OnEntityNameChanged([[maybe_unused]] const AZStd::string& name)
{
UpdateNodeTitle();
}
void EntityRefNodeDescriptorComponent::OnInputChanged(const ScriptCanvas::SlotId& slotId)
{
if (slotId == m_endpoint.GetSlotId())
{
AZ::EntityBus::Handler::BusDisconnect();
AZ::EntityId referencedId = GetReferencedEntityId();
if (referencedId.IsValid())
{
AZ::EntityBus::Handler::BusConnect(referencedId);
}
UpdateNodeTitle();
}
}
void EntityRefNodeDescriptorComponent::OnAddedToGraphCanvasGraph([[maybe_unused]] const GraphCanvas::GraphId& sceneId, const AZ::EntityId& scriptCanvasNodeId)
{
ScriptCanvas::SlotId scriptCanvasSlotId;
ScriptCanvas::NodeRequestBus::EventResult(scriptCanvasSlotId, scriptCanvasNodeId, &ScriptCanvas::NodeRequests::GetSlotId, ScriptCanvas::PureData::k_setThis);
m_endpoint = ScriptCanvas::Endpoint(scriptCanvasNodeId, scriptCanvasSlotId);
if (m_endpoint.IsValid())
{
AZ::EntityId referencedId = GetReferencedEntityId();
if (referencedId.IsValid())
{
AZ::EntityBus::Handler::BusConnect(referencedId);
}
}
UpdateNodeTitle();
}
AZ::EntityId EntityRefNodeDescriptorComponent::GetReferencedEntityId() const
{
AZ::EntityId retVal;
const ScriptCanvas::Datum* object = nullptr;
ScriptCanvas::NodeRequestBus::EventResult(object, m_endpoint.GetNodeId(), &ScriptCanvas::NodeRequests::FindDatum, m_endpoint.GetSlotId());
if (object && object->IS_A<AZ::EntityId>())
{
retVal = (*object->GetAs<AZ::EntityId>());
}
return retVal;
}
void EntityRefNodeDescriptorComponent::UpdateNodeTitle()
{
bool needsTitle = true;
if (m_endpoint.IsValid())
{
AZ::EntityId referencedId = GetReferencedEntityId();
AZStd::string entityName;
AZ::ComponentApplicationBus::BroadcastResult(entityName, &AZ::ComponentApplicationRequests::GetEntityName, referencedId);
if (!entityName.empty())
{
needsTitle = false;
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetTitle, entityName.c_str());
}
else if (referencedId.IsValid())
{
needsTitle = false;
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetTitle, referencedId.ToString().c_str());
}
}
if (needsTitle)
{
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetTitle, "<None>");
}
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetSubTitle, "EntityRef");
}
}
@@ -0,0 +1,53 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <AzCore/Component/EntityBus.h>
#include "Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h"
#include "ScriptCanvas/Core/NodeBus.h"
#include "ScriptCanvas/Core/Endpoint.h"
namespace ScriptCanvasEditor
{
class EntityRefNodeDescriptorComponent
: public NodeDescriptorComponent
, public AZ::EntityBus::Handler
{
public:
AZ_COMPONENT(EntityRefNodeDescriptorComponent, "{887AE9AC-C793-4FE5-BAE2-AF6A7F70A374}", NodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
EntityRefNodeDescriptorComponent();
~EntityRefNodeDescriptorComponent() = default;
// AZ::EntityBus
void OnEntityNameChanged(const AZStd::string& name) override;
////
// ScriptCanvas::NodeNotificationsBus
void OnInputChanged(const ScriptCanvas::SlotId& slotId) override;
////
private:
void OnAddedToGraphCanvasGraph(const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId) override;
AZ::EntityId GetReferencedEntityId() const;
void UpdateNodeTitle();
ScriptCanvas::Endpoint m_endpoint;
};
}
@@ -0,0 +1,132 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include "FunctionNodeDescriptorComponent.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/Nodes/NodeTitleBus.h>
#include <Editor/Assets/ScriptCanvasAssetHelpers.h>
#include <Editor/Translation/TranslationHelper.h>
#include <Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/Libraries/Core/ScriptEventBase.h>
#include <ScriptCanvas/Libraries/Core/FunctionNode.h>
namespace ScriptCanvasEditor
{
/////////////////////////////////////////////
// FunctionNodeDescriptorComponent
/////////////////////////////////////////////
void FunctionNodeDescriptorComponent::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<FunctionNodeDescriptorComponent, NodeDescriptorComponent>()
->Version(1)
->Field("AssetId", &FunctionNodeDescriptorComponent::m_assetId)
;
}
}
FunctionNodeDescriptorComponent::FunctionNodeDescriptorComponent()
: NodeDescriptorComponent(NodeDescriptorType::FunctionNode)
{
}
FunctionNodeDescriptorComponent::FunctionNodeDescriptorComponent(const AZ::Data::AssetId& assetId, const AZStd::string& name)
: NodeDescriptorComponent(NodeDescriptorType::FunctionNode)
, m_assetId(assetId)
, m_name(name)
{
}
void FunctionNodeDescriptorComponent::Activate()
{
NodeDescriptorComponent::Activate();
GraphCanvas::VisualNotificationBus::Handler::BusConnect(GetEntityId());
AZ::Data::AssetBus::Handler::BusConnect(m_assetId);
}
void FunctionNodeDescriptorComponent::Deactivate()
{
GraphCanvas::VisualNotificationBus::Handler::BusDisconnect();
AZ::Data::AssetBus::Handler::BusDisconnect();
}
void FunctionNodeDescriptorComponent::OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset)
{
AZ::EntityId graphCanvasGraphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphCanvasGraphId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
ScriptCanvas::ScriptCanvasId scriptCanvasId;
GeneralRequestBus::BroadcastResult(scriptCanvasId, &GeneralRequests::GetScriptCanvasId, graphCanvasGraphId);
EditorGraphRequestBus::Event(scriptCanvasId, &EditorGraphRequests::QueueVersionUpdate, GetEntityId());
}
void FunctionNodeDescriptorComponent::OnVersionConversionEnd()
{
AZ::Data::Asset<ScriptCanvas::RuntimeFunctionAsset> asset = AZ::Data::AssetManager::Instance().GetAsset<ScriptCanvas::RuntimeFunctionAsset>(m_assetId, AZ::Data::AssetLoadBehavior::Default);
asset.BlockUntilLoadComplete();
if (asset.IsReady())
{
//UpdateTitles();
// For reference:
//if (!asset.Get()->m_definition.HasMethod(m_eventId))
//{
// AZStd::unordered_set< AZ::EntityId > deleteNodes = { GetEntityId() };
// GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::Delete, deleteNodes);
//}
}
}
bool FunctionNodeDescriptorComponent::OnMouseDoubleClick(const QGraphicsSceneMouseEvent*)
{
AZ::Data::AssetInfo assetInfo = AssetHelpers::GetSourceInfoByProductId(m_assetId, azrtti_typeid< ScriptCanvas::RuntimeFunctionAsset>());
if (!assetInfo.m_assetId.IsValid())
{
return false;
}
AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, assetInfo.m_assetId, -1);
return openOutcome.IsSuccess();
}
void FunctionNodeDescriptorComponent::OnAddedToGraphCanvasGraph([[maybe_unused]] const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId)
{
m_scriptCanvasId = scriptCanvasNodeId;
EditorNodeNotificationBus::Handler::BusConnect(m_scriptCanvasId);
}
void FunctionNodeDescriptorComponent::UpdateTitles()
{
GraphCanvas::NodeRequestBus::Event(GetEntityId(), &GraphCanvas::NodeRequests::SetTooltip, m_name);
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetTitle, m_name);
}
}
@@ -0,0 +1,70 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <GraphCanvas/Components/VisualBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h>
#include <ScriptCanvas/Asset/Functions/ScriptCanvasFunctionAsset.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
namespace ScriptCanvasEditor
{
class FunctionNodeDescriptorComponent
: public NodeDescriptorComponent
, public AZ::Data::AssetBus::Handler
, public EditorNodeNotificationBus::Handler
, public GraphCanvas::VisualNotificationBus::Handler
{
public:
AZ_COMPONENT(FunctionNodeDescriptorComponent, "{B9DA0350-AF62-475E-8DD7-30E8F4F313BB}", NodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
FunctionNodeDescriptorComponent();
FunctionNodeDescriptorComponent(const AZ::Data::AssetId& assetId, const AZStd::string& name);
~FunctionNodeDescriptorComponent() = default;
// Component
void Activate() override;
void Deactivate() override;
////
// AZ::Data::AssetBus::Handler
void OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
////
// VersionControlledNodeRequestBus::Handler
void OnVersionConversionEnd() override;
////
// GraphCanvas::NodeNotificationBus
bool OnMouseDoubleClick(const QGraphicsSceneMouseEvent*) override;
//
protected:
void OnAddedToGraphCanvasGraph(const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId) override;
private:
void UpdateTitles();
AZ::EntityId m_scriptCanvasId;
AZ::Data::AssetId m_assetId;
AZStd::string m_name;
};
}
@@ -0,0 +1,57 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Component/ComponentApplicationBus.h>
#include <GraphCanvas/Components/Connections/ConnectionBus.h>
#include <GraphCanvas/Components/Nodes/NodeTitleBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/GetVariableNodeDescriptorComponent.h>
#include <Editor/Include/ScriptCanvas/Bus/RequestBus.h>
#include <Editor/Translation/TranslationHelper.h>
#include <Editor/View/Widgets/PropertyGridBus.h>
#include <ScriptCanvas/Libraries/Core/GetVariable.h>
namespace ScriptCanvasEditor
{
///////////////////////////////////////
// GetVariableNodeDescriptorComponent
///////////////////////////////////////
void GetVariableNodeDescriptorComponent::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<GetVariableNodeDescriptorComponent, VariableNodeDescriptorComponent>()
->Version(1)
;
}
}
GetVariableNodeDescriptorComponent::GetVariableNodeDescriptorComponent()
: VariableNodeDescriptorComponent(NodeDescriptorType::GetVariable)
{
}
void GetVariableNodeDescriptorComponent::UpdateTitle(AZStd::string_view variableName)
{
AZStd::string titleName = AZStd::string::format("Get %s", variableName.data());
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetTitle, titleName);
}
}
@@ -0,0 +1,33 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/VariableNodeDescriptorComponent.h>
#include <ScriptCanvas/Variable/VariableBus.h>
namespace ScriptCanvasEditor
{
class GetVariableNodeDescriptorComponent
: public VariableNodeDescriptorComponent
{
public:
AZ_COMPONENT(GetVariableNodeDescriptorComponent, "{78D946A9-4CC6-4BA7-A46A-A4C87191678D}", VariableNodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
GetVariableNodeDescriptorComponent();
protected:
void UpdateTitle(AZStd::string_view variableName) override;
};
}
@@ -0,0 +1,100 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <GraphCanvas/Components/SceneBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h>
namespace ScriptCanvasEditor
{
////////////////////////////
// NodeDescriptorComponent
////////////////////////////
void NodeDescriptorComponent::Reflect(AZ::ReflectContext* reflect)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflect))
{
serializeContext->Class<NodeDescriptorComponent, AZ::Component>()
->Version(0)
;
}
}
NodeDescriptorComponent::NodeDescriptorComponent()
: m_nodeDescriptorType(NodeDescriptorType::Unknown)
{
}
NodeDescriptorComponent::NodeDescriptorComponent(NodeDescriptorType descriptorType)
: m_nodeDescriptorType(descriptorType)
{
}
void NodeDescriptorComponent::Init()
{
}
void NodeDescriptorComponent::Activate()
{
NodeDescriptorRequestBus::Handler::BusConnect(GetEntityId());
GraphCanvas::NodeNotificationBus::Handler::BusConnect(GetEntityId());
}
void NodeDescriptorComponent::Deactivate()
{
GraphCanvas::NodeNotificationBus::Handler::BusDisconnect();
NodeDescriptorRequestBus::Handler::BusDisconnect();
}
void NodeDescriptorComponent::OnAddedToScene(const AZ::EntityId& sceneId)
{
AZ::EntityId scriptCanvasNodeId = FindScriptCanvasNodeId();
ScriptCanvas::NodeNotificationsBus::Handler::BusConnect(scriptCanvasNodeId);
OnAddedToGraphCanvasGraph(sceneId, scriptCanvasNodeId);
bool isEnabled = true;
ScriptCanvas::NodeRequestBus::EventResult(isEnabled, scriptCanvasNodeId, &ScriptCanvas::NodeRequests::IsNodeEnabled);
if (!isEnabled)
{
GraphCanvas::GraphId graphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
GraphCanvas::SceneRequestBus::Event(graphId, &GraphCanvas::SceneRequests::Disable, GetEntityId());
}
}
void NodeDescriptorComponent::OnAddedToGraphCanvasGraph(const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId)
{
AZ_UNUSED(graphId);
AZ_UNUSED(scriptCanvasNodeId);
}
AZ::EntityId NodeDescriptorComponent::FindScriptCanvasNodeId() const
{
AZStd::any* userData = nullptr;
GraphCanvas::NodeRequestBus::EventResult(userData, GetEntityId(), &GraphCanvas::NodeRequests::GetUserData);
AZ::EntityId* scNodeId = AZStd::any_cast<AZ::EntityId>(userData);
if (scNodeId)
{
return (*scNodeId);
}
return AZ::EntityId();
}
}
@@ -0,0 +1,62 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/Component.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <ScriptCanvas/Core/NodeBus.h>
#include <Editor/Include/ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
namespace ScriptCanvasEditor
{
class NodeDescriptorComponent
: public AZ::Component
, public GraphCanvas::NodeNotificationBus::Handler
, public ScriptCanvas::NodeNotificationsBus::Handler
, public NodeDescriptorRequestBus::Handler
{
public:
AZ_COMPONENT(NodeDescriptorComponent, "{C775A98E-D64E-457F-8ABA-B34CBAD10905}");
static void Reflect(AZ::ReflectContext* reflect);
NodeDescriptorComponent();
NodeDescriptorComponent(NodeDescriptorType descriptorType);
~NodeDescriptorComponent() override = default;
// Component
void Init();
void Activate();
void Deactivate();
////
// NodeDescriptorBus::Handler
NodeDescriptorType GetType() const override { return m_nodeDescriptorType; }
////
// GraphCanvas::NodeNotificationBus
void OnAddedToScene(const AZ::EntityId& sceneId) override final;
////
protected:
virtual void OnAddedToGraphCanvasGraph(const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId);
virtual AZ::EntityId FindScriptCanvasNodeId() const;
private:
NodeDescriptorType m_nodeDescriptorType;
};
}
@@ -0,0 +1,62 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <GraphCanvas/Components/Nodes/NodeTitleBus.h>
#include "NodelingDescriptorComponent.h"
#include <ScriptCanvas/Bus/RequestBus.h>
namespace ScriptCanvasEditor
{
////////////////////////////////
// NodelingDescriptorComponent
////////////////////////////////
void NodelingDescriptorComponent::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<NodelingDescriptorComponent, NodeDescriptorComponent>()
->Version(1)
;
}
}
NodelingDescriptorComponent::NodelingDescriptorComponent()
: NodeDescriptorComponent(NodeDescriptorType::ExecutionNodeling)
{
}
void NodelingDescriptorComponent::OnNameChanged(const AZStd::string& displayName)
{
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetTitle, displayName);
}
void NodelingDescriptorComponent::OnAddedToGraphCanvasGraph(const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId)
{
ScriptCanvas::ScriptCanvasId scriptCanvasId;
GeneralRequestBus::BroadcastResult(scriptCanvasId, &GeneralRequests::GetScriptCanvasId, graphId);
ScriptCanvas::GraphScopedNodeId scopedNodeId(scriptCanvasId, scriptCanvasNodeId);
ScriptCanvas::NodelingNotificationBus::Handler::BusConnect(scopedNodeId);
AZStd::string displayName;
ScriptCanvas::NodelingRequestBus::EventResult(displayName, scopedNodeId, &ScriptCanvas::NodelingRequests::GetDisplayName);
OnNameChanged(displayName);
}
}
@@ -0,0 +1,40 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h>
#include <ScriptCanvas/Core/NodelingBus.h>
namespace ScriptCanvasEditor
{
class NodelingDescriptorComponent
: public NodeDescriptorComponent
, public ScriptCanvas::NodelingNotificationBus::Handler
{
public:
AZ_COMPONENT(NodelingDescriptorComponent, "{9EFA1DA5-2CCB-4A6D-AA84-BD121C75773A}", NodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
NodelingDescriptorComponent();
~NodelingDescriptorComponent() = default;
// NodelingNotificationBus
void OnNameChanged(const AZStd::string& newName) override;
////
protected:
void OnAddedToGraphCanvasGraph(const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId) override;
};
}
@@ -0,0 +1,391 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Asset/AssetManager.h>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/GeometryBus.h>
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <GraphCanvas/Components/Nodes/NodeTitleBus.h>
#include <Editor/Nodes/NodeUtils.h>
#include <Editor/View/Widgets/NodePalette/EBusNodePaletteTreeItemTypes.h>
#include <Editor/Translation/TranslationHelper.h>
#include <Editor/View/Widgets/NodePalette/ScriptEventsNodePaletteTreeItemTypes.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/ScriptEventReceiverEventNodeDescriptorComponent.h>
#include <GraphCanvas/Components/Nodes/NodeTitleBus.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/Core/NodeBus.h>
#include <ScriptCanvas/GraphCanvas/MappingBus.h>
#include <ScriptCanvas/Libraries/Core/EBusEventHandler.h>
#include <ScriptCanvas/Libraries/Core/SendScriptEvent.h>
#include <Libraries/Core/ReceiveScriptEvent.h>
namespace ScriptCanvasEditor
{
////////////////////////////////////////////////////
// ScriptEventReceiverEventNodeDescriptorComponent
////////////////////////////////////////////////////
void ScriptEventReceiverEventNodeDescriptorComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<ScriptEventReceiverEventNodeDescriptorComponent, NodeDescriptorComponent>()
->Version(3)
->Field("AssetId", &ScriptEventReceiverEventNodeDescriptorComponent::m_assetId)
->Field("BusName", &ScriptEventReceiverEventNodeDescriptorComponent::m_busName)
->Field("MethodDefinition", &ScriptEventReceiverEventNodeDescriptorComponent::m_methodDefinition)
->Field("EventName", &ScriptEventReceiverEventNodeDescriptorComponent::m_eventName)
->Field("EventId", &ScriptEventReceiverEventNodeDescriptorComponent::m_eventId)
->Field("EventPropertyId", &ScriptEventReceiverEventNodeDescriptorComponent::m_eventPropertyId)
;
}
}
ScriptEventReceiverEventNodeDescriptorComponent::ScriptEventReceiverEventNodeDescriptorComponent()
: NodeDescriptorComponent(NodeDescriptorType::EBusHandlerEvent)
{
}
ScriptEventReceiverEventNodeDescriptorComponent::ScriptEventReceiverEventNodeDescriptorComponent(const AZ::Data::AssetId assetId, const ScriptEvents::Method& methodDefinition)
: NodeDescriptorComponent(NodeDescriptorType::EBusHandlerEvent)
, m_assetId(assetId)
, m_methodDefinition(methodDefinition)
{
m_eventName = m_methodDefinition.GetName();
m_eventId = m_methodDefinition.GetEventId();
m_eventPropertyId = m_methodDefinition.GetNameProperty().GetId();
}
void ScriptEventReceiverEventNodeDescriptorComponent::Activate()
{
NodeDescriptorComponent::Activate();
ScriptEventReceiverEventNodeDescriptorBus::Handler::BusConnect(GetEntityId());
EBusHandlerEventNodeDescriptorRequestBus::Handler::BusConnect(GetEntityId());
GraphCanvas::ForcedWrappedNodeRequestBus::Handler::BusConnect(GetEntityId());
GraphCanvas::SceneMemberNotificationBus::Handler::BusConnect(GetEntityId());
m_busId = AZ::Crc32(m_assetId.ToString<AZStd::string>().c_str());
}
void ScriptEventReceiverEventNodeDescriptorComponent::Deactivate()
{
NodeDescriptorComponent::Deactivate();
GraphCanvas::SceneMemberNotificationBus::Handler::BusDisconnect();
GraphCanvas::ForcedWrappedNodeRequestBus::Handler::BusDisconnect();
EBusHandlerEventNodeDescriptorRequestBus::Handler::BusDisconnect();
ScriptEventReceiverEventNodeDescriptorBus::Handler::BusDisconnect();
}
AZStd::string_view ScriptEventReceiverEventNodeDescriptorComponent::GetBusName() const
{
return m_busName;
}
AZStd::string_view ScriptEventReceiverEventNodeDescriptorComponent::GetEventName() const
{
return m_eventName;
}
ScriptCanvas::EBusEventId ScriptEventReceiverEventNodeDescriptorComponent::GetEventId() const
{
return m_eventId;
}
void ScriptEventReceiverEventNodeDescriptorComponent::SetHandlerAddress(const ScriptCanvas::Datum& idDatum)
{
if (m_ebusWrapper.m_scriptCanvasId.IsValid())
{
GraphCanvas::GraphId graphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
ScriptCanvas::ScriptCanvasId canvasId;
GeneralRequestBus::BroadcastResult(canvasId, &GeneralRequests::GetScriptCanvasId, graphId);
ScriptCanvas::GraphScopedNodeId scopedNodeId(canvasId, m_ebusWrapper.m_scriptCanvasId);
ScriptCanvas::EBusHandlerNodeRequestBus::Event(scopedNodeId, &ScriptCanvas::EBusHandlerNodeRequests::SetAddressId, AZStd::move(idDatum));
m_queuedId = AZStd::move(ScriptCanvas::Datum());
}
else
{
m_queuedId.DeepCopyDatum(idDatum);
}
}
void ScriptEventReceiverEventNodeDescriptorComponent::OnNodeWrapped(const AZ::EntityId& wrappingNode)
{
bool isValid = false;
AZStd::any* userData = nullptr;
GraphCanvas::NodeRequestBus::EventResult(userData, wrappingNode, &GraphCanvas::NodeRequests::GetUserData);
if (userData && userData->is<AZ::EntityId>())
{
AZ_Warning("ScriptCanvas", !m_ebusWrapper.m_graphCanvasId.IsValid() && !m_ebusWrapper.m_scriptCanvasId.IsValid(), "Wrapping the same ebus event node twice without unwrapping it.");
AZ::EntityId scriptCanvasId = (*AZStd::any_cast<AZ::EntityId>(userData));
m_ebusWrapper.m_graphCanvasId = wrappingNode;
m_ebusWrapper.m_scriptCanvasId = scriptCanvasId;
AZStd::string ebusContextName = TranslationHelper::GetEbusHandlerContext(m_busName);
ScriptCanvas::Nodes::Core::ReceiveScriptEvent* eventHandler = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::ReceiveScriptEvent>(scriptCanvasId);
if (eventHandler)
{
AZStd::vector< AZ::EntityId > graphCanvasSlotIds;
GraphCanvas::NodeRequestBus::EventResult(graphCanvasSlotIds, GetEntityId(), &GraphCanvas::NodeRequests::GetSlotIds);
const ScriptCanvas::Nodes::Core::SendScriptEvent::EventMap& events = eventHandler->GetEvents();
ScriptCanvas::Nodes::Core::Internal::ScriptEventEntry myEvent;
auto mapIter = events.find(m_eventId);
if (mapIter != events.end())
{
myEvent = mapIter->second;
}
const int numEventSlots = 1;
const int numResultSlots = myEvent.m_resultSlotId.IsValid() ? 1 : 0;
const int totalSlots = (myEvent.m_numExpectedArguments + numEventSlots + numResultSlots);
// Potentially overly simplistic way of detecting if we need to refresh our Slot information.
if (totalSlots != graphCanvasSlotIds.size())
{
// Remove the previous slots
for (const auto& graphCanvasSlotId : graphCanvasSlotIds)
{
GraphCanvas::NodeRequestBus::Event(GetEntityId(), &GraphCanvas::NodeRequests::RemoveSlot, graphCanvasSlotId);
}
// Then from a clean slate, fully regenerate all of our slots.
ScriptCanvas::Slot* scriptCanvasSlot = eventHandler->GetSlot(myEvent.m_eventSlotId);
if (scriptCanvasSlot)
{
AZ::EntityId slotId = Nodes::DisplayScriptCanvasSlot(GetEntityId(), (*scriptCanvasSlot));
GraphCanvas::SlotRequestBus::Event(slotId, &GraphCanvas::SlotRequests::SetTranslationKeyedName, TranslationHelper::GetEBusHandlerOnEventTriggeredNameKey());
GraphCanvas::SlotRequestBus::Event(slotId, &GraphCanvas::SlotRequests::SetTranslationKeyedTooltip, TranslationHelper::GetEBusHandlerOnEventTriggeredTooltipKey());
}
//
// inputCount and outputCount work because the order of the slots is maintained from the BehaviorContext, if this changes
// in the future then we should consider storing the actual offset or key name at that time.
//
int inputCount = 0;
int outputCount = 0;
for (const auto& slotId : myEvent.m_parameterSlotIds)
{
scriptCanvasSlot = eventHandler->GetSlot(slotId);
if (scriptCanvasSlot)
{
AZ::EntityId graphCanvasSlotId = Nodes::DisplayScriptCanvasSlot(GetEntityId(), (*scriptCanvasSlot));
TranslationItemType itemType = TranslationHelper::GetItemType(scriptCanvasSlot->GetDescriptor());
GraphCanvas::TranslationKeyedString slotNameKeyedString(scriptCanvasSlot->GetName());
slotNameKeyedString.m_context = ebusContextName;
GraphCanvas::TranslationKeyedString slotTooltipKeyedString(scriptCanvasSlot->GetToolTip());
slotTooltipKeyedString.m_context = ebusContextName;
if (scriptCanvasSlot->GetDescriptor() == ScriptCanvas::SlotDescriptors::DataOut())
{
slotNameKeyedString.m_key = TranslationHelper::GetEBusHandlerSlotKey(m_busName, m_eventName, itemType, TranslationKeyId::Name, outputCount);
slotTooltipKeyedString.m_key = TranslationHelper::GetEBusHandlerSlotKey(m_busName, m_eventName, itemType, TranslationKeyId::Tooltip, outputCount);
++outputCount;
}
else
{
slotNameKeyedString.m_key = TranslationHelper::GetEBusHandlerSlotKey(m_busName, m_eventName, itemType, TranslationKeyId::Name, inputCount);
slotTooltipKeyedString.m_key = TranslationHelper::GetEBusHandlerSlotKey(m_busName, m_eventName, itemType, TranslationKeyId::Tooltip, inputCount);
++inputCount;
}
GraphCanvas::SlotRequestBus::Event(graphCanvasSlotId, &GraphCanvas::SlotRequests::SetTranslationKeyedName, slotNameKeyedString);
GraphCanvas::SlotRequestBus::Event(graphCanvasSlotId, &GraphCanvas::SlotRequests::SetTranslationKeyedTooltip, slotTooltipKeyedString);
}
}
if (myEvent.m_resultSlotId.IsValid())
{
scriptCanvasSlot = eventHandler->GetSlot(myEvent.m_resultSlotId);
if (scriptCanvasSlot)
{
AZ::EntityId graphCanvasSlotId = Nodes::DisplayScriptCanvasSlot(GetEntityId(), (*scriptCanvasSlot));
TranslationItemType itemType = TranslationHelper::GetItemType(scriptCanvasSlot->GetDescriptor());
GraphCanvas::TranslationKeyedString slotNameKeyedString(scriptCanvasSlot->GetName(), ebusContextName);
slotNameKeyedString.m_key = slotNameKeyedString.m_key = TranslationHelper::GetKey(TranslationContextGroup::EbusHandler, m_busName, m_eventName, itemType, TranslationKeyId::Name);
GraphCanvas::TranslationKeyedString slotTooltipKeyedString(TranslationHelper::GetSafeTypeName(scriptCanvasSlot->GetDataType()), ebusContextName);
slotTooltipKeyedString.m_key = TranslationHelper::GetKey(TranslationContextGroup::EbusHandler, m_busName, m_eventName, itemType, TranslationKeyId::Tooltip);
GraphCanvas::SlotRequestBus::Event(graphCanvasSlotId, &GraphCanvas::SlotRequests::SetTranslationKeyedName, slotNameKeyedString);
GraphCanvas::SlotRequestBus::Event(graphCanvasSlotId, &GraphCanvas::SlotRequests::SetTranslationKeyedTooltip, slotTooltipKeyedString);
}
}
GraphCanvas::NodeRequestBus::EventResult(graphCanvasSlotIds, GetEntityId(), &GraphCanvas::NodeRequests::GetSlotIds);
}
isValid = (totalSlots == graphCanvasSlotIds.size());
}
if (m_queuedId.GetType().IsValid())
{
SetHandlerAddress(m_queuedId);
}
}
if (!isValid)
{
AZ::EntityId sceneId;
GraphCanvas::SceneMemberRequestBus::EventResult(sceneId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
if (sceneId.IsValid())
{
AZStd::unordered_set<AZ::EntityId> deleteNodes;
deleteNodes.insert(GetEntityId());
GraphCanvas::SceneRequestBus::Event(sceneId, &GraphCanvas::SceneRequests::Delete, deleteNodes);
}
}
else
{
ScriptEventReceiveNodeDescriptorNotificationBus::Handler::BusConnect(wrappingNode);
}
}
void ScriptEventReceiverEventNodeDescriptorComponent::OnSceneMemberAboutToSerialize(GraphCanvas::GraphSerialization& sceneSerialization)
{
AZ::Entity* wrapperEntity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(wrapperEntity, &AZ::ComponentApplicationRequests::FindEntity, m_ebusWrapper.m_graphCanvasId);
if (wrapperEntity)
{
sceneSerialization.GetGraphData().m_nodes.insert(wrapperEntity);
}
}
void ScriptEventReceiverEventNodeDescriptorComponent::OnSceneMemberDeserialized([[maybe_unused]] const AZ::EntityId& graphId, [[maybe_unused]] const GraphCanvas::GraphSerialization& serializationTarget)
{
// Add in the asset bus hook up here if we want to ensure we get asset notifications post copy/paste
}
AZ::Crc32 ScriptEventReceiverEventNodeDescriptorComponent::GetWrapperType() const
{
return m_busId;
}
AZ::Crc32 ScriptEventReceiverEventNodeDescriptorComponent::GetIdentifier() const
{
return AZ::Crc32(m_eventName.c_str());
}
AZ::EntityId ScriptEventReceiverEventNodeDescriptorComponent::CreateWrapperNode(const AZ::EntityId& sceneId, const AZ::Vector2& nodePosition)
{
CreateScriptEventsHandlerMimeEvent createEbusMimeEvent(m_assetId, m_methodDefinition);
AZ::EntityId wrapperNode;
AZ::Vector2 dummyPosition = nodePosition;
if (createEbusMimeEvent.ExecuteEvent(nodePosition, dummyPosition, sceneId))
{
const NodeIdPair& nodePair = createEbusMimeEvent.GetCreatedPair();
wrapperNode = nodePair.m_graphCanvasId;
}
return wrapperNode;
}
void ScriptEventReceiverEventNodeDescriptorComponent::OnScriptEventReloaded(const AZ::Data::Asset<ScriptEvents::ScriptEventsAsset>& asset)
{
bool isValid = false;
ScriptEvents::ScriptEvent definition = asset.Get()->m_definition;
for (auto methodDefinition : definition.GetMethods())
{
if (methodDefinition.GetEventId() == m_eventId)
{
m_methodDefinition = methodDefinition;
isValid = true;
break;
}
}
if (isValid)
{
UpdateTitles();
}
else
{
AZ::EntityId graphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
// From this point on this element is garbage, so do not reference anything internal
AZStd::unordered_set< AZ::EntityId > deleteSet = { GetEntityId() };
GraphCanvas::SceneRequestBus::Event(graphId, &GraphCanvas::SceneRequests::Delete, deleteSet);
}
}
void ScriptEventReceiverEventNodeDescriptorComponent::OnAddedToGraphCanvasGraph([[maybe_unused]] const GraphCanvas::GraphId& grapphId, [[maybe_unused]] const AZ::EntityId& scriptCanvasNodeId)
{
AZStd::vector< AZ::EntityId > slotIds;
GraphCanvas::NodeRequestBus::EventResult(slotIds, GetEntityId(), &GraphCanvas::NodeRequests::GetSlotIds);
for (const auto& slotId : slotIds)
{
GraphCanvas::SlotType slotType;
GraphCanvas::SlotRequestBus::EventResult(slotType, slotId, &GraphCanvas::SlotRequests::GetSlotType);
if (slotType == GraphCanvas::SlotTypes::ExecutionSlot)
{
GraphCanvas::ConnectionType connectionType = GraphCanvas::ConnectionType::CT_None;
GraphCanvas::SlotRequestBus::EventResult(connectionType, slotId, &GraphCanvas::SlotRequests::GetConnectionType);
if (connectionType == GraphCanvas::ConnectionType::CT_Output)
{
GraphCanvas::SlotRequestBus::Event(slotId, &GraphCanvas::SlotRequests::SetTranslationKeyedName, TranslationHelper::GetEBusHandlerOnEventTriggeredNameKey());
GraphCanvas::SlotRequestBus::Event(slotId, &GraphCanvas::SlotRequests::SetTranslationKeyedTooltip, TranslationHelper::GetEBusHandlerOnEventTriggeredTooltipKey());
break;
}
}
}
UpdateTitles();
}
void ScriptEventReceiverEventNodeDescriptorComponent::UpdateTitles()
{
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetTitle, m_methodDefinition.GetName());
GraphCanvas::NodeRequestBus::Event(GetEntityId(), &GraphCanvas::NodeRequests::SetTooltip, m_methodDefinition.GetTooltip());
}
}
@@ -0,0 +1,106 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <GraphCanvas/Components/SceneBus.h>
#include "Editor/Include/ScriptCanvas/Bus/NodeIdPair.h"
#include "Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h"
#include <ScriptEvents/ScriptEventsAssetRef.h>
namespace ScriptCanvasEditor
{
class ScriptEventReceiverEventNodeDescriptorComponent
: public NodeDescriptorComponent
, protected GraphCanvas::SceneMemberNotificationBus::Handler
, protected ScriptEventReceiverEventNodeDescriptorBus::Handler
, public EBusHandlerEventNodeDescriptorRequestBus::Handler
, public GraphCanvas::ForcedWrappedNodeRequestBus::Handler
, public ScriptEventReceiveNodeDescriptorNotificationBus::Handler
{
public:
AZ_COMPONENT(ScriptEventReceiverEventNodeDescriptorComponent, "{EFC9CCCE-32FC-466F-AA29-2EEE1320FF4F}", NodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
ScriptEventReceiverEventNodeDescriptorComponent();
ScriptEventReceiverEventNodeDescriptorComponent(const AZ::Data::AssetId assetId, const ScriptEvents::Method& methodDefinition);
~ScriptEventReceiverEventNodeDescriptorComponent() = default;
void Activate() override;
void Deactivate() override;
// EBusHandlerEventNodeDescriptorRequestBus
AZStd::string_view GetBusName() const override;
AZStd::string_view GetEventName() const override;
ScriptCanvas::EBusEventId GetEventId() const override;
void SetHandlerAddress(const ScriptCanvas::Datum& idDatum) override;
////
// NodeNotificationBus::Handler
void OnNodeWrapped(const AZ::EntityId& wrappingNode) override;
////
// SceneMemberNotifications
void OnSceneMemberAboutToSerialize(GraphCanvas::GraphSerialization& graphSerialization) override;
void OnSceneMemberDeserialized(const AZ::EntityId& graphId, const GraphCanvas::GraphSerialization& serializationTarget) override;
////
// ScriptEventSenderNodeDescriptorBus::Handler
const ScriptEvents::Method& GetMethodDefinition() override
{
return m_methodDefinition;
}
AZStd::string GetEventName() override
{
return m_eventName;
}
////
// ForcedWrappedNodeRequestBus
AZ::Crc32 GetWrapperType() const override;
AZ::Crc32 GetIdentifier() const override;
AZ::EntityId CreateWrapperNode(const AZ::EntityId& sceneId, const AZ::Vector2& nodePosition) override;
////
// ScriptEventReceiveNodeDescriptorNotifications
void OnScriptEventReloaded(const AZ::Data::Asset<ScriptEvents::ScriptEventsAsset>& asset);
////
protected:
void OnAddedToGraphCanvasGraph(const GraphCanvas::GraphId& grapphId, const AZ::EntityId& scriptCanvasNodeId) override;
private:
void UpdateTitles();
NodeIdPair m_ebusWrapper;
AZ::Data::AssetId m_assetId;
ScriptEvents::Method m_methodDefinition;
ScriptCanvas::EBusEventId m_eventId;
// These are required for reconstructing the node (i.e. copy/paste)
AZStd::string m_busName;
AZ::Crc32 m_busId;
AZStd::string m_eventName;
AZ::Uuid m_eventPropertyId;
ScriptCanvas::Datum m_queuedId;
};
}
@@ -0,0 +1,640 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <QString>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/Slots/Data/DataSlotBus.h>
#include <GraphCanvas/Components/Nodes/NodeTitleBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/ScriptEventReceiverNodeDescriptorComponent.h>
#include <Editor/GraphCanvas/PropertySlotIds.h>
#include <Editor/Include/ScriptCanvas/Bus/RequestBus.h>
#include <Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <Editor/Translation/TranslationHelper.h>
#include <Editor/Nodes/NodeUtils.h>
#include <Editor/View/Widgets/NodePalette/ScriptEventsNodePaletteTreeItemTypes.h>
#include <Editor/View/Widgets/PropertyGridBus.h>
#include <ScriptCanvas/Libraries/Core/SendScriptEvent.h>
#include <ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h>
#include <ScriptCanvas/GraphCanvas/DynamicSlotBus.h>
#include <ScriptCanvas/GraphCanvas/MappingBus.h>
#include <AzCore/Math/Crc.h>
#include <ScriptCanvas/Libraries/Core/ScriptEventBase.h>
namespace ScriptCanvasEditor
{
/////////////////////////////////////////////////////
// ScriptEventReceiverHandlerNodeDescriptorSaveData
/////////////////////////////////////////////////////
ScriptEventReceiverNodeDescriptorComponent::ScriptEventReceiverHandlerNodeDescriptorSaveData::ScriptEventReceiverHandlerNodeDescriptorSaveData()
: m_displayConnections(false)
, m_callback(nullptr)
{
}
ScriptEventReceiverNodeDescriptorComponent::ScriptEventReceiverHandlerNodeDescriptorSaveData::ScriptEventReceiverHandlerNodeDescriptorSaveData(ScriptEventReceiverNodeDescriptorComponent* component)
: m_displayConnections(false)
, m_callback(component)
{
}
void ScriptEventReceiverNodeDescriptorComponent::ScriptEventReceiverHandlerNodeDescriptorSaveData::operator=(const ScriptEventReceiverHandlerNodeDescriptorSaveData& other)
{
// Purposefully skipping over the callback
m_displayConnections = other.m_displayConnections;
m_enabledEvents = other.m_enabledEvents;
}
void ScriptEventReceiverNodeDescriptorComponent::ScriptEventReceiverHandlerNodeDescriptorSaveData::OnDisplayConnectionsChanged()
{
if (m_callback)
{
m_callback->OnDisplayConnectionsChanged();
SignalDirty();
}
}
///////////////////////////////////////////////
// ScriptEventReceiverNodeDescriptorComponent
///////////////////////////////////////////////
void ScriptEventReceiverNodeDescriptorComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<ScriptEventReceiverHandlerNodeDescriptorSaveData, GraphCanvas::ComponentSaveData>()
->Version(2)
->Field("DisplayConnections", &ScriptEventReceiverHandlerNodeDescriptorSaveData::m_displayConnections)
->Field("EventNames", &ScriptEventReceiverHandlerNodeDescriptorSaveData::m_enabledEvents)
;
serializeContext->Class<ScriptEventReceiverNodeDescriptorComponent, NodeDescriptorComponent>()
->Version(3)
->Field("AssetId", &ScriptEventReceiverNodeDescriptorComponent::m_scriptEventsAssetId)
->Field("SaveData", &ScriptEventReceiverNodeDescriptorComponent::m_saveData)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<ScriptEventReceiverHandlerNodeDescriptorSaveData>("SaveData", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "Properties")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptEventReceiverHandlerNodeDescriptorSaveData::m_displayConnections, "Display Connection Controls", "Controls whether or not manual connection controls are visible for this node.")
->Attribute(AZ::Edit::Attributes::ChangeNotify, &ScriptEventReceiverHandlerNodeDescriptorSaveData::OnDisplayConnectionsChanged)
;
editContext->Class<ScriptEventReceiverNodeDescriptorComponent>("Script Event Handler", "Configuration values for the Script Event Receiver node.")
->ClassElement(AZ::Edit::ClassElements::EditorData, "Properties")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptEventReceiverNodeDescriptorComponent::m_saveData, "SaveData", "The modifiable information about this comment.")
->DataElement(AZ::Edit::UIHandlers::Default, &ScriptEventReceiverNodeDescriptorComponent::m_scriptEventsAssetId, "Asset Id", "The Script Event Asset Id to use.")
;
}
}
}
ScriptEventReceiverNodeDescriptorComponent::ScriptEventReceiverNodeDescriptorComponent()
: NodeDescriptorComponent(NodeDescriptorType::EBusHandler)
, m_saveData(this)
, m_loadingEvents(false)
{
}
ScriptEventReceiverNodeDescriptorComponent::ScriptEventReceiverNodeDescriptorComponent(AZ::Data::AssetId assetId)
: NodeDescriptorComponent(NodeDescriptorType::EBusHandler)
, m_saveData(this)
, m_scriptEventsAssetId(assetId)
, m_loadingEvents(false)
{
}
void ScriptEventReceiverNodeDescriptorComponent::Activate()
{
NodeDescriptorComponent::Activate();
EBusHandlerNodeDescriptorRequestBus::Handler::BusConnect(GetEntityId());
GraphCanvas::WrapperNodeNotificationBus::Handler::BusConnect(GetEntityId());
GraphCanvas::GraphCanvasPropertyBusHandler::OnActivate(GetEntityId());
GraphCanvas::WrapperNodeConfigurationRequestBus::Handler::BusConnect(GetEntityId());
GraphCanvas::EntitySaveDataRequestBus::Handler::BusConnect(GetEntityId());
GraphCanvas::SceneMemberNotificationBus::Handler::BusConnect(GetEntityId());
ScriptEventReceiverNodeDescriptorRequestBus::Handler::BusConnect(GetEntityId());
m_busId = AZ::Crc32(m_scriptEventsAssetId.ToString<AZStd::string>().c_str());
AZ::Data::AssetBus::Handler::BusConnect(m_scriptEventsAssetId);
}
void ScriptEventReceiverNodeDescriptorComponent::Deactivate()
{
NodeDescriptorComponent::Deactivate();
AZ::Data::AssetBus::Handler::BusDisconnect();
ScriptEventReceiverNodeDescriptorRequestBus::Handler::BusDisconnect();
GraphCanvas::SceneMemberNotificationBus::Handler::BusDisconnect();
GraphCanvas::EntitySaveDataRequestBus::Handler::BusDisconnect();
GraphCanvas::WrapperNodeConfigurationRequestBus::Handler::BusDisconnect();
GraphCanvas::GraphCanvasPropertyBusHandler::OnDeactivate();
GraphCanvas::WrapperNodeNotificationBus::Handler::BusDisconnect();
EBusHandlerNodeDescriptorRequestBus::Handler::BusDisconnect();
}
void ScriptEventReceiverNodeDescriptorComponent::OnNodeActivated()
{
GraphCanvas::WrapperNodeRequestBus::Event(GetEntityId(), &GraphCanvas::WrapperNodeRequests::SetWrapperType, m_busId);
}
void ScriptEventReceiverNodeDescriptorComponent::OnMemberSetupComplete()
{
m_loadingEvents = true;
AZ::Data::Asset<ScriptEvents::ScriptEventsAsset> asset = AZ::Data::AssetManager::Instance().GetAsset<ScriptEvents::ScriptEventsAsset>(m_scriptEventsAssetId, AZ::Data::AssetLoadBehavior::Default);
AZ_Assert(asset.IsReady(), "ScriptEventsAsset is not ready");
AZ::EntityId graphCanvasGraphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphCanvasGraphId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
ScriptEvents::ScriptEventsAsset* scriptEvent = asset.GetAs<ScriptEvents::ScriptEventsAsset>();
m_busName = scriptEvent->m_definition.GetName();
for (const auto& eventId : m_saveData.m_enabledEvents)
{
if (m_eventTypeToId.find(eventId.first) == m_eventTypeToId.end())
{
AZ::EntityId internalNode;
for (auto& method : scriptEvent->m_definition.GetMethods())
{
if (eventId.first == method.GetEventId())
{
internalNode = Nodes::DisplayScriptEventNode(graphCanvasGraphId, m_scriptEventsAssetId, method);
break;
}
}
if (internalNode.IsValid())
{
GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::Add, internalNode);
GraphCanvas::WrappedNodeConfiguration configuration = GetEventConfiguration(eventId.first);
GraphCanvas::WrapperNodeRequestBus::Event(GetEntityId(), &GraphCanvas::WrapperNodeRequests::WrapNode, internalNode, configuration);
}
}
}
m_loadingEvents = false;
m_saveData.RegisterIds(GetEntityId(), graphCanvasGraphId);
}
void ScriptEventReceiverNodeDescriptorComponent::OnSceneMemberDeserialized(const AZ::EntityId&, const GraphCanvas::GraphSerialization&)
{
m_saveData.m_enabledEvents.clear();
AZ::Data::AssetManager::Instance().GetAsset<ScriptEvents::ScriptEventsAsset>(m_scriptEventsAssetId, AZ::Data::AssetLoadBehavior::Default);
}
void ScriptEventReceiverNodeDescriptorComponent::WriteSaveData(GraphCanvas::EntitySaveDataContainer& saveDataContainer) const
{
ScriptEventReceiverHandlerNodeDescriptorSaveData* saveData = saveDataContainer.FindCreateSaveData<ScriptEventReceiverHandlerNodeDescriptorSaveData>();
if (saveData)
{
(*saveData) = m_saveData;
}
}
void ScriptEventReceiverNodeDescriptorComponent::ReadSaveData(const GraphCanvas::EntitySaveDataContainer& saveDataContainer)
{
const ScriptEventReceiverHandlerNodeDescriptorSaveData* saveData = saveDataContainer.FindSaveDataAs<ScriptEventReceiverHandlerNodeDescriptorSaveData>();
if (saveData)
{
m_saveData = (*saveData);
}
}
AZ::Data::AssetId ScriptEventReceiverNodeDescriptorComponent::GetAssetId() const
{
return m_scriptEventsAssetId;
}
AZStd::string_view ScriptEventReceiverNodeDescriptorComponent::GetBusName() const
{
return m_busName;
}
GraphCanvas::WrappedNodeConfiguration ScriptEventReceiverNodeDescriptorComponent::GetEventConfiguration(const ScriptCanvas::EBusEventId& eventId) const
{
AZ_Warning("ScriptCanvas", m_scriptCanvasId.IsValid(), "Trying to query event list before the node is added to the scene.");
GraphCanvas::WrappedNodeConfiguration wrappedConfiguration;
ScriptCanvas::Nodes::Core::ReceiveScriptEvent* eventHandler = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::ReceiveScriptEvent>(m_scriptCanvasId);
if (eventHandler)
{
const ScriptCanvas::Nodes::Core::Internal::ScriptEventBase::EventMap& events = eventHandler->GetEvents();
AZ::u32 i = 0;
for (const auto& event : events)
{
if (event.first == eventId)
{
wrappedConfiguration.m_layoutOrder = i;
break;
}
++i;
}
}
return wrappedConfiguration;
}
AZStd::vector< HandlerEventConfiguration > ScriptEventReceiverNodeDescriptorComponent::GetEventConfigurations() const
{
AZStd::vector< HandlerEventConfiguration > configurations;
AZ_Warning("ScriptCanvas", m_scriptCanvasId.IsValid(), "Trying to query event list before the node is added to the scene.");
ScriptCanvas::Nodes::Core::ReceiveScriptEvent* eventHandler = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::ReceiveScriptEvent>(m_scriptCanvasId);
if (eventHandler)
{
for (auto& event : eventHandler->GetEvents())
{
HandlerEventConfiguration configuration;
configuration.m_eventId = event.first;
configuration.m_eventName = event.second.m_eventName;
configurations.emplace_back(configuration);
}
}
return configurations;
}
bool ScriptEventReceiverNodeDescriptorComponent::ContainsEvent(const ScriptCanvas::EBusEventId& eventId) const
{
return m_eventTypeToId.count(eventId) != 0;
}
AZ::EntityId ScriptEventReceiverNodeDescriptorComponent::FindEventNodeId(const ScriptCanvas::EBusEventId& eventId) const
{
auto eventTypeEntry = m_eventTypeToId.find(eventId);
if (eventTypeEntry != m_eventTypeToId.end())
{
return eventTypeEntry->second;
}
return AZ::EntityId();
}
AZ::EntityId ScriptEventReceiverNodeDescriptorComponent::FindGraphCanvasNodeIdForSlot(const ScriptCanvas::SlotId& slotId) const
{
ScriptCanvas::Nodes::Core::ReceiveScriptEvent* eventHandler = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::ReceiveScriptEvent>(m_scriptCanvasId);
if (eventHandler)
{
auto nonEventSlotIds = eventHandler->GetNonEventSlotIds();
bool isNonEventSlot = (AZStd::find(nonEventSlotIds.begin(), nonEventSlotIds.end(), slotId) != nonEventSlotIds.end());
if (isNonEventSlot)
{
return GetEntityId();
}
auto scriptEvents = eventHandler->GetEvents();
ScriptCanvas::EBusEventId foundEventId = ScriptCanvas::EBusEventId();
for (auto scriptEventPair : scriptEvents)
{
const auto& scriptEvent = scriptEventPair.second;
bool foundResult = scriptEvent.m_eventSlotId == slotId;
foundResult = foundResult || scriptEvent.m_resultSlotId == slotId;
foundResult = foundResult || (AZStd::find(scriptEvent.m_parameterSlotIds.begin(), scriptEvent.m_parameterSlotIds.end(), slotId) != scriptEvent.m_parameterSlotIds.end());
if (foundResult)
{
foundEventId = scriptEventPair.first;
break;
}
}
if (foundEventId != ScriptCanvas::EBusEventId())
{
return FindEventNodeId(foundEventId);
}
}
return AZ::EntityId();
}
GraphCanvas::Endpoint ScriptEventReceiverNodeDescriptorComponent::MapSlotToGraphCanvasEndpoint(const ScriptCanvas::SlotId& scriptCanvasSlotId) const
{
GraphCanvas::Endpoint endpoint;
AZ::EntityId graphCanvasSlotId;
SlotMappingRequestBus::EventResult(graphCanvasSlotId, GetEntityId(), &SlotMappingRequests::MapToGraphCanvasId, scriptCanvasSlotId);
if (!graphCanvasSlotId.IsValid())
{
for (auto& mapPair : m_eventTypeToId)
{
AZ::EntityId graphCanvasSlotId2;
SlotMappingRequestBus::EventResult(graphCanvasSlotId2, mapPair.second, &SlotMappingRequests::MapToGraphCanvasId, scriptCanvasSlotId);
if (graphCanvasSlotId2.IsValid())
{
endpoint = GraphCanvas::Endpoint(mapPair.second, graphCanvasSlotId2);
break;
}
}
}
else
{
endpoint = GraphCanvas::Endpoint(GetEntityId(), graphCanvasSlotId);
}
return endpoint;
}
void ScriptEventReceiverNodeDescriptorComponent::OnWrappedNode(const AZ::EntityId& wrappedNode)
{
AZStd::string eventName;
ScriptEventReceiverEventNodeDescriptorBus::EventResult(eventName, wrappedNode, &ScriptEventReceiverEventNodeDescriptorRequests::GetEventName);
ScriptCanvas::EBusEventId eventId;
EBusHandlerEventNodeDescriptorRequestBus::EventResult(eventId, wrappedNode, &EBusHandlerEventNodeDescriptorRequests::GetEventId);
auto emplaceResult = m_eventTypeToId.emplace(eventId, wrappedNode);
if (emplaceResult.second)
{
m_idToEventType.emplace(wrappedNode, eventId);
AZStd::any* userData = nullptr;
GraphCanvas::NodeRequestBus::EventResult(userData, wrappedNode, &GraphCanvas::NodeRequests::GetUserData);
if (userData)
{
(*userData) = m_scriptCanvasId;
DynamicSlotRequestBus::Event(wrappedNode, &DynamicSlotRequests::OnUserDataChanged);
GraphCanvas::NodeDataSlotRequestBus::Event(wrappedNode, &GraphCanvas::NodeDataSlotRequests::RecreatePropertyDisplay);
}
if (!m_loadingEvents)
{
m_saveData.m_enabledEvents.push_back(AZStd::make_pair(eventId, eventName));
m_saveData.SignalDirty();
}
}
// If we are wrapping the same node twice for just ignore it and log a message
else if (emplaceResult.first->second != wrappedNode)
{
AZ_Error("ScriptCanvas", false, "Trying to wrap two identically named methods under the same EBus Handler. Deleting the second node.");
AZ::EntityId sceneId;
GraphCanvas::SceneMemberRequestBus::EventResult(sceneId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
AZStd::unordered_set<AZ::EntityId> deleteNodes;
deleteNodes.insert(wrappedNode);
GraphCanvas::SceneRequestBus::Event(sceneId, &GraphCanvas::SceneRequests::Delete, deleteNodes);
}
else
{
AZ_Warning("ScriptCanvas", false, "Trying to wrap the same node twice.");
}
}
void ScriptEventReceiverNodeDescriptorComponent::OnUnwrappedNode(const AZ::EntityId& unwrappedNode)
{
auto iter = m_idToEventType.find(unwrappedNode);
if (iter != m_idToEventType.end())
{
ScriptCanvas::EBusEventId eventId = iter->second;
m_eventTypeToId.erase(iter->second);
m_idToEventType.erase(iter);
for (auto eventIter = m_saveData.m_enabledEvents.begin(); eventIter != m_saveData.m_enabledEvents.end(); ++eventIter)
{
if (eventIter->first == eventId)
{
m_saveData.m_enabledEvents.erase(eventIter);
m_saveData.SignalDirty();
break;
}
}
}
}
GraphCanvas::WrappedNodeConfiguration ScriptEventReceiverNodeDescriptorComponent::GetWrappedNodeConfiguration(const AZ::EntityId& wrappedNodeId) const
{
ScriptEvents::Method methodDefinition;
ScriptEventReceiverEventNodeDescriptorBus::EventResult(methodDefinition, wrappedNodeId, &ScriptEventReceiverEventNodeDescriptorRequests::GetMethodDefinition);
if (methodDefinition.GetName().empty())
{
return GraphCanvas::WrappedNodeConfiguration();
}
else
{
return GetEventConfiguration(AZ::Crc32(methodDefinition.GetNameProperty().GetId().ToString<AZStd::string>().c_str()));
}
}
AZ::Component* ScriptEventReceiverNodeDescriptorComponent::GetPropertyComponent()
{
return this;
}
void ScriptEventReceiverNodeDescriptorComponent::OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset)
{
AZ::EntityId graphCanvasGraphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphCanvasGraphId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
ScriptCanvas::ScriptCanvasId scriptCanvasId;
GeneralRequestBus::BroadcastResult(scriptCanvasId, &GeneralRequests::GetScriptCanvasId, graphCanvasGraphId);
EditorGraphRequestBus::Event(scriptCanvasId, &EditorGraphRequests::QueueVersionUpdate, GetEntityId());
}
void ScriptEventReceiverNodeDescriptorComponent::OnVersionConversionBegin()
{
DynamicSlotRequestBus::Event(GetEntityId(), &DynamicSlotRequests::StartQueueSlotUpdates);
}
void ScriptEventReceiverNodeDescriptorComponent::OnVersionConversionEnd()
{
AZ::EntityId graphCanvasGraphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphCanvasGraphId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
ScriptCanvas::ScriptCanvasId scriptCanvasId;
GeneralRequestBus::BroadcastResult(scriptCanvasId, &GeneralRequests::GetScriptCanvasId, graphCanvasGraphId);
AZStd::vector< GraphCanvas::NodeId > wrappedNodes;
GraphCanvas::WrapperNodeRequestBus::EventResult(wrappedNodes, GetEntityId(), &GraphCanvas::WrapperNodeRequests::GetWrappedNodeIds);
AZStd::unordered_set< AZ::EntityId > deletedNodes;
deletedNodes.insert(wrappedNodes.begin(), wrappedNodes.end());
AZStd::vector<AZStd::pair<ScriptCanvas::EBusEventId, AZStd::string>> enabledEvents = m_saveData.m_enabledEvents;
GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::Delete, deletedNodes);
AZ::Data::Asset<ScriptEvents::ScriptEventsAsset> asset = AZ::Data::AssetManager::Instance().GetAsset<ScriptEvents::ScriptEventsAsset>(m_scriptEventsAssetId, AZ::Data::AssetLoadBehavior::Default);
asset.BlockUntilLoadComplete();
AZ_Error("ScriptCanvas", asset.IsReady(), "Trying to work on asset that isn't ready after a blocking load.");
UpdateTitles(asset);
ScriptEventReceiveNodeDescriptorNotificationBus::Event(GetEntityId(), &ScriptEventReceiveNodeDescriptorNotifications::OnScriptEventReloaded, asset);
const ScriptEvents::ScriptEvent& definition = asset.Get()->m_definition;
for (auto eventToRecreate : enabledEvents)
{
ScriptEvents::Method outMethod;
if (definition.FindMethod(eventToRecreate.first, outMethod))
{
AZ::EntityId graphCanvasNodeId = Nodes::DisplayScriptEventNode(graphCanvasGraphId, m_scriptEventsAssetId, outMethod);
if (graphCanvasNodeId.IsValid())
{
GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::Add, graphCanvasNodeId);
GraphCanvas::WrappedNodeConfiguration configuration = GetWrappedNodeConfiguration(graphCanvasNodeId);
GraphCanvas::WrapperNodeRequestBus::Event(GetEntityId(), &GraphCanvas::WrapperNodeRequests::WrapNode, graphCanvasNodeId, configuration);
}
}
}
DynamicSlotRequestBus::Event(GetEntityId(), &DynamicSlotRequests::StopQueueSlotUpdates);
}
void ScriptEventReceiverNodeDescriptorComponent::OnAddedToGraphCanvasGraph([[maybe_unused]] const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId)
{
m_scriptCanvasId = scriptCanvasNodeId;
GraphCanvas::WrapperNodeRequestBus::Event(GetEntityId(), &GraphCanvas::WrapperNodeRequests::SetActionString, "Add/Remove Events");
GraphCanvas::SlotLayoutRequestBus::Event(GetEntityId(), &GraphCanvas::SlotLayoutRequests::SetSlotGroupVisible, SlotGroups::EBusConnectionSlotGroup, m_saveData.m_displayConnections);
if (m_scriptCanvasId.IsValid())
{
EditorNodeNotificationBus::Handler::BusConnect(m_scriptCanvasId);
AZ::Entity* entity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, m_scriptCanvasId);
if (entity)
{
ScriptCanvas::Nodes::Core::ReceiveScriptEvent* eventHandler = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::ReceiveScriptEvent>(entity);
if (eventHandler && eventHandler->IsIDRequired())
{
AZStd::vector< AZ::EntityId > slotIds;
GraphCanvas::NodeRequestBus::EventResult(slotIds, GetEntityId(), &GraphCanvas::NodeRequests::GetSlotIds);
// Should be exactly one data slot on ourselves. And that is the BusId
for (const AZ::EntityId& testSlotId : slotIds)
{
GraphCanvas::SlotType slotType;
GraphCanvas::SlotRequestBus::EventResult(slotType, testSlotId, &GraphCanvas::SlotRequests::GetSlotType);
if (slotType == GraphCanvas::SlotTypes::DataSlot)
{
GraphCanvas::SlotRequestBus::Event(testSlotId, &GraphCanvas::SlotRequests::SetTranslationKeyedName, TranslationHelper::GetEBusHandlerBusIdNameKey());
GraphCanvas::SlotRequestBus::Event(testSlotId, &GraphCanvas::SlotRequests::SetTranslationKeyedTooltip, TranslationHelper::GetEBusHandlerBusIdTooltipKey());
break;
}
}
}
}
}
AZ::Data::Asset<ScriptEvents::ScriptEventsAsset> asset = AZ::Data::AssetManager::Instance().GetAsset<ScriptEvents::ScriptEventsAsset>(m_scriptEventsAssetId, AZ::Data::AssetLoadBehavior::Default);
asset.BlockUntilLoadComplete();
if (asset.IsReady())
{
UpdateTitles(asset);
}
}
void ScriptEventReceiverNodeDescriptorComponent::OnDisplayConnectionsChanged()
{
AZ::Entity* entity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationBus::Events::FindEntity, m_scriptCanvasId);
if (entity)
{
ScriptCanvas::Nodes::Core::ReceiveScriptEvent* eventHandler = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::ReceiveScriptEvent>(entity);
if (eventHandler)
{
// If we are hiding the connections, we need to confirm that
// everything will be ok(i.e. no active connections)
if (!m_saveData.m_displayConnections)
{
AZStd::vector< ScriptCanvas::SlotId > scriptCanvasSlots = eventHandler->GetNonEventSlotIds();
bool allowChange = true;
for (const auto& slotId : scriptCanvasSlots)
{
ScriptCanvas::Slot* slot = eventHandler->GetSlot(slotId);
if (slot->IsExecution() && eventHandler->IsConnected((*slot)))
{
allowChange = false;
break;
}
}
if (!allowChange)
{
AZ_Warning("Script Canvas", false, "Cannot hide EBus Connection Controls because one ore more slots are currently connected. Please disconnect all slots to hide.");
m_saveData.m_displayConnections = true;
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
}
eventHandler->SetAutoConnectToGraphOwner(!m_saveData.m_displayConnections);
}
}
GraphCanvas::SlotLayoutRequestBus::Event(GetEntityId(), &GraphCanvas::SlotLayoutRequests::SetSlotGroupVisible, SlotGroups::EBusConnectionSlotGroup, m_saveData.m_displayConnections);
}
void ScriptEventReceiverNodeDescriptorComponent::UpdateTitles(const AZ::Data::Asset<ScriptEvents::ScriptEventsAsset>& asset)
{
if (asset.IsReady())
{
const ScriptEvents::ScriptEvent& definition = asset.Get()->m_definition;
GraphCanvas::NodeRequestBus::Event(GetEntityId(), &GraphCanvas::NodeRequests::SetTooltip, definition.GetTooltip());
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetTitle, definition.GetName());
}
}
}
@@ -0,0 +1,154 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <GraphCanvas/Components/Nodes/Wrapper/WrapperNodeBus.h>
#include <GraphCanvas/Components/GraphCanvasPropertyBus.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/EntitySaveDataBus.h>
#include <GraphCanvas/Types/EntitySaveData.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h>
#include <ScriptEvents/ScriptEventsAsset.h>
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
namespace ScriptCanvasEditor
{
class ScriptEventReceiverNodeDescriptorComponent
: public NodeDescriptorComponent
, public EBusHandlerNodeDescriptorRequestBus::Handler
, public ScriptEventReceiverNodeDescriptorRequestBus::Handler
, public GraphCanvas::WrapperNodeNotificationBus::Handler
, public GraphCanvas::GraphCanvasPropertyBusHandler
, public GraphCanvas::WrapperNodeConfigurationRequestBus::Handler
, public GraphCanvas::EntitySaveDataRequestBus::Handler
, public GraphCanvas::SceneMemberNotificationBus::Handler
, public AZ::Data::AssetBus::Handler
, public EditorNodeNotificationBus::Handler
{
public:
class ScriptEventReceiverHandlerNodeDescriptorSaveData
: public GraphCanvas::ComponentSaveData
{
public:
AZ_RTTI(ScriptEventReceiverHandlerNodeDescriptorSaveData, "{D8BBE799-7E4D-495A-B69A-1E3940670891}", GraphCanvas::ComponentSaveData);
AZ_CLASS_ALLOCATOR(ScriptEventReceiverHandlerNodeDescriptorSaveData, AZ::SystemAllocator, 0);
ScriptEventReceiverHandlerNodeDescriptorSaveData();
ScriptEventReceiverHandlerNodeDescriptorSaveData(ScriptEventReceiverNodeDescriptorComponent* component);
~ScriptEventReceiverHandlerNodeDescriptorSaveData() = default;
void operator=(const ScriptEventReceiverHandlerNodeDescriptorSaveData& other);
void OnDisplayConnectionsChanged();
bool m_displayConnections;
AZStd::vector<AZStd::pair<ScriptCanvas::EBusEventId, AZStd::string>> m_enabledEvents;
private:
ScriptEventReceiverNodeDescriptorComponent * m_callback;
};
friend class ScriptEventReceiverHandlerNodeDescriptorSaveData;
AZ_COMPONENT(ScriptEventReceiverNodeDescriptorComponent, "{FF9D3121-64B5-41C8-99D4-211528F39615}", NodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
ScriptEventReceiverNodeDescriptorComponent();
ScriptEventReceiverNodeDescriptorComponent(AZ::Data::AssetId assetId);
~ScriptEventReceiverNodeDescriptorComponent() = default;
void Activate() override;
void Deactivate() override;
// NodeNotifications
void OnNodeActivated() override;
////
// SceneMemberNotifications
void OnMemberSetupComplete() override;
void OnSceneMemberDeserialized(const AZ::EntityId& graphId, const GraphCanvas::GraphSerialization&) override;
////
// GraphCanvas::EntitySaveDataRequestBus::Handler
void WriteSaveData(GraphCanvas::EntitySaveDataContainer& saveDataContainer) const override;
void ReadSaveData(const GraphCanvas::EntitySaveDataContainer& saveDataContainer) override;
////
// ScriptEventReceiverNodeDescriptorRequests
AZ::Data::AssetId GetAssetId() const override;
////
// EBusHandlerNodeDescriptorRequestBus
AZStd::string_view GetBusName() const override;
bool ContainsEvent(const ScriptCanvas::EBusEventId& eventId) const override;
GraphCanvas::WrappedNodeConfiguration GetEventConfiguration(const ScriptCanvas::EBusEventId& eventId) const override;
AZStd::vector< HandlerEventConfiguration > GetEventConfigurations() const override;
AZ::EntityId FindEventNodeId(const ScriptCanvas::EBusEventId& eventId) const override;
AZ::EntityId FindGraphCanvasNodeIdForSlot(const ScriptCanvas::SlotId& slotId) const override;
GraphCanvas::Endpoint MapSlotToGraphCanvasEndpoint(const ScriptCanvas::SlotId& slotId) const override;
////
// WrapperNodeNotificationBus
void OnWrappedNode(const AZ::EntityId& wrappedNode) override;
void OnUnwrappedNode(const AZ::EntityId& unwrappedNode) override;
////
// WrapperNodeConfigurationRequests
GraphCanvas::WrappedNodeConfiguration GetWrappedNodeConfiguration(const AZ::EntityId& wrappedNodeId) const override;
////
// GraphCanvasPropertyBus
AZ::Component* GetPropertyComponent() override;
////
// AZ::Data::AssetBus::Handler
void OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
////
// EditorNodeNotificationBus::Handler
void OnVersionConversionBegin() override;
void OnVersionConversionEnd() override;
////
protected:
void OnAddedToGraphCanvasGraph(const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId) override;
private:
void OnDisplayConnectionsChanged();
void UpdateTitles(const AZ::Data::Asset<ScriptEvents::ScriptEventsAsset>& asset);
ScriptEventReceiverHandlerNodeDescriptorSaveData m_saveData;
AZ::Crc32 m_busId;
AZStd::string m_busName;
bool m_loadingEvents;
AZ::Data::AssetId m_scriptEventsAssetId;
ScriptEvents::Method m_methodDefinition;
AZ::EntityId m_scriptCanvasId;
using EventKey = AZStd::pair<AZ::Uuid, AZStd::string>;
AZStd::unordered_map<ScriptCanvas::EBusEventId, AZ::EntityId> m_eventTypeToId;
AZStd::unordered_map<AZ::EntityId, ScriptCanvas::EBusEventId> m_idToEventType;
};
}
@@ -0,0 +1,173 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/Nodes/NodeTitleBus.h>
#include "ScriptEventSenderNodeDescriptorComponent.h"
#include "Editor/Translation/TranslationHelper.h"
#include "ScriptCanvas/Libraries/Core/Method.h"
#include <Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/GraphCanvas/DynamicSlotBus.h>
#include <ScriptCanvas/Libraries/Core/ScriptEventBase.h>
namespace ScriptCanvasEditor
{
/////////////////////////////////////////////
// ScriptEventSenderNodeDescriptorComponent
/////////////////////////////////////////////
void ScriptEventSenderNodeDescriptorComponent::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<ScriptEventSenderNodeDescriptorComponent, NodeDescriptorComponent>()
->Version(1)
;
}
}
ScriptEventSenderNodeDescriptorComponent::ScriptEventSenderNodeDescriptorComponent()
: NodeDescriptorComponent(NodeDescriptorType::EBusSender)
{
}
ScriptEventSenderNodeDescriptorComponent::ScriptEventSenderNodeDescriptorComponent(const AZ::Data::AssetId& assetId, const ScriptCanvas::EBusEventId& eventId)
: NodeDescriptorComponent(NodeDescriptorType::EBusSender)
, m_assetId(assetId)
, m_eventId(eventId)
{
}
void ScriptEventSenderNodeDescriptorComponent::Activate()
{
NodeDescriptorComponent::Activate();
AZ::Data::AssetBus::Handler::BusConnect(m_assetId);
}
void ScriptEventSenderNodeDescriptorComponent::Deactivate()
{
NodeDescriptorComponent::Deactivate();
AZ::Data::AssetBus::Handler::BusDisconnect();
}
void ScriptEventSenderNodeDescriptorComponent::OnAssetUnloaded([[maybe_unused]] const AZ::Data::AssetId assetId, [[maybe_unused]] const AZ::Data::AssetType assetType)
{
SignalNeedsVersionConversion();
}
void ScriptEventSenderNodeDescriptorComponent::OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset)
{
SignalNeedsVersionConversion();
}
void ScriptEventSenderNodeDescriptorComponent::OnVersionConversionBegin()
{
DynamicSlotRequestBus::Event(GetEntityId(), &DynamicSlotRequests::StartQueueSlotUpdates);
}
void ScriptEventSenderNodeDescriptorComponent::OnVersionConversionEnd()
{
UpdateTitles();
DynamicSlotRequestBus::Event(GetEntityId(), &DynamicSlotRequests::StopQueueSlotUpdates);
}
void ScriptEventSenderNodeDescriptorComponent::OnAddedToGraphCanvasGraph([[maybe_unused]] const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId)
{
m_scriptCanvasId = scriptCanvasNodeId;
EditorNodeNotificationBus::Handler::BusConnect(scriptCanvasNodeId);
ScriptCanvas::Nodes::Core::Method* method = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Nodes::Core::Method>(m_scriptCanvasId);
if (method)
{
if (method->HasBusID())
{
ScriptCanvas::SlotId slotId = method->GetBusSlotId();
AZStd::vector< AZ::EntityId > graphCanvasSlots;
GraphCanvas::NodeRequestBus::EventResult(graphCanvasSlots, GetEntityId(), &GraphCanvas::NodeRequests::GetSlotIds);
for (const AZ::EntityId& graphCanvasId : graphCanvasSlots)
{
AZStd::any* slotData = nullptr;
GraphCanvas::SlotRequestBus::EventResult(slotData, graphCanvasId, &GraphCanvas::SlotRequests::GetUserData);
if (slotData
&& slotData->is< ScriptCanvas::SlotId >())
{
ScriptCanvas::SlotId currentSlotId = (*AZStd::any_cast<ScriptCanvas::SlotId>(slotData));
if (currentSlotId == slotId)
{
GraphCanvas::SlotRequestBus::Event(graphCanvasId, &GraphCanvas::SlotRequests::SetTranslationKeyedName, TranslationHelper::GetEBusSenderBusIdNameKey());
GraphCanvas::SlotRequestBus::Event(graphCanvasId, &GraphCanvas::SlotRequests::SetTranslationKeyedTooltip, TranslationHelper::GetEBusSenderBusIdTooltipKey());
break;
}
}
}
}
}
UpdateTitles();
}
void ScriptEventSenderNodeDescriptorComponent::UpdateTitles()
{
if (m_assetId.IsValid())
{
AZ::Data::Asset<ScriptEvents::ScriptEventsAsset> asset = AZ::Data::AssetManager::Instance().GetAsset<ScriptEvents::ScriptEventsAsset>(m_assetId, AZ::Data::AssetLoadBehavior::Default);
asset.BlockUntilLoadComplete();
if (asset.IsReady())
{
const ScriptEvents::ScriptEvent& definition = asset.Get()->m_definition;
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetSubTitle, definition.GetName());
for (auto eventDefinition : definition.GetMethods())
{
if (eventDefinition.GetEventId() == m_eventId)
{
GraphCanvas::NodeRequestBus::Event(GetEntityId(), &GraphCanvas::NodeRequests::SetTooltip, eventDefinition.GetTooltip());
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetTitle, eventDefinition.GetName());
}
}
}
}
}
void ScriptEventSenderNodeDescriptorComponent::SignalNeedsVersionConversion()
{
AZ::EntityId graphCanvasGraphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphCanvasGraphId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
ScriptCanvas::ScriptCanvasId scriptCanvasId;
GeneralRequestBus::BroadcastResult(scriptCanvasId, &GeneralRequests::GetScriptCanvasId, graphCanvasGraphId);
EditorGraphRequestBus::Event(scriptCanvasId, &EditorGraphRequests::QueueVersionUpdate, GetEntityId());
}
}
@@ -0,0 +1,64 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h>
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <ScriptEvents/ScriptEventsAsset.h>
namespace ScriptCanvasEditor
{
class ScriptEventSenderNodeDescriptorComponent
: public NodeDescriptorComponent
, public AZ::Data::AssetBus::Handler
, public EditorNodeNotificationBus::Handler
{
public:
AZ_COMPONENT(ScriptEventSenderNodeDescriptorComponent, "{7EB63D67-4F32-40E5-8B15-4C3E28D886F9}", NodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
ScriptEventSenderNodeDescriptorComponent();
ScriptEventSenderNodeDescriptorComponent(const AZ::Data::AssetId& assetId, const ScriptCanvas::EBusEventId& eventId);
~ScriptEventSenderNodeDescriptorComponent() = default;
// Component
void Activate() override;
void Deactivate() override;
////
// AZ::Data::AssetBus::Handler
void OnAssetUnloaded(const AZ::Data::AssetId assetId, const AZ::Data::AssetType assetType) override;
void OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
////
// VersionControlledNodeRequestBus::Handler
void OnVersionConversionBegin() override;
void OnVersionConversionEnd() override;
////
protected:
void OnAddedToGraphCanvasGraph(const GraphCanvas::GraphId& graphId, const AZ::EntityId& scriptCanvasNodeId) override;
private:
void UpdateTitles();
void SignalNeedsVersionConversion();
AZ::EntityId m_scriptCanvasId;
AZ::Data::AssetId m_assetId;
ScriptCanvas::EBusEventId m_eventId;
};
}
@@ -0,0 +1,55 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Component/ComponentApplicationBus.h>
#include <GraphCanvas/Components/Nodes/NodeTitleBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/SetVariableNodeDescriptorComponent.h>
#include <Editor/Translation/TranslationHelper.h>
#include <Editor/View/Widgets/PropertyGridBus.h>
#include <ScriptCanvas/Libraries/Core/SetVariable.h>
#include <ScriptCanvas/Variable/VariableData.h>
namespace ScriptCanvasEditor
{
///////////////////////////////////////
// SetVariableNodeDescriptorComponent
///////////////////////////////////////
void SetVariableNodeDescriptorComponent::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<SetVariableNodeDescriptorComponent, NodeDescriptorComponent>()
->Version(1)
;
}
}
SetVariableNodeDescriptorComponent::SetVariableNodeDescriptorComponent()
: VariableNodeDescriptorComponent(NodeDescriptorType::SetVariable)
{
}
void SetVariableNodeDescriptorComponent::UpdateTitle(AZStd::string_view variableName)
{
AZStd::string titleName = AZStd::string::format("Set %s", variableName.data());
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetTitle, titleName);
}
}
@@ -0,0 +1,34 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/VariableNodeDescriptorComponent.h>
#include <ScriptCanvas/Variable/VariableBus.h>
namespace ScriptCanvasEditor
{
class SetVariableNodeDescriptorComponent
: public VariableNodeDescriptorComponent
{
public:
AZ_COMPONENT(SetVariableNodeDescriptorComponent, "{5C1183AC-09E9-4D43-A6F4-76B4F3EE18ED}", VariableNodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
SetVariableNodeDescriptorComponent();
protected:
void UpdateTitle(AZStd::string_view variableName) override;
};
}
@@ -0,0 +1,40 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Serialization/SerializeContext.h>
#include "UserDefinedNodeDescriptorComponent.h"
namespace ScriptCanvasEditor
{
///////////////////////////////////////
// UserDefinedNodeDescriptorComponent
///////////////////////////////////////
void UserDefinedNodeDescriptorComponent::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<UserDefinedNodeDescriptorComponent, NodeDescriptorComponent>()
->Version(2)
;
}
}
UserDefinedNodeDescriptorComponent::UserDefinedNodeDescriptorComponent()
: NodeDescriptorComponent(NodeDescriptorType::UserDefined)
{
}
}
@@ -0,0 +1,28 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include "Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h"
namespace ScriptCanvasEditor
{
class UserDefinedNodeDescriptorComponent
: public NodeDescriptorComponent
{
public:
AZ_COMPONENT(UserDefinedNodeDescriptorComponent, "{24109899-2026-4981-BFA1-38DB134246A2}", NodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
UserDefinedNodeDescriptorComponent();
~UserDefinedNodeDescriptorComponent() = default;
};
}
@@ -0,0 +1,245 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include <AzCore/Component/ComponentApplicationBus.h>
#include <GraphCanvas/Components/Connections/ConnectionBus.h>
#include <GraphCanvas/Components/Nodes/NodeTitleBus.h>
#include <GraphCanvas/Components/SceneBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/VariableNodeDescriptorComponent.h>
#include <Editor/Include/ScriptCanvas/Bus/RequestBus.h>
#include <Editor/Translation/TranslationHelper.h>
#include <Editor/View/Widgets/PropertyGridBus.h>
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <ScriptCanvas/Bus/RequestBus.h>
namespace ScriptCanvasEditor
{
////////////////////////////////////
// VariableNodeDescriptorComponent
////////////////////////////////////
void VariableNodeDescriptorComponent::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<VariableNodeDescriptorComponent, NodeDescriptorComponent>()
->Version(1)
;
}
}
VariableNodeDescriptorComponent::VariableNodeDescriptorComponent(NodeDescriptorType descriptorType)
: NodeDescriptorComponent(descriptorType)
{
}
void VariableNodeDescriptorComponent::Activate()
{
NodeDescriptorComponent::Activate();
GraphCanvas::SceneMemberNotificationBus::Handler::BusConnect(GetEntityId());
VariableNodeDescriptorRequestBus::Handler::BusConnect(GetEntityId());
}
void VariableNodeDescriptorComponent::Deactivate()
{
ScriptCanvas::VariableNodeNotificationBus::Handler::BusDisconnect();
VariableNodeDescriptorRequestBus::Handler::BusDisconnect();
GraphCanvas::SceneMemberNotificationBus::Handler::BusDisconnect();
NodeDescriptorComponent::Deactivate();
}
void VariableNodeDescriptorComponent::OnVariableRenamed(AZStd::string_view variableName)
{
UpdateTitle(variableName);
}
void VariableNodeDescriptorComponent::OnVariableRemoved()
{
AZ_Error("ScriptCanvas", false, "Removing a variable from node that is still in use. Deleting node");
AZStd::unordered_set< AZ::EntityId > deleteIds = { GetEntityId() };
AZ::EntityId graphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphId, GetEntityId(), &GraphCanvas::SceneMemberRequests::GetScene);
// After this call the component is no longer valid.
GraphCanvas::SceneRequestBus::Event(graphId, &GraphCanvas::SceneRequests::Delete, deleteIds);
}
void VariableNodeDescriptorComponent::OnVariableIdChanged(const ScriptCanvas::VariableId& /*oldVariableId*/, const ScriptCanvas::VariableId& newVariableId)
{
ScriptCanvas::ScriptCanvasId scriptCanvasId;
AZ::EntityId scriptCanvasNodeId = FindScriptCanvasNodeId();
ScriptCanvas::NodeRequestBus::EventResult(scriptCanvasId, scriptCanvasNodeId, &ScriptCanvas::NodeRequests::GetOwningScriptCanvasId);
ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
ScriptCanvas::GraphScopedVariableId newScopedVariableId = ScriptCanvas::GraphScopedVariableId(scriptCanvasId, newVariableId);
ScriptCanvas::VariableNotificationBus::Handler::BusConnect(newScopedVariableId);
ScriptCanvas::Data::Type scriptCanvasType;
ScriptCanvas::VariableRequestBus::EventResult(scriptCanvasType, newScopedVariableId, &ScriptCanvas::VariableRequests::GetType);
const AZStd::string typeName = TranslationHelper::GetSafeTypeName(scriptCanvasType);
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetSubTitle, typeName);
AZ::Uuid dataType = ScriptCanvas::Data::ToAZType(scriptCanvasType);
GraphCanvas::NodeTitleRequestBus::Event(GetEntityId(), &GraphCanvas::NodeTitleRequests::SetDataPaletteOverride, dataType);
AZStd::string_view variableName;
ScriptCanvas::VariableRequestBus::EventResult(variableName, newScopedVariableId, &ScriptCanvas::VariableRequests::GetName);
UpdateTitle(variableName);
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RebuildPropertyGrid);
}
void VariableNodeDescriptorComponent::OnAddedToGraphCanvasGraph([[maybe_unused]] const AZ::EntityId& sceneId, const AZ::EntityId& scriptCanvasNodeId)
{
OnVariableIdChanged({}, GetVariableId());
ScriptCanvas::VariableNodeNotificationBus::Handler::BusConnect(scriptCanvasNodeId);
}
void VariableNodeDescriptorComponent::OnSceneMemberAboutToSerialize(GraphCanvas::GraphSerialization& graphSerialization)
{
auto& userDataMapRef = graphSerialization.GetUserDataMapRef();
auto mapIter = userDataMapRef.find(ScriptCanvas::CopiedVariableData::k_variableKey);
ScriptCanvas::GraphVariableMapping* variableConfigurations = nullptr;
if (mapIter == userDataMapRef.end())
{
ScriptCanvas::CopiedVariableData variableData;
auto insertResult = userDataMapRef.emplace(ScriptCanvas::CopiedVariableData::k_variableKey, variableData);
ScriptCanvas::CopiedVariableData* copiedVariableData = AZStd::any_cast<ScriptCanvas::CopiedVariableData>(&insertResult.first->second);
variableConfigurations = (&copiedVariableData->m_variableMapping);
}
else
{
ScriptCanvas::CopiedVariableData* copiedVariableData = AZStd::any_cast<ScriptCanvas::CopiedVariableData>(&mapIter->second);
variableConfigurations = (&copiedVariableData->m_variableMapping);
}
ScriptCanvas::VariableId variableId = GetVariableId();
if (variableConfigurations->find(variableId) == variableConfigurations->end())
{
ScriptCanvas::ScriptCanvasId scriptCanvasId;
GeneralRequestBus::BroadcastResult(scriptCanvasId, &GeneralRequests::GetActiveScriptCanvasId);
ScriptCanvas::GraphVariable* configuration = nullptr;
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(configuration, scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::FindVariableById, variableId);
if (configuration)
{
variableConfigurations->emplace(GetVariableId(), (*configuration));
}
}
}
void VariableNodeDescriptorComponent::OnSceneMemberDeserialized(const AZ::EntityId& graphCanvasGraphId, const GraphCanvas::GraphSerialization& graphSerialization)
{
ScriptCanvas::ScriptCanvasId scriptCanvasId;
GeneralRequestBus::BroadcastResult(scriptCanvasId, &GeneralRequests::GetScriptCanvasId, graphCanvasGraphId);
ScriptCanvas::GraphVariable* graphVariable = nullptr;
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(graphVariable, scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::FindVariableById, GetVariableId());
// If the variable is null. We need to create it from our copied data.
if (graphVariable == nullptr)
{
const auto& userDataMapRef = graphSerialization.GetUserDataMapRef();
auto mapIter = userDataMapRef.find(ScriptCanvas::CopiedVariableData::k_variableKey);
if (mapIter != userDataMapRef.end())
{
const ScriptCanvas::CopiedVariableData* copiedVariableData = AZStd::any_cast<ScriptCanvas::CopiedVariableData>(&mapIter->second);
const ScriptCanvas::GraphVariableMapping* mapping = (&copiedVariableData->m_variableMapping);
ScriptCanvas::VariableId originalVariable = GetVariableId();
auto variableIter = mapping->find(originalVariable);
if (variableIter != mapping->end())
{
ScriptCanvas::ScriptCanvasId scriptCanvasId2;
GeneralRequestBus::BroadcastResult(scriptCanvasId2, &GeneralRequests::GetScriptCanvasId, graphCanvasGraphId);
const ScriptCanvas::GraphVariable& variableConfiguration = variableIter->second;
AZ::Outcome<ScriptCanvas::VariableId, AZStd::string> remapVariableOutcome = AZ::Failure(AZStd::string());
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(remapVariableOutcome, scriptCanvasId2, &ScriptCanvas::GraphVariableManagerRequests::RemapVariable, variableConfiguration);
if (remapVariableOutcome)
{
SetVariableId(remapVariableOutcome.GetValue());
bool runtimeGraph = false;
EditorGraphRequestBus::EventResult(runtimeGraph, scriptCanvasId2, &EditorGraphRequests::IsRuntimeGraph);
ScriptCanvas::GraphVariable* variable = nullptr;
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(variable, scriptCanvasId2, &ScriptCanvas::GraphVariableManagerRequests::FindVariableById, remapVariableOutcome.GetValue());
if (variable)
{
variable->RemoveScope(ScriptCanvas::VariableFlags::Scope::Output);
}
}
}
}
}
}
ScriptCanvas::VariableId VariableNodeDescriptorComponent::GetVariableId() const
{
ScriptCanvas::VariableId variableId;
AZStd::any* userData = nullptr;
GraphCanvas::NodeRequestBus::EventResult(userData, GetEntityId(), &GraphCanvas::NodeRequests::GetUserData);
AZ::EntityId* scNodeId = AZStd::any_cast<AZ::EntityId>(userData);
if (scNodeId)
{
ScriptCanvas::VariableNodeRequestBus::EventResult(variableId, *scNodeId, &ScriptCanvas::VariableNodeRequests::GetId);
}
return variableId;
}
void VariableNodeDescriptorComponent::UpdateTitle([[maybe_unused]] AZStd::string_view variableName)
{
AZ_Error("ScriptCanvas", false, "Should be pure virtual function, but Pure Virtual functions on components are disallowed.");
}
void VariableNodeDescriptorComponent::SetVariableId(const ScriptCanvas::VariableId& variableId)
{
AZStd::any* userData = nullptr;
GraphCanvas::NodeRequestBus::EventResult(userData, GetEntityId(), &GraphCanvas::NodeRequests::GetUserData);
AZ::EntityId* scNodeId = AZStd::any_cast<AZ::EntityId>(userData);
if (scNodeId)
{
ScriptCanvas::VariableNodeRequestBus::Event(*scNodeId, &ScriptCanvas::VariableNodeRequests::SetId, variableId);
}
}
}
@@ -0,0 +1,72 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <GraphCanvas/Components/SceneBus.h>
#include <Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h>
#include <ScriptCanvas/Variable/VariableBus.h>
#include <Editor/Include/ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
namespace ScriptCanvasEditor
{
class VariableNodeDescriptorComponent
: public NodeDescriptorComponent
, public GraphCanvas::SceneMemberNotificationBus::Handler
, public ScriptCanvas::VariableNotificationBus::Handler
, public ScriptCanvas::VariableNodeNotificationBus::Handler
, public VariableNodeDescriptorRequestBus::Handler
{
public:
AZ_COMPONENT(VariableNodeDescriptorComponent, "{80CB9400-E40D-4DC7-B185-412F766C8565}", NodeDescriptorComponent);
static void Reflect(AZ::ReflectContext* reflectContext);
VariableNodeDescriptorComponent() = default;
VariableNodeDescriptorComponent(NodeDescriptorType descriptorType);
~VariableNodeDescriptorComponent() = default;
// Component
void Activate() override;
void Deactivate() override;
////
// VariableNotificationBus
void OnVariableRenamed(AZStd::string_view variableName) override;
void OnVariableRemoved() override;
////
// VariableNodeNotificationBus
void OnVariableIdChanged(const ScriptCanvas::VariableId& oldVariableId, const ScriptCanvas::VariableId& newVariableId) override;
////
// SceneMemberNotifications
void OnSceneMemberAboutToSerialize(GraphCanvas::GraphSerialization& graphSerialization) override;
void OnSceneMemberDeserialized(const AZ::EntityId& graphId, const GraphCanvas::GraphSerialization& graphSerialization) override;
////
// VariableNodeDescriptorBus
ScriptCanvas::VariableId GetVariableId() const;
////
protected:
void OnAddedToGraphCanvasGraph(const AZ::EntityId& sceneId, const AZ::EntityId& scriptCanvasEntityId) override;
virtual void UpdateTitle(AZStd::string_view variableName);
private:
void SetVariableId(const ScriptCanvas::VariableId& variableId);
};
}
@@ -0,0 +1,83 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/NodePropertyDisplay/AssetIdDataInterface.h>
#include <Editor/GraphCanvas/DataInterfaces/ScriptCanvasDataInterface.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Slice/SliceAsset.h>
#include <QWidget>
#include <QMenu>
#include <QAction>
namespace ScriptCanvasEditor
{
class ScriptCanvasAssetIdDataInterface
: public ScriptCanvasDataInterface<GraphCanvas::AssetIdDataInterface>
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasAssetIdDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasAssetIdDataInterface(const AZ::EntityId& nodeId, const ScriptCanvas::SlotId& slotId)
: ScriptCanvasDataInterface(nodeId, slotId)
{
}
~ScriptCanvasAssetIdDataInterface() = default;
// AssetIdDataInterface
AZ::Data::AssetId GetAssetId() const override
{
const ScriptCanvas::Datum* object = GetSlotObject();
if (object)
{
const AZ::Data::AssetId* retVal = object->GetAs<AZ::Data::AssetId>();
if (retVal)
{
return (*retVal);
}
}
return AZ::Data::AssetId();
}
void SetAssetId(const AZ::Data::AssetId& assetId) override
{
ScriptCanvas::ModifiableDatumView datumView;
ModifySlotObject(datumView);
if (datumView.IsValid())
{
datumView.SetAs(assetId);
PostUndoPoint();
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
}
AZ::Data::AssetType GetAssetType() const override
{
return AZ::AzTypeInfo<AZ::DynamicSliceAsset>::Uuid(); //hardcoded for DynamicSliceAsset until the slot definitions can be queried for this
}
AZStd::string GetStringFilter() const override
{
return AZ::DynamicSliceAsset::GetFileFilter(); //hardcoded for DynamicSliceAsset until the slot definitions can be queried for this
}
////
};
}
@@ -0,0 +1,64 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/NodePropertyDisplay/BooleanDataInterface.h>
#include "ScriptCanvasDataInterface.h"
namespace ScriptCanvasEditor
{
class ScriptCanvasBoolDataInterface
: public ScriptCanvasDataInterface<GraphCanvas::BooleanDataInterface>
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasBoolDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasBoolDataInterface(const AZ::EntityId& nodeId, const ScriptCanvas::SlotId& slotId)
: ScriptCanvasDataInterface(nodeId, slotId)
{
}
~ScriptCanvasBoolDataInterface() = default;
// BooleanDataInterface
bool GetBool() const override
{
const ScriptCanvas::Datum* object = GetSlotObject();
if (object)
{
const bool* retVal = object->GetAs<bool>();
if (retVal)
{
return (*retVal);
}
}
return false;
}
void SetBool(bool enabled) override
{
ScriptCanvas::ModifiableDatumView datumView;
ModifySlotObject(datumView);
if (datumView.IsValid())
{
datumView.SetAs(enabled);
PostUndoPoint();
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
}
};
}
@@ -0,0 +1,80 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/NodePropertyDisplay/StringDataInterface.h>
#include "ScriptCanvasDataInterface.h"
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
namespace ScriptCanvasEditor
{
class ScriptCanvasCRCDataInterface
: public ScriptCanvasDataInterface<GraphCanvas::StringDataInterface>
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasCRCDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasCRCDataInterface(const AZ::EntityId& nodeId, const ScriptCanvas::SlotId& slotId)
: ScriptCanvasDataInterface(nodeId, slotId)
{
}
~ScriptCanvasCRCDataInterface() = default;
// StringDataInterface
AZStd::string GetString() const override
{
AZStd::string retVal;
const ScriptCanvas::Datum* object = GetSlotObject();
if (object && object->IS_A<AZ::Crc32>())
{
AZ::Crc32 crcValue = (*object->GetAs<AZ::Crc32>());
EditorGraphRequestBus::EventResult(retVal, GetScriptCanvasId(), &EditorGraphRequests::DecodeCrc, crcValue);
if (retVal.empty() && crcValue != AZ::Crc32())
{
AZ_Warning("ScriptCanvas", false, "Unknown CRC value. Cannot display cached string.");
retVal = AZStd::string::format("0x%X", static_cast<AZ::u32>(crcValue));
}
}
return retVal;
}
void SetString(const AZStd::string& value) override
{
ScriptCanvas::ModifiableDatumView datumView;
ModifySlotObject(datumView);
if (datumView.IsValid())
{
AZ::Crc32 newCrc = AZ::Crc32(value.c_str());
AZ::Crc32 oldCrc = (*datumView.GetAs<AZ::Crc32>());
if (oldCrc != newCrc)
{
EditorGraphRequestBus::Event(GetScriptCanvasId(), &EditorGraphRequests::RemoveCrcCache, oldCrc);
EditorGraphRequestBus::Event(GetScriptCanvasId(), &EditorGraphRequests::AddCrcCache, newCrc, value);
datumView.SetAs<ScriptCanvas::Data::CRCType>(newCrc);
PostUndoPoint();
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
}
}
////
};
}
@@ -0,0 +1,158 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Math/Color.h>
#include <GraphCanvas/Components/NodePropertyDisplay/VectorDataInterface.h>
#include "ScriptCanvasDataInterface.h"
namespace ScriptCanvasEditor
{
class ScriptCanvasColorDataInterface
: public ScriptCanvasDataInterface<GraphCanvas::VectorDataInterface>
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasColorDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasColorDataInterface(const AZ::EntityId& nodeId, const ScriptCanvas::SlotId& slotId)
: ScriptCanvasDataInterface(nodeId, slotId)
{
}
~ScriptCanvasColorDataInterface() = default;
int GetElementCount() const override
{
return 4;
}
double GetValue(int index) const override
{
if (index < GetElementCount())
{
const ScriptCanvas::Datum* object = GetSlotObject();
if (object)
{
const AZ::Color* retVal = object->GetAs<AZ::Color>();
if (retVal)
{
float resultValue = 0.0f;
switch (index)
{
case 0:
resultValue = aznumeric_cast<float>(static_cast<int>(static_cast<float>(retVal->GetR()) * GetMaximum(index)));
break;
case 1:
resultValue = aznumeric_cast<float>(static_cast<int>(static_cast<float>(retVal->GetG()) * GetMaximum(index)));
break;
case 2:
resultValue = aznumeric_cast<float>(static_cast<int>(static_cast<float>(retVal->GetB()) * GetMaximum(index)));
break;
case 3:
resultValue = aznumeric_cast<float>(static_cast<int>(static_cast<float>(retVal->GetA()) * GetMaximum(index)));
break;
default:
break;
}
return aznumeric_cast<double>(static_cast<float>(resultValue));
}
}
}
return 0.0;
}
void SetValue(int index, double value) override
{
if (index < GetElementCount())
{
ScriptCanvas::ModifiableDatumView datumView;
ModifySlotObject(datumView);
if (datumView.IsValid())
{
AZ::Color currentColor = (*datumView.GetAs<AZ::Color>());
switch (index)
{
case 0:
currentColor.SetR(aznumeric_cast<float>(value / GetMaximum(index)));
break;
case 1:
currentColor.SetG(aznumeric_cast<float>(value / GetMaximum(index)));
break;
case 2:
currentColor.SetB(aznumeric_cast<float>(value / GetMaximum(index)));
break;
case 3:
currentColor.SetA(aznumeric_cast<float>(value / GetMaximum(index)));
break;
default:
break;
}
datumView.SetAs(currentColor);
PostUndoPoint();
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
}
}
const char* GetLabel(int index) const override
{
switch (index)
{
case 0:
return "R";
case 1:
return "G";
case 2:
return "B";
case 3:
return "A";
default:
return "???";
}
}
AZStd::string GetStyle() const override
{
return "vectorized";
}
virtual AZStd::string GetElementStyle(int index) const
{
return AZStd::string::format("vector_%i", index);
}
int GetDecimalPlaces([[maybe_unused]] int index) const override
{
return 0;
}
double GetMinimum([[maybe_unused]] int index) const override
{
return 0.0;
}
double GetMaximum([[maybe_unused]] int index) const override
{
return 255.0;
}
};
}
@@ -0,0 +1,101 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/NodePropertyDisplay/DataInterface.h>
#include "ScriptCanvas/Core/Slot.h"
#include "ScriptCanvas/Core/NodeBus.h"
#include "ScriptCanvas/Core/Datum.h"
#include <Editor/View/Widgets/PropertyGridBus.h>
namespace ScriptCanvasEditor
{
template<class InterfaceType>
class ScriptCanvasDataInterface
: public ScriptCanvas::NodeNotificationsBus::Handler
, public InterfaceType
{
protected:
ScriptCanvasDataInterface(const AZ::EntityId& nodeId, const ScriptCanvas::SlotId& slotId)
: m_nodeId(nodeId)
, m_slotId(slotId)
{
static_assert((AZStd::is_base_of<GraphCanvas::DataInterface, InterfaceType>::value), "ScriptCanvasDataInterface given invalid GraphCanvas::DataInterface to inherit.");
ScriptCanvas::NodeNotificationsBus::Handler::BusConnect(nodeId);
}
using InterfaceType::SignalValueChanged;
public:
virtual ~ScriptCanvasDataInterface() = default;
const ScriptCanvas::ScriptCanvasId GetScriptCanvasId() const
{
ScriptCanvas::ScriptCanvasId scriptCanvasId;
ScriptCanvas::NodeRequestBus::EventResult(scriptCanvasId, GetNodeId(), &ScriptCanvas::NodeRequests::GetOwningScriptCanvasId);
return scriptCanvasId;
}
const GraphCanvas::GraphId GetGraphCanvasGraphId() const
{
GraphCanvas::GraphId graphCanvasGraphId;
GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::GetGraphCanvasGraphId, GetScriptCanvasId());
return graphCanvasGraphId;
}
const AZ::EntityId& GetNodeId() const
{
return m_nodeId;
}
const ScriptCanvas::SlotId& GetSlotId() const
{
return m_slotId;
}
const ScriptCanvas::Datum* GetSlotObject() const
{
const ScriptCanvas::Datum* object = nullptr;
ScriptCanvas::NodeRequestBus::EventResult(object, GetNodeId(), &ScriptCanvas::NodeRequests::FindDatum, GetSlotId());
return object;
}
void ModifySlotObject(ScriptCanvas::ModifiableDatumView& datumView)
{
ScriptCanvas::NodeRequestBus::Event(GetNodeId(), &ScriptCanvas::NodeRequests::FindModifiableDatumView, GetSlotId(), datumView);
}
// NodeNotificationsBus
void OnInputChanged(const ScriptCanvas::SlotId& slotId) override
{
if (slotId == m_slotId)
{
SignalValueChanged();
}
}
void PostUndoPoint()
{
GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, GetScriptCanvasId());
}
////
private:
AZ::EntityId m_nodeId;
ScriptCanvas::SlotId m_slotId;
};
}
@@ -0,0 +1,109 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/NodePropertyDisplay/EntityIdDataInterface.h>
#include "ScriptCanvasDataInterface.h"
#include <QWidget>
#include <QMenu>
#include <QAction>
namespace ScriptCanvasEditor
{
class ScriptCanvasEntityIdDataInterface
: public ScriptCanvasDataInterface<GraphCanvas::EntityIdDataInterface>
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasEntityIdDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasEntityIdDataInterface(const AZ::EntityId& nodeId, const ScriptCanvas::SlotId& slotId)
: ScriptCanvasDataInterface(nodeId, slotId)
{
}
~ScriptCanvasEntityIdDataInterface() = default;
// EntityIdDataInterface
AZ::EntityId GetEntityId() const override
{
const ScriptCanvas::Datum* object = GetSlotObject();
if (object)
{
const AZ::EntityId* retVal = object->GetAs<AZ::EntityId>();
if (retVal)
{
return (*retVal);
}
}
return AZ::EntityId();
}
const AZStd::string GetNameOverride() const override
{
const ScriptCanvas::Datum* object = GetSlotObject();
if (object && object->IS_A(ScriptCanvas::Data::Type::EntityID()))
{
const AZ::EntityId* entityId = object->GetAs<AZ::EntityId>();
if (entityId && *entityId == ScriptCanvas::GraphOwnerId)
{
return "Self";
}
}
return {};
}
void OnShowContextMenu(QWidget* nodePropertyDisplay, const QPoint& pos) override
{
QPoint globalPos = nodePropertyDisplay->mapToGlobal(pos);
enum EntityMenuAction
{
SetToSelf
};
QMenu entityMenu;
QAction* setToSelf = entityMenu.addAction("Set to Self");
setToSelf->setToolTip("Reset the EntityId to the Entity that owns this graph.");
setToSelf->setData(EntityMenuAction::SetToSelf);
QAction* selectedItem = entityMenu.exec(globalPos);
if (selectedItem)
{
if (selectedItem->data().toInt() == EntityMenuAction::SetToSelf)
{
SetEntityId(ScriptCanvas::GraphOwnerId);
}
}
}
void SetEntityId(const AZ::EntityId& entityId) override
{
ScriptCanvas::ModifiableDatumView datumView;
ModifySlotObject(datumView);
if (datumView.IsValid() && datumView.IsType(ScriptCanvas::Data::Type::EntityID()))
{
datumView.SetAs(entityId);
PostUndoPoint();
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
}
////
};
}
@@ -0,0 +1,100 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/NodePropertyDisplay/ComboBoxDataInterface.h>
#include <GraphCanvas/Widgets/ComboBox/ComboBoxItemModels.h>
#include "ScriptCanvasDataInterface.h"
namespace ScriptCanvasEditor
{
// Used for fixed values value input.
class ScriptCanvasEnumDataInterface
: public ScriptCanvasDataInterface<GraphCanvas::ComboBoxDataInterface>
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasEnumDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasEnumDataInterface(const AZ::EntityId& nodeId, const ScriptCanvas::SlotId& slotId)
: ScriptCanvasDataInterface(nodeId, slotId)
{
}
~ScriptCanvasEnumDataInterface() = default;
void AddElement(int32_t element, const AZStd::string& displayName)
{
QString qtName = displayName.c_str();
m_comboBoxModel.AddElement(element, qtName);
}
// GraphCanvas::ComboBoxDataInterface
GraphCanvas::ComboBoxItemModelInterface* GetItemInterface() override
{
return &m_comboBoxModel;
}
void AssignIndex(const QModelIndex& index) override
{
ScriptCanvas::ModifiableDatumView datumView;
ModifySlotObject(datumView);
if (datumView.IsValid())
{
int32_t value = m_comboBoxModel.GetValueForIndex(index);
datumView.SetAs(value);
PostUndoPoint();
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
}
QModelIndex GetAssignedIndex() const override
{
const ScriptCanvas::Datum* object = GetSlotObject();
if (object)
{
const int* element = object->GetAs<int>();
if (element)
{
return m_comboBoxModel.GetIndexForValue(*element);
}
}
return m_comboBoxModel.GetDefaultIndex();
}
const QString& GetDisplayString() const override
{
const ScriptCanvas::Datum* object = GetSlotObject();
if (object)
{
const int* element = object->GetAs<int>();
if (element)
{
return m_comboBoxModel.GetNameForValue((*element));
}
}
return GraphCanvas::ComboBoxDataInterface::GetDisplayString();
}
////
private:
GraphCanvas::GraphCanvasListComboBoxModel<int32_t> m_comboBoxModel;
};
}
@@ -0,0 +1,67 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/NodePropertyDisplay/ComboBoxDataInterface.h>
#include <GraphCanvas/Components/NodePropertyDisplay/NumericDataInterface.h>
#include "ScriptCanvasDataInterface.h"
namespace ScriptCanvasEditor
{
// Used for general numeric input.
class ScriptCanvasNumericDataInterface
: public ScriptCanvasDataInterface<GraphCanvas::NumericDataInterface>
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasNumericDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasNumericDataInterface(const AZ::EntityId& nodeId, const ScriptCanvas::SlotId& slotId)
: ScriptCanvasDataInterface(nodeId, slotId)
{
}
~ScriptCanvasNumericDataInterface() = default;
// NumericDataInterface
double GetNumber() const override
{
const ScriptCanvas::Datum* object = GetSlotObject();
if (object)
{
const double* retVal = object->GetAs<double>();
if (retVal)
{
return (*retVal);
}
}
return 0.0;
}
void SetNumber(double value) override
{
ScriptCanvas::ModifiableDatumView datumView;
ModifySlotObject(datumView);
if (datumView.IsValid())
{
datumView.SetAs(value);
PostUndoPoint();
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
}
////
};
}
@@ -0,0 +1,140 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Math/Transform.h>
#include <AzCore/Math/Quaternion.h>
#include <GraphCanvas/Components/NodePropertyDisplay/VectorDataInterface.h>
#include "ScriptCanvasDataInterface.h"
namespace ScriptCanvasEditor
{
class ScriptCanvasQuaternionDataInterface
: public ScriptCanvasDataInterface<GraphCanvas::VectorDataInterface>
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasQuaternionDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasQuaternionDataInterface(const AZ::EntityId& nodeId, const ScriptCanvas::SlotId& slotId)
: ScriptCanvasDataInterface(nodeId, slotId)
{
ConvertToEulerValues();
}
~ScriptCanvasQuaternionDataInterface() = default;
int GetElementCount() const override
{
return 3;
}
double GetValue(int index) const override
{
if (index < GetElementCount())
{
const ScriptCanvas::Datum* object = GetSlotObject();
if (object)
{
const AZ::Quaternion* retVal = object->GetAs<AZ::Quaternion>();
if (retVal)
{
return aznumeric_cast<double>(static_cast<float>(m_eulerAngles.GetElement(index)));
}
}
}
return 0.0;
}
void SetValue(int index, double value) override
{
if (index < GetElementCount())
{
ScriptCanvas::ModifiableDatumView datumView;
ModifySlotObject(datumView);
if (datumView.IsValid())
{
m_eulerAngles.SetElement(index, aznumeric_cast<float>(value));
AZ::Quaternion newValue = AZ::ConvertEulerDegreesToQuaternion(m_eulerAngles);
datumView.SetAs(newValue);
PostUndoPoint();
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
}
}
const char* GetLabel(int index) const override
{
switch (index)
{
case 0:
return "P";
case 1:
return "R";
case 2:
return "Y";
default:
return "???";
}
}
AZStd::string GetStyle() const override
{
return "vectorized";
}
AZStd::string GetElementStyle(int index) const override
{
return AZStd::string::format("quat_%i", index);
}
const char* GetSuffix([[maybe_unused]] int index) const override
{
return " deg";
}
void OnInputChanged(const ScriptCanvas::SlotId& slotId) override
{
if (slotId == GetSlotId())
{
ConvertToEulerValues();
}
ScriptCanvasDataInterface::OnInputChanged(slotId);
}
private:
void ConvertToEulerValues()
{
const ScriptCanvas::Datum* object = GetSlotObject();
if (object)
{
const AZ::Quaternion* quat = object->GetAs<AZ::Quaternion>();
if (quat)
{
m_eulerAngles = AZ::ConvertTransformToEulerDegrees(AZ::Transform::CreateFromQuaternion((*quat)));
}
}
}
AZ::Vector3 m_eulerAngles;
};
}
@@ -0,0 +1,48 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/NodePropertyDisplay/ReadOnlyDataInterface.h>
#include "ScriptCanvasDataInterface.h"
namespace ScriptCanvasEditor
{
class ScriptCanvasReadOnlyDataInterface
: public ScriptCanvasDataInterface<GraphCanvas::ReadOnlyDataInterface>
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasReadOnlyDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasReadOnlyDataInterface(const AZ::EntityId& nodeId, const ScriptCanvas::SlotId& slotId)
: ScriptCanvasDataInterface(nodeId, slotId)
{
}
~ScriptCanvasReadOnlyDataInterface() = default;
// ReadOnlyDataInterface
AZStd::string GetString() const override
{
AZStd::string retVal;
const ScriptCanvas::Datum* object = GetSlotObject();
if (object)
{
object->ToString(retVal);
}
return retVal;
}
////
};
}
@@ -0,0 +1,64 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/NodePropertyDisplay/StringDataInterface.h>
#include "ScriptCanvasDataInterface.h"
namespace ScriptCanvasEditor
{
class ScriptCanvasStringDataInterface
: public ScriptCanvasDataInterface<GraphCanvas::StringDataInterface>
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasStringDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasStringDataInterface(const AZ::EntityId& nodeId, const ScriptCanvas::SlotId& slotId)
: ScriptCanvasDataInterface(nodeId, slotId)
{
}
~ScriptCanvasStringDataInterface() = default;
// StringDataInterface
AZStd::string GetString() const override
{
AZStd::string retVal;
const ScriptCanvas::Datum* object = GetSlotObject();
if (object)
{
object->ToString(retVal);
}
return retVal;
}
void SetString(const AZStd::string& value) override
{
ScriptCanvas::ModifiableDatumView datumView;
ModifySlotObject(datumView);
const AZStd::string* string = datumView.GetAs<AZStd::string>();
if (string->compare(value) != 0)
{
datumView.SetAs<AZStd::string>(value);
PostUndoPoint();
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
}
////
};
}
@@ -0,0 +1,550 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/PlatformDef.h>
AZ_PUSH_DISABLE_WARNING(4251 4800 4244, "-Wunknown-warning-option")
#include <QString>
AZ_POP_DISABLE_WARNING
#include <GraphCanvas/Components/Connections/ConnectionBus.h>
#include <GraphCanvas/Components/NodePropertyDisplay/ComboBoxDataInterface.h>
#include <GraphCanvas/Components/Nodes/NodeTitleBus.h>
#include <GraphCanvas/Components/Slots/Data/DataSlotBus.h>
#include <GraphCanvas/Widgets/ComboBox/ComboBoxItemModels.h>
#include <GraphCanvas/Utils/QtMimeUtils.h>
#include <Editor/Include/ScriptCanvas/Bus/EditorSceneVariableManagerBus.h>
#include <Editor/Include/ScriptCanvas/Bus/RequestBus.h>
#include <Editor/Include/ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
#include <Editor/Include/ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
#include "ScriptCanvasDataInterface.h"
#include <ScriptCanvas/Core/Slot.h>
#include <ScriptCanvas/Core/Node.h>
#include <ScriptCanvas/Variable/VariableBus.h>
#include <ScriptCanvas/Utils/DataUtils.h>
namespace ScriptCanvasEditor
{
class VariableComboBoxDataModel
: public GraphCanvas::GraphCanvasListComboBoxModel<ScriptCanvas::VariableId>
, public ScriptCanvas::GraphVariableManagerNotificationBus::Handler
, public GeneralEditorNotificationBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(VariableComboBoxDataModel, AZ::SystemAllocator, 0);
VariableComboBoxDataModel()
{
}
~VariableComboBoxDataModel() override
{
ScriptCanvas::GraphVariableManagerNotificationBus::Handler::BusDisconnect();
GeneralEditorNotificationBus::Handler::BusDisconnect();
}
void Activate(const ScriptCanvas::ScriptCanvasId& scriptCanvasId)
{
m_scriptCanvasId = scriptCanvasId;
GeneralEditorNotificationBus::Handler::BusConnect(m_scriptCanvasId);
if (!IsInUndo())
{
FinalizeActivation();
}
}
// ScriptCanvas::GraphVariableManagerNotifications
void OnVariableAddedToGraph(const ScriptCanvas::VariableId& variableId, AZStd::string_view variableName) override
{
QString displayName = QString::fromUtf8(variableName.data(), static_cast<int>(variableName.size()));
AddElement(variableId, displayName);
}
void OnVariableRemovedFromGraph(const ScriptCanvas::VariableId& variableId, [[maybe_unused]] AZStd::string_view variableName) override
{
RemoveElement(variableId);
}
void OnVariableNameChangedInGraph(const ScriptCanvas::VariableId& variableId, AZStd::string_view variableName) override
{
RemoveElement(variableId);
OnVariableAddedToGraph(variableId, variableName);
}
////
// GeneralEditorNotifications
void OnUndoRedoBegin()
{
ScriptCanvas::GraphVariableManagerNotificationBus::Handler::BusDisconnect();
}
void OnUndoRedoEnd()
{
FinalizeActivation();
}
////
const ScriptCanvas::GraphVariable* GetGraphVariable(const ScriptCanvas::VariableId& variableId) const
{
const ScriptCanvas::GraphVariable* graphVariable = nullptr;
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(graphVariable, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::FindVariableById, variableId);
return graphVariable;
}
const ScriptCanvas::GraphVariable* GetGraphVariableForIndex(const QModelIndex& index) const
{
return GetGraphVariable(GetValueForIndex(index));
}
private:
void FinalizeActivation()
{
ScriptCanvas::GraphVariableManagerNotificationBus::Handler::BusConnect(m_scriptCanvasId);
const ScriptCanvas::GraphVariableMapping* graphVariables = nullptr;
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(graphVariables, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::GetVariables);
if (graphVariables)
{
ClearElements();
for (auto variablePair : (*graphVariables))
{
OnVariableAddedToGraph(variablePair.first, variablePair.second.GetVariableName());
}
}
}
bool IsInUndo() const
{
bool isInUndo = false;
GeneralRequestBus::BroadcastResult(isInUndo, &GeneralRequests::IsScriptCanvasInUndoRedo, m_scriptCanvasId);
return isInUndo;
}
ScriptCanvas::ScriptCanvasId m_scriptCanvasId;
};
class VariableTypeComboBoxFilterModel
: public GraphCanvas::GraphCanvasSortFilterComboBoxProxyModel
{
public:
AZ_CLASS_ALLOCATOR(VariableTypeComboBoxFilterModel, AZ::SystemAllocator, 0);
VariableTypeComboBoxFilterModel(const VariableComboBoxDataModel* sourceModel, ScriptCanvas::Slot* slot = nullptr)
: m_sourceModel(sourceModel)
, m_slotFilter(slot)
{
SetModelInterface(const_cast<VariableComboBoxDataModel*>(sourceModel));
}
void SetSlotFilter(ScriptCanvas::Slot* slotFilter)
{
if (m_slotFilter != slotFilter)
{
m_slotFilter = slotFilter;
if (sourceModel())
{
invalidateFilter();
}
}
}
void RefreshFilter()
{
if (sourceModel())
{
invalidateFilter();
}
}
bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
if (m_slotFilter == nullptr)
{
return true;
}
QModelIndex sourceIndex = m_sourceModel->index(sourceRow, VariableComboBoxDataModel::ColumnIndex::Name, sourceParent);
const ScriptCanvas::GraphVariable* variable = m_sourceModel->GetGraphVariableForIndex(sourceIndex);
if (variable)
{
auto dataType = variable->GetDatum()->GetType();
return m_slotFilter->IsTypeMatchFor(dataType).IsSuccess();
}
return false;
}
ScriptCanvas::VariableId GetValueForIndex(const QModelIndex& modelIndex) const
{
return m_sourceModel->GetValueForIndex(RemapToSourceIndex(modelIndex));
}
QModelIndex GetIndexForValue(const ScriptCanvas::VariableId& variableId) const
{
return RemapFromSourceIndex(m_sourceModel->GetIndexForValue(variableId));
}
const QString& GetDisplayName(const ScriptCanvas::VariableId& variableId) const
{
return m_sourceModel->GetNameForValue(variableId);
}
const ScriptCanvas::GraphVariable* GetGraphVariable(const ScriptCanvas::VariableId& variableId) const
{
return m_sourceModel->GetGraphVariable(variableId);
}
private:
const VariableComboBoxDataModel* m_sourceModel;
ScriptCanvas::Slot* m_slotFilter;
};
class ScriptCanvasGraphScopedVariableDataInterface
: public ScriptCanvasDataInterface<GraphCanvas::ComboBoxDataInterface>
, public ScriptCanvas::VariableNotificationBus::Handler
, public AZ::SystemTickBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasGraphScopedVariableDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasGraphScopedVariableDataInterface(const VariableComboBoxDataModel* variableDataModel, const AZ::EntityId& scriptCanvasGraphId, const AZ::EntityId& scriptCanvasNodeId, const ScriptCanvas::SlotId& scriptCanvasSlotId)
: ScriptCanvasDataInterface(scriptCanvasNodeId, scriptCanvasSlotId)
, m_scriptCanvasGraphId(scriptCanvasGraphId)
, m_variableTypeModel(variableDataModel)
{
RegisterBus();
}
~ScriptCanvasGraphScopedVariableDataInterface()
{
AZ::SystemTickBus::Handler::BusDisconnect();
ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
}
// SystemTickBus
void OnSystemTick()
{
AZ::SystemTickBus::Handler::BusDisconnect();
AssignIndex(m_variableTypeModel.GetDefaultIndex());
SignalValueChanged();
}
////
// VariableNotificationBus
void OnVariableRenamed([[maybe_unused]] AZStd::string_view newName) override
{
SignalValueChanged();
}
void OnVariableRemoved() override
{
// Delay this since its possible the model hasn't updated yet
AZ::SystemTickBus::Handler::BusConnect();
}
////
// ScriptCanvas::NodeNotificationsBus::Handler
void OnInputChanged(const ScriptCanvas::SlotId& slotId)
{
if (slotId == GetSlotId())
{
RegisterBus();
}
ScriptCanvasDataInterface<GraphCanvas::ComboBoxDataInterface>::OnInputChanged(slotId);
}
////
// GraphCanvas::ComboBoxModelInterface
GraphCanvas::ComboBoxItemModelInterface* GetItemInterface() override
{
return &m_variableTypeModel;
}
void AssignIndex(const QModelIndex& index) override
{
if (!index.isValid())
{
return;
}
ScriptCanvas::VariableId variableId = m_variableTypeModel.GetValueForIndex(index);
SetVariableId(variableId);
}
QModelIndex GetAssignedIndex() const override
{
const ScriptCanvas::Datum* datum = GetSlotObject();
const ScriptCanvas::GraphScopedVariableId* variableId = (datum ? datum->GetAs<ScriptCanvas::GraphScopedVariableId>() : nullptr);
if (variableId)
{
return m_variableTypeModel.GetIndexForValue(variableId->m_identifier);
}
return QModelIndex();
}
// Returns the string used to display the currently selected value[Used in the non-editable format]
const QString& GetDisplayString() const override
{
const ScriptCanvas::Datum* datum = GetSlotObject();
const ScriptCanvas::GraphScopedVariableId* variableId = (datum ? datum->GetAs<ScriptCanvas::GraphScopedVariableId>() : nullptr);
if (variableId)
{
return m_variableTypeModel.GetDisplayName(variableId->m_identifier);
}
return ComboBoxDataInterface::GetDisplayString();
}
void SetVariableId(const ScriptCanvas::VariableId& variableId)
{
ScriptCanvas::GraphScopedVariableId scopedVariableId;
scopedVariableId.m_identifier = variableId;
ScriptCanvas::ModifiableDatumView datumView;
ModifySlotObject(datumView);
datumView.SetAs<ScriptCanvas::GraphScopedVariableId>(scopedVariableId);
if (ScriptCanvas::VariableNotificationBus::Handler::BusIsConnected())
{
ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
}
scopedVariableId.m_scriptCanvasId = GetScriptCanvasId();
ScriptCanvas::VariableNotificationBus::Handler::BusConnect(scopedVariableId);
PostUndoPoint();
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
// DataInterfaceOverrides
bool EnableDropHandling() const override
{
return true;
}
AZ::Outcome<GraphCanvas::DragDropState> ShouldAcceptMimeData(const QMimeData* mimeData) override
{
if (mimeData->hasFormat(GraphCanvas::k_ReferenceMimeType))
{
return AZ::Success(GraphCanvas::DragDropState::Valid);
}
return AZ::Failure();
}
bool HandleMimeData(const QMimeData* mimeData) override
{
ScriptCanvas::VariableId variableId = GraphCanvas::QtMimeUtils::ExtractTypeFromMimeData<ScriptCanvas::VariableId>(mimeData, GraphCanvas::k_ReferenceMimeType);
SetVariableId(variableId);
return true;
}
//
private:
void RegisterBus()
{
if (ScriptCanvas::VariableNotificationBus::Handler::BusIsConnected())
{
ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
}
const ScriptCanvas::Datum* datum = GetSlotObject();
const ScriptCanvas::GraphScopedVariableId* variableId = (datum ? datum->GetAs<ScriptCanvas::GraphScopedVariableId>() : nullptr);
if (variableId)
{
ScriptCanvas::GraphScopedVariableId scopedVariableId = (*variableId);
scopedVariableId.m_scriptCanvasId = GetScriptCanvasId();
ScriptCanvas::VariableNotificationBus::Handler::BusConnect(scopedVariableId);
}
}
VariableTypeComboBoxFilterModel m_variableTypeModel;
AZ::EntityId m_scriptCanvasGraphId;
};
class ScriptCanvasVariableReferenceDataInterface
: public ScriptCanvasDataInterface<GraphCanvas::ComboBoxDataInterface>
, public ScriptCanvas::VariableNotificationBus::Handler
, public ScriptCanvas::EndpointNotificationBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasVariableReferenceDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasVariableReferenceDataInterface(const VariableComboBoxDataModel* variableDataModel, const AZ::EntityId& scriptCanvasGraphId, const AZ::EntityId& scriptCanvasNodeId, const ScriptCanvas::SlotId& scriptCanvasSlotId)
: ScriptCanvasDataInterface(scriptCanvasNodeId, scriptCanvasSlotId)
, m_scriptCanvasGraphId(scriptCanvasGraphId)
, m_variableTypeModel(variableDataModel)
{
ScriptCanvas::Slot* slot = GetSlot();
if (slot)
{
m_variableTypeModel.SetSlotFilter(slot);
ScriptCanvas::VariableId variableId = slot->GetVariableReference();
if (variableId.IsValid())
{
ScriptCanvas::VariableNotificationBus::Handler::BusConnect(ScriptCanvas::GraphScopedVariableId(m_scriptCanvasGraphId, variableId));
}
}
ScriptCanvas::EndpointNotificationBus::Handler::BusConnect(ScriptCanvas::Endpoint(scriptCanvasNodeId, scriptCanvasSlotId));
}
~ScriptCanvasVariableReferenceDataInterface()
{
ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
ScriptCanvas::EndpointNotificationBus::Handler::BusDisconnect();
}
// NodeNotificationBus
void OnSlotDisplayTypeChanged(const ScriptCanvas::SlotId& slotId, [[maybe_unused]] const ScriptCanvas::Data::Type& slotType)
{
if (slotId == GetSlotId())
{
m_variableTypeModel.RefreshFilter();
}
}
////
// VariableNotificationBus
void OnVariableRenamed([[maybe_unused]] AZStd::string_view newName) override
{
SignalValueChanged();
}
////
// EndpointNotificationBus
void OnEndpointReferenceChanged(const ScriptCanvas::VariableId& variableId)
{
ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
ScriptCanvas::VariableNotificationBus::Handler::BusConnect(ScriptCanvas::GraphScopedVariableId(GetScriptCanvasId(), variableId));
SignalValueChanged();
}
void OnSlotRecreated()
{
ScriptCanvas::Slot* slot = GetSlot();
if (slot)
{
m_variableTypeModel.SetSlotFilter(slot);
}
}
////
// GraphCanvas::ComboBoxModelInterface
GraphCanvas::ComboBoxItemModelInterface* GetItemInterface() override
{
return &m_variableTypeModel;
}
void AssignIndex(const QModelIndex& index) override
{
ScriptCanvas::Slot* slot = GetSlot();
if (slot)
{
if (slot->IsVariableReference())
{
// This will trigger an ebus call regarding the modification, which will trigger the value changed.
ScriptCanvas::VariableId variableId = m_variableTypeModel.GetValueForIndex(index);
slot->SetVariableReference(variableId);
PostUndoPoint();
}
}
}
QModelIndex GetAssignedIndex() const override
{
ScriptCanvas::Slot* slot = GetSlot();
if (slot)
{
if (slot->IsVariableReference())
{
return m_variableTypeModel.GetIndexForValue(slot->GetVariableReference());
}
}
return QModelIndex();
}
// Returns the string used to display the currently selected value[Used in the non-editable format]
const QString& GetDisplayString() const override
{
ScriptCanvas::Slot* slot = GetSlot();
if (slot)
{
if (slot->IsVariableReference())
{
const ScriptCanvas::GraphVariable* variable = m_variableTypeModel.GetGraphVariable(slot->GetVariableReference());
if (variable)
{
return m_variableTypeModel.GetDisplayName(variable->GetVariableId());
}
}
}
return ComboBoxDataInterface::GetDisplayString();
}
private:
ScriptCanvas::Slot* GetSlot() const
{
ScriptCanvas::Slot* slot = nullptr;
ScriptCanvas::NodeRequestBus::EventResult(slot, GetNodeId(), &ScriptCanvas::NodeRequests::GetSlot, GetSlotId());
return slot;
}
VariableTypeComboBoxFilterModel m_variableTypeModel;
ScriptCanvas::Data::Type m_displayType = ScriptCanvas::Data::Type::Invalid();
AZ::EntityId m_scriptCanvasGraphId;
};
}
@@ -0,0 +1,120 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/NodePropertyDisplay/VectorDataInterface.h>
#include "ScriptCanvasDataInterface.h"
namespace ScriptCanvasEditor
{
template<class Type, int ElementCount>
class ScriptCanvasVectorizedDataInterface
: public ScriptCanvasDataInterface<GraphCanvas::VectorDataInterface>
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasVectorizedDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasVectorizedDataInterface(const AZ::EntityId& nodeId, const ScriptCanvas::SlotId& slotId)
: ScriptCanvasDataInterface(nodeId, slotId)
{
}
~ScriptCanvasVectorizedDataInterface() = default;
int GetElementCount() const override
{
return ElementCount;
}
double GetValue(int index) const override
{
if (index < GetElementCount())
{
if (const ScriptCanvas::Datum* object = GetSlotObject())
{
if (const Type* retVal = object->GetAs<Type>())
{
return aznumeric_cast<double>(static_cast<float>(retVal->GetElement(index)));
}
}
}
return 0.0;
}
void SetValue(int index, double value) override
{
if (index < GetElementCount())
{
ScriptCanvas::ModifiableDatumView datumView;
ModifySlotObject(datumView);
if (datumView.IsValid())
{
Type currentValue = (*datumView.GetAs<Type>());
currentValue.SetElement(index, aznumeric_cast<float>(value));
datumView.SetAs<Type>(currentValue);
PostUndoPoint();
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
}
}
};
template<class Type, int ElementCount>
class ScriptCanvasVectorDataInterface
: public ScriptCanvasVectorizedDataInterface<Type, ElementCount>
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasVectorDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasVectorDataInterface(const AZ::EntityId& nodeId, const ScriptCanvas::SlotId& slotId)
: ScriptCanvasVectorizedDataInterface<Type, ElementCount>(nodeId, slotId)
{
}
~ScriptCanvasVectorDataInterface() = default;
const char* GetLabel(int index) const override
{
if (index == 0)
{
return "X";
}
else if (index == 1)
{
return "Y";
}
else if (index == 2)
{
return "Z";
}
else if (index == 3)
{
return "W";
}
return "???";
}
AZStd::string GetStyle() const
{
return "vectorized";
}
AZStd::string GetElementStyle(int index) const override
{
return AZStd::string::format("vector_%i", index);
}
};
}
@@ -0,0 +1,21 @@
/*
* All or Portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Math/Crc.h>
#include <GraphCanvas/Editor/EditorTypes.h>
namespace ScriptCanvasEditor
{
static const GraphCanvas::EditorId AssetEditorId = AZ_CRC("ScriptCanvasEditor", 0xa6d1a85a);
}
@@ -0,0 +1,128 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/NodePropertyDisplay/DataInterface.h>
#include <ScriptCanvas/Core/Datum.h>
#include <ScriptCanvas/Core/Node.h>
#include <ScriptCanvas/Core/NodeBus.h>
#include <ScriptCanvas/Core/Slot.h>
#include <Editor/View/Widgets/PropertyGridBus.h>
namespace ScriptCanvasEditor
{
template<class InterfaceType, typename DataType>
class ScriptCanvasPropertyDataInterface
: public ScriptCanvas::NodePropertyInterfaceListener
, public InterfaceType
{
protected:
ScriptCanvasPropertyDataInterface(const AZ::EntityId& nodeId, ScriptCanvas::TypedNodePropertyInterface<DataType>* nodePropertyInterface)
: m_nodeId(nodeId)
, m_nodePropertyInterface(nodePropertyInterface)
{
static_assert((AZStd::is_base_of<GraphCanvas::DataInterface, InterfaceType>::value), "ScriptCanvasPropertyDataInterface given invalid GraphCanvas::DataInterface to inherit.");
if (m_nodePropertyInterface)
{
m_nodePropertyInterface->RegisterListener(this);
}
}
using InterfaceType::SignalValueChanged;
public:
virtual ~ScriptCanvasPropertyDataInterface() = default;
const ScriptCanvas::ScriptCanvasId GetScriptCanvasId() const
{
ScriptCanvas::ScriptCanvasId scriptCanvasId;
ScriptCanvas::NodeRequestBus::EventResult(scriptCanvasId, GetNodeId(), &ScriptCanvas::NodeRequests::GetOwningScriptCanvasId);
return scriptCanvasId;
}
const GraphCanvas::GraphId GetGraphCanvasGraphId() const
{
GraphCanvas::GraphId graphCanvasGraphId;
GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::GetGraphCanvasGraphId, GetScriptCanvasId());
return graphCanvasGraphId;
}
const AZ::EntityId& GetNodeId() const
{
return m_nodeId;
}
ScriptCanvas::TypedNodePropertyInterface<DataType>* GetNodePropertyInterface()
{
return m_nodePropertyInterface;
}
// NodeNotificationsBus
void OnPropertyChanged() override
{
SignalValueChanged();
}
void PushUndoBlock()
{
GeneralRequestBus::Broadcast(&GeneralRequests::PushPreventUndoStateUpdate);
}
void PopUndoBlock()
{
GeneralRequestBus::Broadcast(&GeneralRequests::PopPreventUndoStateUpdate);
}
void PostUndoPoint()
{
GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, GetScriptCanvasId());
}
////
void SetValue(const DataType& valueType)
{
PushUndoBlock();
m_nodePropertyInterface->SetPropertyData(valueType);
PopUndoBlock();
PostUndoPoint();
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
}
const DataType& GetValue() const
{
static DataType s_staticReturn = {};
if (m_nodePropertyInterface)
{
const DataType* dataValue = m_nodePropertyInterface->GetPropertyData();
if (dataValue)
{
return (*dataValue);
}
}
return s_staticReturn;
}
private:
ScriptCanvas::TypedNodePropertyInterface<DataType>* m_nodePropertyInterface;
AZ::EntityId m_nodeId;
};
}
@@ -0,0 +1,44 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <GraphCanvas/Components/NodePropertyDisplay/StringDataInterface.h>
#include "ScriptCanvasPropertyDataInterface.h"
namespace ScriptCanvasEditor
{
class ScriptCanvasStringPropertyDataInterface
: public ScriptCanvasPropertyDataInterface<GraphCanvas::StringDataInterface, ScriptCanvas::Data::StringType>
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasStringPropertyDataInterface, AZ::SystemAllocator, 0);
ScriptCanvasStringPropertyDataInterface(const AZ::EntityId& nodeId, ScriptCanvas::TypedNodePropertyInterface<ScriptCanvas::Data::StringType>* propertyNodeInterface)
: ScriptCanvasPropertyDataInterface(nodeId, propertyNodeInterface)
{
}
~ScriptCanvasStringPropertyDataInterface() = default;
// StringDataInterface
AZStd::string GetString() const override
{
return GetValue();
}
void SetString(const AZStd::string& value) override
{
SetValue(value);
}
////
};
}
@@ -0,0 +1,30 @@
/*
* All or Portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Math/Crc.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
namespace ScriptCanvasEditor
{
namespace SlotGroups
{
static const GraphCanvas::SlotGroup DynamicPropertiesGroup = AZ_CRC("ScriptCanvas_DynamicPropertiesGroup", 0x545b0552);
static const GraphCanvas::SlotGroup EBusConnectionSlotGroup = AZ_CRC("ScriptCanvas_EBusConnectionSlotGroup", 0xc470f5c7);
}
namespace PropertySlotIds
{
static const AZ::Crc32 DefaultValue = AZ_CRC("ScriptCanvas_Property_DefaultValue", 0xf837b153);
}
}
@@ -0,0 +1,76 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/Asset/AssetTypeInfoBus.h>
#include <AzCore/Serialization/ObjectStream.h>
#include <ScriptCanvas/Asset/AssetDescription.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
namespace ScriptCanvas
{
class ScriptCanvasFunctionAsset;
}
namespace AZ
{
class SerializeContext;
}
namespace ScriptCanvasEditor
{
/**
* Manages editor Script Canvas graph assets.
*/
class ScriptCanvasFunctionAssetHandler
: public ScriptCanvasAssetHandler
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasFunctionAssetHandler, AZ::SystemAllocator, 0);
AZ_RTTI(ScriptCanvasFunctionAssetHandler, "{CE1EB0B7-D8DA-4B9B-858B-A34DF5092BC2}", ScriptCanvasAssetHandler);
ScriptCanvasFunctionAssetHandler(AZ::SerializeContext* context = nullptr);
~ScriptCanvasFunctionAssetHandler();
AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) override;
AZ::Data::AssetHandler::LoadResult LoadAssetData(
const AZ::Data::Asset<AZ::Data::AssetData>& asset,
AZStd::shared_ptr<AZ::Data::AssetDataStream> stream,
const AZ::Data::AssetFilterCB& assetLoadFilterCB) override;
bool SaveAssetData(const AZ::Data::Asset<AZ::Data::AssetData>& asset, AZ::IO::GenericStream* stream) override;
bool SaveAssetData(const ScriptCanvas::ScriptCanvasFunctionAsset* assetData, AZ::IO::GenericStream* stream);
bool SaveAssetData(const ScriptCanvas::ScriptCanvasFunctionAsset* assetData, AZ::IO::GenericStream* stream, AZ::DataStream::StreamType streamType);
// Called by asset database on registration.
void GetAssetTypeExtensions(AZStd::vector<AZStd::string>& extensions) override;
void GetHandledAssetTypes(AZStd::vector<AZ::Data::AssetType>& assetTypes) override;
// Provides editor with information about script canvas graph assets.
AZ::Data::AssetType GetAssetType() const override;
const char* GetAssetTypeDisplayName() const override;
bool CanCreateComponent(const AZ::Data::AssetId& assetId) const override;
const char* GetGroup() const override;
const char* GetBrowserIcon() const override;
static AZ::Data::AssetType GetAssetTypeStatic();
ScriptCanvas::ScriptCanvasFunctionAsset* m_scriptCanvasAsset;
};
} // namespace ScriptCanvasEditor
@@ -0,0 +1,92 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Asset/AssetCommon.h>
#include <ScriptCanvas/Asset/AssetDescription.h>
#include <ScriptCanvas/Assets/ScriptCanvasAssetBus.h>
#include <ScriptCanvas/Assets/ScriptCanvasBaseAssetData.h>
#include <ScriptCanvas/Asset/ScriptCanvasAssetBase.h>
namespace AZ
{
class Entity;
}
namespace ScriptCanvas
{
class Graph;
}
namespace ScriptCanvasEditor
{
class Graph;
class ScriptCanvasAsset;
class ScriptCanvasAssetDescription : public ScriptCanvas::AssetDescription
{
public:
AZ_TYPE_INFO(ScriptCanvasAssetDescription, "{3678E33E-521B-4CAC-9DC1-42566AC71249}");
ScriptCanvasAssetDescription()
: ScriptCanvas::AssetDescription(
azrtti_typeid<ScriptCanvasAsset>(),
"Script Canvas",
"Script Canvas Graph Asset",
"@devassets@/scriptcanvas",
".scriptcanvas",
"Script Canvas",
"Untitled-%i",
"Script Canvas Files (*.scriptcanvas)",
"Script Canvas",
"Script Canvas",
"Editor/Icons/ScriptCanvas/Viewport/ScriptCanvas.png",
AZ::Color(0.321f, 0.302f, 0.164f, 1.0f),
true
)
{}
};
class ScriptCanvasAsset
: public ScriptCanvas::ScriptCanvasAssetBase
{
public:
AZ_RTTI(ScriptCanvasAsset, "{FA10C3DA-0717-4B72-8944-CD67D13DFA2B}", ScriptCanvas::ScriptCanvasAssetBase);
AZ_CLASS_ALLOCATOR(ScriptCanvasAsset, AZ::SystemAllocator, 0);
ScriptCanvasAsset(const AZ::Data::AssetId& assetId = AZ::Data::AssetId(AZ::Uuid::CreateRandom()),
AZ::Data::AssetData::AssetStatus status = AZ::Data::AssetData::AssetStatus::NotLoaded)
: ScriptCanvas::ScriptCanvasAssetBase(assetId, status)
{
m_data = aznew ScriptCanvas::ScriptCanvasData();
}
~ScriptCanvasAsset() override
{
}
ScriptCanvas::AssetDescription GetAssetDescription() const override
{
return ScriptCanvasAssetDescription();
}
ScriptCanvas::Graph* GetScriptCanvasGraph() const;
using Description = ScriptCanvasAssetDescription;
ScriptCanvas::ScriptCanvasData& GetScriptCanvasData();
const ScriptCanvas::ScriptCanvasData& GetScriptCanvasData() const;
};
}
@@ -0,0 +1,35 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
namespace ScriptCanvas
{
class ScriptCanvasAssetBusRequests : public AZ::EBusTraits
{
public:
using BusIdType = AZ::Data::AssetId;
using MutexType = AZStd::recursive_mutex;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
virtual void SetAsNewAsset() = 0;
};
using ScriptCanvasAssetBusRequestBus = AZ::EBus<ScriptCanvasAssetBusRequests>;
}
@@ -0,0 +1,80 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#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 ScriptCanvasEditor
{
/**
* Manages editor Script Canvas graph assets.
*/
class ScriptCanvasAssetHandler
: public AZ::Data::AssetHandler
, protected AZ::AssetTypeInfoBus::MultiHandler
{
public:
AZ_CLASS_ALLOCATOR(ScriptCanvasAssetHandler, AZ::SystemAllocator, 0);
AZ_RTTI(ScriptCanvasAssetHandler, "{098B86B2-2527-4155-84C9-A698A0D20068}", AZ::Data::AssetHandler);
ScriptCanvasAssetHandler(AZ::SerializeContext* context = nullptr);
~ScriptCanvasAssetHandler();
// Called by the asset database to create a new asset.
AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) override;
// Override the stream info to force source assets to load into the Editor instead of cached, processed assets.
void GetCustomAssetStreamInfoForLoad(AZ::Data::AssetStreamInfo& streamInfo) override;
// Called by the asset database to perform actual asset load.
AZ::Data::AssetHandler::LoadResult LoadAssetData(
const AZ::Data::Asset<AZ::Data::AssetData>& asset,
AZStd::shared_ptr<AZ::Data::AssetDataStream> stream,
const AZ::Data::AssetFilterCB& assetLoadFilterCB) override;
// Called by the asset database to perform actual asset save. Returns true if successful otherwise false (default - as we don't require support save).
bool SaveAssetData(const AZ::Data::Asset<AZ::Data::AssetData>& asset, AZ::IO::GenericStream* stream) override;
bool SaveAssetData(const ScriptCanvasAsset* assetData, AZ::IO::GenericStream* stream);
bool SaveAssetData(const ScriptCanvasAsset* assetData, AZ::IO::GenericStream* stream , AZ::DataStream::StreamType streamType);
// Called by the asset database when an asset should be deleted.
void DestroyAsset(AZ::Data::AssetPtr ptr) override;
// Called by asset database on registration.
void GetHandledAssetTypes(AZStd::vector<AZ::Data::AssetType>& assetTypes) override;
// Provides editor with information about script canvas graph assets.
AZ::Data::AssetType GetAssetType() const override;
const char* GetAssetTypeDisplayName() const override;
void GetAssetTypeExtensions(AZStd::vector<AZStd::string>& extensions) override;
AZ::Uuid GetComponentTypeId() const override;
AZ::SerializeContext* GetSerializeContext() const;
void SetSerializeContext(AZ::SerializeContext* context);
static AZ::Data::AssetType GetAssetTypeStatic();
protected:
AZ::SerializeContext* m_serializeContext;
};
} // namespace ScriptCanvasEditor
@@ -0,0 +1,18 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
namespace ScriptCanvasEditor
{
}
@@ -0,0 +1,39 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <ScriptCanvas/Variable/VariableData.h>
#include <ScriptCanvas/Core/GraphData.h>
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(); }
AZStd::unique_ptr<AZ::Entity> m_scriptCanvasEntity;
private:
ScriptCanvasData(const ScriptCanvasData&) = delete;
};
}
@@ -0,0 +1,112 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Outcome/Outcome.h>
#include <AzCore/std/string/string_view.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
namespace AZ
{
namespace Data
{
class AssetInfo;
}
}
namespace ScriptCanvasEditor
{
enum class ScriptCanvasFileState : AZ::s32
{
NEW,
MODIFIED,
UNMODIFIED,
INVALID = -1
};
struct ScriptCanvasAssetFileInfo
{
AZ_TYPE_INFO(ScriptCanvasAssetFileInfo, "{81F6B390-7CF3-4A97-B5A6-EC09330F184E}");
AZ_CLASS_ALLOCATOR(ScriptCanvasAssetFileInfo, AZ::SystemAllocator, 0);
ScriptCanvasFileState m_fileModificationState = ScriptCanvasFileState::INVALID;
bool m_reloadable = false;
AZStd::string m_absolutePath;
};
//! Bus for handling transactions involving ScriptCanvas Assets, such as graph Saving, graph modification state, etc
class DocumentContextRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//! Creates a new ScriptCanvas asset and registers it with the document context
virtual AZ::Data::Asset<ScriptCanvasAsset> CreateScriptCanvasAsset(AZStd::string_view relativeAssetPath) = 0;
using SaveCB = AZStd::function<void(bool saveSuccess)>;
// !Callback will fire when a new in-memory Script Canvas asset is saved to disk for the first time and a new AssetId is generated for it
using SourceFileChangedCB = AZStd::function<void(AZStd::string relPath, AZStd::string scanFolder, const AZ::Data::AssetId& newAssetId)>;
//! Saves a ScriptCanvas asset using the supplied AssetPath structure
//! \param assetAbsolutePath path where ScriptCanvas asset will be saved on disk
virtual void SaveScriptCanvasAsset(AZStd::string_view/*assetAbsolutePath*/, AZ::Data::Asset<ScriptCanvasAsset>, const SaveCB&, const SourceFileChangedCB&) = 0;
//! Loads a ScriptCanvas asset by looking up the assetPath in the AssetCatalog
//! \param assetPath filepath to asset that will be looked up in the AssetCatalog for the AssetId
//! \param loadBlocking should the loading of the ScriptCanvas asset be blocking
virtual AZ::Data::Asset<ScriptCanvasAsset> LoadScriptCanvasAsset(const char* assetPath, bool loadBlocking) = 0;
virtual AZ::Data::Asset<ScriptCanvasAsset> LoadScriptCanvasAssetById(const AZ::Data::AssetId& assetId, bool loadBlocking) = 0;
//! Registers a ScriptCanvas assetId with the DocumentContext for lookup. ScriptCanvasAssetFileInfo will be associated with the ScriptCanvasAsset
//! \return true if the assetId is newly registered, false if the assetId is already registered
virtual bool RegisterScriptCanvasAsset(const AZ::Data::AssetId& assetId, const ScriptCanvasAssetFileInfo& assetFileInfo) = 0;
//! Unregisters a ScriptCanvas assetId with the DocumentContext for lookup
//! \return true if assetId was registered with the DocumentContext, false otherwise
virtual bool UnregisterScriptCanvasAsset(const AZ::Data::AssetId& assetId) = 0;
virtual ScriptCanvasFileState GetScriptCanvasAssetModificationState(const AZ::Data::AssetId& assetId) = 0;
virtual void SetScriptCanvasAssetModificationState(const AZ::Data::AssetId& assetId, ScriptCanvasFileState) = 0;
//! Retrieves the file information for the registered ScriptCanvas asset
virtual AZ::Outcome<ScriptCanvasAssetFileInfo, AZStd::string> GetFileInfo(const AZ::Data::AssetId& assetId) const = 0;
virtual AZ::Outcome<void, AZStd::string> SetFileInfo(const AZ::Data::AssetId& assetId, const ScriptCanvasAssetFileInfo& fileInfo) = 0;
};
using DocumentContextRequestBus = AZ::EBus<DocumentContextRequests>;
class DocumentContextNotifications
: public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = AZ::Data::AssetId;
virtual void OnAssetModificationStateChanged(ScriptCanvasFileState) {}
//! Notification which fires after an ScriptCanvasDocumentContext 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<ScriptCanvasAsset>& /*scriptCanvasAsset*/) {}
//! Notification which fires after an ScriptCanvasDocumentContext 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<ScriptCanvasAsset>& /*scriptCanvaAsset */) {}
//! Notification which fires after an ScriptCanvasDocumentContext has received it's on AssetReady callback
//! \param AssetId AssetId of unloaded ScriptCanvas
virtual void OnScriptCanvasAssetUnloaded(const AZ::Data::AssetId& /*assetId*/) {}
};
using DocumentContextNotificationBus = AZ::EBus<DocumentContextNotifications>;
}
@@ -0,0 +1,37 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <QAbstractItemModel>
#include <AzCore/EBus/EBus.h>
#include <AzCore/std/string/string.h>
#include <AzCore/Outcome/Outcome.h>
namespace ScriptCanvasEditor
{
class EditorSceneVariableManagerRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = ScriptCanvas::ScriptCanvasId;
// The QCompleter needs this to be non-const for some reason. Shouldn't
// matter since we should only have have a single instance operating on it at once.
virtual QAbstractItemModel* GetVariableItemModel() = 0;
};
using EditorSceneVariableManagerRequestBus = AZ::EBus<EditorSceneVariableManagerRequests>;
}
@@ -0,0 +1,221 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/std/string/string.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Asset/AssetSerializer.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Math/Uuid.h>
#include <AzCore/Math/Vector2.h>
#include <GraphCanvas/Editor/EditorTypes.h>
#include <GraphCanvas/Types/EntitySaveData.h>
#include <Editor/Include/ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <Editor/Include/ScriptCanvas/Bus/NodeIdPair.h>
#include <ScriptCanvas/Core/ExecutionNotificationsBus.h>
#include <ScriptCanvas/Variable/VariableCore.h>
namespace GraphCanvas
{
class GraphCanvasTreeItem;
}
namespace ScriptCanvasEditor
{
//=========================================================================
// EditorGraphBus
//=========================================================================
class EditorScriptCanvasRequests : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = ScriptCanvas::ScriptCanvasId;
//! Sets the name of the ScriptCanvas Graph.
//! \param name value to set
virtual void SetName(const AZStd::string& name) = 0;
//! Gets the name of the ScriptCanvas Graph.
//! \return reference to Graph name
virtual const AZStd::string& GetName() const = 0;
//! Will open the graph in the editor.
virtual void OpenEditor() = 0;
//! Used to close a graph that is currently opened in the editor.
virtual void CloseGraph() = 0;
//! Returns the Entity ID of the Editor Entity that owns this graph.
virtual AZ::EntityId GetEditorEntityId() const = 0;
virtual AZ::NamedEntityId GetNamedEditorEntityId() const = 0;
};
using EditorScriptCanvasRequestBus = AZ::EBus<EditorScriptCanvasRequests>;
class EditorScriptCanvasComponentRequests : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = AZ::EntityId;
virtual void SetAssetId(const AZ::Data::AssetId& assetId) = 0;
virtual bool HasAssetId() const = 0;
};
using EditorScriptCanvasComponentRequestBus = AZ::EBus<EditorScriptCanvasComponentRequests>;
// Above bus is keyed off of the graph Id. Which I don't really have access to.
// This bus is here just so I can tell it to open the Editor.
class EditorContextMenuRequests : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = AZ::EntityId;
//! Gets the GraphId for the EditorScriptCanvasComponent on the given entity.
virtual AZ::Data::AssetId GetAssetId() const = 0;
};
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;
virtual void DisplayGraphCanvasScene() = 0;
virtual void OnGraphCanvasSceneVisible() = 0;
virtual void UpdateGraphCanvasSaveData(const AZStd::unordered_map< AZ::EntityId, GraphCanvas::EntitySaveDataContainer* >& saveData) = 0;
virtual AZStd::unordered_map< AZ::EntityId, GraphCanvas::EntitySaveDataContainer* > GetGraphCanvasSaveData() = 0;
virtual NodeIdPair CreateCustomNode(const AZ::Uuid& typeId, const AZ::Vector2& position) = 0;
virtual void AddCrcCache(const AZ::Crc32& crcValue, const AZStd::string& cacheString) = 0;
virtual void RemoveCrcCache(const AZ::Crc32& crcValue) = 0;
virtual AZStd::string DecodeCrc(const AZ::Crc32& crcValue) = 0;
virtual void ClearHighlights() = 0;
virtual void HighlightMembersFromTreeItem(const GraphCanvas::GraphCanvasTreeItem* treeItem) = 0;
virtual void HighlightVariables(const AZStd::unordered_set< ScriptCanvas::VariableId>& variableIds) = 0;
virtual void HighlightNodes(const AZStd::vector<NodeIdPair>& nodes) = 0;
virtual AZStd::vector<NodeIdPair> GetNodesOfType(const ScriptCanvas::NodeTypeIdentifier&) = 0;
virtual AZStd::vector<NodeIdPair> GetVariableNodes(const ScriptCanvas::VariableId&) = 0;
virtual void RemoveUnusedVariables() = 0;
virtual bool ConvertVariableNodeToReference(const GraphCanvas::NodeId& nodeId) = 0;
virtual bool ConvertReferenceToVariableNode(const GraphCanvas::Endpoint& endpoint) = 0;
virtual void QueueVersionUpdate(const AZ::EntityId& graphCanvasNodeId) = 0;
virtual bool IsRuntimeGraph() const = 0;
virtual bool IsFunctionGraph() const = 0;
virtual ScriptCanvas::Endpoint ConvertToScriptCanvasEndpoint(const GraphCanvas::Endpoint& endpoinnt) const = 0;
virtual GraphCanvas::Endpoint ConvertToGraphCanvasEndpoint(const ScriptCanvas::Endpoint& endpoint) const = 0;
};
using EditorGraphRequestBus = AZ::EBus<EditorGraphRequests>;
class EditorGraphNotifications
: public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = ScriptCanvas::ScriptCanvasId;
virtual void OnGraphCanvasSceneDisplayed() {};
};
using EditorGraphNotificationBus = AZ::EBus<EditorGraphNotifications>;
class EditorNodeNotifications : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = AZ::EntityId;
virtual void OnGraphCanvasNodeDisplayed(AZ::EntityId /*graphCanvasNodeId*/) {}
virtual void OnVersionConversionBegin() {};
virtual void OnVersionConversionEnd() {};
};
using EditorNodeNotificationBus = AZ::EBus<EditorNodeNotifications>;
// Mainly expected to be used from an aggregator.
class EditorScriptCanvasComponentLogging
: public AZ::ComponentBus
{
public:
virtual AZ::NamedEntityId FindNamedEntityId() const = 0;
virtual ScriptCanvas::GraphIdentifier GetGraphIdentifier() const = 0;
};
using EditorScriptCanvasComponentLoggingBus = AZ::EBus<EditorScriptCanvasComponentLogging>;
class EditorLoggingComponentNotifications
: public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
virtual void OnEditorScriptCanvasComponentActivated(const AZ::NamedEntityId& namedEntityId, const ScriptCanvas::GraphIdentifier& graphIdentifier) = 0;
virtual void OnEditorScriptCanvasComponentDeactivated(const AZ::NamedEntityId& namedEntityId, const ScriptCanvas::GraphIdentifier& graphIdentifier) = 0;
virtual void OnAssetSwitched(const AZ::NamedEntityId& namedEntityId, const ScriptCanvas::GraphIdentifier& newGraphIdentifier, const ScriptCanvas::GraphIdentifier& oldGraphIdentifier) = 0;
};
using EditorLoggingComponentNotificationBus = AZ::EBus<EditorLoggingComponentNotifications>;
}
@@ -0,0 +1,31 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
#include <ScriptCanvas/Core/Core.h>
namespace ScriptCanvasEditor
{
class GeneralGraphEvents : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual void OnBuildGameEntity([[maybe_unused]] const AZStd::string& name, [[maybe_unused]] const AZ::EntityId& editGraphId, [[maybe_unused]] const ScriptCanvas::ScriptCanvasId& scriptCanvasId) {}
};
using GeneralGraphEventBus = AZ::EBus<GeneralGraphEvents>;
}
@@ -0,0 +1,33 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzCore/Component/EntityId.h>
#include <AzCore/std/string/string.h>
namespace ScriptCanvasEditor
{
class IconRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = AZ::EntityId;
virtual AZStd::string GetIconPath() const = 0;
};
using IconBus = AZ::EBus<IconRequests>;
}
@@ -0,0 +1,29 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/EntityId.h>
namespace ScriptCanvasEditor
{
struct NodeIdPair
{
AZ::EntityId m_graphCanvasId;
AZ::EntityId m_scriptCanvasId;
NodeIdPair()
: m_graphCanvasId(AZ::EntityId::InvalidEntityId)
, m_scriptCanvasId(AZ::EntityId::InvalidEntityId)
{}
};
}
@@ -0,0 +1,238 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#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/Math/Vector2.h>
#include <GraphCanvas/Types/Types.h>
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
#include <ScriptCanvas/Bus/NodeIdPair.h>
#include <ScriptCanvas/Data/Data.h>
namespace GraphCanvas
{
struct Endpoint;
class GraphCanvasMimeEvent;
class GraphCanvasTreeItem;
}
namespace ScriptCanvas
{
class ScriptCanvasAssetBase;
}
namespace ScriptCanvasEditor
{
struct CategoryInformation;
struct NodePaletteModelInformation;
namespace Widget
{
struct GraphTabMetadata;
}
namespace TypeDefs
{
typedef AZStd::pair<AZ::EntityId, AZ::ComponentId> EntityComponentId;
}
class GeneralRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//! 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 int CloseScriptCanvasAsset(const AZ::Data::AssetId&) = 0;
virtual bool CreateScriptCanvasAssetFor(const TypeDefs::EntityComponentId& requestingComponent) = 0;
virtual bool IsScriptCanvasAssetOpen(const AZ::Data::AssetId& assetId) const = 0;
virtual void OnChangeActiveGraphTab(AZ::Data::AssetId) {}
virtual void CreateNewFunctionAsset() = 0;
virtual void CreateNewRuntimeAsset() = 0;
virtual ScriptCanvas::ScriptCanvasId GetActiveScriptCanvasId() const
{
return ScriptCanvas::ScriptCanvasId();
}
virtual GraphCanvas::GraphId GetActiveGraphCanvasGraphId() const
{
return GraphCanvas::GraphId();
}
virtual GraphCanvas::GraphId GetGraphCanvasGraphId([[maybe_unused]] const ScriptCanvas::ScriptCanvasId& scriptCanvasEntityId) const
{
return GraphCanvas::GraphId();
}
virtual ScriptCanvas::ScriptCanvasId GetScriptCanvasId([[maybe_unused]] const GraphCanvas::GraphId& graphCanvasSceneId) const
{
return ScriptCanvas::ScriptCanvasId();
}
virtual GraphCanvas::GraphId FindGraphCanvasGraphIdByAssetId([[maybe_unused]] const AZ::Data::AssetId& assetId) const
{
return GraphCanvas::GraphId();
}
virtual ScriptCanvas::ScriptCanvasId FindScriptCanvasIdByAssetId([[maybe_unused]] const AZ::Data::AssetId& assetId) const
{
return ScriptCanvas::ScriptCanvasId();
}
virtual bool IsInUndoRedo(const AZ::EntityId& graphCanvasGraphId) const = 0;
virtual bool IsScriptCanvasInUndoRedo(const ScriptCanvas::ScriptCanvasId& scriptCanvasId) const = 0;
virtual bool IsActiveGraphInUndoRedo() const = 0;
virtual void UpdateName(const AZ::EntityId& /*graphId*/, const AZStd::string& /*name*/) {}
virtual void DeleteNodes(const AZ::EntityId& /*sceneId*/, const AZStd::vector<AZ::EntityId>& /*nodes*/){}
virtual void DeleteConnections(const AZ::EntityId& /*sceneId*/, const AZStd::vector<AZ::EntityId>& /*connections*/){}
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;
// Increment the value of the ignore undo point tracker
virtual void PushPreventUndoStateUpdate() = 0;
// Decrement the value of the ignore undo point tracker
virtual void PopPreventUndoStateUpdate() = 0;
// Sets the value of the ignore undo point tracker to 0.
// Therefore allowing undo points to be posted
virtual void ClearPreventUndoStateUpdate() = 0;
virtual void TriggerUndo() = 0;
virtual void TriggerRedo() = 0;
virtual const CategoryInformation* FindNodePaletteCategoryInformation(AZStd::string_view categoryPath) const = 0;
virtual const NodePaletteModelInformation* FindNodePaletteModelInformation(const ScriptCanvas::NodeTypeIdentifier& nodeType) const = 0;
};
using GeneralRequestBus = AZ::EBus<GeneralRequests>;
class GeneralEditorNotifications
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = ScriptCanvas::ScriptCanvasId;
virtual void OnUndoRedoBegin() {}
virtual void OnUndoRedoEnd() {}
};
using GeneralEditorNotificationBus = AZ::EBus<GeneralEditorNotifications>;
class GeneralAssetNotifications
: 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 OnAssetVisualized() {};
virtual void OnAssetUnloaded() {};
};
using GeneralAssetNotificationBus = AZ::EBus<GeneralAssetNotifications>;
class NodeCreationNotifications : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = ScriptCanvas::ScriptCanvasId;
virtual void OnGraphCanvasNodeCreated(const AZ::EntityId& nodeId) = 0;
};
using NodeCreationNotificationBus = AZ::EBus<NodeCreationNotifications>;
class VariablePaletteRequests : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual void RegisterVariableType(const ScriptCanvas::Data::Type& variabletype) = 0;
};
using VariablePaletteRequestBus = AZ::EBus<VariablePaletteRequests>;
class VariableAutomationRequests : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual AZStd::vector< ScriptCanvas::Data::Type > GetPrimitiveTypes() const = 0;
virtual AZStd::vector< ScriptCanvas::Data::Type > GetBehaviorContextObjectTypes() const = 0;
virtual AZStd::vector< ScriptCanvas::Data::Type > GetMapTypes() const = 0;
virtual AZStd::vector< ScriptCanvas::Data::Type > GetArrayTypes() const = 0;
AZStd::vector< ScriptCanvas::Data::Type > GetVariableTypes() const
{
AZStd::vector< ScriptCanvas::Data::Type > dataTypes = GetPrimitiveTypes();
auto workingTypes = GetBehaviorContextObjectTypes();
dataTypes.insert(dataTypes.begin(), workingTypes.begin(), workingTypes.end());
workingTypes.clear();
workingTypes = GetMapTypes();
dataTypes.insert(dataTypes.begin(), workingTypes.begin(), workingTypes.end());
workingTypes.clear();
workingTypes = GetArrayTypes();
dataTypes.insert(dataTypes.begin(), workingTypes.begin(), workingTypes.end());
workingTypes.clear();
return dataTypes;
}
};
using VariableAutomationRequestBus = AZ::EBus<VariableAutomationRequests>;
class AutomationRequests : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual NodeIdPair ProcessCreateNodeMimeEvent(GraphCanvas::GraphCanvasMimeEvent* mimeEvent, const AZ::EntityId& graphCanvasGraphId, AZ::Vector2 nodeCreationPos) = 0;
virtual const GraphCanvas::GraphCanvasTreeItem* GetNodePaletteRoot() const = 0;
virtual void SignalAutomationBegin() = 0;
virtual void SignalAutomationEnd() = 0;
};
using AutomationRequestBus = AZ::EBus<AutomationRequests>;
}

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