From 7dabe8b6e966273940e7d98284966104064b783e Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Thu, 17 Jun 2021 13:58:20 -0500 Subject: [PATCH] Updated Several Engine Gem's CMakeLists.txt to add themselves as required Gems (#1262) * Fixed organization of the AssetProcessor SourceAssetBrowser Assets within the Engine Root were grouped under a '/' entry. That has been fixed to use the relative path within the engine root for those assets Assets outside of the Engine Root, but on the same drive were using absolute paths before. Now there are child entries that navigate up the directory hierarchy to those asset locations * Added ly_enable_gems call to Atom gems targets that are required The DefaultLevel.prefab contains several Atom components, that require the Atom RHI, RPI, Common_Feature, ShaderBuilder and AtomLyIntegration CommonFeatures gems to be enabled in order to successfully process in the AssetProcessor. * Added ly_enable_gems call to make the Camera gem required in Tools, Builders and Clients. This is needed as the DefaultLevel.prefab contains an Editor Camera Component * Adding the ly_enable_gem call to make the Maestro gem required CrySystem currently requires Maestro to be enabled in order to initialize * Added ly_enable_gems call to the SceneProcessing gem to make it required The SceneCore and SceneData libraries that are part of the core engine Code folder requires the SceneProcessing gem to be enabled in order to invoke the InitializeDynamicModule hooks in DllMain.cpp in order to initialize those libraries. * Fixed bad argument in comment for Prefab CMakeLists.txt * Fixed Assert in Asset Builders due to the Atom RPI Builder The Atom RPI Builder was enabling the Asset Catalog for the ScriptAsset a second time The Atom Feature Common EditorSystemCommonComponent.cpp which also loads in the AssetBuilder is enabling the Asset Catalog for the ScriptAsset Added BehaviorContext reflection to the OutputDeviceTransformType enum to fix the BehaviorContext errors about reflecting a method that returns such an enum * Added TypeId output to the JsonDeserializer report message about missing ClassData Previously the report callback would indicate that the target type was missing Serialization class data, but didn't indicate the TypeId of the target type * Added support to the ly_enable_gems function to be able to support 0 gems being enabled. Updated the Install step for CMake to propagate any ly_enable_gems within a CMakeLists.txt for a target into the generated CMakeLists.txt that is made for each installed IMPORTED target * Adding newline to the end of the Camera Gem CMakeLists.txt * Fixing target TYPE parameter for actual Gem Modules to use the GEM_MODULE tag instead of MODULE * Reverting change to the DESTINATION directory for the installed CMakeLists.txt to use the relative path to the installed directory * Adding the Atom_Bootstrap gem as a required gem The Client and GameLaunchers required the Atom_Bootstrap gem in order to create the NativeWindow Added Atom_Feature_Common client module as a runtime dependency of the AtomLyIntegration CommonsFeature client module * Fixed register.py --all-projects-path and --all-gems-path arguments to NOT register projects or gems that are within a template folder Fixed reading of old pre-1.0 o3de_manifest.json files where the "engines" key was a json array * Changed how the relative target source directory is calculated when that source directroy resides outside of the engine root. The final dirname component is used with a unique SHA256 has to form a -<8 char SHA256> folder for installing files into * Adding newline to the end of Atom_Bootstrap CMakeLists.txt * Moving ly_enable_gems variants for Tools and Builders inside of PAL_TRAIT_BUILD_HOST_TOOLS block * Adding a comment to AWSCore.ResourceMappingTool target to indicate that it is not a GEM_MODULE. Furthermore it cannot be loaded with the Gem system because the library is in a different directory the executable --- .../Serialization/Json/JsonDeserializer.cpp | 5 +- .../tests/DummyProject/project.json | 3 +- .../native/ui/SourceAssetTreeModel.cpp | 13 +- Gems/AWSCore/Code/CMakeLists.txt | 4 +- Gems/Atom/Asset/Shader/Code/CMakeLists.txt | 5 + Gems/Atom/Bootstrap/Code/CMakeLists.txt | 17 ++ .../Features/Shadow/ProjectedShadow.azsli | 8 +- .../Shaders/Shadow/DepthExponentiation.azsl | 2 +- Gems/Atom/Feature/Common/Code/CMakeLists.txt | 8 + .../DisplayMapperConfigurationDescriptor.cpp | 13 ++ .../runtime_dependencies_clients.cmake | 14 ++ .../Android/runtime_dependencies_tools.cmake} | 4 +- .../Linux/runtime_dependencies_clients.cmake | 14 ++ .../Linux/runtime_dependencies_tools.cmake | 19 ++ .../Mac/runtime_dependencies_clients.cmake | 14 ++ .../Mac/runtime_dependencies_tools.cmake | 19 ++ .../runtime_dependencies_clients.cmake | 16 ++ .../Windows/runtime_dependencies_tools.cmake | 19 ++ .../iOS/runtime_dependencies_clients.cmake | 14 ++ .../iOS/runtime_dependencies_tools.cmake} | 4 +- .../ProfilingCaptureSystemComponent.cpp | 4 +- Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp | 2 +- Gems/Atom/RPI/Code/CMakeLists.txt | 4 + .../Material/MaterialReloadNotificationBus.h | 2 +- .../Shader/ShaderReloadNotificationBus.h | 2 +- .../Atom/RPI.Public/Shader/ShaderVariant.h | 6 +- .../Source/RPI.Builders/BuilderComponent.cpp | 14 -- .../RPI.Public/Shader/ShaderVariant.cpp | 4 +- .../RPI.Reflect/Material/MaterialAsset.cpp | 2 +- .../Include/Atom/Utils/ImGuiCpuProfiler.inl | 10 +- .../CommonFeatures/Code/CMakeLists.txt | 54 ++++++ .../CoreLights/EditorAreaLightComponent.cpp | 12 +- Gems/Camera/Code/CMakeLists.txt | 18 ++ Gems/Maestro/Code/CMakeLists.txt | 17 ++ Gems/Prefab/PrefabBuilder/CMakeLists.txt | 4 +- Gems/QtForPython/Code/CMakeLists.txt | 2 +- Gems/SceneProcessing/Code/CMakeLists.txt | 6 + .../DefaultGem/Template/Code/CMakeLists.txt | 2 +- cmake/Gems.cmake | 30 ++- cmake/Platform/Common/Install_common.cmake | 121 +++++++----- scripts/o3de/o3de/register.py | 176 ++++++++++-------- 41 files changed, 521 insertions(+), 186 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Code/Source/Platform/Android/runtime_dependencies_clients.cmake rename Gems/Atom/Feature/Common/Code/{Platform/Common/atom_feature_common_msvc.cmake => Source/Platform/Android/runtime_dependencies_tools.cmake} (91%) create mode 100644 Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_clients.cmake create mode 100644 Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_tools.cmake create mode 100644 Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_clients.cmake create mode 100644 Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_tools.cmake create mode 100644 Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_clients.cmake create mode 100644 Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_tools.cmake create mode 100644 Gems/Atom/Feature/Common/Code/Source/Platform/iOS/runtime_dependencies_clients.cmake rename Gems/Atom/Feature/Common/Code/{Platform/Common/atom_feature_common_clang.cmake => Source/Platform/iOS/runtime_dependencies_tools.cmake} (90%) 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,