diff --git a/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl b/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl index 1016027966..dfd0707ed2 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl +++ b/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl @@ -123,6 +123,7 @@ namespace AZ const static AZ::Crc32 NameLabelOverride = AZ_CRC("NameLabelOverride", 0x9ff79cab); const static AZ::Crc32 AssetPickerTitle = AZ_CRC_CE("AssetPickerTitle"); + const static AZ::Crc32 HideProductFilesInAssetPicker = AZ_CRC_CE("HideProductFilesInAssetPicker"); const static AZ::Crc32 ChildNameLabelOverride = AZ_CRC("ChildNameLabelOverride", 0x73dd2909); //! Container attribute that is used to override labels for its elements given the index of the element const static AZ::Crc32 IndexedChildNameLabelOverride = AZ_CRC("IndexedChildNameLabelOverride", 0x5f313ac2); diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.cpp index b3ba1568bd..da046ff172 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.cpp @@ -10,6 +10,7 @@ * */ +#include #include #include #include @@ -88,4 +89,10 @@ namespace AzFramework { extensions.push_back(Spawnable::FileExtension); } + + uint32_t SpawnableAssetHandler::BuildSubId(AZStd::string_view id) + { + AZ::Uuid subIdHash = AZ::Uuid::CreateData(id.data(), id.size()); + return azlossy_caster(subIdHash.GetHash()); + } } // namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.h index deef314955..78268bf71a 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.h @@ -47,6 +47,7 @@ namespace AzFramework const char* GetGroup() const override; const char* GetBrowserIcon() const override; void GetAssetTypeExtensions(AZStd::vector& extensions) override; + static uint32_t BuildSubId(AZStd::string_view id); protected: LoadResult LoadAssetData( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/ProcesedObjectStore.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/ProcesedObjectStore.cpp index 78d1332a71..050afd813d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/ProcesedObjectStore.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/ProcesedObjectStore.cpp @@ -10,7 +10,7 @@ * */ -#include +#include #include namespace AzToolsFramework::Prefab::PrefabConversionUtils @@ -73,8 +73,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils uint32_t ProcessedObjectStore::BuildSubId(AZStd::string_view id) { - AZ::Uuid subIdHash = AZ::Uuid::CreateData(id.data(), id.size()); - return azlossy_caster(subIdHash.GetHash()); + return AzFramework::SpawnableAssetHandler::BuildSubId(id); } const AZStd::string& ProcessedObjectStore::GetId() const diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp index 23f8378df5..dd39cf9b97 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp @@ -777,6 +777,23 @@ namespace AzToolsFramework selection.SetDefaultDirectory(defaultDirectory); } + if (m_hideProductFilesInAssetPicker) + { + FilterConstType displayFilter = selection.GetDisplayFilter(); + + EntryTypeFilter* productsFilter = new EntryTypeFilter(); + productsFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Product); + + InverseFilter* noProductsFilter = new InverseFilter(); + noProductsFilter->SetFilter(FilterConstType(productsFilter)); + + CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND); + compFilter->AddFilter(FilterConstType(displayFilter)); + compFilter->AddFilter(FilterConstType(noProductsFilter)); + + selection.SetDisplayFilter(FilterConstType(compFilter)); + } + AssetBrowserComponentRequestBus::Broadcast(&AssetBrowserComponentRequests::PickAssets, selection, parentWidget()); if (selection.IsValid()) { @@ -1172,6 +1189,16 @@ namespace AzToolsFramework return m_showProductAssetName; } + void PropertyAssetCtrl::SetHideProductFilesInAssetPicker(bool hide) + { + m_hideProductFilesInAssetPicker = hide; + } + + bool PropertyAssetCtrl::GetHideProductFilesInAssetPicker() const + { + return m_hideProductFilesInAssetPicker; + } + void PropertyAssetCtrl::SetShowThumbnail(bool enable) { m_showThumbnail = enable; @@ -1297,6 +1324,14 @@ namespace AzToolsFramework GUI->SetShowProductAssetName(showProductAssetName); } } + else if(attrib == AZ::Edit::Attributes::HideProductFilesInAssetPicker) + { + bool hideProductFilesInAssetPicker = false; + if (attrValue->Read(hideProductFilesInAssetPicker)) + { + GUI->SetHideProductFilesInAssetPicker(hideProductFilesInAssetPicker); + } + } else if (attrib == AZ::Edit::Attributes::ClearNotify) { PropertyAssetCtrl::ClearCallbackType* func = azdynamic_cast(attrValue->GetAttribute()); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx index 37af3d0594..5a6310eb35 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx @@ -158,6 +158,10 @@ namespace AzToolsFramework //! Assets can be either source or product assets generated from source assets. By default, source assets are shown in the property asset. You can override that with this flag. bool m_showProductAssetName = true; + //! Assets can be either source or product assets generated from source assets. + //! By default the asset picker shows both on an AZ::Asset<> property. You can hide product assets with this flag. + bool m_hideProductFilesInAssetPicker = false; + bool m_showThumbnail = false; bool m_showThumbnailDropDownButton = false; EditCallbackType* m_thumbnailCallback = nullptr; @@ -211,6 +215,9 @@ namespace AzToolsFramework void SetShowProductAssetName(bool enable); bool GetShowProductAssetName() const; + void SetHideProductFilesInAssetPicker(bool hide); + bool GetHideProductFilesInAssetPicker() const; + void SetShowThumbnail(bool enable); bool GetShowThumbnail() const; void SetShowThumbnailDropDownButton(bool enable); diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.h b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.h index 1d1ea1d4aa..fc9613c3a7 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.h +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.h @@ -59,6 +59,7 @@ namespace ScriptCanvasBuilder QuantumLeap, DependencyArguments, DependencyRequirementsData, + AddAssetDependencySearch, // add new entries above Current, }; diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp index ab59ddd840..ba22789cd1 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp @@ -681,6 +681,19 @@ namespace ScriptCanvasBuilder } AssetBuilderSDK::JobProduct jobProduct; + + // Scan our runtime input for any asset references + // Store them as product dependencies + AssetBuilderSDK::OutputObject(&runtimeData.m_input, + azrtti_typeid(), + input.runtimeScriptCanvasOutputPath, + azrtti_typeid(), + AZ_CRC("RuntimeData", 0x163310ae), jobProduct); + + // Output Object marks dependencies as handled. + // We still have more to evaluate + jobProduct.m_dependenciesHandled = false; + jobProduct.m_dependencies.push_back({ runtimeData.m_script.GetId(), {} }); for (const auto& assetDependency : runtimeData.m_requiredAssets) @@ -713,9 +726,6 @@ namespace ScriptCanvasBuilder } jobProduct.m_dependenciesHandled = true; - jobProduct.m_productFileName = input.runtimeScriptCanvasOutputPath; - jobProduct.m_productAssetType = azrtti_typeid(); - jobProduct.m_productSubID = AZ_CRC("RuntimeData", 0x163310ae); input.response->m_outputProducts.push_back(AZStd::move(jobProduct)); return AZ::Success(); } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Libraries.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Libraries.cpp index 641bdca8f7..8c2671ac6d 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Libraries.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Libraries.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,7 @@ namespace ScriptCanvas Entity::InitNodeRegistry(*g_nodeRegistry); Comparison::InitNodeRegistry(*g_nodeRegistry); Time::InitNodeRegistry(*g_nodeRegistry); + Spawning::InitNodeRegistry(*g_nodeRegistry); String::InitNodeRegistry(*g_nodeRegistry); Operators::InitNodeRegistry(*g_nodeRegistry); @@ -61,6 +63,7 @@ namespace ScriptCanvas Entity::Reflect(reflectContext); Comparison::Reflect(reflectContext); Time::Reflect(reflectContext); + Spawning::Reflect(reflectContext); String::Reflect(reflectContext); Operators::Reflect(reflectContext); @@ -90,6 +93,9 @@ namespace ScriptCanvas componentDescriptors = Time::GetComponentDescriptors(); libraryDescriptors.insert(libraryDescriptors.end(), componentDescriptors.begin(), componentDescriptors.end()); + componentDescriptors = Spawning::GetComponentDescriptors(); + libraryDescriptors.insert(libraryDescriptors.end(), componentDescriptors.begin(), componentDescriptors.end()); + componentDescriptors = String::GetComponentDescriptors(); libraryDescriptors.insert(libraryDescriptors.end(), componentDescriptors.begin(), componentDescriptors.end()); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Libraries.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Libraries.h index 3388a029ac..67094f4db8 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Libraries.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Libraries.h @@ -143,6 +143,17 @@ namespace ScriptCanvas }; + struct Spawning : public LibraryDefinition + { + AZ_RTTI(Spawning, "{41E910AE-FBD2-41AD-9173-5105141F0466}", LibraryDefinition); + + static void Reflect(AZ::ReflectContext*); + static void InitNodeRegistry(NodeRegistry& nodeRegistry); + static AZStd::vector GetComponentDescriptors(); + + ~Spawning() override = default; + }; + struct String : public LibraryDefinition { AZ_RTTI(String, "{5B700838-21A2-4579-9303-F4A4822AFEF4}", LibraryDefinition); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.ScriptCanvasNodeable.xml b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.ScriptCanvasNodeable.xml new file mode 100644 index 0000000000..e9b1ce9f4e --- /dev/null +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.ScriptCanvasNodeable.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + /> + + + + + + + + + + + + diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.cpp new file mode 100644 index 0000000000..b93844b989 --- /dev/null +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.cpp @@ -0,0 +1,139 @@ +/* +* 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 + +#include +#include + +namespace ScriptCanvas::Nodeables::Spawning +{ + SpawnNodeable::SpawnNodeable(const SpawnNodeable& rhs) + : m_spawnableAsset(rhs.m_spawnableAsset) + {} + + SpawnNodeable& SpawnNodeable::operator=(SpawnNodeable& rhs) + { + m_spawnableAsset = rhs.m_spawnableAsset; + return *this; + } + + void SpawnNodeable::OnInitializeExecutionState() + { + if (!AZ::TickBus::Handler::BusIsConnected()) + { + AZ::TickBus::Handler::BusConnect(); + } + + m_spawnTicket = AzFramework::EntitySpawnTicket(m_spawnableAsset); + } + + void SpawnNodeable::OnDeactivate() + { + AZ::TickBus::Handler::BusDisconnect(); + + m_spawnTicket = AzFramework::EntitySpawnTicket(); + } + + void SpawnNodeable::OnTick([[maybe_unused]] float delta, [[maybe_unused]] AZ::ScriptTimePoint timePoint) + { + AZStd::vector swappedSpawnedEntityList; + AZStd::vector swappedSpawnBatchSizes; + { + AZStd::lock_guard lock(m_idBatchMutex); + + swappedSpawnedEntityList.swap(m_spawnedEntityList); + swappedSpawnBatchSizes.swap(m_spawnBatchSizes); + } + + AZ::EntityId* batchBegin = swappedSpawnedEntityList.data(); + for (size_t batchSize : swappedSpawnBatchSizes) + { + if (batchSize == 0) + { + continue; + } + + AZStd::vector spawnedEntitiesBatch( + batchBegin, batchBegin + batchSize); + + CallOnSpawn(AZStd::move(spawnedEntitiesBatch)); + + batchBegin += batchSize; + } + } + + void SpawnNodeable::OnSpawnAssetChanged() + { + if (m_spawnableAsset.GetId().IsValid()) + { + AZStd::string rootSpawnableFile; + AzFramework::StringFunc::Path::GetFileName(m_spawnableAsset.GetHint().c_str(), rootSpawnableFile); + + rootSpawnableFile += AzFramework::Spawnable::DotFileExtension; + + AZ::u32 rootSubId = AzFramework::SpawnableAssetHandler::BuildSubId(AZStd::move(rootSpawnableFile)); + + if (m_spawnableAsset.GetId().m_subId != rootSubId) + { + AZ::Data::AssetId rootAssetId = m_spawnableAsset.GetId(); + rootAssetId.m_subId = rootSubId; + + m_spawnableAsset = AZ::Data::AssetManager::Instance(). + FindOrCreateAsset(rootAssetId, AZ::Data::AssetLoadBehavior::Default); + } + else + { + m_spawnableAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::Default); + } + } + } + + void SpawnNodeable::RequestSpawn(Data::Vector3Type translation, Data::Vector3Type rotation, Data::NumberType scale) + { + if (m_spawnableAsset.GetAutoLoadBehavior() == AZ::Data::AssetLoadBehavior::NoLoad) + { + return; + } + + auto preSpawnCB = [this, translation, rotation, scale]([[maybe_unused]] AzFramework::EntitySpawnTicket& ticket, + AzFramework::SpawnableEntityContainerView view) + { + AZ::Entity* rootEntity = *view.begin(); + + AzFramework::TransformComponent* entityTransform = + rootEntity->FindComponent(); + + if (entityTransform) + { + AZ::Vector3 rotationCopy = rotation; + AZ::Quaternion rotationQuat = AZ::Quaternion::CreateFromEulerAnglesDegrees(rotationCopy); + + entityTransform->SetWorldTM(AZ::Transform(translation, rotationQuat, AZ::Vector3(scale, scale, scale))); + } + }; + + auto spawnCompleteCB = [this]([[maybe_unused]] AzFramework::EntitySpawnTicket& ticket, + AzFramework::SpawnableConstEntityContainerView view) + { + AZStd::lock_guard lock(m_idBatchMutex); + m_spawnedEntityList.reserve(m_spawnedEntityList.size() + view.size()); + for (const AZ::Entity* entity : view) + { + m_spawnedEntityList.emplace_back(entity->GetId()); + } + m_spawnBatchSizes.push_back(view.size()); + }; + + AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(m_spawnTicket, preSpawnCB, spawnCompleteCB); + } +} diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.h new file mode 100644 index 0000000000..0f3a27d2ea --- /dev/null +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.h @@ -0,0 +1,52 @@ +/* +* 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 + +#include + +#include + +#include +#include +#include + +namespace ScriptCanvas::Nodeables::Spawning +{ + class SpawnNodeable + : public ScriptCanvas::Nodeable, + public AZ::TickBus::Handler + { + SCRIPTCANVAS_NODE(SpawnNodeable); + public: + SpawnNodeable() = default; + SpawnNodeable(const SpawnNodeable& rhs); + SpawnNodeable& operator=(SpawnNodeable& rhs); + + void OnInitializeExecutionState() override; + void OnDeactivate() override; + + //TickBus + void OnTick(float delta, AZ::ScriptTimePoint timePoint) override; + + void OnSpawnAssetChanged(); + + private: + AzFramework::EntitySpawnTicket m_spawnTicket; + + AZStd::vector m_spawnedEntityList; + AZStd::vector m_spawnBatchSizes; + AZStd::recursive_mutex m_idBatchMutex; + }; +} diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/Spawning.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/Spawning.cpp new file mode 100644 index 0000000000..6591950b77 --- /dev/null +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/Spawning.cpp @@ -0,0 +1,50 @@ +/* +* 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 +#include + +namespace ScriptCanvas +{ + namespace Library + { + void Spawning::Reflect(AZ::ReflectContext* reflection) + { + if (AZ::SerializeContext* serializeContext = azrtti_cast(reflection)) + { + serializeContext->Class() + ->Version(1) + ; + + AZ::EditContext* editContext = serializeContext->GetEditContext(); + if (editContext) + { + editContext->Class("Spawning", "") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::Icon, "Icons/ScriptCanvas/Libraries/Entity.png"); + } + } + } + + void Spawning::InitNodeRegistry(NodeRegistry& nodeRegistry) + { + AddNodeToRegistry(nodeRegistry); + } + + AZStd::vector Spawning::GetComponentDescriptors() + { + return AZStd::vector({ + ScriptCanvas::Nodes::SpawnNodeableNode::CreateDescriptor(), + }); + } + } +} diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/Spawning.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/Spawning.h new file mode 100644 index 0000000000..fa92ee97a9 --- /dev/null +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/Spawning.h @@ -0,0 +1,17 @@ +/* +* 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 + +// This header is only meant to include the nodes and should not contain +// shared code +#include diff --git a/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake b/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake index 84391021df..f0be1accc9 100644 --- a/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake +++ b/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake @@ -454,6 +454,11 @@ set(FILES Include/ScriptCanvas/Libraries/Time/TimerNodeable.h Include/ScriptCanvas/Libraries/Time/TimerNodeable.cpp Include/ScriptCanvas/Libraries/Time/TimerNodeable.ScriptCanvasNodeable.xml + Include/ScriptCanvas/Libraries/Spawning/Spawning.cpp + Include/ScriptCanvas/Libraries/Spawning/Spawning.h + Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.cpp + Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.h + Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.ScriptCanvasNodeable.xml Include/ScriptCanvas/Libraries/String/Contains.cpp Include/ScriptCanvas/Libraries/String/Contains.h Include/ScriptCanvas/Libraries/String/Contains.ScriptCanvasGrammar.xml