Merge branch 'main' into jckand/FoundationAuto

main
jckand-amzn 5 years ago
commit 05a99947e4

@ -16,16 +16,16 @@
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
# Enable after installing NodeJS and CDK on jenkins Windows AMI.
#ly_add_pytest(
# NAME AutomatedTesting::AWSTests
# TEST_SUITE periodic
# TEST_SERIAL
# PATH ${CMAKE_CURRENT_LIST_DIR}/AWS/${PAL_PLATFORM_NAME}/
# RUNTIME_DEPENDENCIES
# Legacy::Editor
# AZ::AssetProcessor
# AutomatedTesting.Assets
# COMPONENT
# AWS
#)
ly_add_pytest(
NAME AutomatedTesting::AWSTests
TEST_SUITE periodic
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/${PAL_PLATFORM_NAME}/
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
AutomatedTesting.Assets
COMPONENT
AWS
)
endif()

@ -0,0 +1,11 @@
"""
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.
"""

@ -0,0 +1,11 @@
"""
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.
"""

@ -0,0 +1,11 @@
"""
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.
"""

@ -68,6 +68,7 @@ class TestAWSClientAuthAnonymousCredentials(object):
log_monitor = ly_test_tools.log.log_monitor.LogMonitor(launcher=launcher, log_file_path=file_to_monitor)
launcher.args = ['+LoadLevel', level]
launcher.args.extend(['-rhi=null'])
with launcher.start(launch_ap=False):
result = log_monitor.monitor_log_for_lines(

@ -67,6 +67,7 @@ class TestAWSClientAuthPasswordSignIn(object):
log_monitor = ly_test_tools.log.log_monitor.LogMonitor(launcher=launcher, log_file_path=file_to_monitor)
launcher.args = ['+LoadLevel', 'AWS/ClientAuthPasswordSignUp']
launcher.args.extend(['-rhi=null'])
with launcher.start(launch_ap=False):
result = log_monitor.monitor_log_for_lines(
@ -87,6 +88,7 @@ class TestAWSClientAuthPasswordSignIn(object):
)
launcher.args = ['+LoadLevel', 'AWS/ClientAuthPasswordSignIn']
launcher.args.extend(['-rhi=null'])
with launcher.start(launch_ap=False):
result = log_monitor.monitor_log_for_lines(

@ -10,8 +10,12 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import os
from os.path import abspath
import pytest
import json
import logging
logger = logging.getLogger(__name__)
AWS_RESOURCE_MAPPINGS_KEY = 'AWSResourceMappings'
AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY = 'AccountId'
@ -57,9 +61,9 @@ class ResourceMappings:
stacks = response.get('Stacks', [])
assert len(stacks) == 1, f'{stack_name} is invalid.'
self.__write_resource_mappings(stacks[0].get('Outputs', []))
self._write_resource_mappings(stacks[0].get('Outputs', []))
def __write_resource_mappings(self, outputs, append_feature_name = True) -> None:
def _write_resource_mappings(self, outputs, append_feature_name = True) -> None:
with open(self._resource_mapping_file_path) as file_content:
resource_mappings = json.load(file_content)
@ -129,8 +133,10 @@ def resource_mappings(
:return: ResourceMappings class object.
"""
path = f'{workspace.paths.engine_root()}\\{project}\\Config\\{resource_mappings_filename}'
resource_mappings_obj = ResourceMappings(path, aws_utils.assume_session().region_name, feature_name,
path = f'{workspace.paths.engine_root()}/{project}/Config/{resource_mappings_filename}'
logger.info(f'Resource mapping path : {path}')
logger.info(f'Resource mapping resolved path : {abspath(path)}')
resource_mappings_obj = ResourceMappings(abspath(path), aws_utils.assume_session().region_name, feature_name,
aws_utils.assume_account_id(), workspace,
aws_utils.client('cloudformation'))

@ -0,0 +1,11 @@
"""
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.
"""

@ -26,19 +26,23 @@ TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "atom_hydra_scripts")
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("level", ["auto_test"])
class TestAtomEditorComponentsMain(object):
"""Holds tests for Atom components."""
@pytest.mark.test_case_id(
"C32078130", # Display Mapper
"C32078129", # Light
"C32078131", # Radius Weight Modifier
"C32078127", # PostFX Layer
"C32078125", # Physical Sky
"C32078115", # Global Skylight (IBL)
"C32078121", # Exposure Control
"C32078120", # Directional Light
"C32078119", # DepthOfField
"C32078118") # Decal (Atom)
def test_AtomEditorComponents_AddedToEntity(self, request, editor, level, workspace, project, launcher_platform):
"""
Please review the hydra script run by this test for more specific test info.
Tests the following Atom components and verifies all "expected_lines" appear in Editor.log:
1. Display Mapper
2. Light
3. Radius Weight Modifier
4. PostFX Layer
5. Physical Sky
6. Global Skylight (IBL)
7. Exposure Control
8. Directional Light
9. DepthOfField
10. Decal (Atom)
"""
cfg_args = [level]
expected_lines = [

@ -224,7 +224,7 @@ void RCcontrollerTest_Simple::SubmitJob()
// This is a regresssion test to ensure the rccontroller can handle multiple jobs for the same file being completed before
// the APM has a chance to send OnFinishedProcesssingJob events
TEST_F(RCcontrollerTest_Simple, SameJobIsCompletedMultipleTimes_CompletesWithoutError)
TEST_F(RCcontrollerTest_Simple, DISABLED_SameJobIsCompletedMultipleTimes_CompletesWithoutError)
{
using namespace AssetProcessor;

@ -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);

@ -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;

@ -25,8 +25,11 @@
#include <AzCore/std/containers/unordered_set.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/Archive/IArchive.h>
#include <AzFramework/Asset/AssetSystemBus.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
@ -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<AZ::IO::IArchive>::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<AzToolsFramework::Prefab::PrefabSystemComponent>();
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<AZStd::string> fileList = Utilities::ReadFileListFromCommandLine(application, "files");
for (AZStd::string& filePath : fileList)
{
bool packOpened = false;
bool convertResult = ConvertSliceFile(convertSettings.m_serializeContext, filePath, isDryRun);
result = result && convertResult;
}
AZ::IO::Path outputPath = filePath;
outputPath.ReplaceExtension("prefab");
DisconnectFromAssetProcessor();
return result;
}
AZ_Printf("Convert-Slice", "------------------------------------------------------------------------------------------\n");
AZ_Printf("Convert-Slice", "Converting '%s' to '%s'\n", filePath.c_str(), outputPath.c_str());
bool SliceConverter::ConvertSliceFile(
AZ::SerializeContext* serializeContext, const AZStd::string& slicePath, bool isDryRun)
{
bool result = true;
bool packOpened = false;
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 archiveInterface = AZ::Interface<AZ::IO::IArchive>::Get();
auto callback = [prefabSystemComponent, &outputPath, isDryRun]
(void* classPtr, const Uuid& classId, [[maybe_unused]] SerializeContext* context)
{
if (classId != azrtti_typeid<AZ::Entity>())
{
AZ_Printf("Convert-Slice", " File not converted: Slice root is not an entity.\n");
return false;
}
AZ::IO::Path outputPath = slicePath;
outputPath.ReplaceExtension("prefab");
AZ::Entity* rootEntity = reinterpret_cast<AZ::Entity*>(classPtr);
return ConvertSliceFile(prefabSystemComponent, outputPath, isDryRun, rootEntity);
};
AZ_Printf("Convert-Slice", "------------------------------------------------------------------------------------------\n");
AZ_Printf("Convert-Slice", "Converting '%s' to '%s'\n", slicePath.c_str(), outputPath.c_str());
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;
}
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()));
}
if (packOpened)
auto callback = [&outputPath, isDryRun](void* classPtr, const Uuid& classId, SerializeContext* context)
{
if (classId != azrtti_typeid<AZ::Entity>())
{
[[maybe_unused]] bool closeResult = archiveInterface->ClosePack(filePath);
AZ_Warning("Convert-Slice", closeResult, "Failed to close '%s'.", filePath.c_str());
AZ_Printf("Convert-Slice", " File not converted: Slice root is not an entity.\n");
return false;
}
AZ_Printf("Convert-Slice", "Finished converting '%s' to '%s'\n", filePath.c_str(), outputPath.c_str());
AZ_Printf("Convert-Slice", "------------------------------------------------------------------------------------------\n");
AZ::Entity* rootEntity = reinterpret_cast<AZ::Entity*>(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::ConvertSliceFile(
AzToolsFramework::Prefab::PrefabSystemComponent* prefabSystemComponent, AZ::IO::PathView outputPath, bool isDryRun,
AZ::Entity* rootEntity)
bool SliceConverter::ConvertSliceToPrefab(
AZ::SerializeContext* serializeContext, AZ::IO::PathView outputPath, bool isDryRun, AZ::Entity* rootEntity)
{
auto prefabSystemComponentInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
// Find the slice from the root entity.
SliceComponent* sliceComponent = AZ::EntityUtils::FindFirstDerivedComponent<SliceComponent>(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<AzToolsFramework::Prefab::Instance> 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<AzToolsFramework::Components::TransformComponent>();
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<AzToolsFramework::Components::TransformComponent>();
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<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::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<AzToolsFramework::Prefab::PrefabLoaderInterface>::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<AZ::SliceAsset>& sliceAsset,
AzToolsFramework::Prefab::TemplateReference nestedTemplate,
AzToolsFramework::Prefab::Instance* topLevelInstance)
{
auto instanceToTemplateInterface = AZ::Interface<AzToolsFramework::Prefab::InstanceToTemplateInterface>::Get();
auto prefabSystemComponentInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
// Create a new unmodified prefab Instance for the nested slice instance.
auto nestedInstance = AZStd::make_unique<AzToolsFramework::Prefab::Instance>();
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<AzToolsFramework::Components::TransformComponent>();
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<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
auto prefabTemplate = prefabSystemComponentInterface->FindTemplate(templateId);
auto& prefabDom = prefabTemplate->get().GetPrefabDom();
const AZ::IO::Path& templatePath = prefabTemplate->get().GetFilePath();
rapidjson::StringBuffer prefabBuffer;
rapidjson::PrettyWriter<rapidjson::StringBuffer> 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

@ -42,11 +42,20 @@ namespace AZ
static bool ConvertSliceFiles(Application& application);
private:
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 ConnectToAssetProcessor();
static void DisconnectFromAssetProcessor();
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<AZ::SliceAsset>& 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

@ -118,6 +118,8 @@ namespace SurfaceData
void EditorSurfaceDataSystemComponent::Deactivate()
{
m_surfaceTagNameAssets.clear();
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
AzToolsFramework::Components::EditorComponentBase::Deactivate();
SurfaceDataTagProviderRequestBus::Handler::BusDisconnect();

@ -9,6 +9,18 @@
},
"PythonAssetBuilder.Editor": {
"AutoLoad": false
},
"AWSCore.Editor": {
"AutoLoad": false
},
"AWSClientAuth": {
"AutoLoad": false
},
"AWSClientAuth.Editor": {
"AutoLoad": false
},
"AWSMetrics": {
"AutoLoad": false
}
}
}

Loading…
Cancel
Save