diff --git a/Code/Tools/SerializeContextTools/Application.cpp b/Code/Tools/SerializeContextTools/Application.cpp index da0cca5ca6..81cc314deb 100644 --- a/Code/Tools/SerializeContextTools/Application.cpp +++ b/Code/Tools/SerializeContextTools/Application.cpp @@ -97,6 +97,11 @@ namespace AZ return m_configFilePath.c_str(); } + void Application::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const + { + appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Tool; + } + void Application::SetSettingsRegistrySpecializations(AZ::SettingsRegistryInterface::Specializations& specializations) { AZ::ComponentApplication::SetSettingsRegistrySpecializations(specializations); diff --git a/Code/Tools/SerializeContextTools/Application.h b/Code/Tools/SerializeContextTools/Application.h index b1b818e27d..b4c02b87c2 100644 --- a/Code/Tools/SerializeContextTools/Application.h +++ b/Code/Tools/SerializeContextTools/Application.h @@ -28,6 +28,7 @@ namespace AZ const char* GetConfigFilePath() const; AZ::ComponentTypeList GetRequiredSystemComponents() const override; + void QueryApplicationType(AZ::ApplicationTypeQuery& appType) const override; protected: void SetSettingsRegistrySpecializations(AZ::SettingsRegistryInterface::Specializations& specializations) override; diff --git a/Code/Tools/SerializeContextTools/SliceConverter.cpp b/Code/Tools/SerializeContextTools/SliceConverter.cpp index a18a6ff3a3..3fbf7cb25c 100644 --- a/Code/Tools/SerializeContextTools/SliceConverter.cpp +++ b/Code/Tools/SerializeContextTools/SliceConverter.cpp @@ -25,8 +25,11 @@ #include #include #include +#include +#include #include #include +#include #include #include #include @@ -36,7 +39,6 @@ // SliceConverter reads in a slice file (saved in an ObjectStream format), instantiates it, creates a prefab out of the data, // and saves the prefab in a JSON format. This can be used for one-time migrations of slices or slice-based levels to prefabs. -// This converter is still in an early state. It can convert trivial slices, but it cannot handle nested slices yet. // // If the slice contains legacy data, it will print out warnings / errors about the data that couldn't be serialized. // The prefab will be generated without that data. @@ -70,6 +72,20 @@ namespace AZ AZ_Error("Convert-Slice", false, "No json registration context found."); return false; } + + // Connect to the Asset Processor so that we can get the correct source path to any nested slice references. + if (!ConnectToAssetProcessor()) + { + AZ_Error("Convert-Slice", false, " Failed to connect to the Asset Processor.\n"); + 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. + AZ::Data::AssetCatalogRequestBus::Broadcast( + &AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, "@assets@/assetcatalog.xml"); + application.Tick(); + AZStd::string logggingScratchBuffer; SetupLogging(logggingScratchBuffer, convertSettings.m_reporting, *commandLine); @@ -80,83 +96,90 @@ namespace AZ verifySettings.m_serializeContext = application.GetSerializeContext(); SetupLogging(logggingScratchBuffer, verifySettings.m_reporting, *commandLine); - auto archiveInterface = AZ::Interface::Get(); - - // Find the Prefab System Component for use in creating and saving the prefab - AZ::Entity* systemEntity = application.FindEntity(AZ::SystemEntityId); - AZ_Assert(systemEntity != nullptr, "System entity doesn't exist."); - auto prefabSystemComponent = systemEntity->FindComponent(); - AZ_Assert(prefabSystemComponent != nullptr, "Prefab System component doesn't exist"); - bool result = true; rapidjson::StringBuffer scratchBuffer; + // Loop through the list of requested files and convert them. AZStd::vector fileList = Utilities::ReadFileListFromCommandLine(application, "files"); for (AZStd::string& filePath : fileList) { - bool packOpened = false; - - AZ::IO::Path outputPath = filePath; - outputPath.ReplaceExtension("prefab"); - - AZ_Printf("Convert-Slice", "------------------------------------------------------------------------------------------\n"); - AZ_Printf("Convert-Slice", "Converting '%s' to '%s'\n", filePath.c_str(), outputPath.c_str()); - - AZ::IO::Path inputPath = filePath; - auto fileExtension = inputPath.Extension(); - if (fileExtension == ".ly") - { - // Special case: for level files, we need to open the .ly zip file and convert the levelentities.editor_xml file - // inside of it. All the other files can be ignored as they are deprecated legacy system files that are no longer - // loaded with prefab-based levels. - packOpened = archiveInterface->OpenPack(filePath); - inputPath.ReplaceFilename("levelentities.editor_xml"); - AZ_Warning("Convert-Slice", packOpened, " '%s' could not be opened as a pack file.\n", filePath.c_str()); - } - else - { - AZ_Warning( - "Convert-Slice", (fileExtension == ".slice"), - " Warning: Only .ly and .slice files are supported, conversion of '%.*s' may not work.\n", - AZ_STRING_ARG(fileExtension.Native())); - } - - auto callback = [prefabSystemComponent, &outputPath, isDryRun] - (void* classPtr, const Uuid& classId, [[maybe_unused]] SerializeContext* context) - { - if (classId != azrtti_typeid()) - { - AZ_Printf("Convert-Slice", " File not converted: Slice root is not an entity.\n"); - return false; - } - - AZ::Entity* rootEntity = reinterpret_cast(classPtr); - return ConvertSliceFile(prefabSystemComponent, outputPath, isDryRun, rootEntity); - }; - - if (!Utilities::InspectSerializedFile(inputPath.c_str(), convertSettings.m_serializeContext, callback)) - { - AZ_Warning("Convert-Slice", false, "Failed to load '%s'. File may not contain an object stream.", inputPath.c_str()); - result = false; - } - - if (packOpened) - { - [[maybe_unused]] bool closeResult = archiveInterface->ClosePack(filePath); - AZ_Warning("Convert-Slice", closeResult, "Failed to close '%s'.", filePath.c_str()); - } - - AZ_Printf("Convert-Slice", "Finished converting '%s' to '%s'\n", filePath.c_str(), outputPath.c_str()); - AZ_Printf("Convert-Slice", "------------------------------------------------------------------------------------------\n"); + bool convertResult = ConvertSliceFile(convertSettings.m_serializeContext, filePath, isDryRun); + result = result && convertResult; } + DisconnectFromAssetProcessor(); return result; } bool SliceConverter::ConvertSliceFile( - AzToolsFramework::Prefab::PrefabSystemComponent* prefabSystemComponent, AZ::IO::PathView outputPath, bool isDryRun, - AZ::Entity* rootEntity) + AZ::SerializeContext* serializeContext, const AZStd::string& slicePath, bool isDryRun) { + bool result = true; + bool packOpened = false; + + auto archiveInterface = AZ::Interface::Get(); + + AZ::IO::Path outputPath = slicePath; + outputPath.ReplaceExtension("prefab"); + + AZ_Printf("Convert-Slice", "------------------------------------------------------------------------------------------\n"); + AZ_Printf("Convert-Slice", "Converting '%s' to '%s'\n", slicePath.c_str(), outputPath.c_str()); + + AZ::IO::Path inputPath = slicePath; + auto fileExtension = inputPath.Extension(); + if (fileExtension == ".ly") + { + // Special case: for level files, we need to open the .ly zip file and convert the levelentities.editor_xml file + // inside of it. All the other files can be ignored as they are deprecated legacy system files that are no longer + // loaded with prefab-based levels. + packOpened = archiveInterface->OpenPack(slicePath); + inputPath.ReplaceFilename("levelentities.editor_xml"); + AZ_Warning("Convert-Slice", packOpened, " '%s' could not be opened as a pack file.\n", slicePath.c_str()); + } + else + { + AZ_Warning( + "Convert-Slice", (fileExtension == ".slice"), + " Warning: Only .ly and .slice files are supported, conversion of '%.*s' may not work.\n", + AZ_STRING_ARG(fileExtension.Native())); + } + + auto callback = [&outputPath, isDryRun](void* classPtr, const Uuid& classId, SerializeContext* context) + { + if (classId != azrtti_typeid()) + { + AZ_Printf("Convert-Slice", " File not converted: Slice root is not an entity.\n"); + return false; + } + + AZ::Entity* rootEntity = reinterpret_cast(classPtr); + return ConvertSliceToPrefab(context, outputPath, isDryRun, rootEntity); + }; + + // Read in the slice file and call the callback on completion to convert the read-in slice to a prefab. + if (!Utilities::InspectSerializedFile(inputPath.c_str(), serializeContext, callback)) + { + AZ_Warning("Convert-Slice", false, "Failed to load '%s'. File may not contain an object stream.", inputPath.c_str()); + result = false; + } + + if (packOpened) + { + [[maybe_unused]] bool closeResult = archiveInterface->ClosePack(slicePath); + AZ_Warning("Convert-Slice", closeResult, "Failed to close '%s'.", slicePath.c_str()); + } + + AZ_Printf("Convert-Slice", "Finished converting '%s' to '%s'\n", slicePath.c_str(), outputPath.c_str()); + AZ_Printf("Convert-Slice", "------------------------------------------------------------------------------------------\n"); + + return result; + } + + bool SliceConverter::ConvertSliceToPrefab( + AZ::SerializeContext* serializeContext, AZ::IO::PathView outputPath, bool isDryRun, AZ::Entity* rootEntity) + { + auto prefabSystemComponentInterface = AZ::Interface::Get(); + // Find the slice from the root entity. SliceComponent* sliceComponent = AZ::EntityUtils::FindFirstDerivedComponent(rootEntity); if (sliceComponent == nullptr) @@ -167,44 +190,21 @@ namespace AZ // Get all of the entities from the slice. SliceComponent::EntityList sliceEntities = sliceComponent->GetNewEntities(); - if (sliceEntities.empty()) - { - AZ_Printf("Convert-Slice", " File not converted: Slice entities could not be retrieved.\n"); - return false; - } - - AZ_Warning("Convert-Slice", sliceComponent->GetSlices().empty(), " Slice depends on other slices, this conversion will lose data.\n"); + AZ_Printf("Convert-Slice", " Slice contains %zu entities.\n", sliceEntities.size()); // Create the Prefab with the entities from the slice AZStd::unique_ptr sourceInstance( - prefabSystemComponent->CreatePrefab(sliceEntities, {}, outputPath)); + prefabSystemComponentInterface->CreatePrefab(sliceEntities, {}, outputPath)); // Dispatch events here, because prefab creation might trigger asset loads in rare circumstances. AZ::Data::AssetManager::Instance().DispatchEvents(); - // Set up the Prefab container entity to be a proper Editor entity. (This logic is normally triggered - // via an EditorRequests EBus in CreatePrefab, but the subsystem that listens for it isn't present in this tool.) + // Fix up the container entity to have the proper components and fix up the slice entities to have the proper hierarchy + // with the container as the top-most parent. AzToolsFramework::Prefab::EntityOptionalReference container = sourceInstance->GetContainerEntity(); - AzToolsFramework::EditorEntityContextRequestBus::Broadcast( - &AzToolsFramework::EditorEntityContextRequestBus::Events::AddRequiredComponents, container->get()); - container->get().AddComponent(aznew AzToolsFramework::Prefab::EditorPrefabComponent()); - - // Reparent any root-level slice entities to the container entity. - for (auto entity : sliceEntities) - { - AzToolsFramework::Components::TransformComponent* transformComponent = - entity->FindComponent(); - if (transformComponent) - { - if (!transformComponent->GetParentId().IsValid()) - { - transformComponent->SetParent(container->get().GetId()); - } - } - } + FixPrefabEntities(container->get(), sliceEntities); auto templateId = sourceInstance->GetTemplateId(); - if (templateId == AzToolsFramework::Prefab::InvalidTemplateId) { AZ_Printf("Convert-Slice", " Path error. Path could be invalid, or the prefab may not be loaded in this level.\n"); @@ -219,14 +219,27 @@ namespace AZ AZ_Printf("Convert-Slice", " Failed to convert prefab instance data to a PrefabDom.\n"); return false; } - prefabSystemComponent->UpdatePrefabTemplate(templateId, prefabDom); + prefabSystemComponentInterface->UpdatePrefabTemplate(templateId, prefabDom); // Dispatch events here, because prefab serialization might trigger asset loads in rare circumstances. AZ::Data::AssetManager::Instance().DispatchEvents(); + // If this slice has nested slices, we need to loop through those, convert them to prefabs as well, and + // set up the new nesting relationships correctly. + const SliceComponent::SliceList& sliceList = sliceComponent->GetSlices(); + AZ_Printf("Convert-Slice", " Slice contains %zu nested slices.\n", sliceList.size()); + if (!sliceList.empty()) + { + bool nestedSliceResult = ConvertNestedSlices(sliceComponent, sourceInstance.get(), serializeContext, isDryRun); + if (!nestedSliceResult) + { + return false; + } + } + if (isDryRun) { - PrintPrefab(prefabDom, sourceInstance->GetTemplateSourcePath()); + PrintPrefab(templateId); return true; } else @@ -235,8 +248,187 @@ namespace AZ } } - void SliceConverter::PrintPrefab(const AzToolsFramework::Prefab::PrefabDom& prefabDom, const AZ::IO::Path& templatePath) + void SliceConverter::FixPrefabEntities(AZ::Entity& containerEntity, SliceComponent::EntityList& sliceEntities) { + // Set up the Prefab container entity to be a proper Editor entity. (This logic is normally triggered + // via an EditorRequests EBus in CreatePrefab, but the subsystem that listens for it isn't present in this tool.) + AzToolsFramework::EditorEntityContextRequestBus::Broadcast( + &AzToolsFramework::EditorEntityContextRequestBus::Events::AddRequiredComponents, containerEntity); + containerEntity.AddComponent(aznew AzToolsFramework::Prefab::EditorPrefabComponent()); + + // Reparent any root-level slice entities to the container entity. + for (auto entity : sliceEntities) + { + AzToolsFramework::Components::TransformComponent* transformComponent = + entity->FindComponent(); + if (transformComponent) + { + if (!transformComponent->GetParentId().IsValid()) + { + transformComponent->SetParent(containerEntity.GetId()); + transformComponent->UpdateCachedWorldTransform(); + } + } + } + } + + bool SliceConverter::ConvertNestedSlices( + SliceComponent* sliceComponent, AzToolsFramework::Prefab::Instance* sourceInstance, + AZ::SerializeContext* serializeContext, bool isDryRun) + { + const SliceComponent::SliceList& sliceList = sliceComponent->GetSlices(); + auto prefabSystemComponentInterface = AZ::Interface::Get(); + + for (auto& slice : sliceList) + { + // Get the nested slice asset + auto sliceAsset = slice.GetSliceAsset(); + sliceAsset.QueueLoad(); + sliceAsset.BlockUntilLoadComplete(); + + // The slice list gives us asset IDs, and we need to get to the source path. So first we get the asset path from the ID, + // then we get the source path from the asset path. + + AZStd::string processedAssetPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + processedAssetPath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, sliceAsset.GetId()); + + AZStd::string assetPath; + AzToolsFramework::AssetSystemRequestBus::Broadcast( + &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, + processedAssetPath, assetPath); + if (assetPath.empty()) + { + AZ_Warning("Convert-Slice", false, + " Source path for nested slice '%s' could not be found, slice not converted.", processedAssetPath.c_str()); + return false; + } + + // Now, convert the nested slice to a prefab. + bool nestedSliceResult = ConvertSliceFile(serializeContext, assetPath, isDryRun); + if (!nestedSliceResult) + { + AZ_Warning("Convert-Slice", nestedSliceResult, " Nested slice '%s' could not be converted.", assetPath.c_str()); + return false; + } + + // Load the prefab template for the newly-created nested prefab. + // To get the template, we need to take our absolute slice path and turn it into a project-relative prefab path. + AZ::IO::Path nestedPrefabPath = assetPath; + nestedPrefabPath.ReplaceExtension("prefab"); + + auto prefabLoaderInterface = AZ::Interface::Get(); + nestedPrefabPath = prefabLoaderInterface->GetRelativePathToProject(nestedPrefabPath); + + AzToolsFramework::Prefab::TemplateId nestedTemplateId = + prefabSystemComponentInterface->GetTemplateIdFromFilePath(nestedPrefabPath); + AzToolsFramework::Prefab::TemplateReference nestedTemplate = + prefabSystemComponentInterface->FindTemplate(nestedTemplateId); + + // For each slice instance of the nested slice, convert it to a nested prefab instance instead. + + auto instances = slice.GetInstances(); + AZ_Printf( + "Convert-Slice", " Attaching %zu instances of nested slice '%s'.\n", instances.size(), + nestedPrefabPath.Native().c_str()); + + for (auto& instance : instances) + { + bool instanceConvertResult = ConvertSliceInstance(instance, sliceAsset, nestedTemplate, sourceInstance); + if (!instanceConvertResult) + { + return false; + } + } + } + + return true; + } + + bool SliceConverter::ConvertSliceInstance( + [[maybe_unused]] AZ::SliceComponent::SliceInstance& instance, + [[maybe_unused]] AZ::Data::Asset& sliceAsset, + AzToolsFramework::Prefab::TemplateReference nestedTemplate, + AzToolsFramework::Prefab::Instance* topLevelInstance) + { + auto instanceToTemplateInterface = AZ::Interface::Get(); + auto prefabSystemComponentInterface = AZ::Interface::Get(); + + // Create a new unmodified prefab Instance for the nested slice instance. + auto nestedInstance = AZStd::make_unique(); + AzToolsFramework::Prefab::Instance::EntityList newEntities; + if (!AzToolsFramework::Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom( + *nestedInstance, newEntities, nestedTemplate->get().GetPrefabDom())) + { + AZ_Error( + "Convert-Slice", false, " Failed to load and instantiate nested Prefab Template '%s'.", + nestedTemplate->get().GetFilePath().c_str()); + return false; + } + + // Get the DOM for the unmodified nested instance. This will be used later below for generating the correct patch + // to the top-level template DOM. + AzToolsFramework::Prefab::PrefabDom unmodifiedNestedInstanceDom; + instanceToTemplateInterface->GenerateDomForInstance(unmodifiedNestedInstanceDom, *(nestedInstance.get())); + + // Currently, DataPatch conversions for nested slices aren't implemented, so all nested slice overrides will + // be lost. + AZ_Warning( + "Convert-Slice", false, " Nested slice instances will lose all of their override data during conversion.", + nestedTemplate->get().GetFilePath().c_str()); + + // Set the container entity of the nested prefab to have the top-level prefab as the parent. + // Once DataPatch conversions are supported, this will need to change to nest the prefab under the appropriate entity + // within the level. + auto containerEntity = nestedInstance->GetContainerEntity(); + AzToolsFramework::Components::TransformComponent* transformComponent = + containerEntity->get().FindComponent(); + if (transformComponent) + { + transformComponent->SetParent(topLevelInstance->GetContainerEntityId()); + transformComponent->UpdateCachedWorldTransform(); + } + + // Add the nested instance itself to the top-level prefab. To do this, we need to add it to our top-level instance, + // create a patch out of it, and patch the top-level prefab template. + + AzToolsFramework::Prefab::PrefabDom topLevelInstanceDomBefore; + instanceToTemplateInterface->GenerateDomForInstance(topLevelInstanceDomBefore, *topLevelInstance); + + AzToolsFramework::Prefab::Instance& addedInstance = topLevelInstance->AddInstance(AZStd::move(nestedInstance)); + + AzToolsFramework::Prefab::PrefabDom topLevelInstanceDomAfter; + instanceToTemplateInterface->GenerateDomForInstance(topLevelInstanceDomAfter, *topLevelInstance); + + AzToolsFramework::Prefab::PrefabDom addedInstancePatch; + instanceToTemplateInterface->GeneratePatch(addedInstancePatch, topLevelInstanceDomBefore, topLevelInstanceDomAfter); + instanceToTemplateInterface->PatchTemplate(addedInstancePatch, topLevelInstance->GetTemplateId()); + + // Get the DOM for the modified nested instance. Now that the data has been fixed up, and the instance has been added + // to the top-level instance, we've got all the changes we need to generate the correct patch. + + AzToolsFramework::Prefab::PrefabDom modifiedNestedInstanceDom; + instanceToTemplateInterface->GenerateDomForInstance(modifiedNestedInstanceDom, addedInstance); + + AzToolsFramework::Prefab::PrefabDom linkPatch; + instanceToTemplateInterface->GeneratePatch(linkPatch, unmodifiedNestedInstanceDom, modifiedNestedInstanceDom); + + prefabSystemComponentInterface->CreateLink( + topLevelInstance->GetTemplateId(), addedInstance.GetTemplateId(), addedInstance.GetInstanceAlias(), linkPatch, + AzToolsFramework::Prefab::InvalidLinkId); + prefabSystemComponentInterface->PropagateTemplateChanges(topLevelInstance->GetTemplateId()); + + return true; + } + + void SliceConverter::PrintPrefab(AzToolsFramework::Prefab::TemplateId templateId) + { + auto prefabSystemComponentInterface = AZ::Interface::Get(); + + auto prefabTemplate = prefabSystemComponentInterface->FindTemplate(templateId); + auto& prefabDom = prefabTemplate->get().GetPrefabDom(); + const AZ::IO::Path& templatePath = prefabTemplate->get().GetFilePath(); + rapidjson::StringBuffer prefabBuffer; rapidjson::PrettyWriter writer(prefabBuffer); prefabDom.Accept(writer); @@ -260,5 +452,41 @@ namespace AZ return true; } + bool SliceConverter::ConnectToAssetProcessor() + { + AzFramework::AssetSystem::ConnectionSettings connectionSettings; + AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings); + + connectionSettings.m_launchAssetProcessorOnFailedConnection = true; + connectionSettings.m_connectionDirection = + AzFramework::AssetSystem::ConnectionSettings::ConnectionDirection::ConnectToAssetProcessor; + connectionSettings.m_connectionIdentifier = AzFramework::AssetSystem::ConnectionIdentifiers::Editor; + connectionSettings.m_loggingCallback = [](AZStd::string_view logData) + { + AZ_Printf("Convert-Slice", "%.*s\n", AZ_STRING_ARG(logData)); + }; + + bool connectedToAssetProcessor = false; + + AzFramework::AssetSystemRequestBus::BroadcastResult( + connectedToAssetProcessor, &AzFramework::AssetSystemRequestBus::Events::EstablishAssetProcessorConnection, + connectionSettings); + + return connectedToAssetProcessor; + } + + void SliceConverter::DisconnectFromAssetProcessor() + { + AzFramework::AssetSystemRequestBus::Broadcast( + &AzFramework::AssetSystem::AssetSystemRequests::StartDisconnectingAssetProcessor); + + // Wait for the disconnect to finish. + bool disconnected = false; + AzFramework::AssetSystemRequestBus::BroadcastResult(disconnected, + &AzFramework::AssetSystem::AssetSystemRequests::WaitUntilAssetProcessorDisconnected, AZStd::chrono::seconds(30)); + + AZ_Error("Convert-Slice", disconnected, "Asset Processor failed to disconnect successfully."); + } + } // namespace SerializeContextTools } // namespace AZ diff --git a/Code/Tools/SerializeContextTools/SliceConverter.h b/Code/Tools/SerializeContextTools/SliceConverter.h index 90dfa0d50a..8dba6a0e55 100644 --- a/Code/Tools/SerializeContextTools/SliceConverter.h +++ b/Code/Tools/SerializeContextTools/SliceConverter.h @@ -42,11 +42,20 @@ namespace AZ static bool ConvertSliceFiles(Application& application); private: + static bool ConnectToAssetProcessor(); + static void DisconnectFromAssetProcessor(); - static bool ConvertSliceFile(AzToolsFramework::Prefab::PrefabSystemComponent* prefabSystemComponent, - AZ::IO::PathView outputPath, bool isDryRun, AZ::Entity* rootEntity); - - static void PrintPrefab(const AzToolsFramework::Prefab::PrefabDom& prefabDom, const AZ::IO::Path& templatePath); + static bool ConvertSliceFile(AZ::SerializeContext* serializeContext, const AZStd::string& slicePath, bool isDryRun); + static bool ConvertSliceToPrefab( + AZ::SerializeContext* serializeContext, AZ::IO::PathView outputPath, bool isDryRun, AZ::Entity* rootEntity); + static void FixPrefabEntities(AZ::Entity& containerEntity, SliceComponent::EntityList& sliceEntities); + static bool ConvertNestedSlices( + SliceComponent* sliceComponent, AzToolsFramework::Prefab::Instance* sourceInstance, + AZ::SerializeContext* serializeContext, bool isDryRun); + static bool SliceConverter::ConvertSliceInstance( + AZ::SliceComponent::SliceInstance& instance, AZ::Data::Asset& sliceAsset, + AzToolsFramework::Prefab::TemplateReference nestedTemplate, AzToolsFramework::Prefab::Instance* topLevelInstance); + static void PrintPrefab(AzToolsFramework::Prefab::TemplateId templateId); static bool SavePrefab(AzToolsFramework::Prefab::TemplateId templateId); }; } // namespace SerializeContextTools diff --git a/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataSystemComponent.cpp b/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataSystemComponent.cpp index 4dcc969434..4703977ab4 100644 --- a/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataSystemComponent.cpp +++ b/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataSystemComponent.cpp @@ -118,6 +118,8 @@ namespace SurfaceData void EditorSurfaceDataSystemComponent::Deactivate() { + m_surfaceTagNameAssets.clear(); + AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); AzToolsFramework::Components::EditorComponentBase::Deactivate(); SurfaceDataTagProviderRequestBus::Handler::BusDisconnect(); diff --git a/Registry/gem_autoload.serializecontexttools.setreg b/Registry/gem_autoload.serializecontexttools.setreg index 1f4a8931c5..e7e88dd6a6 100644 --- a/Registry/gem_autoload.serializecontexttools.setreg +++ b/Registry/gem_autoload.serializecontexttools.setreg @@ -9,6 +9,18 @@ }, "PythonAssetBuilder.Editor": { "AutoLoad": false + }, + "AWSCore.Editor": { + "AutoLoad": false + }, + "AWSClientAuth": { + "AutoLoad": false + }, + "AWSClientAuth.Editor": { + "AutoLoad": false + }, + "AWSMetrics": { + "AutoLoad": false } } }