diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp index 3be3fbce11..d6faed4b0a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp @@ -28,7 +28,7 @@ namespace AzToolsFramework { namespace Internal { - AZ::JsonSerializationResult::ResultCode JsonIssueReporter(AZStd::string& scratchBuffer, + static AZ::JsonSerializationResult::ResultCode JsonIssueReporter(AZStd::string& scratchBuffer, AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path) { namespace JSR = AZ::JsonSerializationResult; @@ -48,6 +48,66 @@ namespace AzToolsFramework return result; } + + static bool StoreInstanceInPrefabDom( + const Instance& instance, + PrefabDom& prefabDom, + AZStd::vector>* referencedAssets, + StoreFlags flags) + { + InstanceEntityIdMapper entityIdMapper; + entityIdMapper.SetStoringInstance(instance); + + // Need to store the id mapper as both its type and its base type + // Metadata is found by type id and we need access to both types at different levels (Instance, EntityId) + AZ::JsonSerializerSettings settings; + settings.m_metadata.Add(static_cast(&entityIdMapper)); + settings.m_metadata.Add(&entityIdMapper); + if (referencedAssets) + { + settings.m_metadata.Add(AZ::Data::SerializedAssetTracker{}); + } + + if ((flags & StoreFlags::StripDefaultValues) != StoreFlags::StripDefaultValues) + { + settings.m_keepDefaults = true; + } + + if ((flags & StoreFlags::StoreLinkIds) != StoreFlags::None) + { + settings.m_metadata.Create(); + } + + AZStd::string scratchBuffer; + auto issueReportingCallback = [&scratchBuffer]( + AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, + AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode + { + return Internal::JsonIssueReporter(scratchBuffer, message, result, path); + }; + + settings.m_reporting = AZStd::move(issueReportingCallback); + + AZ::JsonSerializationResult::ResultCode result = + AZ::JsonSerialization::Store(prefabDom, prefabDom.GetAllocator(), instance, settings); + + if (result.GetProcessing() == AZ::JsonSerializationResult::Processing::Halted) + { + AZ_Error( + "Prefab", false, + "Failed to serialize prefab instance with source path %s. " + "Unable to proceed.", + instance.GetTemplateSourcePath().c_str()); + + return false; + } + + if (referencedAssets) + { + *referencedAssets = AZStd::move(settings.m_metadata.Find()->GetTrackedAssets()); + } + return true; + } } PrefabDomValueReference FindPrefabDomValue(PrefabDomValue& parentValue, const char* valueName) @@ -74,49 +134,7 @@ namespace AzToolsFramework bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreFlags flags) { - InstanceEntityIdMapper entityIdMapper; - entityIdMapper.SetStoringInstance(instance); - - // Need to store the id mapper as both its type and its base type - // Meta data is found by type id and we need access to both types at different levels (Instance, EntityId) - AZ::JsonSerializerSettings settings; - settings.m_metadata.Add(static_cast(&entityIdMapper)); - settings.m_metadata.Add(&entityIdMapper); - - if ((flags & StoreFlags::StripDefaultValues) != StoreFlags::StripDefaultValues) - { - settings.m_keepDefaults = true; - } - - if ((flags & StoreFlags::StoreLinkIds) != StoreFlags::None) - { - settings.m_metadata.Create(); - } - - AZStd::string scratchBuffer; - auto issueReportingCallback = [&scratchBuffer] - (AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, - AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode - { - return Internal::JsonIssueReporter(scratchBuffer, message, result, path); - }; - - settings.m_reporting = AZStd::move(issueReportingCallback); - - AZ::JsonSerializationResult::ResultCode result = - AZ::JsonSerialization::Store(prefabDom, prefabDom.GetAllocator(), instance, settings); - - if (result.GetProcessing() == AZ::JsonSerializationResult::Processing::Halted) - { - AZ_Error("Prefab", false, - "Failed to serialize prefab instance with source path %s. " - "Unable to proceed.", - instance.GetTemplateSourcePath().c_str()); - - return false; - } - - return true; + return Internal::StoreInstanceInPrefabDom(instance, prefabDom, nullptr, flags); } bool StoreInstanceInPrefabDom( @@ -125,52 +143,7 @@ namespace AzToolsFramework AZStd::vector>& referencedAssets, StoreFlags flags) { - InstanceEntityIdMapper entityIdMapper; - entityIdMapper.SetStoringInstance(instance); - - // Need to store the id mapper as both its type and its base type - // Meta data is found by type id and we need access to both types at different levels (Instance, EntityId) - AZ::JsonSerializerSettings settings; - settings.m_metadata.Add(static_cast(&entityIdMapper)); - settings.m_metadata.Add(&entityIdMapper); - settings.m_metadata.Add(AZ::Data::SerializedAssetTracker{}); - - if ((flags & StoreFlags::StripDefaultValues) != StoreFlags::StripDefaultValues) - { - settings.m_keepDefaults = true; - } - - if ((flags & StoreFlags::StoreLinkIds) != StoreFlags::None) - { - settings.m_metadata.Create(); - } - - AZStd::string scratchBuffer; - auto issueReportingCallback = [&scratchBuffer]( - AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, - AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode - { - return Internal::JsonIssueReporter(scratchBuffer, message, result, path); - }; - - settings.m_reporting = AZStd::move(issueReportingCallback); - - AZ::JsonSerializationResult::ResultCode result = - AZ::JsonSerialization::Store(prefabDom, prefabDom.GetAllocator(), instance, settings); - - if (result.GetProcessing() == AZ::JsonSerializationResult::Processing::Halted) - { - AZ_Error( - "Prefab", false, - "Failed to serialize prefab instance with source path %s. " - "Unable to proceed.", - instance.GetTemplateSourcePath().c_str()); - - return false; - } - - referencedAssets = AZStd::move(settings.m_metadata.Find()->GetTrackedAssets()); - return true; + return Internal::StoreInstanceInPrefabDom(instance, prefabDom, &referencedAssets, flags); } bool StoreEntityInPrefabDomFormat(const AZ::Entity& entity, Instance& owningInstance, PrefabDom& prefabDom, StoreFlags flags) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp index 634cb9d448..a927f60789 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp @@ -255,20 +255,23 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils AZ::Data::AssetId assetId = asset->GetId(); AZ::Data::AssetType assetType = asset->GetType(); - // Always queue load as the next step will stop loading for all PreLoad assets - *asset = AZ::Data::AssetManager::Instance().GetAsset(assetId, assetType, AZ::Data::AssetLoadBehavior::QueueLoad); - - if (!asset->GetId().IsValid()) - { - AZ_Error("Prefab", false, "Invalid asset found referenced in scene while entering game mode"); - return false; - } - if (loadBehavior == AZ::Data::AssetLoadBehavior::PreLoad) { // Only assets that are preloaded need to be waited on. blockingAssets.push_back(asset); + // Queue any pending request in parallel. Assets that were set to PreLoad will be waited for resulting + // in the same overall load guarantees. + asset->SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::QueueLoad); } + if (!asset->QueueLoad()) + { + AZ_Error( + "Prefab", false, "Failed to queue asset '%s' (%s) of type '%s' for loading while entering game mode.", + asset->GetHint().c_str(), asset->GetId().ToString>().c_str(), + asset->GetType().ToString>().c_str()); + return false; + } + return false; } return true; @@ -288,8 +291,9 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils if (asset->IsError()) { AZ_Error( - "Prefab", false, "Asset with id %s failed to preload while entering game mode", - asset->GetId().ToString().c_str()); + "Prefab", false, "Asset '%s' (%s) of type '%s' failed to preload while entering game mode", asset->GetHint().c_str(), + asset->GetId().ToString>().c_str(), + asset->GetType().ToString>().c_str()); continue; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp index f13ddc027f..097acbb47c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp @@ -154,7 +154,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils } } - bool PrefabDocument::RefreshPrefabDom() const + void PrefabDocument::RefreshPrefabDom() const { if (m_isDirty) { @@ -162,14 +162,11 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils if (PrefabDomUtils::StoreInstanceInPrefabDom(*m_instance, m_dom, m_referencedAssets)) { m_isDirty = false; - return true; } else { AZ_Assert(false, "Failed to store Instance '%s' to PrefabDom.", m_name.c_str()); - return false; } } - return true; } } // namespace AzToolsFramework::Prefab::PrefabConversionUtils diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h index a651d73e63..cff6e8368f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h @@ -59,7 +59,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils private: bool ConstructInstanceFromPrefabDom(const PrefabDom& prefab); // Marked const so this function can be called from other const functions. It will only operate on mutable variables. - bool RefreshPrefabDom() const; + void RefreshPrefabDom() const; mutable PrefabDom m_dom; AZStd::unique_ptr m_instance;