diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp index d948966b4b..a0a2ea6c37 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include namespace AZ @@ -595,7 +596,9 @@ namespace AZ } else { - status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, "Serialization information for target type not found."); + using ReporterString = AZStd::fixed_string<1024>; + status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, + ReporterString::format("Serialization information for target type %s not found.", loadedTypeId.m_typeId.ToString().c_str())); return ResolvePointerResult::FullyProcessed; } objectType = loadedTypeId.m_typeId; diff --git a/Code/Tools/AssetBundler/tests/DummyProject/project.json b/Code/Tools/AssetBundler/tests/DummyProject/project.json index 0fa6ec7011..84edbe781b 100644 --- a/Code/Tools/AssetBundler/tests/DummyProject/project.json +++ b/Code/Tools/AssetBundler/tests/DummyProject/project.json @@ -10,5 +10,6 @@ "version_number" : 1, "version_name" : "1.0.0.0", "orientation" : "landscape" - } + }, + "engine" : "o3de" } diff --git a/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp b/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp index 69e60f6733..74562f5af1 100644 --- a/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp +++ b/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp @@ -63,7 +63,7 @@ namespace AssetProcessor } - AZ::IO::Path fullPath = AZ::IO::Path(scanFolder.m_scanFolder, AZ::IO::PosixPathSeparator) / source.m_sourceName; + AZ::IO::Path fullPath = AZ::IO::Path(scanFolder.m_scanFolder) / source.m_sourceName; // It's common for Open 3D Engine game projects and scan folders to be in a subfolder // of the engine install. To improve readability of the source files, strip out @@ -74,7 +74,7 @@ namespace AssetProcessor } if (m_assetRootSet) { - AzFramework::StringFunc::Replace(fullPath.Native(), m_assetRoot.absolutePath().toUtf8(), ""); + fullPath = fullPath.LexicallyProximate(m_assetRoot.absolutePath().toUtf8().constData()); } if (fullPath.empty()) @@ -88,11 +88,12 @@ namespace AssetProcessor QModelIndex newIndicesStart; AssetTreeItem* parentItem = m_root.get(); - AZ::IO::Path currentFullFolderPath; - const AZ::IO::PathView filename = fullPath.Filename(); - const AZ::IO::PathView fullPathWithoutFilename = fullPath.RemoveFilename(); + // Use posix path separator for each child item + AZ::IO::Path currentFullFolderPath(AZ::IO::PosixPathSeparator); + const AZ::IO::FixedMaxPath filename = fullPath.Filename(); + fullPath.RemoveFilename(); AZStd::fixed_string currentPath; - for (auto pathIt = fullPathWithoutFilename.begin(); pathIt != fullPathWithoutFilename.end(); ++pathIt) + for (auto pathIt = fullPath.begin(); pathIt != fullPath.end(); ++pathIt) { currentPath = pathIt->FixedMaxPathString(); currentFullFolderPath /= currentPath; diff --git a/Gems/AWSCore/Code/CMakeLists.txt b/Gems/AWSCore/Code/CMakeLists.txt index d6cd57355f..4ade4b5e54 100644 --- a/Gems/AWSCore/Code/CMakeLists.txt +++ b/Gems/AWSCore/Code/CMakeLists.txt @@ -74,7 +74,7 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) ) ly_add_target( - NAME AWSCore.Editor MODULE + NAME AWSCore.Editor GEM_MODULE NAMESPACE Gem FILES_CMAKE awscore_editor_shared_files.cmake @@ -89,6 +89,8 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) Gem::AWSCore ) + # This target is not a real gem module + # It is not meant to be loaded by the ModuleManager in C++ ly_add_target( NAME AWSCore.ResourceMappingTool MODULE NAMESPACE Gem diff --git a/Gems/Atom/Asset/Shader/Code/CMakeLists.txt b/Gems/Atom/Asset/Shader/Code/CMakeLists.txt index dd8afec534..8bc032537d 100644 --- a/Gems/Atom/Asset/Shader/Code/CMakeLists.txt +++ b/Gems/Atom/Asset/Shader/Code/CMakeLists.txt @@ -102,6 +102,11 @@ ly_add_target( 3rdParty::azslc ) +# The Atom_Asset_Shader is a required gem for Builders in order to process the assets that come WITHOUT +# the Atom_Feature_Common required gem +ly_enable_gems(GEMS Atom_Asset_Shader VARIANTS Builders + TARGETS AssetBuilder AssetProcessor AssetProcessorBatch) + ################################################################################ # Tests ################################################################################ diff --git a/Gems/Atom/Bootstrap/Code/CMakeLists.txt b/Gems/Atom/Bootstrap/Code/CMakeLists.txt index 5e5a8c96d9..e2147f0bf3 100644 --- a/Gems/Atom/Bootstrap/Code/CMakeLists.txt +++ b/Gems/Atom/Bootstrap/Code/CMakeLists.txt @@ -37,3 +37,20 @@ ly_add_target( Legacy::CryCommon Gem::Atom_RPI.Public ) + +# Atom_Bootstrap is only used in Launchers +ly_create_alias(NAME Atom_Bootstrap.Clients NAMESPACE Gem TARGETS Gem::Atom_Bootstrap) +ly_create_alias(NAME Atom_Bootstrap.Servers NAMESPACE Gem TARGETS Gem::Atom_Bootstrap) + +# The Atom_Bootstrap gem is responsible for making the NativeWindow handle in the launcher applications +# Loop over each Project name to allow the ${ProjectName}.GameLauncher and ${ProjectName}.ServerLauncher +# target to add the gem the Clients and Servers variant +get_property(LY_PROJECTS_TARGET_NAME GLOBAL PROPERTY LY_PROJECTS_TARGET_NAME) +foreach(project_name IN LISTS LY_PROJECTS_TARGET_NAME) + # Add gem as a dependency of the Clients Launcher + ly_enable_gems(PROJECT_NAME ${project_name} GEMS Atom_Bootstrap VARIANTS Clients TARGETS ${project_name}.GameLauncher) + # Add gem as a dependency of the Servers Launcher + if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) + ly_enable_gems(PROJECT_NAME ${project_name} GEMS Atom_Bootstrap VARIANTS Servers TARGETS ${project_name}.ServerLauncher) + endif() +endforeach() diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli index 8668ac10d8..b8e5c485aa 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli @@ -246,8 +246,8 @@ float ProjectedShadow::GetVisibilityEsm() const float occluder = shadowmap.Sample( PassSrg::LinearSampler, float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r; - - const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder); + + const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder); const float ratio = exp(exponent); // pow() mitigates light bleeding to shadows from near shadow casters. return saturate( pow(ratio, 8) ); @@ -287,8 +287,8 @@ float ProjectedShadow::GetVisibilityEsmPcf() const float occluder = shadowmap.Sample( PassSrg::LinearSampler, float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r; - - const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder); + + const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder); float ratio = exp(exponent); static const float pcfFallbackThreshold = 1.04; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.azsl index 1954605656..5012f85c54 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.azsl @@ -71,7 +71,7 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID) // Todo: Expose Esm exponent slider for directional lights // This would remove the exp calculation below, collapsing it into a subtraction in DirectionalLightShadow.azsli - // ATOM-15775 + // ATOM-15775 const float outValue = exp(EsmExponentialShift * depth); PassSrg::m_outputShadowmap[dispatchId].r = outValue; break; diff --git a/Gems/Atom/Feature/Common/Code/CMakeLists.txt b/Gems/Atom/Feature/Common/Code/CMakeLists.txt index 6f087edefe..da092c3f8a 100644 --- a/Gems/Atom/Feature/Common/Code/CMakeLists.txt +++ b/Gems/Atom/Feature/Common/Code/CMakeLists.txt @@ -76,6 +76,8 @@ ly_add_target( FILES_CMAKE atom_feature_common_shared_files.cmake ../Assets/atom_feature_common_asset_files.cmake + PLATFORM_INCLUDE_FILES + ${pal_source_dir}/runtime_dependencies_clients.cmake INCLUDE_DIRECTORIES PRIVATE Source @@ -99,6 +101,8 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) NAMESPACE Gem FILES_CMAKE atom_feature_common_editor_files.cmake + PLATFORM_INCLUDE_FILES + ${pal_source_dir}/runtime_dependencies_tools.cmake INCLUDE_DIRECTORIES PRIVATE . @@ -130,12 +134,16 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) NAMESPACE Gem FILES_CMAKE atom_feature_common_builders_files.cmake + PLATFORM_INCLUDE_FILES + ${pal_source_dir}/runtime_dependencies_tools.cmake INCLUDE_DIRECTORIES PRIVATE Source/Builders BUILD_DEPENDENCIES PRIVATE AZ::AzCore + RUNTIME_DEPENDENCIES + Gem::Atom_RHI.Private ) endif() diff --git a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp index a064b61a1a..95f2046fe5 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp @@ -50,6 +50,19 @@ namespace AZ if (auto behaviorContext = azrtti_cast(context)) { + behaviorContext->Class() + ->Enum("OutputDeviceTransformType_48Nits") + ->Attribute(AZ::Script::Attributes::Module, "atom") + ->Enum("OutputDeviceTransformType_100Nits") + ->Attribute(AZ::Script::Attributes::Module, "atom") + ->Enum("OutputDeviceTransformType_2000Nits") + ->Attribute(AZ::Script::Attributes::Module, "atom") + ->Enum("OutputDeviceTransformType_4000Nits") + ->Attribute(AZ::Script::Attributes::Module, "atom") + ->Enum("OutputDeviceTransformType_NumOutputDeviceTransformTypes") + ->Attribute(AZ::Script::Attributes::Module, "atom") + ; + behaviorContext->Class("AcesParameterOverrides") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "render") diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Android/runtime_dependencies_clients.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Android/runtime_dependencies_clients.cmake new file mode 100644 index 0000000000..31c0cab74b --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Android/runtime_dependencies_clients.cmake @@ -0,0 +1,14 @@ +# +# 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. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Vulkan.Private +) diff --git a/Gems/Atom/Feature/Common/Code/Platform/Common/atom_feature_common_msvc.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Android/runtime_dependencies_tools.cmake similarity index 91% rename from Gems/Atom/Feature/Common/Code/Platform/Common/atom_feature_common_msvc.cmake rename to Gems/Atom/Feature/Common/Code/Source/Platform/Android/runtime_dependencies_tools.cmake index 74ca22aaea..99eec9a733 100644 --- a/Gems/Atom/Feature/Common/Code/Platform/Common/atom_feature_common_msvc.cmake +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Android/runtime_dependencies_tools.cmake @@ -9,7 +9,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -set(LY_COMPILE_OPTIONS - PRIVATE - /EHsc +set(LY_RUNTIME_DEPENDENCIES ) diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_clients.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_clients.cmake new file mode 100644 index 0000000000..31c0cab74b --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_clients.cmake @@ -0,0 +1,14 @@ +# +# 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. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Vulkan.Private +) diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_tools.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_tools.cmake new file mode 100644 index 0000000000..c76527afa0 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_tools.cmake @@ -0,0 +1,19 @@ +# +# 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. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Vulkan.Private + Gem::Atom_RHI_DX12.Private + Gem::Atom_RHI_Metal.Private + Gem::Atom_RHI_Vulkan.Builders + Gem::Atom_RHI_DX12.Builders + Gem::Atom_RHI_Metal.Builders +) diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_clients.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_clients.cmake new file mode 100644 index 0000000000..a0aa67c703 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_clients.cmake @@ -0,0 +1,14 @@ +# +# 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. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Metal.Private +) diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_tools.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_tools.cmake new file mode 100644 index 0000000000..81046d3071 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_tools.cmake @@ -0,0 +1,19 @@ +# +# 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. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Metal.Private + Gem::Atom_RHI_Vulkan.Private + Gem::Atom_RHI_DX12.Private + Gem::Atom_RHI_Metal.Builders + Gem::Atom_RHI_Vulkan.Builders + Gem::Atom_RHI_DX12.Builders +) diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_clients.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_clients.cmake new file mode 100644 index 0000000000..dfd0319c05 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_clients.cmake @@ -0,0 +1,16 @@ +# +# 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. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Vulkan.Private + Gem::Atom_RHI_DX12.Private + Gem::Atom_RHI_Null.Private +) diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_tools.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_tools.cmake new file mode 100644 index 0000000000..c76527afa0 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_tools.cmake @@ -0,0 +1,19 @@ +# +# 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. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Vulkan.Private + Gem::Atom_RHI_DX12.Private + Gem::Atom_RHI_Metal.Private + Gem::Atom_RHI_Vulkan.Builders + Gem::Atom_RHI_DX12.Builders + Gem::Atom_RHI_Metal.Builders +) diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/iOS/runtime_dependencies_clients.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/iOS/runtime_dependencies_clients.cmake new file mode 100644 index 0000000000..a0aa67c703 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/iOS/runtime_dependencies_clients.cmake @@ -0,0 +1,14 @@ +# +# 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. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Metal.Private +) diff --git a/Gems/Atom/Feature/Common/Code/Platform/Common/atom_feature_common_clang.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/iOS/runtime_dependencies_tools.cmake similarity index 90% rename from Gems/Atom/Feature/Common/Code/Platform/Common/atom_feature_common_clang.cmake rename to Gems/Atom/Feature/Common/Code/Source/Platform/iOS/runtime_dependencies_tools.cmake index 5963f882c3..99eec9a733 100644 --- a/Gems/Atom/Feature/Common/Code/Platform/Common/atom_feature_common_clang.cmake +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/iOS/runtime_dependencies_tools.cmake @@ -9,7 +9,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -set(LY_COMPILE_OPTIONS - PRIVATE - -fexceptions +set(LY_RUNTIME_DEPENDENCIES ) diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index 295e10a53f..4fa466589c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -486,7 +486,7 @@ namespace AZ AZ_Warning("ProfilingCaptureSystemComponent", false, captureInfo.c_str()); } else - { + { AZ_Printf("ProfilingCaptureSystemComponent", "Cpu profiling statistics was saved to file [%s]\n", outputFilePath.c_str()); } @@ -500,7 +500,7 @@ namespace AZ ProfilingCaptureNotificationBus::Broadcast(&ProfilingCaptureNotificationBus::Events::OnCaptureCpuProfilingStatisticsFinished, saveResult.IsSuccess(), captureInfo); - + }); // Start the TickBus. diff --git a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp index e1666549c9..16ddc8599d 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp @@ -219,7 +219,7 @@ namespace AZ { AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzRender, "main per-frame work"); m_frameScheduler.BeginFrame(); - + frameGraphCallback(m_frameScheduler); /** diff --git a/Gems/Atom/RPI/Code/CMakeLists.txt b/Gems/Atom/RPI/Code/CMakeLists.txt index 8a2684347e..bd2af88816 100644 --- a/Gems/Atom/RPI/Code/CMakeLists.txt +++ b/Gems/Atom/RPI/Code/CMakeLists.txt @@ -66,6 +66,8 @@ ly_add_target( Gem::Atom_RPI.Public Gem::Atom_RHI.Public Gem::Atom_RHI.Reflect + RUNTIME_DEPENDENCIES + Gem::Atom_RHI.Private ) if(PAL_TRAIT_BUILD_HOST_TOOLS) @@ -129,6 +131,8 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) Gem::Atom_RPI.Editor.Static Gem::Atom_RPI.Edit Gem::Atom_RPI.Public + RUNTIME_DEPENDENCIES + Gem::Atom_RHI.Private ) endif() diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/MaterialReloadNotificationBus.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/MaterialReloadNotificationBus.h index 881b40b785..d62acab369 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/MaterialReloadNotificationBus.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/MaterialReloadNotificationBus.h @@ -24,7 +24,7 @@ namespace AZ //! Connect to this EBus to get notifications whenever material objects reload. //! The bus address is the AssetId of the MaterialAsset or MaterialTypeAsset. - //! + //! //! Be careful when using the parameters provided by these functions. The bus ID is an AssetId, and it's possible for the system to have //! both *old* versions and *new reloaded* versions of the asset in memory at the same time, and they will have the same AssetId. Therefore //! your bus Handlers could receive Reinitialized messages from multiple sources. It may be necessary to check the memory addresses of these diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h index 8ea34187ff..ec90b5d790 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h @@ -27,7 +27,7 @@ namespace AZ /** * Connect to this EBus to get notifications whenever a shader system class reinitializes itself. * The bus address is the AssetId of the ShaderAsset, even when the thing being reinitialized is a ShaderVariant or other shader related class. - * + * * Be careful when using the parameters provided by these functions. The bus ID is an AssetId, and it's possible for the system to have * both *old* versions and *new reloaded* versions of the asset in memory at the same time, and they will have the same AssetId. Therefore * your bus Handlers could receive Reinitialized messages from multiple sources. It may be necessary to check the memory addresses of these diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderVariant.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderVariant.h index 7363ab4d1a..72953bd153 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderVariant.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderVariant.h @@ -56,7 +56,7 @@ namespace AZ bool IsRootVariant() const { return m_shaderVariantAsset->IsRootVariant(); } ShaderVariantStableId GetStableId() const { return m_shaderVariantAsset->GetStableId(); } - + const Data::Asset& GetShaderAsset() const { return m_shaderAsset; } const Data::Asset& GetShaderVariantAsset() const { return m_shaderVariantAsset; } @@ -65,10 +65,10 @@ namespace AZ bool Init( const Data::Asset& shaderAsset, const Data::Asset& shaderVariantAsset); - + // AssetBus overrides... void OnAssetReloaded(Data::Asset asset) override; - + //! A reference to the shader asset that this is a variant of. Data::Asset m_shaderAsset; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/BuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/BuilderComponent.cpp index 70752bf02b..ac641d67fc 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/BuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/BuilderComponent.cpp @@ -105,20 +105,6 @@ namespace AZ m_assetHandlers.emplace_back(MakeAssetHandler()); m_assetHandlers.emplace_back(MakeAssetHandler()); m_assetHandlers.emplace_back(MakeAssetHandler()); - - RPI::MaterialFunctorSourceDataRegistration* materialFunctorRegistration = RPI::MaterialFunctorSourceDataRegistration::Get(); - AZ_Assert(materialFunctorRegistration, - "MaterialFunctorSourceDataRegistration must be added to a component of the current module, " - "and initialize it in the component's Init() call."); - materialFunctorRegistration->RegisterMaterialFunctor("Lua", azrtti_typeid()); - - - // Add asset types and extensions to AssetCatalog. Uses "AssetCatalogService". - auto assetCatalog = AZ::Data::AssetCatalogRequestBus::FindFirstHandler(); - if (assetCatalog) - { - assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid()); - } } void BuilderComponent::Deactivate() diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariant.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariant.cpp index acd9922b68..3ef6f76333 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariant.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariant.cpp @@ -91,7 +91,7 @@ namespace AZ { return m_shaderVariantAsset->GetOutputContract(); } - + void ShaderVariant::OnAssetReloaded(Data::Asset asset) { ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderVariant::OnAssetReloaded %s", this, asset.GetHint().c_str()); @@ -102,7 +102,7 @@ namespace AZ Init(m_shaderAsset, shaderVariantAsset); ShaderReloadNotificationBus::Event(m_shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, *this); } - + if (asset.GetAs()) { Data::Asset shaderAsset = { asset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp index 7446c498cd..bb0de1b3c6 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp @@ -119,7 +119,7 @@ namespace AZ { // When reloads occur, it's possible for old Asset objects to hang around and report reinitialization, // so we can reduce unnecessary reinitialization in that case. - if (materialTypeAsset.Get() == m_materialTypeAsset.Get()) + if (materialTypeAsset.Get() == m_materialTypeAsset.Get()) { ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnMaterialTypeAssetReinitialized %s", this, materialTypeAsset.GetHint().c_str()); diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index 50ef1a8e66..72e313157d 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -12,7 +12,7 @@ #include #include -#include // For AZ_MAX_PATH_LEN +#include #include namespace AZ @@ -48,10 +48,10 @@ namespace AZ if (ImGui::Begin("Cpu Profiler", &keepDrawing, ImGuiWindowFlags_None)) { m_paused = !AZ::RHI::CpuProfiler::Get()->IsProfilerEnabled(); - if (ImGui::Button(m_paused?"Resume":"Pause")) + if (ImGui::Button(m_paused ? "Resume" : "Pause")) { m_paused = !m_paused; - AZ::RHI::CpuProfiler::Get()->SetProfilerEnabled(!m_paused); + AZ::RHI::CpuProfiler::Get()->SetProfilerEnabled(!m_paused); } // Update region map and cache the input cpu timing statistics when the profiling is not paused @@ -194,8 +194,8 @@ namespace AZ AZStd::to_string(timeString, timeNow); u64 currentTick = AZ::RPI::RPISystemInterface::Get()->GetCurrentTick(); AZStd::string frameDataFilePath = AZStd::string::format("@user@/CpuProfiler/%s_%llu.json", timeString.c_str(), currentTick); - char resolvedPath[AZ_MAX_PATH_LEN]; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(frameDataFilePath.c_str(), resolvedPath, AZ_MAX_PATH_LEN); + char resolvedPath[AZ::IO::MaxPathLength]; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(frameDataFilePath.c_str(), resolvedPath, AZ::IO::MaxPathLength); m_lastCapturedFilePath = resolvedPath; AZ::Render::ProfilingCaptureRequestBus::Broadcast(&AZ::Render::ProfilingCaptureRequestBus::Events::CaptureCpuProfilingStatistics, frameDataFilePath); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt b/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt index 33fad00cbe..ea4f4259da 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt @@ -61,6 +61,21 @@ ly_add_target( BUILD_DEPENDENCIES PRIVATE Gem::AtomLyIntegration_CommonFeatures.Static + RUNTIME_DEPENDENCIES + Gem::Atom_RPI.Private + Gem::Atom_Feature_Common +) + +# The AtomLyIntegration_CommonFeatures module is used for Clients and Servers +ly_create_alias(NAME AtomLyIntegration_CommonFeatures.Clients NAMESPACE Gem + TARGETS + Gem::AtomLyIntegration_CommonFeatures + Gem::GradientSignal.Clients +) +ly_create_alias(NAME AtomLyIntegration_CommonFeatures.Servers NAMESPACE Gem + TARGETS + Gem::AtomLyIntegration_CommonFeatures + Gem::GradientSignal.Servers ) if(PAL_TRAIT_BUILD_HOST_TOOLS) @@ -94,5 +109,44 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) Legacy::Editor.Headers Legacy::EditorCommon Legacy::CryCommon + RUNTIME_DEPENDENCIES + Gem::Atom_RPI.Editor + Gem::Atom_Feature_Common.Editor + ) + + # The AtomLyIntegration_CommonFeatures.Editor module is used for Builders and Tools + ly_create_alias(NAME AtomLyIntegration_CommonFeatures.Builders NAMESPACE Gem + TARGETS + Gem::AtomLyIntegration_CommonFeatures.Editor + Gem::Atom_RPI.Builders + Gem::GradientSignal.Builders ) + ly_create_alias(NAME AtomLyIntegration_CommonFeatures.Tools NAMESPACE Gem + TARGETS + Gem::AtomLyIntegration_CommonFeatures.Editor + Gem::GradientSignal.Tools + ) + + # AtomLyIntergration_CommonFeatures gem targets are required as part of the Editor and AssetProcessor + # due to the AZ::Render::EditorDirectionalLightComponent, AZ::Render::EditorMeshComponent, + # AZ::Render::EditorGridComponent, AZ::Render::EditorHDRiSkyboxComponent, + # AZ::Render::EditorImageBasedLightComponent being saved as part of the DefaultLevel.prefab + ly_enable_gems(GEMS AtomLyIntegration_CommonFeatures VARIANTS Tools + TARGETS Editor) + ly_enable_gems(GEMS AtomLyIntegration_CommonFeatures VARIANTS Builders + TARGETS AssetBuilder AssetProcessor AssetProcessorBatch) endif() + + +# Added dependencies to the Client and Server Launchers +get_property(LY_PROJECTS_TARGET_NAME GLOBAL PROPERTY LY_PROJECTS_TARGET_NAME) +foreach(project_name IN LISTS LY_PROJECTS_TARGET_NAME) + # Add gem as a dependency of the Clients Launcher + ly_enable_gems(PROJECT_NAME ${project_name} GEMS AtomLyIntegration_CommonFeatures VARIANTS Clients + TARGETS ${project_name}.GameLauncher) + # Add gem as a dependency of the Servers Launcher + if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) + ly_enable_gems(PROJECT_NAME ${project_name} GEMS AtomLyIntegration_CommonFeatures VARIANTS Servers + TARGETS ${project_name}.ServerLauncher) + endif() +endforeach() diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp index 91a909e809..378059b766 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp @@ -179,18 +179,18 @@ namespace AZ ->EnumAttribute(PcfMethod::BoundarySearch, "Boundary search") ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) - ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled) ->DataElement( Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_esmExponent, "Esm Exponent", - "Exponent used by Esm shadows. " - "Larger values increase the sharpness of the border between lit and unlit areas.") + "Exponent used by Esm shadows. " + "Larger values increase the sharpness of the border between lit and unlit areas.") ->Attribute(Edit::Attributes::Min, 50.0f) - ->Attribute(Edit::Attributes::Max, 5000.0f) + ->Attribute(Edit::Attributes::Max, 5000.0f) ->Attribute(AZ::Edit::Attributes::Decimals, 0) ->Attribute(AZ::Edit::Attributes::SliderCurveMidpoint, 0.05f) - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) - ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsEsmDisabled) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsEsmDisabled) ; } } diff --git a/Gems/Camera/Code/CMakeLists.txt b/Gems/Camera/Code/CMakeLists.txt index 703424416b..b45f768cb7 100644 --- a/Gems/Camera/Code/CMakeLists.txt +++ b/Gems/Camera/Code/CMakeLists.txt @@ -69,4 +69,22 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) # tools and builders use the above module. ly_create_alias(NAME Camera.Tools NAMESPACE Gem TARGETS Gem::Camera.Editor) ly_create_alias(NAME Camera.Builders NAMESPACE Gem TARGETS Gem::Camera.Editor) + + # The DefaultPrefab contains an EditorCameraComponent which makes this gem required + ly_enable_gems(GEMS Camera VARIANTS Tools TARGETS Editor) + ly_enable_gems(GEMS Camera VARIANTS Builders TARGETS AssetBuilder AssetProcessor AssetProcessorBatch) endif() + + +# Added dependencies to the Client and Server Launchers +get_property(LY_PROJECTS_TARGET_NAME GLOBAL PROPERTY LY_PROJECTS_TARGET_NAME) +foreach(project_name IN LISTS LY_PROJECTS_TARGET_NAME) + # Add gem as a dependency of the Clients Launcher + ly_enable_gems(PROJECT_NAME ${project_name} GEMS Camera VARIANTS Clients + TARGETS ${project_name}.GameLauncher) + # Add gem as a dependency of the Servers Launcher + if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) + ly_enable_gems(PROJECT_NAME ${project_name} GEMS Camera VARIANTS Servers + TARGETS ${project_name}.ServerLauncher) + endif() +endforeach() diff --git a/Gems/Maestro/Code/CMakeLists.txt b/Gems/Maestro/Code/CMakeLists.txt index 01b22b1abf..d92f2ab643 100644 --- a/Gems/Maestro/Code/CMakeLists.txt +++ b/Gems/Maestro/Code/CMakeLists.txt @@ -78,8 +78,25 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) ly_create_alias(NAME Maestro.Tools NAMESPACE Gem TARGETS Gem::Maestro.Editor) ly_create_alias(NAME Maestro.Builders NAMESPACE Gem TARGETS Gem::Maestro.Editor) + # Maestro is still used by the CrySystem Level System and SystemInit and TrackView + # It is required by the GameLauncher, ServerLauncher and Editor applications + ly_enable_gems(GEMS Maestro VARIANTS Tools TARGETS Editor) + endif() +# Loop over each Project name to allow the ${ProjectName}.GameLauncher and ${ProjectName}.ServerLauncher +# target to add the gem the Clients and Servers variant +get_property(LY_PROJECTS_TARGET_NAME GLOBAL PROPERTY LY_PROJECTS_TARGET_NAME) +foreach(project_name IN LISTS LY_PROJECTS_TARGET_NAME) + # Add gem as a dependency of the Clients Launcher + ly_enable_gems(PROJECT_NAME ${project_name} GEMS Maestro VARIANTS Clients TARGETS ${project_name}.GameLauncher) + # Add gem as a dependency of the Servers Launcher + if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) + ly_enable_gems(PROJECT_NAME ${project_name} GEMS Maestro VARIANTS Servers TARGETS ${project_name}.ServerLauncher) + endif() +endforeach() + + ################################################################################ # Tests ################################################################################ diff --git a/Gems/Prefab/PrefabBuilder/CMakeLists.txt b/Gems/Prefab/PrefabBuilder/CMakeLists.txt index dbd3c2281b..f6de132dcb 100644 --- a/Gems/Prefab/PrefabBuilder/CMakeLists.txt +++ b/Gems/Prefab/PrefabBuilder/CMakeLists.txt @@ -26,7 +26,7 @@ ly_add_target( ) ly_add_target( - NAME PrefabBuilder MODULE + NAME PrefabBuilder GEM_MODULE NAMESPACE Gem INCLUDE_DIRECTORIES PRIVATE @@ -47,7 +47,7 @@ ly_enable_gems(GEMS PrefabBuilder VARIANTS Builders TARGETS AssetProcessor Asset # if you have a custom builder application in your project, then use ly_enable_gems() to # add it to that application for your project, like this to make YOUR_TARGET_NAME load it automatically -# ly_enable_gems(PROJECT (YOUR_PROJECT_NAME) GEMS PrefabBuilder VARIANTS Builders TARGETS (YOUR_TARGET_NAME) ) +# ly_enable_gems(PROJECT_NAME (YOUR_PROJECT_NAME) GEMS PrefabBuilder VARIANTS Builders TARGETS (YOUR_TARGET_NAME) ) if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_target( diff --git a/Gems/QtForPython/Code/CMakeLists.txt b/Gems/QtForPython/Code/CMakeLists.txt index c11d93634e..f0d82a1464 100644 --- a/Gems/QtForPython/Code/CMakeLists.txt +++ b/Gems/QtForPython/Code/CMakeLists.txt @@ -45,7 +45,7 @@ ly_add_target( ) ly_add_target( - NAME QtForPython.Editor MODULE + NAME QtForPython.Editor GEM_MODULE NAMESPACE Gem FILES_CMAKE qtforpython_shared_files.cmake diff --git a/Gems/SceneProcessing/Code/CMakeLists.txt b/Gems/SceneProcessing/Code/CMakeLists.txt index 4b0dfbab27..6a26a176b5 100644 --- a/Gems/SceneProcessing/Code/CMakeLists.txt +++ b/Gems/SceneProcessing/Code/CMakeLists.txt @@ -70,8 +70,14 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) ly_create_alias(NAME SceneProcessing.Builders NAMESPACE Gem TARGETS Gem::SceneProcessing.Editor) ly_create_alias(NAME SceneProcessing.Tools NAMESPACE Gem TARGETS Gem::SceneProcessing.Editor) +# SceneProcessing Gem is only used in Tools and builders and is a requirement for the Editor +ly_enable_gems(GEMS SceneProcessing VARIANTS Tools + TARGETS Editor) +ly_enable_gems(GEMS SceneProcessing VARIANTS Builders + TARGETS AssetBuilder AssetProcessor AssetProcessorBatch) endif() + ################################################################################ # Tests ################################################################################ diff --git a/Templates/DefaultGem/Template/Code/CMakeLists.txt b/Templates/DefaultGem/Template/Code/CMakeLists.txt index b0e52dd79f..25b393302c 100644 --- a/Templates/DefaultGem/Template/Code/CMakeLists.txt +++ b/Templates/DefaultGem/Template/Code/CMakeLists.txt @@ -85,7 +85,7 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) ) ly_add_target( - NAME ${Name}.Editor MODULE + NAME ${Name}.Editor GEM_MODULE NAMESPACE Gem AUTOMOC OUTPUT_NAME Gem.${Name}.Editor diff --git a/cmake/Gems.cmake b/cmake/Gems.cmake index 169210d991..b9c47fd54d 100644 --- a/cmake/Gems.cmake +++ b/cmake/Gems.cmake @@ -84,7 +84,7 @@ function(ly_create_alias) # now add the final alias: add_library(${ly_create_alias_NAMESPACE}::${ly_create_alias_NAME} ALIAS ${ly_create_alias_NAME}) - # Store off the arguments needed used ly_create_alias into a DIRECTORY property + # Store off the arguments used by ly_create_alias into a DIRECTORY property # This will be used to re-create the calls in the generated CMakeLists.txt in the INSTALL step # Replace the CMake list separator with a space to replicate the space separated TARGETS arguments @@ -136,8 +136,8 @@ function(ly_enable_gems) if(NOT was_able_to_load_the_file) message(FATAL_ERROR "could not load the GEM_FILE ${ly_enable_gems_GEM_FILE}") endif() - if(NOT ENABLED_GEMS) - message(FATAL_ERROR "GEM_FILE ${ly_enable_gems_GEM_FILE} did not set the value of ENABLED_GEMS.\n" + if(NOT DEFINED ENABLED_GEMS) + message(WARNING "GEM_FILE ${ly_enable_gems_GEM_FILE} did not set the value of ENABLED_GEMS.\n" "Gem Files should contain set(ENABLED_GEMS ... )") endif() set(ly_enable_gems_GEMS ${ENABLED_GEMS}) @@ -148,9 +148,19 @@ function(ly_enable_gems) foreach(target_name ${ly_enable_gems_TARGETS}) foreach(variant_name ${ly_enable_gems_VARIANTS}) set_property(GLOBAL APPEND PROPERTY LY_DELAYED_ENABLE_GEMS "${ly_enable_gems_PROJECT_NAME},${target_name},${variant_name}") + define_property(GLOBAL PROPERTY LY_DELAYED_ENABLE_GEMS_"${ly_enable_gems_PROJECT_NAME},${target_name},${variant_name}" + BRIEF_DOCS "List of gem names to evaluate variants against" FULL_DOCS "Names of gems that will be paired with the variant name + to determine if it is valid target that should be added as an application dynamic load dependency") set_property(GLOBAL APPEND PROPERTY LY_DELAYED_ENABLE_GEMS_"${ly_enable_gems_PROJECT_NAME},${target_name},${variant_name}" ${ly_enable_gems_GEMS}) endforeach() endforeach() + + # Store off the arguments used by ly_enable_gems into a DIRECTORY property + # This will be used to re-create the ly_enable_gems call in the generated CMakeLists.txt at the INSTALL step + + # Replace the CMake list separator with a space to replicate the space separated TARGETS arguments + string(REPLACE ";" " " enable_gems_args "${ly_enable_gems_PROJECT_NAME},${ly_enable_gems_GEMS},${ly_enable_gems_GEM_FILE},${ly_enable_gems_VARIANTS},${ly_enable_gems_TARGETS}") + set_property(DIRECTORY APPEND PROPERTY LY_ENABLE_GEMS_ARGUMENTS "${enable_gems_args}") endfunction() # call this before runtime dependencies are used to add any relevant targets @@ -176,6 +186,20 @@ function(ly_enable_gems_delayed) get_property(gem_dependencies GLOBAL PROPERTY LY_DELAYED_ENABLE_GEMS_"${project_target_variant}") if (NOT gem_dependencies) + get_property(gem_dependencies_defined GLOBAL PROPERTY LY_DELAYED_ENABLE_GEMS_"${project_target_variant}" DEFINED) + if (gem_dependencies_defined) + # special case, if the LY_DELAYED_ENABLE_GEMS_"${project_target_variant}" property is DEFINED + # but empty, add an entry to the LY_DELAYED_LOAD_DEPENDENCIES to have the + # cmake_dependencies.*.setreg file for the (project, target) tuple to be regenerated + # This is needed if the ENABLED_GEMS list for a project goes from >0 to 0. In this case + # the cmake_dependencies would have a stale list of gems to load unless it is regenerated + get_property(delayed_load_target_set GLOBAL PROPERTY LY_DELAYED_LOAD_"${project},${target}" SET) + if(NOT delayed_load_target_set) + set_property(GLOBAL APPEND PROPERTY LY_DELAYED_LOAD_DEPENDENCIES "${project},${target}") + set_property(GLOBAL APPEND PROPERTY LY_DELAYED_LOAD_"${project},${target}" "") + endif() + endif() + # Continue to the next iteration loop regardless as there are no gem dependencies continue() endif() diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index bf7134d470..6998c260b7 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -13,8 +13,8 @@ set(CMAKE_INSTALL_MESSAGE NEVER) # Simplify messages to reduce output noise ly_set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Core) -file(RELATIVE_PATH runtime_output_directory ${CMAKE_BINARY_DIR} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -file(RELATIVE_PATH library_output_directory ${CMAKE_BINARY_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) +cmake_path(RELATIVE_PATH CMAKE_RUNTIME_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE runtime_output_directory) +cmake_path(RELATIVE_PATH CMAKE_LIBRARY_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE library_output_directory) # Anywhere CMAKE_INSTALL_PREFIX is used, it has to be escaped so it is baked into the cmake_install.cmake script instead # of baking the path. This is needed so `cmake --install --prefix ` works regardless of the CMAKE_INSTALL_PREFIX # used to generate the solution. @@ -22,11 +22,34 @@ file(RELATIVE_PATH library_output_directory ${CMAKE_BINARY_DIR} ${CMAKE_LIBRARY_ set(install_output_folder "\${CMAKE_INSTALL_PREFIX}/${runtime_output_directory}/${PAL_PLATFORM_NAME}/$") +function(ly_get_engine_relative_source_dir absolute_target_source_dir output_source_dir) + # Get a relative target source directory to the LY root folder if possible + # Otherwise use the final component name + cmake_path(IS_PREFIX LY_ROOT_FOLDER ${absolute_target_source_dir} is_target_prefix_of_engine_root) + if(is_target_prefix_of_engine_root) + cmake_path(RELATIVE_PATH absolute_target_source_dir BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE relative_target_source_dir) + else() + # In this case the target source directory is outside of the engine root of the target source directory and concatenate the first + # is used first 8 characters of the absolute path SHA256 hash to make a unique relative directory + # that can be used to install the generated CMakeLists.txt + # of a SHA256 hash + string(SHA256 target_source_hash ${absolute_target_source_dir}) + string(SUBSTRING ${target_source_hash} 0 8 target_source_hash) + cmake_path(GET absolute_target_source_dir FILENAME target_source_dirname) + cmake_path(SET relative_target_source_dir "${target_source_dirname}-${target_source_hash}") + endif() + + set(${output_source_dir} ${relative_target_source_dir} PARENT_SCOPE) +endfunction() + #! ly_setup_target: Setup the data needed to re-create the cmake target commands for a single target -function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME) +function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_target_source_dir) # De-alias target name ly_de_alias_target(${ALIAS_TARGET_NAME} TARGET_NAME) + # Get the target source directory relative to the LY root folder + ly_get_engine_relative_source_dir(${absolute_target_source_dir} relative_target_source_dir) + # get the component ID. if the property isn't set for the target, it will auto fallback to use CMAKE_INSTALL_DEFAULT_COMPONENT_NAME get_property(install_component TARGET ${TARGET_NAME} PROPERTY INSTALL_COMPONENT) @@ -67,16 +90,16 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME) endif() # Get the output folders, archive is always the same, but runtime/library can be in subfolders defined per target - file(RELATIVE_PATH archive_output_directory ${CMAKE_BINARY_DIR} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) + cmake_path(RELATIVE_PATH CMAKE_ARCHIVE_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE archive_output_directory) get_target_property(target_runtime_output_directory ${TARGET_NAME} RUNTIME_OUTPUT_DIRECTORY) if(target_runtime_output_directory) - file(RELATIVE_PATH target_runtime_output_subdirectory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${target_runtime_output_directory}) + cmake_path(RELATIVE_PATH target_runtime_output_directory BASE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} OUTPUT_VARIABLE target_runtime_output_subdirectory) endif() get_target_property(target_library_output_directory ${TARGET_NAME} LIBRARY_OUTPUT_DIRECTORY) if(target_library_output_directory) - file(RELATIVE_PATH target_library_output_subdirectory ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${target_library_output_directory}) + cmake_path(RELATIVE_PATH target_library_output_directory BASE_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} OUTPUT_VARIABLE target_library_output_subdirectory) endif() install( @@ -127,9 +150,9 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME) foreach(include ${include_directories}) string(GENEX_STRIP ${include} include_genex_expr) if(include_genex_expr STREQUAL include) # only for cases where there are no generation expressions - file(RELATIVE_PATH relative_include ${absolute_target_source_dir} ${include}) - cmake_path(APPEND include_location "${target_source_dir}" "${relative_include}" OUTPUT_VARIABLE target_include) + cmake_path(RELATIVE_PATH include BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE target_include) cmake_path(NORMAL_PATH target_include) + # Escape the LY_ROOT_FOLDER variable so that it isn't resolved during the install step string(APPEND INCLUDE_DIRECTORIES_PLACEHOLDER "\${LY_ROOT_FOLDER}/${target_include}\n") endif() endforeach() @@ -207,21 +230,10 @@ set_property(TARGET ${TARGET_NAME} endif() endif() - if(IS_ABSOLUTE ${target_source_dir}) - # This normally applies the target_source_dir is outside of the engine root - # such as when invoking ly_setup_subdirectory from the project - # Therefore the final directory component of the target source directory is used first 8 characters - # of a SHA256 hash - string(SHA256 target_source_hash ${target_source_dir}) - string(SUBSTRING ${target_source_hash} 0 8 target_source_hash) - get_filename_component(target_source_folder_name ${target_source_dir} NAME) - set(target_source_dir "${target_source_folder_name}-${target_source_hash}") - endif() - - set(target_install_source_dir ${CMAKE_CURRENT_BINARY_DIR}/install/${target_source_dir}) + set(target_install_source_dir ${CMAKE_CURRENT_BINARY_DIR}/install/${relative_target_source_dir}) file(GENERATE OUTPUT "${target_install_source_dir}/${NAME_PLACEHOLDER}_$.cmake" CONTENT "${target_file_contents}") install(FILES "${target_install_source_dir}/${NAME_PLACEHOLDER}_$.cmake" - DESTINATION ${target_source_dir} + DESTINATION ${relative_target_source_dir} COMPONENT ${install_component} ) @@ -231,24 +243,26 @@ set_property(TARGET ${TARGET_NAME} set(${OUTPUT_CONFIGURED_TARGET} ${output_cmakelists_data} PARENT_SCOPE) endfunction() + #! ly_setup_subdirectories: setups all targets on a per directory basis function(ly_setup_subdirectories) get_property(all_subdirectories GLOBAL PROPERTY LY_ALL_TARGET_DIRECTORIES) - foreach(target IN LISTS all_subdirectories) - ly_setup_subdirectory(${target}) + foreach(target_subdirectory IN LISTS all_subdirectories) + ly_setup_subdirectory(${target_subdirectory}) endforeach() endfunction() -#! ly_setup_subdirectory: setup all targets in the subdirectory +#! ly_setup_subdirectory: setup all targets in the subdirectory function(ly_setup_subdirectory absolute_target_source_dir) + # Get the target source directory relative to the LY roo folder + ly_get_engine_relative_source_dir(${absolute_target_source_dir} relative_target_source_dir) # The builtin BUILDSYSTEM_TARGETS property isn't being used here as that returns the de-alised # TARGET and we need the alias namespace for recreating the CMakeLists.txt in the install layout get_property(ALIAS_TARGETS_NAME DIRECTORY ${absolute_target_source_dir} PROPERTY LY_DIRECTORY_TARGETS) - file(RELATIVE_PATH target_source_dir ${LY_ROOT_FOLDER} ${absolute_target_source_dir}) foreach(ALIAS_TARGET_NAME IN LISTS ALIAS_TARGETS_NAME) - ly_setup_target(configured_target ${ALIAS_TARGET_NAME}) + ly_setup_target(configured_target ${ALIAS_TARGET_NAME} ${absolute_target_source_dir}) string(APPEND all_configured_targets "${configured_target}") endforeach() @@ -271,34 +285,55 @@ function(ly_setup_subdirectory absolute_target_source_dir) string(APPEND CREATE_ALIASES_PLACEHOLDER ${create_alias_command}) endforeach() - file(READ ${LY_ROOT_FOLDER}/cmake/install/Copyright.in cmake_copyright_comment) - if(IS_ABSOLUTE ${target_source_dir}) - # This normally applies the target_source_dir is outside of the engine root - # such as when invoking ly_setup_subdirectory from the project - # Therefore the final directory component of the target source directory is used first 8 characters - # of a SHA256 hash - string(SHA256 target_source_hash ${target_source_dir}) - string(SUBSTRING ${target_source_hash} 0 8 target_source_hash) - get_filename_component(target_source_folder_name ${target_source_dir} NAME) - set(target_source_dir "${target_source_folder_name}-${target_source_hash}") - endif() + # Reproduce the ly_enable_gems() calls made in the the SOURCE_DIR for this target into the CMakeLists.txt that + # is about to be generated + string(JOIN "\n" enable_gems_template + " ly_enable_gems(@enable_gem_PROJECT_NAME@ @enable_gem_GEM@ @enable_gem_GEM_FILE@ @enable_gem_VARIANTS@ @enable_gem_TARGETS@)" + "endif()" + "" + ) + get_property(enable_gems_commands_arg_list DIRECTORY ${absolute_target_source_dir} PROPERTY LY_ENABLE_GEMS_ARGUMENTS) + foreach(enable_gems_single_command_arg_list ${enable_gems_commands_arg_list}) + # Split the ly_enable_gems arguments back out based on commas + string(REPLACE "," ";" ly_enable_gems_single_command_arg_list "${enable_gems_single_command_arg_list}") + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_PROJECT_NAME) + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_GEM) + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_GEM_FILE) + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_GEM) + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_VARIANTS) + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_TARGETS) + foreach(enable_gem_arg_kw IN ITEMS PROJECT_NAME GEM GEM_FILE GEM VARIANTS TARGETS) + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_${enable_gem_arg_kw}) + if(enable_gem_${enable_gem_arg_kw}) + # if the argument exist append to argument keyword to the front + string(PREPEND enable_gem_${enable_gem_arg_kw} "${enable_gem_arg_kw} ") + endif() + endforeach() + + string(CONFIGURE "${enable_gems_template}" enable_gems_command @ONLY) + string(APPEND ENABLE_GEMS_PLACEHOLDER ${enable_gems_command}) + endforeach() + + + file(READ ${LY_ROOT_FOLDER}/cmake/install/Copyright.in cmake_copyright_comment) # Initialize the target install source directory to path underneath the current binary directory - set(target_install_source_dir ${CMAKE_CURRENT_BINARY_DIR}/install/${target_source_dir}) + set(target_install_source_dir ${CMAKE_CURRENT_BINARY_DIR}/install/${relative_target_source_dir}) # Write out all the aggregated ly_add_target function calls and the final ly_create_alias() calls to the target CMakeLists.txt file(WRITE ${target_install_source_dir}/CMakeLists.txt "${cmake_copyright_comment}" "${all_configured_targets}" "\n" "${CREATE_ALIASES_PLACEHOLDER}" + "${ENABLE_GEMS_PLACEHOLDER}" ) # get the component ID. if the property isn't set for the directory, it will auto fallback to use CMAKE_INSTALL_DEFAULT_COMPONENT_NAME get_property(install_component DIRECTORY ${absolute_target_source_dir} PROPERTY INSTALL_COMPONENT) install(FILES "${target_install_source_dir}/CMakeLists.txt" - DESTINATION ${target_source_dir} + DESTINATION ${relative_target_source_dir} COMPONENT ${install_component} ) @@ -328,7 +363,7 @@ function(ly_setup_cmake_install) # Transform the LY_EXTERNAL_SUBDIRS list into a json array set(indent " ") foreach(external_subdir ${LY_EXTERNAL_SUBDIRS}) - file(RELATIVE_PATH engine_rel_external_subdir ${LY_ROOT_FOLDER} ${external_subdir}) + cmake_path(RELATIVE_PATH external_subdir BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE engine_rel_external_subdir) list(APPEND relative_external_subdirs "\"${engine_rel_external_subdir}\"") endforeach() list(JOIN relative_external_subdirs ",\n${indent}" LY_INSTALL_EXTERNAL_SUBDIRS) @@ -368,8 +403,8 @@ function(ly_setup_cmake_install) # Add to the FIND_PACKAGES_PLACEHOLDER all directories in which ly_add_target were called in get_property(all_subdirectories GLOBAL PROPERTY LY_ALL_TARGET_DIRECTORIES) foreach(target_subdirectory IN LISTS all_subdirectories) - file(RELATIVE_PATH target_source_dir_relative ${LY_ROOT_FOLDER} ${target_subdirectory}) - string(APPEND FIND_PACKAGES_PLACEHOLDER " add_subdirectory(${target_source_dir_relative})\n") + cmake_path(RELATIVE_PATH target_subdirectory BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE relative_target_subdirectory) + string(APPEND FIND_PACKAGES_PLACEHOLDER " add_subdirectory(${relative_target_subdirectory})\n") endforeach() configure_file(${LY_ROOT_FOLDER}/cmake/install/Findo3de.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/cmake/Findo3de.cmake @ONLY) @@ -430,7 +465,7 @@ endfunction()" get_target_property(target_runtime_output_directory ${target} RUNTIME_OUTPUT_DIRECTORY) if(target_runtime_output_directory) - file(RELATIVE_PATH target_runtime_output_subdirectory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${target_runtime_output_directory}) + cmake_path(RELATIVE_PATH target_runtime_output_directory BASE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} OUTPUT_VARIABLE target_runtime_output_subdirectory) endif() # Qt diff --git a/scripts/o3de/o3de/register.py b/scripts/o3de/o3de/register.py index b3a6a1e44c..37c572b6a4 100644 --- a/scripts/o3de/o3de/register.py +++ b/scripts/o3de/o3de/register.py @@ -64,9 +64,9 @@ def register_shipped_engine_o3de_objects(force: bool = False) -> int: return ret_val -def register_all_in_folder(folder_path: str or pathlib.Path, +def register_all_in_folder(folder_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None, + engine_path: pathlib.Path = None, exclude: list = None) -> int: if not folder_path: logger.error(f'Folder path cannot be empty.') @@ -136,10 +136,11 @@ def register_all_in_folder(folder_path: str or pathlib.Path, return ret_val -def register_all_o3de_objects_of_type_in_folder(o3de_object_path: str or pathlib.Path, +def register_all_o3de_objects_of_type_in_folder(o3de_object_path: pathlib.Path, o3de_object_type: str, remove: bool, force: bool, + stop_iteration_callable: callable, **register_kwargs) -> int: if not o3de_object_path: logger.error(f'Engines path cannot be empty.') @@ -155,8 +156,11 @@ def register_all_o3de_objects_of_type_in_folder(o3de_object_path: str or pathlib ret_val = 0 for root, dirs, files in os.walk(o3de_object_path): + # Skip subdirectories where the stop iteration callback is true + if stop_iteration_callable and stop_iteration_callable(dirs, files): + dirs[:] = [] if f'{o3de_object_type}.json' in files: - o3de_object_type_set.add(root) + o3de_object_type_set.add(pathlib.Path(root)) # Stop iteration of any subdirectories # Nested o3de objects of the same type aren't supported(i.e an engine cannot be inside of a engine). dirs[:] = [] @@ -170,41 +174,49 @@ def register_all_o3de_objects_of_type_in_folder(o3de_object_path: str or pathlib return ret_val -def register_all_engines_in_folder(engines_path: str or pathlib.Path, +def stop_on_template_folders(dirs: list, files: list) -> bool: + return 'template.json' in files + + +def register_all_engines_in_folder(engines_path: pathlib.Path, remove: bool = False, force: bool = False) -> int: - return register_all_o3de_objects_of_type_in_folder(engines_path, 'engine', remove, force) + return register_all_o3de_objects_of_type_in_folder(engines_path, 'engine', remove, force, None) -def register_all_projects_in_folder(projects_path: str or pathlib.Path, +def register_all_projects_in_folder(projects_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: - return register_all_o3de_objects_of_type_in_folder(projects_path, 'project', remove, False, engine_path=engine_path) + engine_path: pathlib.Path = None) -> int: + return register_all_o3de_objects_of_type_in_folder(projects_path, 'project', remove, False, + stop_on_template_folders, engine_path=engine_path) -def register_all_gems_in_folder(gems_path: str or pathlib.Path, +def register_all_gems_in_folder(gems_path: pathlib.Path, remove: bool = False, engine_path: pathlib.Path = None, project_path: pathlib.Path = None) -> int: - return register_all_o3de_objects_of_type_in_folder(gems_path, 'gem', remove, False, engine_path=engine_path) + return register_all_o3de_objects_of_type_in_folder(gems_path, 'gem', remove, False, stop_on_template_folders, + engine_path=engine_path) -def register_all_templates_in_folder(templates_path: str or pathlib.Path, +def register_all_templates_in_folder(templates_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: - return register_all_o3de_objects_of_type_in_folder(templates_path, 'template', remove, False, engine_path=engine_path) + engine_path: pathlib.Path = None) -> int: + return register_all_o3de_objects_of_type_in_folder(templates_path, 'template', remove, False, None, + engine_path=engine_path) -def register_all_restricted_in_folder(restricted_path: str or pathlib.Path, +def register_all_restricted_in_folder(restricted_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: - return register_all_o3de_objects_of_type_in_folder(restricted_path, 'restricted', remove, False, engine_path=engine_path) + engine_path: pathlib.Path = None) -> int: + return register_all_o3de_objects_of_type_in_folder(restricted_path, 'restricted', remove, False, None, + engine_path=engine_path) -def register_all_repos_in_folder(repos_path: str or pathlib.Path, +def register_all_repos_in_folder(repos_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: - return register_all_o3de_objects_of_type_in_folder(repos_path, 'repo', remove, force, engine_path=engine_path) + engine_path: pathlib.Path = None) -> int: + return register_all_o3de_objects_of_type_in_folder(repos_path, 'repo', remove, force, None, engine_path=engine_path) def remove_engine_name_to_path(json_data: dict, @@ -252,7 +264,7 @@ def add_engine_name_to_path(json_data: dict, engine_path: pathlib.Path, force: b def register_engine_path(json_data: dict, - engine_path: str or pathlib.Path, + engine_path: pathlib.Path, remove: bool = False, force: bool = False) -> int: if not engine_path: @@ -260,8 +272,11 @@ def register_engine_path(json_data: dict, return 1 engine_path = pathlib.Path(engine_path).resolve() - for engine_object in json_data.get('engines', {}): - engine_object_path = pathlib.Path(engine_object['path']).resolve() + for engine_object in json_data.get('engines', []): + if isinstance(engine_object, dict): + engine_object_path = pathlib.Path(engine_object['path']).resolve() + else: + engine_object_path = pathlib.Path(engine_object).resolve() if engine_object_path == engine_path: json_data['engines'].remove(engine_object) @@ -362,7 +377,7 @@ def register_o3de_object_path(json_data: dict, def register_external_subdirectory(json_data: dict, - external_subdir_path: str or pathlib.Path, + external_subdir_path: pathlib.Path, remove: bool = False, engine_path: pathlib.Path = None, project_path: pathlib.Path = None) -> int: @@ -375,7 +390,7 @@ def register_external_subdirectory(json_data: dict, def register_gem_path(json_data: dict, - gem_path: str or pathlib.Path, + gem_path: pathlib.Path, remove: bool = False, engine_path: pathlib.Path = None, project_path: pathlib.Path = None) -> int: @@ -384,9 +399,9 @@ def register_gem_path(json_data: dict, def register_project_path(json_data: dict, - project_path: str or pathlib.Path, + project_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: + engine_path: pathlib.Path = None) -> int: result = register_o3de_object_path(json_data, project_path, 'projects', 'project.json', validation.valid_o3de_project_json, remove, engine_path, None) @@ -408,9 +423,10 @@ def register_project_path(json_data: dict, update_project_json = True if update_project_json: + project_json_path = project_path / 'project.json' project_json_data['engine'] = this_engine_json['engine_name'] - utils.backup_file(project_json) - if not manifest.save_o3de_manifest(project_json_data, project_path): + utils.backup_file(project_json_path) + if not manifest.save_o3de_manifest(project_json_data, project_json_path): return 1 @@ -418,17 +434,17 @@ def register_project_path(json_data: dict, def register_template_path(json_data: dict, - template_path: str or pathlib.Path, + template_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: + engine_path: pathlib.Path = None) -> int: return register_o3de_object_path(json_data, template_path, 'templates', 'template.json', validation.valid_o3de_template_json, remove, engine_path, None) def register_restricted_path(json_data: dict, - restricted_path: str or pathlib.Path, + restricted_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: + engine_path: pathlib.Path = None) -> int: return register_o3de_object_path(json_data, restricted_path, 'restricted', 'restricted.json', validation.valid_o3de_restricted_json, remove, engine_path, None) @@ -468,7 +484,7 @@ def register_repo(json_data: dict, def register_default_o3de_object_folder(json_data: dict, - default_o3de_object_folder: str or pathlib.Path, + default_o3de_object_folder: pathlib.Path, o3de_object_key: str) -> int: # make sure the path exists default_o3de_object_folder = pathlib.Path(default_o3de_object_folder).resolve() @@ -482,7 +498,7 @@ def register_default_o3de_object_folder(json_data: dict, def register_default_engines_folder(json_data: dict, - default_engines_folder: str or pathlib.Path, + default_engines_folder: pathlib.Path, remove: bool = False) -> int: return register_default_o3de_object_folder(json_data, manifest.get_o3de_engines_folder() if remove else default_engines_folder, @@ -490,7 +506,7 @@ def register_default_engines_folder(json_data: dict, def register_default_projects_folder(json_data: dict, - default_projects_folder: str or pathlib.Path, + default_projects_folder: pathlib.Path, remove: bool = False) -> int: return register_default_o3de_object_folder(json_data, manifest.get_o3de_projects_folder() if remove else default_projects_folder, @@ -498,7 +514,7 @@ def register_default_projects_folder(json_data: dict, def register_default_gems_folder(json_data: dict, - default_gems_folder: str or pathlib.Path, + default_gems_folder: pathlib.Path, remove: bool = False) -> int: return register_default_o3de_object_folder(json_data, manifest.get_o3de_gems_folder() if remove else default_gems_folder, @@ -506,7 +522,7 @@ def register_default_gems_folder(json_data: dict, def register_default_templates_folder(json_data: dict, - default_templates_folder: str or pathlib.Path, + default_templates_folder: pathlib.Path, remove: bool = False) -> int: return register_default_o3de_object_folder(json_data, manifest.get_o3de_templates_folder() if remove else default_templates_folder, @@ -514,7 +530,7 @@ def register_default_templates_folder(json_data: dict, def register_default_restricted_folder(json_data: dict, - default_restricted_folder: str or pathlib.Path, + default_restricted_folder: pathlib.Path, remove: bool = False) -> int: return register_default_o3de_object_folder(json_data, manifest.get_o3de_restricted_folder() if remove else default_restricted_folder, @@ -527,18 +543,18 @@ def register_default_third_party_folder(json_data: dict, manifest.get_o3de_third_party_folder() if remove else default_third_party_folder, 'default_third_party_folder') -def register(engine_path: str or pathlib.Path = None, - project_path: str or pathlib.Path = None, - gem_path: str or pathlib.Path = None, - external_subdir_path: str or pathlib.Path = None, - template_path: str or pathlib.Path = None, - restricted_path: str or pathlib.Path = None, +def register(engine_path: pathlib.Path = None, + project_path: pathlib.Path = None, + gem_path: pathlib.Path = None, + external_subdir_path: pathlib.Path = None, + template_path: pathlib.Path = None, + restricted_path: pathlib.Path = None, repo_uri: str or pathlib.Path = None, - default_engines_folder: str or pathlib.Path = None, - default_projects_folder: str or pathlib.Path = None, - default_gems_folder: str or pathlib.Path = None, - default_templates_folder: str or pathlib.Path = None, - default_restricted_folder: str or pathlib.Path = None, + default_engines_folder: pathlib.Path = None, + default_projects_folder: pathlib.Path = None, + default_gems_folder: pathlib.Path = None, + default_templates_folder: pathlib.Path = None, + default_restricted_folder: pathlib.Path = None, default_third_party_folder: pathlib.Path = None, external_subdir_engine_path: pathlib.Path = None, external_subdir_project_path: pathlib.Path = None, @@ -576,32 +592,32 @@ def register(engine_path: str or pathlib.Path = None, result = 0 # do anything that could require a engine context first - if isinstance(project_path, str) or isinstance(project_path, pathlib.PurePath): + if isinstance(project_path, pathlib.PurePath): if not project_path: logger.error(f'Project path cannot be empty.') return 1 result = result or register_project_path(json_data, project_path, remove, engine_path) - if isinstance(gem_path, str) or isinstance(gem_path, pathlib.PurePath): + if isinstance(gem_path, pathlib.PurePath): if not gem_path: logger.error(f'Gem path cannot be empty.') return 1 result = result or register_gem_path(json_data, gem_path, remove, external_subdir_engine_path, external_subdir_project_path) - if isinstance(external_subdir_path, str) or isinstance(external_subdir_path, pathlib.PurePath): + if isinstance(external_subdir_path, pathlib.PurePath): if not external_subdir_path: logger.error(f'External Subdirectory path is None.') return 1 result = result or register_external_subdirectory(json_data, external_subdir_path, remove, external_subdir_engine_path, external_subdir_project_path) - if isinstance(template_path, str) or isinstance(template_path, pathlib.PurePath): + if isinstance(template_path, pathlib.PurePath): if not template_path: logger.error(f'Template path cannot be empty.') return 1 result = result or register_template_path(json_data, template_path, remove, engine_path) - if isinstance(restricted_path, str) or isinstance(restricted_path, pathlib.PurePath): + if isinstance(restricted_path, pathlib.PurePath): if not restricted_path: logger.error(f'Restricted path cannot be empty.') return 1 @@ -613,28 +629,28 @@ def register(engine_path: str or pathlib.Path = None, return 1 result = result or register_repo(json_data, repo_uri, remove) - if isinstance(default_engines_folder, str) or isinstance(default_engines_folder, pathlib.PurePath): + if isinstance(default_engines_folder, pathlib.PurePath): result = result or register_default_engines_folder(json_data, default_engines_folder, remove) - if isinstance(default_projects_folder, str) or isinstance(default_projects_folder, pathlib.PurePath): + if isinstance(default_projects_folder, pathlib.PurePath): result = result or register_default_projects_folder(json_data, default_projects_folder, remove) - if isinstance(default_gems_folder, str) or isinstance(default_gems_folder, pathlib.PurePath): + if isinstance(default_gems_folder, pathlib.PurePath): result = result or register_default_gems_folder(json_data, default_gems_folder, remove) - if isinstance(default_templates_folder, str) or isinstance(default_templates_folder, pathlib.PurePath): + if isinstance(default_templates_folder, pathlib.PurePath): result = result or register_default_templates_folder(json_data, default_templates_folder, remove) - if isinstance(default_restricted_folder, str) or isinstance(default_restricted_folder, pathlib.PurePath): + if isinstance(default_restricted_folder, pathlib.PurePath): result = result or register_default_restricted_folder(json_data, default_restricted_folder, remove) - if isinstance(default_third_party_folder, str) or isinstance(default_third_party_folder, pathlib.PurePath): + if isinstance(default_third_party_folder, pathlib.PurePath): result = result or register_default_third_party_folder(json_data, default_third_party_folder, remove) # engine is done LAST # Now that everything that could have an engine context is done, if the engine is supplied that means this is # registering the engine itself - if isinstance(engine_path, str) or isinstance(engine_path, pathlib.PurePath): + if isinstance(engine_path, pathlib.PurePath): if not engine_path: logger.error(f'Engine path cannot be empty.') return 1 @@ -789,41 +805,41 @@ def add_parser_args(parser): group.add_argument('--this-engine', action='store_true', required=False, default=False, help='Registers the engine this script is running from.') - group.add_argument('-ep', '--engine-path', type=str, required=False, + group.add_argument('-ep', '--engine-path', type=pathlib.Path, required=False, help='Engine path to register/remove.') - group.add_argument('-pp', '--project-path', type=str, required=False, + group.add_argument('-pp', '--project-path', type=pathlib.Path, required=False, help='Project path to register/remove.') - group.add_argument('-gp', '--gem-path', type=str, required=False, + group.add_argument('-gp', '--gem-path', type=pathlib.Path, required=False, help='Gem path to register/remove.') - group.add_argument('-es', '--external-subdirectory', type=str, required=False, + group.add_argument('-es', '--external-subdirectory', type=pathlib.Path, required=False, help='External subdirectory path to register/remove.') - group.add_argument('-tp', '--template-path', type=str, required=False, + group.add_argument('-tp', '--template-path', type=pathlib.Path, required=False, help='Template path to register/remove.') - group.add_argument('-rp', '--restricted-path', type=str, required=False, + group.add_argument('-rp', '--restricted-path', type=pathlib.Path, required=False, help='A restricted folder to register/remove.') group.add_argument('-ru', '--repo-uri', type=str, required=False, help='A repo uri to register/remove.') - group.add_argument('-aep', '--all-engines-path', type=str, required=False, + group.add_argument('-aep', '--all-engines-path', type=pathlib.Path, required=False, help='All engines under this folder to register/remove.') - group.add_argument('-app', '--all-projects-path', type=str, required=False, + group.add_argument('-app', '--all-projects-path', type=pathlib.Path, required=False, help='All projects under this folder to register/remove.') - group.add_argument('-agp', '--all-gems-path', type=str, required=False, + group.add_argument('-agp', '--all-gems-path', type=pathlib.Path, required=False, help='All gems under this folder to register/remove.') - group.add_argument('-atp', '--all-templates-path', type=str, required=False, + group.add_argument('-atp', '--all-templates-path', type=pathlib.Path, required=False, help='All templates under this folder to register/remove.') - group.add_argument('-arp', '--all-restricted-path', type=str, required=False, + group.add_argument('-arp', '--all-restricted-path', type=pathlib.Path, required=False, help='All templates under this folder to register/remove.') - group.add_argument('-aru', '--all-repo-uri', type=str, required=False, + group.add_argument('-aru', '--all-repo-uri', type=pathlib.Path, required=False, help='All repos under this folder to register/remove.') - group.add_argument('-def', '--default-engines-folder', type=str, required=False, + group.add_argument('-def', '--default-engines-folder', type=pathlib.Path, required=False, help='The default engines folder to register/remove.') - group.add_argument('-dpf', '--default-projects-folder', type=str, required=False, + group.add_argument('-dpf', '--default-projects-folder', type=pathlib.Path, required=False, help='The default projects folder to register/remove.') - group.add_argument('-dgf', '--default-gems-folder', type=str, required=False, + group.add_argument('-dgf', '--default-gems-folder', type=pathlib.Path, required=False, help='The default gems folder to register/remove.') - group.add_argument('-dtf', '--default-templates-folder', type=str, required=False, + group.add_argument('-dtf', '--default-templates-folder', type=pathlib.Path, required=False, help='The default templates folder to register/remove.') - group.add_argument('-drf', '--default-restricted-folder', type=str, required=False, + group.add_argument('-drf', '--default-restricted-folder', type=pathlib.Path, required=False, help='The default restricted folder to register/remove.') group.add_argument('-dtpf', '--default-third-party-folder', type=pathlib.Path, required=False, help='The default 3rd Party folder to register/remove.') @@ -831,7 +847,7 @@ def add_parser_args(parser): default=False, help='Refresh the repo cache.') - parser.add_argument('-ohf', '--override-home-folder', type=str, required=False, + parser.add_argument('-ohf', '--override-home-folder', type=pathlib.Path, required=False, help='By default the home folder is the user folder, override it to this folder.') parser.add_argument('-r', '--remove', action='store_true', required=False, default=False,