The Great ScriptCanvas Purge, Part V
Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com>main
parent
360236b89e
commit
0a910a31aa
@ -1,154 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "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;
|
||||
}
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <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;
|
||||
};
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <AzCore/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());
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1,234 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
#include <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;
|
||||
};
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
#include <AzCore/Asset/AssetTypeInfoBus.h>
|
||||
#include <AzCore/Serialization/ObjectStream.h>
|
||||
#include <ScriptCanvas/Asset/AssetDescription.h>
|
||||
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
|
||||
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class SerializeContext;
|
||||
}
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
class ScriptCanvasFunctionAsset;
|
||||
|
||||
/**
|
||||
* 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 ScriptCanvasEditor::ScriptCanvasFunctionAsset* assetData, AZ::IO::GenericStream* stream);
|
||||
|
||||
bool SaveAssetData(const ScriptCanvasEditor::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();
|
||||
|
||||
ScriptCanvasEditor::ScriptCanvasFunctionAsset* m_scriptCanvasAsset;
|
||||
|
||||
};
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#include "precompiled.h"
|
||||
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
|
||||
#include <Editor/Nodes/EditorLibrary.h>
|
||||
#include <Editor/Nodes/ScriptCanvasAssetNode.h>
|
||||
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
namespace Library
|
||||
{
|
||||
void Editor::Reflect(AZ::ReflectContext* reflection)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<Editor, LibraryDefinition>()
|
||||
->Version(1)
|
||||
;
|
||||
|
||||
AZ::EditContext* editContext = serializeContext->GetEditContext();
|
||||
if (editContext)
|
||||
{
|
||||
editContext->Class<Editor>("Editor", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/All.png")
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::InitNodeRegistry(ScriptCanvas::NodeRegistry& nodeRegistry)
|
||||
{
|
||||
ScriptCanvas::Library::AddNodeToRegistry<Editor, ScriptCanvasAssetNode>(nodeRegistry);
|
||||
}
|
||||
|
||||
AZStd::vector<AZ::ComponentDescriptor*> Editor::GetComponentDescriptors()
|
||||
{
|
||||
return AZStd::vector<AZ::ComponentDescriptor*>({
|
||||
ScriptCanvasAssetNode::CreateDescriptor(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::vector<AZ::ComponentDescriptor*> GetLibraryDescriptors()
|
||||
{
|
||||
return Library::Editor::GetComponentDescriptors();
|
||||
}
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <ScriptCanvas/Libraries/Libraries.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
class ComponentDescriptor;
|
||||
}
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
namespace Library
|
||||
{
|
||||
struct Editor : public ScriptCanvas::Library::LibraryDefinition
|
||||
{
|
||||
AZ_RTTI(Editor, "{59697735-4B64-4DC5-8380-02B2999FFCFE}", ScriptCanvas::Library::LibraryDefinition);
|
||||
|
||||
static void Reflect(AZ::ReflectContext*);
|
||||
static void InitNodeRegistry(ScriptCanvas::NodeRegistry& nodeRegistry);
|
||||
static AZStd::vector<AZ::ComponentDescriptor*> GetComponentDescriptors();
|
||||
};
|
||||
}
|
||||
|
||||
AZStd::vector<AZ::ComponentDescriptor*> GetLibraryDescriptors();
|
||||
}
|
||||
@ -1,200 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
#include <Editor/Nodes/ScriptCanvasAssetNode.h>
|
||||
|
||||
#include <ScriptCanvas/Core/Graph.h>
|
||||
#include <Editor/Assets/ScriptCanvasAssetTrackerBus.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
/**
|
||||
* \note when we reflecting we can check if the class is inheriting from IEventHandler
|
||||
* and use the this->events.
|
||||
*/
|
||||
class ScriptCanvasAssetNodeEventHandler
|
||||
: public AZ::SerializeContext::IEventHandler
|
||||
{
|
||||
void OnReadBegin(void* classPtr)
|
||||
{
|
||||
auto* scriptCanvasAssetNode = reinterpret_cast<ScriptCanvasAssetNode*>(classPtr);
|
||||
scriptCanvasAssetNode->ComputeDataPatch();
|
||||
}
|
||||
};
|
||||
|
||||
void ScriptCanvasAssetNode::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (!serializeContext)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
serializeContext->Class<ScriptCanvasAssetNode, ScriptCanvas::Node>()
|
||||
->Version(0)
|
||||
->EventHandler<ScriptCanvasAssetNodeEventHandler>()
|
||||
->Field("m_assetInstance", &ScriptCanvasAssetNode::m_scriptCanvasAssetInstance)
|
||||
;
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<ScriptCanvasAssetNode>("ScriptCanvas Asset", "Script Canvas Asset Node which contains a reference to another ScriptCanvas graph")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Icons/ScriptCanvas/Placeholder.png")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::List)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptCanvasAssetNode::ScriptCanvasAssetNode(const AZ::Data::Asset<ScriptCanvasAsset>& scriptCanvasAsset, bool storeAssetDataInternally)
|
||||
{
|
||||
SetAssetDataStoredInternally(storeAssetDataInternally);
|
||||
SetAsset(scriptCanvasAsset);
|
||||
}
|
||||
|
||||
ScriptCanvasAssetNode::~ScriptCanvasAssetNode()
|
||||
{
|
||||
}
|
||||
|
||||
void ScriptCanvasAssetNode::OnInit()
|
||||
{
|
||||
if (GetAsset().GetId().IsValid())
|
||||
{
|
||||
AZ::Data::AssetBus::Handler::BusConnect(GetAsset().GetId());
|
||||
AZ::Entity* scriptCanvasEntity = GetScriptCanvasEntity();
|
||||
if (scriptCanvasEntity)
|
||||
{
|
||||
if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed)
|
||||
{
|
||||
scriptCanvasEntity->Init();
|
||||
}
|
||||
if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init)
|
||||
{
|
||||
scriptCanvasEntity->Activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ScriptCanvasAssetNode::GetAssetDataStoredInternally() const
|
||||
{
|
||||
return m_scriptCanvasAssetInstance.GetReference().GetAssetDataStoredInternally();
|
||||
}
|
||||
|
||||
void ScriptCanvasAssetNode::SetAssetDataStoredInternally(bool storeInObjectStream)
|
||||
{
|
||||
m_scriptCanvasAssetInstance.GetReference().SetAssetDataStoredInternally(storeInObjectStream);
|
||||
}
|
||||
|
||||
ScriptCanvas::ScriptCanvasData& ScriptCanvasAssetNode::GetScriptCanvasData()
|
||||
{
|
||||
return m_scriptCanvasAssetInstance.GetScriptCanvasData();
|
||||
}
|
||||
|
||||
const ScriptCanvas::ScriptCanvasData& ScriptCanvasAssetNode::GetScriptCanvasData() const
|
||||
{
|
||||
return m_scriptCanvasAssetInstance.GetScriptCanvasData();
|
||||
}
|
||||
|
||||
AZ::Entity* ScriptCanvasAssetNode::GetScriptCanvasEntity() const
|
||||
{
|
||||
return GetScriptCanvasData().GetScriptCanvasEntity();
|
||||
}
|
||||
|
||||
AZ::Data::Asset<ScriptCanvasAsset>& ScriptCanvasAssetNode::GetAsset()
|
||||
{
|
||||
return m_scriptCanvasAssetInstance.GetReference().GetAsset();
|
||||
}
|
||||
|
||||
const AZ::Data::Asset<ScriptCanvasAsset>& ScriptCanvasAssetNode::GetAsset() const
|
||||
{
|
||||
return m_scriptCanvasAssetInstance.GetReference().GetAsset();
|
||||
}
|
||||
|
||||
void ScriptCanvasAssetNode::SetAsset(const AZ::Data::Asset<ScriptCanvasAsset>& scriptCanvasAsset)
|
||||
{
|
||||
m_scriptCanvasAssetInstance.GetReference().SetAsset(scriptCanvasAsset);
|
||||
if (scriptCanvasAsset.GetId().IsValid())
|
||||
{
|
||||
auto onAssetReady = [](ScriptCanvasMemoryAsset&) {};
|
||||
AssetTrackerRequestBus::Broadcast(&AssetTrackerRequests::Load, scriptCanvasAsset.GetId(), azrtti_typeid<ScriptCanvasAsset>(), onAssetReady);
|
||||
|
||||
AZ::Data::AssetBus::Handler::BusConnect(scriptCanvasAsset.GetId());
|
||||
ApplyDataPatch();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptCanvasAssetNode::OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
{
|
||||
SetAsset(asset);
|
||||
if (!GetAsset().IsReady())
|
||||
{
|
||||
AZ_Error("Script Canvas", false, "Reloaded graph with id %s is not valid", asset.GetId().ToString<AZStd::string>().data());
|
||||
return;
|
||||
}
|
||||
|
||||
// Update data patches against the old version of the asset.
|
||||
ApplyDataPatch();
|
||||
}
|
||||
|
||||
void ScriptCanvasAssetNode::OnAssetUnloaded(const AZ::Data::AssetId assetId, const AZ::Data::AssetType)
|
||||
{
|
||||
AZ::Data::AssetBus::Handler::BusDisconnect(assetId);
|
||||
}
|
||||
|
||||
void ScriptCanvasAssetNode::ComputeDataPatch()
|
||||
{
|
||||
m_scriptCanvasAssetInstance.ComputeDataPatch();
|
||||
}
|
||||
|
||||
void ScriptCanvasAssetNode::ApplyDataPatch()
|
||||
{
|
||||
m_scriptCanvasAssetInstance.ApplyDataPatch();
|
||||
}
|
||||
|
||||
bool ScriptCanvasAssetNode::Visit(const VisitCB& preVisitCB, const VisitCB & postVisitCB)
|
||||
{
|
||||
AZStd::unordered_set<AZ::Data::AssetId> visitedGraphs;
|
||||
return Visit(preVisitCB, postVisitCB, visitedGraphs);
|
||||
}
|
||||
|
||||
bool ScriptCanvasAssetNode::Visit(const VisitCB& preVisitCB, const VisitCB & postVisitCB, AZStd::unordered_set<AZ::Data::AssetId>& visitedGraphs)
|
||||
{
|
||||
const AZ::Data::AssetId& visitedAssetId = GetAsset().GetId();
|
||||
if (visitedGraphs.count(visitedAssetId) > 0)
|
||||
{
|
||||
AZ_Error("Script Canvas", false, "The Script Canvas Asset %s has already been visited, processing will stop", visitedAssetId.ToString<AZStd::string>().data());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!preVisitCB || preVisitCB(*this))
|
||||
{
|
||||
auto graph = GetScriptCanvasEntity() ? AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Graph>(GetScriptCanvasEntity()) : nullptr;
|
||||
if (graph)
|
||||
{
|
||||
for (AZ::Entity* nodeEntity : graph->GetNodeEntities())
|
||||
{
|
||||
if (auto childAssetNode = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvasAssetNode>(nodeEntity))
|
||||
{
|
||||
// Visit ScriptCanvasAssetNodes that are in the asset referenced by @assetNode
|
||||
if (!childAssetNode->Visit(preVisitCB, postVisitCB, visitedGraphs))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Visit siblings ScriptCanvasAssetNodes
|
||||
bool visitSiblings = !postVisitCB || postVisitCB(*this);
|
||||
visitedGraphs.insert(visitedAssetId);
|
||||
return visitSiblings;
|
||||
}
|
||||
}
|
||||
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
|
||||
#include <ScriptCanvas/Core/Node.h>
|
||||
#include <ScriptCanvas/Bus/GraphBus.h>
|
||||
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
|
||||
#include <Editor/Assets/ScriptCanvasAssetInstance.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
//! A group of entities in a scene
|
||||
class ScriptCanvasAssetNode
|
||||
: public ScriptCanvas::Node
|
||||
, protected AZ::Data::AssetBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(ScriptCanvasAssetNode, "{65A34956-B6ED-4EB2-966C-5BC844F7B05E}", ScriptCanvas::Node);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
ScriptCanvasAssetNode() = default;
|
||||
ScriptCanvasAssetNode(const AZ::Data::Asset<ScriptCanvasAsset>& scriptCanvasAsset, bool storeAssetDataInternally);
|
||||
~ScriptCanvasAssetNode() override;
|
||||
|
||||
// AZ::Component
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
{
|
||||
provided.push_back(AZ_CRC("ScriptCanvas_AssetService", 0x17a357ae));
|
||||
}
|
||||
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC("ScriptCanvas_AssetService", 0x17a357ae));
|
||||
}
|
||||
|
||||
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
|
||||
{
|
||||
(void)dependent;
|
||||
}
|
||||
|
||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
(void)required;
|
||||
}
|
||||
////
|
||||
|
||||
void OnInit() override;
|
||||
|
||||
// Retrieves the asset associated with this node
|
||||
AZ::Data::Asset<ScriptCanvasAsset>& GetAsset();
|
||||
const AZ::Data::Asset<ScriptCanvasAsset>& GetAsset() const;
|
||||
// Sets the asset associated with this node
|
||||
void SetAsset(const AZ::Data::Asset<ScriptCanvasAsset>& scriptCanvasAsset);
|
||||
|
||||
bool GetAssetDataStoredInternally() const;
|
||||
void SetAssetDataStoredInternally(bool storeInObjectStream);
|
||||
|
||||
ScriptCanvas::ScriptCanvasData& GetScriptCanvasData();
|
||||
const ScriptCanvas::ScriptCanvasData& GetScriptCanvasData() const;
|
||||
|
||||
AZ::Entity* GetScriptCanvasEntity() const;
|
||||
|
||||
using VisitCB = AZStd::function<bool(ScriptCanvasAssetNode& scriptCanvasAssetNode)>;
|
||||
bool Visit(const VisitCB& preVisitCB, const VisitCB & postVisitCB);
|
||||
bool Visit(const VisitCB& preVisitCB, const VisitCB & postVisitCB, AZStd::unordered_set<AZ::Data::AssetId>& visitedGraphs);
|
||||
////
|
||||
|
||||
protected:
|
||||
// AssetBus::Handler
|
||||
void OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
|
||||
void OnAssetUnloaded(const AZ::Data::AssetId assetId, const AZ::Data::AssetType) override;
|
||||
////
|
||||
|
||||
friend class ScriptCanvasAssetNodeEventHandler;
|
||||
void ComputeDataPatch();
|
||||
void ApplyDataPatch();
|
||||
|
||||
private:
|
||||
ScriptCanvasAssetNode(const ScriptCanvasAssetNode&) = delete;
|
||||
//! References to the Script Canvas asset used by this component
|
||||
ScriptCanvasAssetInstance m_scriptCanvasAssetInstance;
|
||||
};
|
||||
}
|
||||
@ -1,316 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#include <AzCore/PlatformDef.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
|
||||
#include <Source/Framework/ScriptCanvasTestFixture.h>
|
||||
#include <Source/Framework/ScriptCanvasTestUtilities.h>
|
||||
|
||||
#include <ScriptCanvas/Core/SlotConfigurationDefaults.h>
|
||||
|
||||
using namespace ScriptCanvasTests;
|
||||
using namespace ScriptCanvasEditor;
|
||||
|
||||
// Asynchronous ScriptCanvas Behaviors
|
||||
|
||||
#if AZ_COMPILER_MSVC
|
||||
|
||||
#include <future>
|
||||
|
||||
class AsyncEvent : public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
|
||||
using BusIdType = AZ::EntityId;
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
static const bool LocklessDispatch = true;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void OnAsyncEvent() = 0;
|
||||
};
|
||||
|
||||
using AsyncEventNotificationBus = AZ::EBus<AsyncEvent>;
|
||||
|
||||
class LongRunningProcessSimulator3000
|
||||
{
|
||||
public:
|
||||
|
||||
static void Run(const AZ::EntityId& listener)
|
||||
{
|
||||
int duration = 40;
|
||||
while (--duration > 0)
|
||||
{
|
||||
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(10));
|
||||
}
|
||||
|
||||
AsyncEventNotificationBus::Event(listener, &AsyncEvent::OnAsyncEvent);
|
||||
}
|
||||
};
|
||||
|
||||
class AsyncNode
|
||||
: public ScriptCanvas::Node
|
||||
, protected AsyncEventNotificationBus::Handler
|
||||
, protected AZ::TickBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(AsyncNode, "{0A7FF6C6-878B-42EC-A8BB-4D29C4039853}", ScriptCanvas::Node);
|
||||
|
||||
bool IsEntryPoint() const { return true; }
|
||||
|
||||
AsyncNode()
|
||||
: Node()
|
||||
{}
|
||||
|
||||
static void Reflect(AZ::ReflectContext* reflection)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AsyncNode, Node>()
|
||||
->Version(1)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureSlots() override
|
||||
{
|
||||
AddSlot(ScriptCanvas::CommonSlots::GeneralInSlot());
|
||||
AddSlot(ScriptCanvas::CommonSlots::GeneralOutSlot());
|
||||
}
|
||||
|
||||
void OnActivate() override
|
||||
{
|
||||
ScriptCanvasTestFixture::s_asyncOperationActive = true;
|
||||
AZ::TickBus::Handler::BusConnect();
|
||||
AsyncEventNotificationBus::Handler::BusConnect(GetEntityId());
|
||||
|
||||
std::packaged_task<void()> task([this]() { LongRunningProcessSimulator3000::Run(GetEntityId()); }); // wrap the function
|
||||
|
||||
m_eventThread = AZStd::make_shared<AZStd::thread>(AZStd::move(task)); // launch on a thread
|
||||
}
|
||||
|
||||
void OnDeactivate() override
|
||||
{
|
||||
if (m_eventThread)
|
||||
{
|
||||
m_eventThread->join();
|
||||
m_eventThread.reset();
|
||||
}
|
||||
|
||||
// We've received the event, no longer need the bus connection
|
||||
AsyncEventNotificationBus::Handler::BusDisconnect();
|
||||
|
||||
// We're done, kick it out.
|
||||
SignalOutput(GetSlotId("Out"));
|
||||
|
||||
// Disconnect from tick bus as well
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
virtual void HandleAsyncEvent()
|
||||
{
|
||||
EXPECT_GT(m_duration, 0.f);
|
||||
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void OnAsyncEvent() override
|
||||
{
|
||||
HandleAsyncEvent();
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
ScriptCanvasTestFixture::s_asyncOperationActive = false;
|
||||
}
|
||||
|
||||
void OnTick(float deltaTime, AZ::ScriptTimePoint) override
|
||||
{
|
||||
AZ_TracePrintf("Debug", "Awaiting async operation: %.2f\n", m_duration);
|
||||
m_duration += deltaTime;
|
||||
}
|
||||
|
||||
protected:
|
||||
AZStd::shared_ptr<AZStd::thread> m_eventThread;
|
||||
private:
|
||||
double m_duration = 0.f;
|
||||
};
|
||||
|
||||
TEST_F(ScriptCanvasTestFixture, Asynchronous_Behaviors)
|
||||
{
|
||||
using namespace ScriptCanvas;
|
||||
|
||||
RegisterComponentDescriptor<AsyncNode>();
|
||||
|
||||
// Make the graph.
|
||||
ScriptCanvas::Graph* graph =nullptr;
|
||||
SystemRequestBus::BroadcastResult(graph, &SystemRequests::MakeGraph);
|
||||
ASSERT_TRUE(graph != nullptr);
|
||||
|
||||
AZ::Entity* graphEntity = graph->GetEntity();
|
||||
graphEntity->Init();
|
||||
|
||||
const ScriptCanvasId& graphUniqueId = graph->GetScriptCanvasId();
|
||||
|
||||
AZ::Entity* startEntity{ aznew AZ::Entity };
|
||||
startEntity->Init();
|
||||
|
||||
AZ::EntityId startNodeId;
|
||||
CreateTestNode<ScriptCanvas::Nodes::Core::Start>(graphUniqueId, startNodeId);
|
||||
|
||||
AZ::EntityId asyncNodeId;
|
||||
CreateTestNode<AsyncNode>(graphUniqueId, asyncNodeId);
|
||||
|
||||
EXPECT_TRUE(Connect(*graph, startNodeId, ScriptCanvas::CommonSlots::GeneralOutSlot::GetName(), asyncNodeId, ScriptCanvas::CommonSlots::GeneralInSlot::GetName()));
|
||||
|
||||
{
|
||||
ScopedOutputSuppression supressOutput;
|
||||
graphEntity->Activate();
|
||||
|
||||
// Tick the TickBus while the graph entity is active
|
||||
while (ScriptCanvasTestFixture::s_asyncOperationActive)
|
||||
{
|
||||
AZ::TickBus::ExecuteQueuedEvents();
|
||||
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(100));
|
||||
AZ::TickBus::Broadcast(&AZ::TickEvents::OnTick, 0.01f, AZ::ScriptTimePoint(AZStd::chrono::system_clock::now()));
|
||||
}
|
||||
}
|
||||
|
||||
graphEntity->Deactivate();
|
||||
delete graphEntity;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
// Fibonacci solver, used to compare against the graph version.
|
||||
long ComputeFibonacci(int digits)
|
||||
{
|
||||
int a = 0;
|
||||
int b = 1;
|
||||
long sum = 0;
|
||||
for (int i = 0; i < digits - 2; ++i)
|
||||
{
|
||||
sum = a + b;
|
||||
a = b;
|
||||
b = sum;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
||||
class AsyncFibonacciComputeNode
|
||||
: public AsyncNode
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(AsyncFibonacciComputeNode, "{B198F52D-708C-414B-BB90-DFF0462D7F03}", AsyncNode);
|
||||
|
||||
AsyncFibonacciComputeNode()
|
||||
: AsyncNode()
|
||||
{}
|
||||
|
||||
bool IsEntryPoint() const { return true; }
|
||||
|
||||
static const int k_numberOfFibonacciDigits = 64;
|
||||
|
||||
static void Reflect(AZ::ReflectContext* reflection)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AsyncFibonacciComputeNode, AsyncNode>()
|
||||
->Version(1)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void OnActivate() override
|
||||
{
|
||||
AZ::TickBus::Handler::BusConnect();
|
||||
AsyncEventNotificationBus::Handler::BusConnect(GetEntityId());
|
||||
|
||||
int digits = k_numberOfFibonacciDigits;
|
||||
|
||||
std::promise<long> p;
|
||||
m_computeFuture = p.get_future();
|
||||
m_eventThread = AZStd::make_shared<AZStd::thread>([this, digits, p = AZStd::move(p)]() mutable
|
||||
{
|
||||
p.set_value(ComputeFibonacci(digits));
|
||||
AsyncEventNotificationBus::Event(GetEntityId(), &AsyncEvent::OnAsyncEvent);
|
||||
});
|
||||
}
|
||||
|
||||
void HandleAsyncEvent() override
|
||||
{
|
||||
m_result = m_computeFuture.get();
|
||||
|
||||
EXPECT_EQ(m_result, ComputeFibonacci(k_numberOfFibonacciDigits));
|
||||
}
|
||||
|
||||
void OnTick(float deltaTime, AZ::ScriptTimePoint) override
|
||||
{
|
||||
AZ_TracePrintf("Debug", "Awaiting async fib operation: %.2f\n", m_duration);
|
||||
m_duration += deltaTime;
|
||||
|
||||
if (m_result != 0)
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::future<long> m_computeFuture;
|
||||
long m_result = 0;
|
||||
double m_duration = 0.f;
|
||||
};
|
||||
|
||||
TEST_F(ScriptCanvasTestFixture, ComputeFibonacciAsyncGraphTest)
|
||||
{
|
||||
using namespace ScriptCanvas;
|
||||
|
||||
RegisterComponentDescriptor<AsyncNode>();
|
||||
RegisterComponentDescriptor<AsyncFibonacciComputeNode>();
|
||||
|
||||
// Make the graph.
|
||||
ScriptCanvas::Graph* graph =nullptr;
|
||||
SystemRequestBus::BroadcastResult(graph, &SystemRequests::MakeGraph);
|
||||
ASSERT_NE(graph, nullptr);
|
||||
|
||||
AZ::Entity* graphEntity = graph->GetEntity();
|
||||
graphEntity->Init();
|
||||
|
||||
const ScriptCanvasId& graphUniqueId = graph->GetScriptCanvasId();
|
||||
|
||||
AZ::EntityId startNodeId;
|
||||
CreateTestNode<ScriptCanvas::Nodes::Core::Start>(graphUniqueId, startNodeId);
|
||||
|
||||
AZ::EntityId asyncNodeId;
|
||||
CreateTestNode<AsyncFibonacciComputeNode>(graphUniqueId, asyncNodeId);
|
||||
|
||||
EXPECT_TRUE(Connect(*graph, startNodeId, "Out", asyncNodeId, "In"));
|
||||
|
||||
graphEntity->Activate();
|
||||
|
||||
// Tick the TickBus while the graph entity is active
|
||||
while (ScriptCanvasTestFixture::s_asyncOperationActive)
|
||||
{
|
||||
AZ::TickBus::ExecuteQueuedEvents();
|
||||
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(100));
|
||||
AZ::TickBus::Broadcast(&AZ::TickEvents::OnTick, 0.01f, AZ::ScriptTimePoint(AZStd::chrono::system_clock::now()));
|
||||
}
|
||||
|
||||
graphEntity->Deactivate();
|
||||
delete graphEntity;
|
||||
}
|
||||
|
||||
#endif // AZ_COMPILER_MSVC
|
||||
Loading…
Reference in New Issue