diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 77099761c1..1c4e22b99e 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -1352,8 +1352,27 @@ void CCryEditApp::CompileCriticalAssets() const } } assetsInQueueNotifcation.BusDisconnect(); - CCryEditApp::OutputStartupMessage(QString("Asset Processor is now ready.")); + // Signal the "CriticalAssetsCompiled" lifecycle event + // Also reload the "assetcatalog.xml" if it exists + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + AZ::ComponentApplicationLifecycle::SignalEvent(*settingsRegistry, "CriticalAssetsCompiled", R"({})"); + // Reload the assetcatalog.xml at this point again + // Start Monitoring Asset changes over the network and load the AssetCatalog + auto LoadCatalog = [settingsRegistry](AZ::Data::AssetCatalogRequests* assetCatalogRequests) + { + if (AZ::IO::FixedMaxPath assetCatalogPath; + settingsRegistry->Get(assetCatalogPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder)) + { + assetCatalogPath /= "assetcatalog.xml"; + assetCatalogRequests->LoadCatalog(assetCatalogPath.c_str()); + } + }; + AZ::Data::AssetCatalogRequestBus::Broadcast(AZStd::move(LoadCatalog)); + } + + CCryEditApp::OutputStartupMessage(QString("Asset Processor is now ready.")); } bool CCryEditApp::ConnectToAssetProcessor() const @@ -1669,7 +1688,7 @@ bool CCryEditApp::InitInstance() return false; } - if (AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get()) + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) { AZ::ComponentApplicationLifecycle::SignalEvent(*settingsRegistry, "LegacySystemInterfaceCreated", R"({})"); } diff --git a/Code/Framework/AzFramework/AzFramework/FileTag/FileTagComponent.cpp b/Code/Framework/AzFramework/AzFramework/FileTag/FileTagComponent.cpp index 1d09500415..f4831d1f8b 100644 --- a/Code/Framework/AzFramework/AzFramework/FileTag/FileTagComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/FileTag/FileTagComponent.cpp @@ -97,19 +97,38 @@ namespace AzFramework AZStd::vector registeredAssetPaths; AZ::Data::AssetCatalogRequestBus::BroadcastResult(registeredAssetPaths, &AZ::Data::AssetCatalogRequests::GetRegisteredAssetPaths); - const char* dependencyXmlPattern = "*_dependencies.xml"; + constexpr const char* dependencyXmlPattern = "_dependencies.xml"; for (const AZStd::string& assetPath : registeredAssetPaths) { - if (!AZStd::wildcard_match(dependencyXmlPattern, assetPath.c_str())) + if (assetPath.ends_with(dependencyXmlPattern)) { - continue; - } - - if (!m_excludeFileQueryManager.get()->LoadEngineDependencies(assetPath)) - { - AZ_Error("ExcludeFileComponent", false, "Failed to add assets referenced from %s to the blocked list", assetPath.c_str()); + AZ_VerifyError("ExcludeFileComponent", m_excludeFileQueryManager.get()->LoadEngineDependencies(assetPath), + "Failed to add assets referenced from %s to the blocked list", assetPath.c_str()); } } } + + void ExcludeFileComponent::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) + { + // Reload any modified "_dependencies.xml" files + AZ::IO::Path assetPath; + auto GetAssetPath = [&assetId, &assetPath](AZ::Data::AssetCatalogRequests* assetCatalogRequests) + { + assetPath = assetCatalogRequests->GetAssetPathById(assetId); + }; + + AZ::Data::AssetCatalogRequestBus::Broadcast(AZStd::move(GetAssetPath)); + constexpr const char* dependencyXmlPattern = "_dependencies.xml"; + if (assetPath.Native().ends_with(dependencyXmlPattern)) + { + AZ_VerifyError("ExcludeFileComponent", m_excludeFileQueryManager.get()->LoadEngineDependencies(assetPath.Native()), + "Failed to add assets referenced from %s to the blocked list", assetPath.c_str()); + } + } + + void ExcludeFileComponent::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) + { + OnCatalogAssetChanged(assetId); + } } } diff --git a/Code/Framework/AzFramework/AzFramework/FileTag/FileTagComponent.h b/Code/Framework/AzFramework/AzFramework/FileTag/FileTagComponent.h index d53e4e7a89..1bd0f46aa0 100644 --- a/Code/Framework/AzFramework/AzFramework/FileTag/FileTagComponent.h +++ b/Code/Framework/AzFramework/AzFramework/FileTag/FileTagComponent.h @@ -65,6 +65,8 @@ namespace AzFramework void Deactivate() override; void OnCatalogLoaded(const char* catalogFile) override; + void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override; + void OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) override; static void Reflect(AZ::ReflectContext* context); diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.cpp index 6ca2f3a53a..4ba9c45a98 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -61,15 +62,6 @@ namespace AzFramework m_entitiesManager.ProcessQueue(SpawnableEntitiesManager::CommandQueuePriority::High); } - void SpawnableSystemComponent::OnCatalogLoaded([[maybe_unused]] const char* catalogFile) - { - if (!m_catalogAvailable) - { - m_catalogAvailable = true; - LoadRootSpawnableFromSettingsRegistry(); - } - } - uint64_t SpawnableSystemComponent::AssignRootSpawnable(AZ::Data::Asset rootSpawnable) { uint32_t generation = 0; @@ -157,20 +149,29 @@ namespace AzFramework // Register with AssetDatabase AZ_Assert(AZ::Data::AssetManager::IsReady(), "Spawnables can't be registered because the Asset Manager is not ready yet."); AZ::Data::AssetManager::Instance().RegisterHandler(&m_assetHandler, AZ::AzTypeInfo::Uuid()); - + // Register with AssetCatalog AZ::Data::AssetCatalogRequestBus::Broadcast( &AZ::Data::AssetCatalogRequestBus::Events::EnableCatalogForAsset, AZ::AzTypeInfo::Uuid()); AZ::Data::AssetCatalogRequestBus::Broadcast( &AZ::Data::AssetCatalogRequestBus::Events::AddExtension, Spawnable::FileExtension); - AssetCatalogEventBus::Handler::BusConnect(); + // Register for the CriticalAssetsCompiled lifecycle event to trigger the loading of the root spawnable + auto settingsRegistry = AZ::SettingsRegistry::Get(); + AZ_Assert(settingsRegistry, "Unable to change root spawnable callback because Settings Registry is not available."); + + auto LifecycleCallback = [this](AZStd::string_view, AZ::SettingsRegistryInterface::Type) + { + LoadRootSpawnableFromSettingsRegistry(); + }; + AZ::ComponentApplicationLifecycle::RegisterHandler(*settingsRegistry, m_criticalAssetsHandler, + AZStd::move(LifecycleCallback), "CriticalAssetsCompiled"); + + RootSpawnableNotificationBus::Handler::BusConnect(); AZ::TickBus::Handler::BusConnect(); - auto registry = AZ::SettingsRegistry::Get(); - AZ_Assert(registry, "Unable to change root spawnable callback because Settings Registry is not available."); - m_registryChangeHandler = registry->RegisterNotifier([this](AZStd::string_view path, AZ::SettingsRegistryInterface::Type /*type*/) + m_registryChangeHandler = settingsRegistry->RegisterNotifier([this](AZStd::string_view path, AZ::SettingsRegistryInterface::Type /*type*/) { if (path.starts_with(RootSpawnableRegistryKey)) { @@ -187,13 +188,14 @@ namespace AzFramework AZ::TickBus::Handler::BusDisconnect(); RootSpawnableNotificationBus::Handler::BusDisconnect(); - AssetCatalogEventBus::Handler::BusDisconnect(); + // Unregister Lifecycle event handler + m_criticalAssetsHandler = {}; - if (m_catalogAvailable) + if (m_rootSpawnableId.IsValid()) { ReleaseRootSpawnable(); - // The SpawnalbleSystemComponent needs to guarantee there's no more processing left to do by the + // The SpawnableSystemComponent needs to guarantee there's no more processing left to do by the // entity manager before it can safely destroy it on shutdown, but also to make sure that are no // more calls to the callback registered to the root spawnable as that accesses this component. m_rootSpawnableContainer.Clear(); @@ -210,8 +212,6 @@ namespace AzFramework void SpawnableSystemComponent::LoadRootSpawnableFromSettingsRegistry() { - AZ_Assert(m_catalogAvailable, "Attempting to load root spawnable while the catalog is not available yet."); - auto registry = AZ::SettingsRegistry::Get(); AZ_Assert(registry, "Unable to check for root spawnable because the Settings Registry is not available."); diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.h index ecd2a9b728..712cd1529d 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -25,7 +24,6 @@ namespace AzFramework : public AZ::Component , public AZ::TickBus::Handler , public AZ::SystemTickBus::Handler - , public AssetCatalogEventBus::Handler , public RootSpawnableInterface::Registrar , public RootSpawnableNotificationBus::Handler { @@ -63,12 +61,6 @@ namespace AzFramework void OnSystemTick() override; - // - // AssetCatalogEventBus - // - - void OnCatalogLoaded(const char* catalogFile) override; - // // RootSpawnableInterface // @@ -97,6 +89,6 @@ namespace AzFramework AZ::SettingsRegistryInterface::NotifyEventHandler m_registryChangeHandler; AZ::Data::AssetId m_rootSpawnableId; - bool m_catalogAvailable{ false }; + AZ::SettingsRegistryInterface::NotifyEventHandler m_criticalAssetsHandler; }; } // namespace AzFramework diff --git a/Code/LauncherUnified/Launcher.cpp b/Code/LauncherUnified/Launcher.cpp index ed01a67f39..9dfd6213c4 100644 --- a/Code/LauncherUnified/Launcher.cpp +++ b/Code/LauncherUnified/Launcher.cpp @@ -229,33 +229,65 @@ namespace O3DELauncher void CreateRemoteFileIO(); - bool ConnectToAssetProcessor() + // This function make sure the launcher has signaled the "CriticalAssetsCompiled" + // lifecycle event as well as to load the "assetcatalog.xml" file if it exists + void CompileCriticalAssets() { - bool connectedToAssetProcessor{}; - // When the AssetProcessor is already launched it should take less than a second to perform a connection - // but when the AssetProcessor needs to be launch it could take up to 15 seconds to have the AssetProcessor initialize - // and able to negotiate a connection when running a debug build - // and to negotiate a connection - // Setting the connectTimeout to 3 seconds if not set within the settings registry - - AzFramework::AssetSystem::ConnectionSettings connectionSettings; - AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings); - - connectionSettings.m_launchAssetProcessorOnFailedConnection = true; - connectionSettings.m_connectionIdentifier = AzFramework::AssetSystem::ConnectionIdentifiers::Game; - connectionSettings.m_loggingCallback = []([[maybe_unused]] AZStd::string_view logData) + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) { - AZ_TracePrintf("Launcher", "%.*s", aznumeric_cast(logData.size()), logData.data()); - }; + AZ::ComponentApplicationLifecycle::SignalEvent(*settingsRegistry, "CriticalAssetsCompiled", R"({})"); + // Reload the assetcatalog.xml at this point again + // Start Monitoring Asset changes over the network and load the AssetCatalog + auto LoadCatalog = [settingsRegistry](AZ::Data::AssetCatalogRequests* assetCatalogRequests) + { + if (AZ::IO::FixedMaxPath assetCatalogPath; + settingsRegistry->Get(assetCatalogPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder)) + { + assetCatalogPath /= "assetcatalog.xml"; + assetCatalogRequests->LoadCatalog(assetCatalogPath.c_str()); + } + }; + AZ::Data::AssetCatalogRequestBus::Broadcast(AZStd::move(LoadCatalog)); + } + } - AzFramework::AssetSystemRequestBus::BroadcastResult(connectedToAssetProcessor, &AzFramework::AssetSystemRequestBus::Events::EstablishAssetProcessorConnection, connectionSettings); - - if (connectedToAssetProcessor) + // If the connect option is false, this function will return true + // to make sure the Launcher passes the connected to AP check + // If REMOTE_ASSET_PROCESSOR is not defined, then the launcher doesn't need + // to connect to the AssetProcessor and therefore this function returns true + bool ConnectToAssetProcessor([[maybe_unused]] bool connect) + { + bool connectedToAssetProcessor = true; +#if defined(REMOTE_ASSET_PROCESSOR) + if (connect) { - AZ_TracePrintf("Launcher", "Connected to Asset Processor\n"); - CreateRemoteFileIO(); + // When the AssetProcessor is already launched it should take less than a second to perform a connection + // but when the AssetProcessor needs to be launch it could take up to 15 seconds to have the AssetProcessor initialize + // and able to negotiate a connection when running a debug build + // and to negotiate a connection + // Setting the connectTimeout to 3 seconds if not set within the settings registry + + AzFramework::AssetSystem::ConnectionSettings connectionSettings; + AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings); + + connectionSettings.m_launchAssetProcessorOnFailedConnection = true; + connectionSettings.m_connectionIdentifier = AzFramework::AssetSystem::ConnectionIdentifiers::Game; + connectionSettings.m_loggingCallback = []([[maybe_unused]] AZStd::string_view logData) + { + AZ_TracePrintf("Launcher", "%.*s", aznumeric_cast(logData.size()), logData.data()); + }; + + AzFramework::AssetSystemRequestBus::BroadcastResult(connectedToAssetProcessor, &AzFramework::AssetSystemRequestBus::Events::EstablishAssetProcessorConnection, connectionSettings); + + if (connectedToAssetProcessor) + { + AZ_TracePrintf("Launcher", "Connected to Asset Processor\n"); + CreateRemoteFileIO(); + } } +#endif + CompileCriticalAssets(); return connectedToAssetProcessor; } @@ -403,25 +435,21 @@ namespace O3DELauncher gameApplication.Start({}, gameApplicationStartupParams); -#if defined(REMOTE_ASSET_PROCESSOR) - bool allowedEngineConnection = !systemInitParams.bToolMode && !systemInitParams.bTestMode && bg_ConnectToAssetProcessor; //connect to the asset processor using the bootstrap values - if (allowedEngineConnection) + const bool allowedEngineConnection = !systemInitParams.bToolMode && !systemInitParams.bTestMode && bg_ConnectToAssetProcessor; + if (!ConnectToAssetProcessor(allowedEngineConnection)) { - if (!ConnectToAssetProcessor()) + AZ::s64 waitForConnect{}; + AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, waitForConnect, + AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey, "wait_for_connect"); + if (waitForConnect != 0) { - AZ::s64 waitForConnect{}; - AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, waitForConnect, - AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey, "wait_for_connect"); - if (waitForConnect != 0) - { - AZ_Error("Launcher", false, "Failed to connect to AssetProcessor."); - return ReturnCode::ErrAssetProccessor; - } + AZ_Error("Launcher", false, "Failed to connect to AssetProcessor."); + return ReturnCode::ErrAssetProccessor; } } -#endif + AZ_Assert(AZ::AllocatorInstance::IsReady(), "System allocator was not created or creation failed."); //Initialize the Debug trace instance to create necessary environment variables AZ::Debug::Trace::Instance().Init(); diff --git a/Code/Tools/SerializeContextTools/SliceConverter.cpp b/Code/Tools/SerializeContextTools/SliceConverter.cpp index d0528a9cad..cfb1998f48 100644 --- a/Code/Tools/SerializeContextTools/SliceConverter.cpp +++ b/Code/Tools/SerializeContextTools/SliceConverter.cpp @@ -79,10 +79,6 @@ namespace AZ return false; } - // Load the asset catalog so that we can find any nested assets successfully. We also need to tick the tick bus - // so that the OnCatalogLoaded event gets processed now, instead of during application shutdown. - application.Tick(); - AZStd::string logggingScratchBuffer; SetupLogging(logggingScratchBuffer, convertSettings.m_reporting, *commandLine); diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp index 84fc58718c..ef03a839d7 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp @@ -155,7 +155,7 @@ namespace AZ { Initialize(); }, - "LegacySystemInterfaceCreated"); + "CriticalAssetsCompiled"); } } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystemInterface.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystemInterface.h index 3f30d498cf..693185b6d2 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystemInterface.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystemInterface.h @@ -34,8 +34,7 @@ namespace AZ RPISystemInterface() = default; virtual ~RPISystemInterface() = default; - //! Pre-load some system assets. This should be called once the asset catalog is ready and before create any RPI instances. - //! Note: can't rely on the AzFramework::AssetCatalogEventBus's OnCatalogLoaded since the order of calling handlers is undefined. + //! Pre-load some system assets. This should be called once Critical Asset have compiled ready and before create any RPI instances. virtual void InitializeSystemAssets() = 0; //! Was the RPI system initialized properly diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index ec365d7a6a..02248fffd4 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -295,10 +296,24 @@ namespace AtomToolsFramework QMessageBox::critical( activeWindow(), QString("Failed to compile critical assets"), QString("Failed to compile the following critical assets:\n%1\n%2") - .arg(failedAssets.join(",\n")) - .arg("Make sure this is an Atom project.")); + .arg(failedAssets.join(",\n")) + .arg("Make sure this is an Atom project.")); ExitMainLoop(); } + + AZ::ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "CriticalAssetsCompiled", R"({})"); + // Reload the assetcatalog.xml at this point again + // Start Monitoring Asset changes over the network and load the AssetCatalog + auto LoadCatalog = [settingsRegistry = m_settingsRegistry.get()](AZ::Data::AssetCatalogRequests* assetCatalogRequests) + { + if (AZ::IO::FixedMaxPath assetCatalogPath; + settingsRegistry->Get(assetCatalogPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder)) + { + assetCatalogPath /= "assetcatalog.xml"; + assetCatalogRequests->LoadCatalog(assetCatalogPath.c_str()); + } + }; + AZ::Data::AssetCatalogRequestBus::Broadcast(AZStd::move(LoadCatalog)); } void AtomToolsApplication::SaveSettings() diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp index 35f5067cd0..9cf714b40e 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -165,12 +165,12 @@ namespace MaterialEditor // AssetCatalogRequestBus::EnumerateAssets can lead to deadlocked) AZ::Data::AssetCatalogRequests::AssetEnumerationCB enumerateCB = [this]([[maybe_unused]] const AZ::Data::AssetId id, const AZ::Data::AssetInfo& info) { - if (AzFramework::StringFunc::EndsWith(info.m_relativePath.c_str(), ".lightingpreset.azasset")) + if (AZ::StringFunc::EndsWith(info.m_relativePath.c_str(), ".lightingpreset.azasset")) { m_lightingPresetAssets[info.m_assetId] = { info.m_assetId, info.m_assetType }; AZ::Data::AssetBus::MultiHandler::BusConnect(info.m_assetId); } - else if (AzFramework::StringFunc::EndsWith(info.m_relativePath.c_str(), ".modelpreset.azasset")) + else if (AZ::StringFunc::EndsWith(info.m_relativePath.c_str(), ".modelpreset.azasset")) { m_modelPresetAssets[info.m_assetId] = { info.m_assetId, info.m_assetType }; AZ::Data::AssetBus::MultiHandler::BusConnect(info.m_assetId); @@ -429,4 +429,51 @@ namespace MaterialEditor ReloadContent(); }); } + + void MaterialViewportComponent::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) + { + auto ReloadLightingAndModelPresets = [this, &assetId](AZ::Data::AssetCatalogRequests* assetCatalogRequests) + { + AZ::Data::AssetInfo assetInfo = assetCatalogRequests->GetAssetInfoById(assetId); + AZ::Data::Asset* modifiedPresetAsset{}; + if (AZ::StringFunc::EndsWith(assetInfo.m_relativePath.c_str(), ".lightingpreset.azasset")) + { + m_lightingPresetAssets[assetInfo.m_assetId] = { assetInfo.m_assetId, assetInfo.m_assetType }; + AZ::Data::AssetBus::MultiHandler::BusConnect(assetInfo.m_assetId); + modifiedPresetAsset = &m_lightingPresetAssets[assetInfo.m_assetId]; + } + else if (AzFramework::StringFunc::EndsWith(assetInfo.m_relativePath.c_str(), ".modelpreset.azasset")) + { + m_modelPresetAssets[assetInfo.m_assetId] = { assetInfo.m_assetId, assetInfo.m_assetType }; + AZ::Data::AssetBus::MultiHandler::BusConnect(assetInfo.m_assetId); + modifiedPresetAsset = &m_modelPresetAssets[assetInfo.m_assetId]; + } + + // Queue a load on the changed asset + if (modifiedPresetAsset != nullptr) + { + modifiedPresetAsset->QueueLoad(); + } + }; + AZ::Data::AssetCatalogRequestBus::Broadcast(AZStd::move(ReloadLightingAndModelPresets)); + } + + void MaterialViewportComponent::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) + { + OnCatalogAssetChanged(assetId); + } + + void MaterialViewportComponent::OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& assetInfo) + { + if (AZ::StringFunc::EndsWith(assetInfo.m_relativePath.c_str(), ".lightingpreset.azasset")) + { + AZ::Data::AssetBus::MultiHandler::BusDisconnect(assetInfo.m_assetId); + m_lightingPresetAssets.erase(assetId); + } + if (AZ::StringFunc::EndsWith(assetInfo.m_relativePath.c_str(), ".modelpreset.azasset")) + { + AZ::Data::AssetBus::MultiHandler::BusDisconnect(assetInfo.m_assetId); + m_modelPresetAssets.erase(assetId); + } + } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.h index 07385d842d..68668bd804 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.h @@ -95,6 +95,9 @@ namespace MaterialEditor //////////////////////////////////////////////////////////////////////// // AzFramework::AssetCatalogEventBus::Handler overrides ... void OnCatalogLoaded(const char* catalogFile) override; + void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override; + void OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) override; + void OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& assetInfo) override; //////////////////////////////////////////////////////////////////////// AZStd::unordered_map> m_lightingPresetAssets; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/EditorCommonFeaturesSystemComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/EditorCommonFeaturesSystemComponent.cpp index 2bf428bd2d..0250640d65 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/EditorCommonFeaturesSystemComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/EditorCommonFeaturesSystemComponent.cpp @@ -6,6 +6,7 @@ * */ +#include #include #include #include @@ -88,14 +89,22 @@ namespace AZ AzToolsFramework::EditorLevelNotificationBus::Handler::BusConnect(); AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler::BusConnect(); - AzFramework::AssetCatalogEventBus::Handler::BusConnect(); + if (auto settingsRegistry{ AZ::SettingsRegistry::Get() }; settingsRegistry != nullptr) + { + auto LifecycleCallback = [this](AZStd::string_view, AZ::SettingsRegistryInterface::Type) + { + SetupThumbnails(); + }; + AZ::ComponentApplicationLifecycle::RegisterHandler(*settingsRegistry, m_criticalAssetsHandler, + AZStd::move(LifecycleCallback), "CriticalAssetsCompiled"); + } AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect(); } void EditorCommonFeaturesSystemComponent::Deactivate() { AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect(); - AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); + m_criticalAssetsHandler = {}; AzToolsFramework::EditorLevelNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler::BusDisconnect(); @@ -192,13 +201,6 @@ namespace AZ } } - void EditorCommonFeaturesSystemComponent::OnCatalogLoaded([[maybe_unused]] const char* catalogFile) - { - AZ::TickBus::QueueFunction([this](){ - SetupThumbnails(); - }); - } - const AzToolsFramework::AssetBrowser::PreviewerFactory* EditorCommonFeaturesSystemComponent::GetPreviewerFactory( const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const { diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/EditorCommonFeaturesSystemComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/EditorCommonFeaturesSystemComponent.h index 82bb93a808..dff9e68814 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/EditorCommonFeaturesSystemComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/EditorCommonFeaturesSystemComponent.h @@ -28,7 +28,6 @@ namespace AZ , public AzToolsFramework::EditorLevelNotificationBus::Handler , public AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler , public AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler - , public AzFramework::AssetCatalogEventBus::Handler , public AzFramework::ApplicationLifecycleEvents::Bus::Handler { public: @@ -58,9 +57,6 @@ namespace AZ const AZ::Data::AssetId&, AZ::SliceComponent::SliceInstanceAddress&, const AzFramework::SliceInstantiationTicket&) override; void OnSliceInstantiationFailed(const AZ::Data::AssetId&, const AzFramework::SliceInstantiationTicket&) override; - // AzFramework::AssetCatalogEventBus::Handler overrides ... - void OnCatalogLoaded(const char* catalogFile) override; - // AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler overrides... const AzToolsFramework::AssetBrowser::PreviewerFactory* GetPreviewerFactory( const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const override; @@ -80,6 +76,7 @@ namespace AZ AZStd::unique_ptr m_thumbnailRenderer; AZStd::unique_ptr m_previewerFactory; + AZ::SettingsRegistryInterface::NotifyEventHandler m_criticalAssetsHandler; }; } // namespace Render } // namespace AZ diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp index f112098eae..c8c1ed15bd 100644 --- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp +++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp @@ -58,7 +58,7 @@ namespace Multiplayer { ActivateDedicatedEditorServer(); }, - "LegacySystemInterfaceCreated"); + "CriticalAssetsCompiled"); } } } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp index ba8836b6e6..f60778dbb4 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -17,12 +18,20 @@ namespace Multiplayer NetworkSpawnableLibrary::NetworkSpawnableLibrary() { AZ::Interface::Register(this); - AzFramework::AssetCatalogEventBus::Handler::BusConnect(); + if (auto settingsRegistry{ AZ::SettingsRegistry::Get() }; settingsRegistry != nullptr) + { + auto LifecycleCallback = [this](AZStd::string_view, AZ::SettingsRegistryInterface::Type) + { + BuildSpawnablesList(); + }; + AZ::ComponentApplicationLifecycle::RegisterHandler(*settingsRegistry, m_criticalAssetsHandler, + AZStd::move(LifecycleCallback), "CriticalAssetsCompiled"); + } } NetworkSpawnableLibrary::~NetworkSpawnableLibrary() { - AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); + m_criticalAssetsHandler = {}; AZ::Interface::Unregister(this); } @@ -50,11 +59,6 @@ namespace Multiplayer m_spawnablesReverseLookup[id] = name; } - void NetworkSpawnableLibrary::OnCatalogLoaded([[maybe_unused]] const char* catalogFile) - { - BuildSpawnablesList(); - } - AZ::Name NetworkSpawnableLibrary::GetSpawnableNameFromAssetId(AZ::Data::AssetId assetId) { if (assetId.IsValid()) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h index 1cec63f81d..0fc3ae07cc 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h @@ -9,14 +9,13 @@ #pragma once #include -#include +#include namespace Multiplayer { /// Implementation of the network prefab library interface. class NetworkSpawnableLibrary final : public INetworkSpawnableLibrary - , private AzFramework::AssetCatalogEventBus::Handler { public: AZ_RTTI(NetworkSpawnableLibrary, "{65E15F33-E893-49C2-A8E2-B6A8A6EF31E0}", INetworkSpawnableLibrary); @@ -30,11 +29,10 @@ namespace Multiplayer AZ::Name GetSpawnableNameFromAssetId(AZ::Data::AssetId assetId) override; AZ::Data::AssetId GetAssetIdByName(AZ::Name name) override; - /// AssetCatalogEventBus overrides. - void OnCatalogLoaded(const char* catalogFile) override; private: AZStd::unordered_map m_spawnables; AZStd::unordered_map m_spawnablesReverseLookup; + AZ::SettingsRegistryInterface::NotifyEventHandler m_criticalAssetsHandler; }; } diff --git a/Gems/PhysX/Code/Source/System/PhysXSystem.cpp b/Gems/PhysX/Code/Source/System/PhysXSystem.cpp index 168adc8910..39c0dfc686 100644 --- a/Gems/PhysX/Code/Source/System/PhysXSystem.cpp +++ b/Gems/PhysX/Code/Source/System/PhysXSystem.cpp @@ -103,15 +103,13 @@ namespace PhysX if (auto* settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) { - // Automatically register the event if it's not registered, because - // this system is initialized before the settings registry has loaded the event list. AZ::ComponentApplicationLifecycle::RegisterHandler( *settingsRegistry, m_componentApplicationLifecycleHandler, [this]([[maybe_unused]] AZStd::string_view path, [[maybe_unused]] AZ::SettingsRegistryInterface::Type type) { InitializeMaterialLibrary(); }, - "LegacySystemInterfaceCreated"); // LegacySystemInterfaceCreated is signaled after critical assets have been processed + "CriticalAssetsCompiled"); } m_state = State::Initialized; diff --git a/Registry/application_lifecycle_events.setreg b/Registry/application_lifecycle_events.setreg index 0d9cd0f170..c52c93c0c0 100644 --- a/Registry/application_lifecycle_events.setreg +++ b/Registry/application_lifecycle_events.setreg @@ -23,7 +23,8 @@ "GemsUnloaded": {}, "FileIOAvailable": {}, "FileIOUnavailable": {}, - "LegacySystemInterfaceCreated": {} + "LegacySystemInterfaceCreated": {}, + "CriticalAssetsCompiled": {} } } }