From 898b1811e0be97b50e9b7845803765fda0635d5f Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 21 Oct 2021 16:04:38 -0500 Subject: [PATCH 01/97] material editor loads source data Signed-off-by: Guthrie Adams --- .../RPI.Edit/Material/MaterialSourceData.h | 25 ++- .../RPI.Edit/Material/MaterialSourceData.cpp | 209 +++++++++++++----- .../Material/MaterialTypeAssetCreator.cpp | 1 + .../Code/Source/Document/MaterialDocument.cpp | 2 +- 4 files changed, 172 insertions(+), 65 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h index a67477f061..739c4341a9 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h @@ -31,6 +31,7 @@ namespace AZ static constexpr const char UvGroupName[] = "uvSets"; class MaterialAsset; + class MaterialAssetCreator; //! This is a simple data structure for serializing in/out material source files. class MaterialSourceData final @@ -78,15 +79,33 @@ namespace AZ //! Creates a MaterialAsset from the MaterialSourceData content. //! @param assetId ID for the MaterialAsset - //! @param materialSourceFilePath Indicates the path of the .material file that the MaterialSourceData represents. Used for resolving file-relative paths. + //! @param materialSourceFilePath Indicates the path of the .material file that the MaterialSourceData represents. Used for + //! resolving file-relative paths. //! @param elevateWarnings Indicates whether to treat warnings as errors //! @param includeMaterialPropertyNames Indicates whether to save material property names into the material asset file Outcome> CreateMaterialAsset( Data::AssetId assetId, AZStd::string_view materialSourceFilePath = "", bool elevateWarnings = true, - bool includeMaterialPropertyNames = true - ) const; + bool includeMaterialPropertyNames = true) const; + + //! Creates a MaterialAsset from the MaterialSourceData content. + //! @param assetId ID for the MaterialAsset + //! @param materialSourceFilePath Indicates the path of the .material file that the MaterialSourceData represents. Used for + //! resolving file-relative paths. + //! @param elevateWarnings Indicates whether to treat warnings as errors + //! @param includeMaterialPropertyNames Indicates whether to save material property names into the material asset file + Outcome> CreateMaterialAssetFromSourceData( + Data::AssetId assetId, + AZStd::string_view materialSourceFilePath = "", + bool elevateWarnings = true, + bool includeMaterialPropertyNames = true) const; + + private: + static void ApplyMaterialSourceDataPropertiesToAssetCreator( + AZ::RPI::MaterialAssetCreator& materialAssetCreator, + const AZStd::string_view& materialSourceFilePath, + const MaterialSourceData& materialSourceData); }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 1467b017d5..2a76befdf4 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -126,7 +127,8 @@ namespace AZ return changesWereApplied ? ApplyVersionUpdatesResult::UpdatesApplied : ApplyVersionUpdatesResult::NoUpdates; } - Outcome > MaterialSourceData::CreateMaterialAsset(Data::AssetId assetId, AZStd::string_view materialSourceFilePath, bool elevateWarnings, bool includeMaterialPropertyNames) const + Outcome> MaterialSourceData::CreateMaterialAsset( + Data::AssetId assetId, AZStd::string_view materialSourceFilePath, bool elevateWarnings, bool includeMaterialPropertyNames) const { MaterialAssetCreator materialAssetCreator; materialAssetCreator.SetElevateWarnings(elevateWarnings); @@ -172,66 +174,7 @@ namespace AZ materialAssetCreator.Begin(assetId, *parentMaterialAsset.GetValue().Get(), includeMaterialPropertyNames); } - for (auto& group : m_properties) - { - for (auto& property : group.second) - { - MaterialPropertyId propertyId{ group.first, property.first }; - if (!property.second.m_value.IsValid()) - { - AZ_Warning("Material source data", false, "Source data for material property value is invalid."); - } - else - { - MaterialPropertyIndex propertyIndex = materialAssetCreator.m_materialPropertiesLayout->FindPropertyIndex(propertyId.GetFullName()); - if (propertyIndex.IsValid()) - { - const MaterialPropertyDescriptor* propertyDescriptor = materialAssetCreator.m_materialPropertiesLayout->GetPropertyDescriptor(propertyIndex); - switch (propertyDescriptor->GetDataType()) - { - case MaterialPropertyDataType::Image: - { - Outcome> imageAssetResult = MaterialUtils::GetImageAssetReference(materialSourceFilePath, property.second.m_value.GetValue()); - - if (imageAssetResult.IsSuccess()) - { - auto& imageAsset = imageAssetResult.GetValue(); - // Load referenced images when load material - imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); - materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); - } - else - { - materialAssetCreator.ReportError("Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), property.second.m_value.GetValue().data()); - } - } - break; - case MaterialPropertyDataType::Enum: - { - AZ::Name enumName = AZ::Name(property.second.m_value.GetValue()); - uint32_t enumValue = propertyDescriptor->GetEnumValue(enumName); - if (enumValue == MaterialPropertyDescriptor::InvalidEnumValue) - { - materialAssetCreator.ReportError("Enum value '%s' couldn't be found in the 'enumValues' list", enumName.GetCStr()); - } - else - { - materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), enumValue); - } - } - break; - default: - materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), property.second.m_value); - break; - } - } - else - { - materialAssetCreator.ReportWarning("Can not find property id '%s' in MaterialPropertyLayout", propertyId.GetFullName().GetStringView().data()); - } - } - } - } + ApplyMaterialSourceDataPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath, *this); Data::Asset material; if (materialAssetCreator.End(material)) @@ -244,5 +187,149 @@ namespace AZ } } + Outcome> MaterialSourceData::CreateMaterialAssetFromSourceData( + Data::AssetId assetId, AZStd::string_view materialSourceFilePath, bool elevateWarnings, bool includeMaterialPropertyNames) const + { + MaterialAssetCreator materialAssetCreator; + materialAssetCreator.SetElevateWarnings(elevateWarnings); + + MaterialTypeSourceData materialTypeSourceData; + AZStd::string materialTypeSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, m_materialType); + if (!AZ::RPI::JsonUtils::LoadObjectFromFile(materialTypeSourcePath, materialTypeSourceData)) + { + return Failure(); + } + + materialTypeSourceData.ResolveUvEnums(); + + auto materialTypeAsset = + materialTypeSourceData.CreateMaterialTypeAsset(AZ::Uuid::CreateRandom(), materialTypeSourcePath, elevateWarnings); + if (!materialTypeAsset.IsSuccess()) + { + return Failure(); + } + + materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); + + AZStd::vector parentMaterialSourceDataVec; + + AZStd::string parentMaterialPath = m_parentMaterial; + AZStd::string parentMaterialSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, parentMaterialPath); + while (!parentMaterialPath.empty()) + { + MaterialSourceData parentMaterialSourceData; + if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentMaterialSourcePath, parentMaterialSourceData)) + { + return Failure(); + } + + // Make sure the parent material has the same material type + auto materialTypeIdOutcome1 = AssetUtils::MakeAssetId(materialSourceFilePath, m_materialType, 0); + auto materialTypeIdOutcome2 = AssetUtils::MakeAssetId(parentMaterialSourcePath, parentMaterialSourceData.m_materialType, 0); + if (!materialTypeIdOutcome1.IsSuccess() || !materialTypeIdOutcome2.IsSuccess() || + materialTypeIdOutcome1.GetValue() != materialTypeIdOutcome2.GetValue()) + { + AZ_Error("MaterialSourceData", false, "This material and its parent material do not share the same material type."); + return Failure(); + } + + parentMaterialPath = parentMaterialSourceData.m_parentMaterial; + parentMaterialSourcePath = AssetUtils::ResolvePathReference(parentMaterialSourcePath, parentMaterialPath); + parentMaterialSourceDataVec.push_back(parentMaterialSourceData); + } + + AZStd::reverse(parentMaterialSourceDataVec.begin(), parentMaterialSourceDataVec.end()); + for (const auto& parentMaterialSourceData : parentMaterialSourceDataVec) + { + ApplyMaterialSourceDataPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath, parentMaterialSourceData); + } + + ApplyMaterialSourceDataPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath, *this); + + Data::Asset material; + if (materialAssetCreator.End(material)) + { + return Success(material); + } + else + { + return Failure(); + } + } + + void MaterialSourceData::ApplyMaterialSourceDataPropertiesToAssetCreator( + AZ::RPI::MaterialAssetCreator& materialAssetCreator, + const AZStd::string_view& materialSourceFilePath, + const MaterialSourceData& materialSourceData) + { + for (auto& group : materialSourceData.m_properties) + { + for (auto& property : group.second) + { + MaterialPropertyId propertyId{ group.first, property.first }; + if (!property.second.m_value.IsValid()) + { + AZ_Warning("Material source data", false, "Source data for material property value is invalid."); + } + else + { + MaterialPropertyIndex propertyIndex = + materialAssetCreator.m_materialPropertiesLayout->FindPropertyIndex(propertyId.GetFullName()); + if (propertyIndex.IsValid()) + { + const MaterialPropertyDescriptor* propertyDescriptor = + materialAssetCreator.m_materialPropertiesLayout->GetPropertyDescriptor(propertyIndex); + switch (propertyDescriptor->GetDataType()) + { + case MaterialPropertyDataType::Image: + { + Outcome> imageAssetResult = MaterialUtils::GetImageAssetReference( + materialSourceFilePath, property.second.m_value.GetValue()); + + if (imageAssetResult.IsSuccess()) + { + auto& imageAsset = imageAssetResult.GetValue(); + // Load referenced images when load material + imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); + materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); + } + else + { + materialAssetCreator.ReportError( + "Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), + property.second.m_value.GetValue().data()); + } + } + break; + case MaterialPropertyDataType::Enum: + { + AZ::Name enumName = AZ::Name(property.second.m_value.GetValue()); + uint32_t enumValue = propertyDescriptor->GetEnumValue(enumName); + if (enumValue == MaterialPropertyDescriptor::InvalidEnumValue) + { + materialAssetCreator.ReportError( + "Enum value '%s' couldn't be found in the 'enumValues' list", enumName.GetCStr()); + } + else + { + materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), enumValue); + } + } + break; + default: + materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), property.second.m_value); + break; + } + } + else + { + materialAssetCreator.ReportWarning( + "Can not find property id '%s' in MaterialPropertyLayout", propertyId.GetFullName().GetStringView().data()); + } + } + } + } + } + } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp index 46086dfecc..c81cf31d09 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp @@ -43,6 +43,7 @@ namespace AZ return false; } + m_asset->PostLoadInit(); m_asset->SetReady(); m_materialShaderResourceGroupLayout = nullptr; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 98af749261..1dcef43577 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -722,7 +722,7 @@ namespace MaterialEditor // we can create the asset dynamically from the source data. // Long term, the material document should not be concerned with assets at all. The viewport window should be the // only thing concerned with assets or instances. - auto createResult = m_materialSourceData.CreateMaterialAsset(Uuid::CreateRandom(), m_absolutePath, true); + auto createResult = m_materialSourceData.CreateMaterialAssetFromSourceData(Uuid::CreateRandom(), m_absolutePath, true); if (!createResult) { AZ_Error("MaterialDocument", false, "Material asset could not be created from source data: '%s'.", m_absolutePath.c_str()); From 30120b962607bba2698400d73b27036f3e5bfc63 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 22 Oct 2021 01:30:12 -0500 Subject: [PATCH 02/97] cleanup and setting asset preload flags Signed-off-by: Guthrie Adams --- .../RPI.Edit/Material/MaterialSourceData.h | 6 +-- .../RPI.Edit/Material/MaterialSourceData.cpp | 38 +++++++++---------- .../Material/MaterialTypeSourceData.cpp | 29 ++++++++------ 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h index 739c4341a9..17dc4556fb 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h @@ -102,10 +102,8 @@ namespace AZ bool includeMaterialPropertyNames = true) const; private: - static void ApplyMaterialSourceDataPropertiesToAssetCreator( - AZ::RPI::MaterialAssetCreator& materialAssetCreator, - const AZStd::string_view& materialSourceFilePath, - const MaterialSourceData& materialSourceData); + void ApplyPropertiesToAssetCreator( + AZ::RPI::MaterialAssetCreator& materialAssetCreator, const AZStd::string_view& materialSourceFilePath) const; }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 2a76befdf4..877e12ab2e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -174,7 +174,7 @@ namespace AZ materialAssetCreator.Begin(assetId, *parentMaterialAsset.GetValue().Get(), includeMaterialPropertyNames); } - ApplyMaterialSourceDataPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath, *this); + ApplyPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath); Data::Asset material; if (materialAssetCreator.End(material)) @@ -211,21 +211,21 @@ namespace AZ materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); - AZStd::vector parentMaterialSourceDataVec; + AZStd::vector parentSourceDataStack; - AZStd::string parentMaterialPath = m_parentMaterial; - AZStd::string parentMaterialSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, parentMaterialPath); - while (!parentMaterialPath.empty()) + AZStd::string parentSourceRelPath = m_parentMaterial; + AZStd::string parentSourceAbsPath = AssetUtils::ResolvePathReference(materialSourceFilePath, parentSourceRelPath); + while (!parentSourceRelPath.empty()) { - MaterialSourceData parentMaterialSourceData; - if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentMaterialSourcePath, parentMaterialSourceData)) + MaterialSourceData parentSourceData; + if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentSourceAbsPath, parentSourceData)) { return Failure(); } // Make sure the parent material has the same material type auto materialTypeIdOutcome1 = AssetUtils::MakeAssetId(materialSourceFilePath, m_materialType, 0); - auto materialTypeIdOutcome2 = AssetUtils::MakeAssetId(parentMaterialSourcePath, parentMaterialSourceData.m_materialType, 0); + auto materialTypeIdOutcome2 = AssetUtils::MakeAssetId(parentSourceAbsPath, parentSourceData.m_materialType, 0); if (!materialTypeIdOutcome1.IsSuccess() || !materialTypeIdOutcome2.IsSuccess() || materialTypeIdOutcome1.GetValue() != materialTypeIdOutcome2.GetValue()) { @@ -233,18 +233,18 @@ namespace AZ return Failure(); } - parentMaterialPath = parentMaterialSourceData.m_parentMaterial; - parentMaterialSourcePath = AssetUtils::ResolvePathReference(parentMaterialSourcePath, parentMaterialPath); - parentMaterialSourceDataVec.push_back(parentMaterialSourceData); + parentSourceDataStack.push_back(parentSourceData); + parentSourceRelPath = parentSourceData.m_parentMaterial; + parentSourceAbsPath = AssetUtils::ResolvePathReference(parentSourceAbsPath, parentSourceRelPath); } - AZStd::reverse(parentMaterialSourceDataVec.begin(), parentMaterialSourceDataVec.end()); - for (const auto& parentMaterialSourceData : parentMaterialSourceDataVec) + while (!parentSourceDataStack.empty()) { - ApplyMaterialSourceDataPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath, parentMaterialSourceData); + parentSourceDataStack.back().ApplyPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath); + parentSourceDataStack.pop_back(); } - ApplyMaterialSourceDataPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath, *this); + ApplyPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath); Data::Asset material; if (materialAssetCreator.End(material)) @@ -257,12 +257,10 @@ namespace AZ } } - void MaterialSourceData::ApplyMaterialSourceDataPropertiesToAssetCreator( - AZ::RPI::MaterialAssetCreator& materialAssetCreator, - const AZStd::string_view& materialSourceFilePath, - const MaterialSourceData& materialSourceData) + void MaterialSourceData::ApplyPropertiesToAssetCreator( + AZ::RPI::MaterialAssetCreator& materialAssetCreator, const AZStd::string_view& materialSourceFilePath) const { - for (auto& group : materialSourceData.m_properties) + for (auto& group : m_properties) { for (auto& property : group.second) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp index 08f57c7cd3..b20873141b 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp @@ -393,11 +393,14 @@ namespace AZ for (const ShaderVariantReferenceData& shaderRef : m_shaderCollection) { const auto& shaderFile = shaderRef.m_shaderFilePath; - const auto& shaderAsset = AssetUtils::LoadAsset(materialTypeSourceFilePath, shaderFile, 0); + auto shaderAssetResult = AssetUtils::LoadAsset(materialTypeSourceFilePath, shaderFile, 0); - if (shaderAsset) + if (shaderAssetResult) { - auto optionsLayout = shaderAsset.GetValue()->GetShaderOptionGroupLayout(); + auto shaderAsset = shaderAssetResult.GetValue(); + shaderAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); + + auto optionsLayout = shaderAsset->GetShaderOptionGroupLayout(); ShaderOptionGroup options{ optionsLayout }; for (auto& iter : shaderRef.m_shaderOptionValues) { @@ -408,12 +411,11 @@ namespace AZ } materialTypeAssetCreator.AddShader( - shaderAsset.GetValue(), options.GetShaderVariantId(), - shaderRef.m_shaderTag.IsEmpty() ? Uuid::CreateRandom().ToString() : shaderRef.m_shaderTag - ); + shaderAsset, options.GetShaderVariantId(), + shaderRef.m_shaderTag.IsEmpty() ? Uuid::CreateRandom().ToString() : shaderRef.m_shaderTag); // Gather UV names - const ShaderInputContract& shaderInputContract = shaderAsset.GetValue()->GetInputContract(); + const ShaderInputContract& shaderInputContract = shaderAsset->GetInputContract(); for (const ShaderInputContract::StreamChannelInfo& channel : shaderInputContract.m_streamChannels) { const RHI::ShaderSemantic& semantic = channel.m_semantic; @@ -493,15 +495,20 @@ namespace AZ { case MaterialPropertyDataType::Image: { - Outcome> imageAssetResult = MaterialUtils::GetImageAssetReference(materialTypeSourceFilePath, property.m_value.GetValue()); + auto imageAssetResult = MaterialUtils::GetImageAssetReference( + materialTypeSourceFilePath, property.m_value.GetValue()); - if (imageAssetResult.IsSuccess()) + if (imageAssetResult) { - materialTypeAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAssetResult.GetValue()); + auto imageAsset = imageAssetResult.GetValue(); + imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); + materialTypeAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); } else { - materialTypeAssetCreator.ReportError("Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), property.m_value.GetValue().data()); + materialTypeAssetCreator.ReportError( + "Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), + property.m_value.GetValue().data()); } } break; From 0724403f9014708c9e34fa7382cc4fcf10c82e76 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 25 Oct 2021 12:35:19 -0500 Subject: [PATCH 03/97] adding ifdef to compare loading vs creating material type assets Signed-off-by: Guthrie Adams --- .../Code/Source/RPI.Edit/Material/MaterialSourceData.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 877e12ab2e..f1a41d0548 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -193,6 +193,7 @@ namespace AZ MaterialAssetCreator materialAssetCreator; materialAssetCreator.SetElevateWarnings(elevateWarnings); +#if 0 MaterialTypeSourceData materialTypeSourceData; AZStd::string materialTypeSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, m_materialType); if (!AZ::RPI::JsonUtils::LoadObjectFromFile(materialTypeSourcePath, materialTypeSourceData)) @@ -208,6 +209,13 @@ namespace AZ { return Failure(); } +#else + auto materialTypeAsset = AssetUtils::LoadAsset(materialSourceFilePath, m_materialType); + if (!materialTypeAsset.IsSuccess()) + { + return Failure(); + } +#endif materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); From e632dc3b3982900770bd120cfa1238e1543489dd Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 26 Oct 2021 12:24:37 -0500 Subject: [PATCH 04/97] Moving material type asset PostInit call to be consistent with material asset Signed-off-by: Guthrie Adams --- .../Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp | 4 ++++ .../Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp index 76634201eb..48654d7769 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp @@ -188,6 +188,10 @@ namespace AZ void MaterialTypeAsset::SetReady() { m_status = AssetStatus::Ready; + + // If this was created dynamically using MaterialTypeAssetCreator (which is what calls SetReady()), + // we need to connect to the AssetBus for reloads. + PostLoadInit(); } bool MaterialTypeAsset::PostLoadInit() diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp index c81cf31d09..46086dfecc 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp @@ -43,7 +43,6 @@ namespace AZ return false; } - m_asset->PostLoadInit(); m_asset->SetReady(); m_materialShaderResourceGroupLayout = nullptr; From 48f3bb7d7a354c9b7340c69d7698e85fd9ada063 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Wed, 3 Nov 2021 23:56:59 -0700 Subject: [PATCH 05/97] Fixed missing initialization of ShaderCollection::Item::m_renderStatesOverlay. This RenderStates is used to override the values in the final draw packet, if the values are valid; it's supposed to be initialized to invalid values, but it wasn't. So the depth compare function was getting set to Less instead of GreaterEqual. This wasn't a problem when using serialized assets from disk, because the deserialization uses the default constructor which did initialize m_renderStatesOverlay. No all Item constructors initialize m_renderStatesOverlay. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> Signed-off-by: Guthrie Adams --- .../Code/Source/RPI.Edit/Material/MaterialSourceData.cpp | 2 +- .../Code/Source/RPI.Reflect/Material/ShaderCollection.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index f1a41d0548..7ff33b2d04 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -193,7 +193,7 @@ namespace AZ MaterialAssetCreator materialAssetCreator; materialAssetCreator.SetElevateWarnings(elevateWarnings); -#if 0 +#if 1 MaterialTypeSourceData materialTypeSourceData; AZStd::string materialTypeSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, m_materialType); if (!AZ::RPI::JsonUtils::LoadObjectFromFile(materialTypeSourcePath, materialTypeSourceData)) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp index 87076891dd..16813cb6b7 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp @@ -126,8 +126,8 @@ namespace AZ } ShaderCollection::Item::Item() + : m_renderStatesOverlay(RHI::GetInvalidRenderStates()) { - m_renderStatesOverlay = RHI::GetInvalidRenderStates(); } ShaderCollection::Item& ShaderCollection::operator[](size_t i) @@ -156,7 +156,8 @@ namespace AZ } ShaderCollection::Item::Item(const Data::Asset& shaderAsset, const AZ::Name& shaderTag, ShaderVariantId variantId) - : m_shaderAsset(shaderAsset) + : m_renderStatesOverlay(RHI::GetInvalidRenderStates()) + , m_shaderAsset(shaderAsset) , m_shaderVariantId(variantId) , m_shaderTag(shaderTag) , m_shaderOptionGroup(shaderAsset->GetShaderOptionGroupLayout(), variantId) @@ -164,7 +165,8 @@ namespace AZ } ShaderCollection::Item::Item(Data::Asset&& shaderAsset, const AZ::Name& shaderTag, ShaderVariantId variantId) - : m_shaderAsset(AZStd::move(shaderAsset)) + : m_renderStatesOverlay(RHI::GetInvalidRenderStates()) + , m_shaderAsset(AZStd::move(shaderAsset)) , m_shaderVariantId(variantId) , m_shaderTag(shaderTag) , m_shaderOptionGroup(shaderAsset->GetShaderOptionGroupLayout(), variantId) From c0acbe7bd4cc17f1519efa9dee5a117c091d6be1 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 4 Nov 2021 12:27:18 -0500 Subject: [PATCH 06/97] =?UTF-8?q?Changed=20how=20asset=20creator=20generat?= =?UTF-8?q?es=20the=20asset=20instance.=20Instead=20of=20finding=20or=20cr?= =?UTF-8?q?eating=20the=20asset=20in=20the=20asset=20manager,=20one=20is?= =?UTF-8?q?=20directly=20instantiated=20and=20only=20added=20to=20the=20as?= =?UTF-8?q?set=20manager=20after=20creation=20is=20complete.=20This=20allo?= =?UTF-8?q?ws=20for=20reuse=20of=20previously=20loaded=20asset=20ids=20and?= =?UTF-8?q?=20will=20replace=20or=20=E2=80=9Creload=E2=80=9D=20a=20pre-exi?= =?UTF-8?q?sting=20asset=20with=20the=20newly=20created=20one.=20This=20al?= =?UTF-8?q?so=20sends=20although=20correct=20notifications.=20Changed=20ma?= =?UTF-8?q?terial=20document=20to=20load=20a=20source=20data=20are=20for?= =?UTF-8?q?=20the=20parent=20material=20as=20well.=20=20It=20was=20also=20?= =?UTF-8?q?a=20previously=20loading=20the=20parent=20material=20products?= =?UTF-8?q?=20asset=20which=20would=20be=20out=20of=20date=20compared=20to?= =?UTF-8?q?=20the=20source=20data.=20Changed=20material=20document=20to=20?= =?UTF-8?q?track=20source=20file=20dependency=20changes=20instead=20of=20p?= =?UTF-8?q?roduct=20asset=20changes.=20Fixed=20a=20bug=20or=20copy=20paste?= =?UTF-8?q?=20error=20in=20the=20document=20manager=20that=20was=20using?= =?UTF-8?q?=20the=20same=20container=20to=20track=20documents=20the=20modi?= =?UTF-8?q?fied=20externally=20and=20from=20other=20dependency=20changes.?= =?UTF-8?q?=20Returning=20source=20data=20dependencies=20when=20creating?= =?UTF-8?q?=20a=20material=20asset=20from=20source.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Guthrie Adams --- .../RPI.Edit/Material/MaterialSourceData.h | 3 +- .../Include/Atom/RPI.Reflect/AssetCreator.h | 3 +- .../RPI.Edit/Material/MaterialSourceData.cpp | 61 +++++++++++------- .../Material/MaterialTypeSourceData.cpp | 3 - .../AtomToolsDocumentSystemComponent.cpp | 14 +++-- .../AtomToolsDocumentSystemComponent.h | 4 +- .../Code/Source/Document/MaterialDocument.cpp | 63 ++++++++++--------- .../Code/Source/Document/MaterialDocument.h | 11 +--- 8 files changed, 86 insertions(+), 76 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h index 17dc4556fb..77bf45023d 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h @@ -99,7 +99,8 @@ namespace AZ Data::AssetId assetId, AZStd::string_view materialSourceFilePath = "", bool elevateWarnings = true, - bool includeMaterialPropertyNames = true) const; + bool includeMaterialPropertyNames = true, + AZStd::unordered_set* sourceDependencies = nullptr) const; private: void ApplyPropertiesToAssetCreator( diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h index abdbe9cdce..79d43d0b8d 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h @@ -118,7 +118,7 @@ namespace AZ ResetIssueCounts(); // Because the asset creator can be used multiple times - m_asset = Data::AssetManager::Instance().CreateAsset(assetId, AZ::Data::AssetLoadBehavior::PreLoad); + m_asset = Data::Asset(assetId, aznew AssetDataT, AZ::Data::AssetLoadBehavior::PreLoad); m_beginCalled = true; if (!m_asset) @@ -138,6 +138,7 @@ namespace AZ } else { + Data::AssetManager::Instance().AssignAssetData(m_asset); result = AZStd::move(m_asset); success = true; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 7ff33b2d04..c912826026 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -188,14 +188,20 @@ namespace AZ } Outcome> MaterialSourceData::CreateMaterialAssetFromSourceData( - Data::AssetId assetId, AZStd::string_view materialSourceFilePath, bool elevateWarnings, bool includeMaterialPropertyNames) const + Data::AssetId assetId, + AZStd::string_view materialSourceFilePath, + bool elevateWarnings, + bool includeMaterialPropertyNames, + AZStd::unordered_set* sourceDependencies) const { - MaterialAssetCreator materialAssetCreator; - materialAssetCreator.SetElevateWarnings(elevateWarnings); + const auto materialTypeSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, m_materialType); + const auto materialTypeAssetId = AssetUtils::MakeAssetId(materialTypeSourcePath, 0); + if (!materialTypeAssetId.IsSuccess()) + { + return Failure(); + } -#if 1 MaterialTypeSourceData materialTypeSourceData; - AZStd::string materialTypeSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, m_materialType); if (!AZ::RPI::JsonUtils::LoadObjectFromFile(materialTypeSourcePath, materialTypeSourceData)) { return Failure(); @@ -203,21 +209,16 @@ namespace AZ materialTypeSourceData.ResolveUvEnums(); - auto materialTypeAsset = - materialTypeSourceData.CreateMaterialTypeAsset(AZ::Uuid::CreateRandom(), materialTypeSourcePath, elevateWarnings); + const auto materialTypeAsset = + materialTypeSourceData.CreateMaterialTypeAsset(materialTypeAssetId.GetValue(), materialTypeSourcePath, elevateWarnings); if (!materialTypeAsset.IsSuccess()) { return Failure(); } -#else - auto materialTypeAsset = AssetUtils::LoadAsset(materialSourceFilePath, m_materialType); - if (!materialTypeAsset.IsSuccess()) - { - return Failure(); - } -#endif - materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); + AZStd::unordered_set dependencies; + dependencies.insert(materialSourceFilePath); + dependencies.insert(materialTypeSourcePath); AZStd::vector parentSourceDataStack; @@ -225,6 +226,13 @@ namespace AZ AZStd::string parentSourceAbsPath = AssetUtils::ResolvePathReference(materialSourceFilePath, parentSourceRelPath); while (!parentSourceRelPath.empty()) { + if (dependencies.find(parentSourceAbsPath) != dependencies.end()) + { + return Failure(); + } + + dependencies.insert(parentSourceAbsPath); + MaterialSourceData parentSourceData; if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentSourceAbsPath, parentSourceData)) { @@ -232,20 +240,22 @@ namespace AZ } // Make sure the parent material has the same material type - auto materialTypeIdOutcome1 = AssetUtils::MakeAssetId(materialSourceFilePath, m_materialType, 0); - auto materialTypeIdOutcome2 = AssetUtils::MakeAssetId(parentSourceAbsPath, parentSourceData.m_materialType, 0); - if (!materialTypeIdOutcome1.IsSuccess() || !materialTypeIdOutcome2.IsSuccess() || - materialTypeIdOutcome1.GetValue() != materialTypeIdOutcome2.GetValue()) + const auto parentTypeAssetId = AssetUtils::MakeAssetId(parentSourceAbsPath, parentSourceData.m_materialType, 0); + if (!parentTypeAssetId || parentTypeAssetId.GetValue() != materialTypeAssetId.GetValue()) { AZ_Error("MaterialSourceData", false, "This material and its parent material do not share the same material type."); return Failure(); } - parentSourceDataStack.push_back(parentSourceData); parentSourceRelPath = parentSourceData.m_parentMaterial; parentSourceAbsPath = AssetUtils::ResolvePathReference(parentSourceAbsPath, parentSourceRelPath); + parentSourceDataStack.emplace_back(AZStd::move(parentSourceData)); } + MaterialAssetCreator materialAssetCreator; + materialAssetCreator.SetElevateWarnings(elevateWarnings); + materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); + while (!parentSourceDataStack.empty()) { parentSourceDataStack.back().ApplyPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath); @@ -257,12 +267,15 @@ namespace AZ Data::Asset material; if (materialAssetCreator.End(material)) { + if (sourceDependencies) + { + sourceDependencies->insert(dependencies.begin(), dependencies.end()); + } + return Success(material); } - else - { - return Failure(); - } + + return Failure(); } void MaterialSourceData::ApplyPropertiesToAssetCreator( diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp index b20873141b..396ba71e14 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp @@ -398,8 +398,6 @@ namespace AZ if (shaderAssetResult) { auto shaderAsset = shaderAssetResult.GetValue(); - shaderAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); - auto optionsLayout = shaderAsset->GetShaderOptionGroupLayout(); ShaderOptionGroup options{ optionsLayout }; for (auto& iter : shaderRef.m_shaderOptionValues) @@ -501,7 +499,6 @@ namespace AZ if (imageAssetResult) { auto imageAsset = imageAssetResult.GetValue(); - imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); materialTypeAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); } else diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp index 5652e9fe23..00de2a7c4c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp @@ -159,7 +159,7 @@ namespace AtomToolsFramework void AtomToolsDocumentSystemComponent::OnDocumentExternallyModified(const AZ::Uuid& documentId) { - m_documentIdsToReopen.insert(documentId); + m_documentIdsWithExternalChanges.insert(documentId); if (!AZ::TickBus::Handler::BusIsConnected()) { AZ::TickBus::Handler::BusConnect(); @@ -168,7 +168,7 @@ namespace AtomToolsFramework void AtomToolsDocumentSystemComponent::OnDocumentDependencyModified(const AZ::Uuid& documentId) { - m_documentIdsToReopen.insert(documentId); + m_documentIdsWithDependencyChanges.insert(documentId); if (!AZ::TickBus::Handler::BusIsConnected()) { AZ::TickBus::Handler::BusConnect(); @@ -177,7 +177,7 @@ namespace AtomToolsFramework void AtomToolsDocumentSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) { - for (const AZ::Uuid& documentId : m_documentIdsToReopen) + for (const AZ::Uuid& documentId : m_documentIdsWithExternalChanges) { AZStd::string documentPath; AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); @@ -191,6 +191,8 @@ namespace AtomToolsFramework continue; } + m_documentIdsWithDependencyChanges.erase(documentId); + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool openResult = false; @@ -204,7 +206,7 @@ namespace AtomToolsFramework } } - for (const AZ::Uuid& documentId : m_documentIdsToReopen) + for (const AZ::Uuid& documentId : m_documentIdsWithDependencyChanges) { AZStd::string documentPath; AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); @@ -231,8 +233,8 @@ namespace AtomToolsFramework } } - m_documentIdsToReopen.clear(); - m_documentIdsToReopen.clear(); + m_documentIdsWithDependencyChanges.clear(); + m_documentIdsWithExternalChanges.clear(); AZ::TickBus::Handler::BusDisconnect(); } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h index 9c556a07e7..a0f5eb085d 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h @@ -85,8 +85,8 @@ namespace AtomToolsFramework AZStd::intrusive_ptr m_settings; AZStd::function m_documentCreator; AZStd::unordered_map> m_documentMap; - AZStd::unordered_set m_documentIdsToRebuild; - AZStd::unordered_set m_documentIdsToReopen; + AZStd::unordered_set m_documentIdsWithExternalChanges; + AZStd::unordered_set m_documentIdsWithDependencyChanges; const size_t m_maxMessageBoxLineCount = 15; }; } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 1dcef43577..049d4c47ff 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -567,26 +567,26 @@ namespace MaterialEditor } } - void MaterialDocument::SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid sourceUUID) + void MaterialDocument::SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, [[maybe_unused]] AZ::Uuid sourceUUID) { - if (m_sourceAssetId.m_guid == sourceUUID) + auto sourcePath = AZ::RPI::AssetUtils::ResolvePathReference(scanFolder, relativePath); + + if (m_absolutePath == sourcePath) { // ignore notifications caused by saving the open document if (!m_saveTriggeredInternally) { AZ_TracePrintf("MaterialDocument", "Material document changed externally: '%s'.\n", m_absolutePath.c_str()); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id); } m_saveTriggeredInternally = false; } - } - - void MaterialDocument::OnAssetReloaded(AZ::Data::Asset asset) - { - if (m_dependentAssetIds.find(asset->GetId()) != m_dependentAssetIds.end()) + else if (m_sourceDependencies.find(sourcePath) != m_sourceDependencies.end()) { AZ_TracePrintf("MaterialDocument", "Material document dependency changed: '%s'.\n", m_absolutePath.c_str()); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id); } } @@ -655,7 +655,6 @@ namespace MaterialEditor return false; } - m_sourceAssetId = sourceAssetInfo.m_assetId; m_relativePath = sourceAssetInfo.m_relativePath; if (!AzFramework::StringFunc::Path::Normalize(m_relativePath)) { @@ -722,14 +721,15 @@ namespace MaterialEditor // we can create the asset dynamically from the source data. // Long term, the material document should not be concerned with assets at all. The viewport window should be the // only thing concerned with assets or instances. - auto createResult = m_materialSourceData.CreateMaterialAssetFromSourceData(Uuid::CreateRandom(), m_absolutePath, true); - if (!createResult) + auto materialAssetResult = + m_materialSourceData.CreateMaterialAssetFromSourceData(Uuid::CreateRandom(), m_absolutePath, true, true, &m_sourceDependencies); + if (!materialAssetResult) { AZ_Error("MaterialDocument", false, "Material asset could not be created from source data: '%s'.", m_absolutePath.c_str()); return false; } - m_materialAsset = createResult.GetValue(); + m_materialAsset = materialAssetResult.GetValue(); if (!m_materialAsset.IsReady()) { AZ_Error("MaterialDocument", false, "Material asset is not ready: '%s'.", m_absolutePath.c_str()); @@ -743,28 +743,35 @@ namespace MaterialEditor return false; } - // track material type asset to notify when dependencies change - m_dependentAssetIds.insert(materialTypeAsset->GetId()); - AZ::Data::AssetBus::MultiHandler::BusConnect(materialTypeAsset->GetId()); - AZStd::array_view parentPropertyValues = materialTypeAsset->GetDefaultPropertyValues(); AZ::Data::Asset parentMaterialAsset; if (!m_materialSourceData.m_parentMaterial.empty()) { - // There is a parent for this material - auto parentMaterialResult = AssetUtils::LoadAsset(m_absolutePath, m_materialSourceData.m_parentMaterial); - if (!parentMaterialResult) + AZ::RPI::MaterialSourceData parentMaterialSourceData; + const auto parentMaterialFilePath = AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_parentMaterial); + if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentMaterialFilePath, parentMaterialSourceData)) { - AZ_Error("MaterialDocument", false, "Parent material asset could not be loaded: '%s'.", m_materialSourceData.m_parentMaterial.c_str()); + AZ_Error("MaterialDocument", false, "Material parent source data could not be loaded for: '%s'.", parentMaterialFilePath.c_str()); return false; } - parentMaterialAsset = parentMaterialResult.GetValue(); - parentPropertyValues = parentMaterialAsset->GetPropertyValues(); + const auto parentMaterialAssetIdResult = AssetUtils::MakeAssetId(parentMaterialFilePath, 0); + if (!parentMaterialAssetIdResult) + { + AZ_Error("MaterialDocument", false, "Material parent asset ID could not be created: '%s'.", parentMaterialFilePath.c_str()); + return false; + } - // track parent material asset to notify when dependencies change - m_dependentAssetIds.insert(parentMaterialAsset->GetId()); - AZ::Data::AssetBus::MultiHandler::BusConnect(parentMaterialAsset->GetId()); + auto parentMaterialAssetResult = m_materialSourceData.CreateMaterialAssetFromSourceData( + parentMaterialAssetIdResult.GetValue(), parentMaterialFilePath, true, true, &m_sourceDependencies); + if (!parentMaterialAssetResult) + { + AZ_Error("MaterialDocument", false, "Material parent asset could not be created from source data: '%s'.", parentMaterialFilePath.c_str()); + return false; + } + + parentMaterialAsset = parentMaterialAssetResult.GetValue(); + parentPropertyValues = parentMaterialAsset->GetPropertyValues(); } // Creating a material from a material asset will fail if a texture is referenced but not loaded @@ -913,15 +920,13 @@ namespace MaterialEditor void MaterialDocument::Clear() { AZ::TickBus::Handler::BusDisconnect(); - AZ::Data::AssetBus::MultiHandler::BusDisconnect(); AzToolsFramework::AssetSystemBus::Handler::BusDisconnect(); m_materialAsset = {}; m_materialInstance = {}; m_absolutePath.clear(); m_relativePath.clear(); - m_sourceAssetId = {}; - m_dependentAssetIds.clear(); + m_sourceDependencies.clear(); m_saveTriggeredInternally = {}; m_compilePending = {}; m_properties.clear(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h index 03997a2a91..452111f99a 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h @@ -29,7 +29,6 @@ namespace MaterialEditor : public AtomToolsFramework::AtomToolsDocument , public MaterialDocumentRequestBus::Handler , private AZ::TickBus::Handler - , private AZ::Data::AssetBus::MultiHandler , private AzToolsFramework::AssetSystemBus::Handler { public: @@ -105,11 +104,6 @@ namespace MaterialEditor void SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid sourceUUID) override; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AZ::Data::AssetBus::Router overrides... - void OnAssetReloaded(AZ::Data::Asset asset) override; - ////////////////////////////////////////////////////////////////////////// - bool SavePropertiesToSourceData(AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const; bool OpenInternal(AZStd::string_view loadPath); @@ -137,11 +131,8 @@ namespace MaterialEditor // Material instance being edited AZ::Data::Instance m_materialInstance; - // Asset used to open document - AZ::Data::AssetId m_sourceAssetId; - // Set of assets that can trigger a document reload - AZStd::unordered_set m_dependentAssetIds; + AZStd::unordered_set m_sourceDependencies; // Track if document saved itself last to skip external modification notification bool m_saveTriggeredInternally = false; From 5afd701e2389d244c3ea03c529a806b20dd95993 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 4 Nov 2021 18:20:27 -0500 Subject: [PATCH 07/97] updated comments and error messages Signed-off-by: Guthrie Adams --- .../RPI.Edit/Material/MaterialSourceData.h | 1 + .../RPI.Edit/Material/MaterialSourceData.cpp | 25 +++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h index 77bf45023d..53d3072370 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h @@ -95,6 +95,7 @@ namespace AZ //! resolving file-relative paths. //! @param elevateWarnings Indicates whether to treat warnings as errors //! @param includeMaterialPropertyNames Indicates whether to save material property names into the material asset file + //! @param sourceDependencies if not null, will be populated with a set of all of the loaded material and material type paths Outcome> CreateMaterialAssetFromSourceData( Data::AssetId assetId, AZStd::string_view materialSourceFilePath = "", diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index c912826026..7c37d894d4 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -198,12 +198,14 @@ namespace AZ const auto materialTypeAssetId = AssetUtils::MakeAssetId(materialTypeSourcePath, 0); if (!materialTypeAssetId.IsSuccess()) { + AZ_Error("MaterialSourceData", false, "Failed to create material type asset ID: '%s'.", materialTypeSourcePath.c_str()); return Failure(); } MaterialTypeSourceData materialTypeSourceData; if (!AZ::RPI::JsonUtils::LoadObjectFromFile(materialTypeSourcePath, materialTypeSourceData)) { + AZ_Error("MaterialSourceData", false, "Failed to load MaterialTypeSourceData: '%s'.", materialTypeSourcePath.c_str()); return Failure(); } @@ -213,45 +215,58 @@ namespace AZ materialTypeSourceData.CreateMaterialTypeAsset(materialTypeAssetId.GetValue(), materialTypeSourcePath, elevateWarnings); if (!materialTypeAsset.IsSuccess()) { + AZ_Error("MaterialSourceData", false, "Failed to create material type asset from source data: '%s'.", materialTypeSourcePath.c_str()); return Failure(); } + // Track all of the material and material type assets loaded while trying to create a material asset from source data. This will + // be used for evaluating circular dependencies and returned for external monitoring or other use. AZStd::unordered_set dependencies; dependencies.insert(materialSourceFilePath); dependencies.insert(materialTypeSourcePath); + // Load and build a stack of MaterialSourceData from all of the parent materials in the hierarchy. Properties from the source + // data will be applied in reverse to the asset creator. AZStd::vector parentSourceDataStack; AZStd::string parentSourceRelPath = m_parentMaterial; AZStd::string parentSourceAbsPath = AssetUtils::ResolvePathReference(materialSourceFilePath, parentSourceRelPath); while (!parentSourceRelPath.empty()) { - if (dependencies.find(parentSourceAbsPath) != dependencies.end()) + if (!dependencies.insert(parentSourceAbsPath).second) { + AZ_Error("MaterialSourceData", false, "Detected circular dependency between materials: '%s' and '%s'.", materialSourceFilePath, parentSourceAbsPath.c_str()); return Failure(); } - dependencies.insert(parentSourceAbsPath); - MaterialSourceData parentSourceData; if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentSourceAbsPath, parentSourceData)) { + AZ_Error("MaterialSourceData", false, "Failed to load MaterialSourceData for parent material: '%s'.", parentSourceAbsPath.c_str()); return Failure(); } - // Make sure the parent material has the same material type + // Make sure that all materials in the hierarchy share the same material type const auto parentTypeAssetId = AssetUtils::MakeAssetId(parentSourceAbsPath, parentSourceData.m_materialType, 0); - if (!parentTypeAssetId || parentTypeAssetId.GetValue() != materialTypeAssetId.GetValue()) + if (!parentTypeAssetId) + { + AZ_Error("MaterialSourceData", false, "Parent material asset ID isn't valid: '%s'.", parentSourceAbsPath.c_str()); + return Failure(); + } + + if (parentTypeAssetId.GetValue() != materialTypeAssetId.GetValue()) { AZ_Error("MaterialSourceData", false, "This material and its parent material do not share the same material type."); return Failure(); } + // Get the location of the next parent material and push the source data onto the stack parentSourceRelPath = parentSourceData.m_parentMaterial; parentSourceAbsPath = AssetUtils::ResolvePathReference(parentSourceAbsPath, parentSourceRelPath); parentSourceDataStack.emplace_back(AZStd::move(parentSourceData)); } + // Create the material asset from all the previously loaded source data MaterialAssetCreator materialAssetCreator; materialAssetCreator.SetElevateWarnings(elevateWarnings); materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); From 791d11c8f96cd500164688e5df225148167ead93 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 5 Nov 2021 22:06:31 -0500 Subject: [PATCH 08/97] Fix parent material loading Signed-off-by: Guthrie Adams --- .../RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp | 2 +- .../MaterialEditor/Code/Source/Document/MaterialDocument.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 7c37d894d4..e5466a173f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -235,7 +235,7 @@ namespace AZ { if (!dependencies.insert(parentSourceAbsPath).second) { - AZ_Error("MaterialSourceData", false, "Detected circular dependency between materials: '%s' and '%s'.", materialSourceFilePath, parentSourceAbsPath.c_str()); + AZ_Error("MaterialSourceData", false, "Detected circular dependency between materials: '%s' and '%s'.", materialSourceFilePath.data(), parentSourceAbsPath.c_str()); return Failure(); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 049d4c47ff..ee58cbea3e 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -762,8 +762,8 @@ namespace MaterialEditor return false; } - auto parentMaterialAssetResult = m_materialSourceData.CreateMaterialAssetFromSourceData( - parentMaterialAssetIdResult.GetValue(), parentMaterialFilePath, true, true, &m_sourceDependencies); + auto parentMaterialAssetResult = parentMaterialSourceData.CreateMaterialAssetFromSourceData( + parentMaterialAssetIdResult.GetValue(), parentMaterialFilePath, true, true); if (!parentMaterialAssetResult) { AZ_Error("MaterialDocument", false, "Material parent asset could not be created from source data: '%s'.", parentMaterialFilePath.c_str()); From c372761f4e348bf63f7f7b6b0ee930f177bfd2da Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sun, 7 Nov 2021 15:04:46 -0600 Subject: [PATCH 09/97] Changing lua material functor script loading code to pass the correct sub ID for a compiled script asset Signed-off-by: Guthrie Adams --- .../Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp index b230953f8c..37bd5a19f2 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp @@ -137,7 +137,7 @@ namespace AZ } else if (!m_luaSourceFile.empty()) { - auto loadOutcome = RPI::AssetUtils::LoadAsset(materialTypeSourceFilePath, m_luaSourceFile); + auto loadOutcome = RPI::AssetUtils::LoadAsset(materialTypeSourceFilePath, m_luaSourceFile, ScriptAsset::CompiledAssetSubId); if (!loadOutcome) { AZ_Error("LuaMaterialFunctorSourceData", false, "Could not load script file '%s'", m_luaSourceFile.c_str()); From d5ae98496ca8abc139c7cf30ccac04dc8cae45ae Mon Sep 17 00:00:00 2001 From: nggieber Date: Tue, 9 Nov 2021 10:26:37 -0800 Subject: [PATCH 10/97] Full UI Built for Updating and Uninstalling Gems Signed-off-by: nggieber --- .../Resources/ProjectManager.qss | 46 ++++++++++++++ .../Source/GemCatalog/GemCatalogScreen.cpp | 42 ++++++++++--- .../Source/GemCatalog/GemCatalogScreen.h | 3 + .../Source/GemCatalog/GemInfo.h | 2 +- .../Source/GemCatalog/GemInspector.cpp | 32 +++++++++- .../Source/GemCatalog/GemInspector.h | 9 ++- .../Source/GemCatalog/GemUninstallDialog.cpp | 60 +++++++++++++++++++ .../Source/GemCatalog/GemUninstallDialog.h | 25 ++++++++ .../Source/GemCatalog/GemUpdateDialog.cpp | 60 +++++++++++++++++++ .../Source/GemCatalog/GemUpdateDialog.h | 25 ++++++++ .../project_manager_files.cmake | 4 ++ 11 files changed, 297 insertions(+), 11 deletions(-) create mode 100644 Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.cpp create mode 100644 Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.h create mode 100644 Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp create mode 100644 Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.h diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qss b/Code/Tools/ProjectManager/Resources/ProjectManager.qss index d3ec066be7..426f409581 100644 --- a/Code/Tools/ProjectManager/Resources/ProjectManager.qss +++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qss @@ -563,6 +563,52 @@ QProgressBar::chunk { margin-top:5px; } +#gemCatalogUpdateGemButton, +#gemCatalogUninstallGemButton +{ + qproperty-flat: true; + min-height:24px; + max-height:24px; + border-radius: 3px; + text-align:center; + font-size:12px; + font-weight:600; +} + +#gemCatalogUpdateGemButton { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #888888, stop: 1.0 #555555); +} +#gemCatalogUpdateGemButton:hover { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #999999, stop: 1.0 #666666); +} +#gemCatalogUpdateGemButton:pressed { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #555555, stop: 1.0 #777777); +} + +#footer > #gemCatalogUninstallGemButton, +#gemCatalogUninstallGemButton { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #E32C27, stop: 1.0 #951D21); +} +#footer > #gemCatalogUninstallGemButton:hover, +#gemCatalogUninstallGemButton:hover { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #FD3129, stop: 1.0 #AF2221); +} +#footer > #gemCatalogUninstallGemButton:pressed, +#gemCatalogUninstallGemButton:pressed { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #951D1F, stop: 1.0 #C92724); +} + +#gemCatalogDialogSubTitle { + font-size:14px; + font-weight:600; +} + /************** Filter Tag widget **************/ #FilterTagWidgetTextLabel { diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 1a3dc03230..1395dce764 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -12,7 +12,10 @@ #include #include #include +#include +#include #include + #include #include #include @@ -55,6 +58,8 @@ namespace O3DE::ProjectManager m_gemInspector->setFixedWidth(240); connect(m_gemInspector, &GemInspector::TagClicked, this, &GemCatalogScreen::SelectGem); + connect(m_gemInspector, &GemInspector::UpdateGem, this, &GemCatalogScreen::UpdateGem); + connect(m_gemInspector, &GemInspector::UninstallGem, this, &GemCatalogScreen::UninstallGem); QWidget* filterWidget = new QWidget(this); filterWidget->setFixedWidth(240); @@ -104,9 +109,10 @@ namespace O3DE::ProjectManager // Select the first entry after everything got correctly sized QTimer::singleShot(200, [=]{ - QModelIndex firstModelIndex = m_gemListView->model()->index(0,0); - m_gemListView->selectionModel()->select(firstModelIndex, QItemSelectionModel::ClearAndSelect); - }); + QModelIndex firstModelIndex = m_gemModel->index(0, 0); // m_gemListView->model()->index(0,0); + //m_gemListView->selectionModel()->select(firstModelIndex, QItemSelectionModel::ClearAndSelect); + m_gemModel->GetSelectionModel()->select(firstModelIndex, QItemSelectionModel::ClearAndSelect); + }); } void GemCatalogScreen::OnAddGemClicked() @@ -170,7 +176,7 @@ namespace O3DE::ProjectManager notification = GemModel::GetDisplayName(modelIndex); if (numChangedDependencies > 0) { - notification += " " + tr("and") + " "; + notification += tr(" and "); } if (added && GemModel::GetDownloadStatus(modelIndex) == GemInfo::DownloadStatus::NotDownloaded) { @@ -178,15 +184,15 @@ namespace O3DE::ProjectManager } } - if (numChangedDependencies == 1 ) + if (numChangedDependencies == 1) { - notification += "1 Gem " + tr("dependency"); + notification += tr("1 Gem dependency"); } else if (numChangedDependencies > 1) { - notification += QString("%1 Gem ").arg(numChangedDependencies) + tr("dependencies"); + notification += tr("%1 Gem %2").arg(QString(numChangedDependencies), tr("dependencies")); } - notification += " " + (added ? tr("activated") : tr("deactivated")); + notification += (added ? tr(" activated") : tr(" deactivated")); AzQtComponents::ToastConfiguration toastConfiguration(AzQtComponents::ToastType::Custom, notification, ""); toastConfiguration.m_customIconImage = ":/gem.svg"; @@ -210,6 +216,26 @@ namespace O3DE::ProjectManager m_gemListView->scrollTo(proxyIndex); } + void GemCatalogScreen::UpdateGem(const QModelIndex& modelIndex) + { + const QString selectedGemName = m_gemModel->GetDisplayName(modelIndex); + GemUpdateDialog* confirmUpdateDialog = new GemUpdateDialog(selectedGemName, this); + if (confirmUpdateDialog->exec() == QDialog::Accepted) + { + // Update Gem + } + } + + void GemCatalogScreen::UninstallGem(const QModelIndex& modelIndex) + { + const QString selectedGemName = m_gemModel->GetDisplayName(modelIndex); + GemUninstallDialog* confirmUninstallDialog = new GemUninstallDialog(selectedGemName, this); + if (confirmUninstallDialog->exec() == QDialog::Accepted) + { + // Uninstall Gem + } + } + void GemCatalogScreen::hideEvent(QHideEvent* event) { ScreenWidget::hideEvent(event); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h index 55fbb1befc..5a5a782254 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h @@ -49,6 +49,8 @@ namespace O3DE::ProjectManager void OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies); void OnAddGemClicked(); void SelectGem(const QString& gemName); + void UpdateGem(const QModelIndex& modelIndex); + void UninstallGem(const QModelIndex& modelIndex); protected: void hideEvent(QHideEvent* event) override; @@ -62,6 +64,7 @@ namespace O3DE::ProjectManager private: void FillModel(const QString& projectPath); + QModelIndex GetCurrentlySelectedGem(); AZStd::unique_ptr m_notificationsView; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h index 12cce5a4ea..bef9f6cd99 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h @@ -57,7 +57,7 @@ namespace O3DE::ProjectManager UnknownDownloadStatus = -1, NotDownloaded, Downloading, - Downloaded, + Downloaded }; static QString GetDownloadStatusString(DownloadStatus status); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp index b0b8cca29a..7b6947c040 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace O3DE::ProjectManager { @@ -70,6 +71,8 @@ namespace O3DE::ProjectManager void GemInspector::Update(const QModelIndex& modelIndex) { + m_curModelIndex = modelIndex; + if (!modelIndex.isValid()) { m_mainWidget->hide(); @@ -122,6 +125,18 @@ namespace O3DE::ProjectManager m_lastUpdatedLabel->setText(tr("Last Updated: %1").arg(m_model->GetLastUpdated(modelIndex))); m_binarySizeLabel->setText(tr("Binary Size: %1 KB").arg(m_model->GetBinarySizeInKB(modelIndex))); + // Update and Uninstall buttons + if (m_model->GetGemOrigin(modelIndex) == GemInfo::Remote && m_model->GetDownloadStatus(modelIndex) == GemInfo::Downloaded) + { + m_updateGemButton->show(); + m_uninstallGemButton->show(); + } + else + { + m_updateGemButton->hide(); + m_uninstallGemButton->hide(); + } + m_mainWidget->adjustSize(); m_mainWidget->show(); } @@ -222,7 +237,7 @@ namespace O3DE::ProjectManager // Depending gems m_dependingGems = new GemsSubWidget(); - connect(m_dependingGems, &GemsSubWidget::TagClicked, this, [=](const QString& tag){ emit TagClicked(tag); }); + connect(m_dependingGems, &GemsSubWidget::TagClicked, this, [this](const QString& tag){ emit TagClicked(tag); }); m_mainLayout->addWidget(m_dependingGems); m_mainLayout->addSpacing(20); @@ -233,5 +248,20 @@ namespace O3DE::ProjectManager m_versionLabel = CreateStyledLabel(m_mainLayout, s_baseFontSize, s_textColor); m_lastUpdatedLabel = CreateStyledLabel(m_mainLayout, s_baseFontSize, s_textColor); m_binarySizeLabel = CreateStyledLabel(m_mainLayout, s_baseFontSize, s_textColor); + + m_mainLayout->addSpacing(20); + + // Update and Uninstall buttons + m_updateGemButton = new QPushButton(tr("Update Gem")); + m_updateGemButton->setObjectName("gemCatalogUpdateGemButton"); + m_mainLayout->addWidget(m_updateGemButton); + connect(m_updateGemButton, &QPushButton::clicked, this , [this]{ emit UpdateGem(m_curModelIndex); }); + + m_mainLayout->addSpacing(10); + + m_uninstallGemButton = new QPushButton(tr("Uninstall Gem")); + m_uninstallGemButton->setObjectName("gemCatalogUninstallGemButton"); + m_mainLayout->addWidget(m_uninstallGemButton); + connect(m_uninstallGemButton, &QPushButton::clicked, this , [this]{ emit UninstallGem(m_curModelIndex); }); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.h index c6548527ab..4fb2375d6b 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.h @@ -16,11 +16,12 @@ #include #include -#include #endif QT_FORWARD_DECLARE_CLASS(QVBoxLayout) QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QSpacerItem) +QT_FORWARD_DECLARE_CLASS(QPushButton) namespace O3DE::ProjectManager { @@ -45,6 +46,8 @@ namespace O3DE::ProjectManager signals: void TagClicked(const QString& tag); + void UpdateGem(const QModelIndex& modelIndex); + void UninstallGem(const QModelIndex& modelIndex); private slots: void OnSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); @@ -55,6 +58,7 @@ namespace O3DE::ProjectManager GemModel* m_model = nullptr; QWidget* m_mainWidget = nullptr; QVBoxLayout* m_mainLayout = nullptr; + QModelIndex m_curModelIndex; // General info (top) section QLabel* m_nameLabel = nullptr; @@ -77,5 +81,8 @@ namespace O3DE::ProjectManager QLabel* m_versionLabel = nullptr; QLabel* m_lastUpdatedLabel = nullptr; QLabel* m_binarySizeLabel = nullptr; + + QPushButton* m_updateGemButton = nullptr; + QPushButton* m_uninstallGemButton = nullptr; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.cpp new file mode 100644 index 0000000000..6838741417 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +#include +#include +#include +#include +#include + +namespace O3DE::ProjectManager +{ + GemUninstallDialog::GemUninstallDialog(const QString& gemName, QWidget* parent) + : QDialog(parent) + { + setWindowTitle(tr("Uninstall Remote Gem")); + setObjectName("GemUninstallDialog"); + setAttribute(Qt::WA_DeleteOnClose); + setModal(true); + + QVBoxLayout* layout = new QVBoxLayout(); + layout->setMargin(30); + layout->setAlignment(Qt::AlignTop); + setLayout(layout); + + // Body + QLabel* subTitleLabel = new QLabel(tr("Are you sure you want to uninstall %1?").arg(gemName)); + subTitleLabel->setObjectName("gemCatalogDialogSubTitle"); + layout->addWidget(subTitleLabel); + + layout->addSpacing(10); + + QLabel* bodyLabel = new QLabel(tr("The Gem and its related files will be uninstalled. This does not affect the Gem’s repository. " + "You can reinstall this Gem from the Catalog, but its contents may be subject to change.")); + bodyLabel->setWordWrap(true); + bodyLabel->setFixedWidth(440); + layout->addWidget(bodyLabel); + + layout->addSpacing(60); + + // Buttons + QDialogButtonBox* dialogButtons = new QDialogButtonBox(); + dialogButtons->setObjectName("footer"); + layout->addWidget(dialogButtons); + + QPushButton* cancelButton = dialogButtons->addButton(tr("Cancel"), QDialogButtonBox::RejectRole); + cancelButton->setProperty("secondary", true); + QPushButton* uninstallButton = dialogButtons->addButton(tr("Uninstall Gem"), QDialogButtonBox::ApplyRole); + uninstallButton->setObjectName("gemCatalogUninstallGemButton"); + + connect(cancelButton, &QPushButton::clicked, this, &QDialog::reject); + connect(uninstallButton, &QPushButton::clicked, this, &QDialog::accept); + } +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.h new file mode 100644 index 0000000000..9e3f4c3f3b --- /dev/null +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#endif + +namespace O3DE::ProjectManager +{ + class GemUninstallDialog + : public QDialog + { + Q_OBJECT // AUTOMOC + public: + explicit GemUninstallDialog(const QString& gemName, QWidget *parent = nullptr); + ~GemUninstallDialog() = default; + }; +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp new file mode 100644 index 0000000000..8d8490ab40 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +#include +#include +#include +#include +#include + +namespace O3DE::ProjectManager +{ + GemUpdateDialog::GemUpdateDialog(const QString& gemName, QWidget* parent) + : QDialog(parent) + { + setWindowTitle(tr("Update Remote Gem")); + setObjectName("GemUpdateDialog"); + setAttribute(Qt::WA_DeleteOnClose); + setModal(true); + + QVBoxLayout* layout = new QVBoxLayout(); + layout->setMargin(30); + layout->setAlignment(Qt::AlignTop); + setLayout(layout); + + // Body + QLabel* subTitleLabel = new QLabel(tr("Update to the latest version of %1?").arg(gemName)); + subTitleLabel->setObjectName("gemCatalogDialogSubTitle"); + layout->addWidget(subTitleLabel); + + layout->addSpacing(10); + + QLabel* bodyLabel = new QLabel(tr("The latest version of this Gem may not be compatible with your engine. " + "Updating this Gem will remove any local changes made to this Gem, " + "and may remove old features that are in use.")); + bodyLabel->setWordWrap(true); + bodyLabel->setFixedWidth(440); + layout->addWidget(bodyLabel); + + layout->addSpacing(60); + + // Buttons + QDialogButtonBox* dialogButtons = new QDialogButtonBox(); + dialogButtons->setObjectName("footer"); + layout->addWidget(dialogButtons); + + QPushButton* cancelButton = dialogButtons->addButton(tr("Cancel"), QDialogButtonBox::RejectRole); + cancelButton->setProperty("secondary", true); + QPushButton* updateButton = dialogButtons->addButton(tr("Update Gem"), QDialogButtonBox::ApplyRole); + + connect(cancelButton, &QPushButton::clicked, this, &QDialog::reject); + connect(updateButton, &QPushButton::clicked, this, &QDialog::accept); + } +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.h new file mode 100644 index 0000000000..1a2813d1a2 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#endif + +namespace O3DE::ProjectManager +{ + class GemUpdateDialog + : public QDialog + { + Q_OBJECT // AUTOMOC + public : + explicit GemUpdateDialog(const QString& gemName, QWidget* parent = nullptr); + ~GemUpdateDialog() = default; + }; +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/project_manager_files.cmake b/Code/Tools/ProjectManager/project_manager_files.cmake index e2e35717f6..fcfae2f336 100644 --- a/Code/Tools/ProjectManager/project_manager_files.cmake +++ b/Code/Tools/ProjectManager/project_manager_files.cmake @@ -96,6 +96,10 @@ set(FILES Source/GemCatalog/GemListHeaderWidget.cpp Source/GemCatalog/GemModel.h Source/GemCatalog/GemModel.cpp + Source/GemCatalog/GemUninstallDialog.h + Source/GemCatalog/GemUninstallDialog.cpp + Source/GemCatalog/GemUpdateDialog.h + Source/GemCatalog/GemUpdateDialog.cpp Source/GemCatalog/GemDependenciesDialog.h Source/GemCatalog/GemDependenciesDialog.cpp Source/GemCatalog/GemRequirementDialog.h From c8b9f05079fd974d904504a63b77775b6e9d002c Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Tue, 9 Nov 2021 15:35:17 -0800 Subject: [PATCH 11/97] Ensuring the 4 types of RPCs (1)Autonomous->Authority (2)Authority->Autonomous (3)Authority->Client and (4)Server->Authority all compile. Invoking anything that starts from Autonomous or Authority requires a controller (otherwise just requires a component), and anything handled by Authority or Autonomous requires a controller for Handle on OnEvent methods (otherwise OnEvent and Handle occurs on the component) Signed-off-by: Gene Walters --- .../AutoGen/AutoComponent_Header.jinja | 28 +++---- .../AutoGen/AutoComponent_Source.jinja | 78 ++++++++++--------- 2 files changed, 57 insertions(+), 49 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Header.jinja b/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Header.jinja index 5cfeb250fa..b78b7cffba 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Header.jinja +++ b/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Header.jinja @@ -443,35 +443,31 @@ namespace {{ Component.attrib['Namespace'] }} {{ DeclareNetworkPropertyAccessors(Component, 'Autonomous', 'Authority', false)|indent(8) -}} {{ DeclareNetworkPropertyAccessors(Component, 'Autonomous', 'Authority', true)|indent(8) -}} {{ DeclareArchetypePropertyGetters(Component)|indent(8) -}} - {{ DeclareRpcInvocations(Component, 'Client', 'Authority', false)|indent(8) -}} - {{ DeclareRpcInvocations(Component, 'Client', 'Authority', true)|indent(8) -}} {{ DeclareRpcInvocations(Component, 'Autonomous', 'Authority', false)|indent(8) -}} {{ DeclareRpcInvocations(Component, 'Autonomous', 'Authority', true)|indent(8) -}} {{ DeclareRpcInvocations(Component, 'Authority', 'Autonomous', false)|indent(8) -}} {{ DeclareRpcInvocations(Component, 'Authority', 'Autonomous', true)|indent(8) -}} {{ DeclareRpcInvocations(Component, 'Authority', 'Client', false)|indent(8) -}} {{ DeclareRpcInvocations(Component, 'Authority', 'Client', true)|indent(8) -}} + + //! RPC Handlers: Override handlers in order ti implement what happens after receiving an RPC {{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Server', 'Authority', false)|indent(8) -}} - {{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Client', 'Authority', false)|indent(8) -}} {{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Autonomous', 'Authority', false)|indent(8) -}} {{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Authority', 'Autonomous', false)|indent(8) -}} - {{ AutoComponentMacros.DeclareRpcSignals(Component, 'Server', 'Authority')|indent(8) -}} - {{ AutoComponentMacros.DeclareRpcSignals(Component, 'Client', 'Authority')|indent(8) -}} - {{ AutoComponentMacros.DeclareRpcSignals(Component, 'Autonomous', 'Authority')|indent(8) -}} - {{ AutoComponentMacros.DeclareRpcSignals(Component, 'Authority', 'Autonomous')|indent(8) -}} + + //! RPC Event Getters: Subscribe to these events and get notified when an RPC is received {{ AutoComponentMacros.DeclareRpcEventGetters(Component, 'Server', 'Authority')|indent(8) -}} - {{ AutoComponentMacros.DeclareRpcEventGetters(Component, 'Client', 'Authority')|indent(8) -}} {{ AutoComponentMacros.DeclareRpcEventGetters(Component, 'Autonomous', 'Authority')|indent(8) -}} - {{ AutoComponentMacros.DeclareRpcEventGetters(Component, 'Authority', 'Autonomous')|indent(8) }} + {{ AutoComponentMacros.DeclareRpcEventGetters(Component, 'Authority', 'Autonomous')|indent(8) -}} + {% for Service in Component.iter('ComponentRelation') %} {% if (Service.attrib['HasController']|booleanTrue) and (Service.attrib['Constraint'] != 'Incompatible') %} {{ Service.attrib['Namespace'] }}::{{ Service.attrib['Name'] }}Controller* Get{{ Service.attrib['Name'] }}Controller(); {% endif %} {% endfor %} - + protected: {{ AutoComponentMacros.DeclareRpcEvents(Component, 'Server', 'Authority')|indent(8) -}} - {{ AutoComponentMacros.DeclareRpcEvents(Component, 'Client', 'Authority')|indent(8) -}} {{ AutoComponentMacros.DeclareRpcEvents(Component, 'Autonomous', 'Authority')|indent(8) -}} {{ AutoComponentMacros.DeclareRpcEvents(Component, 'Authority', 'Autonomous')|indent(8) }} }; @@ -517,6 +513,8 @@ namespace {{ Component.attrib['Namespace'] }} {{ DeclareNetworkPropertyGetters(Component, 'Autonomous', 'Authority', false)|indent(8) -}} {{ DeclareArchetypePropertyGetters(Component)|indent(8) -}} {{ DeclareRpcInvocations(Component, 'Server', 'Authority', false)|indent(8) -}} + + //! RPC Event Getters: Subscribe to these events and get notified when this component receives an RPC {{ AutoComponentMacros.DeclareRpcEventGetters(Component, 'Authority', 'Client')|indent(8) -}} //! MultiplayerComponent interface @@ -541,9 +539,13 @@ namespace {{ Component.attrib['Namespace'] }} {{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Client', true)|indent(8) -}} {{ DeclareNetworkPropertyGetters(Component, 'Autonomous', 'Authority', true)|indent(8) -}} {{ DeclareRpcInvocations(Component, 'Server', 'Authority', true)|indent(8) -}} + + //! RPC Handlers: Override handlers in order to implement what happens after receiving an RPC {{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Authority', 'Client', false)|indent(8) -}} - {{ AutoComponentMacros.DeclareRpcSignals(Component, 'Authority', 'Client')|indent(8) -}} - {{ AutoComponentMacros.DeclareRpcEvents(Component, 'Authority', 'Client')|indent(8) }} + + //! RPC Events: Subscribe to these events and get notified when an RPC is received + {{ AutoComponentMacros.DeclareRpcEvents(Component, 'Authority', 'Client')|indent(8) -}} + {% for Service in Component.iter('ComponentRelation') %} {% if Service.attrib['Constraint'] != 'Incompatible' %} const {{ Service.attrib['Namespace'] }}::{{ Service.attrib['Name'] }}* Get{{ Service.attrib['Name'] }}() const; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Source.jinja index cf62f6f901..e9bc21875b 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Source.jinja @@ -340,27 +340,11 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(par {% endmacro %} {# -#} -{% macro DefineRpcSignal(Component, ClassName, Property, InvokeFrom) %} -{% set paramNames = [] %} -{% set paramTypes = [] %} -{% set paramDefines = [] %} -{{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }} -void {{ ClassName }}::Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramDefines) }}) -{ - m_{{ UpperFirst(Property.attrib['Name']) }}Event.Signal({{ ', '.join(paramNames) }}); -} -{% endmacro %} -{# - #} {% macro DefineRpcInvocations(Component, ClassName, InvokeFrom, HandleOn, IsProtected) %} {% call(Property) AutoComponentMacros.ParseRemoteProcedures(Component, InvokeFrom, HandleOn) %} {% if Property.attrib['IsPublic']|booleanTrue != IsProtected %} {{ DefineRpcInvocation(Component, ClassName, Property, InvokeFrom, HandleOn) -}} -{% if Property.attrib['GenerateEventBindings']|booleanTrue == true %} -{{ DefineRpcSignal(Component, ClassName, Property, InvokeFrom) -}} -{% endif %} {% endif %} {% endcall %} {% endmacro %} @@ -374,33 +358,46 @@ void {{ ClassName }}::Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.jo {% set paramTypes = [] %} {% set paramDefines = [] %} {{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }} - ->Method("{{ UpperFirst(Property.attrib['Name']) }}", [](const {{ ClassName }}* self, {{ ', '.join(paramDefines) }}) { - self->m_controller->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }}); + ->Method("{{ UpperFirst(Property.attrib['Name']) }}", []({{ ClassName }}* self, {{ ', '.join(paramDefines) }}) { +{% if (InvokeFrom == 'Server') %} + self->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }}); +{% elif (InvokeFrom == 'Authority') or (InvokeFrom == 'Autonomous') %} + if (self->m_controller) + { + self->m_controller->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }}); + } + else + { + AZ_Warning("Network RPC", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }} method failed. Entity '%s' (id: %s) {{ ClassName }} is missing the network controller. This remote-procedure can only be invoked from {{InvokeFrom}} network entities, because this entity doesn't have a controller, it must not be a {{InvokeFrom}} entity. Please check your network context before attempting to call {{ UpperFirst(Property.attrib['Name']) }}.", self->GetEntity()->GetName().c_str(), self->GetEntityId().ToString().c_str()) + } +{% endif %} }) ->Method("{{ UpperFirst(Property.attrib['Name']) }}ByEntityId", [](AZ::EntityId id, {{ ', '.join(paramDefines) }}) { AZ::Entity* entity = AZ::Interface::Get()->FindEntity(id); if (!entity) { - AZ_Warning("Network Property", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }}ByEntityId failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str()) + AZ_Warning("Network RPC", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }}ByEntityId failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str()) return; } {{ ClassName }}* networkComponent = entity->FindComponent<{{ ClassName }}>(); if (!networkComponent) { - AZ_Warning("Network Property", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }}ByEntityId failed. Entity '%s' (id: %s) is missing {{ ClassName }}, be sure to add {{ ClassName }} to this entity.", entity->GetName().c_str(), id.ToString().c_str()) + AZ_Warning("Network RPC", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }}ByEntityId failed. Entity '%s' (id: %s) is missing {{ ClassName }}, be sure to add {{ ClassName }} to this entity.", entity->GetName().c_str(), id.ToString().c_str()) return; } - +{% if (InvokeFrom == 'Server') %} + networkComponent->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }}); +{% elif (InvokeFrom == 'Authority') or (InvokeFrom == 'Autonomous') %} {{ ClassName }}Controller* controller = static_cast<{{ ClassName }}Controller*>(networkComponent->GetController()); if (!controller) { - AZ_Warning("Network Property", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }}ByEntityId method failed. Entity '%s' (id: %s) {{ ClassName }} is missing the network controller. This RemoteProcedure can only be invoked from {{InvokeFrom}} network entities, because this entity doesn't have a controller, it must not be a {{InvokeFrom}} entity. Please check your network context before attempting to call {{ UpperFirst(Property.attrib['Name']) }}.", entity->GetName().c_str(), id.ToString().c_str()) + AZ_Warning("Network RPC", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }}ByEntityId method failed. Entity '%s' (id: %s) {{ ClassName }} is missing the network controller. This RemoteProcedure can only be invoked from {{InvokeFrom}} network entities, because this entity doesn't have a controller, it must not be a {{InvokeFrom}} entity. Please check your network context before attempting to call {{ UpperFirst(Property.attrib['Name']) }}.", entity->GetName().c_str(), id.ToString().c_str()) return; } - controller->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }}); +{% endif %} }, { { { "Source", "The Source containing the {{ ClassName }}Controller" }{% for paramName in paramNames %}, {"{{ paramName }}"}{% endfor %}}}) ->Attribute(AZ::Script::Attributes::ToolTip, "{{Property.attrib['Description']}}") {% endif %} @@ -436,9 +433,13 @@ void {{ ClassName }}::Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.jo {% set paramTypes = [] %} {% set paramDefines = [] %} {{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }} - ->Method("Get{{ UpperFirst(Property.attrib['Name']) }}Event", [](const {{ ClassName }}* self) -> AZ::Event<{{ ', '.join(paramTypes) }}>& + ->Method("Get{{ UpperFirst(Property.attrib['Name']) }}Event", []({{ ClassName }}* self) -> AZ::Event<{{ ', '.join(paramTypes) }}>& { +{% if HandleOn == 'Client' %} + return self->Get{{ UpperFirst(Property.attrib['Name']) }}Event(); +{% elif (HandleOn == 'Authority') or (HandleOn == 'Autonomous') %} return self->m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event(); +{% endif %} }) ->Attribute(AZ::Script::Attributes::AzEventDescription, {{ LowerFirst(Property.attrib['Name']) }}EventDesc) ->Method("Get{{ UpperFirst(Property.attrib['Name']) }}EventByEntityId", [](AZ::EntityId id) -> AZ::Event<{{ ', '.join(paramTypes) }}>* @@ -456,7 +457,9 @@ void {{ ClassName }}::Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.jo AZ_Warning("Network Property", false, "{{ ClassName }} Get{{ UpperFirst(Property.attrib['Name']) }}EventByEntityId failed. Entity '%s' (id: %s) is missing {{ ClassName }}, be sure to add {{ ClassName }} to this entity.", entity->GetName().c_str(), id.ToString().c_str()) return nullptr; } - +{% if HandleOn == 'Client' %} + return &networkComponent->Get{{ UpperFirst(Property.attrib['Name']) }}Event(); +{% elif (HandleOn == 'Authority') or (HandleOn == 'Autonomous') %} {{ ClassName }}Controller* controller = static_cast<{{ ClassName }}Controller*>(networkComponent->GetController()); if (!controller) { @@ -465,6 +468,7 @@ void {{ ClassName }}::Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.jo } return &controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event(); +{% endif %} }) ->Attribute(AZ::Script::Attributes::AzEventDescription, AZStd::move({{ LowerFirst(Property.attrib['Name']) }}EventDesc)) {% endif %} @@ -494,29 +498,31 @@ case {{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ Upp { AZ_Assert(GetNetBindComponent()->GetNetEntityRole() == Multiplayer::NetEntityRole::Authority, "Entity proxy does not have authority"); m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection, {{ ', '.join(rpcParamList) }}); -{% if Property.attrib['GenerateEventBindings']|booleanTrue == true %} - m_controller->Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(rpcParamList) }}); -{% endif %} +{% if (Property.attrib['GenerateEventBindings']|booleanTrue == true) %} + m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event().Signal({{ ', '.join(rpcParamList) }}); +{% endif %} } -{% if Property.attrib['IsReliable']|booleanTrue %} -{# if the rpc is not reliable we can simply drop it, also note message reliability type is default reliable in EntityRpcMessage #} else // Note that this rpc is marked reliable, trigger the appropriate rpc event so it can be forwarded { +{% if Property.attrib['IsReliable']|booleanTrue %} +{# if the rpc is not reliable we can simply drop it, also note message reliability type is default reliable in EntityRpcMessage #} m_netBindComponent->{{ "GetSend" + InvokeFrom + "To" + HandleOn + "RpcEvent" }}().Signal(message); +{% endif %} } - -{% endif %} {% elif HandleOn == 'Autonomous' %} if (m_controller) { AZ_Assert(GetNetBindComponent()->GetNetEntityRole() == Multiplayer::NetEntityRole::Autonomous, "Entity proxy does not have autonomy"); m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection, {{ ', '.join(rpcParamList) }}); -{% if Property.attrib['GenerateEventBindings']|booleanTrue == true %} - m_controller->Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(rpcParamList) }}); -{% endif %} +{% if Property.attrib['GenerateEventBindings']|booleanTrue == true %} + m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event().Signal({{ ', '.join(rpcParamList) }}); +{% endif %} } -{% else %} +{% elif HandleOn == 'Client' %} Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection, {{ ', '.join(rpcParamList) }}); +{% if Property.attrib['GenerateEventBindings']|booleanTrue == true %} + m_{{ UpperFirst(Property.attrib['Name']) }}Event.Signal({{ ', '.join(rpcParamList) }}); +{% endif %} {% endif %} } else if (paramsSerialized) From c99071533d2ff5acec2b576d3932c3635e5b6565 Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Tue, 9 Nov 2021 15:39:43 -0800 Subject: [PATCH 12/97] Small: fix typo Signed-off-by: Gene Walters --- .../Code/Include/Multiplayer/AutoGen/AutoComponent_Header.jinja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Header.jinja b/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Header.jinja index b78b7cffba..58a47b336f 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Header.jinja +++ b/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Header.jinja @@ -450,7 +450,7 @@ namespace {{ Component.attrib['Namespace'] }} {{ DeclareRpcInvocations(Component, 'Authority', 'Client', false)|indent(8) -}} {{ DeclareRpcInvocations(Component, 'Authority', 'Client', true)|indent(8) -}} - //! RPC Handlers: Override handlers in order ti implement what happens after receiving an RPC + //! RPC Handlers: Override handlers in order to implement what happens after receiving an RPC {{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Server', 'Authority', false)|indent(8) -}} {{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Autonomous', 'Authority', false)|indent(8) -}} {{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Authority', 'Autonomous', false)|indent(8) -}} From dadf06edda132c0d2c02a9668f16da770670d01f Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Tue, 9 Nov 2021 19:03:26 -0800 Subject: [PATCH 13/97] Fixed issue where skin material wouldn't render if applied to a model with several submeshes and those submeshes had different material types applied to them. Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Atom/Feature/Mesh/MeshFeatureProcessor.h | 13 +- .../Mesh/MeshFeatureProcessorInterface.h | 6 +- .../Code/Mocks/MockMeshFeatureProcessor.h | 2 +- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 244 +++++++++--------- .../SkinnedMeshFeatureProcessor.cpp | 14 +- .../Code/Source/AtomActorInstance.cpp | 6 +- 6 files changed, 147 insertions(+), 138 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h index 2ac184e2e0..4aec78be51 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h @@ -30,7 +30,7 @@ namespace AZ class TransformServiceFeatureProcessor; class RayTracingFeatureProcessor; - class MeshDataInstance + class ModelDataInstance { friend class MeshFeatureProcessor; friend class MeshLoader; @@ -47,7 +47,7 @@ namespace AZ public: using ModelChangedEvent = MeshFeatureProcessorInterface::ModelChangedEvent; - MeshLoader(const Data::Asset& modelAsset, MeshDataInstance* parent); + MeshLoader(const Data::Asset& modelAsset, ModelDataInstance* parent); ~MeshLoader(); ModelChangedEvent& GetModelChangedEvent(); @@ -68,7 +68,7 @@ namespace AZ } }; MeshFeatureProcessorInterface::ModelChangedEvent m_modelChangedEvent; Data::Asset m_modelAsset; - MeshDataInstance* m_parent = nullptr; + ModelDataInstance* m_parent = nullptr; }; void DeInit(); @@ -99,7 +99,8 @@ namespace AZ //! A reference to the original model asset in case it got cloned before creating the model instance. Data::Asset m_originalModelAsset; - Data::Instance m_shaderResourceGroup; + //! List of object SRGs used by meshes in this model + AZStd::vector> m_objectSrgList; AZStd::unique_ptr m_meshLoader; RPI::Scene* m_scene = nullptr; RHI::DrawItemSortKey m_sortKey; @@ -152,7 +153,7 @@ namespace AZ Data::Instance GetModel(const MeshHandle& meshHandle) const override; Data::Asset GetModelAsset(const MeshHandle& meshHandle) const override; - Data::Instance GetObjectSrg(const MeshHandle& meshHandle) const override; + AZStd::vector>& GetObjectSrgs(const MeshHandle& meshHandle) const override; void QueueObjectSrgForCompile(const MeshHandle& meshHandle) const override; void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const Data::Instance& material) override; void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const MaterialAssignmentMap& materials) override; @@ -195,7 +196,7 @@ namespace AZ void OnRenderPipelineRemoved(RPI::RenderPipeline* pipeline) override; AZStd::concurrency_checker m_meshDataChecker; - StableDynamicArray m_meshData; + StableDynamicArray m_modelData; TransformServiceFeatureProcessor* m_transformService; RayTracingFeatureProcessor* m_rayTracingFeatureProcessor = nullptr; AZ::RPI::ShaderSystemInterface::GlobalShaderOptionUpdatedEvent::Handler m_handleGlobalShaderOptionUpdate; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h index cffbe5c3c5..3be5f3efd8 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h @@ -20,7 +20,7 @@ namespace AZ { namespace Render { - class MeshDataInstance; + class ModelDataInstance; //! Settings to apply to a mesh handle when acquiring it for the first time struct MeshHandleDescriptor @@ -40,7 +40,7 @@ namespace AZ public: AZ_RTTI(AZ::Render::MeshFeatureProcessorInterface, "{975D7F0C-2E7E-4819-94D0-D3C4E2024721}", FeatureProcessor); - using MeshHandle = StableDynamicArrayHandle; + using MeshHandle = StableDynamicArrayHandle; using ModelChangedEvent = Event>; //! Acquires a model with an optional collection of material assignments. @@ -66,7 +66,7 @@ namespace AZ //! instead of compiling the srg directly. This way, if the srg has already been queued for compile, //! it will not be queued twice in the same frame. The ObjectSrg should not be updated during //! Simulate, or it will create a race between updating the data and the call to Compile - virtual Data::Instance GetObjectSrg(const MeshHandle& meshHandle) const = 0; + virtual AZStd::vector>& GetObjectSrgs(const MeshHandle& meshHandle) const = 0; //! Queues the object srg for compile. virtual void QueueObjectSrgForCompile(const MeshHandle& meshHandle) const = 0; //! Sets the MaterialAssignmentMap for a meshHandle, using just a single material for the DefaultMaterialAssignmentId. diff --git a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h index 35e399997f..05a3274657 100644 --- a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h @@ -19,7 +19,7 @@ namespace UnitTest MOCK_METHOD1(CloneMesh, MeshHandle(const MeshHandle&)); MOCK_CONST_METHOD1(GetModel, AZStd::intrusive_ptr(const MeshHandle&)); MOCK_CONST_METHOD1(GetModelAsset, AZ::Data::Asset(const MeshHandle&)); - MOCK_CONST_METHOD1(GetObjectSrg, AZStd::intrusive_ptr(const MeshHandle&)); + MOCK_CONST_METHOD1(GetObjectSrgs, AZStd::vector>&(const MeshHandle&)); MOCK_CONST_METHOD1(QueueObjectSrgForCompile, void(const MeshHandle&)); MOCK_CONST_METHOD1(GetMaterialAssignmentMap, const AZ::Render::MaterialAssignmentMap&(const MeshHandle&)); MOCK_METHOD2(ConnectModelChangeEventHandler, void(const MeshHandle&, ModelChangedEvent::Handler&)); diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index c7fb19bc5d..778c80e5e1 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -67,7 +67,7 @@ namespace AZ m_handleGlobalShaderOptionUpdate.Disconnect(); DisableSceneNotification(); - AZ_Warning("MeshFeatureProcessor", m_meshData.size() == 0, + AZ_Warning("MeshFeatureProcessor", m_modelData.size() == 0, "Deactivaing the MeshFeatureProcessor, but there are still outstanding mesh handles.\n" ); m_transformService = nullptr; @@ -81,7 +81,7 @@ namespace AZ AZStd::concurrency_check_scope scopeCheck(m_meshDataChecker); - const auto iteratorRanges = m_meshData.GetParallelRanges(); + const auto iteratorRanges = m_modelData.GetParallelRanges(); AZ::JobCompletion jobCompletion; for (const auto& iteratorRange : iteratorRanges) { @@ -125,11 +125,11 @@ namespace AZ m_forceRebuildDrawPackets = false; // CullingSystem::RegisterOrUpdateCullable() is not threadsafe, so need to do those updates in a single thread - for (MeshDataInstance& meshDataInstance : m_meshData) + for (ModelDataInstance& modelDataInstance : m_modelData) { - if (meshDataInstance.m_model && meshDataInstance.m_cullBoundsNeedsUpdate) + if (modelDataInstance.m_model && modelDataInstance.m_cullBoundsNeedsUpdate) { - meshDataInstance.UpdateCullBounds(m_transformService); + modelDataInstance.UpdateCullBounds(m_transformService); } } } @@ -151,14 +151,14 @@ namespace AZ AZ_PROFILE_SCOPE(AzRender, "MeshFeatureProcessor: AcquireMesh"); // don't need to check the concurrency during emplace() because the StableDynamicArray won't move the other elements during insertion - MeshHandle meshDataHandle = m_meshData.emplace(); + MeshHandle meshDataHandle = m_modelData.emplace(); meshDataHandle->m_descriptor = descriptor; meshDataHandle->m_scene = GetParentScene(); meshDataHandle->m_materialAssignments = materials; meshDataHandle->m_objectId = m_transformService->ReserveObjectId(); meshDataHandle->m_originalModelAsset = descriptor.m_modelAsset; - meshDataHandle->m_meshLoader = AZStd::make_unique(descriptor.m_modelAsset, &*meshDataHandle); + meshDataHandle->m_meshLoader = AZStd::make_unique(descriptor.m_modelAsset, &*meshDataHandle); return meshDataHandle; } @@ -183,7 +183,7 @@ namespace AZ m_transformService->ReleaseObjectId(meshHandle->m_objectId); AZStd::concurrency_check_scope scopeCheck(m_meshDataChecker); - m_meshData.erase(meshHandle); + m_modelData.erase(meshHandle); return true; } @@ -215,9 +215,10 @@ namespace AZ return {}; } - Data::Instance MeshFeatureProcessor::GetObjectSrg(const MeshHandle& meshHandle) const + AZStd::vector>& MeshFeatureProcessor::GetObjectSrgs(const MeshHandle& meshHandle) const { - return meshHandle.IsValid() ? meshHandle->m_shaderResourceGroup : nullptr; + static AZStd::vector> staticEmptyList; + return meshHandle.IsValid() ? meshHandle->m_objectSrgList : staticEmptyList; } void MeshFeatureProcessor::QueueObjectSrgForCompile(const MeshHandle& meshHandle) const @@ -274,9 +275,9 @@ namespace AZ { if (meshHandle.IsValid()) { - MeshDataInstance& meshData = *meshHandle; - meshData.m_cullBoundsNeedsUpdate = true; - meshData.m_objectSrgNeedsUpdate = true; + ModelDataInstance& modelData = *meshHandle; + modelData.m_cullBoundsNeedsUpdate = true; + modelData.m_objectSrgNeedsUpdate = true; m_transformService->SetTransformForId(meshHandle->m_objectId, transform, nonUniformScale); @@ -292,10 +293,10 @@ namespace AZ { if (meshHandle.IsValid()) { - MeshDataInstance& meshData = *meshHandle; - meshData.m_aabb = localAabb; - meshData.m_cullBoundsNeedsUpdate = true; - meshData.m_objectSrgNeedsUpdate = true; + ModelDataInstance& modelData = *meshHandle; + modelData.m_aabb = localAabb; + modelData.m_cullBoundsNeedsUpdate = true; + modelData.m_objectSrgNeedsUpdate = true; } }; @@ -465,7 +466,7 @@ namespace AZ void MeshFeatureProcessor::UpdateMeshReflectionProbes() { // we need to rebuild the Srg for any meshes that are using the forward pass IBL specular option - for (auto& meshInstance : m_meshData) + for (auto& meshInstance : m_modelData) { if (meshInstance.m_descriptor.m_useForwardPassIblSpecular) { @@ -474,14 +475,14 @@ namespace AZ } } - // MeshDataInstance::MeshLoader... - MeshDataInstance::MeshLoader::MeshLoader(const Data::Asset& modelAsset, MeshDataInstance* parent) + // ModelDataInstance::MeshLoader... + ModelDataInstance::MeshLoader::MeshLoader(const Data::Asset& modelAsset, ModelDataInstance* parent) : m_modelAsset(modelAsset) , m_parent(parent) { if (!m_modelAsset.GetId().IsValid()) { - AZ_Error("MeshDataInstance::MeshLoader", false, "Invalid model asset Id."); + AZ_Error("ModelDataInstance::MeshLoader", false, "Invalid model asset Id."); return; } @@ -494,19 +495,19 @@ namespace AZ AzFramework::AssetCatalogEventBus::Handler::BusConnect(); } - MeshDataInstance::MeshLoader::~MeshLoader() + ModelDataInstance::MeshLoader::~MeshLoader() { AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); Data::AssetBus::Handler::BusDisconnect(); } - MeshFeatureProcessorInterface::ModelChangedEvent& MeshDataInstance::MeshLoader::GetModelChangedEvent() + MeshFeatureProcessorInterface::ModelChangedEvent& ModelDataInstance::MeshLoader::GetModelChangedEvent() { return m_modelChangedEvent; } //! AssetBus::Handler overrides... - void MeshDataInstance::MeshLoader::OnAssetReady(Data::Asset asset) + void ModelDataInstance::MeshLoader::OnAssetReady(Data::Asset asset) { Data::Asset modelAsset = asset; @@ -527,7 +528,7 @@ namespace AZ } else { - AZ_Error("MeshDataInstance", false, "Cannot clone model for '%s'. Cloth simulation results won't be individual per entity.", modelAsset->GetName().GetCStr()); + AZ_Error("ModelDataInstance", false, "Cannot clone model for '%s'. Cloth simulation results won't be individual per entity.", modelAsset->GetName().GetCStr()); model = RPI::Model::FindOrCreate(modelAsset); } } @@ -547,29 +548,29 @@ namespace AZ { //when running with null renderer, the RPI::Model::FindOrCreate(...) is expected to return nullptr, so suppress this error. AZ_Error( - "MeshDataInstance::OnAssetReady", RHI::IsNullRenderer(), "Failed to create model instance for '%s'", + "ModelDataInstance::OnAssetReady", RHI::IsNullRenderer(), "Failed to create model instance for '%s'", asset.GetHint().c_str()); } } - void MeshDataInstance::MeshLoader::OnModelReloaded(Data::Asset asset) + void ModelDataInstance::MeshLoader::OnModelReloaded(Data::Asset asset) { OnAssetReady(asset); } - void MeshDataInstance::MeshLoader::OnAssetError(Data::Asset asset) + void ModelDataInstance::MeshLoader::OnAssetError(Data::Asset asset) { // Note: m_modelAsset and asset represents same asset, but only m_modelAsset contains the file path in its hint from serialization AZ_Error( - "MeshDataInstance::MeshLoader", false, "Failed to load asset %s. It may be missing, or not be finished processing", + "ModelDataInstance::MeshLoader", false, "Failed to load asset %s. It may be missing, or not be finished processing", m_modelAsset.GetHint().c_str()); AzFramework::AssetSystemRequestBus::Broadcast( &AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetByUuid, m_modelAsset.GetId().m_guid); } - void MeshDataInstance::MeshLoader::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) + void ModelDataInstance::MeshLoader::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) { if (assetId == m_modelAsset.GetId()) { @@ -584,7 +585,7 @@ namespace AZ } } - void MeshDataInstance::MeshLoader::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) + void ModelDataInstance::MeshLoader::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) { if (assetId == m_modelAsset.GetId()) { @@ -599,9 +600,9 @@ namespace AZ } } - // MeshDataInstance... + // ModelDataInstance... - void MeshDataInstance::DeInit() + void ModelDataInstance::DeInit() { m_scene->GetCullingScene()->UnregisterCullable(m_cullable); @@ -609,11 +610,11 @@ namespace AZ m_drawPacketListsByLod.clear(); m_materialAssignments.clear(); - m_shaderResourceGroup = {}; + m_objectSrgList = {}; m_model = {}; } - void MeshDataInstance::Init(Data::Instance model) + void ModelDataInstance::Init(Data::Instance model) { m_model = model; const size_t modelLodCount = m_model->GetLodCount(); @@ -623,11 +624,11 @@ namespace AZ BuildDrawPacketList(modelLodIndex); } - if (m_shaderResourceGroup) + for(auto& objectSrg : m_objectSrgList) { // Set object Id once since it never changes RHI::ShaderInputNameIndex objectIdIndex = "m_objectId"; - m_shaderResourceGroup->SetConstant(objectIdIndex, m_objectId.GetIndex()); + objectSrg->SetConstant(objectIdIndex, m_objectId.GetIndex()); objectIdIndex.AssertValid(); } @@ -643,12 +644,12 @@ namespace AZ m_objectSrgNeedsUpdate = true; } - void MeshDataInstance::BuildDrawPacketList(size_t modelLodIndex) + void ModelDataInstance::BuildDrawPacketList(size_t modelLodIndex) { RPI::ModelLod& modelLod = *m_model->GetLods()[modelLodIndex]; const size_t meshCount = modelLod.GetMeshes().size(); - MeshDataInstance::DrawPacketList& drawPacketListOut = m_drawPacketListsByLod[modelLodIndex]; + ModelDataInstance::DrawPacketList& drawPacketListOut = m_drawPacketListsByLod[modelLodIndex]; drawPacketListOut.clear(); drawPacketListOut.reserve(meshCount); @@ -682,27 +683,32 @@ namespace AZ continue; } - if (m_shaderResourceGroup && m_shaderResourceGroup->GetLayout()->GetHash() != objectSrgLayout->GetHash()) + Data::Instance meshObjectSrg; + + // See if the object SRG for this mesh is already in our list of object SRGs + for (auto& objectSrgIter : m_objectSrgList) { - AZ_Warning("MeshFeatureProcessor", false, "All materials on a model must use the same per-object ShaderResourceGroup. Skipping."); - continue; + if (objectSrgIter->GetLayout()->GetHash() == objectSrgLayout->GetHash()) + { + meshObjectSrg = objectSrgIter; + } } - // The first time we find the per-surface SRG asset we create an instance and store it - // in shaderResourceGroupInOut. All of the Model's draw packets will use this same instance. - if (!m_shaderResourceGroup) + // If the object SRG for this mesh was not already in the list, create it and add it to the list + if (!meshObjectSrg) { auto& shaderAsset = material->GetAsset()->GetMaterialTypeAsset()->GetShaderAssetForObjectSrg(); - m_shaderResourceGroup = RPI::ShaderResourceGroup::Create(shaderAsset, objectSrgLayout->GetName()); - if (!m_shaderResourceGroup) + meshObjectSrg = RPI::ShaderResourceGroup::Create(shaderAsset, objectSrgLayout->GetName()); + if (!meshObjectSrg) { AZ_Warning("MeshFeatureProcessor", false, "Failed to create a new shader resource group, skipping."); continue; } + m_objectSrgList.push_back(meshObjectSrg); } // setup the mesh draw packet - RPI::MeshDrawPacket drawPacket(modelLod, meshIndex, material, m_shaderResourceGroup, materialAssignment.m_matModUvOverrides); + RPI::MeshDrawPacket drawPacket(modelLod, meshIndex, material, meshObjectSrg, materialAssignment.m_matModUvOverrides); // set the shader option to select forward pass IBL specular if necessary if (!drawPacket.SetShaderOption(AZ::Name("o_meshUseForwardPassIBLSpecular"), AZ::RPI::ShaderOptionValue{ m_descriptor.m_useForwardPassIblSpecular })) @@ -726,7 +732,7 @@ namespace AZ } } - void MeshDataInstance::SetRayTracingData() + void ModelDataInstance::SetRayTracingData() { if (!m_model) { @@ -993,7 +999,7 @@ namespace AZ rayTracingFeatureProcessor->SetMesh(m_objectId, m_model->GetModelAsset()->GetId(), subMeshes); } - void MeshDataInstance::RemoveRayTracingData() + void ModelDataInstance::RemoveRayTracingData() { // remove from ray tracing RayTracingFeatureProcessor* rayTracingFeatureProcessor = m_scene->GetFeatureProcessor(); @@ -1003,7 +1009,7 @@ namespace AZ } } - void MeshDataInstance::SetSortKey(RHI::DrawItemSortKey sortKey) + void ModelDataInstance::SetSortKey(RHI::DrawItemSortKey sortKey) { m_sortKey = sortKey; for (auto& drawPacketList : m_drawPacketListsByLod) @@ -1015,24 +1021,24 @@ namespace AZ } } - RHI::DrawItemSortKey MeshDataInstance::GetSortKey() const + RHI::DrawItemSortKey ModelDataInstance::GetSortKey() const { return m_sortKey; } - void MeshDataInstance::SetMeshLodConfiguration(RPI::Cullable::LodConfiguration meshLodConfig) + void ModelDataInstance::SetMeshLodConfiguration(RPI::Cullable::LodConfiguration meshLodConfig) { m_cullable.m_lodData.m_lodConfiguration = meshLodConfig; } - RPI::Cullable::LodConfiguration MeshDataInstance::GetMeshLodConfiguration() const + RPI::Cullable::LodConfiguration ModelDataInstance::GetMeshLodConfiguration() const { return m_cullable.m_lodData.m_lodConfiguration; } - void MeshDataInstance::UpdateDrawPackets(bool forceUpdate /*= false*/) + void ModelDataInstance::UpdateDrawPackets(bool forceUpdate /*= false*/) { - AZ_PROFILE_SCOPE(AzRender, "MeshDataInstance:: UpdateDrawPackets"); + AZ_PROFILE_SCOPE(AzRender, "ModelDataInstance:: UpdateDrawPackets"); for (auto& drawPacketList : m_drawPacketListsByLod) { for (auto& drawPacket : drawPacketList) @@ -1045,9 +1051,9 @@ namespace AZ } } - void MeshDataInstance::BuildCullable() + void ModelDataInstance::BuildCullable() { - AZ_PROFILE_SCOPE(AzRender, "MeshDataInstance: BuildCullable"); + AZ_PROFILE_SCOPE(AzRender, "ModelDataInstance: BuildCullable"); AZ_Assert(m_cullableNeedsRebuild, "This function only needs to be called if the cullable to be rebuilt"); AZ_Assert(m_model, "The model has not finished loading yet"); @@ -1122,9 +1128,9 @@ namespace AZ m_cullBoundsNeedsUpdate = true; } - void MeshDataInstance::UpdateCullBounds(const TransformServiceFeatureProcessor* transformService) + void ModelDataInstance::UpdateCullBounds(const TransformServiceFeatureProcessor* transformService) { - AZ_PROFILE_SCOPE(AzRender, "MeshDataInstance: UpdateCullBounds"); + AZ_PROFILE_SCOPE(AzRender, "ModelDataInstance: UpdateCullBounds"); AZ_Assert(m_cullBoundsNeedsUpdate, "This function only needs to be called if the culling bounds need to be rebuilt"); AZ_Assert(m_model, "The model has not finished loading yet"); @@ -1148,70 +1154,70 @@ namespace AZ m_cullBoundsNeedsUpdate = false; } - void MeshDataInstance::UpdateObjectSrg() + void ModelDataInstance::UpdateObjectSrg() { - if (!m_shaderResourceGroup) + for (auto& objectSrg : m_objectSrgList) { - return; + ReflectionProbeFeatureProcessor* reflectionProbeFeatureProcessor = m_scene->GetFeatureProcessor(); + + if (reflectionProbeFeatureProcessor && (m_descriptor.m_useForwardPassIblSpecular || m_hasForwardPassIblSpecularMaterial)) + { + // retrieve probe constant indices + AZ::RHI::ShaderInputConstantIndex modelToWorldConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorld")); + AZ_Error("ModelDataInstance", modelToWorldConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + + AZ::RHI::ShaderInputConstantIndex modelToWorldInverseConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorldInverse")); + AZ_Error("ModelDataInstance", modelToWorldInverseConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + + AZ::RHI::ShaderInputConstantIndex outerObbHalfLengthsConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerObbHalfLengths")); + AZ_Error("ModelDataInstance", outerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + + AZ::RHI::ShaderInputConstantIndex innerObbHalfLengthsConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerObbHalfLengths")); + AZ_Error("ModelDataInstance", innerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + + AZ::RHI::ShaderInputConstantIndex useReflectionProbeConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useReflectionProbe")); + AZ_Error("ModelDataInstance", useReflectionProbeConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + + AZ::RHI::ShaderInputConstantIndex useParallaxCorrectionConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useParallaxCorrection")); + AZ_Error("ModelDataInstance", useParallaxCorrectionConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + + // retrieve probe cubemap index + Name reflectionCubeMapImageName = Name("m_reflectionProbeCubeMap"); + RHI::ShaderInputImageIndex reflectionCubeMapImageIndex = objectSrg->FindShaderInputImageIndex(reflectionCubeMapImageName); + AZ_Error("ModelDataInstance", reflectionCubeMapImageIndex.IsValid(), "Failed to find shader image index [%s]", reflectionCubeMapImageName.GetCStr()); + + // retrieve the list of probes that contain the centerpoint of the mesh + TransformServiceFeatureProcessor* transformServiceFeatureProcessor = m_scene->GetFeatureProcessor(); + Transform transform = transformServiceFeatureProcessor->GetTransformForId(m_objectId); + + ReflectionProbeFeatureProcessor::ReflectionProbeVector reflectionProbes; + reflectionProbeFeatureProcessor->FindReflectionProbes(transform.GetTranslation(), reflectionProbes); + + if (!reflectionProbes.empty() && reflectionProbes[0]) + { + objectSrg->SetConstant(modelToWorldConstantIndex, reflectionProbes[0]->GetTransform()); + objectSrg->SetConstant(modelToWorldInverseConstantIndex, Matrix3x4::CreateFromTransform(reflectionProbes[0]->GetTransform()).GetInverseFull()); + objectSrg->SetConstant(outerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetOuterObbWs().GetHalfLengths()); + objectSrg->SetConstant(innerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetInnerObbWs().GetHalfLengths()); + objectSrg->SetConstant(useReflectionProbeConstantIndex, true); + objectSrg->SetConstant(useParallaxCorrectionConstantIndex, reflectionProbes[0]->GetUseParallaxCorrection()); + + objectSrg->SetImage(reflectionCubeMapImageIndex, reflectionProbes[0]->GetCubeMapImage()); + } + else + { + objectSrg->SetConstant(useReflectionProbeConstantIndex, false); + } + } + + objectSrg->Compile(); } - ReflectionProbeFeatureProcessor* reflectionProbeFeatureProcessor = m_scene->GetFeatureProcessor(); - - if (reflectionProbeFeatureProcessor && (m_descriptor.m_useForwardPassIblSpecular || m_hasForwardPassIblSpecularMaterial)) - { - // retrieve probe constant indices - AZ::RHI::ShaderInputConstantIndex modelToWorldConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorld")); - AZ_Error("MeshDataInstance", modelToWorldConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - - AZ::RHI::ShaderInputConstantIndex modelToWorldInverseConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorldInverse")); - AZ_Error("MeshDataInstance", modelToWorldInverseConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - - AZ::RHI::ShaderInputConstantIndex outerObbHalfLengthsConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerObbHalfLengths")); - AZ_Error("MeshDataInstance", outerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - - AZ::RHI::ShaderInputConstantIndex innerObbHalfLengthsConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerObbHalfLengths")); - AZ_Error("MeshDataInstance", innerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - - AZ::RHI::ShaderInputConstantIndex useReflectionProbeConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useReflectionProbe")); - AZ_Error("MeshDataInstance", useReflectionProbeConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - - AZ::RHI::ShaderInputConstantIndex useParallaxCorrectionConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useParallaxCorrection")); - AZ_Error("MeshDataInstance", useParallaxCorrectionConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - - // retrieve probe cubemap index - Name reflectionCubeMapImageName = Name("m_reflectionProbeCubeMap"); - RHI::ShaderInputImageIndex reflectionCubeMapImageIndex = m_shaderResourceGroup->FindShaderInputImageIndex(reflectionCubeMapImageName); - AZ_Error("MeshDataInstance", reflectionCubeMapImageIndex.IsValid(), "Failed to find shader image index [%s]", reflectionCubeMapImageName.GetCStr()); - - // retrieve the list of probes that contain the centerpoint of the mesh - TransformServiceFeatureProcessor* transformServiceFeatureProcessor = m_scene->GetFeatureProcessor(); - Transform transform = transformServiceFeatureProcessor->GetTransformForId(m_objectId); - - ReflectionProbeFeatureProcessor::ReflectionProbeVector reflectionProbes; - reflectionProbeFeatureProcessor->FindReflectionProbes(transform.GetTranslation(), reflectionProbes); - - if (!reflectionProbes.empty() && reflectionProbes[0]) - { - m_shaderResourceGroup->SetConstant(modelToWorldConstantIndex, reflectionProbes[0]->GetTransform()); - m_shaderResourceGroup->SetConstant(modelToWorldInverseConstantIndex, Matrix3x4::CreateFromTransform(reflectionProbes[0]->GetTransform()).GetInverseFull()); - m_shaderResourceGroup->SetConstant(outerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetOuterObbWs().GetHalfLengths()); - m_shaderResourceGroup->SetConstant(innerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetInnerObbWs().GetHalfLengths()); - m_shaderResourceGroup->SetConstant(useReflectionProbeConstantIndex, true); - m_shaderResourceGroup->SetConstant(useParallaxCorrectionConstantIndex, reflectionProbes[0]->GetUseParallaxCorrection()); - - m_shaderResourceGroup->SetImage(reflectionCubeMapImageIndex, reflectionProbes[0]->GetCubeMapImage()); - } - else - { - m_shaderResourceGroup->SetConstant(useReflectionProbeConstantIndex, false); - } - } - - m_shaderResourceGroup->Compile(); - m_objectSrgNeedsUpdate = false; + // Set m_objectSrgNeedsUpdate to false if there are object SRGs in the list + m_objectSrgNeedsUpdate = m_objectSrgNeedsUpdate && (m_objectSrgList.size() == 0); } - bool MeshDataInstance::MaterialRequiresForwardPassIblSpecular(Data::Instance material) const + bool ModelDataInstance::MaterialRequiresForwardPassIblSpecular(Data::Instance material) const { // look for a shader that has the o_materialUseForwardPassIBLSpecular option set // Note: this should be changed to have the material automatically set the forwardPassIBLSpecular @@ -1237,7 +1243,7 @@ namespace AZ return false; } - void MeshDataInstance::SetVisible(bool isVisible) + void ModelDataInstance::SetVisible(bool isVisible) { m_visible = isVisible; m_cullable.m_isHidden = !isVisible; diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp index 4c379c4239..c135b017fa 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp @@ -95,13 +95,13 @@ namespace AZ renderProxy.m_instance->m_model->WaitForUpload(); } - //Note: we are creating pointers to the meshDataInstance cullpacket and lod packet here, + //Note: we are creating pointers to the modelDataInstance cullpacket and lod packet here, //and holding them until the skinnedMeshDispatchItems are dispatched. There is an assumption that the underlying //data will not move during this phase. - MeshDataInstance& meshDataInstance = **renderProxy.m_meshHandle; - m_workgroup.m_cullPackets.push_back(&meshDataInstance.GetCullPacket()); - m_workgroup.m_drawListMask |= meshDataInstance.GetCullPacket().m_drawListMask; - m_lodPackets.push_back(&meshDataInstance.GetLodPacket()); + ModelDataInstance& modelDataInstance = **renderProxy.m_meshHandle; + m_workgroup.m_cullPackets.push_back(&modelDataInstance.GetCullPacket()); + m_workgroup.m_drawListMask |= modelDataInstance.GetCullPacket().m_drawListMask; + m_lodPackets.push_back(&modelDataInstance.GetLodPacket()); m_potentiallyVisibleProxies.push_back(&renderProxy); } } @@ -187,8 +187,8 @@ namespace AZ renderProxy.m_instance->m_model->WaitForUpload(); } - MeshDataInstance& meshDataInstance = **renderProxy.m_meshHandle; - const RPI::Cullable& cullable = meshDataInstance.GetCullable(); + ModelDataInstance& modelDataInstance = **renderProxy.m_meshHandle; + const RPI::Cullable& cullable = modelDataInstance.GetCullable(); for (const RPI::ViewPtr& viewPtr : packet.m_views) { diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index a3161002a0..7cd4fc073b 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -880,12 +880,14 @@ namespace AZ { if (m_meshHandle) { - Data::Instance wrinkleMaskObjectSrg = m_meshFeatureProcessor->GetObjectSrg(*m_meshHandle); - if (wrinkleMaskObjectSrg) + AZStd::vector>& wrinkleMaskObjectSrgs = m_meshFeatureProcessor->GetObjectSrgs(*m_meshHandle); + + for (auto& wrinkleMaskObjectSrg : wrinkleMaskObjectSrgs) { RHI::ShaderInputImageIndex wrinkleMasksIndex = wrinkleMaskObjectSrg->FindShaderInputImageIndex(Name{ "m_wrinkle_masks" }); RHI::ShaderInputConstantIndex wrinkleMaskWeightsIndex = wrinkleMaskObjectSrg->FindShaderInputConstantIndex(Name{ "m_wrinkle_mask_weights" }); RHI::ShaderInputConstantIndex wrinkleMaskCountIndex = wrinkleMaskObjectSrg->FindShaderInputConstantIndex(Name{ "m_wrinkle_mask_count" }); + if (wrinkleMasksIndex.IsValid() || wrinkleMaskWeightsIndex.IsValid() || wrinkleMaskCountIndex.IsValid()) { AZ_Error("AtomActorInstance", wrinkleMasksIndex.IsValid(), "m_wrinkle_masks not found on the ObjectSrg, but m_wrinkle_mask_weights and/or m_wrinkle_mask_count are being used."); From 1f72001cdb2bc03967e4680c3c9671018f98f09f Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Wed, 10 Nov 2021 00:56:25 -0800 Subject: [PATCH 14/97] Added two missing MeshDataInstance to ModelDataInstance renames in error message Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 49fe4cf093..7227311915 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -1182,12 +1182,12 @@ namespace AZ AZ_Error("ModelDataInstance", useParallaxCorrectionConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); AZ::RHI::ShaderInputConstantIndex exposureConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_exposure")); - AZ_Error("MeshDataInstance", exposureConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + AZ_Error("ModelDataInstance", exposureConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); // retrieve probe cubemap index Name reflectionCubeMapImageName = Name("m_reflectionProbeCubeMap"); RHI::ShaderInputImageIndex reflectionCubeMapImageIndex = objectSrg->FindShaderInputImageIndex(reflectionCubeMapImageName); - AZ_Error("MeshDataInstance", reflectionCubeMapImageIndex.IsValid(), "Failed to find shader image index [%s]", reflectionCubeMapImageName.GetCStr()); + AZ_Error("ModelDataInstance", reflectionCubeMapImageIndex.IsValid(), "Failed to find shader image index [%s]", reflectionCubeMapImageName.GetCStr()); // retrieve the list of probes that contain the centerpoint of the mesh TransformServiceFeatureProcessor* transformServiceFeatureProcessor = m_scene->GetFeatureProcessor(); From 847e13154f2b95947561b07ad00b8420764916de Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Wed, 10 Nov 2021 09:55:49 -0600 Subject: [PATCH 15/97] Updated some Script Canvas node slot names to EntityID for consistency. Signed-off-by: Chris Galvan --- Assets/Editor/Translation/scriptcanvas_en_us.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Assets/Editor/Translation/scriptcanvas_en_us.ts b/Assets/Editor/Translation/scriptcanvas_en_us.ts index 7b8361c879..6d436b7caf 100644 --- a/Assets/Editor/Translation/scriptcanvas_en_us.ts +++ b/Assets/Editor/Translation/scriptcanvas_en_us.ts @@ -62164,7 +62164,7 @@ An Entity can be selected by using the pick button, or by dragging an Entity fro HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_NAME Simple Type: EntityID C++ Type: const EntityId& - Entity + EntityID HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_TOOLTIP @@ -62202,7 +62202,7 @@ An Entity can be selected by using the pick button, or by dragging an Entity fro HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_NAME Simple Type: EntityID C++ Type: const EntityId& - Entity + EntityId HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_TOOLTIP @@ -81852,7 +81852,7 @@ The element is removed from its current parent and added as a child of the new p HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_NAME Simple Type: EntityID C++ Type: const EntityId& - Entity + EntityID HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_TOOLTIP @@ -89198,7 +89198,7 @@ The element is removed from its current parent and added as a child of the new p HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_NAME Simple Type: EntityID C++ Type: const EntityId& - Entity + EntityID HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_TOOLTIP @@ -89236,7 +89236,7 @@ The element is removed from its current parent and added as a child of the new p HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_NAME Simple Type: EntityID C++ Type: const EntityId& - Entity + EntityID HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_TOOLTIP From 0102894a8309bf42ed165571d43902c0439a62cd Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Wed, 10 Nov 2021 08:44:24 -0800 Subject: [PATCH 16/97] Handle servers with no content length and make downloading more obvious Signed-off-by: AMZN-Phil --- .../Resources/ProjectManager.qrc | 1 + .../ProjectManager/Resources/checkmark.svg | 12 +++ .../Source/DownloadController.cpp | 7 +- .../Source/DownloadController.h | 6 +- .../ProjectManager/Source/DownloadWorker.cpp | 5 +- .../ProjectManager/Source/DownloadWorker.h | 3 +- .../GemCatalog/GemCatalogHeaderWidget.cpp | 80 +++++++++++++++---- .../GemCatalog/GemCatalogHeaderWidget.h | 13 ++- .../Source/GemCatalog/GemCatalogScreen.cpp | 10 ++- .../Source/GemCatalog/GemInfo.h | 4 +- .../Source/GemCatalog/GemItemDelegate.cpp | 10 +++ .../Source/GemCatalog/GemItemDelegate.h | 2 + .../ProjectManager/Source/PythonBindings.cpp | 6 +- .../ProjectManager/Source/PythonBindings.h | 2 +- .../Source/PythonBindingsInterface.h | 2 +- scripts/o3de/o3de/download.py | 2 +- scripts/o3de/o3de/utils.py | 12 +-- 17 files changed, 133 insertions(+), 44 deletions(-) create mode 100644 Code/Tools/ProjectManager/Resources/checkmark.svg diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qrc b/Code/Tools/ProjectManager/Resources/ProjectManager.qrc index 8dd7e4c9b5..2260ae62b9 100644 --- a/Code/Tools/ProjectManager/Resources/ProjectManager.qrc +++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qrc @@ -41,5 +41,6 @@ Download.svg in_progress.gif gem.svg + checkmark.svg diff --git a/Code/Tools/ProjectManager/Resources/checkmark.svg b/Code/Tools/ProjectManager/Resources/checkmark.svg new file mode 100644 index 0000000000..d612b35370 --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/checkmark.svg @@ -0,0 +1,12 @@ + + + Icons / Hub / Download Copy 5 + + + + + + + + + diff --git a/Code/Tools/ProjectManager/Source/DownloadController.cpp b/Code/Tools/ProjectManager/Source/DownloadController.cpp index 6326b2fc11..06e51b5116 100644 --- a/Code/Tools/ProjectManager/Source/DownloadController.cpp +++ b/Code/Tools/ProjectManager/Source/DownloadController.cpp @@ -18,7 +18,6 @@ namespace O3DE::ProjectManager { DownloadController::DownloadController(QWidget* parent) : QObject() - , m_lastProgress(0) , m_parent(parent) { m_worker = new DownloadWorker(); @@ -69,10 +68,9 @@ namespace O3DE::ProjectManager } } - void DownloadController::UpdateUIProgress(int progress) + void DownloadController::UpdateUIProgress(int bytesDownloaded, int totalBytes) { - m_lastProgress = progress; - emit GemDownloadProgress(m_gemNames.front(), progress); + emit GemDownloadProgress(m_gemNames.front(), bytesDownloaded, totalBytes); } void DownloadController::HandleResults(const QString& result) @@ -88,6 +86,7 @@ namespace O3DE::ProjectManager QString gemName = m_gemNames.front(); m_gemNames.erase(m_gemNames.begin()); emit Done(gemName, succeeded); + emit GemDownloadRemoved(gemName); if (!m_gemNames.empty()) { diff --git a/Code/Tools/ProjectManager/Source/DownloadController.h b/Code/Tools/ProjectManager/Source/DownloadController.h index 0bf0ae473c..211d9b48bc 100644 --- a/Code/Tools/ProjectManager/Source/DownloadController.h +++ b/Code/Tools/ProjectManager/Source/DownloadController.h @@ -53,7 +53,7 @@ namespace O3DE::ProjectManager } } public slots: - void UpdateUIProgress(int progress); + void UpdateUIProgress(int bytesDownloaded, int totalBytes); void HandleResults(const QString& result); signals: @@ -61,14 +61,12 @@ namespace O3DE::ProjectManager void Done(const QString& gemName, bool success = true); void GemDownloadAdded(const QString& gemName); void GemDownloadRemoved(const QString& gemName); - void GemDownloadProgress(const QString& gemName, int percentage); + void GemDownloadProgress(const QString& gemName, int bytesDownloaded, int totalBytes); private: DownloadWorker* m_worker; QThread m_workerThread; QWidget* m_parent; AZStd::vector m_gemNames; - - int m_lastProgress; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/DownloadWorker.cpp b/Code/Tools/ProjectManager/Source/DownloadWorker.cpp index 9bda1b34cc..169b276284 100644 --- a/Code/Tools/ProjectManager/Source/DownloadWorker.cpp +++ b/Code/Tools/ProjectManager/Source/DownloadWorker.cpp @@ -20,10 +20,9 @@ namespace O3DE::ProjectManager void DownloadWorker::StartDownload() { - auto gemDownloadProgress = [=](int downloadProgress) + auto gemDownloadProgress = [=](int bytesDownloaded, int totalBytes) { - m_downloadProgress = downloadProgress; - emit UpdateProgress(downloadProgress); + emit UpdateProgress(bytesDownloaded, totalBytes); }; AZ::Outcome gemInfoResult = PythonBindingsInterface::Get()->DownloadGem(m_gemName, gemDownloadProgress); if (gemInfoResult.IsSuccess()) diff --git a/Code/Tools/ProjectManager/Source/DownloadWorker.h b/Code/Tools/ProjectManager/Source/DownloadWorker.h index 316a730a78..4084080ff7 100644 --- a/Code/Tools/ProjectManager/Source/DownloadWorker.h +++ b/Code/Tools/ProjectManager/Source/DownloadWorker.h @@ -31,12 +31,11 @@ namespace O3DE::ProjectManager void SetGemToDownload(const QString& gemName, bool downloadNow = true); signals: - void UpdateProgress(int progress); + void UpdateProgress(int bytesDownloaded, int totalBytes); void Done(QString result = ""); private: QString m_gemName; - int m_downloadProgress; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp index bd0a6e9bc3..23c060e343 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include namespace O3DE::ProjectManager { @@ -224,7 +226,6 @@ namespace O3DE::ProjectManager connect(m_downloadController, &DownloadController::GemDownloadAdded, this, &CartOverlayWidget::GemDownloadAdded); connect(m_downloadController, &DownloadController::GemDownloadRemoved, this, &CartOverlayWidget::GemDownloadRemoved); connect(m_downloadController, &DownloadController::GemDownloadProgress, this, &CartOverlayWidget::GemDownloadProgress); - connect(m_downloadController, &DownloadController::Done, this, &CartOverlayWidget::GemDownloadComplete); } void CartOverlayWidget::GemDownloadAdded(const QString& gemName) @@ -288,29 +289,40 @@ namespace O3DE::ProjectManager } } - void CartOverlayWidget::GemDownloadProgress(const QString& gemName, int percentage) + void CartOverlayWidget::GemDownloadProgress(const QString& gemName, int bytesDownloaded, int totalBytes) { QWidget* gemToUpdate = m_downloadingListWidget->findChild(gemName); if (gemToUpdate) { QLabel* progressLabel = gemToUpdate->findChild("DownloadProgressLabel"); - if (progressLabel) - { - progressLabel->setText(QString("%1%").arg(percentage)); - } QProgressBar* progressBar = gemToUpdate->findChild("DownloadProgressBar"); - if (progressBar) + + if (totalBytes != 0) { - progressBar->setValue(percentage); + int downloadPercentage = static_cast((bytesDownloaded / static_cast(totalBytes)) * 100); + if (progressLabel) + { + progressLabel->setText(QString("%1%").arg(downloadPercentage)); + } + if (progressBar) + { + progressBar->setValue(downloadPercentage); + } + } + else + { + if (progressLabel) + { + progressLabel->setText(QLocale::system().formattedDataSize(bytesDownloaded)); + } + if (progressBar) + { + progressBar->setRange(0, 0); + } } } } - void CartOverlayWidget::GemDownloadComplete(const QString& gemName, bool /*success*/) - { - GemDownloadRemoved(gemName); // update the list to remove the gem that has finished - } - QVector CartOverlayWidget::GetTagsFromModelIndices(const QVector& gems) const { QVector tags; @@ -430,6 +442,7 @@ namespace O3DE::ProjectManager GemCatalogHeaderWidget::GemCatalogHeaderWidget(GemModel* gemModel, GemSortFilterProxyModel* filterProxyModel, DownloadController* downloadController, QWidget* parent) : QFrame(parent) + , m_downloadController(downloadController) { QHBoxLayout* hLayout = new QHBoxLayout(); hLayout->setAlignment(Qt::AlignLeft); @@ -456,8 +469,25 @@ namespace O3DE::ProjectManager hLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding)); hLayout->addSpacerItem(new QSpacerItem(75, 0, QSizePolicy::Fixed)); - CartButton* cartButton = new CartButton(gemModel, downloadController); - hLayout->addWidget(cartButton); + // spinner + m_downloadSpinnerMovie = new QMovie(":/in_progress.gif"); + m_downloadSpinner = new QLabel(this); + m_downloadSpinner->setScaledContents(true); + m_downloadSpinner->setMaximumSize(16, 16); + m_downloadSpinner->setMovie(m_downloadSpinnerMovie); + hLayout->addWidget(m_downloadSpinner); + hLayout->addSpacing(8); + + // downloading label + m_downloadLabel = new QLabel(tr("Downloading")); + hLayout->addWidget(m_downloadLabel); + m_downloadSpinner->hide(); + m_downloadLabel->hide(); + + hLayout->addSpacing(16); + + m_cartButton = new CartButton(gemModel, downloadController); + hLayout->addWidget(m_cartButton); hLayout->addSpacing(16); // Separating line @@ -479,6 +509,26 @@ namespace O3DE::ProjectManager gemMenuButton->setIcon(QIcon(":/menu.svg")); gemMenuButton->setIconSize(QSize(36, 24)); hLayout->addWidget(gemMenuButton); + + connect(m_downloadController, &DownloadController::GemDownloadAdded, this, &GemCatalogHeaderWidget::GemDownloadAdded); + connect(m_downloadController, &DownloadController::GemDownloadRemoved, this, &GemCatalogHeaderWidget::GemDownloadRemoved); + } + + void GemCatalogHeaderWidget::GemDownloadAdded(const QString& /*gemName*/) + { + m_downloadSpinner->show(); + m_downloadLabel->show(); + m_downloadSpinnerMovie->start(); + } + + void GemCatalogHeaderWidget::GemDownloadRemoved(const QString& /*gemName*/) + { + if (m_downloadController->IsDownloadQueueEmpty()) + { + m_downloadSpinner->hide(); + m_downloadLabel->hide(); + m_downloadSpinnerMovie->stop(); + } } void GemCatalogHeaderWidget::ReinitForProject() diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h index f3242d6db7..788e67a545 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h @@ -24,6 +24,7 @@ QT_FORWARD_DECLARE_CLASS(QVBoxLayout) QT_FORWARD_DECLARE_CLASS(QHBoxLayout) QT_FORWARD_DECLARE_CLASS(QHideEvent) QT_FORWARD_DECLARE_CLASS(QMoveEvent) +QT_FORWARD_DECLARE_CLASS(QMovie) namespace O3DE::ProjectManager { @@ -39,8 +40,7 @@ namespace O3DE::ProjectManager public slots: void GemDownloadAdded(const QString& gemName); void GemDownloadRemoved(const QString& gemName); - void GemDownloadProgress(const QString& gemName, int percentage); - void GemDownloadComplete(const QString& gemName, bool success); + void GemDownloadProgress(const QString& gemName, int bytesDownloaded, int totalBytes); private: QVector GetTagsFromModelIndices(const QVector& gems) const; @@ -96,6 +96,10 @@ namespace O3DE::ProjectManager void ReinitForProject(); + public slots: + void GemDownloadAdded(const QString& gemName); + void GemDownloadRemoved(const QString& gemName); + signals: void AddGem(); void OpenGemsRepo(); @@ -103,5 +107,10 @@ namespace O3DE::ProjectManager private: AzQtComponents::SearchLineEdit* m_filterLineEdit = nullptr; inline constexpr static int s_height = 60; + DownloadController* m_downloadController = nullptr; + QLabel* m_downloadSpinner = nullptr; + QLabel* m_downloadLabel = nullptr; + QMovie* m_downloadSpinnerMovie = nullptr; + CartButton* m_cartButton = nullptr; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 732f4813a2..0c342e12b3 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -483,7 +483,7 @@ namespace O3DE::ProjectManager QModelIndex index = m_gemModel->FindIndexByNameString(gemName); if (index.isValid()) { - m_gemModel->setData(index, GemInfo::Downloaded, GemModel::RoleDownloadStatus); + m_proxyModel->setData(m_proxyModel->mapFromSource(index), GemInfo::DownloadSuccessful, GemModel::RoleDownloadStatus); m_gemModel->setData(index, gemInfo.m_path, GemModel::RolePath); m_gemModel->setData(index, gemInfo.m_path, GemModel::RoleDirectoryLink); } @@ -493,6 +493,14 @@ namespace O3DE::ProjectManager } } } + else + { + QModelIndex index = m_gemModel->FindIndexByNameString(gemName); + if (index.isValid()) + { + m_proxyModel->setData(m_proxyModel->mapFromSource(index), GemInfo::DownloadFailed, GemModel::RoleDownloadStatus); + } + } } ProjectManagerScreen GemCatalogScreen::GetScreenEnum() diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h index 12cce5a4ea..abd0062749 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h @@ -57,7 +57,9 @@ namespace O3DE::ProjectManager UnknownDownloadStatus = -1, NotDownloaded, Downloading, - Downloaded, + DownloadSuccessful, + DownloadFailed, + Downloaded }; static QString GetDownloadStatusString(DownloadStatus status); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp index e15c4b3b39..dd94e42fc4 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp @@ -37,6 +37,8 @@ namespace O3DE::ProjectManager SetStatusIcon(m_notDownloadedPixmap, ":/Download.svg"); SetStatusIcon(m_unknownStatusPixmap, ":/X.svg"); + SetStatusIcon(m_downloadSuccessfulPixmap, ":/checkmark.svg"); + SetStatusIcon(m_downloadFailedPixmap, ":/Warning.svg"); m_downloadingMovie = new QMovie(":/in_progress.gif"); } @@ -480,6 +482,14 @@ namespace O3DE::ProjectManager currentFrame = currentFrame.scaled(s_statusIconSize, s_statusIconSize); statusPixmap = ¤tFrame; } + else if (downloadStatus == GemInfo::DownloadStatus::DownloadSuccessful) + { + statusPixmap = &m_downloadSuccessfulPixmap; + } + else if (downloadStatus == GemInfo::DownloadStatus::DownloadFailed) + { + statusPixmap = &m_downloadFailedPixmap; + } else if (downloadStatus == GemInfo::DownloadStatus::NotDownloaded) { statusPixmap = &m_notDownloadedPixmap; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h index c013be0d9e..107de6de15 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h @@ -97,6 +97,8 @@ namespace O3DE::ProjectManager QPixmap m_unknownStatusPixmap; QPixmap m_notDownloadedPixmap; + QPixmap m_downloadSuccessfulPixmap; + QPixmap m_downloadFailedPixmap; QMovie* m_downloadingMovie = nullptr; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 021066e1c7..b1cbc1a2a3 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -1166,7 +1166,7 @@ namespace O3DE::ProjectManager return AZ::Success(AZStd::move(gemRepos)); } - AZ::Outcome PythonBindings::DownloadGem(const QString& gemName, std::function gemProgressCallback) + AZ::Outcome PythonBindings::DownloadGem(const QString& gemName, std::function gemProgressCallback) { // This process is currently limited to download a single gem at a time. bool downloadSucceeded = false; @@ -1181,9 +1181,9 @@ namespace O3DE::ProjectManager false, // skip auto register false, // force pybind11::cpp_function( - [this, gemProgressCallback](int progress) + [this, gemProgressCallback](int bytesDownloaded, int totalBytes) { - gemProgressCallback(progress); + gemProgressCallback(bytesDownloaded, totalBytes); return m_requestCancelDownload; }) // Callback for download progress and cancelling diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.h b/Code/Tools/ProjectManager/Source/PythonBindings.h index 4375d56d02..4aae1c2e95 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.h +++ b/Code/Tools/ProjectManager/Source/PythonBindings.h @@ -64,7 +64,7 @@ namespace O3DE::ProjectManager bool AddGemRepo(const QString& repoUri) override; bool RemoveGemRepo(const QString& repoUri) override; AZ::Outcome, AZStd::string> GetAllGemRepoInfos() override; - AZ::Outcome DownloadGem(const QString& gemName, std::function gemProgressCallback) override; + AZ::Outcome DownloadGem(const QString& gemName, std::function gemProgressCallback) override; void CancelDownload() override; AZ::Outcome, AZStd::string> GetAllGemRepoGemsInfos() override; diff --git a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h index 1134804f1f..b5ff86af2d 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h +++ b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h @@ -215,7 +215,7 @@ namespace O3DE::ProjectManager * @param gemProgressCallback a callback function that is called with an int percentage download value * @return an outcome with a string error message on failure. */ - virtual AZ::Outcome DownloadGem(const QString& gemName, std::function gemProgressCallback) = 0; + virtual AZ::Outcome DownloadGem(const QString& gemName, std::function gemProgressCallback) = 0; /** * Cancels the current download. diff --git a/scripts/o3de/o3de/download.py b/scripts/o3de/o3de/download.py index 9e576d64b5..9b7c8cc782 100644 --- a/scripts/o3de/o3de/download.py +++ b/scripts/o3de/o3de/download.py @@ -105,7 +105,7 @@ def download_o3de_object(object_name: str, default_folder_name: str, dest_path: origin_uri = downloadable_object_data['originuri'] parsed_uri = urllib.parse.urlparse(origin_uri) - download_zip_result = utils.download_zip_file(parsed_uri, download_zip_path, download_progress_callback) + download_zip_result = utils.download_zip_file(parsed_uri, download_zip_path, force_overwrite, download_progress_callback) if download_zip_result != 0: return download_zip_result diff --git a/scripts/o3de/o3de/utils.py b/scripts/o3de/o3de/utils.py index 56f9ae4bcd..0195b9905e 100755 --- a/scripts/o3de/o3de/utils.py +++ b/scripts/o3de/o3de/utils.py @@ -117,7 +117,7 @@ def backup_folder(folder: str or pathlib.Path) -> None: if backup_folder_name.is_dir(): renamed = True -def download_file(parsed_uri, download_path: pathlib.Path, force_overwrite, download_progress_callback = None) -> int: +def download_file(parsed_uri, download_path: pathlib.Path, force_overwrite: bool = False, download_progress_callback = None) -> int: """ :param parsed_uri: uniform resource identifier to zip file to download :param download_path: location path on disk to download file @@ -140,9 +140,9 @@ def download_file(parsed_uri, download_path: pathlib.Path, force_overwrite, down download_file_size = s.headers['content-length'] except KeyError: pass - def download_progress(blocks): - if download_progress_callback and download_file_size: - return download_progress_callback(int(blocks/int(download_file_size) * 100)) + def download_progress(downloaded_bytes): + if download_progress_callback: + return download_progress_callback(int(downloaded_bytes), int(download_file_size)) return False with download_path.open('wb') as f: download_cancelled = copyfileobj(s, f, download_progress) @@ -157,12 +157,12 @@ def download_file(parsed_uri, download_path: pathlib.Path, force_overwrite, down return 0 -def download_zip_file(parsed_uri, download_zip_path: pathlib.Path, download_progress_callback = None) -> int: +def download_zip_file(parsed_uri, download_zip_path: pathlib.Path, force_overwrite: bool, download_progress_callback = None) -> int: """ :param parsed_uri: uniform resource identifier to zip file to download :param download_zip_path: path to output zip file """ - download_file_result = download_file(parsed_uri, download_zip_path, download_progress_callback) + download_file_result = download_file(parsed_uri, download_zip_path, force_overwrite, download_progress_callback) if download_file_result != 0: return download_file_result From f0b4eb17127534ca0919cb9eb372439e2739f5de Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 10 Nov 2021 10:54:53 -0600 Subject: [PATCH 17/97] update comment and error message Signed-off-by: Guthrie Adams --- .../RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp | 5 ++++- .../RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp index 37bd5a19f2..14ef3bb17d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp @@ -137,7 +137,10 @@ namespace AZ } else if (!m_luaSourceFile.empty()) { - auto loadOutcome = RPI::AssetUtils::LoadAsset(materialTypeSourceFilePath, m_luaSourceFile, ScriptAsset::CompiledAssetSubId); + // The sub ID for script assets must be explicit. + // LUA source files output a compiled as well as an uncompiled asset, sub Ids of 1 and 2. + auto loadOutcome = + RPI::AssetUtils::LoadAsset(materialTypeSourceFilePath, m_luaSourceFile, ScriptAsset::CompiledAssetSubId); if (!loadOutcome) { AZ_Error("LuaMaterialFunctorSourceData", false, "Could not load script file '%s'", m_luaSourceFile.c_str()); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index e5466a173f..d6308ec655 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -250,7 +250,7 @@ namespace AZ const auto parentTypeAssetId = AssetUtils::MakeAssetId(parentSourceAbsPath, parentSourceData.m_materialType, 0); if (!parentTypeAssetId) { - AZ_Error("MaterialSourceData", false, "Parent material asset ID isn't valid: '%s'.", parentSourceAbsPath.c_str()); + AZ_Error("MaterialSourceData", false, "Parent material asset ID wasn't found: '%s'.", parentSourceAbsPath.c_str()); return Failure(); } From 7159e3fe575378254983e09dabe44a9ef52e53c7 Mon Sep 17 00:00:00 2001 From: sphrose <82213493+sphrose@users.noreply.github.com> Date: Wed, 10 Nov 2021 17:22:55 +0000 Subject: [PATCH 18/97] Moving to stabilization Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> --- Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp | 162 +++++++++--------- 1 file changed, 82 insertions(+), 80 deletions(-) diff --git a/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp b/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp index 3778ba860f..9de441eecf 100644 --- a/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp +++ b/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp @@ -6,15 +6,13 @@ * */ +#include + #include #include #include -#include - #include -#include -#include #include #include @@ -23,21 +21,12 @@ using ::testing::NiceMock; using ::testing::AtLeast; using ::testing::_; -using ::testing::NiceMock; -using ::testing::AtLeast; -using ::testing::_; - class LayerSpawnerComponentTest : public ::testing::Test { protected: AZ::ComponentApplication m_app; - AZStd::unique_ptr m_entity; - Terrain::TerrainLayerSpawnerComponent* m_layerSpawnerComponent; - UnitTest::MockAxisAlignedBoxShapeComponent* m_shapeComponent; - AZStd::unique_ptr> m_terrainSystem; - void SetUp() override { AZ::ComponentApplication::Descriptor appDesc; @@ -50,78 +39,86 @@ protected: void TearDown() override { - m_entity.reset(); - m_terrainSystem.reset(); m_app.Destroy(); } - void CreateEntity() + AZStd::unique_ptr CreateEntity() { - m_entity = AZStd::make_unique(); - m_entity->Init(); + auto entity = AZStd::make_unique(); + entity->Init(); - ASSERT_TRUE(m_entity); + return entity; } - void AddLayerSpawnerAndShapeComponentToEntity() + Terrain::TerrainLayerSpawnerComponent* AddLayerSpawnerToEntity(AZ::Entity* entity, const Terrain::TerrainLayerSpawnerConfig& config) { - AddLayerSpawnerAndShapeComponentToEntity(Terrain::TerrainLayerSpawnerConfig()); + auto layerSpawnerComponent = entity->CreateComponent(config); + m_app.RegisterComponentDescriptor(layerSpawnerComponent->CreateDescriptor()); + + return layerSpawnerComponent; } - void AddLayerSpawnerAndShapeComponentToEntity(const Terrain::TerrainLayerSpawnerConfig& config) + UnitTest::MockAxisAlignedBoxShapeComponent* AddShapeComponentToEntity(AZ::Entity* entity) { - m_layerSpawnerComponent = m_entity->CreateComponent(config); - m_app.RegisterComponentDescriptor(m_layerSpawnerComponent->CreateDescriptor()); + UnitTest::MockAxisAlignedBoxShapeComponent* shapeComponent = entity->CreateComponent(); + m_app.RegisterComponentDescriptor(shapeComponent->CreateDescriptor()); - m_shapeComponent = m_entity->CreateComponent(); - m_app.RegisterComponentDescriptor(m_shapeComponent->CreateDescriptor()); - - ASSERT_TRUE(m_layerSpawnerComponent); - ASSERT_TRUE(m_shapeComponent); - } - - void CreateMockTerrainSystem() - { - m_terrainSystem = AZStd::make_unique>(); + return shapeComponent; } }; -TEST_F(LayerSpawnerComponentTest, ActivatEntityActivateSuccess) +TEST_F(LayerSpawnerComponentTest, ActivateEntityWithoutShapeFails) { - CreateEntity(); - AddLayerSpawnerAndShapeComponentToEntity(); + auto entity = CreateEntity(); - m_entity->Activate(); - EXPECT_EQ(m_entity->GetState(), AZ::Entity::State::Active); - - m_entity->Deactivate(); + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + + const AZ::Entity::DependencySortOutcome sortOutcome = entity->EvaluateDependenciesGetDetails(); + EXPECT_FALSE(sortOutcome.IsSuccess()); + + entity.reset(); +} + +TEST_F(LayerSpawnerComponentTest, ActivateEntityActivateSuccess) +{ + auto entity = CreateEntity(); + + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + AddShapeComponentToEntity(entity.get()); + + entity->Activate(); + EXPECT_EQ(entity->GetState(), AZ::Entity::State::Active); + + entity.reset(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerDefaultValuesCorrect) { - CreateEntity(); - AddLayerSpawnerAndShapeComponentToEntity(); + auto entity = CreateEntity(); + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + AddShapeComponentToEntity(entity.get()); - m_entity->Activate(); + entity->Activate(); AZ::u32 priority = 999, layer = 999; - Terrain::TerrainSpawnerRequestBus::Event(m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority); + Terrain::TerrainSpawnerRequestBus::Event(entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority); EXPECT_EQ(0, priority); EXPECT_EQ(1, layer); bool useGroundPlane = false; - Terrain::TerrainSpawnerRequestBus::EventResult(useGroundPlane, m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane); + Terrain::TerrainSpawnerRequestBus::EventResult( + useGroundPlane, entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane); EXPECT_TRUE(useGroundPlane); - m_entity->Deactivate(); + entity.reset(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerConfigValuesCorrect) { - CreateEntity(); + auto entity = CreateEntity(); constexpr static AZ::u32 testPriority = 15; constexpr static AZ::u32 testLayer = 0; @@ -131,12 +128,13 @@ TEST_F(LayerSpawnerComponentTest, LayerSpawnerConfigValuesCorrect) config.m_priority = testPriority; config.m_useGroundPlane = false; - AddLayerSpawnerAndShapeComponentToEntity(config); + AddLayerSpawnerToEntity(entity.get(), config); + AddShapeComponentToEntity(entity.get()); - m_entity->Activate(); + entity->Activate(); AZ::u32 priority = 999, layer = 999; - Terrain::TerrainSpawnerRequestBus::Event(m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority); + Terrain::TerrainSpawnerRequestBus::Event(entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority); EXPECT_EQ(testPriority, priority); EXPECT_EQ(testLayer, layer); @@ -144,82 +142,86 @@ TEST_F(LayerSpawnerComponentTest, LayerSpawnerConfigValuesCorrect) bool useGroundPlane = true; Terrain::TerrainSpawnerRequestBus::EventResult( - useGroundPlane, m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane); + useGroundPlane, entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane); EXPECT_FALSE(useGroundPlane); - m_entity->Deactivate(); + entity.reset(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerRegisterAreaUpdatesTerrainSystem) { - CreateEntity(); + auto entity = CreateEntity(); - CreateMockTerrainSystem(); + NiceMock terrainSystem; // The Activate call should register the area. - EXPECT_CALL(*m_terrainSystem, RegisterArea(_)).Times(1); + EXPECT_CALL(terrainSystem, RegisterArea(_)).Times(1); - AddLayerSpawnerAndShapeComponentToEntity(); + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + AddShapeComponentToEntity(entity.get()); - m_entity->Activate(); + entity->Activate(); - m_entity->Deactivate(); + entity.reset(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerUnregisterAreaUpdatesTerrainSystem) { - CreateEntity(); + auto entity = CreateEntity(); - CreateMockTerrainSystem(); + NiceMock terrainSystem; // The Deactivate call should unregister the area. - EXPECT_CALL(*m_terrainSystem, UnregisterArea(_)).Times(1); + EXPECT_CALL(terrainSystem, UnregisterArea(_)).Times(1); - AddLayerSpawnerAndShapeComponentToEntity(); + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + AddShapeComponentToEntity(entity.get()); - m_entity->Activate(); + entity->Activate(); - m_entity->Deactivate(); + entity.reset(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerTransformChangedUpdatesTerrainSystem) { - CreateEntity(); + auto entity = CreateEntity(); - CreateMockTerrainSystem(); + NiceMock terrainSystem; // The TransformChanged call should refresh the area. - EXPECT_CALL(*m_terrainSystem, RefreshArea(_, _)).Times(1); + EXPECT_CALL(terrainSystem, RefreshArea(_, _)).Times(1); - AddLayerSpawnerAndShapeComponentToEntity(); + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + AddShapeComponentToEntity(entity.get()); - m_entity->Activate(); + entity->Activate(); // The component gets transform change notifications via the shape bus. LmbrCentral::ShapeComponentNotificationsBus::Event( - m_entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged, + entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged, LmbrCentral::ShapeComponentNotifications::ShapeChangeReasons::TransformChanged); - m_entity->Deactivate(); + entity.reset(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerShapeChangedUpdatesTerrainSystem) { - CreateEntity(); + auto entity = CreateEntity(); - CreateMockTerrainSystem(); + NiceMock terrainSystem; // The ShapeChanged call should refresh the area. - EXPECT_CALL(*m_terrainSystem, RefreshArea(_, _)).Times(1); + EXPECT_CALL(terrainSystem, RefreshArea(_, _)).Times(1); - AddLayerSpawnerAndShapeComponentToEntity(); + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + AddShapeComponentToEntity(entity.get()); - m_entity->Activate(); + entity->Activate(); - LmbrCentral::ShapeComponentNotificationsBus::Event( - m_entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged, + LmbrCentral::ShapeComponentNotificationsBus::Event( + entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged, LmbrCentral::ShapeComponentNotifications::ShapeChangeReasons::ShapeChanged); - m_entity->Deactivate(); + entity.reset(); } From 0c546828d642b5a71e2762a8dbe419acbf3a3400 Mon Sep 17 00:00:00 2001 From: SJ Date: Wed, 10 Nov 2021 09:31:59 -0800 Subject: [PATCH 19/97] 1. Add nullptr checks to prevent crashes when non-critical shaders fail to compile. (#5451) 2. Add a higher "launch_ap_timeout" for Mac because launching a newly built/downloaded AP can take a while. Signed-off-by: amzn-sj --- .../PostProcessing/BlendColorGradingLutsPass.cpp | 6 +++++- .../ReflectionProbeFeatureProcessor.cpp | 7 ++++++- .../RPI.Public/Pass/FullscreenTrianglePass.cpp | 6 ++++++ Registry/Platform/Mac/bootstrap_overrides.setreg | 12 ++++++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 Registry/Platform/Mac/bootstrap_overrides.setreg diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp index f74837bd9a..ca93898d5e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp @@ -46,7 +46,11 @@ namespace AZ void BlendColorGradingLutsPass::InitializeShaderVariant() { - AZ_Assert(m_shader != nullptr, "BlendColorGradingLutsPass %s has a null shader when calling InitializeShaderVariant.", GetPathName().GetCStr()); + if (m_shader == nullptr) + { + AZ_Assert(false, "BlendColorGradingLutsPass %s has a null shader when calling InitializeShaderVariant.", GetPathName().GetCStr()); + return; + } // Total variations is MaxBlendLuts plus one for the fallback case that none of the LUTs are found, // and hence zero LUTs are blended resulting in an identity LUT. diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index b1484ac8a8..e9038858ad 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -443,7 +443,12 @@ namespace AZ { // load shader shader = RPI::LoadCriticalShader(filePath); - AZ_Error("ReflectionProbeFeatureProcessor", shader, "Failed to find asset for shader [%s]", filePath); + + if (shader == nullptr) + { + AZ_Error("ReflectionProbeFeatureProcessor", false, "Failed to find asset for shader [%s]", filePath); + return; + } // store drawlist tag drawListTag = shader->GetDrawListTag(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp index 40dce7d138..828966f377 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp @@ -136,6 +136,12 @@ namespace AZ RHI::DrawLinear draw = RHI::DrawLinear(); draw.m_vertexCount = 3; + if (m_shader == nullptr) + { + AZ_Error("PassSystem", false, "[FullscreenTrianglePass]: Shader not loaded!"); + return; + } + RHI::PipelineStateDescriptorForDraw pipelineStateDescriptor; // [GFX TODO][ATOM-872] The pass should be able to drive the shader variant diff --git a/Registry/Platform/Mac/bootstrap_overrides.setreg b/Registry/Platform/Mac/bootstrap_overrides.setreg new file mode 100644 index 0000000000..4e1ca76724 --- /dev/null +++ b/Registry/Platform/Mac/bootstrap_overrides.setreg @@ -0,0 +1,12 @@ +{ + "Amazon": { + "AzCore": { + "Bootstrap": { + // The first time an application is launched on MacOS, each + // dynamic library is inspected by the OS before being loaded. + // This can take a while on some Macs. + "launch_ap_timeout": 300 + } + } + } +} From 3ced915f8ede3c1e0eb13688aaa9516abfd6e2b9 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 10 Nov 2021 17:36:21 +0000 Subject: [PATCH 20/97] Fix attempted rendering of invalid Entity selection boxes. Signed-off-by: John --- .../ViewportSelection/EditorTransformComponentSelection.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 39c882b766..f40e354ca2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -1177,8 +1177,10 @@ namespace AzToolsFramework continue; } - const AZ::Aabb bound = CalculateEditorEntitySelectionBounds(entityId, viewportInfo); - debugDisplay.DrawSolidBox(bound.GetMin(), bound.GetMax()); + if (const AZ::Aabb bound = CalculateEditorEntitySelectionBounds(entityId, viewportInfo); bound.IsValid()) + { + debugDisplay.DrawSolidBox(bound.GetMin(), bound.GetMax()); + } } debugDisplay.DepthTestOn(); From 576248a870fb7aab37949822a54a9b3969a6a6b1 Mon Sep 17 00:00:00 2001 From: Shirang Jia Date: Wed, 10 Nov 2021 10:26:44 -0800 Subject: [PATCH 21/97] Merge Jenkinsfile from development to stabilization (#5391) Signed-off-by: shiranj --- scripts/build/Jenkins/Jenkinsfile | 45 ++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 34732a5fad..beb4a21620 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -16,7 +16,7 @@ EMPTY_JSON = readJSON text: '{}' ENGINE_REPOSITORY_NAME = 'o3de' // Branches with build snapshots -BUILD_SNAPSHOTS = ['development', 'stabilization/2106'] +BUILD_SNAPSHOTS = ['development', 'stabilization/2110'] // Build snapshots with empty snapshot (for use with 'SNAPSHOT' pipeline paramater) BUILD_SNAPSHOTS_WITH_EMPTY = BUILD_SNAPSHOTS + '' @@ -102,6 +102,10 @@ def IsJobEnabled(branchName, buildTypeMap, pipelineName, platformName) { } } +def IsAPLogUpload(branchName, jobName) { + return !IsPullRequest(branchName) && jobName.toLowerCase().contains('asset') && env.AP_LOGS_S3_BUCKET +} + def GetRunningPipelineName(JENKINS_JOB_NAME) { // If the job name has an underscore def job_parts = JENKINS_JOB_NAME.tokenize('/')[0].tokenize('_') @@ -267,7 +271,7 @@ def CheckoutRepo(boolean disableSubmodules = false) { palRm('commitdate') } -def HandleDriveMount(String snapshot, String repositoryName, String projectName, String pipeline, String branchName, String platform, String buildType, String workspace, boolean recreateVolume = false) { +def HandleDriveMount(String snapshot, String repositoryName, String projectName, String pipeline, String branchName, String platform, String buildType, String workspace, boolean recreateVolume = false) { unstash name: 'incremental_build_script' def pythonCmd = '' @@ -429,6 +433,27 @@ def ExportTestScreenshots(Map options, String branchName, String platformName, S } } +def UploadAPLogs(Map options, String branchName, String platformName, String jobName, String workspace, Map params) { + dir("${workspace}/${ENGINE_REPOSITORY_NAME}") { + projects = params.CMAKE_LY_PROJECTS.split(",") + projects.each{ project -> + def apLogsPath = "${project}/user/log" + def s3UploadScriptPath = "scripts/build/tools/upload_to_s3.py" + if(env.IS_UNIX) { + pythonPath = "${options.PYTHON_DIR}/python.sh" + } + else { + pythonPath = "${options.PYTHON_DIR}/python.cmd" + } + def command = "${pythonPath} -u ${s3UploadScriptPath} --base_dir ${apLogsPath} " + + "--file_regex \".*\" --bucket ${env.AP_LOGS_S3_BUCKET} " + + "--search_subdirectories True --key_prefix ${env.JENKINS_JOB_NAME}/${branchName}/${env.BUILD_NUMBER}/${platformName}/${jobName} " + + '--extra_args {\\"ACL\\":\\"bucket-owner-full-control\\"}' + palSh(command, "Uploading AP logs for job ${jobName} for branch ${branchName}", false) + } + } + } + def PostBuildCommonSteps(String workspace, boolean mount = true) { echo 'Starting post-build common steps...' @@ -492,6 +517,14 @@ def CreateExportTestScreenshotsStage(Map pipelineConfig, String branchName, Stri } } +def CreateUploadAPLogsStage(Map pipelineConfig, String branchName, String platformName, String jobName, String workspace, Map params) { + return { + stage("${jobName}_upload_ap_logs") { + UploadAPLogs(pipelineConfig, branchName, platformName, jobName, workspace, params) + } + } +} + def CreateTeardownStage(Map environmentVars) { return { stage('Teardown') { @@ -516,9 +549,11 @@ def CreateSingleNode(Map pipelineConfig, def platform, def build_job, Map envVar CreateSetupStage(pipelineConfig, snapshot, repositoryName, projectName, pipelineName, branchName, platform.key, build_job.key, envVars, onlyMountEBSVolume).call() if(build_job.value.steps) { //this is a pipe with many steps so create all the build stages + pipelineEnvVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, build_job.value.PIPELINE_ENV ?: EMPTY_JSON, pipelineName) build_job.value.steps.each { build_step -> build_job_name = build_step - envVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, platform.value.build_types[build_step].PIPELINE_ENV ?: EMPTY_JSON, pipelineName) + // This addition of maps makes it that the right operand will override entries if they overlap with the left operand + envVars = pipelineEnvVars + GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, platform.value.build_types[build_step].PIPELINE_ENV ?: EMPTY_JSON, pipelineName) try { CreateBuildStage(pipelineConfig, platform.key, build_step, envVars).call() } @@ -541,6 +576,9 @@ def CreateSingleNode(Map pipelineConfig, def platform, def build_job, Map envVar error "Node disconnected during build: ${e}" // Error raised to retry stage on a new node } } + if (IsAPLogUpload(branchName, build_job_name)) { + CreateUploadAPLogsStage(pipelineConfig, branchName, platform.key, build_job_name, envVars['WORKSPACE'], platform.value.build_types[build_job_name].PARAMETERS).call() + } // All other errors will be raised outside the retry block currentResult = envVars['ON_FAILURE_MARK'] ?: 'FAILURE' currentException = e.toString() @@ -768,6 +806,7 @@ try { platform.value.build_types.each { build_job -> if (IsJobEnabled(branchName, build_job, pipelineName, platform.key)) { // User can filter jobs, jobs are tagged by pipeline def envVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, build_job.value.PIPELINE_ENV ?: EMPTY_JSON, pipelineName) + envVars['JENKINS_JOB_NAME'] = env.JOB_NAME // Save original Jenkins job name to JENKINS_JOB_NAME envVars['JOB_NAME'] = "${branchName}_${platform.key}_${build_job.key}" // backwards compatibility, some scripts rely on this someBuildHappened = true From f2e191ea77c64232fb1fabf8f02ac235c3704518 Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Wed, 10 Nov 2021 10:28:32 -0800 Subject: [PATCH 22/97] Fix trying to remove a cache file Signed-off-by: AMZN-Phil --- scripts/o3de/o3de/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/o3de/o3de/utils.py b/scripts/o3de/o3de/utils.py index 56f9ae4bcd..9872c0779b 100755 --- a/scripts/o3de/o3de/utils.py +++ b/scripts/o3de/o3de/utils.py @@ -128,7 +128,7 @@ def download_file(parsed_uri, download_path: pathlib.Path, force_overwrite, down logger.warn(f'File already downloaded to {download_path}.') else: try: - shutil.rmtree(download_path) + os.unlink(download_path) except OSError: logger.error(f'Could not remove existing download path {download_path}.') return 1 From 541e501b066b5274807011e3f319160c61e29ec4 Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Wed, 10 Nov 2021 10:56:44 -0800 Subject: [PATCH 23/97] Re-add the line to open the cart overlay automatically when a new download starts Signed-off-by: AMZN-Phil --- .../ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp index 23c060e343..26c75d553f 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp @@ -519,6 +519,7 @@ namespace O3DE::ProjectManager m_downloadSpinner->show(); m_downloadLabel->show(); m_downloadSpinnerMovie->start(); + m_cartButton->ShowOverlay(); } void GemCatalogHeaderWidget::GemDownloadRemoved(const QString& /*gemName*/) From e0cc86e8985b93e836a72772910ae304ef26cc3c Mon Sep 17 00:00:00 2001 From: amzn-mike <80125227+amzn-mike@users.noreply.github.com> Date: Wed, 10 Nov 2021 13:21:42 -0600 Subject: [PATCH 24/97] Remove AssetProcessorManagerTest AssertAbsorber and update test to use the one from the base class instead (#5216) (#5381) Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> (cherry picked from commit b3301414ad1f76161fa88eaf8650f42bfb94617c) # Conflicts: # Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp --- .../AssetProcessorManagerTest.cpp | 32 +++++++++---------- .../assetmanager/AssetProcessorManagerTest.h | 1 - 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp index f8d758e092..1a6063cff0 100644 --- a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp +++ b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp @@ -243,7 +243,7 @@ void AssetProcessorManagerTest::SetUp() m_mockApplicationManager->BusConnect(); m_assetProcessorManager.reset(new AssetProcessorManager_Test(m_config.get())); - m_assertAbsorber.Clear(); + m_errorAbsorber->Clear(); m_isIdling = false; @@ -334,9 +334,9 @@ TEST_F(AssetProcessorManagerTest, UnitTestForGettingJobInfoBySourceUUIDSuccess) EXPECT_STRCASEEQ(relFileName.toUtf8().data(), response.m_jobList[0].m_sourceFile.c_str()); EXPECT_STRCASEEQ(tempPath.filePath("subfolder1").toUtf8().data(), response.m_jobList[0].m_watchFolder.c_str()); - ASSERT_EQ(m_assertAbsorber.m_numWarningsAbsorbed, 0); - ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 0); - ASSERT_EQ(m_assertAbsorber.m_numAssertsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numWarningsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); } TEST_F(AssetProcessorManagerTest, WarningsAndErrorsReported_SuccessfullySavedToDatabase) @@ -388,9 +388,9 @@ TEST_F(AssetProcessorManagerTest, WarningsAndErrorsReported_SuccessfullySavedToD ASSERT_EQ(response.m_jobList[0].m_warningCount, 11); ASSERT_EQ(response.m_jobList[0].m_errorCount, 22); - ASSERT_EQ(m_assertAbsorber.m_numWarningsAbsorbed, 0); - ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 0); - ASSERT_EQ(m_assertAbsorber.m_numAssertsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numWarningsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); } @@ -1312,8 +1312,8 @@ void PathDependencyTest::SetUp() void PathDependencyTest::TearDown() { - ASSERT_EQ(m_assertAbsorber.m_numAssertsAbsorbed, 0); - ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0); AssetProcessorManagerTest::TearDown(); } @@ -1617,7 +1617,7 @@ TEST_F(PathDependencyTest, AssetProcessed_Impl_SelfReferrentialProductDependency mainFile.m_products.push_back(productAssetId); // tell the APM that the asset has been processed and allow it to bubble through its event queue: - m_assertAbsorber.Clear(); + m_errorAbsorber->Clear(); m_assetProcessorManager->AssetProcessed(jobDetails.m_jobEntry, processJobResponse); ASSERT_TRUE(BlockUntilIdle(5000)); @@ -1627,8 +1627,8 @@ TEST_F(PathDependencyTest, AssetProcessed_Impl_SelfReferrentialProductDependency ASSERT_TRUE(dependencyContainer.empty()); // We are testing 2 different dependencies, so we should get 2 warnings - ASSERT_EQ(m_assertAbsorber.m_numWarningsAbsorbed, 2); - m_assertAbsorber.Clear(); + ASSERT_EQ(m_errorAbsorber->m_numWarningsAbsorbed, 2); + m_errorAbsorber->Clear(); } // This test shows the process of deferring resolution of a path dependency works. @@ -1945,8 +1945,8 @@ TEST_F(PathDependencyTest, WildcardDependencies_ExcludePathsExisting_ResolveCorr ); // Test asset PrimaryFile1 has 4 conflict dependencies - ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 4); - m_assertAbsorber.Clear(); + ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 4); + m_errorAbsorber->Clear(); } TEST_F(PathDependencyTest, WildcardDependencies_Deferred_ResolveCorrectly) @@ -2093,8 +2093,8 @@ TEST_F(PathDependencyTest, WildcardDependencies_ExcludedPathDeferred_ResolveCorr // Test asset PrimaryFile1 has 4 conflict dependencies // After test assets dep2 and dep3 are processed, // another 2 errors will be raised because of the confliction - ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 6); - m_assertAbsorber.Clear(); + ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 6); + m_errorAbsorber->Clear(); } void PathDependencyTest::RunWildcardTest(bool useCorrectDatabaseSeparator, AssetBuilderSDK::ProductPathDependencyType pathDependencyType, bool buildDependenciesFirst) diff --git a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h index 3443a4c519..2f0121485e 100644 --- a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h +++ b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h @@ -58,7 +58,6 @@ protected: AZStd::unique_ptr m_assetProcessorManager; AZStd::unique_ptr m_mockApplicationManager; AZStd::unique_ptr m_config; - UnitTestUtils::AssertAbsorber m_assertAbsorber; // absorb asserts/warnings/errors so that the unit test output is not cluttered QString m_gameName; QDir m_normalizedCacheRootDir; AZStd::atomic_bool m_isIdling; From d945a031c1b97fd7fd7a9d11ae8e75a2a9ceb83c Mon Sep 17 00:00:00 2001 From: greerdv Date: Wed, 10 Nov 2021 19:30:12 +0000 Subject: [PATCH 25/97] prevent twist limits being created with equal lower and upper limits Signed-off-by: greerdv --- .../Code/Source/Joint/PhysXJointUtils.cpp | 18 ++++++++++++++++-- Gems/PhysX/Code/Source/Joint/PhysXJointUtils.h | 4 +++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp b/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp index 3558c9fb56..e69fb70fb2 100644 --- a/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp +++ b/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp @@ -224,8 +224,22 @@ namespace PhysX { physx::PxJointLimitCone limitCone(swingLimitY, swingLimitZ); joint->setSwingLimit(limitCone); - const float twistLower = AZ::DegToRad(AZStd::GetMin(configuration.m_twistLimitLower, configuration.m_twistLimitUpper)); - const float twistUpper = AZ::DegToRad(AZStd::GetMax(configuration.m_twistLimitLower, configuration.m_twistLimitUpper)); + float twistLower = AZ::DegToRad(AZStd::GetMin(configuration.m_twistLimitLower, configuration.m_twistLimitUpper)); + float twistUpper = AZ::DegToRad(AZStd::GetMax(configuration.m_twistLimitLower, configuration.m_twistLimitUpper)); + // make sure there is at least a small difference between the lower and upper limits to avoid problems in PhysX + const float minSwingLimitRangeRadians = AZ::DegToRad(JointConstants::MinTwistLimitRangeDegrees); + if (const float twistLimitRange = twistUpper - twistLower; + twistLimitRange < minSwingLimitRangeRadians) + { + if (twistUpper > 0.0f) + { + twistLower -= (minSwingLimitRangeRadians - twistLimitRange); + } + else + { + twistUpper += (minSwingLimitRangeRadians - twistLimitRange); + } + } physx::PxJointAngularLimitPair twistLimitPair(twistLower, twistUpper); joint->setTwistLimit(twistLimitPair); diff --git a/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.h b/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.h index 7a30473dac..a99eb7aacb 100644 --- a/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.h +++ b/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.h @@ -18,9 +18,11 @@ namespace PhysX { namespace JointConstants { - // Setting swing limits to very small values can cause extreme stability problems, so clamp above a small + // Setting joint limits to very small values can cause extreme stability problems, so clamp above a small // threshold. static const float MinSwingLimitDegrees = 1.0f; + // Minimum range between lower and upper twist limits. + static const float MinTwistLimitRangeDegrees = 1.0f; } // namespace JointConstants namespace Utils From 3fd03479de46c75509d730164973f60e04f8371b Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Wed, 10 Nov 2021 11:56:45 -0800 Subject: [PATCH 26/97] Addressed PR feedback Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Atom/Feature/Mesh/MeshFeatureProcessor.h | 2 +- .../Feature/Mesh/MeshFeatureProcessorInterface.h | 13 ++++++++----- .../Common/Code/Mocks/MockMeshFeatureProcessor.h | 2 +- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 2 +- .../EMotionFXAtom/Code/Source/AtomActorInstance.cpp | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h index 4aec78be51..23cd76ca20 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h @@ -153,7 +153,7 @@ namespace AZ Data::Instance GetModel(const MeshHandle& meshHandle) const override; Data::Asset GetModelAsset(const MeshHandle& meshHandle) const override; - AZStd::vector>& GetObjectSrgs(const MeshHandle& meshHandle) const override; + const AZStd::vector>& GetObjectSrgs(const MeshHandle& meshHandle) const override; void QueueObjectSrgForCompile(const MeshHandle& meshHandle) const override; void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const Data::Instance& material) override; void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const MaterialAssignmentMap& materials) override; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h index 3be5f3efd8..356b1936ca 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h @@ -61,12 +61,15 @@ namespace AZ virtual Data::Instance GetModel(const MeshHandle& meshHandle) const = 0; //! Gets the underlying RPI::ModelAsset for a meshHandle. virtual Data::Asset GetModelAsset(const MeshHandle& meshHandle) const = 0; - //! Gets the ObjectSrg for a meshHandle. - //! Updating the ObjectSrg should be followed by a call to QueueObjectSrgForCompile, - //! instead of compiling the srg directly. This way, if the srg has already been queued for compile, - //! it will not be queued twice in the same frame. The ObjectSrg should not be updated during + + //! Gets the ObjectSrgs for a meshHandle. + //! Updating the ObjectSrgs should be followed by a call to QueueObjectSrgForCompile, + //! instead of compiling the srgs directly. This way, if the srgs have already been queued for compile, + //! they will not be queued twice in the same frame. The ObjectSrgs should not be updated during //! Simulate, or it will create a race between updating the data and the call to Compile - virtual AZStd::vector>& GetObjectSrgs(const MeshHandle& meshHandle) const = 0; + //! Cases where there may be multiple ObjectSrgs: if a model has multiple submeshes and those submeshes use different + //! materials with different object SRGs. + virtual const AZStd::vector>& GetObjectSrgs(const MeshHandle& meshHandle) const = 0; //! Queues the object srg for compile. virtual void QueueObjectSrgForCompile(const MeshHandle& meshHandle) const = 0; //! Sets the MaterialAssignmentMap for a meshHandle, using just a single material for the DefaultMaterialAssignmentId. diff --git a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h index 05a3274657..2c818d3c9b 100644 --- a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h @@ -19,7 +19,7 @@ namespace UnitTest MOCK_METHOD1(CloneMesh, MeshHandle(const MeshHandle&)); MOCK_CONST_METHOD1(GetModel, AZStd::intrusive_ptr(const MeshHandle&)); MOCK_CONST_METHOD1(GetModelAsset, AZ::Data::Asset(const MeshHandle&)); - MOCK_CONST_METHOD1(GetObjectSrgs, AZStd::vector>&(const MeshHandle&)); + MOCK_CONST_METHOD1(GetObjectSrgs, const AZStd::vector>&(const MeshHandle&)); MOCK_CONST_METHOD1(QueueObjectSrgForCompile, void(const MeshHandle&)); MOCK_CONST_METHOD1(GetMaterialAssignmentMap, const AZ::Render::MaterialAssignmentMap&(const MeshHandle&)); MOCK_METHOD2(ConnectModelChangeEventHandler, void(const MeshHandle&, ModelChangedEvent::Handler&)); diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 7227311915..112eff64a8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -215,7 +215,7 @@ namespace AZ return {}; } - AZStd::vector>& MeshFeatureProcessor::GetObjectSrgs(const MeshHandle& meshHandle) const + const AZStd::vector>& MeshFeatureProcessor::GetObjectSrgs(const MeshHandle& meshHandle) const { static AZStd::vector> staticEmptyList; return meshHandle.IsValid() ? meshHandle->m_objectSrgList : staticEmptyList; diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 7cd4fc073b..a3978c2d03 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -880,7 +880,7 @@ namespace AZ { if (m_meshHandle) { - AZStd::vector>& wrinkleMaskObjectSrgs = m_meshFeatureProcessor->GetObjectSrgs(*m_meshHandle); + const AZStd::vector>& wrinkleMaskObjectSrgs = m_meshFeatureProcessor->GetObjectSrgs(*m_meshHandle); for (auto& wrinkleMaskObjectSrg : wrinkleMaskObjectSrgs) { From f470351d0c5a32ad9859c6d111d00338f4738311 Mon Sep 17 00:00:00 2001 From: nggieber Date: Wed, 10 Nov 2021 12:33:24 -0800 Subject: [PATCH 27/97] Hook up Gem Updating and Uninstallation and fix lots of minor bugs between gem catalog and gem repos Signed-off-by: nggieber --- .../ProjectManager/Source/DownloadWorker.cpp | 2 +- .../GemCatalog/GemCatalogHeaderWidget.cpp | 1 + .../GemCatalog/GemCatalogHeaderWidget.h | 1 + .../Source/GemCatalog/GemCatalogScreen.cpp | 83 +++++++++++++++++-- .../Source/GemCatalog/GemInfo.h | 1 + .../Source/GemCatalog/GemInspector.cpp | 2 +- .../Source/GemCatalog/GemModel.cpp | 25 ++++++ .../Source/GemCatalog/GemModel.h | 4 +- .../Source/GemCatalog/GemUninstallDialog.cpp | 4 +- .../Source/GemCatalog/GemUpdateDialog.cpp | 18 ++-- .../Source/GemCatalog/GemUpdateDialog.h | 2 +- .../ProjectManager/Source/PythonBindings.cpp | 69 ++++++++++----- .../ProjectManager/Source/PythonBindings.h | 7 +- .../Source/PythonBindingsInterface.h | 41 +++++---- scripts/o3de/o3de/repo.py | 13 +-- scripts/o3de/o3de/utils.py | 6 +- 16 files changed, 206 insertions(+), 73 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/DownloadWorker.cpp b/Code/Tools/ProjectManager/Source/DownloadWorker.cpp index 9bda1b34cc..5f5c64987b 100644 --- a/Code/Tools/ProjectManager/Source/DownloadWorker.cpp +++ b/Code/Tools/ProjectManager/Source/DownloadWorker.cpp @@ -25,7 +25,7 @@ namespace O3DE::ProjectManager m_downloadProgress = downloadProgress; emit UpdateProgress(downloadProgress); }; - AZ::Outcome gemInfoResult = PythonBindingsInterface::Get()->DownloadGem(m_gemName, gemDownloadProgress); + AZ::Outcome gemInfoResult = PythonBindingsInterface::Get()->DownloadGem(m_gemName, gemDownloadProgress, true); if (gemInfoResult.IsSuccess()) { emit Done(""); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp index 8c875e4846..def02ea9ba 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp @@ -429,6 +429,7 @@ namespace O3DE::ProjectManager hLayout->addSpacing(16); QMenu* gemMenu = new QMenu(this); + gemMenu->addAction( tr("Refresh"), [this]() { emit RefreshGems(); }); gemMenu->addAction( tr("Show Gem Repos"), [this]() { emit OpenGemsRepo(); }); gemMenu->addSeparator(); gemMenu->addAction( tr("Add Existing Gem"), [this]() { emit AddGem(); }); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h index 6da78cce7a..a0ed7c70f9 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h @@ -89,6 +89,7 @@ namespace O3DE::ProjectManager signals: void AddGem(); void OpenGemsRepo(); + void RefreshGems(); private: AzQtComponents::SearchLineEdit* m_filterLineEdit = nullptr; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 29f73e5651..6758010cf5 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,7 @@ namespace O3DE::ProjectManager vLayout->addWidget(m_headerWidget); connect(m_gemModel, &GemModel::gemStatusChanged, this, &GemCatalogScreen::OnGemStatusChanged); + connect(m_headerWidget, &GemCatalogHeaderWidget::RefreshGems, this, &GemCatalogScreen::Refresh); connect(m_headerWidget, &GemCatalogHeaderWidget::OpenGemsRepo, this, &GemCatalogScreen::HandleOpenGemRepo); connect(m_headerWidget, &GemCatalogHeaderWidget::AddGem, this, &GemCatalogScreen::OnAddGemClicked); connect(m_downloadController, &DownloadController::Done, this, &GemCatalogScreen::OnGemDownloadResult); @@ -235,6 +237,9 @@ namespace O3DE::ProjectManager // temporary, until we can refresh filter counts m_proxyModel->ResetFilters(); m_filterWidget->ResetAllFilters(); + + // Reselect the same selection to proc UI updates + m_proxyModel->GetSelectionModel()->select(m_proxyModel->GetSelectionModel()->selection(), QItemSelectionModel::Select); } void GemCatalogScreen::OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies) @@ -300,21 +305,83 @@ namespace O3DE::ProjectManager void GemCatalogScreen::UpdateGem(const QModelIndex& modelIndex) { - const QString selectedGemName = m_gemModel->GetDisplayName(modelIndex); - GemUpdateDialog* confirmUpdateDialog = new GemUpdateDialog(selectedGemName, this); + const QString selectedGemName = m_gemModel->GetName(modelIndex); + const QString selectedGemLastUpdate = m_gemModel->GetLastUpdated(modelIndex); + const QString selectedDisplayGemName = m_gemModel->GetDisplayName(modelIndex); + const QString selectedGemRepoUri = m_gemModel->GetRepoUri(modelIndex); + + // Refresh gem repo + if (!selectedGemRepoUri.isEmpty()) + { + AZ::Outcome refreshResult = PythonBindingsInterface::Get()->RefreshGemRepo(selectedGemRepoUri); + if (refreshResult.IsSuccess()) + { + Refresh(); + } + else + { + QMessageBox::critical( + this, tr("Operation failed"), + tr("Failed to refresh gem repo %1
Error:
%2").arg(selectedGemRepoUri, refreshResult.GetError().c_str())); + } + } + // If repo uri isn't specified warn user that repo might not be refreshed + else + { + int result = QMessageBox::warning( + this, tr("Gem Repo Unspecified"), + tr("The repo for %1 is unspecfied. Repo cannot be automatically refreshed. " + "Please ensure this gem's repo is refreshed before attempting to update.") + .arg(selectedDisplayGemName), + QMessageBox::Cancel, QMessageBox::Ok); + + // Allow user to cancel update to manually refresh repo + if (result != QMessageBox::Ok) + { + return; + } + } + + // Check if there is an update avaliable now that repo is refreshed + bool updateAvaliable = PythonBindingsInterface::Get()->IsGemUpdateAvaliable(selectedGemName, selectedGemLastUpdate); + + GemUpdateDialog* confirmUpdateDialog = new GemUpdateDialog(selectedGemName, updateAvaliable, this); if (confirmUpdateDialog->exec() == QDialog::Accepted) { - // Update Gem + m_downloadController->AddGemDownload(selectedGemName); } } void GemCatalogScreen::UninstallGem(const QModelIndex& modelIndex) { - const QString selectedGemName = m_gemModel->GetDisplayName(modelIndex); - GemUninstallDialog* confirmUninstallDialog = new GemUninstallDialog(selectedGemName, this); + const QString selectedDisplayGemName = m_gemModel->GetDisplayName(modelIndex); + + GemUninstallDialog* confirmUninstallDialog = new GemUninstallDialog(selectedDisplayGemName, this); if (confirmUninstallDialog->exec() == QDialog::Accepted) { - // Uninstall Gem + const QString selectedGemPath = m_gemModel->GetPath(modelIndex); + + // Unregister the gem + auto unregisterResult = PythonBindingsInterface::Get()->RegisterGem(selectedGemPath, {}, /*remove*/true); + if (!unregisterResult) + { + QMessageBox::critical(this, tr("Failed to unregister gem"), unregisterResult.GetError().c_str()); + } + else + { + // Remove gem from model + m_gemModel->removeRow(modelIndex.row()); + + // Delete uninstalled gem directory + if (!ProjectUtils::DeleteProjectFiles(selectedGemPath, /*force*/true)) + { + QMessageBox::critical( + this, tr("Failed to remove gem directory"), tr("Could not delete gem directory at:
%1").arg(selectedGemPath)); + } + + // Show undownloaded remote gem again + Refresh(); + } } } @@ -351,8 +418,10 @@ namespace O3DE::ProjectManager { // Add all available gems to the model. const QVector& allGemInfos = allGemInfosResult.GetValue(); - for (const GemInfo& gemInfo : allGemInfos) + for (GemInfo gemInfo : allGemInfos) { + // Mark as downloaded because this gem was registered with an existing directory + gemInfo.m_downloadStatus = GemInfo::DownloadStatus::Downloaded; m_gemModel->AddGem(gemInfo); } diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h index bef9f6cd99..b3b29d6ee6 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h @@ -85,6 +85,7 @@ namespace O3DE::ProjectManager QString m_licenseLink; QString m_directoryLink; QString m_documentationLink; + QString m_repoUri; QString m_version = "Unknown Version"; QString m_lastUpdatedDate = "Unknown Date"; int m_binarySizeInKB = 0; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp index f0f5adebaa..52e078eacd 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp @@ -238,7 +238,7 @@ namespace O3DE::ProjectManager // Depending gems m_dependingGems = new GemsSubWidget(); - connect(m_dependingGems, &GemsSubWidget::TagClicked, this, [this](const QString& tag){ emit TagClicked(tag); }); + connect(m_dependingGems, &GemsSubWidget::TagClicked, this, [this](const Tag& tag){ emit TagClicked(tag); }); m_mainLayout->addWidget(m_dependingGems); m_mainLayout->addSpacing(20); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp index 88c54de0b3..886b9e57c7 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp @@ -61,6 +61,7 @@ namespace O3DE::ProjectManager item->setData(gemInfo.m_downloadStatus, RoleDownloadStatus); item->setData(gemInfo.m_licenseText, RoleLicenseText); item->setData(gemInfo.m_licenseLink, RoleLicenseLink); + item->setData(gemInfo.m_repoUri, RoleRepoUri); appendRow(item); @@ -255,6 +256,11 @@ namespace O3DE::ProjectManager return modelIndex.data(RoleLicenseLink).toString(); } + QString GemModel::GetRepoUri(const QModelIndex& modelIndex) + { + return modelIndex.data(RoleRepoUri).toString(); + } + GemModel* GemModel::GetSourceModel(QAbstractItemModel* model) { GemSortFilterProxyModel* proxyModel = qobject_cast(model); @@ -369,11 +375,30 @@ namespace O3DE::ProjectManager void GemModel::OnRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last) { + bool selectedRowRemoved = false; for (int i = first; i <= last; ++i) { QModelIndex modelIndex = index(i, 0, parent); const QString& gemName = GetName(modelIndex); m_nameToIndexMap.remove(gemName); + + if (GetSelectionModel()->isRowSelected(i)) + { + selectedRowRemoved = true; + } + } + + // Select a valid row if currently selected row was removed + if (selectedRowRemoved) + { + for (const QModelIndex& index : m_nameToIndexMap) + { + if (index.isValid()) + { + GetSelectionModel()->select(index, QItemSelectionModel::ClearAndSelect); + break; + } + } } } diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h index e25a1c7703..87a718d8c7 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h @@ -51,7 +51,8 @@ namespace O3DE::ProjectManager RoleRequirement, RoleDownloadStatus, RoleLicenseText, - RoleLicenseLink + RoleLicenseLink, + RoleRepoUri }; void AddGem(const GemInfo& gemInfo); @@ -80,6 +81,7 @@ namespace O3DE::ProjectManager static QString GetRequirement(const QModelIndex& modelIndex); static QString GetLicenseText(const QModelIndex& modelIndex); static QString GetLicenseLink(const QModelIndex& modelIndex); + static QString GetRepoUri(const QModelIndex& modelIndex); static GemModel* GetSourceModel(QAbstractItemModel* model); static const GemModel* GetSourceModel(const QAbstractItemModel* model); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.cpp index 6838741417..6b2f14e551 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.cpp @@ -39,10 +39,10 @@ namespace O3DE::ProjectManager QLabel* bodyLabel = new QLabel(tr("The Gem and its related files will be uninstalled. This does not affect the Gem’s repository. " "You can reinstall this Gem from the Catalog, but its contents may be subject to change.")); bodyLabel->setWordWrap(true); - bodyLabel->setFixedWidth(440); + bodyLabel->setFixedSize(QSize(440, 80)); layout->addWidget(bodyLabel); - layout->addSpacing(60); + layout->addSpacing(40); // Buttons QDialogButtonBox* dialogButtons = new QDialogButtonBox(); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp index 8d8490ab40..dab4a2a0fe 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp @@ -16,7 +16,7 @@ namespace O3DE::ProjectManager { - GemUpdateDialog::GemUpdateDialog(const QString& gemName, QWidget* parent) + GemUpdateDialog::GemUpdateDialog(const QString& gemName, bool updateAvaliable, QWidget* parent) : QDialog(parent) { setWindowTitle(tr("Update Remote Gem")); @@ -30,20 +30,23 @@ namespace O3DE::ProjectManager setLayout(layout); // Body - QLabel* subTitleLabel = new QLabel(tr("Update to the latest version of %1?").arg(gemName)); + QLabel* subTitleLabel = new QLabel(tr("%1Update to the latest version of %2?").arg( + updateAvaliable ? "" : tr("Force "), gemName)); subTitleLabel->setObjectName("gemCatalogDialogSubTitle"); layout->addWidget(subTitleLabel); layout->addSpacing(10); - QLabel* bodyLabel = new QLabel(tr("The latest version of this Gem may not be compatible with your engine. " + QLabel* bodyLabel = new QLabel(tr("%1The latest version of this Gem may not be compatible with your engine. " "Updating this Gem will remove any local changes made to this Gem, " - "and may remove old features that are in use.")); + "and may remove old features that are in use.").arg( + updateAvaliable ? "" : tr("No update detected for Gem. " + "This will force a redownload of the gem anyways. "))); bodyLabel->setWordWrap(true); - bodyLabel->setFixedWidth(440); + bodyLabel->setFixedSize(QSize(440, 80)); layout->addWidget(bodyLabel); - layout->addSpacing(60); + layout->addSpacing(40); // Buttons QDialogButtonBox* dialogButtons = new QDialogButtonBox(); @@ -52,7 +55,8 @@ namespace O3DE::ProjectManager QPushButton* cancelButton = dialogButtons->addButton(tr("Cancel"), QDialogButtonBox::RejectRole); cancelButton->setProperty("secondary", true); - QPushButton* updateButton = dialogButtons->addButton(tr("Update Gem"), QDialogButtonBox::ApplyRole); + QPushButton* updateButton = + dialogButtons->addButton(tr("%1Update Gem").arg(updateAvaliable ? "" : tr("Force ")), QDialogButtonBox::ApplyRole); connect(cancelButton, &QPushButton::clicked, this, &QDialog::reject); connect(updateButton, &QPushButton::clicked, this, &QDialog::accept); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.h index 1a2813d1a2..cf34abfb3d 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.h @@ -19,7 +19,7 @@ namespace O3DE::ProjectManager { Q_OBJECT // AUTOMOC public : - explicit GemUpdateDialog(const QString& gemName, QWidget* parent = nullptr); + explicit GemUpdateDialog(const QString& gemName, bool updateAvaliable = true, QWidget* parent = nullptr); ~GemUpdateDialog() = default; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 021066e1c7..ef7daa761e 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -560,7 +560,7 @@ namespace O3DE::ProjectManager return AZ::Success(AZStd::move(gemNames)); } - AZ::Outcome PythonBindings::RegisterGem(const QString& gemPath, const QString& projectPath) + AZ::Outcome PythonBindings::RegisterGem(const QString& gemPath, const QString& projectPath, bool remove) { bool registrationResult = false; auto result = ExecuteWithLockErrorHandling( @@ -582,7 +582,8 @@ namespace O3DE::ProjectManager pybind11::none(), // default_restricted_folder pybind11::none(), // default_third_party_folder pybind11::none(), // external_subdir_engine_path - externalProjectPath // external_subdir_project_path + externalProjectPath, // external_subdir_project_path + remove // remove ); // Returns an exit code so boolify it then invert result @@ -715,6 +716,7 @@ namespace O3DE::ProjectManager gemInfo.m_documentationLink = Py_To_String_Optional(data, "documentation_url", ""); gemInfo.m_licenseText = Py_To_String_Optional(data, "license", "Unspecified License"); gemInfo.m_licenseLink = Py_To_String_Optional(data, "license_url", ""); + gemInfo.m_repoUri = Py_To_String_Optional(data, "repo_uri", ""); if (gemInfo.m_creator.contains("Open 3D Engine")) { @@ -728,6 +730,11 @@ namespace O3DE::ProjectManager { gemInfo.m_gemOrigin = GemInfo::GemOrigin::Remote; } + // If no origin was provided this cannot be remote and would be specified if O3DE so it should be local + else + { + gemInfo.m_gemOrigin = GemInfo::GemOrigin::Local; + } // As long Base Open3DEngine gems are installed before first startup non-remote gems will be downloaded if (gemInfo.m_gemOrigin != GemInfo::GemOrigin::Remote) @@ -1166,7 +1173,34 @@ namespace O3DE::ProjectManager return AZ::Success(AZStd::move(gemRepos)); } - AZ::Outcome PythonBindings::DownloadGem(const QString& gemName, std::function gemProgressCallback) + AZ::Outcome, AZStd::string> PythonBindings::GetAllGemRepoGemsInfos() + { + QVector gemInfos; + AZ::Outcome result = ExecuteWithLockErrorHandling( + [&] + { + auto gemPaths = m_repo.attr("get_gem_json_paths_from_all_cached_repos")(); + + if (pybind11::isinstance(gemPaths)) + { + for (auto path : gemPaths) + { + GemInfo gemInfo = GemInfoFromPath(path, pybind11::none()); + gemInfo.m_downloadStatus = GemInfo::DownloadStatus::NotDownloaded; + gemInfos.push_back(gemInfo); + } + } + }); + + if (!result.IsSuccess()) + { + return AZ::Failure(result.GetError()); + } + + return AZ::Success(AZStd::move(gemInfos)); + } + + AZ::Outcome PythonBindings::DownloadGem(const QString& gemName, std::function gemProgressCallback, bool force) { // This process is currently limited to download a single gem at a time. bool downloadSucceeded = false; @@ -1179,7 +1213,7 @@ namespace O3DE::ProjectManager QString_To_Py_String(gemName), // gem name pybind11::none(), // destination path false, // skip auto register - false, // force + force, // force overwrite pybind11::cpp_function( [this, gemProgressCallback](int progress) { @@ -1209,30 +1243,19 @@ namespace O3DE::ProjectManager m_requestCancelDownload = true; } - AZ::Outcome, AZStd::string> PythonBindings::GetAllGemRepoGemsInfos() + bool PythonBindings::IsGemUpdateAvaliable(const QString& gemName, const QString& lastUpdated) { - QVector gemInfos; - AZ::Outcome result = ExecuteWithLockErrorHandling( + bool updateAvaliableResult = false; + bool result = ExecuteWithLock( [&] { - auto gemPaths = m_repo.attr("get_gem_json_paths_from_all_cached_repos")(); + auto pyGemName = QString_To_Py_String(gemName); + auto pyLastUpdated = QString_To_Py_String(lastUpdated); + auto pythonUpdateAvaliableResult = m_download.attr("is_o3de_gem_update_available")(pyGemName, pyLastUpdated); - if (pybind11::isinstance(gemPaths)) - { - for (auto path : gemPaths) - { - GemInfo gemInfo = GemInfoFromPath(path, pybind11::none()); - gemInfo.m_downloadStatus = GemInfo::DownloadStatus::NotDownloaded; - gemInfos.push_back(gemInfo); - } - } + updateAvaliableResult = pythonUpdateAvaliableResult.cast(); }); - if (!result.IsSuccess()) - { - return AZ::Failure(result.GetError()); - } - - return AZ::Success(AZStd::move(gemInfos)); + return result && updateAvaliableResult; } } diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.h b/Code/Tools/ProjectManager/Source/PythonBindings.h index 4375d56d02..8a22344596 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.h +++ b/Code/Tools/ProjectManager/Source/PythonBindings.h @@ -42,7 +42,7 @@ namespace O3DE::ProjectManager AZ::Outcome, AZStd::string> GetEngineGemInfos() override; AZ::Outcome, AZStd::string> GetAllGemInfos(const QString& projectPath) override; AZ::Outcome, AZStd::string> GetEnabledGemNames(const QString& projectPath) override; - AZ::Outcome RegisterGem(const QString& gemPath, const QString& projectPath = {}) override; + AZ::Outcome RegisterGem(const QString& gemPath, const QString& projectPath = {}, bool remove = false) override; // Project AZ::Outcome CreateProject(const QString& projectTemplatePath, const ProjectInfo& projectInfo) override; @@ -64,9 +64,10 @@ namespace O3DE::ProjectManager bool AddGemRepo(const QString& repoUri) override; bool RemoveGemRepo(const QString& repoUri) override; AZ::Outcome, AZStd::string> GetAllGemRepoInfos() override; - AZ::Outcome DownloadGem(const QString& gemName, std::function gemProgressCallback) override; - void CancelDownload() override; AZ::Outcome, AZStd::string> GetAllGemRepoGemsInfos() override; + AZ::Outcome DownloadGem(const QString& gemName, std::function gemProgressCallback, bool force = false) override; + void CancelDownload() override; + bool IsGemUpdateAvaliable(const QString& gemName, const QString& lastUpdated) override; private: AZ_DISABLE_COPY_MOVE(PythonBindings); diff --git a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h index 1134804f1f..07d4551c60 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h +++ b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h @@ -94,10 +94,11 @@ namespace O3DE::ProjectManager /** * Registers the gem to the specified project, or to the o3de_manifest.json if no project path is given * @param gemPath the path to the gem - * @param projectPath the path to the project. If empty, will register the external path in o3de_manifest.json + * @param projectPath the path to the project. If empty, will register the external path in o3de_manifest.json + * @param remove Unregister instead of registering this gem * @return An outcome with the success flag as well as an error message in case of a failure. */ - virtual AZ::Outcome RegisterGem(const QString& gemPath, const QString& projectPath = {}) = 0; + virtual AZ::Outcome RegisterGem(const QString& gemPath, const QString& projectPath = {}, bool remove = false) = 0; // Projects @@ -209,24 +210,34 @@ namespace O3DE::ProjectManager */ virtual AZ::Outcome, AZStd::string> GetAllGemRepoInfos() = 0; - /** - * Downloads and registers a Gem. - * @param gemName the name of the Gem to download - * @param gemProgressCallback a callback function that is called with an int percentage download value - * @return an outcome with a string error message on failure. - */ - virtual AZ::Outcome DownloadGem(const QString& gemName, std::function gemProgressCallback) = 0; - - /** - * Cancels the current download. - */ - virtual void CancelDownload() = 0; - /** * Gathers all gem infos for all gems registered from repos. * @return A list of gem infos. */ virtual AZ::Outcome, AZStd::string> GetAllGemRepoGemsInfos() = 0; + + /** + * Downloads and registers a Gem. + * @param gemName the name of the Gem to download. + * @param gemProgressCallback a callback function that is called with an int percentage download value. + * @param force should we forcibly overwrite the old version of the gem. + * @return an outcome with a string error message on failure. + */ + virtual AZ::Outcome DownloadGem( + const QString& gemName, std::function gemProgressCallback, bool force = false) = 0; + + /** + * Cancels the current download. + */ + virtual void CancelDownload() = 0; + + /** + * Checks if there is an update avaliable for a gem on a repo. + * @param gemName the name of the gem to check. + * @param lastUpdated last time the gem was update. + * @return true if update is avaliable, false if not. + */ + virtual bool IsGemUpdateAvaliable(const QString& gemName, const QString& lastUpdated) = 0; }; using PythonBindingsInterface = AZ::Interface; diff --git a/scripts/o3de/o3de/repo.py b/scripts/o3de/o3de/repo.py index a6b1505761..1462015630 100644 --- a/scripts/o3de/o3de/repo.py +++ b/scripts/o3de/o3de/repo.py @@ -74,9 +74,9 @@ def process_add_o3de_repo(file_name: str or pathlib.Path, manifest_json_uri = f'{o3de_object_uri}/{manifest_json}' manifest_json_sha256 = hashlib.sha256(manifest_json_uri.encode()) cache_file = cache_folder / str(manifest_json_sha256.hexdigest() + '.json') - if not cache_file.is_file(): + if cache_file.is_file(): parsed_uri = urllib.parse.urlparse(manifest_json_uri) - download_file_result = utils.download_file(parsed_uri, cache_file) + download_file_result = utils.download_file(parsed_uri, cache_file, True) if download_file_result != 0: return download_file_result @@ -96,7 +96,7 @@ def process_add_o3de_repo(file_name: str or pathlib.Path, cache_file = cache_folder / str(manifest_json_sha256.hexdigest() + '.json') if cache_file.is_file(): cache_file.unlink() - download_file_result = utils.download_file(parsed_uri, cache_file) + download_file_result = utils.download_file(parsed_uri, cache_file, True) if download_file_result != 0: return download_file_result @@ -165,7 +165,7 @@ def refresh_repo(repo_uri: str, repo_sha256 = hashlib.sha256(parsed_uri.geturl().encode()) cache_file = cache_folder / str(repo_sha256.hexdigest() + '.json') - download_file_result = utils.download_file(parsed_uri, cache_file) + download_file_result = utils.download_file(parsed_uri, cache_file, True) if download_file_result != 0: return download_file_result @@ -178,12 +178,7 @@ def refresh_repo(repo_uri: str, def refresh_repos() -> int: json_data = manifest.load_o3de_manifest() - - # clear the cache cache_folder = manifest.get_o3de_cache_folder() - shutil.rmtree(cache_folder) - cache_folder = manifest.get_o3de_cache_folder() # will recreate it - result = 0 # set will stop circular references diff --git a/scripts/o3de/o3de/utils.py b/scripts/o3de/o3de/utils.py index 56f9ae4bcd..71929af7b5 100755 --- a/scripts/o3de/o3de/utils.py +++ b/scripts/o3de/o3de/utils.py @@ -117,7 +117,7 @@ def backup_folder(folder: str or pathlib.Path) -> None: if backup_folder_name.is_dir(): renamed = True -def download_file(parsed_uri, download_path: pathlib.Path, force_overwrite, download_progress_callback = None) -> int: +def download_file(parsed_uri, download_path: pathlib.Path, force_overwrite: bool = False, download_progress_callback = None) -> int: """ :param parsed_uri: uniform resource identifier to zip file to download :param download_path: location path on disk to download file @@ -128,7 +128,7 @@ def download_file(parsed_uri, download_path: pathlib.Path, force_overwrite, down logger.warn(f'File already downloaded to {download_path}.') else: try: - shutil.rmtree(download_path) + os.unlink(download_path) except OSError: logger.error(f'Could not remove existing download path {download_path}.') return 1 @@ -162,7 +162,7 @@ def download_zip_file(parsed_uri, download_zip_path: pathlib.Path, download_prog :param parsed_uri: uniform resource identifier to zip file to download :param download_zip_path: path to output zip file """ - download_file_result = download_file(parsed_uri, download_zip_path, download_progress_callback) + download_file_result = download_file(parsed_uri, download_zip_path, True, download_progress_callback) if download_file_result != 0: return download_file_result From 0bc3e6a18f819454da183024ba44d7b91897ee29 Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Wed, 10 Nov 2021 12:33:28 -0800 Subject: [PATCH 28/97] Let cart overlay be opened to view downloads even when there are no gems to be added or removed Signed-off-by: AMZN-Phil --- .../ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp index 26c75d553f..41e292d93c 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp @@ -401,7 +401,7 @@ namespace O3DE::ProjectManager { const QVector toBeAdded = m_gemModel->GatherGemsToBeAdded(/*includeDependencies=*/true); const QVector toBeRemoved = m_gemModel->GatherGemsToBeRemoved(/*includeDependencies=*/true); - if (toBeAdded.isEmpty() && toBeRemoved.isEmpty()) + if (toBeAdded.isEmpty() && toBeRemoved.isEmpty() && m_downloadController->IsDownloadQueueEmpty()) { return; } From cf58398c6c31e10bfea1c134328e585efcaab05b Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Wed, 10 Nov 2021 13:05:32 -0800 Subject: [PATCH 29/97] [AWSMetrics] Fail to build the project when include AWSMetricsBus header in the project C++ code (#5468) --- .../Code/Include/{Private => Public}/MetricsAttribute.h | 0 Gems/AWSMetrics/Code/awsmetrics_files.cmake | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename Gems/AWSMetrics/Code/Include/{Private => Public}/MetricsAttribute.h (100%) diff --git a/Gems/AWSMetrics/Code/Include/Private/MetricsAttribute.h b/Gems/AWSMetrics/Code/Include/Public/MetricsAttribute.h similarity index 100% rename from Gems/AWSMetrics/Code/Include/Private/MetricsAttribute.h rename to Gems/AWSMetrics/Code/Include/Public/MetricsAttribute.h diff --git a/Gems/AWSMetrics/Code/awsmetrics_files.cmake b/Gems/AWSMetrics/Code/awsmetrics_files.cmake index b51235c957..b1a3a647df 100644 --- a/Gems/AWSMetrics/Code/awsmetrics_files.cmake +++ b/Gems/AWSMetrics/Code/awsmetrics_files.cmake @@ -8,6 +8,7 @@ set(FILES Include/Public/AWSMetricsBus.h + Include/Public/MetricsAttribute.h Include/Private/AWSMetricsConstant.h Include/Private/AWSMetricsServiceApi.h Include/Private/AWSMetricsSystemComponent.h @@ -15,7 +16,6 @@ set(FILES Include/Private/DefaultClientIdProvider.h Include/Private/GlobalStatistics.h Include/Private/IdentityProvider.h - Include/Private/MetricsAttribute.h Include/Private/MetricsEvent.h Include/Private/MetricsEventBuilder.h Include/Private/MetricsManager.h From 21a254e9dca5262dcde7a1cebd41ef7dcf8df09c Mon Sep 17 00:00:00 2001 From: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> Date: Wed, 10 Nov 2021 13:15:04 -0800 Subject: [PATCH 30/97] Fixed a type with pass filter (#5506) Signed-off-by: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> --- .../Source/CoreLights/DirectionalLightFeatureProcessor.cpp | 2 +- Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h | 4 ++-- Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassFilter.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index b6c6910fd3..410c80dbdc 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -1056,7 +1056,7 @@ namespace AZ // if the shadow is rendering in an EnvironmentCubeMapPass it also needs to be a ReflectiveCubeMap view, // to filter out shadows from objects that are excluded from the cubemap RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassClass(); - passFilter.SetOwenrScene(GetParentScene()); // only handles passes for this scene + passFilter.SetOwnerScene(GetParentScene()); // only handles passes for this scene RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [&usageFlags]([[maybe_unused]] RPI::Pass* pass) -> RPI::PassFilterExecutionFlow { usageFlags |= RPI::View::UsageReflectiveCubeMap; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h index c42991725e..b93458113b 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h @@ -56,8 +56,8 @@ namespace AZ OwnerRenderPipeline = AZ_BIT(5) }; - void SetOwenrScene(const Scene* scene); - void SetOwenrRenderPipeline(const RenderPipeline* renderPipeline); + void SetOwnerScene(const Scene* scene); + void SetOwnerRenderPipeline(const RenderPipeline* renderPipeline); void SetPassName(Name passName); void SetTemplateName(Name passTemplateName); void SetPassClass(TypeId passClassTypeId); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassFilter.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassFilter.cpp index d9e458c615..d172abd81f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassFilter.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassFilter.cpp @@ -90,13 +90,13 @@ namespace AZ return filter; } - void PassFilter::SetOwenrScene(const Scene* scene) + void PassFilter::SetOwnerScene(const Scene* scene) { m_ownerScene = scene; UpdateFilterOptions(); } - void PassFilter::SetOwenrRenderPipeline(const RenderPipeline* renderPipeline) + void PassFilter::SetOwnerRenderPipeline(const RenderPipeline* renderPipeline) { m_ownerRenderPipeline = renderPipeline; UpdateFilterOptions(); From d5081a47db1bb8ec4c7a154f2a61b9bad1450034 Mon Sep 17 00:00:00 2001 From: jiaweig <51759646+jiaweig-amzn@users.noreply.github.com> Date: Wed, 10 Nov 2021 13:32:23 -0800 Subject: [PATCH 31/97] Fix/update swapchain recreation on vsync interval changes (#5502) Signed-off-by: jiaweig <51759646+jiaweig-amzn@users.noreply.github.com> --- Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp index 19c88ec34f..47c92d97fb 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp @@ -78,8 +78,7 @@ namespace AZ { // The presentation mode may change when transitioning to or from a vsynced presentation mode // In this case, the swapchain must be recreated. - InvalidateNativeSwapChain(); - CreateSwapchain(); + m_pendingRecreation = true; } } From 5054cfe9b550baf29750118c6b7b387a8ed5a8fc Mon Sep 17 00:00:00 2001 From: greerdv Date: Wed, 10 Nov 2021 22:04:40 +0000 Subject: [PATCH 32/97] fix typo Signed-off-by: greerdv --- Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp b/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp index e69fb70fb2..107bced7f2 100644 --- a/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp +++ b/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp @@ -227,17 +227,17 @@ namespace PhysX { float twistLower = AZ::DegToRad(AZStd::GetMin(configuration.m_twistLimitLower, configuration.m_twistLimitUpper)); float twistUpper = AZ::DegToRad(AZStd::GetMax(configuration.m_twistLimitLower, configuration.m_twistLimitUpper)); // make sure there is at least a small difference between the lower and upper limits to avoid problems in PhysX - const float minSwingLimitRangeRadians = AZ::DegToRad(JointConstants::MinTwistLimitRangeDegrees); + const float minTwistLimitRangeRadians = AZ::DegToRad(JointConstants::MinTwistLimitRangeDegrees); if (const float twistLimitRange = twistUpper - twistLower; - twistLimitRange < minSwingLimitRangeRadians) + twistLimitRange < minTwistLimitRangeRadians) { if (twistUpper > 0.0f) { - twistLower -= (minSwingLimitRangeRadians - twistLimitRange); + twistLower -= (minTwistLimitRangeRadians - twistLimitRange); } else { - twistUpper += (minSwingLimitRangeRadians - twistLimitRange); + twistUpper += (minTwistLimitRangeRadians - twistLimitRange); } } physx::PxJointAngularLimitPair twistLimitPair(twistLower, twistUpper); From 7a2eb349ca04051e281fcbfe0adca25e7850a3f9 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Wed, 10 Nov 2021 16:20:12 -0600 Subject: [PATCH 33/97] Fixed LC crash by preventing graphs from staying open after they are no longer in prefab focus. Signed-off-by: Chris Galvan --- .../Code/Source/Editor/MainWindow.cpp | 24 +++++++++++++++++++ .../Code/Source/Editor/MainWindow.h | 15 ++++++++++++ 2 files changed, 39 insertions(+) diff --git a/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp b/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp index 4574b938f6..f6f0d8b655 100644 --- a/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp +++ b/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -448,6 +449,9 @@ namespace LandscapeCanvasEditor AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext); AZ_Assert(m_serializeContext, "Failed to acquire application serialize context."); + m_prefabFocusPublicInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabFocusPublicInterface, "LandscapeCanvas - could not get PrefabFocusPublicInterface on construction."); + const GraphCanvas::EditorId& editorId = GetEditorId(); // Register unique color palettes for our connections (data types) @@ -459,6 +463,7 @@ namespace LandscapeCanvasEditor AzToolsFramework::EditorPickModeNotificationBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId()); AzToolsFramework::EntityCompositionNotificationBus::Handler::BusConnect(); AzToolsFramework::ToolsApplicationNotificationBus::Handler::BusConnect(); + AzToolsFramework::Prefab::PrefabFocusNotificationBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId()); AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusConnect(); CrySystemEventBus::Handler::BusConnect(); AZ::EntitySystemBus::Handler::BusConnect(); @@ -484,6 +489,7 @@ namespace LandscapeCanvasEditor AZ::EntitySystemBus::Handler::BusDisconnect(); CrySystemEventBus::Handler::BusDisconnect(); AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusDisconnect(); + AzToolsFramework::Prefab::PrefabFocusNotificationBus::Handler::BusDisconnect(); AzToolsFramework::ToolsApplicationNotificationBus::Handler::BusDisconnect(); AzToolsFramework::EditorPickModeNotificationBus::Handler::BusDisconnect(); AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect(); @@ -2500,6 +2506,24 @@ namespace LandscapeCanvasEditor } } + void MainWindow::OnPrefabFocusChanged() + { + // Make sure to close any open graphs that aren't currently in p refab focus + // to prevent the user from making modifications outside of the allowed focus scope + AZStd::vector dockWidgetsToClose; + for (auto [entityId, dockWidgetId] : m_dockWidgetsByEntity) + { + if (!m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId)) + { + dockWidgetsToClose.push_back(dockWidgetId); + } + } + for (auto dockWidgetId : dockWidgetsToClose) + { + CloseEditor(dockWidgetId); + } + } + void MainWindow::OnPrefabInstancePropagationBegin() { // Ignore graph updates during prefab propagation because the entities will be diff --git a/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.h b/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.h index e0fb2d8e10..de6b10529d 100644 --- a/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.h +++ b/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,14 @@ #include #endif +namespace AzToolsFramework +{ + namespace Prefab + { + class PrefabFocusPublicInterface; + } +} + namespace LandscapeCanvasEditor { //////////////////////////////////////////////////////////////////////// @@ -81,6 +90,7 @@ namespace LandscapeCanvasEditor , private AzToolsFramework::EntityCompositionNotificationBus::Handler , private AzToolsFramework::PropertyEditorEntityChangeNotificationBus::MultiHandler , private AzToolsFramework::ToolsApplicationNotificationBus::Handler + , private AzToolsFramework::Prefab::PrefabFocusNotificationBus::Handler , private AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler , private CrySystemEventBus::Handler { @@ -181,6 +191,9 @@ namespace LandscapeCanvasEditor void EntityParentChanged(AZ::EntityId entityId, AZ::EntityId newParentId, AZ::EntityId oldParentId) override; //////////////////////////////////////////////////////////////////////// + //! PrefabFocusNotificationBus overrides + void OnPrefabFocusChanged() override; + //! PrefabPublicNotificationBus overrides void OnPrefabInstancePropagationBegin() override; void OnPrefabInstancePropagationEnd() override; @@ -248,6 +261,8 @@ namespace LandscapeCanvasEditor AZ::SerializeContext* m_serializeContext = nullptr; + AzToolsFramework::Prefab::PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr; + bool m_ignoreGraphUpdates = false; bool m_prefabPropagationInProgress = false; bool m_inObjectPickMode = false; From 27f0aa7f137babf9097bf90d8fcbdf42a692ac06 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 10 Nov 2021 14:43:32 -0800 Subject: [PATCH 34/97] LYN-7468 | Viewport manipulators for the container of the focused prefab should be hidden (#5432) * Extend the level entity behavior to open prefab containers in focus mode. Disable manipulators for these entities too. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Minor adjustments Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Fix enum casing in Entity Inspector. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Split views between for Level and FocusedContainer entities. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Slightly different fix to support components on focused containers. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Minor fixesto RefreshSelectedEntityIds. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../Prefab/PrefabFocusHandler.cpp | 16 ++--- .../PropertyEditor/EntityPropertyEditor.cpp | 68 +++++++++++++++---- .../PropertyEditor/EntityPropertyEditor.hxx | 12 ++-- .../EditorTransformComponentSelection.cpp | 11 +++ 4 files changed, 77 insertions(+), 30 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp index 8098727177..5b51944a75 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -175,20 +175,14 @@ namespace AzToolsFramework::Prefab m_focusedInstance = focusedInstance; m_focusedTemplateId = focusedInstance->get().GetTemplateId(); - AZ::EntityId containerEntityId; - - if (focusedInstance->get().GetParentInstance() != AZStd::nullopt) - { - containerEntityId = focusedInstance->get().GetContainerEntityId(); - } - else - { - containerEntityId = AZ::EntityId(); - } - // Focus on the descendants of the container entity in the Editor, if the interface is initialized. if (m_focusModeInterface) { + const AZ::EntityId containerEntityId = + (focusedInstance->get().GetParentInstance() != AZStd::nullopt) + ? focusedInstance->get().GetContainerEntityId() + : AZ::EntityId(); + m_focusModeInterface->SetFocusRoot(containerEntityId); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp index a449fa0055..29bc106eed 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp @@ -45,6 +45,7 @@ AZ_POP_DISABLE_WARNING #include #include #include +#include #include #include #include @@ -894,25 +895,51 @@ namespace AzToolsFramework { if (!m_prefabsAreEnabled) { - return m_isLevelEntityEditor ? InspectorLayout::LEVEL : InspectorLayout::ENTITY; + return m_isLevelEntityEditor ? InspectorLayout::Level : InspectorLayout::Entity; } + // Prefabs layout logic + + // If this is the container entity for the root instance, treat it like a level entity. AZ::EntityId levelContainerEntityId = m_prefabPublicInterface->GetLevelInstanceContainerEntityId(); if (AZStd::find(m_selectedEntityIds.begin(), m_selectedEntityIds.end(), levelContainerEntityId) != m_selectedEntityIds.end()) { if (m_selectedEntityIds.size() > 1) { - return InspectorLayout::INVALID; + return InspectorLayout::Invalid; } else { - return InspectorLayout::LEVEL; + return InspectorLayout::Level; } } else { - return InspectorLayout::ENTITY; + // If this is the container entity for the currently focused prefab, utilize a separate layout. + if (auto prefabFocusPublicInterface = AZ::Interface::Get()) + { + AzFramework::EntityContextId editorEntityContextId = AzFramework::EntityContextId::CreateNull(); + EditorEntityContextRequestBus::BroadcastResult( + editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId); + + AZ::EntityId focusedPrefabContainerEntityId = + prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId); + if (AZStd::find(m_selectedEntityIds.begin(), m_selectedEntityIds.end(), focusedPrefabContainerEntityId) != + m_selectedEntityIds.end()) + { + if (m_selectedEntityIds.size() > 1) + { + return InspectorLayout::Invalid; + } + else + { + return InspectorLayout::ContainerEntityOfFocusedPrefab; + } + } + } } + + return InspectorLayout::Entity; } void EntityPropertyEditor::UpdateEntityDisplay() @@ -921,7 +948,7 @@ namespace AzToolsFramework InspectorLayout layout = GetCurrentInspectorLayout(); - if (layout == InspectorLayout::LEVEL) + if (!m_prefabsAreEnabled && layout == InspectorLayout::Level) { AZStd::string levelName; AzToolsFramework::EditorRequestBus::BroadcastResult(levelName, &AzToolsFramework::EditorRequests::GetLevelName); @@ -963,14 +990,19 @@ namespace AzToolsFramework InspectorLayout layout = GetCurrentInspectorLayout(); - if (layout == InspectorLayout::LEVEL) + if (layout == InspectorLayout::Level) { // The Level Inspector should only have a list of selectable components after the // level entity itself is valid (i.e. "selected"). return selection.empty() ? SelectionEntityTypeInfo::None : SelectionEntityTypeInfo::LevelEntity; } - if (layout == InspectorLayout::INVALID) + if (layout == InspectorLayout::ContainerEntityOfFocusedPrefab) + { + return selection.empty() ? SelectionEntityTypeInfo::None : SelectionEntityTypeInfo::ContainerEntityOfFocusedPrefab; + } + + if (layout == InspectorLayout::Invalid) { return SelectionEntityTypeInfo::Mixed; } @@ -1140,7 +1172,8 @@ namespace AzToolsFramework } } - bool isLevelLayout = GetCurrentInspectorLayout() == InspectorLayout::LEVEL; + bool isLevelLayout = GetCurrentInspectorLayout() == InspectorLayout::Level; + bool isContainerOfFocusedPrefabLayout = GetCurrentInspectorLayout() == InspectorLayout::ContainerEntityOfFocusedPrefab; m_gui->m_entityDetailsLabel->setText(entityDetailsLabelText); m_gui->m_entityDetailsLabel->setVisible(entityDetailsVisible); @@ -1148,10 +1181,14 @@ namespace AzToolsFramework m_gui->m_entityNameLabel->setVisible(hasEntitiesDisplayed); m_gui->m_entityIcon->setVisible(hasEntitiesDisplayed); m_gui->m_pinButton->setVisible(m_overrideSelectedEntityIds.empty() && hasEntitiesDisplayed && !m_isSystemEntityEditor); - m_gui->m_statusLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout); - m_gui->m_statusComboBox->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout); - m_gui->m_entityIdLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout); - m_gui->m_entityIdText->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout); + m_gui->m_statusLabel->setVisible( + hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout); + m_gui->m_statusComboBox->setVisible( + hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout); + m_gui->m_entityIdLabel->setVisible( + hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout); + m_gui->m_entityIdText->setVisible( + hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout); bool displayComponentSearchBox = hasEntitiesDisplayed; if (hasEntitiesDisplayed) @@ -1159,7 +1196,9 @@ namespace AzToolsFramework // Build up components to display SharedComponentArray sharedComponentArray; BuildSharedComponentArray(sharedComponentArray, - !(selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyStandardEntities || selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyPrefabEntities)); + !(selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyStandardEntities || + selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyPrefabEntities) || + selectionEntityTypeInfo == SelectionEntityTypeInfo::ContainerEntityOfFocusedPrefab); if (sharedComponentArray.size() == 0) { @@ -1175,7 +1214,8 @@ namespace AzToolsFramework UpdateEntityDisplay(); } - m_gui->m_darkBox->setVisible(displayComponentSearchBox && !m_isSystemEntityEditor && !isLevelLayout); + m_gui->m_darkBox->setVisible( + displayComponentSearchBox && !m_isSystemEntityEditor && !isLevelLayout && !isContainerOfFocusedPrefabLayout); m_gui->m_entitySearchBox->setVisible(displayComponentSearchBox); bool displayAddComponentMenu = CanAddComponentsToSelection(selectionEntityTypeInfo); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx index 5279cefa9f..8dd0ffc4ee 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx @@ -354,7 +354,8 @@ namespace AzToolsFramework OnlyLayerEntities, OnlyPrefabEntities, Mixed, - LevelEntity + LevelEntity, + ContainerEntityOfFocusedPrefab }; /** * Returns what kinds of entities are in the current selection. This is used because mixed selection @@ -364,7 +365,7 @@ namespace AzToolsFramework SelectionEntityTypeInfo GetSelectionEntityTypeInfo(const EntityIdList& selection) const; /** - * Returns true if a selection matching the passed in selection informatation allows components to be added. + * Returns true if a selection matching the passed in selection information allows components to be added. */ bool CanAddComponentsToSelection(const SelectionEntityTypeInfo& selectionEntityTypeInfo) const; @@ -581,9 +582,10 @@ namespace AzToolsFramework enum class InspectorLayout { - ENTITY = 0, // All selected entities are regular entities - LEVEL, // The selected entity is the level prefab container entity - INVALID // Other entities are selected alongside the level prefab container entity + Entity = 0, // All selected entities are regular entities. + Level, // The selected entity is the prefab container entity for the level prefab, or the slice level entity. + ContainerEntityOfFocusedPrefab, // The selected entity is the prefab container entity for the focused prefab. + Invalid // Other entities are selected alongside the level prefab container entity. }; InspectorLayout GetCurrentInspectorLayout() const; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 39c882b766..084b489aa1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -3604,6 +3605,16 @@ namespace AzToolsFramework m_selectedEntityIds.clear(); m_selectedEntityIds.reserve(selectedEntityIds.size()); AZStd::copy(selectedEntityIds.begin(), selectedEntityIds.end(), AZStd::inserter(m_selectedEntityIds, m_selectedEntityIds.end())); + + // Do not create manipulators for the container entity of the focused prefab. + if (auto prefabFocusPublicInterface = AZ::Interface::Get()) + { + AzFramework::EntityContextId editorEntityContextId = GetEntityContextId(); + if (AZ::EntityId focusRoot = prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId); focusRoot.IsValid()) + { + m_selectedEntityIds.erase(focusRoot); + } + } } void EditorTransformComponentSelection::OnTransformChanged( From e7035c5af6a71be30e1ac7cd1cf00bd7b099a633 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Wed, 10 Nov 2021 16:56:29 -0600 Subject: [PATCH 35/97] Fixed typo. Signed-off-by: Chris Galvan --- Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp b/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp index f6f0d8b655..ce9eab5f7e 100644 --- a/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp +++ b/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp @@ -2508,7 +2508,7 @@ namespace LandscapeCanvasEditor void MainWindow::OnPrefabFocusChanged() { - // Make sure to close any open graphs that aren't currently in p refab focus + // Make sure to close any open graphs that aren't currently in prefab focus // to prevent the user from making modifications outside of the allowed focus scope AZStd::vector dockWidgetsToClose; for (auto [entityId, dockWidgetId] : m_dockWidgetsByEntity) From d9443ec42ce8039f3e7c75a26835b1ab8c12426a Mon Sep 17 00:00:00 2001 From: nggieber Date: Wed, 10 Nov 2021 15:29:20 -0800 Subject: [PATCH 36/97] Addressed some PR feedback and continue filtering with same search string even after refresh Signed-off-by: nggieber --- Code/Tools/ProjectManager/Source/DownloadWorker.cpp | 4 +++- .../Source/GemCatalog/GemCatalogScreen.cpp | 10 +++++----- .../Source/GemCatalog/GemSortFilterProxyModel.cpp | 7 +++++-- .../Source/GemCatalog/GemSortFilterProxyModel.h | 2 +- .../Source/GemCatalog/GemUpdateDialog.cpp | 6 +++--- scripts/o3de/o3de/repo.py | 10 +++++----- 6 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/DownloadWorker.cpp b/Code/Tools/ProjectManager/Source/DownloadWorker.cpp index 5f5c64987b..a71a8dd486 100644 --- a/Code/Tools/ProjectManager/Source/DownloadWorker.cpp +++ b/Code/Tools/ProjectManager/Source/DownloadWorker.cpp @@ -25,7 +25,9 @@ namespace O3DE::ProjectManager m_downloadProgress = downloadProgress; emit UpdateProgress(downloadProgress); }; - AZ::Outcome gemInfoResult = PythonBindingsInterface::Get()->DownloadGem(m_gemName, gemDownloadProgress, true); + AZ::Outcome gemInfoResult = + PythonBindingsInterface::Get()->DownloadGem(m_gemName, gemDownloadProgress, /*force*/true); + if (gemInfoResult.IsSuccess()) { emit Done(""); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 3a513fdc1d..cff9a28db3 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -106,7 +106,7 @@ namespace O3DE::ProjectManager FillModel(projectPath); - m_proxyModel->ResetFilters(); + m_proxyModel->ResetFilters(false); m_proxyModel->sort(/*column=*/0); if (m_filterWidget) @@ -235,7 +235,7 @@ namespace O3DE::ProjectManager m_proxyModel->sort(/*column=*/0); // temporary, until we can refresh filter counts - m_proxyModel->ResetFilters(); + m_proxyModel->ResetFilters(false); m_filterWidget->ResetAllFilters(); // Reselect the same selection to proc UI updates @@ -323,15 +323,15 @@ namespace O3DE::ProjectManager { QMessageBox::critical( this, tr("Operation failed"), - tr("Failed to refresh gem repo %1
Error:
%2").arg(selectedGemRepoUri, refreshResult.GetError().c_str())); + tr("Failed to refresh gem repository %1
Error:
%2").arg(selectedGemRepoUri, refreshResult.GetError().c_str())); } } // If repo uri isn't specified warn user that repo might not be refreshed else { int result = QMessageBox::warning( - this, tr("Gem Repo Unspecified"), - tr("The repo for %1 is unspecfied. Repo cannot be automatically refreshed. " + this, tr("Gem Repository Unspecified"), + tr("The repo for %1 is unspecfied. Repository cannot be automatically refreshed. " "Please ensure this gem's repo is refreshed before attempting to update.") .arg(selectedDisplayGemName), QMessageBox::Cancel, QMessageBox::Ok); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.cpp index 32d0e2fee9..a32492cf1e 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.cpp @@ -204,9 +204,12 @@ namespace O3DE::ProjectManager emit OnInvalidated(); } - void GemSortFilterProxyModel::ResetFilters() + void GemSortFilterProxyModel::ResetFilters(bool clearSearchString) { - m_searchString.clear(); + if (clearSearchString) + { + m_searchString.clear(); + } m_gemSelectedFilter = GemSelected::NoFilter; m_gemActiveFilter = GemActive::NoFilter; m_gemOriginFilter = {}; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.h index ab739e62f9..0c58d66ccf 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemSortFilterProxyModel.h @@ -70,7 +70,7 @@ namespace O3DE::ProjectManager void SetFeatures(const QSet& features) { m_featureFilter = features; InvalidateFilter(); } void InvalidateFilter(); - void ResetFilters(); + void ResetFilters(bool clearSearchString = true); signals: void OnInvalidated(); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp index dab4a2a0fe..3e68c597de 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp @@ -30,8 +30,8 @@ namespace O3DE::ProjectManager setLayout(layout); // Body - QLabel* subTitleLabel = new QLabel(tr("%1Update to the latest version of %2?").arg( - updateAvaliable ? "" : tr("Force "), gemName)); + QLabel* subTitleLabel = new QLabel(tr("%1 to the latest version of %2?").arg( + updateAvaliable ? tr("Update") : tr("Force update"), gemName)); subTitleLabel->setObjectName("gemCatalogDialogSubTitle"); layout->addWidget(subTitleLabel); @@ -46,7 +46,7 @@ namespace O3DE::ProjectManager bodyLabel->setFixedSize(QSize(440, 80)); layout->addWidget(bodyLabel); - layout->addSpacing(40); + layout->addSpacing(); // Buttons QDialogButtonBox* dialogButtons = new QDialogButtonBox(); diff --git a/scripts/o3de/o3de/repo.py b/scripts/o3de/o3de/repo.py index 1462015630..c8fac38605 100644 --- a/scripts/o3de/o3de/repo.py +++ b/scripts/o3de/o3de/repo.py @@ -74,11 +74,11 @@ def process_add_o3de_repo(file_name: str or pathlib.Path, manifest_json_uri = f'{o3de_object_uri}/{manifest_json}' manifest_json_sha256 = hashlib.sha256(manifest_json_uri.encode()) cache_file = cache_folder / str(manifest_json_sha256.hexdigest() + '.json') - if cache_file.is_file(): - parsed_uri = urllib.parse.urlparse(manifest_json_uri) - download_file_result = utils.download_file(parsed_uri, cache_file, True) - if download_file_result != 0: - return download_file_result + + parsed_uri = urllib.parse.urlparse(manifest_json_uri) + download_file_result = utils.download_file(parsed_uri, cache_file, True) + if download_file_result != 0: + return download_file_result # Having a repo is also optional repo_list = [] From 9c57c9e64fb67cc78bad3834f279f4e71e4f07fa Mon Sep 17 00:00:00 2001 From: hershey5045 <43485729+hershey5045@users.noreply.github.com> Date: Wed, 10 Nov 2021 16:03:50 -0800 Subject: [PATCH 37/97] Fix track view bug where postfxs do not render correctly. (#5465) * Fix track view bug where postfxs do not render correctly. Signed-off-by: hershey5045 <43485729+hershey5045@users.noreply.github.com> * Reduce scope and add comments. Signed-off-by: hershey5045 <43485729+hershey5045@users.noreply.github.com> --- .../TrackView/AtomOutputFrameCapture.cpp | 27 ++++++++++++++++++- .../Editor/TrackView/AtomOutputFrameCapture.h | 3 ++- .../TrackView/SequenceBatchRenderDialog.cpp | 6 ++++- .../PostProcessFeatureProcessor.cpp | 21 ++++++++++++++- .../PostProcess/PostProcessFeatureProcessor.h | 6 +++++ .../PostProcessing/EyeAdaptationPass.cpp | 4 +-- 6 files changed, 61 insertions(+), 6 deletions(-) diff --git a/Code/Editor/TrackView/AtomOutputFrameCapture.cpp b/Code/Editor/TrackView/AtomOutputFrameCapture.cpp index 94451e6914..5943e3c2d7 100644 --- a/Code/Editor/TrackView/AtomOutputFrameCapture.cpp +++ b/Code/Editor/TrackView/AtomOutputFrameCapture.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -47,18 +48,42 @@ namespace TrackView AZ::Name viewName = AZ::Name("MainCamera"); m_view = AZ::RPI::View::CreateView(viewName, AZ::RPI::View::UsageCamera); m_renderPipeline->SetDefaultView(m_view); + m_targetView = scene.GetDefaultRenderPipeline()->GetDefaultView(); + if (AZ::Render::PostProcessFeatureProcessor* fp = scene.GetFeatureProcessor()) + { + // This will be set again to mimic the active camera in UpdateView + fp->SetViewAlias(m_view, m_targetView); + } } void AtomOutputFrameCapture::DestroyPipeline(AZ::RPI::Scene& scene) { + if (AZ::Render::PostProcessFeatureProcessor* fp = scene.GetFeatureProcessor()) + { + // Remove view alias introduced in CreatePipeline and UpdateView + fp->RemoveViewAlias(m_view); + } scene.RemoveRenderPipeline(m_renderPipeline->GetId()); m_passHierarchy.clear(); m_renderPipeline.reset(); m_view.reset(); + m_targetView.reset(); } - void AtomOutputFrameCapture::UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection) + void AtomOutputFrameCapture::UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection, const AZ::RPI::ViewPtr targetView) { + if (targetView && targetView != m_targetView) + { + if (AZ::RPI::Scene* scene = SceneFromGameEntityContext()) + { + if (AZ::Render::PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor()) + { + fp->SetViewAlias(m_view, targetView); + m_targetView = targetView; + } + } + } + m_view->SetCameraTransform(cameraTransform); m_view->SetViewToClipMatrix(cameraProjection); } diff --git a/Code/Editor/TrackView/AtomOutputFrameCapture.h b/Code/Editor/TrackView/AtomOutputFrameCapture.h index 2686a81c99..4719ab08e5 100644 --- a/Code/Editor/TrackView/AtomOutputFrameCapture.h +++ b/Code/Editor/TrackView/AtomOutputFrameCapture.h @@ -39,11 +39,12 @@ namespace TrackView CaptureFinishedCallback captureFinishedCallback); //! Update the internal view that is associated with the created pipeline. - void UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection); + void UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection, const AZ::RPI::ViewPtr targetView = nullptr); private: AZ::RPI::RenderPipelinePtr m_renderPipeline; //!< The internal render pipeline. AZ::RPI::ViewPtr m_view; //!< The view associated with the render pipeline. + AZ::RPI::ViewPtr m_targetView; //!< The view that this render pipeline will mimic. AZStd::vector m_passHierarchy; //!< Pass hierarchy (includes pipelineName and CopyToSwapChain). CaptureFinishedCallback m_captureFinishedCallback; //!< Stored callback called from OnCaptureFinished. diff --git a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp index d7901e338a..a796a8ce37 100644 --- a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp +++ b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp @@ -16,6 +16,7 @@ #include #include +#include // Qt #include @@ -91,9 +92,12 @@ namespace static void UpdateAtomOutputFrameCaptureView(TrackView::AtomOutputFrameCapture& atomOutputFrameCapture, const int width, const int height) { const AZ::EntityId activeCameraEntityId = TrackView::ActiveCameraEntityId(); + AZ::RPI::ViewPtr view = nullptr; + AZ::RPI::ViewProviderBus::EventResult(view, activeCameraEntityId, &AZ::RPI::ViewProvider::GetView); atomOutputFrameCapture.UpdateView( TrackView::TransformFromEntityId(activeCameraEntityId), - TrackView::ProjectionFromCameraEntityId(activeCameraEntityId, static_cast(width), static_cast(height))); + TrackView::ProjectionFromCameraEntityId(activeCameraEntityId, aznumeric_cast(width), aznumeric_cast(height)), + view); } CSequenceBatchRenderDialog::CSequenceBatchRenderDialog(float fps, QWidget* pParent /* = nullptr */) diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.cpp index a9d8d5105f..c8e683e1d1 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.cpp @@ -37,6 +37,11 @@ namespace AZ m_currentTime = AZStd::chrono::system_clock::now(); } + void PostProcessFeatureProcessor::Deactivate() + { + m_viewAliasMap.clear(); + } + void PostProcessFeatureProcessor::UpdateTime() { AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now(); @@ -45,6 +50,16 @@ namespace AZ m_deltaTime = deltaTime.count(); } + void PostProcessFeatureProcessor::SetViewAlias(const AZ::RPI::ViewPtr sourceView, const AZ::RPI::ViewPtr targetView) + { + m_viewAliasMap[sourceView.get()] = targetView.get(); + } + + void PostProcessFeatureProcessor::RemoveViewAlias(const AZ::RPI::ViewPtr sourceView) + { + m_viewAliasMap.erase(sourceView.get()); + } + void PostProcessFeatureProcessor::Simulate(const FeatureProcessor::SimulatePacket& packet) { AZ_PROFILE_SCOPE(RPI, "PostProcessFeatureProcessor: Simulate"); @@ -200,8 +215,12 @@ namespace AZ AZ::Render::PostProcessSettings* PostProcessFeatureProcessor::GetLevelSettingsFromView(AZ::RPI::ViewPtr view) { + // check for view aliases first + auto viewAliasiterator = m_viewAliasMap.find(view.get()); + + // Use the view alias if it exists + auto settingsIterator = m_blendedPerViewSettings.find(viewAliasiterator != m_viewAliasMap.end() ? viewAliasiterator->second : view.get()); // If no settings for the view is found, the global settings is returned. - auto settingsIterator = m_blendedPerViewSettings.find(view.get()); return settingsIterator != m_blendedPerViewSettings.end() ? &settingsIterator->second : m_globalAggregateLevelSettings.get(); diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.h index 2c1cc98449..10af993d9d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.h @@ -34,6 +34,7 @@ namespace AZ //! FeatureProcessor overrides... void Activate() override; + void Deactivate() override; void Simulate(const FeatureProcessor::SimulatePacket& packet) override; //! PostProcessFeatureProcessorInterface... @@ -43,6 +44,9 @@ namespace AZ void OnPostProcessSettingsChanged() override; PostProcessSettings* GetLevelSettingsFromView(AZ::RPI::ViewPtr view); + void SetViewAlias(const AZ::RPI::ViewPtr sourceView, const AZ::RPI::ViewPtr targetView); + void RemoveViewAlias(const AZ::RPI::ViewPtr sourceView); + private: PostProcessFeatureProcessor(const PostProcessFeatureProcessor&) = delete; @@ -83,6 +87,8 @@ namespace AZ // Each camera/view will have its own PostProcessSettings AZStd::unordered_map m_blendedPerViewSettings; + // This is used for mimicking a postfx setting of a different view + AZStd::unordered_map m_viewAliasMap; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/EyeAdaptationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/EyeAdaptationPass.cpp index 862892ad1b..5683241693 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/EyeAdaptationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/EyeAdaptationPass.cpp @@ -81,7 +81,7 @@ namespace AZ if (scene) { PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor(); - AZ::RPI::ViewPtr view = GetView(); + AZ::RPI::ViewPtr view = GetRenderPipeline()->GetDefaultView(); if (fp) { PostProcessSettings* postProcessSettings = fp->GetLevelSettingsFromView(view); @@ -110,7 +110,7 @@ namespace AZ PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor(); if (fp) { - AZ::RPI::ViewPtr view = GetView(); + AZ::RPI::ViewPtr view = GetRenderPipeline()->GetDefaultView(); PostProcessSettings* postProcessSettings = fp->GetLevelSettingsFromView(view); if (postProcessSettings) { From 0b6c3382f14bf8385bd5bc3a8fd0d09c435ba0d7 Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Wed, 10 Nov 2021 16:05:38 -0800 Subject: [PATCH 38/97] Add an additional comment Signed-off-by: AMZN-Phil --- .../ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp index 41e292d93c..4e3296a91f 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp @@ -297,6 +297,7 @@ namespace O3DE::ProjectManager QLabel* progressLabel = gemToUpdate->findChild("DownloadProgressLabel"); QProgressBar* progressBar = gemToUpdate->findChild("DownloadProgressBar"); + // totalBytes can be 0 if the server does not return a content-length for the object if (totalBytes != 0) { int downloadPercentage = static_cast((bytesDownloaded / static_cast(totalBytes)) * 100); From e98a65a7351da2e36cddfc8abad0cff906fa87c9 Mon Sep 17 00:00:00 2001 From: moraaar Date: Thu, 11 Nov 2021 09:31:28 +0000 Subject: [PATCH 39/97] Fixed casing of all .fbx.assetinfo files to match their .fbx (#5490) Signed-off-by: moraaar --- .../{r0-b_body.fbx.assetinfo => R0-B_Body.fbx.assetinfo} | 0 .../{r0-b_body.fbx.assetinfo => R0-B_Body.fbx.assetinfo} | 0 ...dev_sedan_r0-b.fbx.assetinfo => _dev_Sedan_r0-b.fbx.assetinfo} | 0 ...dev_sedan_r0-b.fbx.assetinfo => _dev_Sedan_r0-b.fbx.assetinfo} | 0 ...opy.fbx.assetinfo => rin_skeleton_newgeo - Copy.fbx.assetinfo} | 0 ...dev_sedan_r0-b.fbx.assetinfo => _dev_Sedan_r0-b.fbx.assetinfo} | 0 ...dev_sedan_r0-b.fbx.assetinfo => _dev_Sedan_r0-b.fbx.assetinfo} | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename AutomatedTesting/Assets/Physics/Collider_PxMeshAutoAssigned/SphereBot/{r0-b_body.fbx.assetinfo => R0-B_Body.fbx.assetinfo} (100%) rename AutomatedTesting/Assets/Physics/Collider_PxMeshConvexMeshCollides/SphereBot/{r0-b_body.fbx.assetinfo => R0-B_Body.fbx.assetinfo} (100%) rename AutomatedTesting/Levels/Physics/ForceRegion_ImpulsesPxMeshShapedRigidBody/PhysXSedan/{_dev_sedan_r0-b.fbx.assetinfo => _dev_Sedan_r0-b.fbx.assetinfo} (100%) rename AutomatedTesting/Levels/Physics/ForceRegion_PxMeshShapedForce/PhysXSedan/{_dev_sedan_r0-b.fbx.assetinfo => _dev_Sedan_r0-b.fbx.assetinfo} (100%) rename AutomatedTesting/Levels/Physics/Material_DefaultMaterialLibraryChangesWork/{rin_skeleton_newgeo - copy.fbx.assetinfo => rin_skeleton_newgeo - Copy.fbx.assetinfo} (100%) rename AutomatedTesting/Levels/Physics/Physics_WorldBodyBusWorksOnEditorComponents/PhysXSedan/{_dev_sedan_r0-b.fbx.assetinfo => _dev_Sedan_r0-b.fbx.assetinfo} (100%) rename AutomatedTesting/Levels/Physics/RigidBody_COM_ComputingWorks/PhysXSedan/{_dev_sedan_r0-b.fbx.assetinfo => _dev_Sedan_r0-b.fbx.assetinfo} (100%) diff --git a/AutomatedTesting/Assets/Physics/Collider_PxMeshAutoAssigned/SphereBot/r0-b_body.fbx.assetinfo b/AutomatedTesting/Assets/Physics/Collider_PxMeshAutoAssigned/SphereBot/R0-B_Body.fbx.assetinfo similarity index 100% rename from AutomatedTesting/Assets/Physics/Collider_PxMeshAutoAssigned/SphereBot/r0-b_body.fbx.assetinfo rename to AutomatedTesting/Assets/Physics/Collider_PxMeshAutoAssigned/SphereBot/R0-B_Body.fbx.assetinfo diff --git a/AutomatedTesting/Assets/Physics/Collider_PxMeshConvexMeshCollides/SphereBot/r0-b_body.fbx.assetinfo b/AutomatedTesting/Assets/Physics/Collider_PxMeshConvexMeshCollides/SphereBot/R0-B_Body.fbx.assetinfo similarity index 100% rename from AutomatedTesting/Assets/Physics/Collider_PxMeshConvexMeshCollides/SphereBot/r0-b_body.fbx.assetinfo rename to AutomatedTesting/Assets/Physics/Collider_PxMeshConvexMeshCollides/SphereBot/R0-B_Body.fbx.assetinfo diff --git a/AutomatedTesting/Levels/Physics/ForceRegion_ImpulsesPxMeshShapedRigidBody/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo b/AutomatedTesting/Levels/Physics/ForceRegion_ImpulsesPxMeshShapedRigidBody/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo similarity index 100% rename from AutomatedTesting/Levels/Physics/ForceRegion_ImpulsesPxMeshShapedRigidBody/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo rename to AutomatedTesting/Levels/Physics/ForceRegion_ImpulsesPxMeshShapedRigidBody/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo diff --git a/AutomatedTesting/Levels/Physics/ForceRegion_PxMeshShapedForce/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo b/AutomatedTesting/Levels/Physics/ForceRegion_PxMeshShapedForce/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo similarity index 100% rename from AutomatedTesting/Levels/Physics/ForceRegion_PxMeshShapedForce/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo rename to AutomatedTesting/Levels/Physics/ForceRegion_PxMeshShapedForce/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo diff --git a/AutomatedTesting/Levels/Physics/Material_DefaultMaterialLibraryChangesWork/rin_skeleton_newgeo - copy.fbx.assetinfo b/AutomatedTesting/Levels/Physics/Material_DefaultMaterialLibraryChangesWork/rin_skeleton_newgeo - Copy.fbx.assetinfo similarity index 100% rename from AutomatedTesting/Levels/Physics/Material_DefaultMaterialLibraryChangesWork/rin_skeleton_newgeo - copy.fbx.assetinfo rename to AutomatedTesting/Levels/Physics/Material_DefaultMaterialLibraryChangesWork/rin_skeleton_newgeo - Copy.fbx.assetinfo diff --git a/AutomatedTesting/Levels/Physics/Physics_WorldBodyBusWorksOnEditorComponents/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo b/AutomatedTesting/Levels/Physics/Physics_WorldBodyBusWorksOnEditorComponents/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo similarity index 100% rename from AutomatedTesting/Levels/Physics/Physics_WorldBodyBusWorksOnEditorComponents/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo rename to AutomatedTesting/Levels/Physics/Physics_WorldBodyBusWorksOnEditorComponents/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo diff --git a/AutomatedTesting/Levels/Physics/RigidBody_COM_ComputingWorks/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo b/AutomatedTesting/Levels/Physics/RigidBody_COM_ComputingWorks/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo similarity index 100% rename from AutomatedTesting/Levels/Physics/RigidBody_COM_ComputingWorks/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo rename to AutomatedTesting/Levels/Physics/RigidBody_COM_ComputingWorks/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo From f24c3d3457e1b773b2615d0864820783a8acb5ba Mon Sep 17 00:00:00 2001 From: galibzon <66021303+galibzon@users.noreply.github.com> Date: Thu, 11 Nov 2021 05:24:33 -0600 Subject: [PATCH 40/97] ASV Trace::Assert Environment.h(438) You are using an invalid variable, (#5521) the owner has removed it! This fixes the issue by forcing NameDictionary to not transfer ownership. This means ComponentApplication()::Destroy will fully destroy the NameDictionary before the OS::Allocator is destroyed. In Windows the bug was not happening when running AssetProcessorBatch because for Windows, _exit() is called before the application shutsdown forcing all module to properly decrease the reference count of EnvironmentVaqriableHolderBase::m_useCount for NameDictionary. In MacOS, there's no _exit() so when the NameDictionary destructor was being called before existing the application the reference count wouldn't be 0, and would eventually try to destry the NameDictionary BUT the OS::Allocator was already destroyed. Signed-off-by: galibzon <66021303+galibzon@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp index 3047a2894e..6cba54a17f 100644 --- a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp +++ b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp @@ -50,7 +50,12 @@ namespace AZ if (!s_instance) { - s_instance = Environment::FindVariable(NameDictionaryInstanceName); + // Because the NameDictionary allocates memory using the AZ::Allocator and it is created + // in the executable memory space, it's ownership cannot be transferred to other module memory spaces + // Otherwise this could cause the the NameDictionary to be destroyed in static de-init + // after the AZ::Allocators have been destroyed + // Therefore we supply the isTransferOwnership value of false using CreateVariableEx + s_instance = AZ::Environment::CreateVariableEx(NameDictionaryInstanceName, true, false); } return s_instance.IsConstructed(); From c3093edffeaada3e1eb5aabfe301bf3b139fc986 Mon Sep 17 00:00:00 2001 From: sphrose <82213493+sphrose@users.noreply.github.com> Date: Thu, 11 Nov 2021 12:12:18 +0000 Subject: [PATCH 41/97] Redoing tests that got lost when TerrainPhysicsManager was merged. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> --- .../Tests/TerrainHeightGradientListTests.cpp | 93 ++++++++++++------ .../Tests/TerrainSurfaceGradientListTests.cpp | 97 +++++++++---------- 2 files changed, 106 insertions(+), 84 deletions(-) diff --git a/Gems/Terrain/Code/Tests/TerrainHeightGradientListTests.cpp b/Gems/Terrain/Code/Tests/TerrainHeightGradientListTests.cpp index ec500d6ada..535aacb8c8 100644 --- a/Gems/Terrain/Code/Tests/TerrainHeightGradientListTests.cpp +++ b/Gems/Terrain/Code/Tests/TerrainHeightGradientListTests.cpp @@ -19,7 +19,6 @@ #include using ::testing::_; -using ::testing::AtLeast; using ::testing::Mock; using ::testing::NiceMock; using ::testing::Return; @@ -29,8 +28,6 @@ class TerrainHeightGradientListComponentTest : public ::testing::Test protected: AZ::ComponentApplication m_app; - AZStd::unique_ptr m_entity; - void SetUp() override { AZ::ComponentApplication::Descriptor appDesc; @@ -46,47 +43,74 @@ protected: m_app.Destroy(); } - void CreateEntity() + AZStd::unique_ptr CreateEntity() { - m_entity = AZStd::make_unique(); - ASSERT_TRUE(m_entity); - - // Create the required box component. - UnitTest::MockAxisAlignedBoxShapeComponent* boxComponent = m_entity->CreateComponent(); - m_app.RegisterComponentDescriptor(boxComponent->CreateDescriptor()); + auto entity = AZStd::make_unique(); + entity->Init(); + return entity; + } + Terrain::TerrainHeightGradientListComponent* AddHeightGradientListToEntity(AZ::Entity* entity) + { // Create the TerrainHeightGradientListComponent with an entity in its configuration. Terrain::TerrainHeightGradientListConfig config; - config.m_gradientEntities.push_back(m_entity->GetId()); + config.m_gradientEntities.push_back(entity->GetId()); - Terrain::TerrainHeightGradientListComponent* heightGradientListComponent = m_entity->CreateComponent(config); + auto heightGradientListComponent = entity->CreateComponent(config); m_app.RegisterComponentDescriptor(heightGradientListComponent->CreateDescriptor()); - // Create a MockTerrainLayerSpawnerComponent to provide the required TerrainAreaService. - UnitTest::MockTerrainLayerSpawnerComponent* layerSpawner = m_entity->CreateComponent(); - m_app.RegisterComponentDescriptor(layerSpawner->CreateDescriptor()); + return heightGradientListComponent; + } - m_entity->Init(); + void AddRequiredComponetsToEntity(AZ::Entity* entity) + { + // Create the required box component. + UnitTest::MockAxisAlignedBoxShapeComponent* boxComponent = entity->CreateComponent(); + m_app.RegisterComponentDescriptor(boxComponent->CreateDescriptor()); + + // Create a MockTerrainLayerSpawnerComponent to provide the required TerrainAreaService. + UnitTest::MockTerrainLayerSpawnerComponent* layerSpawner = entity->CreateComponent(); + m_app.RegisterComponentDescriptor(layerSpawner->CreateDescriptor()); } }; +TEST_F(TerrainHeightGradientListComponentTest, MissingRequiredComponentsActivateFailure) +{ + auto entity = CreateEntity(); + + AddHeightGradientListToEntity(entity.get()); + + const AZ::Entity::DependencySortOutcome sortOutcome = entity->EvaluateDependenciesGetDetails(); + EXPECT_FALSE(sortOutcome.IsSuccess()); + + entity.reset(); +} + TEST_F(TerrainHeightGradientListComponentTest, ActivateEntityActivateSuccess) { // Check that the entity activates. - CreateEntity(); + auto entity = CreateEntity(); - m_entity->Activate(); - EXPECT_EQ(m_entity->GetState(), AZ::Entity::State::Active); + AddHeightGradientListToEntity(entity.get()); - m_entity.reset(); + AddRequiredComponetsToEntity(entity.get()); + + entity->Activate(); + EXPECT_EQ(entity->GetState(), AZ::Entity::State::Active); + + entity.reset(); } TEST_F(TerrainHeightGradientListComponentTest, TerrainHeightGradientRefreshesTerrainSystem) { // Check that the HeightGradientListComponent informs the TerrainSystem when the composition changes. - CreateEntity(); + auto entity = CreateEntity(); - m_entity->Activate(); + AddHeightGradientListToEntity(entity.get()); + + AddRequiredComponetsToEntity(entity.get()); + + entity->Activate(); NiceMock terrainSystem; @@ -95,32 +119,36 @@ TEST_F(TerrainHeightGradientListComponentTest, TerrainHeightGradientRefreshesTer // and once when the HeightGradientListComponent gets the OnCompositionChanged directly through the DependencyNotificationBus. EXPECT_CALL(terrainSystem, RefreshArea(_, _)).Times(2); - LmbrCentral::DependencyNotificationBus::Event(m_entity->GetId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged); + LmbrCentral::DependencyNotificationBus::Event(entity->GetId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged); // Stop the EXPECT_CALL check now, as OnCompositionChanged will get called twice again during the reset. Mock::VerifyAndClearExpectations(&terrainSystem); - m_entity.reset(); + entity.reset(); } TEST_F(TerrainHeightGradientListComponentTest, TerrainHeightGradientListReturnsHeights) { // Check that the HeightGradientListComponent returns expected height values. - CreateEntity(); + auto entity = CreateEntity(); - NiceMock heightfieldRequestBus(m_entity->GetId()); + AddHeightGradientListToEntity(entity.get()); - m_entity->Activate(); + AddRequiredComponetsToEntity(entity.get()); + + NiceMock heightfieldRequestBus(entity->GetId()); + + entity->Activate(); const float mockGradientValue = 0.25f; - NiceMock gradientRequests(m_entity->GetId()); + NiceMock gradientRequests(entity->GetId()); ON_CALL(gradientRequests, GetValue).WillByDefault(Return(mockGradientValue)); // Setup a mock to provide the encompassing Aabb to the HeightGradientListComponent. const float min = 0.0f; const float max = 1000.0f; const AZ::Aabb aabb = AZ::Aabb::CreateFromMinMax(AZ::Vector3(min), AZ::Vector3(max)); - NiceMock mockShapeRequests(m_entity->GetId()); + NiceMock mockShapeRequests(entity->GetId()); ON_CALL(mockShapeRequests, GetEncompassingAabb).WillByDefault(Return(aabb)); const float worldMax = 10000.0f; @@ -130,17 +158,18 @@ TEST_F(TerrainHeightGradientListComponentTest, TerrainHeightGradientListReturnsH ON_CALL(mockterrainDataRequests, GetTerrainAabb).WillByDefault(Return(worldAabb)); // Ensure the cached values in the HeightGradientListComponent are up to date. - LmbrCentral::DependencyNotificationBus::Event(m_entity->GetId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged); + LmbrCentral::DependencyNotificationBus::Event(entity->GetId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged); const AZ::Vector3 inPosition = AZ::Vector3::CreateZero(); AZ::Vector3 outPosition = AZ::Vector3::CreateZero(); bool terrainExists = false; - Terrain::TerrainAreaHeightRequestBus::Event(m_entity->GetId(), &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, terrainExists); + Terrain::TerrainAreaHeightRequestBus::Event( + entity->GetId(), &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, terrainExists); const float height = outPosition.GetZ(); EXPECT_NEAR(height, mockGradientValue * max, 0.01f); - m_entity.reset(); + entity.reset(); } diff --git a/Gems/Terrain/Code/Tests/TerrainSurfaceGradientListTests.cpp b/Gems/Terrain/Code/Tests/TerrainSurfaceGradientListTests.cpp index dea861bda5..fb94d2320d 100644 --- a/Gems/Terrain/Code/Tests/TerrainSurfaceGradientListTests.cpp +++ b/Gems/Terrain/Code/Tests/TerrainSurfaceGradientListTests.cpp @@ -11,8 +11,6 @@ #include using ::testing::NiceMock; -using ::testing::AtLeast; -using ::testing::_; using ::testing::Return; namespace UnitTest @@ -22,10 +20,6 @@ namespace UnitTest protected: AZ::ComponentApplication m_app; - AZStd::unique_ptr m_entity; - UnitTest::MockTerrainLayerSpawnerComponent* m_layerSpawnerComponent = nullptr; - AZStd::unique_ptr m_gradientEntity1, m_gradientEntity2; - const AZStd::string surfaceTag1 = "testtag1"; const AZStd::string surfaceTag2 = "testtag2"; @@ -37,81 +31,80 @@ namespace UnitTest appDesc.m_stackRecordLevels = 20; m_app.Create(appDesc); - - CreateEntities(); } void TearDown() override { - m_gradientEntity2.reset(); - m_gradientEntity1.reset(); - m_entity.reset(); - m_app.Destroy(); } - void CreateEntities() + AZStd::unique_ptr CreateEntity() { - m_entity = AZStd::make_unique(); - ASSERT_TRUE(m_entity); - - m_entity->Init(); - - m_gradientEntity1 = AZStd::make_unique(); - ASSERT_TRUE(m_gradientEntity1); - - m_gradientEntity1->Init(); - - m_gradientEntity2 = AZStd::make_unique(); - ASSERT_TRUE(m_gradientEntity2); - - m_gradientEntity2->Init(); + auto entity = AZStd::make_unique(); + entity->Init(); + return entity; } - void AddSurfaceGradientListToEntities() + UnitTest::MockTerrainLayerSpawnerComponent* AddRequiredComponentsToEntity(AZ::Entity* entity) { - m_layerSpawnerComponent = m_entity->CreateComponent(); - m_app.RegisterComponentDescriptor(m_layerSpawnerComponent->CreateDescriptor()); + auto layerSpawnerComponent = entity->CreateComponent(); + m_app.RegisterComponentDescriptor(layerSpawnerComponent->CreateDescriptor()); - Terrain::TerrainSurfaceGradientListConfig config; - - Terrain::TerrainSurfaceGradientMapping mapping1; - mapping1.m_gradientEntityId = m_gradientEntity1->GetId(); - mapping1.m_surfaceTag = SurfaceData::SurfaceTag(surfaceTag1); - config.m_gradientSurfaceMappings.emplace_back(mapping1); - - Terrain::TerrainSurfaceGradientMapping mapping2; - mapping2.m_gradientEntityId = m_gradientEntity2->GetId(); - mapping2.m_surfaceTag = SurfaceData::SurfaceTag(surfaceTag2); - config.m_gradientSurfaceMappings.emplace_back(mapping2); - - Terrain::TerrainSurfaceGradientListComponent* terrainSurfaceGradientListComponent = - m_entity->CreateComponent(config); - m_app.RegisterComponentDescriptor(terrainSurfaceGradientListComponent->CreateDescriptor()); + return layerSpawnerComponent; } }; + TEST_F(TerrainSurfaceGradientListTest, SurfaceGradientMissingRequirementsActivateFails) + { + auto entity = CreateEntity(); + + auto terrainSurfaceGradientListComponent = entity->CreateComponent(); + m_app.RegisterComponentDescriptor(terrainSurfaceGradientListComponent->CreateDescriptor()); + + const AZ::Entity::DependencySortOutcome sortOutcome = entity->EvaluateDependenciesGetDetails(); + EXPECT_FALSE(sortOutcome.IsSuccess()); + + entity.reset(); + } + + TEST_F(TerrainSurfaceGradientListTest, SurfaceGradientActivateSuccess) + { + auto entity = CreateEntity(); + + AddRequiredComponentsToEntity(entity.get()); + + auto terrainSurfaceGradientListComponent = entity->CreateComponent(); + m_app.RegisterComponentDescriptor(terrainSurfaceGradientListComponent->CreateDescriptor()); + + entity->Activate(); + + + + entity.reset(); + } + TEST_F(TerrainSurfaceGradientListTest, SurfaceGradientReturnsSurfaceWeights) { // When there is more than one surface/weight defined and added to the component, they should all // be returned. The component isn't required to return them in descending order. - AddSurfaceGradientListToEntities(); + auto entity = CreateEntity(); - m_entity->Activate(); - m_gradientEntity1->Activate(); - m_gradientEntity2->Activate(); + AddRequiredComponentsToEntity(entity.get()); + + auto gradientEntity1 = CreateEntity(); + auto gradientEntity2 = CreateEntity(); const float gradient1Value = 0.3f; - NiceMock mockGradientRequests1(m_gradientEntity1->GetId()); + NiceMock mockGradientRequests1(gradientEntity1->GetId()); ON_CALL(mockGradientRequests1, GetValue).WillByDefault(Return(gradient1Value)); const float gradient2Value = 1.0f; - NiceMock mockGradientRequests2(m_gradientEntity2->GetId()); + NiceMock mockGradientRequests2(gradientEntity2->GetId()); ON_CALL(mockGradientRequests2, GetValue).WillByDefault(Return(gradient2Value)); AzFramework::SurfaceData::SurfaceTagWeightList weightList; Terrain::TerrainAreaSurfaceRequestBus::Event( - m_entity->GetId(), &Terrain::TerrainAreaSurfaceRequestBus::Events::GetSurfaceWeights, AZ::Vector3::CreateZero(), weightList); + entity->GetId(), &Terrain::TerrainAreaSurfaceRequestBus::Events::GetSurfaceWeights, AZ::Vector3::CreateZero(), weightList); AZ::Crc32 expectedCrcList[] = { AZ::Crc32(surfaceTag1), AZ::Crc32(surfaceTag2) }; const float expectedWeightList[] = { gradient1Value, gradient2Value }; From 039d2fc0c4b82ba97acb3d41a87c858e2da7649f Mon Sep 17 00:00:00 2001 From: John Date: Thu, 11 Nov 2021 12:13:55 +0000 Subject: [PATCH 42/97] Remove SurfaceManipulator. Signed-off-by: John --- .../EditorTransformComponentSelection.cpp | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 39c882b766..e9af69dc36 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -1334,39 +1334,6 @@ namespace AzToolsFramework EndRecordManipulatorCommand(); }); - // surface - translationManipulators->InstallSurfaceManipulatorMouseDownCallback( - [this, manipulatorEntityIds]([[maybe_unused]] const SurfaceManipulator::Action& action) - { - BuildSortedEntityIdVectorFromEntityIdMap(m_entityIdManipulators.m_lookups, manipulatorEntityIds->m_entityIds); - - InitializeTranslationLookup(m_entityIdManipulators); - - m_axisPreview.m_translation = m_entityIdManipulators.m_manipulators->GetLocalTransform().GetTranslation(); - m_axisPreview.m_orientation = QuaternionFromTransformNoScaling(m_entityIdManipulators.m_manipulators->GetLocalTransform()); - - // [ref 1.] - BeginRecordManipulatorCommand(); - }); - - translationManipulators->InstallSurfaceManipulatorMouseMoveCallback( - [this, prevModifiers, manipulatorEntityIds](const SurfaceManipulator::Action& action) mutable - { - UpdateTranslationManipulator( - action, manipulatorEntityIds->m_entityIds, m_entityIdManipulators, m_pivotOverrideFrame, prevModifiers, - m_transformChangedInternally, m_spaceCluster.m_spaceLock); - }); - - translationManipulators->InstallSurfaceManipulatorMouseUpCallback( - [this, manipulatorEntityIds]([[maybe_unused]] const SurfaceManipulator::Action& action) - { - AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast( - &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanged, - manipulatorEntityIds->m_entityIds); - - EndRecordManipulatorCommand(); - }); - // transfer ownership m_entityIdManipulators.m_manipulators = AZStd::move(translationManipulators); } From 4e0e3c7904bed001a8e7f0403d923ffdb2d0b48b Mon Sep 17 00:00:00 2001 From: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> Date: Thu, 11 Nov 2021 13:16:11 +0100 Subject: [PATCH 43/97] Entering the Game Mode when the SlideAlongAxisBasedOnAngle in the Camera Rig is set results in an assert (#5410) * Fixed assert and added None behavior. Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * cleaned up file Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Switched over to checkboxes Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Fixed naming. Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Fixed naming Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Fixed serialize version and zero vector normalization Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Cleaned up format. Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Fixed Warnings Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> --- .../StartingPointCameraConstants.h | 11 ----- .../StartingPointCameraUtilities.h | 18 +++------ .../SlideAlongAxisBasedOnAngle.cpp | 21 +++++----- .../SlideAlongAxisBasedOnAngle.h | 4 +- .../StartingPointCameraUtilities.cpp | 40 +++++++------------ 5 files changed, 34 insertions(+), 60 deletions(-) diff --git a/Gems/StartingPointCamera/Code/Include/StartingPointCamera/StartingPointCameraConstants.h b/Gems/StartingPointCamera/Code/Include/StartingPointCamera/StartingPointCameraConstants.h index 849a462ab2..9a36cf5222 100644 --- a/Gems/StartingPointCamera/Code/Include/StartingPointCamera/StartingPointCameraConstants.h +++ b/Gems/StartingPointCamera/Code/Include/StartingPointCamera/StartingPointCameraConstants.h @@ -24,17 +24,6 @@ namespace Camera Z_Axis = 2 }; - ////////////////////////////////////////////////////////////////////////// - /// These are intended to be used as an index and needs to be implicitly - /// convertible to int. See StartingPointCameraUtilities.h for examples - enum VectorComponentType : int - { - X_Component = 0, - Y_Component = 1, - Z_Component = 2, - None = 3, - }; - ////////////////////////////////////////////////////////////////////////// /// These are intended to be used as an index and needs to be implicitly /// convertible to int. See StartingPointCameraUtilities.h for examples diff --git a/Gems/StartingPointCamera/Code/Include/StartingPointCamera/StartingPointCameraUtilities.h b/Gems/StartingPointCamera/Code/Include/StartingPointCamera/StartingPointCameraUtilities.h index eec86059c5..c565bf9379 100644 --- a/Gems/StartingPointCamera/Code/Include/StartingPointCamera/StartingPointCameraUtilities.h +++ b/Gems/StartingPointCamera/Code/Include/StartingPointCamera/StartingPointCameraUtilities.h @@ -16,24 +16,16 @@ namespace Camera { const char* GetNameFromUuid(const AZ::Uuid& uuid); - ////////////////////////////////////////////////////////////////////////// - /// This methods will 0 out a vector component and re-normalize it - ////////////////////////////////////////////////////////////////////////// - void MaskComponentFromNormalizedVector(AZ::Vector3& v, VectorComponentType vectorComponentType); + //! This methods will 0 out specified vector components and re-normalize it + void MaskComponentFromNormalizedVector(AZ::Vector3& v, bool ignoreX, bool ignoreY, bool ignoreZ); - ////////////////////////////////////////////////////////////////////////// - /// This will calculate the requested Euler angle from a given AZ::Quaternion - ////////////////////////////////////////////////////////////////////////// + //! This will calculate the requested Euler angle from a given AZ::Quaternion float GetEulerAngleFromTransform(const AZ::Transform& rotation, EulerAngleType eulerAngleType); - ////////////////////////////////////////////////////////////////////////// - /// This will calculate an AZ::Transform based on an Euler angle - ////////////////////////////////////////////////////////////////////////// + //! This will calculate an AZ::Transform based on an Euler angle AZ::Transform CreateRotationFromEulerAngle(EulerAngleType rotationType, float radians); - ////////////////////////////////////////////////////////////////////////// - /// Creates the Quaternion representing the rotation looking down the vector - ////////////////////////////////////////////////////////////////////////// + //! Creates the Quaternion representing the rotation looking down the vector AZ::Quaternion CreateQuaternionFromViewVector(const AZ::Vector3 lookVector); } //namespace Camera diff --git a/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.cpp b/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.cpp index d7fcc771f4..5031f149b8 100644 --- a/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.cpp +++ b/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.cpp @@ -20,10 +20,12 @@ namespace Camera if (serializeContext) { serializeContext->Class() - ->Version(1) + ->Version(2) ->Field("Axis to slide along", &SlideAlongAxisBasedOnAngle::m_axisToSlideAlong) ->Field("Angle Type", &SlideAlongAxisBasedOnAngle::m_angleTypeToChangeFor) - ->Field("Vector Component To Ignore", &SlideAlongAxisBasedOnAngle::m_vectorComponentToIgnore) + ->Field("Ignore X Component", &SlideAlongAxisBasedOnAngle::m_ignoreX) + ->Field("Ignore Y Component", &SlideAlongAxisBasedOnAngle::m_ignoreY) + ->Field("Ignore Z Component", &SlideAlongAxisBasedOnAngle::m_ignoreZ) ->Field("Max Positive Slide Distance", &SlideAlongAxisBasedOnAngle::m_maximumPositiveSlideDistance) ->Field("Max Negative Slide Distance", &SlideAlongAxisBasedOnAngle::m_maximumNegativeSlideDistance); @@ -40,15 +42,16 @@ namespace Camera ->EnumAttribute(EulerAngleType::Pitch, "Pitch") ->EnumAttribute(EulerAngleType::Roll, "Roll") ->EnumAttribute(EulerAngleType::Yaw, "Yaw") - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &SlideAlongAxisBasedOnAngle::m_vectorComponentToIgnore, "Vector Component To Ignore", "The Vector Component To Ignore") - ->EnumAttribute(VectorComponentType::None, "None") - ->EnumAttribute(VectorComponentType::X_Component, "X") - ->EnumAttribute(VectorComponentType::Y_Component, "Y") - ->EnumAttribute(VectorComponentType::Z_Component, "Z") ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_maximumPositiveSlideDistance, "Max Positive Slide Distance", "The maximum distance to slide in the positive") ->Attribute(AZ::Edit::Attributes::Suffix, "m") ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_maximumNegativeSlideDistance, "Max Negative Slide Distance", "The maximum distance to slide in the negative") - ->Attribute(AZ::Edit::Attributes::Suffix, "m"); + ->Attribute(AZ::Edit::Attributes::Suffix, "m") + ->ClassElement(AZ::Edit::ClassElements::Group, "Vector Components To Ignore") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_ignoreX, "X", "When active, the X Component will be ignored.") + ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_ignoreY, "Y", "When active, the Y Component will be ignored.") + ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_ignoreZ, "Z", "When active, the Z Component will be ignored.") + ; } } } @@ -60,7 +63,7 @@ namespace Camera float slideScale = currentPositionOnRange > 0.0f ? m_maximumPositiveSlideDistance : m_maximumNegativeSlideDistance; AZ::Vector3 basis = outLookAtTargetTransform.GetBasis(m_axisToSlideAlong); - MaskComponentFromNormalizedVector(basis, m_vectorComponentToIgnore); + MaskComponentFromNormalizedVector(basis, m_ignoreX, m_ignoreY, m_ignoreZ); outLookAtTargetTransform.SetTranslation(outLookAtTargetTransform.GetTranslation() + basis * currentPositionOnRange * slideScale); } diff --git a/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.h b/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.h index 3558fd7272..2c756d1ac7 100644 --- a/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.h +++ b/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.h @@ -43,8 +43,10 @@ namespace Camera // Reflected data RelativeAxisType m_axisToSlideAlong = ForwardBackward; EulerAngleType m_angleTypeToChangeFor = Pitch; - VectorComponentType m_vectorComponentToIgnore = None; float m_maximumPositiveSlideDistance = 0.0f; float m_maximumNegativeSlideDistance = 0.0f; + bool m_ignoreX = false; + bool m_ignoreY = false; + bool m_ignoreZ = false; }; } // namespace Camera diff --git a/Gems/StartingPointCamera/Code/Source/StartingPointCamera/StartingPointCameraUtilities.cpp b/Gems/StartingPointCamera/Code/Source/StartingPointCamera/StartingPointCameraUtilities.cpp index b8f0945c55..0831ef26e0 100644 --- a/Gems/StartingPointCamera/Code/Source/StartingPointCamera/StartingPointCameraUtilities.cpp +++ b/Gems/StartingPointCamera/Code/Source/StartingPointCamera/StartingPointCameraUtilities.cpp @@ -26,38 +26,32 @@ namespace Camera return ""; } - ////////////////////////////////////////////////////////////////////////// - /// This methods will 0 out a vector component and re-normalize it - ////////////////////////////////////////////////////////////////////////// - void MaskComponentFromNormalizedVector(AZ::Vector3& v, VectorComponentType vectorComponentType) + void MaskComponentFromNormalizedVector(AZ::Vector3& v, bool ignoreX, bool ignoreY, bool ignoreZ) { - switch (vectorComponentType) - { - case X_Component: + + if (ignoreX) { v.SetX(0.f); - break; } - case Y_Component: + + if (ignoreY) { v.SetY(0.f); - break; } - case Z_Component: + + if (ignoreZ) { v.SetZ(0.f); - break; } - default: - AZ_Assert(false, "MaskComponentFromNormalizedVector: VectorComponentType - unexpected value"); - break; + + if (v.IsZero()) + { + AZ_Warning("StartingPointCameraUtilities", false, "MaskComponentFromNormalizedVector: trying to normalize zero vector.") + return; } v.Normalize(); } - ////////////////////////////////////////////////////////////////////////// - /// This will calculate the requested Euler angle from a given AZ::Quaternion - ////////////////////////////////////////////////////////////////////////// float GetEulerAngleFromTransform(const AZ::Transform& rotation, EulerAngleType eulerAngleType) { AZ::Vector3 angles = rotation.GetEulerDegrees(); @@ -70,14 +64,11 @@ namespace Camera case Yaw: return angles.GetZ(); default: - AZ_Warning("", false, "GetEulerAngleFromRotation: eulerAngleType - value not supported"); + AZ_Warning("StartingPointCameraUtilities", false, "GetEulerAngleFromRotation: eulerAngleType - value not supported"); return 0.f; } } - ////////////////////////////////////////////////////////////////////////// - /// This will calculate an AZ::Transform based on an Euler angle - ////////////////////////////////////////////////////////////////////////// AZ::Transform CreateRotationFromEulerAngle(EulerAngleType rotationType, float radians) { switch (rotationType) @@ -89,14 +80,11 @@ namespace Camera case Yaw: return AZ::Transform::CreateRotationZ(radians); default: - AZ_Warning("", false, "CreateRotationFromEulerAngle: rotationType - value not supported"); + AZ_Warning("StartingPointCameraUtilities", false, "CreateRotationFromEulerAngle: rotationType - value not supported"); return AZ::Transform::Identity(); } } - ////////////////////////////////////////////////////////////////////////// - /// Creates the Quaternion representing the rotation looking down the vector - ////////////////////////////////////////////////////////////////////////// AZ::Quaternion CreateQuaternionFromViewVector(const AZ::Vector3 lookVector) { float twoDimensionLength = AZ::Vector2(lookVector.GetX(), lookVector.GetY()).GetLength(); From 398decd06eff4fb718abb7e8da22bcd52d33e8a9 Mon Sep 17 00:00:00 2001 From: sphrose <82213493+sphrose@users.noreply.github.com> Date: Thu, 11 Nov 2021 12:57:48 +0000 Subject: [PATCH 44/97] review changes Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> --- .../Terrain/Code/Tests/TerrainHeightGradientListTests.cpp | 8 -------- .../Code/Tests/TerrainSurfaceGradientListTests.cpp | 6 +----- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/Gems/Terrain/Code/Tests/TerrainHeightGradientListTests.cpp b/Gems/Terrain/Code/Tests/TerrainHeightGradientListTests.cpp index 535aacb8c8..89fc714c3c 100644 --- a/Gems/Terrain/Code/Tests/TerrainHeightGradientListTests.cpp +++ b/Gems/Terrain/Code/Tests/TerrainHeightGradientListTests.cpp @@ -82,8 +82,6 @@ TEST_F(TerrainHeightGradientListComponentTest, MissingRequiredComponentsActivate const AZ::Entity::DependencySortOutcome sortOutcome = entity->EvaluateDependenciesGetDetails(); EXPECT_FALSE(sortOutcome.IsSuccess()); - - entity.reset(); } TEST_F(TerrainHeightGradientListComponentTest, ActivateEntityActivateSuccess) @@ -97,8 +95,6 @@ TEST_F(TerrainHeightGradientListComponentTest, ActivateEntityActivateSuccess) entity->Activate(); EXPECT_EQ(entity->GetState(), AZ::Entity::State::Active); - - entity.reset(); } TEST_F(TerrainHeightGradientListComponentTest, TerrainHeightGradientRefreshesTerrainSystem) @@ -123,8 +119,6 @@ TEST_F(TerrainHeightGradientListComponentTest, TerrainHeightGradientRefreshesTer // Stop the EXPECT_CALL check now, as OnCompositionChanged will get called twice again during the reset. Mock::VerifyAndClearExpectations(&terrainSystem); - - entity.reset(); } TEST_F(TerrainHeightGradientListComponentTest, TerrainHeightGradientListReturnsHeights) @@ -169,7 +163,5 @@ TEST_F(TerrainHeightGradientListComponentTest, TerrainHeightGradientListReturnsH const float height = outPosition.GetZ(); EXPECT_NEAR(height, mockGradientValue * max, 0.01f); - - entity.reset(); } diff --git a/Gems/Terrain/Code/Tests/TerrainSurfaceGradientListTests.cpp b/Gems/Terrain/Code/Tests/TerrainSurfaceGradientListTests.cpp index fb94d2320d..71f5d64fa8 100644 --- a/Gems/Terrain/Code/Tests/TerrainSurfaceGradientListTests.cpp +++ b/Gems/Terrain/Code/Tests/TerrainSurfaceGradientListTests.cpp @@ -63,8 +63,6 @@ namespace UnitTest const AZ::Entity::DependencySortOutcome sortOutcome = entity->EvaluateDependenciesGetDetails(); EXPECT_FALSE(sortOutcome.IsSuccess()); - - entity.reset(); } TEST_F(TerrainSurfaceGradientListTest, SurfaceGradientActivateSuccess) @@ -78,9 +76,7 @@ namespace UnitTest entity->Activate(); - - - entity.reset(); + EXPECT_EQ(entity->GetState(), AZ::Entity::State::Active); } TEST_F(TerrainSurfaceGradientListTest, SurfaceGradientReturnsSurfaceWeights) From 2df8d5b620efef3d5022db65d0a5fd5c93fcf9d4 Mon Sep 17 00:00:00 2001 From: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> Date: Thu, 11 Nov 2021 07:50:16 -0800 Subject: [PATCH 45/97] Fixed crash if you save a bundle outside the default bundle folder (#4974) (#5255) Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> --- .../source/models/AssetBundlerAbstractFileTableModel.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.cpp b/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.cpp index 45d01b9b5b..8def0a698c 100644 --- a/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.cpp +++ b/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.cpp @@ -61,8 +61,12 @@ namespace AssetBundler { AZStd::string absolutePath = filePath.toUtf8().data(); if (AZ::IO::FileIOBase::GetInstance()->Exists(absolutePath.c_str())) - { - AZStd::string projectName = pathToProjectNameMap.at(absolutePath); + { + AZStd::string projectName; + if (pathToProjectNameMap.contains(absolutePath)) + { + projectName = pathToProjectNameMap.at(absolutePath); + } // If a project name is already specified, then the associated file is a default file LoadFile(absolutePath, projectName, !projectName.empty()); From 6e70097ad712a02171cd6cc27908c737a6566b65 Mon Sep 17 00:00:00 2001 From: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> Date: Thu, 11 Nov 2021 07:50:25 -0800 Subject: [PATCH 46/97] Fixed all errors with default seeds (#5489) * Cleaning up errors with default assets, used in bundled release builds Signed-off-by: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Updated simple asset references to be to the product, not source assets Signed-off-by: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> --- .../Slices/DefaultLevelSetup.slice | 2 +- Assets/Engine/Entities/GeomCache.ent | 3 - .../Scripts/Entities/Render/GeomCache.lua | 178 ------------------ Code/Editor/CryEdit.cpp | 10 - Code/Editor/Include/IFileUtil.h | 1 - Code/Editor/Objects/EntityObject.cpp | 18 +- Code/Editor/Objects/EntityObject.h | 1 - Code/Editor/Objects/ObjectManager.cpp | 2 +- Code/Editor/Util/FileUtil.cpp | 4 +- Code/LauncherUnified/Launcher.cpp | 19 -- .../AssetBuilderSDK/AssetBuilderSDK.cpp | 7 - .../Canvases/DefaultMainMenuScreen.uicanvas | 4 +- Gems/LmbrCentral/Assets/seedList.seed | 37 ---- Gems/LyShine/Assets/seedList.seed | 4 +- Gems/LyShine/Code/Source/Sprite.cpp | 3 +- .../Comp/Button/Styles.uicanvas | 28 +-- .../Comp/Image/ImageTypes.uicanvas | 12 +- .../Comp/Mask/MaskingInteractables.uicanvas | 36 ++-- .../Comp/Text/ImageMarkup.uicanvas | 4 +- .../Performance/DrawCallsControl.uicanvas | 2 +- .../ChildDropTargets_Draggable.slice | 6 +- .../ChildDropTargets_EndDropTarget.slice | 2 +- .../DragAndDrop/DraggableElement.slice | 4 +- .../Slices/LyShineExamples/NextButton.slice | 4 +- Gems/LyShineExamples/Assets/seedList.seed | 32 ++-- .../Assets/UI/Slices/Library/Button.slice | 4 +- .../Assets/UI/Slices/Library/Checkbox.slice | 10 +- .../Assets/UI/Slices/Library/Dropdown.slice | 6 +- .../Assets/UI/Slices/Library/Textinput.slice | 4 +- .../UI/Slices/Library/TooltipDisplay.slice | 2 +- 30 files changed, 91 insertions(+), 358 deletions(-) delete mode 100644 Assets/Engine/Entities/GeomCache.ent delete mode 100644 Assets/Engine/Scripts/Entities/Render/GeomCache.lua delete mode 100644 Gems/LmbrCentral/Assets/seedList.seed diff --git a/Assets/Engine/EngineAssets/Slices/DefaultLevelSetup.slice b/Assets/Engine/EngineAssets/Slices/DefaultLevelSetup.slice index 1b7dfdf40d..b82c482c4f 100644 --- a/Assets/Engine/EngineAssets/Slices/DefaultLevelSetup.slice +++ b/Assets/Engine/EngineAssets/Slices/DefaultLevelSetup.slice @@ -145,7 +145,7 @@ - + diff --git a/Assets/Engine/Entities/GeomCache.ent b/Assets/Engine/Entities/GeomCache.ent deleted file mode 100644 index e7a63190c3..0000000000 --- a/Assets/Engine/Entities/GeomCache.ent +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cf441215a769562f88aa20711aee68dadcbf02597d1e2270547055e8e6aec6a3 -size 77 diff --git a/Assets/Engine/Scripts/Entities/Render/GeomCache.lua b/Assets/Engine/Scripts/Entities/Render/GeomCache.lua deleted file mode 100644 index b496aecd8d..0000000000 --- a/Assets/Engine/Scripts/Entities/Render/GeomCache.lua +++ /dev/null @@ -1,178 +0,0 @@ ----------------------------------------------------------------------------------------------------- --- --- Copyright (c) Contributors to the Open 3D Engine Project. --- For complete copyright and license terms please see the LICENSE at the root of this distribution. --- --- SPDX-License-Identifier: Apache-2.0 OR MIT --- --- --- ----------------------------------------------------------------------------------------------------- -Script.ReloadScript("scripts/Utils/EntityUtils.lua") - -GeomCache = -{ - Properties = { - geomcacheFile = "EngineAssets/GeomCaches/defaultGeomCache.cax", - bPlaying = 0, - fStartTime = 0, - bLooping = 0, - objectStandIn = "", - materialStandInMaterial = "", - objectFirstFrameStandIn = "", - materialFirstFrameStandInMaterial = "", - objectLastFrameStandIn = "", - materialLastFrameStandInMaterial = "", - fStandInDistance = 0, - fStreamInDistance = 0, - Physics = { - bPhysicalize = 0, - } - }, - - Editor={ - Icon = "animobject.bmp", - IconOnTop = 1, - }, - - bPlaying = 0, - currentTime = 0, - precacheTime = 0, - bPrecachedOutputTriggered = false, -} - -function GeomCache:OnLoad(table) - self.currentTime = table.currentTime; -end - -function GeomCache:OnSave(table) - table.currentTime = self.currentTime; -end - -function GeomCache:OnSpawn() - self.currentTime = self.Properties.fStartTime; - self:SetFromProperties(); -end - -function GeomCache:OnReset() - self.currentTime = self.Properties.fStartTime; - self.bPrecachedOutputTriggered = true; - self:SetFromProperties(); -end - -function GeomCache:SetFromProperties() - local Properties = self.Properties; - - if (Properties.geomcacheFile == "") then - do return end; - end - - self:LoadGeomCache(0, Properties.geomcacheFile); - - self.bPlaying = Properties.bPlaying; - if (self.bPlaying == 0) then - self.currentTime = Properties.fStartTime; - end - - self:SetGeomCachePlaybackTime(self.currentTime); - self:SetGeomCacheParams(Properties.bLooping, Properties.objectStandIn, Properties.materialStandInMaterial, Properties.objectFirstFrameStandIn, - Properties.materialFirstFrameStandInMaterial, Properties.objectLastFrameStandIn, Properties.materialLastFrameStandInMaterial, - Properties.fStandInDistance, Properties.fStreamInDistance); - self:SetGeomCacheStreaming(false, 0); - - if (Properties.Physics.bPhysicalize == 1) then - local tempPhysParams = EntityCommon.TempPhysParams; - self:Physicalize(0, PE_ARTICULATED, tempPhysParams); - end - - self:Activate(1); -end - -function GeomCache:PhysicalizeThis() - local Physics = self.Properties.Physics; - EntityCommon.PhysicalizeRigid(self, 0, Physics, false); -end - -function GeomCache:OnUpdate(dt) - if (self.bPlaying == 1) then - self:SetGeomCachePlaybackTime(self.currentTime); - end - - if (self:IsGeomCacheStreaming() and not self.bPrecachedOutputTriggered) then - local precachedTime = self:GetGeomCachePrecachedTime(); - if (precachedTime >= self.precacheTime) then - self:ActivateOutput("Precached", true); - self.bPrecachedOutputTriggered = true; - end - end - - if (self.bPlaying == 1) then - self.currentTime = self.currentTime + dt; - end -end - -function GeomCache:OnPropertyChange() - self:SetFromProperties(); -end - -function GeomCache:Event_Start(sender, val) - self.bPlaying = 1; -end - -function GeomCache:Event_Stop(sender, value) - self.bPlaying = 0; -end - -function GeomCache:Event_SetTime(sender, value) - self.currentTime = value; -end - -function GeomCache:Event_StartStreaming(sender, value) - self.bPrecachedOutputTriggered = false; - self:SetGeomCacheStreaming(true, self.currentTime); -end - -function GeomCache:Event_StopStreaming(sender, value) - self:SetGeomCacheStreaming(false, 0); -end - -function GeomCache:Event_PrecacheTime(sender, value) - self.precacheTime = value; -end - -function GeomCache:Event_Hide(sender, value) - self:Hide(1); -end - -function GeomCache:Event_Unhide(sender, value) - self:Hide(0); -end - -function GeomCache:Event_StopDrawing(sender, value) - self:SetGeomCacheDrawing(false); -end - -function GeomCache:Event_StartDrawing(sender, value) - self:SetGeomCacheDrawing(true); -end - -GeomCache.FlowEvents = -{ - Inputs = - { - Start = { GeomCache.Event_Start, "any" }, - Stop = { GeomCache.Event_Stop, "any" }, - SetTime = { GeomCache.Event_SetTime, "float" }, - StartStreaming = { GeomCache.Event_StartStreaming, "any" }, - StopStreaming = { GeomCache.Event_StopStreaming, "any" }, - PrecacheTime = { GeomCache.Event_PrecacheTime, "float" }, - Hide = { GeomCache.Event_Hide, "any" }, - Unhide = { GeomCache.Event_Unhide, "any" }, - StopDrawing = { GeomCache.Event_StopDrawing, "any" }, - StartDrawing = { GeomCache.Event_StartDrawing, "any" }, - }, - Outputs = - { - Precached = "bool", - }, -} diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 0ea22e8ce3..0b40390a18 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -1362,16 +1362,6 @@ void CCryEditApp::CompileCriticalAssets() const assetsInQueueNotifcation.BusDisconnect(); CCryEditApp::OutputStartupMessage(QString("Asset Processor is now ready.")); - // VERY early on, as soon as we can, request that the asset system make sure the following assets take priority over others, - // so that by the time we ask for them there is a greater likelihood that they're already good to go. - // these can be loaded later but are still important: - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "/texturemsg/"); - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/materials"); - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/geomcaches"); - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/objects"); - - // some are specifically extra important and will cause issues if missing completely: - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::CompileAssetSync, "engineassets/objects/default.cgf"); } bool CCryEditApp::ConnectToAssetProcessor() const diff --git a/Code/Editor/Include/IFileUtil.h b/Code/Editor/Include/IFileUtil.h index 4d5f6e23c4..036a0bc5ee 100644 --- a/Code/Editor/Include/IFileUtil.h +++ b/Code/Editor/Include/IFileUtil.h @@ -60,7 +60,6 @@ struct IFileUtil EFILE_TYPE_GEOMETRY, EFILE_TYPE_TEXTURE, EFILE_TYPE_SOUND, - EFILE_TYPE_GEOMCACHE, EFILE_TYPE_LAST, }; diff --git a/Code/Editor/Objects/EntityObject.cpp b/Code/Editor/Objects/EntityObject.cpp index 6e2354998c..b2dfc04102 100644 --- a/Code/Editor/Objects/EntityObject.cpp +++ b/Code/Editor/Objects/EntityObject.cpp @@ -956,11 +956,7 @@ void CEntityObject::Serialize(CObjectArchive& ar) QString attachmentType; xmlNode->getAttr("AttachmentType", attachmentType); - if (attachmentType == "GeomCacheNode") - { - m_attachmentType = eAT_GeomCacheNode; - } - else if (attachmentType == "CharacterBone") + if (attachmentType == "CharacterBone") { m_attachmentType = eAT_CharacterBone; } @@ -987,11 +983,7 @@ void CEntityObject::Serialize(CObjectArchive& ar) { if (m_attachmentType != eAT_Pivot) { - if (m_attachmentType == eAT_GeomCacheNode) - { - xmlNode->setAttr("AttachmentType", "GeomCacheNode"); - } - else if (m_attachmentType == eAT_CharacterBone) + if (m_attachmentType == eAT_CharacterBone) { xmlNode->setAttr("AttachmentType", "CharacterBone"); } @@ -1091,11 +1083,7 @@ XmlNodeRef CEntityObject::Export([[maybe_unused]] const QString& levelPath, XmlN objNode->setAttr("ParentId", parentEntity->GetEntityId()); if (m_attachmentType != eAT_Pivot) { - if (m_attachmentType == eAT_GeomCacheNode) - { - objNode->setAttr("AttachmentType", "GeomCacheNode"); - } - else if (m_attachmentType == eAT_CharacterBone) + if (m_attachmentType == eAT_CharacterBone) { objNode->setAttr("AttachmentType", "CharacterBone"); } diff --git a/Code/Editor/Objects/EntityObject.h b/Code/Editor/Objects/EntityObject.h index dcc6ff7b22..a4f4752b75 100644 --- a/Code/Editor/Objects/EntityObject.h +++ b/Code/Editor/Objects/EntityObject.h @@ -131,7 +131,6 @@ public: enum EAttachmentType { eAT_Pivot, - eAT_GeomCacheNode, eAT_CharacterBone, }; diff --git a/Code/Editor/Objects/ObjectManager.cpp b/Code/Editor/Objects/ObjectManager.cpp index ee7e9a8e96..265d828481 100644 --- a/Code/Editor/Objects/ObjectManager.cpp +++ b/Code/Editor/Objects/ObjectManager.cpp @@ -608,7 +608,7 @@ bool CObjectManager::AddObject(CBaseObject* obj) if (CEntityObject* entityObj = qobject_cast(obj)) { CEntityObject::EAttachmentType attachType = entityObj->GetAttachType(); - if (attachType == CEntityObject::EAttachmentType::eAT_GeomCacheNode || attachType == CEntityObject::EAttachmentType::eAT_CharacterBone) + if (attachType == CEntityObject::EAttachmentType::eAT_CharacterBone) { m_animatedAttachedEntities.insert(entityObj); } diff --git a/Code/Editor/Util/FileUtil.cpp b/Code/Editor/Util/FileUtil.cpp index 36c1879407..9f96d45381 100644 --- a/Code/Editor/Util/FileUtil.cpp +++ b/Code/Editor/Util/FileUtil.cpp @@ -54,8 +54,8 @@ #include #endif -bool CFileUtil::s_singleFileDlgPref[IFileUtil::EFILE_TYPE_LAST] = { true, true, true, true, true }; -bool CFileUtil::s_multiFileDlgPref[IFileUtil::EFILE_TYPE_LAST] = { true, true, true, true, true }; +bool CFileUtil::s_singleFileDlgPref[IFileUtil::EFILE_TYPE_LAST] = { true, true, true, true }; +bool CFileUtil::s_multiFileDlgPref[IFileUtil::EFILE_TYPE_LAST] = { true, true, true, true }; CAutoRestorePrimaryCDRoot::~CAutoRestorePrimaryCDRoot() { diff --git a/Code/LauncherUnified/Launcher.cpp b/Code/LauncherUnified/Launcher.cpp index 0f832ff1a5..97859a604b 100644 --- a/Code/LauncherUnified/Launcher.cpp +++ b/Code/LauncherUnified/Launcher.cpp @@ -369,7 +369,6 @@ namespace O3DELauncher } } - void CompileCriticalAssets(); void CreateRemoteFileIO(); bool ConnectToAssetProcessor() @@ -397,29 +396,11 @@ namespace O3DELauncher { AZ_TracePrintf("Launcher", "Connected to Asset Processor\n"); CreateRemoteFileIO(); - CompileCriticalAssets(); } return connectedToAssetProcessor; } - //! Compiles the critical assets that are within the Engine directory of Open 3D Engine - //! This code should be in a centralized location, but doesn't belong in AzFramework - //! since it is specific to how Open 3D Engine projects has assets setup - void CompileCriticalAssets() - { - // VERY early on, as soon as we can, request that the asset system make sure the following assets take priority over others, - // so that by the time we ask for them there is a greater likelihood that they're already good to go. - // these can be loaded later but are still important: - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "/texturemsg/"); - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/materials"); - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/geomcaches"); - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/objects"); - - // some are specifically extra important and will cause issues if missing completely: - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::CompileAssetSync, "engineassets/objects/default.cgf"); - } - //! Remote FileIO to use as a Virtual File System //! Communication of FileIOBase operations occur through an AssetProcessor connection void CreateRemoteFileIO() diff --git a/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp b/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp index 62b063c83b..a02eef8b75 100644 --- a/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp +++ b/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp @@ -699,7 +699,6 @@ namespace AssetBuilderSDK // XML files may contain generic data (avoid this in new builders - use a custom extension!) static const char* xmlExtensions = ".xml"; - static const char* geomCacheExtensions = ".cax"; static const char* skeletonExtensions = ".chr"; static AZ::Data::AssetType unknownAssetType = AZ::Data::AssetType::CreateNull(); @@ -710,7 +709,6 @@ namespace AssetBuilderSDK static AZ::Data::AssetType textureMipsAssetType("{3918728C-D3CA-4D9E-813E-A5ED20C6821E}"); static AZ::Data::AssetType skinnedMeshLodsAssetType("{58E5824F-C27B-46FD-AD48-865BA41B7A51}"); static AZ::Data::AssetType staticMeshLodsAssetType("{9AAE4926-CB6A-4C60-9948-A1A22F51DB23}"); - static AZ::Data::AssetType geomCacheAssetType("{EBC96071-E960-41B6-B3E3-328F515AE5DA}"); static AZ::Data::AssetType skeletonAssetType("{60161B46-21F0-4396-A4F0-F2CCF0664CDE}"); static AZ::Data::AssetType entityIconAssetType("{3436C30E-E2C5-4C3B-A7B9-66C94A28701B}"); @@ -822,11 +820,6 @@ namespace AssetBuilderSDK return skinnedMeshAssetType; } - if (AzFramework::StringFunc::Find(geomCacheExtensions, extension.c_str()) != AZStd::string::npos) - { - return geomCacheAssetType; - } - if (AzFramework::StringFunc::Find(skeletonExtensions, extension.c_str()) != AZStd::string::npos) { return skeletonAssetType; diff --git a/Gems/GameStateSamples/Assets/UI/Canvases/DefaultMainMenuScreen.uicanvas b/Gems/GameStateSamples/Assets/UI/Canvases/DefaultMainMenuScreen.uicanvas index 2a0d6d476a..d87baa8aa2 100644 --- a/Gems/GameStateSamples/Assets/UI/Canvases/DefaultMainMenuScreen.uicanvas +++ b/Gems/GameStateSamples/Assets/UI/Canvases/DefaultMainMenuScreen.uicanvas @@ -753,7 +753,7 @@ - + @@ -983,7 +983,7 @@ - + diff --git a/Gems/LmbrCentral/Assets/seedList.seed b/Gems/LmbrCentral/Assets/seedList.seed deleted file mode 100644 index 54c12c9faa..0000000000 --- a/Gems/LmbrCentral/Assets/seedList.seed +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Gems/LyShine/Assets/seedList.seed b/Gems/LyShine/Assets/seedList.seed index b19aa77191..6b53200c4a 100644 --- a/Gems/LyShine/Assets/seedList.seed +++ b/Gems/LyShine/Assets/seedList.seed @@ -2,8 +2,8 @@ - - + + diff --git a/Gems/LyShine/Code/Source/Sprite.cpp b/Gems/LyShine/Code/Source/Sprite.cpp index 5c7adae481..d9a0775cc1 100644 --- a/Gems/LyShine/Code/Source/Sprite.cpp +++ b/Gems/LyShine/Code/Source/Sprite.cpp @@ -855,7 +855,8 @@ bool CSprite::LoadImage(const AZStd::string& nameTex, AZ::Data::Instance().c_str()); return false; } diff --git a/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Button/Styles.uicanvas b/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Button/Styles.uicanvas index 386df81e5c..6a41034bd2 100644 --- a/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Button/Styles.uicanvas +++ b/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Button/Styles.uicanvas @@ -569,7 +569,7 @@ - + @@ -591,7 +591,7 @@ - + @@ -626,7 +626,7 @@ - + @@ -650,7 +650,7 @@ - + @@ -1161,7 +1161,7 @@ - + @@ -1209,7 +1209,7 @@ - + @@ -1227,7 +1227,7 @@ - + @@ -1368,7 +1368,7 @@ - + @@ -1438,7 +1438,7 @@ - + @@ -1498,7 +1498,7 @@ - + @@ -1516,7 +1516,7 @@ - + @@ -1657,7 +1657,7 @@ - + @@ -1714,7 +1714,7 @@ - + @@ -1771,7 +1771,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Image/ImageTypes.uicanvas b/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Image/ImageTypes.uicanvas index a0fbcbc0ce..0fb5e390d3 100644 --- a/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Image/ImageTypes.uicanvas +++ b/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Image/ImageTypes.uicanvas @@ -370,7 +370,7 @@ - + @@ -475,7 +475,7 @@ - + @@ -616,7 +616,7 @@ - + @@ -757,7 +757,7 @@ - + @@ -898,7 +898,7 @@ - + @@ -1118,7 +1118,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Mask/MaskingInteractables.uicanvas b/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Mask/MaskingInteractables.uicanvas index a99a40c6be..e627fafd54 100644 --- a/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Mask/MaskingInteractables.uicanvas +++ b/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Mask/MaskingInteractables.uicanvas @@ -215,7 +215,7 @@ - + @@ -240,7 +240,7 @@ - + @@ -265,7 +265,7 @@ - + @@ -301,7 +301,7 @@ - + @@ -378,7 +378,7 @@ - + @@ -455,7 +455,7 @@ - + @@ -645,7 +645,7 @@ - + @@ -716,7 +716,7 @@ - + @@ -975,7 +975,7 @@ - + @@ -1000,7 +1000,7 @@ - + @@ -1052,7 +1052,7 @@ - + @@ -1129,7 +1129,7 @@ - + @@ -1206,7 +1206,7 @@ - + @@ -1296,7 +1296,7 @@ - + @@ -1399,7 +1399,7 @@ - + @@ -1425,7 +1425,7 @@ - + @@ -1475,7 +1475,7 @@ - + @@ -1658,7 +1658,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Text/ImageMarkup.uicanvas b/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Text/ImageMarkup.uicanvas index 3bcd4f3db3..efa2e79b50 100644 --- a/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Text/ImageMarkup.uicanvas +++ b/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Comp/Text/ImageMarkup.uicanvas @@ -475,7 +475,7 @@ - + @@ -854,7 +854,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Performance/DrawCallsControl.uicanvas b/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Performance/DrawCallsControl.uicanvas index 9b89289dd4..4d3f08a1cd 100644 --- a/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Performance/DrawCallsControl.uicanvas +++ b/Gems/LyShineExamples/Assets/UI/Canvases/LyShineExamples/Performance/DrawCallsControl.uicanvas @@ -1910,7 +1910,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/DragAndDrop/ChildDropTargets/ChildDropTargets_Draggable.slice b/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/DragAndDrop/ChildDropTargets/ChildDropTargets_Draggable.slice index 4c857ecb60..9e5c72b9ee 100644 --- a/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/DragAndDrop/ChildDropTargets/ChildDropTargets_Draggable.slice +++ b/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/DragAndDrop/ChildDropTargets/ChildDropTargets_Draggable.slice @@ -64,7 +64,7 @@ - + @@ -102,7 +102,7 @@ - + @@ -422,7 +422,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/DragAndDrop/ChildDropTargets/ChildDropTargets_EndDropTarget.slice b/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/DragAndDrop/ChildDropTargets/ChildDropTargets_EndDropTarget.slice index cb6f6749d4..6f00a98399 100644 --- a/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/DragAndDrop/ChildDropTargets/ChildDropTargets_EndDropTarget.slice +++ b/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/DragAndDrop/ChildDropTargets/ChildDropTargets_EndDropTarget.slice @@ -174,7 +174,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/DragAndDrop/DraggableElement.slice b/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/DragAndDrop/DraggableElement.slice index 8781688a94..3249e61b53 100644 --- a/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/DragAndDrop/DraggableElement.slice +++ b/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/DragAndDrop/DraggableElement.slice @@ -61,7 +61,7 @@ - + @@ -99,7 +99,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/NextButton.slice b/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/NextButton.slice index 85046d4d1b..661fa6ccf3 100644 --- a/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/NextButton.slice +++ b/Gems/LyShineExamples/Assets/UI/Slices/LyShineExamples/NextButton.slice @@ -63,7 +63,7 @@ - + @@ -118,7 +118,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/seedList.seed b/Gems/LyShineExamples/Assets/seedList.seed index 777269ee7a..d730765515 100644 --- a/Gems/LyShineExamples/Assets/seedList.seed +++ b/Gems/LyShineExamples/Assets/seedList.seed @@ -11,10 +11,10 @@ - + - + @@ -27,10 +27,10 @@ - + - + @@ -43,10 +43,10 @@ - + - + @@ -59,10 +59,10 @@ - + - + @@ -75,10 +75,10 @@ - + - + @@ -91,26 +91,26 @@ - + - + - + - + - + - + diff --git a/Gems/UiBasics/Assets/UI/Slices/Library/Button.slice b/Gems/UiBasics/Assets/UI/Slices/Library/Button.slice index 276d181ad6..020db8367a 100644 --- a/Gems/UiBasics/Assets/UI/Slices/Library/Button.slice +++ b/Gems/UiBasics/Assets/UI/Slices/Library/Button.slice @@ -112,7 +112,7 @@ - + @@ -158,7 +158,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Slices/Library/Checkbox.slice b/Gems/UiBasics/Assets/UI/Slices/Library/Checkbox.slice index 9334903463..74e7bb1c2b 100644 --- a/Gems/UiBasics/Assets/UI/Slices/Library/Checkbox.slice +++ b/Gems/UiBasics/Assets/UI/Slices/Library/Checkbox.slice @@ -30,7 +30,7 @@ - + @@ -55,7 +55,7 @@ - + @@ -74,7 +74,7 @@ - + @@ -234,7 +234,7 @@ - + @@ -311,7 +311,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Slices/Library/Dropdown.slice b/Gems/UiBasics/Assets/UI/Slices/Library/Dropdown.slice index e73c53e0d5..4185e80332 100644 --- a/Gems/UiBasics/Assets/UI/Slices/Library/Dropdown.slice +++ b/Gems/UiBasics/Assets/UI/Slices/Library/Dropdown.slice @@ -231,7 +231,7 @@ - + @@ -383,7 +383,7 @@ - + @@ -1218,7 +1218,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Slices/Library/Textinput.slice b/Gems/UiBasics/Assets/UI/Slices/Library/Textinput.slice index cb9eaeb213..f57d307543 100644 --- a/Gems/UiBasics/Assets/UI/Slices/Library/Textinput.slice +++ b/Gems/UiBasics/Assets/UI/Slices/Library/Textinput.slice @@ -75,7 +75,7 @@ - + @@ -233,7 +233,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Slices/Library/TooltipDisplay.slice b/Gems/UiBasics/Assets/UI/Slices/Library/TooltipDisplay.slice index e92f722837..5c9aa5cbf2 100644 --- a/Gems/UiBasics/Assets/UI/Slices/Library/TooltipDisplay.slice +++ b/Gems/UiBasics/Assets/UI/Slices/Library/TooltipDisplay.slice @@ -79,7 +79,7 @@ - + From 4e1825a3fecbf74407d8c54158ec26ba463f7fe3 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 9 Nov 2021 11:10:03 -0800 Subject: [PATCH 47/97] Better compiler detection on Linux (#5376) * Better compiler detection on Linux Moving EngineFinder.cmake to cmake/ in the templates Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * skipping detection if compiler is passed through environment Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * Fixes condition, needs to be in quotes since is the value of the sttring Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- CMakeLists.txt | 1 + .../DefaultProject/Template/CMakeLists.txt | 3 +- .../Template/cmake/CompilerSettings.cmake | 13 +++++++ .../Template/{ => cmake}/EngineFinder.cmake | 0 .../Platform/Linux/CompilerSettings.cmake | 34 +++++++++++++++++++ Templates/DefaultProject/template.json | 16 +++++++-- .../MinimalProject/Template/CMakeLists.txt | 3 +- .../Template/cmake/CompilerSettings.cmake | 13 +++++++ .../Template/{ => cmake}/EngineFinder.cmake | 0 .../Platform/Linux/CompilerSettings.cmake | 34 +++++++++++++++++++ Templates/MinimalProject/template.json | 16 +++++++-- cmake/CompilerSettings.cmake | 13 +++++++ cmake/Platform/Linux/CompilerSettings.cmake | 34 +++++++++++++++++++ 13 files changed, 174 insertions(+), 6 deletions(-) create mode 100644 Templates/DefaultProject/Template/cmake/CompilerSettings.cmake rename Templates/DefaultProject/Template/{ => cmake}/EngineFinder.cmake (100%) create mode 100644 Templates/DefaultProject/Template/cmake/Platform/Linux/CompilerSettings.cmake create mode 100644 Templates/MinimalProject/Template/cmake/CompilerSettings.cmake rename Templates/MinimalProject/Template/{ => cmake}/EngineFinder.cmake (100%) create mode 100644 Templates/MinimalProject/Template/cmake/Platform/Linux/CompilerSettings.cmake create mode 100644 cmake/CompilerSettings.cmake create mode 100644 cmake/Platform/Linux/CompilerSettings.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index e659270f84..f61a9561e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ include(cmake/Version.cmake) include(cmake/OutputDirectory.cmake) if(NOT PROJECT_NAME) + include(cmake/CompilerSettings.cmake) project(O3DE LANGUAGES C CXX VERSION ${LY_VERSION_STRING} diff --git a/Templates/DefaultProject/Template/CMakeLists.txt b/Templates/DefaultProject/Template/CMakeLists.txt index 76e8f227be..ae4bb662a3 100644 --- a/Templates/DefaultProject/Template/CMakeLists.txt +++ b/Templates/DefaultProject/Template/CMakeLists.txt @@ -10,11 +10,12 @@ if(NOT PROJECT_NAME) cmake_minimum_required(VERSION 3.20) + include(cmake/CompilerSettings.cmake) project(${Name} LANGUAGES C CXX VERSION 1.0.0.0 ) - include(EngineFinder.cmake OPTIONAL) + include(cmake/EngineFinder.cmake OPTIONAL) find_package(o3de REQUIRED) o3de_initialize() else() diff --git a/Templates/DefaultProject/Template/cmake/CompilerSettings.cmake b/Templates/DefaultProject/Template/cmake/CompilerSettings.cmake new file mode 100644 index 0000000000..cf6614e4a5 --- /dev/null +++ b/Templates/DefaultProject/Template/cmake/CompilerSettings.cmake @@ -0,0 +1,13 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +# File to tweak compiler settings before compiler detection happens (before project() is called) +# We dont have PAL enabled at this point, so we can only use pure-CMake variables +if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux") + include(cmake/Platform/${CMAKE_HOST_SYSTEM_NAME}/CompilerSettings.cmake) +endif() diff --git a/Templates/DefaultProject/Template/EngineFinder.cmake b/Templates/DefaultProject/Template/cmake/EngineFinder.cmake similarity index 100% rename from Templates/DefaultProject/Template/EngineFinder.cmake rename to Templates/DefaultProject/Template/cmake/EngineFinder.cmake diff --git a/Templates/DefaultProject/Template/cmake/Platform/Linux/CompilerSettings.cmake b/Templates/DefaultProject/Template/cmake/Platform/Linux/CompilerSettings.cmake new file mode 100644 index 0000000000..9bb629c53b --- /dev/null +++ b/Templates/DefaultProject/Template/cmake/Platform/Linux/CompilerSettings.cmake @@ -0,0 +1,34 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +if(NOT CMAKE_C_COMPILER AND NOT CMAKE_CXX_COMPILER AND NOT "$ENV{CC}" AND NOT "$ENV{CXX}") + set(path_search + /bin + /usr/bin + /usr/local/bin + /sbin + /usr/sbin + /usr/local/sbin + ) + list(TRANSFORM path_search APPEND "/clang-[0-9]*") + file(GLOB clang_versions ${path_search}) + if(clang_versions) + # Find and pick the highest installed version + list(SORT clang_versions COMPARE NATURAL) + list(GET clang_versions 0 clang_higher_version_path) + string(REGEX MATCH "clang-([0-9.]*)" clang_higher_version ${clang_higher_version_path}) + if(CMAKE_MATCH_1) + set(CMAKE_C_COMPILER clang-${CMAKE_MATCH_1}) + set(CMAKE_CXX_COMPILER clang++-${CMAKE_MATCH_1}) + else() + message(FATAL_ERROR "Clang not found, please install clang") + endif() + else() + message(FATAL_ERROR "Clang not found, please install clang") + endif() +endif() diff --git a/Templates/DefaultProject/template.json b/Templates/DefaultProject/template.json index 1e84ea8424..a36926f632 100644 --- a/Templates/DefaultProject/template.json +++ b/Templates/DefaultProject/template.json @@ -181,8 +181,20 @@ "isOptional": false }, { - "file": "EngineFinder.cmake", - "origin": "EngineFinder.cmake", + "file": "cmake/EngineFinder.cmake", + "origin": "cmake/EngineFinder.cmake", + "isTemplated": false, + "isOptional": false + }, + { + "file": "cmake/CompilerSettings.cmake", + "origin": "cmake/CompilerSettings.cmake", + "isTemplated": false, + "isOptional": false + }, + { + "file": "cmake/Platform/Linux/CompilerSettings.cmake", + "origin": "cmake/Platform/Linux/CompilerSettings.cmake", "isTemplated": false, "isOptional": false }, diff --git a/Templates/MinimalProject/Template/CMakeLists.txt b/Templates/MinimalProject/Template/CMakeLists.txt index 76e8f227be..ae4bb662a3 100644 --- a/Templates/MinimalProject/Template/CMakeLists.txt +++ b/Templates/MinimalProject/Template/CMakeLists.txt @@ -10,11 +10,12 @@ if(NOT PROJECT_NAME) cmake_minimum_required(VERSION 3.20) + include(cmake/CompilerSettings.cmake) project(${Name} LANGUAGES C CXX VERSION 1.0.0.0 ) - include(EngineFinder.cmake OPTIONAL) + include(cmake/EngineFinder.cmake OPTIONAL) find_package(o3de REQUIRED) o3de_initialize() else() diff --git a/Templates/MinimalProject/Template/cmake/CompilerSettings.cmake b/Templates/MinimalProject/Template/cmake/CompilerSettings.cmake new file mode 100644 index 0000000000..cf6614e4a5 --- /dev/null +++ b/Templates/MinimalProject/Template/cmake/CompilerSettings.cmake @@ -0,0 +1,13 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +# File to tweak compiler settings before compiler detection happens (before project() is called) +# We dont have PAL enabled at this point, so we can only use pure-CMake variables +if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux") + include(cmake/Platform/${CMAKE_HOST_SYSTEM_NAME}/CompilerSettings.cmake) +endif() diff --git a/Templates/MinimalProject/Template/EngineFinder.cmake b/Templates/MinimalProject/Template/cmake/EngineFinder.cmake similarity index 100% rename from Templates/MinimalProject/Template/EngineFinder.cmake rename to Templates/MinimalProject/Template/cmake/EngineFinder.cmake diff --git a/Templates/MinimalProject/Template/cmake/Platform/Linux/CompilerSettings.cmake b/Templates/MinimalProject/Template/cmake/Platform/Linux/CompilerSettings.cmake new file mode 100644 index 0000000000..9bb629c53b --- /dev/null +++ b/Templates/MinimalProject/Template/cmake/Platform/Linux/CompilerSettings.cmake @@ -0,0 +1,34 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +if(NOT CMAKE_C_COMPILER AND NOT CMAKE_CXX_COMPILER AND NOT "$ENV{CC}" AND NOT "$ENV{CXX}") + set(path_search + /bin + /usr/bin + /usr/local/bin + /sbin + /usr/sbin + /usr/local/sbin + ) + list(TRANSFORM path_search APPEND "/clang-[0-9]*") + file(GLOB clang_versions ${path_search}) + if(clang_versions) + # Find and pick the highest installed version + list(SORT clang_versions COMPARE NATURAL) + list(GET clang_versions 0 clang_higher_version_path) + string(REGEX MATCH "clang-([0-9.]*)" clang_higher_version ${clang_higher_version_path}) + if(CMAKE_MATCH_1) + set(CMAKE_C_COMPILER clang-${CMAKE_MATCH_1}) + set(CMAKE_CXX_COMPILER clang++-${CMAKE_MATCH_1}) + else() + message(FATAL_ERROR "Clang not found, please install clang") + endif() + else() + message(FATAL_ERROR "Clang not found, please install clang") + endif() +endif() diff --git a/Templates/MinimalProject/template.json b/Templates/MinimalProject/template.json index 21608e9204..4260e71527 100644 --- a/Templates/MinimalProject/template.json +++ b/Templates/MinimalProject/template.json @@ -173,8 +173,20 @@ "isOptional": false }, { - "file": "EngineFinder.cmake", - "origin": "EngineFinder.cmake", + "file": "cmake/EngineFinder.cmake", + "origin": "cmake/EngineFinder.cmake", + "isTemplated": false, + "isOptional": false + }, + { + "file": "cmake/CompilerSettings.cmake", + "origin": "cmake/CompilerSettings.cmake", + "isTemplated": false, + "isOptional": false + }, + { + "file": "cmake/Platform/Linux/CompilerSettings.cmake", + "origin": "cmake/Platform/Linux/CompilerSettings.cmake", "isTemplated": false, "isOptional": false }, diff --git a/cmake/CompilerSettings.cmake b/cmake/CompilerSettings.cmake new file mode 100644 index 0000000000..cf6614e4a5 --- /dev/null +++ b/cmake/CompilerSettings.cmake @@ -0,0 +1,13 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +# File to tweak compiler settings before compiler detection happens (before project() is called) +# We dont have PAL enabled at this point, so we can only use pure-CMake variables +if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux") + include(cmake/Platform/${CMAKE_HOST_SYSTEM_NAME}/CompilerSettings.cmake) +endif() diff --git a/cmake/Platform/Linux/CompilerSettings.cmake b/cmake/Platform/Linux/CompilerSettings.cmake new file mode 100644 index 0000000000..9bb629c53b --- /dev/null +++ b/cmake/Platform/Linux/CompilerSettings.cmake @@ -0,0 +1,34 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +if(NOT CMAKE_C_COMPILER AND NOT CMAKE_CXX_COMPILER AND NOT "$ENV{CC}" AND NOT "$ENV{CXX}") + set(path_search + /bin + /usr/bin + /usr/local/bin + /sbin + /usr/sbin + /usr/local/sbin + ) + list(TRANSFORM path_search APPEND "/clang-[0-9]*") + file(GLOB clang_versions ${path_search}) + if(clang_versions) + # Find and pick the highest installed version + list(SORT clang_versions COMPARE NATURAL) + list(GET clang_versions 0 clang_higher_version_path) + string(REGEX MATCH "clang-([0-9.]*)" clang_higher_version ${clang_higher_version_path}) + if(CMAKE_MATCH_1) + set(CMAKE_C_COMPILER clang-${CMAKE_MATCH_1}) + set(CMAKE_CXX_COMPILER clang++-${CMAKE_MATCH_1}) + else() + message(FATAL_ERROR "Clang not found, please install clang") + endif() + else() + message(FATAL_ERROR "Clang not found, please install clang") + endif() +endif() From 2812ec2024a7c884ad0110f84602ef54d98c9dd5 Mon Sep 17 00:00:00 2001 From: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> Date: Thu, 11 Nov 2021 16:33:08 +0000 Subject: [PATCH 48/97] Fix brute force mesh intersection function (#5447) * fix brute force mesh intersection function Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * add test for brute force ray intersection fix Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * refactor tests to remove as much duplication and provide API for future tests if required Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * small updates after review feedback Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * update following review feedback Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * fix for pointer offset Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Math/Vector3.h | 2 +- Code/Framework/AzCore/AzCore/Math/Vector3.inl | 2 +- .../Model/ModelAssetBuilderComponent.cpp | 2 +- .../Source/RPI.Reflect/Model/ModelAsset.cpp | 56 +++--- Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp | 179 +++++++++++++++--- 5 files changed, 178 insertions(+), 63 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Math/Vector3.h b/Code/Framework/AzCore/AzCore/Math/Vector3.h index 821dc8292c..6b7c53266d 100644 --- a/Code/Framework/AzCore/AzCore/Math/Vector3.h +++ b/Code/Framework/AzCore/AzCore/Math/Vector3.h @@ -100,7 +100,7 @@ namespace AZ void Set(float x, float y, float z); //! Sets components from an array of 3 floats in xyz order. - void Set(float values[]); + void Set(const float values[]); //! Indexed access using operator(), just for convenience. float operator()(int32_t index) const; diff --git a/Code/Framework/AzCore/AzCore/Math/Vector3.inl b/Code/Framework/AzCore/AzCore/Math/Vector3.inl index 879ade38cf..6371c688b8 100644 --- a/Code/Framework/AzCore/AzCore/Math/Vector3.inl +++ b/Code/Framework/AzCore/AzCore/Math/Vector3.inl @@ -186,7 +186,7 @@ namespace AZ } - AZ_MATH_INLINE void Vector3::Set(float values[]) + AZ_MATH_INLINE void Vector3::Set(const float values[]) { m_value = Simd::Vec3::LoadImmediate(values[0], values[1], values[2]); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp index 9fc99e3ea4..dbf0fea791 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp @@ -2088,7 +2088,7 @@ namespace AZ AZ::Vector3 vpos; //note: it seems to be fastest to reuse a local Vector3 rather than constructing new ones each loop iteration for (uint32_t i = 0; i < elementCount; ++i) { - vpos.Set(const_cast(reinterpret_cast(&buffer[i]))); + vpos.Set(reinterpret_cast(&buffer[i])); aabb.AddPoint(vpos); } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp index 9a432643d7..e362229d2d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp @@ -201,23 +201,11 @@ namespace AZ AZ::Vector3& normal) const { const BufferAssetView& indexBufferView = mesh.GetIndexBufferAssetView(); - const AZStd::array_view& streamBufferList = mesh.GetStreamBufferInfoList(); + const BufferAssetView* positionBufferView = mesh.GetSemanticBufferAssetView(m_positionName); - // find position semantic - const ModelLodAsset::Mesh::StreamBufferInfo* positionBuffer = nullptr; - - for (const ModelLodAsset::Mesh::StreamBufferInfo& bufferInfo : streamBufferList) + if (positionBufferView && positionBufferView->GetBufferAsset().Get()) { - if (bufferInfo.m_semantic.m_name == m_positionName) - { - positionBuffer = &bufferInfo; - break; - } - } - - if (positionBuffer && positionBuffer->m_bufferAssetView.GetBufferAsset().Get()) - { - BufferAsset* bufferAssetViewPtr = positionBuffer->m_bufferAssetView.GetBufferAsset().Get(); + BufferAsset* bufferAssetViewPtr = positionBufferView->GetBufferAsset().Get(); BufferAsset* indexAssetViewPtr = indexBufferView.GetBufferAsset().Get(); if (!bufferAssetViewPtr || !indexAssetViewPtr) @@ -225,7 +213,7 @@ namespace AZ return false; } - RHI::BufferViewDescriptor positionBufferViewDesc = bufferAssetViewPtr->GetBufferViewDescriptor(); + RHI::BufferViewDescriptor positionBufferViewDesc = positionBufferView->GetBufferViewDescriptor(); AZStd::array_view positionRawBuffer = bufferAssetViewPtr->GetBuffer(); const uint32_t positionElementSize = positionBufferViewDesc.m_elementSize; @@ -234,22 +222,28 @@ namespace AZ // Position is 3 floats if (positionElementSize != sizeof(float) * 3) { - AZ_Warning("ModelAsset", false, "unsupported mesh posiiton format, only full 3 floats per vertex are supported at the moment"); + AZ_Warning( + "ModelAsset", false, "unsupported mesh posiiton format, only full 3 floats per vertex are supported at the moment"); return false; } + RHI::BufferViewDescriptor indexBufferViewDesc = indexBufferView.GetBufferViewDescriptor(); AZStd::array_view indexRawBuffer = indexAssetViewPtr->GetBuffer(); - RHI::BufferViewDescriptor indexRawDesc = indexAssetViewPtr->GetBufferViewDescriptor(); - - bool anyHit = false; const AZ::Vector3 rayEnd = rayStart + rayDir; AZ::Vector3 a, b, c; AZ::Vector3 intersectionNormal; + bool anyHit = false; float shortestDistanceNormalized = AZStd::numeric_limits::max(); - const AZ::u32* indexPtr = reinterpret_cast(indexRawBuffer.data()); - for (uint32_t indexIter = 0; indexIter <= indexRawDesc.m_elementCount - 3; indexIter += 3, indexPtr += 3) + + const AZ::u32* indexPtr = reinterpret_cast( + indexRawBuffer.data() + (indexBufferViewDesc.m_elementOffset * indexBufferViewDesc.m_elementSize)); + const float* positionPtr = reinterpret_cast( + positionRawBuffer.data() + (positionBufferViewDesc.m_elementOffset * positionBufferViewDesc.m_elementSize)); + + constexpr int StepSize = 3; // number of values per vertex (x, y, z) + for (uint32_t indexIter = 0; indexIter < indexBufferViewDesc.m_elementCount; indexIter += StepSize, indexPtr += StepSize) { AZ::u32 index0 = indexPtr[0]; AZ::u32 index1 = indexPtr[1]; @@ -261,17 +255,17 @@ namespace AZ return false; } - const float* p = reinterpret_cast(&positionRawBuffer[index0 * positionElementSize]); - a.Set(const_cast(p)); // faster than AZ::Vector3 c-tor - - p = reinterpret_cast(&positionRawBuffer[index1 * positionElementSize]); - b.Set(const_cast(p)); - - p = reinterpret_cast(&positionRawBuffer[index2 * positionElementSize]); - c.Set(const_cast(p)); + // faster than AZ::Vector3 c-tor + const float* aRef = &positionPtr[index0 * StepSize]; + a.Set(aRef); + const float* bRef = &positionPtr[index1 * StepSize]; + b.Set(bRef); + const float* cRef = &positionPtr[index2 * StepSize]; + c.Set(cRef); float currentDistanceNormalized; - if (AZ::Intersect::IntersectSegmentTriangleCCW(rayStart, rayEnd, a, b, c, intersectionNormal, currentDistanceNormalized)) + if (AZ::Intersect::IntersectSegmentTriangleCCW( + rayStart, rayEnd, a, b, c, intersectionNormal, currentDistanceNormalized)) { anyHit = true; diff --git a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp index 7b07e14de0..81d773d8c0 100644 --- a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp @@ -38,7 +38,7 @@ namespace UnitTest bufferData.resize(bufferSize); //The actual data doesn't matter - const uint8_t bufferDataSize = static_cast(bufferData.size()); + const uint8_t bufferDataSize = aznumeric_cast(bufferData.size()); for (uint8_t i = 0; i < bufferDataSize; ++i) { bufferData[i] = i; @@ -248,7 +248,8 @@ namespace UnitTest return asset; } - AZ::Data::Asset BuildTestModel(const uint32_t lodCount, const uint32_t sharedMeshCount, const uint32_t separateMeshCount, ExpectedModel& expectedModel) + AZ::Data::Asset BuildTestModel( + const uint32_t lodCount, const uint32_t sharedMeshCount, const uint32_t separateMeshCount, ExpectedModel& expectedModel) { using namespace AZ; @@ -989,6 +990,9 @@ namespace UnitTest uint32_t{ 0 }, 2, 1, 1, 2, 3, 4, 5, 6, 5, 7, 6, 0, 4, 2, 4, 6, 2, 1, 3, 5, 5, 3, 7, 0, 1, 4, 4, 1, 5, 2, 6, 3, 6, 7, 3, }; + static constexpr AZStd::array QuadPositions = { -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f }; + static constexpr AZStd::array QuadIndices = { uint32_t{ 0 }, 2, 1, 1, 2, 3 }; + // This class creates a Model with one LOD, whose mesh contains 2 planes. Plane 1 is in the XY plane at Z=-0.5, and // plane 2 is in the XY plane at Z=0.5. The two planes each have 9 quads which have been triangulated. It only has // a position and index buffer. @@ -1031,42 +1035,80 @@ namespace UnitTest static constexpr inline auto minmaxElement = AZStd::minmax_element(begin(TwoSeparatedPlanesIndices), end(TwoSeparatedPlanesIndices)); static_assert(*minmaxElement.second == (TwoSeparatedPlanesPositions.size() / 3) - 1); - template class TD; class TestMesh { public: + TestMesh() = default; + TestMesh(const float* positions, size_t positionCount, const uint32_t* indices, size_t indicesCount) { AZ::RPI::ModelLodAssetCreator lodCreator; - lodCreator.Begin(AZ::Data::AssetId(AZ::Uuid::CreateRandom())); + Begin(lodCreator); + Add(lodCreator, positions, positionCount, /*positionOffset=*/0, indices, indicesCount, /*indexOffset=*/0); + End(lodCreator); + } + // initiate the asset lod creation process (note: End must be called after meshes have been added). + void Begin(AZ::RPI::ModelLodAssetCreator& lodCreator) + { + lodCreator.Begin(AZ::Data::AssetId(AZ::Uuid::CreateRandom())); + } + + // add a sub mesh and reuse existing position/index buffer (be very careful with the offsets used) + void Add( + AZ::RPI::ModelLodAssetCreator& lodCreator, + const float* positions, + size_t positionCount, + size_t positionOffset, + AZ::Data::Asset positionBuffer, + const uint32_t* indices, + size_t indexCount, + size_t indexOffset, + AZ::Data::Asset indexBuffer) + { lodCreator.BeginMesh(); - lodCreator.SetMeshAabb(AZ::Aabb::CreateFromMinMax({-1.0f, -1.0f, -0.5f}, {1.0f, 1.0f, 0.5f})); + lodCreator.SetMeshAabb(AZ::Aabb::CreateFromMinMax({ -1.0f, -1.0f, -0.5f }, { 1.0f, 1.0f, 0.5f })); lodCreator.SetMeshMaterialSlot(AZ::Sfmt::GetInstance().Rand32()); - { - AZ::Data::Asset indexBuffer = BuildTestBuffer(static_cast(indicesCount), sizeof(uint32_t)); - AZStd::copy(indices, indices + indicesCount, reinterpret_cast(const_cast(indexBuffer->GetBuffer().data()))); - lodCreator.SetMeshIndexBuffer({ - indexBuffer, - AZ::RHI::BufferViewDescriptor::CreateStructured(0, static_cast(indicesCount), sizeof(uint32_t)) - }); - } + AZStd::copy( + indices, indices + indexCount, + reinterpret_cast(const_cast(indexBuffer->GetBuffer().data())) + indexOffset); + lodCreator.SetMeshIndexBuffer( + { indexBuffer, + AZ::RHI::BufferViewDescriptor::CreateStructured( + aznumeric_cast(indexOffset), aznumeric_cast(indexCount), sizeof(uint32_t)) }); + AZStd::copy( + positions, positions + positionCount, + reinterpret_cast(const_cast(positionBuffer->GetBuffer().data())) + positionOffset); + lodCreator.AddMeshStreamBuffer( + AZ::RHI::ShaderSemantic(AZ::Name("POSITION")), AZ::Name(), + { positionBuffer, + AZ::RHI::BufferViewDescriptor::CreateStructured( + aznumeric_cast(positionOffset / 3), aznumeric_cast(positionCount / 3), sizeof(float) * 3) }); - { - AZ::Data::Asset positionBuffer = BuildTestBuffer(static_cast(positionCount / 3), sizeof(float) * 3); - AZStd::copy(positions, positions + positionCount, reinterpret_cast(const_cast(positionBuffer->GetBuffer().data()))); - lodCreator.AddMeshStreamBuffer( - AZ::RHI::ShaderSemantic(AZ::Name("POSITION")), - AZ::Name(), - { - positionBuffer, - AZ::RHI::BufferViewDescriptor::CreateStructured(0, static_cast(positionCount / 3), sizeof(float) * 3) - } - ); - } lodCreator.EndMesh(); + } + // overload of Add - here a new index/position buffer is created for the new data instead of potentially reusing an existing buffer + void Add( + AZ::RPI::ModelLodAssetCreator& lodCreator, + const float* positions, + size_t positionCount, + size_t positionOffset, + const uint32_t* indices, + size_t indexCount, + size_t indexOffset) + { + AZ::Data::Asset indexBuffer = BuildTestBuffer(aznumeric_cast(indexCount), sizeof(uint32_t)); + AZ::Data::Asset positionBuffer = + BuildTestBuffer(aznumeric_cast(positionCount / 3), sizeof(float) * 3); + + Add(lodCreator, positions, positionCount, positionOffset, positionBuffer, indices, indexCount, indexOffset, indexBuffer); + } + + // complete the asset lod creation process + void End(AZ::RPI::ModelLodAssetCreator& lodCreator) + { AZ::Data::Asset lodAsset; lodCreator.End(lodAsset); @@ -1199,7 +1241,7 @@ namespace UnitTest constexpr float rayLength = 100.0f; EXPECT_THAT( m_kdTree->RayIntersection( - AZ::Vector3::CreateZero(), AZ::Vector3::CreateAxisZ(-rayLength), t, normal), testing::Eq(true)); + AZ::Vector3::CreateZero(), AZ::Vector3::CreateAxisZ(-rayLength), t, normal), testing::IsTrue()); EXPECT_THAT(t, testing::FloatEq(0.005f)); } @@ -1210,7 +1252,7 @@ namespace UnitTest constexpr float rayLength = 10.0f; EXPECT_THAT( - m_kdTree->RayIntersection(AZ::Vector3::CreateAxisZ(0.75f), AZ::Vector3::CreateAxisZ(-rayLength), t, normal), testing::Eq(true)); + m_kdTree->RayIntersection(AZ::Vector3::CreateAxisZ(0.75f), AZ::Vector3::CreateAxisZ(-rayLength), t, normal), testing::IsTrue()); EXPECT_THAT(t, testing::FloatEq(0.025f)); } @@ -1288,7 +1330,7 @@ namespace UnitTest EXPECT_THAT( m_mesh->GetModel()->LocalRayIntersectionAgainstModel( AZ::Vector3::CreateAxisZ(5.0f), -AZ::Vector3::CreateAxisZ(10.0f), AllowBruteForce, t, normal), - testing::Eq(true)); + testing::IsTrue()); EXPECT_THAT(t, testing::FloatEq(0.4f)); } @@ -1302,8 +1344,87 @@ namespace UnitTest EXPECT_THAT( m_mesh->GetModel()->LocalRayIntersectionAgainstModel( AZ::Vector3::CreateAxisY(10.0f), -AZ::Vector3::CreateAxisY(9.0f), AllowBruteForce, t, normal), - testing::Eq(true)); + testing::IsTrue()); EXPECT_THAT(t, testing::FloatEq(1.0f)); EXPECT_THAT(normal, IsClose(AZ::Vector3::CreateAxisY())); } + + // test to verify that each secondary sub meshes are still intersected with correctly when using brute-force + // ray intersection + class BruteForceMultiModelIntersectsFixture : public ModelTests + { + public: + inline static const float QuadOffsetX = 15.0f; + + void SetUp() override + { + ModelTests::SetUp(); + m_mesh = AZStd::make_unique(); + + AZ::RPI::ModelLodAssetCreator lodCreator; + m_mesh->Begin(lodCreator); + + // take default quad positions and offset in X by set amount + AZStd::vector offsetQuadPositions; + offsetQuadPositions.resize(QuadPositions.size()); + AZStd::copy(QuadPositions.begin(), QuadPositions.end(), offsetQuadPositions.begin()); + for (size_t xVertIndex = 0; xVertIndex < offsetQuadPositions.size(); xVertIndex += 3) + { + offsetQuadPositions[xVertIndex] += QuadOffsetX; + } + + // create shared buffer to store cube and quad mesh in the same buffer + const size_t indicesCount = QuadIndices.size() + CubeIndices.size(); + const size_t positionCount = QuadPositions.size() + CubePositions.size(); + AZ::Data::Asset indexBuffer = BuildTestBuffer(aznumeric_cast(indicesCount), sizeof(uint32_t)); + AZ::Data::Asset positionBuffer = + BuildTestBuffer(aznumeric_cast(positionCount / 3), sizeof(float) * 3); + + // add the cube mesh + m_mesh->Add( + lodCreator, CubePositions.data(), CubePositions.size(), 0, positionBuffer, CubeIndices.data(), CubeIndices.size(), 0, + indexBuffer); + // add the quad mesh (offset by the cube position and index data into the same buffer) + m_mesh->Add( + lodCreator, offsetQuadPositions.data(), offsetQuadPositions.size(), /*offset=*/CubePositions.size(), positionBuffer, + QuadIndices.data(), QuadIndices.size(), /*offset=*/CubeIndices.size(), indexBuffer); + + m_mesh->End(lodCreator); + } + + void TearDown() override + { + m_mesh.reset(); + ModelTests::TearDown(); + } + + AZStd::unique_ptr m_mesh; + inline static constexpr bool AllowBruteForce = false; + }; + + TEST_F(BruteForceMultiModelIntersectsFixture, RayIntersectsWithFirstSubMesh) + { + float t = 0.0f; + AZ::Vector3 normal = AZ::Vector3::CreateOne(); // invalid starting normal + // fire a ray at the first sub mesh and ensure a successful hit is returned + EXPECT_THAT( + m_mesh->GetModel()->LocalRayIntersectionAgainstModel( + AZ::Vector3(0.0f, 0.0f, 5.0f), -AZ::Vector3::CreateAxisZ(10.0f), AllowBruteForce, t, normal), + testing::IsTrue()); + EXPECT_THAT(t, testing::FloatEq(0.4f)); + EXPECT_THAT(normal, IsClose(AZ::Vector3::CreateAxisZ())); + } + + TEST_F(BruteForceMultiModelIntersectsFixture, RayIntersectsWithSecondSubMesh) + { + float t = 0.0f; + AZ::Vector3 normal = AZ::Vector3::CreateOne(); // invalid starting normal + // fire a ray at the second sub mesh and ensure a successful hit is returned + EXPECT_THAT( + m_mesh->GetModel()->LocalRayIntersectionAgainstModel( + AZ::Vector3(QuadOffsetX, 0.0f, 5.0f), -AZ::Vector3::CreateAxisZ(10.0f), AllowBruteForce, t, normal), + testing::IsTrue()); + EXPECT_THAT(t, testing::FloatEq(0.5f)); + EXPECT_THAT(normal, IsClose(AZ::Vector3::CreateAxisZ())); + } } // namespace UnitTest From 289d783f25a61d1789ef443190fb0d8fb4b7d7ab Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Thu, 11 Nov 2021 09:41:45 -0800 Subject: [PATCH 49/97] Fixes for Project Manager on Linux - Fix error with EngineFinder using the wrong path to locate project.json - Simplified and expanded clang detection - Remove forcing clang-12 for builds and will rely on the new cmake detection of clang by default Signed-off-by: Steve Pham <82231385+spham-amzn@users.noreply.github.com> --- .../Platform/Linux/ProjectBuilderWorker_linux.cpp | 14 -------------- .../Platform/Linux/ProjectUtils_linux.cpp | 15 +++++---------- .../Template/cmake/EngineFinder.cmake | 4 ++-- .../Template/cmake/EngineFinder.cmake | 4 ++-- 4 files changed, 9 insertions(+), 28 deletions(-) diff --git a/Code/Tools/ProjectManager/Platform/Linux/ProjectBuilderWorker_linux.cpp b/Code/Tools/ProjectManager/Platform/Linux/ProjectBuilderWorker_linux.cpp index 2987fc4dc2..fdeaef93bb 100644 --- a/Code/Tools/ProjectManager/Platform/Linux/ProjectBuilderWorker_linux.cpp +++ b/Code/Tools/ProjectManager/Platform/Linux/ProjectBuilderWorker_linux.cpp @@ -23,25 +23,11 @@ namespace O3DE::ProjectManager QString cmakeGenerator = (whichNinjaResult.IsSuccess()) ? "Ninja Multi-Config" : "Unix Makefiles"; bool compileProfileOnBuild = (whichNinjaResult.IsSuccess()); - // On Linux the default compiler is gcc. For O3DE, it is clang, so we need to specify the version of clang that is detected - // in order to get the compiler option. - auto compilerOptionResult = ProjectUtils::FindSupportedCompilerForPlatform(); - if (!compilerOptionResult.IsSuccess()) - { - return AZ::Failure(compilerOptionResult.GetError()); - } - auto clangCompilers = compilerOptionResult.GetValue().split('|'); - AZ_Assert(clangCompilers.length()==2, "Invalid clang compiler pair specification"); - - QString clangCompilerOption = clangCompilers[0]; - QString clangPPCompilerOption = clangCompilers[1]; QString targetBuildPath = QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix); QStringList generateProjectArgs = QStringList{ProjectCMakeCommand, "-B", ProjectBuildPathPostfix, "-S", ".", QString("-G%1").arg(cmakeGenerator), - QString("-DCMAKE_C_COMPILER=").append(clangCompilerOption), - QString("-DCMAKE_CXX_COMPILER=").append(clangPPCompilerOption), QString("-DLY_3RDPARTY_PATH=").append(thirdPartyPath)}; if (!compileProfileOnBuild) { diff --git a/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp b/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp index e901d807b4..dc3ec55dee 100644 --- a/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp +++ b/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp @@ -17,13 +17,11 @@ namespace O3DE::ProjectManager namespace ProjectUtils { // The list of clang C/C++ compiler command lines to validate on the host Linux system - const QStringList SupportedClangCommands = {"clang-12|clang++-12"}; + const QStringList SupportedClangVersions = {"13", "12", "11", "10", "9", "8", "7", "6.0"}; AZ::Outcome GetCommandLineProcessEnvironment() { QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment()); - currentEnvironment.insert("CC", "clang-12"); - currentEnvironment.insert("CXX", "clang++-12"); return AZ::Success(currentEnvironment); } @@ -39,16 +37,13 @@ namespace O3DE::ProjectManager } // Look for the first compatible version of clang. The list below will contain the known clang compilers that have been tested for O3DE. - for (const QString& supportClangCommand : SupportedClangCommands) + for (const QString& supportClangVersion : SupportedClangVersions) { - auto clangCompilers = supportClangCommand.split('|'); - AZ_Assert(clangCompilers.length()==2, "Invalid clang compiler pair specification"); - - auto whichClangResult = ProjectUtils::ExecuteCommandResult("which", QStringList{clangCompilers[0]}, QProcessEnvironment::systemEnvironment()); - auto whichClangPPResult = ProjectUtils::ExecuteCommandResult("which", QStringList{clangCompilers[1]}, QProcessEnvironment::systemEnvironment()); + auto whichClangResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang-%1").arg(supportClangVersion)}, QProcessEnvironment::systemEnvironment()); + auto whichClangPPResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang++-%1").arg(supportClangVersion)}, QProcessEnvironment::systemEnvironment()); if (whichClangResult.IsSuccess() && whichClangPPResult.IsSuccess()) { - return AZ::Success(supportClangCommand); + return AZ::Success(QString("clang-%1").arg(supportClangVersion)); } } return AZ::Failure(QObject::tr("Clang not found.

" diff --git a/Templates/DefaultProject/Template/cmake/EngineFinder.cmake b/Templates/DefaultProject/Template/cmake/EngineFinder.cmake index 98ad61bae8..15b96eb8a9 100644 --- a/Templates/DefaultProject/Template/cmake/EngineFinder.cmake +++ b/Templates/DefaultProject/Template/cmake/EngineFinder.cmake @@ -13,8 +13,8 @@ include_guard() # Read the engine name from the project_json file -file(READ ${CMAKE_CURRENT_LIST_DIR}/project.json project_json) -set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/project.json) +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/project.json project_json) +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/project.json) string(JSON LY_ENGINE_NAME_TO_USE ERROR_VARIABLE json_error GET ${project_json} engine) if(json_error) diff --git a/Templates/MinimalProject/Template/cmake/EngineFinder.cmake b/Templates/MinimalProject/Template/cmake/EngineFinder.cmake index 98ad61bae8..15b96eb8a9 100644 --- a/Templates/MinimalProject/Template/cmake/EngineFinder.cmake +++ b/Templates/MinimalProject/Template/cmake/EngineFinder.cmake @@ -13,8 +13,8 @@ include_guard() # Read the engine name from the project_json file -file(READ ${CMAKE_CURRENT_LIST_DIR}/project.json project_json) -set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/project.json) +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/project.json project_json) +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/project.json) string(JSON LY_ENGINE_NAME_TO_USE ERROR_VARIABLE json_error GET ${project_json} engine) if(json_error) From d71196102f875150b03cd0c9c550fbdc356bb989 Mon Sep 17 00:00:00 2001 From: nggieber Date: Thu, 11 Nov 2021 10:20:46 -0800 Subject: [PATCH 50/97] More PR feedback changes Signed-off-by: nggieber --- .../Source/GemCatalog/GemCatalogScreen.cpp | 6 ++---- .../Source/GemCatalog/GemUpdateDialog.cpp | 4 ++-- .../ProjectManager/Source/PythonBindings.cpp | 21 ++++++++++++++++--- .../ProjectManager/Source/PythonBindings.h | 4 +++- .../Source/PythonBindingsInterface.h | 11 ++++++++-- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index cff9a28db3..7004fe24d4 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -363,7 +363,7 @@ namespace O3DE::ProjectManager const QString selectedGemPath = m_gemModel->GetPath(modelIndex); // Unregister the gem - auto unregisterResult = PythonBindingsInterface::Get()->RegisterGem(selectedGemPath, {}, /*remove*/true); + auto unregisterResult = PythonBindingsInterface::Get()->UnregisterGem(selectedGemPath); if (!unregisterResult) { QMessageBox::critical(this, tr("Failed to unregister gem"), unregisterResult.GetError().c_str()); @@ -419,10 +419,8 @@ namespace O3DE::ProjectManager { // Add all available gems to the model. const QVector& allGemInfos = allGemInfosResult.GetValue(); - for (GemInfo gemInfo : allGemInfos) + for (const GemInfo& gemInfo : allGemInfos) { - // Mark as downloaded because this gem was registered with an existing directory - gemInfo.m_downloadStatus = GemInfo::DownloadStatus::Downloaded; m_gemModel->AddGem(gemInfo); } diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp index 3e68c597de..82d205aab5 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemUpdateDialog.cpp @@ -41,12 +41,12 @@ namespace O3DE::ProjectManager "Updating this Gem will remove any local changes made to this Gem, " "and may remove old features that are in use.").arg( updateAvaliable ? "" : tr("No update detected for Gem. " - "This will force a redownload of the gem anyways. "))); + "This will force a re-download of the gem. "))); bodyLabel->setWordWrap(true); bodyLabel->setFixedSize(QSize(440, 80)); layout->addWidget(bodyLabel); - layout->addSpacing(); + layout->addSpacing(40); // Buttons QDialogButtonBox* dialogButtons = new QDialogButtonBox(); diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index ef7daa761e..e0208a266c 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -515,7 +515,11 @@ namespace O3DE::ProjectManager auto pyProjectPath = QString_To_Py_Path(projectPath); for (auto path : m_manifest.attr("get_all_gems")(pyProjectPath)) { - gems.push_back(GemInfoFromPath(path, pyProjectPath)); + GemInfo gemInfo = GemInfoFromPath(path, pyProjectPath); + // Mark as downloaded because this gem was registered with an existing directory + gemInfo.m_downloadStatus = GemInfo::DownloadStatus::Downloaded; + + gems.push_back(AZStd::move(gemInfo)); } }); if (!result.IsSuccess()) @@ -560,7 +564,7 @@ namespace O3DE::ProjectManager return AZ::Success(AZStd::move(gemNames)); } - AZ::Outcome PythonBindings::RegisterGem(const QString& gemPath, const QString& projectPath, bool remove) + AZ::Outcome PythonBindings::GemRegistration(const QString& gemPath, const QString& projectPath, bool remove) { bool registrationResult = false; auto result = ExecuteWithLockErrorHandling( @@ -596,12 +600,23 @@ namespace O3DE::ProjectManager } else if (!registrationResult) { - return AZ::Failure(AZStd::string::format("Failed to register gem path %s", gemPath.toUtf8().constData())); + return AZ::Failure(AZStd::string::format( + "Failed to %s gem path %s", remove ? "unregister" : "register", gemPath.toUtf8().constData())); } return AZ::Success(); } + AZ::Outcome PythonBindings::RegisterGem(const QString& gemPath, const QString& projectPath) + { + return GemRegistration(gemPath, projectPath); + } + + AZ::Outcome PythonBindings::UnregisterGem(const QString& gemPath, const QString& projectPath) + { + return GemRegistration(gemPath, projectPath, /*remove*/true); + } + bool PythonBindings::AddProject(const QString& path) { bool registrationResult = false; diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.h b/Code/Tools/ProjectManager/Source/PythonBindings.h index 8a22344596..d258898fae 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.h +++ b/Code/Tools/ProjectManager/Source/PythonBindings.h @@ -42,7 +42,8 @@ namespace O3DE::ProjectManager AZ::Outcome, AZStd::string> GetEngineGemInfos() override; AZ::Outcome, AZStd::string> GetAllGemInfos(const QString& projectPath) override; AZ::Outcome, AZStd::string> GetEnabledGemNames(const QString& projectPath) override; - AZ::Outcome RegisterGem(const QString& gemPath, const QString& projectPath = {}, bool remove = false) override; + AZ::Outcome RegisterGem(const QString& gemPath, const QString& projectPath = {}) override; + AZ::Outcome UnregisterGem(const QString& gemPath, const QString& projectPath = {}) override; // Project AZ::Outcome CreateProject(const QString& projectTemplatePath, const ProjectInfo& projectInfo) override; @@ -78,6 +79,7 @@ namespace O3DE::ProjectManager GemRepoInfo GetGemRepoInfo(pybind11::handle repoUri); ProjectInfo ProjectInfoFromPath(pybind11::handle path); ProjectTemplateInfo ProjectTemplateInfoFromPath(pybind11::handle path, pybind11::handle pyProjectPath); + AZ::Outcome GemRegistration(const QString& gemPath, const QString& projectPath, bool remove = false); bool RegisterThisEngine(); bool StopPython(); diff --git a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h index 07d4551c60..6c8b0c89a6 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h +++ b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h @@ -95,10 +95,17 @@ namespace O3DE::ProjectManager * Registers the gem to the specified project, or to the o3de_manifest.json if no project path is given * @param gemPath the path to the gem * @param projectPath the path to the project. If empty, will register the external path in o3de_manifest.json - * @param remove Unregister instead of registering this gem * @return An outcome with the success flag as well as an error message in case of a failure. */ - virtual AZ::Outcome RegisterGem(const QString& gemPath, const QString& projectPath = {}, bool remove = false) = 0; + virtual AZ::Outcome RegisterGem(const QString& gemPath, const QString& projectPath = {}) = 0; + + /** + * Unregisters the gem from the specified project, or from the o3de_manifest.json if no project path is given + * @param gemPath the path to the gem + * @param projectPath the path to the project. If empty, will unregister the external path in o3de_manifest.json + * @return An outcome with the success flag as well as an error message in case of a failure. + */ + virtual AZ::Outcome UnregisterGem(const QString& gemPath, const QString& projectPath = {}) = 0; // Projects From 2b248ac4859a4d35bed04b6bd4d21a38316c5edc Mon Sep 17 00:00:00 2001 From: nggieber Date: Thu, 11 Nov 2021 12:09:24 -0800 Subject: [PATCH 51/97] Fix merge issue and validation issue Signed-off-by: nggieber --- Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp | 4 +++- .../ProjectManager/Source/GemCatalog/GemUninstallDialog.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp index 52e078eacd..26844b43e6 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp @@ -127,7 +127,9 @@ namespace O3DE::ProjectManager m_binarySizeLabel->setText(tr("Binary Size: %1").arg(binarySize ? tr("%1 KB").arg(binarySize) : tr("Unknown"))); // Update and Uninstall buttons - if (m_model->GetGemOrigin(modelIndex) == GemInfo::Remote && m_model->GetDownloadStatus(modelIndex) == GemInfo::Downloaded) + if (m_model->GetGemOrigin(modelIndex) == GemInfo::Remote && + (m_model->GetDownloadStatus(modelIndex) == GemInfo::Downloaded || + m_model->GetDownloadStatus(modelIndex) == GemInfo::DownloadSuccessful)) { m_updateGemButton->show(); m_uninstallGemButton->show(); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.cpp index 6b2f14e551..1408e29b6d 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemUninstallDialog.cpp @@ -36,7 +36,7 @@ namespace O3DE::ProjectManager layout->addSpacing(10); - QLabel* bodyLabel = new QLabel(tr("The Gem and its related files will be uninstalled. This does not affect the Gem’s repository. " + QLabel* bodyLabel = new QLabel(tr("The Gem and its related files will be uninstalled. This does not affect the Gem's repository. " "You can reinstall this Gem from the Catalog, but its contents may be subject to change.")); bodyLabel->setWordWrap(true); bodyLabel->setFixedSize(QSize(440, 80)); From 71eedb895d69314abf3a999fc10a44e7edd5ed59 Mon Sep 17 00:00:00 2001 From: rgba16f <82187279+rgba16f@users.noreply.github.com> Date: Wed, 10 Nov 2021 10:26:03 -0600 Subject: [PATCH 52/97] Move PipelineStateCache validation of set uniqeness to only be active in debug builds (#5472) Signed-off-by: rgba16f <82187279+rgba16f@users.noreply.github.com> --- Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp b/Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp index 0c06887dd6..79c05c37da 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp @@ -41,9 +41,12 @@ namespace AZ AZ_Assert(readOnlyCache.empty(), "Inactive library has pipeline states in its global entry."); } +#if defined(AZ_DEBUG_BUILD) + // the PipelineStateSet is expensive to duplicate, only do this in debug. PipelineStateSet readOnlyCacheCopy = readOnlyCache; AZ_Assert(AZStd::unique(readOnlyCacheCopy.begin(), readOnlyCacheCopy.end()) == readOnlyCacheCopy.end(), "'%d' Duplicates existed in the read-only cache!", readOnlyCache.size() - readOnlyCacheCopy.size()); +#endif } m_threadLibrarySet.ForEach([this](const ThreadLibrarySet& threadLibrarySet) From 394ba9a8bcb061be377a115f596dac834b753f85 Mon Sep 17 00:00:00 2001 From: rgba16f <82187279+rgba16f@users.noreply.github.com> Date: Wed, 10 Nov 2021 14:08:55 -0600 Subject: [PATCH 53/97] Atom CPU threading optimization (#5481) * Small change to make the RasterPass Scope jobs split the work more evenly over the cores Signed-off-by: rgba16f <82187279+rgba16f@users.noreply.github.com> * Update with PR feedback. Remove scale of EstimatedItemCount, modify the command list cost threshold instead Signed-off-by: rgba16f <82187279+rgba16f@users.noreply.github.com> --- .../Include/Atom/RHI.Reflect/DX12/PlatformLimitsDescriptor.h | 2 +- .../Include/Atom/RHI.Reflect/Metal/PlatformLimitsDescriptor.h | 2 +- .../Include/Atom/RHI.Reflect/Vulkan/PlatformLimitsDescriptor.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/RHI/DX12/Code/Include/Atom/RHI.Reflect/DX12/PlatformLimitsDescriptor.h b/Gems/Atom/RHI/DX12/Code/Include/Atom/RHI.Reflect/DX12/PlatformLimitsDescriptor.h index 63c2d69ea2..1a447693c2 100644 --- a/Gems/Atom/RHI/DX12/Code/Include/Atom/RHI.Reflect/DX12/PlatformLimitsDescriptor.h +++ b/Gems/Atom/RHI/DX12/Code/Include/Atom/RHI.Reflect/DX12/PlatformLimitsDescriptor.h @@ -40,7 +40,7 @@ namespace AZ uint32_t m_swapChainsPerCommandList = 8; // The maximum cost that can be associated with a single command list. - uint32_t m_commandListCostThresholdMin = 1000; + uint32_t m_commandListCostThresholdMin = 250; // The maximum number of command lists per scope. uint32_t m_commandListsPerScopeMax = 16; diff --git a/Gems/Atom/RHI/Metal/Code/Include/Atom/RHI.Reflect/Metal/PlatformLimitsDescriptor.h b/Gems/Atom/RHI/Metal/Code/Include/Atom/RHI.Reflect/Metal/PlatformLimitsDescriptor.h index 375b532d39..bd52c37a67 100644 --- a/Gems/Atom/RHI/Metal/Code/Include/Atom/RHI.Reflect/Metal/PlatformLimitsDescriptor.h +++ b/Gems/Atom/RHI/Metal/Code/Include/Atom/RHI.Reflect/Metal/PlatformLimitsDescriptor.h @@ -31,7 +31,7 @@ namespace AZ uint32_t m_swapChainsPerCommandList = 8; // The maximum cost that can be associated with a single command list. - uint32_t m_commandListCostThresholdMin = 1000; + uint32_t m_commandListCostThresholdMin = 250; // The maximum number of command lists per scope. uint32_t m_commandListsPerScopeMax = 16; diff --git a/Gems/Atom/RHI/Vulkan/Code/Include/Atom/RHI.Reflect/Vulkan/PlatformLimitsDescriptor.h b/Gems/Atom/RHI/Vulkan/Code/Include/Atom/RHI.Reflect/Vulkan/PlatformLimitsDescriptor.h index 5e41da9627..eaa4356796 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Include/Atom/RHI.Reflect/Vulkan/PlatformLimitsDescriptor.h +++ b/Gems/Atom/RHI/Vulkan/Code/Include/Atom/RHI.Reflect/Vulkan/PlatformLimitsDescriptor.h @@ -33,7 +33,7 @@ namespace AZ uint32_t m_swapChainsPerCommandList = 8; // The maximum cost that can be associated with a single command list. - uint32_t m_commandListCostThresholdMin = 1000; + uint32_t m_commandListCostThresholdMin = 250; // The maximum number of command lists per scope. uint32_t m_commandListsPerScopeMax = 16; From f1d9e7ae28bf0667487c939aa32b1ef833da80f4 Mon Sep 17 00:00:00 2001 From: Tommy Walton Date: Thu, 11 Nov 2021 12:55:06 -0800 Subject: [PATCH 54/97] Skybox hot reloading - fix black screen when running the editor for the first time with a clean cache (#5529) * Add a default fallback image when a StreamingImageAsset fails to load Signed-off-by: Tommy Walton * Don't release a missing/invalid texture reference in the skybox component. Hold on to the reference so that it can hot-reload Signed-off-by: Tommy Walton * Don't release a missing/invalid texture reference in the ibl component. Hold on to the reference so that it can hot-reload Signed-off-by: Tommy Walton * Use a different fallback image depending on the status of the asset. Including a setting to use a friendly image that is less obnoxious for anything that might have been missed in a release build Signed-off-by: Tommy Walton * Adding the stubbed in fallback textures Signed-off-by: Tommy Walton * Updated the seedlist for the RPI to include the fallback images. It only needs the default and the missing asset images, since the AP doesn't run in release builds, the asset status will always be unknown, not processing or failed to process, so if an asset is not bundled, it is just missing. Signed-off-by: Tommy Walton * Switched to GetAssetIdByPath and removed some tabs Signed-off-by: Tommy Walton --- .../Textures/Defaults/DefaultFallback.png | 3 + .../RPI/Assets/Textures/Defaults/Missing.png | 3 + .../Assets/Textures/Defaults/Processing.png | 3 + .../Textures/Defaults/ProcessingFailed.png | 3 + Gems/Atom/RPI/Assets/seedList.seed | 16 ++++++ .../Image/StreamingImageAssetHandler.h | 3 + .../Image/StreamingImageAssetHandler.cpp | 57 ++++++++++++++++++- .../Atom/RPI/Registry/atom_rpi.release.setreg | 9 +++ Gems/Atom/RPI/Registry/atom_rpi.setreg | 3 +- .../ImageBasedLightComponentController.cpp | 2 - .../SkyBox/HDRiSkyboxComponentController.cpp | 2 - 11 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/DefaultFallback.png create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png create mode 100644 Gems/Atom/RPI/Registry/atom_rpi.release.setreg diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/DefaultFallback.png b/Gems/Atom/RPI/Assets/Textures/Defaults/DefaultFallback.png new file mode 100644 index 0000000000..1352d14edf --- /dev/null +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/DefaultFallback.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb91c050a829ff03b972202cf8c90034e4f252d972332224791d135c07d9d528 +size 796 diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png b/Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png new file mode 100644 index 0000000000..3e9bc68ea5 --- /dev/null +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28c3cfd8958813b4b539738bfff589731da0aeec5b3376558f377da2ebe973ff +size 5455 diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png b/Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png new file mode 100644 index 0000000000..914499d6e7 --- /dev/null +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a0935be7347d695ed1716d030b5bae68153a88239b0ff15f67f900ac90be442 +size 5038 diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png b/Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png new file mode 100644 index 0000000000..558b16b96e --- /dev/null +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb243cd6d6414b4e95eab919fa94193b57825902b8d09f40ce3f334d829e74e2 +size 6286 diff --git a/Gems/Atom/RPI/Assets/seedList.seed b/Gems/Atom/RPI/Assets/seedList.seed index 300092e6c3..622638d698 100644 --- a/Gems/Atom/RPI/Assets/seedList.seed +++ b/Gems/Atom/RPI/Assets/seedList.seed @@ -24,6 +24,22 @@ + + + + + + + + + + + + + + + + diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAssetHandler.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAssetHandler.h index 3f4e15744a..b3b62cbc31 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAssetHandler.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAssetHandler.h @@ -25,6 +25,9 @@ namespace AZ const Data::Asset& asset, AZStd::shared_ptr stream, const Data::AssetFilterCB& assetLoadFilterCB) override; + + // Return a default fallback image if an asset is missing + Data::AssetId AssetMissingInCatalog(const Data::Asset& /*asset*/) override; }; } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAssetHandler.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAssetHandler.cpp index fa39820329..fd04635da3 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAssetHandler.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAssetHandler.cpp @@ -7,6 +7,8 @@ */ #include +#include +#include namespace AZ { @@ -40,5 +42,56 @@ namespace AZ return loadResult; } - } -} + + Data::AssetId StreamingImageAssetHandler::AssetMissingInCatalog(const Data::Asset& asset) + { + // Find out if the asset is missing completely, or just still processing + // and escalate the asset to the top of the list + AzFramework::AssetSystem::AssetStatus missingAssetStatus; + AzFramework::AssetSystemRequestBus::BroadcastResult( + missingAssetStatus, &AzFramework::AssetSystem::AssetSystemRequests::GetAssetStatusById, asset.GetId().m_guid); + + // Determine which fallback image to use + const char* relativePath = "textures/defaults/defaultfallback.png.streamingimage"; + + bool useDebugFallbackImages = true; + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + settingsRegistry->GetObject(useDebugFallbackImages, "/O3DE/Atom/RPI/UseDebugFallbackImages"); + } + + if (useDebugFallbackImages) + { + switch (missingAssetStatus) + { + case AzFramework::AssetSystem::AssetStatus::AssetStatus_Queued: + case AzFramework::AssetSystem::AssetStatus::AssetStatus_Compiling: + relativePath = "textures/defaults/processing.png.streamingimage"; + break; + case AzFramework::AssetSystem::AssetStatus::AssetStatus_Failed: + relativePath = "textures/defaults/processingfailed.png.streamingimage"; + break; + case AzFramework::AssetSystem::AssetStatus::AssetStatus_Missing: + case AzFramework::AssetSystem::AssetStatus::AssetStatus_Unknown: + case AzFramework::AssetSystem::AssetStatus::AssetStatus_Compiled: + relativePath = "textures/defaults/missing.png.streamingimage"; + break; + } + } + + // Make sure the fallback image has been processed + AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown; + AzFramework::AssetSystemRequestBus::BroadcastResult( + status, &AzFramework::AssetSystemRequestBus::Events::CompileAssetSync, relativePath); + + // Return the asset id of the fallback image + Data::AssetId assetId{}; + bool autoRegisterIfNotFound = false; + Data::AssetCatalogRequestBus::BroadcastResult( + assetId, &Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, relativePath, + azrtti_typeid(), autoRegisterIfNotFound); + + return assetId; + } + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/RPI/Registry/atom_rpi.release.setreg b/Gems/Atom/RPI/Registry/atom_rpi.release.setreg new file mode 100644 index 0000000000..72fb4f01e8 --- /dev/null +++ b/Gems/Atom/RPI/Registry/atom_rpi.release.setreg @@ -0,0 +1,9 @@ +{ + "O3DE": { + "Atom": { + "RPI": { + "UseDebugFallbackImages": false + } + } + } +} diff --git a/Gems/Atom/RPI/Registry/atom_rpi.setreg b/Gems/Atom/RPI/Registry/atom_rpi.setreg index bcbade5d38..9f3cacd1a9 100644 --- a/Gems/Atom/RPI/Registry/atom_rpi.setreg +++ b/Gems/Atom/RPI/Registry/atom_rpi.setreg @@ -17,7 +17,8 @@ "DynamicDrawSystemDescriptor": { "DynamicBufferPoolSize": 50331648 // 3 * 16 * 1024 * 1024 (for 3 frames) } - } + }, + "UseDebugFallbackImages": true } } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ImageBasedLights/ImageBasedLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ImageBasedLights/ImageBasedLightComponentController.cpp index 6ea7580fc6..73cfd53c21 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ImageBasedLights/ImageBasedLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ImageBasedLights/ImageBasedLightComponentController.cpp @@ -163,8 +163,6 @@ namespace AZ return true; } } - // If this asset didn't load or isn't a cubemap, release it. - configAsset.Release(); return false; } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/HDRiSkyboxComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/HDRiSkyboxComponentController.cpp index 171c5e417f..7bf6237c1a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/HDRiSkyboxComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/HDRiSkyboxComponentController.cpp @@ -196,8 +196,6 @@ namespace AZ } else { - // If this asset didn't load or isn't a cubemap, release it. - m_configuration.m_cubemapAsset.Release(); m_featureProcessorInterface->SetCubemap(nullptr); } } From e3c3db4ba61b230a69b670e02873c0f4b7766504 Mon Sep 17 00:00:00 2001 From: Tommy Walton Date: Thu, 11 Nov 2021 12:55:23 -0800 Subject: [PATCH 55/97] In Atom_Feature_Common.static, get cvar values from cvar system instead of reading directly (#5350) Signed-off-by: Tommy Walton --- .../Common/Code/Source/FrameCaptureSystemComponent.cpp | 7 ++++++- .../Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp index a9bb7271ab..09f0d3f917 100644 --- a/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp @@ -97,7 +97,12 @@ namespace AZ Utils::PngFile image = Utils::PngFile::Create(readbackResult.m_imageDescriptor.m_size, format, *buffer); Utils::PngFile::SaveSettings saveSettings; - saveSettings.m_compressionLevel = r_pngCompressionLevel; + + if (auto console = AZ::Interface::Get(); console != nullptr) + { + console->GetCvarValue("r_pngCompressionLevel", saveSettings.m_compressionLevel); + } + // We should probably strip alpha to save space, especially for automated test screenshots. Alpha is left in to maintain // prior behavior, changing this is out of scope for the current task. Note, it would have bit of a cascade effect where // AtomSampleViewer's ScriptReporter assumes an RGBA image. diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp index 8bf518e277..87fb46a7c6 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp @@ -98,7 +98,12 @@ namespace AZ } m_needsInit = false; - const AZ::u64 sizeInMb = r_skinnedMeshInstanceMemoryPoolSize; + AZ::u64 sizeInMb{}; + if (auto console = AZ::Interface::Get(); console != nullptr) + { + console->GetCvarValue("r_skinnedMeshInstanceMemoryPoolSize", sizeInMb); + } + m_sizeInBytes = sizeInMb * (1024u * 1024u); CalculateAlignment(); From e0d736dd844a82b0c232739540a168078e63e276 Mon Sep 17 00:00:00 2001 From: galibzon <66021303+galibzon@users.noreply.github.com> Date: Thu, 11 Nov 2021 16:04:22 -0600 Subject: [PATCH 56/97] Fixed the other call to CreateVariable (#5561) in favor of CreateVariableEx Signed-off-by: galibzon <66021303+galibzon@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp index 6cba54a17f..1b39eb81bd 100644 --- a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp +++ b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp @@ -32,7 +32,12 @@ namespace AZ if (!s_instance) { - s_instance = AZ::Environment::CreateVariable(NameDictionaryInstanceName); + // Because the NameDictionary allocates memory using the AZ::Allocator and it is created + // in the executable memory space, it's ownership cannot be transferred to other module memory spaces + // Otherwise this could cause the the NameDictionary to be destroyed in static de-init + // after the AZ::Allocators have been destroyed + // Therefore we supply the isTransferOwnership value of false using CreateVariableEx + s_instance = AZ::Environment::CreateVariableEx(NameDictionaryInstanceName, true, false); } } From 6ffee4b0a8292b5ad6bb9a35b49655c62b2b5b3b Mon Sep 17 00:00:00 2001 From: Allen Jackson <23512001+jackalbe@users.noreply.github.com> Date: Thu, 11 Nov 2021 16:07:02 -0600 Subject: [PATCH 57/97] {lyn7352} adding more logging around mock_asset_builder.py (#5103) (#5566) o3de\AutomatedTesting\Gem\PythonTests\PythonAssetBuilder\mock_asset_builder.py - adding more logging - updated keys for platforms (pc, server) Signed-off-by: Allen Jackson <23512001+jackalbe@users.noreply.github.com> --- .../Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py index 443a420b61..a6e8b97b63 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py @@ -23,7 +23,7 @@ def create_jobs(request): jobDescriptorList = [] for platformInfo in request.enabledPlatforms: jobDesc = azlmbr.asset.builder.JobDescriptor() - jobDesc.jobKey = jobKeyName + jobDesc.jobKey = f'{jobKeyName}-{platformInfo.identifier}' jobDesc.set_platform_identifier(platformInfo.identifier) jobDescriptorList.append(jobDesc) @@ -38,7 +38,7 @@ def on_create_jobs(args): return create_jobs(request) except: log_exception_traceback() - # returing back a default CreateJobsResponse() records an asset error + # returning back a default CreateJobsResponse() records an asset error return azlmbr.asset.builder.CreateJobsResponse() def process_file(request): @@ -58,6 +58,7 @@ def process_file(request): fileOutput = open(tempFilename, "w") fileOutput.write('{}') fileOutput.close() + print(f'Wrote mock asset file: {tempFilename}') # generate a product asset file entry subId = binascii.crc32(mockFilename.encode()) From b8f7767cd6ca0201cd5ae0a44c37b75d42f22299 Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Thu, 11 Nov 2021 16:11:52 -0800 Subject: [PATCH 58/97] [Resource Mapping Tool] make top-level Account id optional in ResourceMapping tool schema (#5569) * [Resource Mapping Tool] make top-level Account id optional in ResourceMapping tool schema Signed-off-by: junbo75 <68558268+junbo75@users.noreply.github.com> --- .../controller/view_edit_controller.py | 6 +-- .../controller/test_view_edit_controller.py | 52 +++++++++++++++++-- .../tests/unit/utils/test_json_utils.py | 5 ++ .../ResourceMappingTool/utils/json_utils.py | 2 +- 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/controller/view_edit_controller.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/controller/view_edit_controller.py index bdfe7fa11e..39f7b5ccf1 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/controller/view_edit_controller.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/controller/view_edit_controller.py @@ -69,17 +69,13 @@ class ViewEditController(QObject): json_dict: Dict[str, any] = \ json_utils.convert_resources_to_json_dict(self._proxy_model.get_resources(), self._config_file_json_source) - configuration: Configuration = self._configuration_manager.configuration - if json_dict.get(json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME) == \ - json_utils.RESOURCE_MAPPING_ACCOUNTID_TEMPLATE_VALUE: - json_dict[json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] = configuration.account_id - if json_dict == self._config_file_json_source: # skip because no difference found against existing json file return True # try to write in memory json content into json file try: + configuration: Configuration = self._configuration_manager.configuration config_file_full_path: str = file_utils.join_path(configuration.config_directory, config_file_name) json_utils.write_into_json_file(config_file_full_path, json_dict) self._config_file_json_source = json_dict diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_view_edit_controller.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_view_edit_controller.py index c73bddcd9c..41d4490c44 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_view_edit_controller.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_view_edit_controller.py @@ -420,8 +420,30 @@ class TestViewEditController(TestCase): self._mocked_view_edit_page.config_file_combobox.currentText.return_value = \ TestViewEditController._expected_config_file_name expected_json_dict: Dict[str, any] = { - "dummyKey": "dummyValue", - self._expected_account_id_attribute_name: self._expected_account_id_template_vale} + "dummyKey": "dummyValue" + } + mock_json_utils.validate_resources_according_to_json_schema.return_value = [] + mock_json_utils.convert_resources_to_json_dict.return_value = expected_json_dict + mock_file_utils.join_path.return_value = TestViewEditController._expected_config_file_full_path + mocked_call_args: call = self._mocked_view_edit_page.save_changes_button.clicked.connect.call_args[0] + + mocked_call_args[0]() # triggering save_changes_button connected function + mock_json_utils.convert_resources_to_json_dict.assert_called_once() + mock_json_utils.write_into_json_file.assert_called_once_with( + TestViewEditController._expected_config_file_full_path, expected_json_dict) + self._mocked_proxy_model.override_all_resources_status.assert_called_once_with( + ResourceMappingAttributesStatus(ResourceMappingAttributesStatus.SUCCESS_STATUS_VALUE, + [ResourceMappingAttributesStatus.SUCCESS_STATUS_VALUE])) + + @patch("controller.view_edit_controller.file_utils") + @patch("controller.view_edit_controller.json_utils") + def test_page_save_changes_button_json_file_saved_and_template_account_id_unchanged( + self, mock_json_utils: MagicMock, mock_file_utils: MagicMock) -> None: + self._mocked_view_edit_page.config_file_combobox.currentText.return_value = \ + TestViewEditController._expected_config_file_name + expected_json_dict: Dict[str, any] = { + self._expected_account_id_attribute_name: self._expected_account_id_template_vale + } mock_json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME = self._expected_account_id_attribute_name mock_json_utils.RESOURCE_MAPPING_ACCOUNTID_TEMPLATE_VALUE = self._expected_account_id_template_vale mock_json_utils.validate_resources_according_to_json_schema.return_value = [] @@ -430,7 +452,31 @@ class TestViewEditController(TestCase): mocked_call_args: call = self._mocked_view_edit_page.save_changes_button.clicked.connect.call_args[0] mocked_call_args[0]() # triggering save_changes_button connected function - assert expected_json_dict["AccountId"] == self._mocked_configuration_manager.configuration.account_id + assert expected_json_dict[mock_json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] == self._expected_account_id_template_vale + mock_json_utils.convert_resources_to_json_dict.assert_called_once() + mock_json_utils.write_into_json_file.assert_called_once_with( + TestViewEditController._expected_config_file_full_path, expected_json_dict) + self._mocked_proxy_model.override_all_resources_status.assert_called_once_with( + ResourceMappingAttributesStatus(ResourceMappingAttributesStatus.SUCCESS_STATUS_VALUE, + [ResourceMappingAttributesStatus.SUCCESS_STATUS_VALUE])) + + @patch("controller.view_edit_controller.file_utils") + @patch("controller.view_edit_controller.json_utils") + def test_page_save_changes_button_json_file_saved_and_empty_account_id_unchanged( + self, mock_json_utils: MagicMock, mock_file_utils: MagicMock) -> None: + self._mocked_view_edit_page.config_file_combobox.currentText.return_value = \ + TestViewEditController._expected_config_file_name + expected_json_dict: Dict[str, any] = { + self._expected_account_id_attribute_name: '' + } + mock_json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME = self._expected_account_id_attribute_name + mock_json_utils.validate_resources_according_to_json_schema.return_value = [] + mock_json_utils.convert_resources_to_json_dict.return_value = expected_json_dict + mock_file_utils.join_path.return_value = TestViewEditController._expected_config_file_full_path + mocked_call_args: call = self._mocked_view_edit_page.save_changes_button.clicked.connect.call_args[0] + + mocked_call_args[0]() # triggering save_changes_button connected function + assert expected_json_dict[mock_json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] == '' mock_json_utils.convert_resources_to_json_dict.assert_called_once() mock_json_utils.write_into_json_file.assert_called_once_with( TestViewEditController._expected_config_file_full_path, expected_json_dict) diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_json_utils.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_json_utils.py index 7eb92ff222..9fe99461ba 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_json_utils.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_json_utils.py @@ -103,6 +103,11 @@ class TestJsonUtils(TestCase): invalid_json_dict.pop(json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME) self.assertRaises(KeyError, json_utils.validate_json_dict_according_to_json_schema, invalid_json_dict) + def test_validate_json_dict_according_to_json_schema_raise_error_when_json_dict_has_empty_accountid(self) -> None: + valid_json_dict: Dict[str, any] = copy.deepcopy(TestJsonUtils._expected_json_dict) + valid_json_dict[json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] = '' + json_utils.validate_json_dict_according_to_json_schema(valid_json_dict) + def test_validate_json_dict_according_to_json_schema_pass_when_json_dict_has_template_accountid(self) -> None: valid_json_dict: Dict[str, any] = copy.deepcopy(TestJsonUtils._expected_json_dict) valid_json_dict[json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] = \ diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/json_utils.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/json_utils.py index 5b9377ada3..7926cca970 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/json_utils.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/json_utils.py @@ -28,7 +28,7 @@ _RESOURCE_MAPPING_JSON_FORMAT_VERSION: str = "1.0.0" RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME: str = "AccountId" RESOURCE_MAPPING_ACCOUNTID_TEMPLATE_VALUE: str = "EMPTY" -_RESOURCE_MAPPING_ACCOUNTID_PATTERN: str = f"^[0-9]{{12}}|{RESOURCE_MAPPING_ACCOUNTID_TEMPLATE_VALUE}$" +_RESOURCE_MAPPING_ACCOUNTID_PATTERN: str = f"^[0-9]{{12}}$|{RESOURCE_MAPPING_ACCOUNTID_TEMPLATE_VALUE}|^$" _RESOURCE_MAPPING_REGION_PATTERN: str = "^[a-z]{2}-[a-z]{4,9}-[0-9]{1}$" _RESOURCE_MAPPING_VERSION_PATTERN: str = "^[0-9]{1}.[0-9]{1}.[0-9]{1}$" From 2cd732de6cb55a5dd0f2441acfcef12e954bad58 Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Thu, 11 Nov 2021 16:43:49 -0800 Subject: [PATCH 59/97] Fixing RPC autogen so that RPCs without parameters compile (and function). Signed-off-by: Gene Walters --- .../AutoGen/AutoComponent_Source.jinja | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Source.jinja index e9bc21875b..d0b77159f8 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Source.jinja @@ -308,13 +308,21 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Prop {% endmacro %} {# +#} +{% macro PrintRpcParameters(printPrefix, paramDefines) %} +{% if paramDefines|count > 0 %} +{{ printPrefix }}{{ ', '.join(paramDefines) }} +{% endif %} +{% endmacro %} +{# + #} {% macro DefineRpcInvocation(Component, ClassName, Property, InvokeFrom, HandleOn) %} {% set paramNames = [] %} {% set paramTypes = [] %} {% set paramDefines = [] %} {{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }} -void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramDefines) }}) +void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ PrintRpcParameters('', paramDefines) }}) { constexpr Multiplayer::RpcIndex rpcId = static_cast({{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ UpperFirst(Property.attrib['Name']) }}); {% if Property.attrib['IsReliable']|booleanTrue %} @@ -358,7 +366,7 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(par {% set paramTypes = [] %} {% set paramDefines = [] %} {{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }} - ->Method("{{ UpperFirst(Property.attrib['Name']) }}", []({{ ClassName }}* self, {{ ', '.join(paramDefines) }}) { + ->Method("{{ UpperFirst(Property.attrib['Name']) }}", []({{ ClassName }}* self{{ PrintRpcParameters(', ', paramDefines) }}) { {% if (InvokeFrom == 'Server') %} self->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }}); {% elif (InvokeFrom == 'Authority') or (InvokeFrom == 'Autonomous') %} @@ -372,7 +380,7 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(par } {% endif %} }) - ->Method("{{ UpperFirst(Property.attrib['Name']) }}ByEntityId", [](AZ::EntityId id, {{ ', '.join(paramDefines) }}) { + ->Method("{{ UpperFirst(Property.attrib['Name']) }}ByEntityId", [](AZ::EntityId id{{ PrintRpcParameters(', ', paramDefines) }}) { AZ::Entity* entity = AZ::Interface::Get()->FindEntity(id); if (!entity) @@ -497,9 +505,9 @@ case {{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ Upp if (m_controller) { AZ_Assert(GetNetBindComponent()->GetNetEntityRole() == Multiplayer::NetEntityRole::Authority, "Entity proxy does not have authority"); - m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection, {{ ', '.join(rpcParamList) }}); + m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection{{ PrintRpcParameters(', ', rpcParamList) }}); {% if (Property.attrib['GenerateEventBindings']|booleanTrue == true) %} - m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event().Signal({{ ', '.join(rpcParamList) }}); + m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event().Signal({{ PrintRpcParameters('', rpcParamList) }}); {% endif %} } else // Note that this rpc is marked reliable, trigger the appropriate rpc event so it can be forwarded @@ -513,15 +521,15 @@ case {{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ Upp if (m_controller) { AZ_Assert(GetNetBindComponent()->GetNetEntityRole() == Multiplayer::NetEntityRole::Autonomous, "Entity proxy does not have autonomy"); - m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection, {{ ', '.join(rpcParamList) }}); + m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection{{ PrintRpcParameters(', ', rpcParamList) }}); {% if Property.attrib['GenerateEventBindings']|booleanTrue == true %} - m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event().Signal({{ ', '.join(rpcParamList) }}); + m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event().Signal({{ PrintRpcParameters('', rpcParamList) }}); {% endif %} } {% elif HandleOn == 'Client' %} - Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection, {{ ', '.join(rpcParamList) }}); + Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection{{ PrintRpcParameters(', ', rpcParamList) }}); {% if Property.attrib['GenerateEventBindings']|booleanTrue == true %} - m_{{ UpperFirst(Property.attrib['Name']) }}Event.Signal({{ ', '.join(rpcParamList) }}); + m_{{ UpperFirst(Property.attrib['Name']) }}Event.Signal({{ PrintRpcParameters('', rpcParamList) }}); {% endif %} {% endif %} } From 2fa3c134e04c89b61b1e47bf0b44bdc74b840866 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Thu, 11 Nov 2021 17:18:36 -0800 Subject: [PATCH 60/97] Terrain depends on SurfaceData and GradientSignal (#5476) Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- Gems/Terrain/Code/CMakeLists.txt | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Gems/Terrain/Code/CMakeLists.txt b/Gems/Terrain/Code/CMakeLists.txt index 4b2f32e172..d532284350 100644 --- a/Gems/Terrain/Code/CMakeLists.txt +++ b/Gems/Terrain/Code/CMakeLists.txt @@ -26,8 +26,6 @@ ly_add_target( Gem::GradientSignal Gem::SurfaceData Gem::LmbrCentral - - ) ly_add_target( @@ -49,14 +47,14 @@ ly_add_target( ) # the above module is for use in all client/server types -ly_create_alias(NAME Terrain.Servers NAMESPACE Gem TARGETS Gem::Terrain) -ly_create_alias(NAME Terrain.Clients NAMESPACE Gem TARGETS Gem::Terrain) +ly_create_alias(NAME Terrain.Servers NAMESPACE Gem TARGETS Gem::Terrain Gem::SurfaceData.Servers Gem::GradientSignal.Servers) +ly_create_alias(NAME Terrain.Clients NAMESPACE Gem TARGETS Gem::Terrain Gem::SurfaceData.Clients Gem::GradientSignal.Clients) # If we are on a host platform, we want to add the host tools targets like the Terrain.Editor target which # will also depend on Terrain.Static if(PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( - NAME Terrain.Editor MODULE + NAME Terrain.Editor GEM_MODULE NAMESPACE Gem AUTOMOC FILES_CMAKE @@ -78,8 +76,8 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) ) # the above module is for use in dev tool situations - ly_create_alias(NAME Terrain.Builders NAMESPACE Gem TARGETS Gem::Terrain.Editor) - ly_create_alias(NAME Terrain.Tools NAMESPACE Gem TARGETS Gem::Terrain.Editor) + ly_create_alias(NAME Terrain.Builders NAMESPACE Gem TARGETS Gem::Terrain.Editor Gem::SurfaceData.Builders Gem::GradientSignal.Builders) + ly_create_alias(NAME Terrain.Tools NAMESPACE Gem TARGETS Gem::Terrain.Editor Gem::SurfaceData.Tools Gem::GradientSignal.Tools) endif() ################################################################################ From 92c0e598d576a755389b5d681c9c9b3408f78d4e Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 8 Nov 2021 10:54:32 -0600 Subject: [PATCH 61/97] Starting to remove MTL asset references Signed-off-by: Guthrie Adams --- .../AzAssetBrowserRequestHandler.cpp | 35 ------------------- Code/Editor/Include/IEditorMaterialManager.h | 4 --- .../AssetBrowser/AssetBrowserComponent.cpp | 5 --- .../PropertyEditor/EntityPropertyEditor.cpp | 19 +--------- .../AssetBuilderSDK/AssetBuilderSDK.cpp | 6 ---- Gems/LmbrCentral/Code/Source/LmbrCentral.cpp | 2 -- 6 files changed, 1 insertion(+), 70 deletions(-) diff --git a/Code/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp b/Code/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp index 1c2be16a3d..6fc10e379a 100644 --- a/Code/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp +++ b/Code/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp @@ -199,41 +199,6 @@ namespace AzAssetBrowserRequestHandlerPrivate } } } - - // Helper utility - determines if the thing being dragged is a FBX from the scene import pipeline - // This is important to differentiate. - // when someone drags a MTL file directly into the viewport, even from a FBX, we want to spawn it as a decal - // but when someone drags a FBX that contains MTL files, we want only to spawn the meshes. - // so we have to specifically differentiate here between the mimeData type that contains the source as the root - // (dragging the fbx file itself) - // and one which contains the actual product at its root. - - bool IsDragOfFBX(const QMimeData* mimeData) - { - AZStd::vector entries; - if (!AssetBrowserEntry::FromMimeData(mimeData, entries)) - { - // if mimedata does not even contain entries, no point in proceeding. - return false; - } - - for (auto entry : entries) - { - if (entry->GetEntryType() != AssetBrowserEntry::AssetEntryType::Source) - { - continue; - } - // this is a source file. Is it the filetype we're looking for? - if (SourceAssetBrowserEntry* source = azrtti_cast(entry)) - { - if (AzFramework::StringFunc::Equal(source->GetExtension().c_str(), ".fbx", false)) - { - return true; - } - } - } - return false; - } } AzAssetBrowserRequestHandler::AzAssetBrowserRequestHandler() diff --git a/Code/Editor/Include/IEditorMaterialManager.h b/Code/Editor/Include/IEditorMaterialManager.h index d76ec32829..6f71c5ddd1 100644 --- a/Code/Editor/Include/IEditorMaterialManager.h +++ b/Code/Editor/Include/IEditorMaterialManager.h @@ -9,10 +9,6 @@ #define CRYINCLUDE_EDITOR_MATERIAL_IEDITORMATERIALMANAGER_H #pragma once -#define MATERIAL_FILE_EXT ".mtl" -#define DCC_MATERIAL_FILE_EXT ".dccmtl" -#define MATERIALS_PATH "materials/" - #include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserComponent.cpp index 7da6f794d6..172bd3a29c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserComponent.cpp @@ -234,11 +234,6 @@ namespace AzToolsFramework return SourceFileDetails("Icons/AssetBrowser/Lua_16.svg"); } - if (AzFramework::StringFunc::Equal(extension.c_str(), ".mtl")) - { - return SourceFileDetails("Icons/AssetBrowser/Material_16.svg"); - } - if (AzFramework::StringFunc::Equal(extension.c_str(), AzToolsFramework::SliceUtilities::GetSliceFileExtension().c_str())) { return SourceFileDetails("Icons/AssetBrowser/Slice_16.svg"); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp index 29bc106eed..9ecbdf5ffc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp @@ -4705,13 +4705,6 @@ namespace AzToolsFramework { if (mimeData->hasFormat(AssetBrowser::AssetBrowserEntry::GetMimeType())) { - // extra special case: MTLs from FBX drags are ignored. are we dragging a FBX file? - bool isDraggingFBXFile = false; - AssetBrowser::AssetBrowserEntry::ForEachEntryInMimeData(mimeData, [&](const AssetBrowser::SourceAssetBrowserEntry* source) - { - isDraggingFBXFile = isDraggingFBXFile || AzFramework::StringFunc::Equal(source->GetExtension().c_str(), ".fbx", false); - }); - // the usual case - we only allow asset browser drops of assets that have actually been associated with a kind of component. AssetBrowser::AssetBrowserEntry::ForEachEntryInMimeData(mimeData, [&](const AssetBrowser::ProductAssetBrowserEntry* product) { @@ -4723,17 +4716,7 @@ namespace AzToolsFramework if (canCreateComponent && !componentTypeId.IsNull()) { - // we have a component type that handles this asset. - // but we disallow it if its a MTL file from a FBX and the FBX itself is being dragged. Its still allowed - // to drag the actual MTL. - EBusFindAssetTypeByName materialAssetTypeResult("Material"); - AZ::AssetTypeInfoBus::BroadcastResult(materialAssetTypeResult, &AZ::AssetTypeInfo::GetAssetType); - AZ::Data::AssetType materialAssetType = materialAssetTypeResult.GetAssetType(); - - if ((!isDraggingFBXFile) || (product->GetAssetType() != materialAssetType)) - { - callbackFunction(product); - } + callbackFunction(product); } }); } diff --git a/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp b/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp index a02eef8b75..f9b5d6aef7 100644 --- a/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp +++ b/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp @@ -690,7 +690,6 @@ namespace AssetBuilderSDK static const char* textureExtensions = ".dds"; static const char* staticMeshExtensions = ".cgf"; static const char* skinnedMeshExtensions = ".skin"; - static const char* materialExtensions = ".mtl"; // MIPS static const int c_MaxMipsCount = 11; // 11 is for 8k textures non-compressed. When not compressed it is using one file per mip. @@ -805,11 +804,6 @@ namespace AssetBuilderSDK return textureAssetType; } - if (AzFramework::StringFunc::Find(materialExtensions, extension.c_str()) != AZStd::string::npos) - { - return materialAssetType; - } - if (AzFramework::StringFunc::Find(staticMeshExtensions, extension.c_str()) != AZStd::string::npos) { return meshAssetType; diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp index 027d19fdef..ab187a6eed 100644 --- a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp +++ b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp @@ -364,8 +364,6 @@ namespace LmbrCentral assetCatalog->AddExtension("dds"); assetCatalog->AddExtension("caf"); assetCatalog->AddExtension("xml"); - assetCatalog->AddExtension("mtl"); - assetCatalog->AddExtension("dccmtl"); assetCatalog->AddExtension("sprite"); assetCatalog->AddExtension("cax"); } From 44f2cbae47f57c259f87f457f310d894b46a9aa6 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 11 Nov 2021 12:58:20 -0600 Subject: [PATCH 62/97] Removing material builder and related tests Signed-off-by: Guthrie Adams --- .../MaterialBuilderComponent.cpp | 612 ------------------ .../MaterialBuilderComponent.h | 65 -- .../Code/Source/LmbrCentralEditor.cpp | 2 - .../Tests/Builders/MaterialBuilderTests.cpp | 261 -------- .../Code/lmbrcentral_editor_files.cmake | 2 - .../Code/lmbrcentral_editor_tests_files.cmake | 1 - 6 files changed, 943 deletions(-) delete mode 100644 Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp delete mode 100644 Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.h delete mode 100644 Gems/LmbrCentral/Code/Tests/Builders/MaterialBuilderTests.cpp diff --git a/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp b/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp deleted file mode 100644 index 48973b2779..0000000000 --- a/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include "MaterialBuilderComponent.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace MaterialBuilder -{ - [[maybe_unused]] const char s_materialBuilder[] = "MaterialBuilder"; - - namespace Internal - { - const char g_nodeNameMaterial[] = "Material"; - const char g_nodeNameSubmaterial[] = "SubMaterials"; - const char g_nodeNameTexture[] = "Texture"; - const char g_nodeNameTextures[] = "Textures"; - const char g_attributeFileName[] = "File"; - - const int g_numSourceImageFormats = 9; - const char* g_sourceImageFormats[g_numSourceImageFormats] = { ".tif", ".tiff", ".bmp", ".gif", ".jpg", ".jpeg", ".tga", ".png", ".dds" }; - bool IsSupportedImageExtension(const AZStd::string& extension) - { - for (const char* format : g_sourceImageFormats) - { - if (extension == format) - { - return true; - } - } - return false; - } - - // Cleans up legacy pathing from older materials - const char* CleanLegacyPathingFromTexturePath(const char* texturePath) - { - // Copied from MaterialHelpers::SetTexturesFromXml, line 459 - // legacy. Some textures used to be referenced using "engine\\" or "engine/" - this is no longer valid - if ( - (strlen(texturePath) > 7) && - (azstrnicmp(texturePath, "engine", 6) == 0) && - ((texturePath[6] == '\\') || (texturePath[6] == '/')) - ) - { - texturePath = texturePath + 7; - } - - // legacy: Files were saved into a mtl with many leading forward or back slashes, we eat them all here. We want it to start with a relative path. - const char* actualFileName = texturePath; - while ((actualFileName[0]) && ((actualFileName[0] == '\\') || (actualFileName[0] == '/'))) - { - ++actualFileName; - } - return actualFileName; - } - - // Parses the material XML for all texture paths - AZ::Outcome GetTexturePathsFromMaterial(AZ::rapidxml::xml_node* materialNode, AZStd::vector& paths) - { - AZ::Outcome resultOutcome = AZ::Failure(AZStd::string("")); - AZStd::string success_with_warning_message; - - // check if this material has a set of textures defined, and if so, grab all the paths from the textures - AZ::rapidxml::xml_node* texturesNode = materialNode->first_node(g_nodeNameTextures); - if (texturesNode) - { - AZ::rapidxml::xml_node* textureNode = texturesNode->first_node(g_nodeNameTexture); - // it is possible for an empty node to exist for things like collision materials, so check - // to make sure that there is at least one child node before starting to iterate. - if (textureNode) - { - do - { - AZ::rapidxml::xml_attribute* fileAttribute = textureNode->first_attribute(g_attributeFileName); - if (!fileAttribute) - { - success_with_warning_message = "Texture node exists but does not have a file attribute defined"; - } - else - { - const char* rawTexturePath = fileAttribute->value(); - // do an initial clean-up of the path taken from the file, similar to MaterialHelpers::SetTexturesFromXml - AZStd::string texturePath = CleanLegacyPathingFromTexturePath(rawTexturePath); - paths.emplace_back(AZStd::move(texturePath)); - } - - textureNode = textureNode->next_sibling(g_nodeNameTexture); - } while (textureNode); - } - } - - // check to see if this material has sub materials defined. If so, recurse into this function for each sub material - AZ::rapidxml::xml_node* subMaterialsNode = materialNode->first_node(g_nodeNameSubmaterial); - if (subMaterialsNode) - { - AZ::rapidxml::xml_node* subMaterialNode = subMaterialsNode->first_node(g_nodeNameMaterial); - if (subMaterialNode == nullptr) - { - // this is a malformed material as there is no material node child in the SubMaterials node, so error out - return AZ::Failure(AZStd::string("SubMaterials node exists but does not have any child Material nodes.")); - } - - do - { - // grab the texture paths from the submaterial, or error out if necessary - AZ::Outcome subMaterialTexturePathsResult = GetTexturePathsFromMaterial(subMaterialNode, paths); - if (!subMaterialTexturePathsResult.IsSuccess()) - { - return subMaterialTexturePathsResult; - } - else if (!subMaterialTexturePathsResult.GetValue().empty()) - { - success_with_warning_message = subMaterialTexturePathsResult.GetValue(); - } - - subMaterialNode = subMaterialNode->next_sibling(g_nodeNameMaterial); - } while (subMaterialNode); - } - - if (texturesNode == nullptr && subMaterialsNode == nullptr) - { - return AZ::Failure(AZStd::string("Failed to find a Textures node or SubMaterials node in this material. At least one of these must exist to be able to gather texture dependencies.")); - } - - if (!success_with_warning_message.empty()) - { - return AZ::Success(success_with_warning_message); - } - return AZ::Success(AZStd::string()); - } - - // find a sequence of digits with a string starting from lastDigitIndex, and try to parse that sequence to and int - // and store it in outAnimIndex. - bool ParseFilePathForCompleteNumber(const AZStd::string& filePath, int& lastDigitIndex, int& outAnimIndex) - { - int firstAnimIndexDigit = lastDigitIndex; - while (isdigit(static_cast(filePath[lastDigitIndex]))) - { - ++lastDigitIndex; - } - if (!AzFramework::StringFunc::LooksLikeInt(filePath.substr(firstAnimIndexDigit, lastDigitIndex - firstAnimIndexDigit).c_str(), &outAnimIndex)) - { - return false; - } - return true; - } - - // Parse the texture path for a texture animation to determine the actual names of the textures to resolve that - // make up the entire sequence. - AZ::Outcome GetAllTexturesInTextureSequence(const AZStd::string& path, AZStd::vector& texturesInSequence) - { - // Taken from CShaderMan::mfReadTexSequence - // All comments next to variable declarations in this function are the original variable names in - // CShaderMan::mfReadTexSequence, to help keep track of how these variables relate to the original function - AZStd::string prefix; - AZStd::string postfix; - - AZStd::string filePath = path; // name - AZStd::string extension; // ext - AzFramework::StringFunc::Path::GetExtension(filePath.c_str(), extension); - AzFramework::StringFunc::Path::StripExtension(filePath); - - // unsure if it is actually possible to enter here or the original version with '$' as the indicator - // for texture sequences, but they check for both just in case, so this will match the behavior. - char separator = '#'; // chSep - int firstSeparatorIndex = static_cast(filePath.find(separator)); - if (firstSeparatorIndex == AZStd::string::npos) - { - firstSeparatorIndex = static_cast(filePath.find('$')); - if (firstSeparatorIndex == AZStd::string::npos) - { - return AZ::Failure(AZStd::string("Failed to find separator '#' or '$' in texture path.")); - } - separator = '$'; - } - - // we don't actually care about getting the speed of the animation, so just remove everything from the - // end of the string starting with the last open parenthesis - size_t speedStartIndex = filePath.find_last_of('('); - if (speedStartIndex != AZStd::string::npos) - { - AzFramework::StringFunc::LKeep(filePath, speedStartIndex); - AzFramework::StringFunc::Append(filePath, '\0'); - } - - // try to find where the digits start after the separator (there can be any number of separators - // between the texture name prefix and where the digit range starts) - int firstAnimIndexDigit = -1; // m - int numSeparators = 0; // j - for (int stringIndex = firstSeparatorIndex; stringIndex < filePath.length(); ++stringIndex) - { - if (filePath[stringIndex] == separator) - { - ++numSeparators; - if (firstSeparatorIndex == -1) - { - firstSeparatorIndex = stringIndex; - } - } - else if (firstSeparatorIndex > 0 && firstAnimIndexDigit < 0) - { - firstAnimIndexDigit = stringIndex; - break; - } - } - if (numSeparators == 0) - { - return AZ::Failure(AZStd::string("Failed to find separator '#' or '$' in texture path.")); - } - - // store off everything before the separator - prefix = AZStd::move(filePath.substr(0, firstSeparatorIndex)); - - int startAnimIndex = 0; // startn - int endAnimIndex = 0; // endn - // we only found the separator, but no indexes, so just assume its 0 - 999 - if (firstAnimIndexDigit < 0) - { - startAnimIndex = 0; - endAnimIndex = 999; - } - else - { - // find the length of the first index, then parse that to an int - int lastDigitIndex = firstAnimIndexDigit; - if (!ParseFilePathForCompleteNumber(filePath, lastDigitIndex, startAnimIndex)) - { - return AZ::Failure(AZStd::string("Failed to determine first index of the sequence after the separators in texture path.")); - } - - // reset to the start of the next index - ++lastDigitIndex; - - // find the length of the end index, then parse that to an int - if (!ParseFilePathForCompleteNumber(filePath, lastDigitIndex, endAnimIndex)) - { - return AZ::Failure(AZStd::string("Failed to determine last index of the sequence after the first index of the sequence in texture path.")); - } - - // save off the rest of the string - postfix = AZStd::move(filePath.substr(lastDigitIndex)); - } - - int numTextures = endAnimIndex - startAnimIndex + 1; - const char* textureNameFormat = "%s%.*d%s%s"; // prefix, num separators (number of digits), sequence index, postfix, extension) - for (int sequenceIndex = 0; sequenceIndex < numTextures; ++sequenceIndex) - { - texturesInSequence.emplace_back(AZStd::move(AZStd::string::format(textureNameFormat, prefix.c_str(), numSeparators, startAnimIndex + sequenceIndex, postfix.c_str(), extension.c_str()))); - } - - return AZ::Success(); - } - - // Determine which product path to use based on the path stored in the texture, and make it relative to - // the cache. - bool ResolveMaterialTexturePath(const AZStd::string& path, AZStd::string& outPath) - { - AZStd::string aliasedPath = path; - - //if its a source image format try to load the dds - AZStd::string extension; - bool hasExtension = AzFramework::StringFunc::Path::GetExtension(path.c_str(), extension); - - // Replace all supported extensions with DDS if it has an extension. If the extension exists but is not supported, fail out. - if (hasExtension && IsSupportedImageExtension(extension)) - { - AzFramework::StringFunc::Path::ReplaceExtension(aliasedPath, ".dds"); - } - else if (hasExtension) - { - AZ_Warning(s_materialBuilder, false, "Failed to resolve texture path %s as the path is not to a supported texture format. Please make sure that textures in materials are formats supported by Open 3D Engine.", aliasedPath.c_str()); - return false; - } - - AZStd::to_lower(aliasedPath.begin(), aliasedPath.end()); - AzFramework::StringFunc::Path::Normalize(aliasedPath); - - AZStd::string currentFolderSpecifier = AZStd::string::format(".%c", AZ_CORRECT_FILESYSTEM_SEPARATOR); - if (AzFramework::StringFunc::StartsWith(aliasedPath, currentFolderSpecifier)) - { - AzFramework::StringFunc::Strip(aliasedPath, currentFolderSpecifier.c_str(), false, true); - } - - AZStd::string resolvedPath; - char fullPathBuffer[AZ_MAX_PATH_LEN] = {}; - // if there is an alias already at the front of the path, resolve it, and try to make it relative to the - // cache (@products@). If it can't, then error out. - // This case handles the possibility of aliases existing in texture paths in materials that is still supported - // by the legacy loading code, however it is not currently used, so the else path is always taken. - if (aliasedPath[0] == '@') - { - if (!AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(aliasedPath.c_str(), fullPathBuffer, AZ_MAX_PATH_LEN)) - { - AZ_Warning(s_materialBuilder, false, "Failed to resolve the alias in texture path %s. Please make sure all aliases are registered with the engine.", aliasedPath.c_str()); - return false; - } - resolvedPath = fullPathBuffer; - AzFramework::StringFunc::Path::Normalize(resolvedPath); - if (!AzFramework::StringFunc::Replace(resolvedPath, AZ::IO::FileIOBase::GetDirectInstance()->GetAlias("@products@"), "")) - { - AZ_Warning(s_materialBuilder, false, "Failed to resolve aliased texture path %s to be relative to the asset cache. Please make sure this alias resolves to a path within the asset cache.", aliasedPath.c_str()); - return false; - } - } - else - { - resolvedPath = AZStd::move(aliasedPath); - } - - // AP deferred path resolution requires UNIX separators and no leading separators, so clean up and convert here - if (AzFramework::StringFunc::StartsWith(resolvedPath, AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING)) - { - AzFramework::StringFunc::Strip(resolvedPath, AZ_CORRECT_FILESYSTEM_SEPARATOR, false, true); - } - AzFramework::StringFunc::Replace(resolvedPath, AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING, "/"); - - outPath = AZStd::move(resolvedPath); - return true; - } - - } - - BuilderPluginComponent::BuilderPluginComponent() - { - } - - BuilderPluginComponent::~BuilderPluginComponent() - { - } - - void BuilderPluginComponent::Init() - { - } - - void BuilderPluginComponent::Activate() - { - // Register material builder - AssetBuilderSDK::AssetBuilderDesc builderDescriptor; - builderDescriptor.m_name = "MaterialBuilderWorker"; - builderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.mtl", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); - builderDescriptor.m_busId = MaterialBuilderWorker::GetUUID(); - builderDescriptor.m_version = 5; - builderDescriptor.m_createJobFunction = AZStd::bind(&MaterialBuilderWorker::CreateJobs, &m_materialBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); - builderDescriptor.m_processJobFunction = AZStd::bind(&MaterialBuilderWorker::ProcessJob, &m_materialBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); - - // (optimization) this builder does not emit source dependencies: - builderDescriptor.m_flags |= AssetBuilderSDK::AssetBuilderDesc::BF_EmitsNoDependencies; - - m_materialBuilder.BusConnect(builderDescriptor.m_busId); - - EBUS_EVENT(AssetBuilderSDK::AssetBuilderBus, RegisterBuilderInformation, builderDescriptor); - } - - void BuilderPluginComponent::Deactivate() - { - m_materialBuilder.BusDisconnect(); - } - - void BuilderPluginComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context) - { - if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector({ AssetBuilderSDK::ComponentTags::AssetBuilder })); - } - } - - MaterialBuilderWorker::MaterialBuilderWorker() - { - } - MaterialBuilderWorker::~MaterialBuilderWorker() - { - } - - void MaterialBuilderWorker::ShutDown() - { - // This will be called on a different thread than the process job thread - m_isShuttingDown = true; - } - - // This happens early on in the file scanning pass. - // This function should always create the same jobs and not do any checking whether the job is up to date. - void MaterialBuilderWorker::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) - { - if (m_isShuttingDown) - { - response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown; - return; - } - - for (const AssetBuilderSDK::PlatformInfo& info : request.m_enabledPlatforms) - { - AssetBuilderSDK::JobDescriptor descriptor; - descriptor.m_jobKey = "Material Builder Job"; - descriptor.SetPlatformIdentifier(info.m_identifier.c_str()); - descriptor.m_priority = 8; // meshes are more important (at 10) but mats are still pretty important. - response.m_createJobOutputs.push_back(descriptor); - } - - response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; - } - - // The request will contain the CreateJobResponse you constructed earlier, including any keys and - // values you placed into the hash table - void MaterialBuilderWorker::ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response) - { - AZ_TracePrintf(AssetBuilderSDK::InfoWindow, "Starting Job.\n"); - AZStd::string fileName; - AzFramework::StringFunc::Path::GetFullFileName(request.m_fullPath.c_str(), fileName); - AZStd::string destPath; - - // Do all work inside the tempDirPath. - AzFramework::StringFunc::Path::ConstructFull(request.m_tempDirPath.c_str(), fileName.c_str(), destPath, true); - - AZ::IO::LocalFileIO fileIO; - if (!m_isShuttingDown && fileIO.Copy(request.m_fullPath.c_str(), destPath.c_str()) == AZ::IO::ResultCode::Success) - { - // Push assets back into the response's product list - // Assets you created in your temp path can be specified using paths relative to the temp path - // since that is assumed where you're writing stuff. - AZStd::string relPath = destPath; - AssetBuilderSDK::ProductPathDependencySet dependencyPaths; - response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - AssetBuilderSDK::JobProduct jobProduct(fileName); - - bool dependencyResult = GatherProductDependencies(request.m_fullPath, dependencyPaths); - if (dependencyResult) - { - jobProduct.m_pathDependencies = AZStd::move(dependencyPaths); - jobProduct.m_dependenciesHandled = true; // We've output the dependencies immediately above so it's OK to tell the AP we've handled dependencies - } - else - { - AZ_Error(s_materialBuilder, false, "Dependency gathering for %s failed.", request.m_fullPath.c_str()); - } - response.m_outputProducts.push_back(jobProduct); - } - else - { - if (m_isShuttingDown) - { - AZ_TracePrintf(AssetBuilderSDK::ErrorWindow, "Cancelled job %s because shutdown was requested.\n", request.m_fullPath.c_str()); - response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Cancelled; - } - else - { - AZ_TracePrintf(AssetBuilderSDK::ErrorWindow, "Error during processing job %s.\n", request.m_fullPath.c_str()); - response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed; - } - } - } - - bool MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial(const AZStd::string& path, AZStd::vector& resolvedPaths) - { - if (!AZ::IO::SystemFile::Exists(path.c_str())) - { - AZ_Error(s_materialBuilder, false, "Failed to find material at path %s. Please make sure this material exists on disk.", path.c_str()); - return false; - } - - uint64_t fileSize = AZ::IO::SystemFile::Length(path.c_str()); - if (fileSize == 0) - { - AZ_Error(s_materialBuilder, false, "Material at path %s is an empty file. Please make sure this material was properly saved to disk.", path.c_str()); - return false; - } - - AZStd::vector buffer(fileSize + 1); - buffer[fileSize] = 0; - if (!AZ::IO::SystemFile::Read(path.c_str(), buffer.data())) - { - AZ_Error(s_materialBuilder, false, "Failed to read material at path %s. Please make sure the file is not open or being edited by another program.", path.c_str()); - return false; - } - - AZ::rapidxml::xml_document* xmlDoc = azcreate(AZ::rapidxml::xml_document, (), AZ::SystemAllocator, "Mtl builder temp XML Reader"); - if (!xmlDoc->parse(buffer.data())) - { - azdestroy(xmlDoc, AZ::SystemAllocator, AZ::rapidxml::xml_document); - AZ_Error(s_materialBuilder, false, "Failed to parse material at path %s into XML. Please make sure that the material was properly saved to disk.", path.c_str()); - return false; - } - - // if the first node in this file isn't a material, this must not actually be a material so it can't have deps - AZ::rapidxml::xml_node* rootNode = xmlDoc->first_node(Internal::g_nodeNameMaterial); - if (!rootNode) - { - azdestroy(xmlDoc, AZ::SystemAllocator, AZ::rapidxml::xml_document); - AZ_Error(s_materialBuilder, false, "Failed to find root material node for material at path %s. Please make sure that the material was properly saved to disk.", path.c_str()); - return false; - } - - AZStd::vector texturePaths; - // gather all textures in the material file - AZ::Outcome texturePathsResult = Internal::GetTexturePathsFromMaterial(rootNode, texturePaths); - if (!texturePathsResult.IsSuccess()) - { - azdestroy(xmlDoc, AZ::SystemAllocator, AZ::rapidxml::xml_document); - AZ_Error(s_materialBuilder, false, "Failed to gather dependencies for %s as the material file is malformed. %s", path.c_str(), texturePathsResult.GetError().c_str()); - return false; - } - else if (!texturePathsResult.GetValue().empty()) - { - AZ_Warning(s_materialBuilder, false, "Some nodes in material %s could not be read as the material is malformed. %s. Some dependencies might not be reported correctly. Please make sure that the material was properly saved to disk.", path.c_str(), texturePathsResult.GetValue().c_str()); - } - azdestroy(xmlDoc, AZ::SystemAllocator, AZ::rapidxml::xml_document); - - // fail this if there are absolute paths. - for (const AZStd::string& texPath : texturePaths) - { - if (AZ::IO::PathView(texPath).IsAbsolute()) - { - AZ_Warning(s_materialBuilder, false, "Skipping resolving of texture path %s in material %s as the texture path is an absolute path. Please update the texture path to be relative to the asset cache.", texPath.c_str(), path.c_str()); - texturePaths.erase(AZStd::find(texturePaths.begin(), texturePaths.end(), texPath)); - } - } - - // for each path in the array, split any texture animation entry up into the individual files and add each to the list. - for (const AZStd::string& texPath : texturePaths) - { - if (texPath.find('#') != AZStd::string::npos) - { - AZStd::vector actualTexturePaths; - AZ::Outcome parseTextureSequenceResult = Internal::GetAllTexturesInTextureSequence(texPath, actualTexturePaths); - if (parseTextureSequenceResult.IsSuccess()) - { - texturePaths.erase(AZStd::find(texturePaths.begin(), texturePaths.end(), texPath)); - texturePaths.insert(texturePaths.end(), actualTexturePaths.begin(), actualTexturePaths.end()); - } - else - { - texturePaths.erase(AZStd::find(texturePaths.begin(), texturePaths.end(), texPath)); - AZ_Warning(s_materialBuilder, false, "Failed to parse texture sequence %s when trying to gather dependencies for %s. %s Please make sure the texture sequence path is formatted correctly. Registering dependencies for the texture sequence will be skipped.", texPath.c_str(), path.c_str(), parseTextureSequenceResult.GetError().c_str()); - } - } - } - - // for each texture in the file - for (const AZStd::string& texPath : texturePaths) - { - // if the texture path starts with a '$' then it is a special runtime defined texture, so it it doesn't have - // an actual asset on disk to depend on. If the texture path doesn't have an extension, then it is a texture - // that is determined at runtime (such as 'nearest_cubemap'), so also ignore those, as other things pull in - // those dependencies. - if (AzFramework::StringFunc::StartsWith(texPath, "$") || !AzFramework::StringFunc::Path::HasExtension(texPath.c_str())) - { - continue; - } - - // resolve the path in the file. - AZStd::string resolvedPath; - if (!Internal::ResolveMaterialTexturePath(texPath, resolvedPath)) - { - AZ_Warning(s_materialBuilder, false, "Failed to resolve texture path %s to a product path when gathering dependencies for %s. Registering dependencies on this texture path will be skipped.", texPath.c_str(), path.c_str()); - continue; - } - - resolvedPaths.emplace_back(AZStd::move(resolvedPath)); - } - - return true; - } - - bool MaterialBuilderWorker::PopulateProductDependencyList(AZStd::vector& resolvedPaths, AssetBuilderSDK::ProductPathDependencySet& dependencies) - { - for (const AZStd::string& texturePath : resolvedPaths) - { - if (texturePath.empty()) - { - AZ_Warning(s_materialBuilder, false, "Resolved path is empty.\n"); - return false; - } - - dependencies.emplace(texturePath, AssetBuilderSDK::ProductPathDependencyType::ProductFile); - } - return true; - } - - bool MaterialBuilderWorker::GatherProductDependencies(const AZStd::string& path, AssetBuilderSDK::ProductPathDependencySet& dependencies) - { - AZStd::vector resolvedTexturePaths; - if (!GetResolvedTexturePathsFromMaterial(path, resolvedTexturePaths)) - { - return false; - } - - if (!PopulateProductDependencyList(resolvedTexturePaths, dependencies)) - { - AZ_Warning(s_materialBuilder, false, "Failed to populate dependency list for material %s with possible variants for textures.", path.c_str()); - } - - return true; - } - - AZ::Uuid MaterialBuilderWorker::GetUUID() - { - return AZ::Uuid::CreateString("{258D34AC-12F8-4196-B535-3206D8E7287B}"); - } -} diff --git a/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.h b/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.h deleted file mode 100644 index a7813cf0bd..0000000000 --- a/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include -#include -#include - -namespace MaterialBuilder -{ - //! Material builder is responsible for building material files - class MaterialBuilderWorker - : public AssetBuilderSDK::AssetBuilderCommandBus::Handler - { - public: - MaterialBuilderWorker(); - ~MaterialBuilderWorker(); - - //! Asset Builder Callback Functions - void CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response); - void ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response); - - //!AssetBuilderSDK::AssetBuilderCommandBus interface - void ShutDown() override; - - //! Returns the UUID for this builder - static AZ::Uuid GetUUID(); - - bool GetResolvedTexturePathsFromMaterial(const AZStd::string& path, AZStd::vector& resolvedPaths); - bool PopulateProductDependencyList(AZStd::vector& resolvedPaths, AssetBuilderSDK::ProductPathDependencySet& dependencies); - - private: - bool GatherProductDependencies(const AZStd::string& path, AssetBuilderSDK::ProductPathDependencySet& dependencies); - - bool m_isShuttingDown = false; - }; - - class BuilderPluginComponent - : public AZ::Component - { - public: - AZ_COMPONENT(BuilderPluginComponent, "{4D1A4B0C-54CE-4397-B8AE-ADD08898C2CD}") - static void Reflect(AZ::ReflectContext* context); - - BuilderPluginComponent(); - - ////////////////////////////////////////////////////////////////////////// - // AZ::Component - virtual void Init(); // create objects, allocate memory and initialize yourself without reaching out to the outside world - virtual void Activate(); // reach out to the outside world and connect up to what you need to, register things, etc. - virtual void Deactivate(); // unregister things, disconnect from the outside world - ////////////////////////////////////////////////////////////////////////// - - virtual ~BuilderPluginComponent(); // free memory an uninitialize yourself. - - private: - MaterialBuilderWorker m_materialBuilder; - }; -} diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp index 511bf98582..61b8c8f73d 100644 --- a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp +++ b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include "Builders/CopyDependencyBuilder/CopyDependencyBuilderComponent.h" @@ -84,7 +83,6 @@ namespace LmbrCentral CopyDependencyBuilder::CopyDependencyBuilderComponent::CreateDescriptor(), DependencyBuilder::DependencyBuilderComponent::CreateDescriptor(), LevelBuilder::LevelBuilderComponent::CreateDescriptor(), - MaterialBuilder::BuilderPluginComponent::CreateDescriptor(), SliceBuilder::BuilderPluginComponent::CreateDescriptor(), TranslationBuilder::BuilderPluginComponent::CreateDescriptor(), LuaBuilder::BuilderPluginComponent::CreateDescriptor(), diff --git a/Gems/LmbrCentral/Code/Tests/Builders/MaterialBuilderTests.cpp b/Gems/LmbrCentral/Code/Tests/Builders/MaterialBuilderTests.cpp deleted file mode 100644 index 3786ef7565..0000000000 --- a/Gems/LmbrCentral/Code/Tests/Builders/MaterialBuilderTests.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace UnitTest -{ - using namespace MaterialBuilder; - using namespace AZ; - - class MaterialBuilderTests - : public UnitTest::AllocatorsTestFixture - , public UnitTest::TraceBusRedirector - { - protected: - void SetUp() override - { - UnitTest::AllocatorsTestFixture::SetUp(); - - m_app.reset(aznew AzToolsFramework::ToolsApplication); - m_app->Start(AZ::ComponentApplication::Descriptor()); - // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is - // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash - // in the unit tests. - AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - - const AZStd::string engineRoot = AZ::Test::GetEngineRootPath(); - AZ::IO::FileIOBase::GetInstance()->SetAlias("@engroot@", engineRoot.c_str()); - - AZ::IO::Path assetRoot(AZ::Utils::GetProjectPath()); - assetRoot /= "Cache"; - AZ::IO::FileIOBase::GetInstance()->SetAlias("@products@", assetRoot.c_str()); - } - - void TearDown() override - { - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - m_app->Stop(); - m_app.reset(); - - UnitTest::AllocatorsTestFixture::TearDown(); - } - - AZStd::string GetTestFileAliasedPath(AZStd::string_view fileName) - { - constexpr char testFileFolder[] = "@engroot@/Gems/LmbrCentral/Code/Tests/Materials/"; - return AZStd::string::format("%s%.*s", testFileFolder, aznumeric_cast(fileName.size()), fileName.data()); - } - - AZStd::string GetTestFileFullPath(AZStd::string_view fileName) - { - AZStd::string aliasedPath = GetTestFileAliasedPath(fileName); - char resolvedPath[AZ_MAX_PATH_LEN]; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(aliasedPath.c_str(), resolvedPath, AZ_MAX_PATH_LEN); - return AZStd::string(resolvedPath); - } - - void TestFailureCase(AZStd::string_view fileName, [[maybe_unused]] int expectedErrorCount) - { - MaterialBuilderWorker worker; - AZStd::vector resolvedPaths; - - AZStd::string absoluteMatPath = GetTestFileFullPath(fileName); - - AZ_TEST_START_ASSERTTEST; - ASSERT_FALSE(worker.GetResolvedTexturePathsFromMaterial(absoluteMatPath, resolvedPaths)); - AZ_TEST_STOP_ASSERTTEST(expectedErrorCount * 2); // The assert tests double count AZ errors, so just multiply expected count by 2 - ASSERT_EQ(resolvedPaths.size(), 0); - } - - void TestSuccessCase(AZStd::string_view fileName, AZStd::vector& expectedTextures) - { - MaterialBuilderWorker worker; - AZStd::vector resolvedPaths; - size_t texturesInMaterialFile = expectedTextures.size(); - - AZStd::string absoluteMatPath = GetTestFileFullPath(fileName); - ASSERT_TRUE(worker.GetResolvedTexturePathsFromMaterial(absoluteMatPath, resolvedPaths)); - ASSERT_EQ(resolvedPaths.size(), texturesInMaterialFile); - if (texturesInMaterialFile > 0) - { - ASSERT_THAT(resolvedPaths, testing::ElementsAreArray(expectedTextures)); - - AssetBuilderSDK::ProductPathDependencySet dependencies; - ASSERT_TRUE(worker.PopulateProductDependencyList(resolvedPaths, dependencies)); - ASSERT_EQ(dependencies.size(), texturesInMaterialFile); - } - } - - void TestSuccessCase(AZStd::string_view fileName, const char* expectedTexture) - { - AZStd::vector expectedTextures; - expectedTextures.push_back(expectedTexture); - TestSuccessCase(fileName, expectedTextures); - } - - void TestSuccessCaseNoDependencies(AZStd::string_view fileName) - { - AZStd::vector expectedTextures; - TestSuccessCase(fileName, expectedTextures); - } - - AZStd::unique_ptr m_app; - }; - - TEST_F(MaterialBuilderTests, MaterialBuilder_EmptyFile_ExpectFailure) - { - // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial, when checking for the size of the file. - TestFailureCase("test_mat1.mtl", 1); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_NoChildren_ExpectFailure) - { - // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial after calling - // Internal::GetTexturePathsFromMaterial, which should return an AZ::Failure when both a Textures node and a - // SubMaterials node are not found. No other AZ_Errors should be generated. - TestFailureCase("test_mat2.mtl", 1); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyTexturesNode_NoDependencies) - { - TestSuccessCaseNoDependencies("test_mat3.mtl"); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptySubMaterialNode_ExpectFailure) - { - // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial after calling - // Internal::GetTexturePathsFromMaterial, which should return an AZ::Failure when a SubMaterials node is present, - // but has no children Material node. No other AZ_Errors should be generated. - TestFailureCase("test_mat4.mtl", 1); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyTextureNode_NoDependencies) - { - TestSuccessCaseNoDependencies("test_mat5.mtl"); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyMaterialInSubMaterial_ExpectFailure) - { - // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial after calling - // Internal::GetTexturePathsFromMaterial, which should return an AZ::Failure when a SubMaterials node is present, - // but a child Material node has no child Textures node and no child SubMaterials node. No other AZ_Errors should - // be generated. - TestFailureCase("test_mat6.mtl", 1); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyTextureNodeInSubMaterial_NoDependencies) - { - TestSuccessCaseNoDependencies("test_mat7.mtl"); - } - -#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS // The following test file 'test_mat8.mtl' has a windows-specific absolute path, so this test is only valid on windows - TEST_F(MaterialBuilderTests, MaterialBuilder_TextureAbsolutePath_NoDependencies) - { - TestSuccessCaseNoDependencies("test_mat8.mtl"); - } -#endif - - TEST_F(MaterialBuilderTests, MaterialBuilder_TextureRuntimeAlias_NoDependencies) - { - TestSuccessCaseNoDependencies("test_mat9.mtl"); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_TextureRuntimeTexture_NoDependencies) - { - TestSuccessCaseNoDependencies("test_mat10.mtl"); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialSingleTexture_ValidSourceFormat) - { - // texture referenced is textures/natural/terrain/am_floor_tile_ddn.png - const char* expectedPath = "textures/natural/terrain/am_floor_tile_ddn.dds"; - TestSuccessCase("test_mat11.mtl", expectedPath); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialSingleTexture_ValidProductFormat) - { - // texture referenced is textures/natural/terrain/am_floor_tile_ddn.dds - const char* expectedPath = "textures/natural/terrain/am_floor_tile_ddn.dds"; - TestSuccessCase("test_mat12.mtl", expectedPath); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialSingleTexture_InvalidSourceFormat_NoDependenices) - { - // texture referenced is textures/natural/terrain/am_floor_tile_ddn.txt - TestSuccessCaseNoDependencies("test_mat13.mtl"); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_TextureAnimSequence) - { - AZStd::vector expectedPaths = { - "path/to/my/textures/test_anim_sequence_01_texture000.dds", - "path/to/my/textures/test_anim_sequence_01_texture001.dds", - "path/to/my/textures/test_anim_sequence_01_texture002.dds", - "path/to/my/textures/test_anim_sequence_01_texture003.dds", - "path/to/my/textures/test_anim_sequence_01_texture004.dds", - "path/to/my/textures/test_anim_sequence_01_texture005.dds" - }; - TestSuccessCase("test_mat14.mtl", expectedPaths); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialMultipleTexture) - { - AZStd::vector expectedPaths = { - "engineassets/textures/hex.dds", - "engineassets/textures/hex_ddn.dds" - }; - TestSuccessCase("test_mat15.mtl", expectedPaths); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_MultipleTextures_OneEmptyTexture) - { - TestSuccessCase("test_mat16.mtl", "engineassets/textures/hex_ddn.dds"); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialMultipleTexture_ResolveLeadingSeparatorsAndAliases) - { - AZStd::vector expectedPaths = { - "engineassets/textures/hex.dds", // resolved from "/engineassets/textures/hex.dds" - "engineassets/textures/hex_ddn.dds", // resolved from "./engineassets/textures/hex_ddn.dds" - "engineassets/textures/hex_spec.dds" // resolved from "@products@/engineassets/textures/hex_spec.dds" - }; - TestSuccessCase("test_mat17.mtl", expectedPaths); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_SubMaterialSingleTexture) - { - AZStd::vector expectedPaths = { - "engineassets/textures/scratch.dds", - "engineassets/textures/perlinnoise2d.dds" - }; - TestSuccessCase("test_mat18.mtl", expectedPaths); - } - - TEST_F(MaterialBuilderTests, MaterialBuilder_SubMaterialMultipleTexture) - { - AZStd::vector expectedPaths = { - "engineassets/textures/scratch.dds", - "engineassets/textures/scratch_ddn.dds", - "engineassets/textures/perlinnoise2d.dds", - "engineassets/textures/perlinnoisenormal_ddn.dds" - }; - TestSuccessCase("test_mat19.mtl", expectedPaths); - } -} diff --git a/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake index 5c77888922..aea2f493c7 100644 --- a/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake +++ b/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake @@ -116,8 +116,6 @@ set(FILES Source/Builders/LevelBuilder/LevelBuilderComponent.h Source/Builders/LevelBuilder/LevelBuilderWorker.cpp Source/Builders/LevelBuilder/LevelBuilderWorker.h - Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp - Source/Builders/MaterialBuilder/MaterialBuilderComponent.h Source/Builders/SliceBuilder/SliceBuilderComponent.cpp Source/Builders/SliceBuilder/SliceBuilderComponent.h Source/Builders/SliceBuilder/SliceBuilderWorker.cpp diff --git a/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake index 0f0cf484d1..afba79e566 100644 --- a/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake +++ b/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake @@ -21,7 +21,6 @@ set(FILES Tests/Builders/CopyDependencyBuilderTest.cpp Tests/Builders/SliceBuilderTests.cpp Tests/Builders/LevelBuilderTest.cpp - Tests/Builders/MaterialBuilderTests.cpp Tests/Builders/LuaBuilderTests.cpp Tests/Builders/SeedBuilderTests.cpp Source/LmbrCentral.cpp From 320ae45989a3e569f43f9808907349ef111662c6 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 11 Nov 2021 19:16:18 -0600 Subject: [PATCH 63/97] Removing material type asset info Signed-off-by: Guthrie Adams --- .../UI/AssetCatalogModel.cpp | 9 -- Gems/LmbrCentral/Code/Source/LmbrCentral.cpp | 15 ---- .../Material/MaterialAssetTypeInfo.cpp | 88 ------------------- .../Material/MaterialAssetTypeInfo.h | 55 ------------ Gems/LmbrCentral/Code/lmbrcentral_files.cmake | 2 - .../Code/Source/InstanceSystemComponent.cpp | 3 - 6 files changed, 172 deletions(-) delete mode 100644 Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.cpp delete mode 100644 Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.h diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/AssetCatalogModel.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/AssetCatalogModel.cpp index d0091f968e..2073d0dd5a 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/AssetCatalogModel.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/AssetCatalogModel.cpp @@ -18,7 +18,6 @@ #include #include -#include #include #include @@ -136,14 +135,6 @@ AssetCatalogModel::AssetCatalogModel(QObject* parent) } } - // Special cases for SimpleAssets. If these get full-fledged AssetData types, these cases can be removed. - QString textureExtensions = LmbrCentral::TextureAsset::GetFileFilter(); - m_extensionToAssetType.insert(AZStd::make_pair(textureExtensions.replace("*", "").replace(" ", "").toStdString().c_str(), AZStd::vector { AZ::AzTypeInfo::Uuid() })); - QString materialExtensions = LmbrCentral::MaterialAsset::GetFileFilter(); - m_extensionToAssetType.insert(AZStd::make_pair(materialExtensions.replace("*", "").replace(" ", "").toStdString().c_str(), AZStd::vector { AZ::AzTypeInfo::Uuid() })); - QString dccMaterialExtensions = LmbrCentral::DccMaterialAsset::GetFileFilter(); - m_extensionToAssetType.insert(AZStd::make_pair(dccMaterialExtensions.replace("*", "").replace(" ", "").toStdString().c_str(), AZStd::vector { AZ::AzTypeInfo::Uuid() })); - AZ::SerializeContext* serializeContext = nullptr; EBUS_EVENT_RESULT(serializeContext, AZ::ComponentApplicationBus, GetSerializeContext); AZ_Assert(serializeContext, "Failed to acquire application serialize context."); diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp index ab187a6eed..ad90c16f43 100644 --- a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp +++ b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp @@ -38,9 +38,6 @@ #include "Geometry/GeometrySystemComponent.h" #include -// Unhandled asset types -// Material -#include "Unhandled/Material/MaterialAssetTypeInfo.h" // Other #include "Unhandled/Other/AudioAssetTypeInfo.h" #include "Unhandled/Other/CharacterPhysicsAssetTypeInfo.h" @@ -353,8 +350,6 @@ namespace LmbrCentral // Add asset types and extensions to AssetCatalog. Uses "AssetCatalogService". if (auto assetCatalog = AZ::Data::AssetCatalogRequestBus::FindFirstHandler(); assetCatalog) { - assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid()); - assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid()); assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid()); assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid()); @@ -370,16 +365,6 @@ namespace LmbrCentral AZ::Data::AssetManagerNotificationBus::Handler::BusConnect(); - - // Register unhandled asset type info - // Material - auto materialAssetTypeInfo = aznew MaterialAssetTypeInfo(); - materialAssetTypeInfo->Register(); - m_unhandledAssetInfo.emplace_back(materialAssetTypeInfo); - // DCC Material - auto dccMaterialAssetTypeInfo = aznew DccMaterialAssetTypeInfo(); - dccMaterialAssetTypeInfo->Register(); - m_unhandledAssetInfo.emplace_back(dccMaterialAssetTypeInfo); // Other auto audioAssetTypeInfo = aznew AudioAssetTypeInfo(); audioAssetTypeInfo->Register(); diff --git a/Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.cpp b/Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.cpp deleted file mode 100644 index 24bc43740d..0000000000 --- a/Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include "MaterialAssetTypeInfo.h" - -#include - -namespace LmbrCentral -{ - // MaterialAssetTypeInfo - - MaterialAssetTypeInfo::~MaterialAssetTypeInfo() - { - Unregister(); - } - - void MaterialAssetTypeInfo::Register() - { - AZ::AssetTypeInfoBus::Handler::BusConnect(AZ::AzTypeInfo::Uuid()); - } - - void MaterialAssetTypeInfo::Unregister() - { - AZ::AssetTypeInfoBus::Handler::BusDisconnect(AZ::AzTypeInfo::Uuid()); - } - - AZ::Data::AssetType MaterialAssetTypeInfo::GetAssetType() const - { - return AZ::AzTypeInfo::Uuid(); - } - - const char* MaterialAssetTypeInfo::GetAssetTypeDisplayName() const - { - return "Material"; - } - - const char* MaterialAssetTypeInfo::GetGroup() const - { - return "Material"; - } - - const char* MaterialAssetTypeInfo::GetBrowserIcon() const - { - return "Icons/Components/Decal.svg"; - } - - // DccMaterialAssetTypeInfo - - DccMaterialAssetTypeInfo::~DccMaterialAssetTypeInfo() - { - Unregister(); - } - - void DccMaterialAssetTypeInfo::Register() - { - AZ::AssetTypeInfoBus::Handler::BusConnect(AZ::AzTypeInfo::Uuid()); - } - - void DccMaterialAssetTypeInfo::Unregister() - { - AZ::AssetTypeInfoBus::Handler::BusDisconnect(AZ::AzTypeInfo::Uuid()); - } - - AZ::Data::AssetType DccMaterialAssetTypeInfo::GetAssetType() const - { - return AZ::AzTypeInfo::Uuid(); - } - - const char* DccMaterialAssetTypeInfo::GetAssetTypeDisplayName() const - { - return "DccMaterial"; - } - - const char* DccMaterialAssetTypeInfo::GetGroup() const - { - return "DccMaterial"; - } - - const char* DccMaterialAssetTypeInfo::GetBrowserIcon() const - { - return "Icons/Components/Decal.svg"; - } -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.h b/Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.h deleted file mode 100644 index 2eafa31b41..0000000000 --- a/Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ -#pragma once - -#include - -namespace LmbrCentral -{ - class MaterialAssetTypeInfo - : public AZ::AssetTypeInfoBus::Handler - { - public: - - AZ_CLASS_ALLOCATOR(MaterialAssetTypeInfo, AZ::SystemAllocator, 0); - - ~MaterialAssetTypeInfo() override; - - ////////////////////////////////////////////////////////////////////////////////////////////// - // AZ::AssetTypeInfoBus::Handler - AZ::Data::AssetType GetAssetType() const override; - const char* GetAssetTypeDisplayName() const override; - const char* GetGroup() const override; - const char* GetBrowserIcon() const override; - ////////////////////////////////////////////////////////////////////////////////////////////// - - void Register(); - void Unregister(); - }; - - class DccMaterialAssetTypeInfo - : public AZ::AssetTypeInfoBus::Handler - { - public: - - AZ_CLASS_ALLOCATOR(DccMaterialAssetTypeInfo, AZ::SystemAllocator, 0); - - ~DccMaterialAssetTypeInfo() override; - - ////////////////////////////////////////////////////////////////////////////////////////////// - // AZ::AssetTypeInfoBus::Handler - AZ::Data::AssetType GetAssetType() const override; - const char* GetAssetTypeDisplayName() const override; - const char* GetGroup() const override; - const char* GetBrowserIcon() const override; - ////////////////////////////////////////////////////////////////////////////////////////////// - - void Register(); - void Unregister(); - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/lmbrcentral_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_files.cmake index 18412e2a38..20a366b5f7 100644 --- a/Gems/LmbrCentral/Code/lmbrcentral_files.cmake +++ b/Gems/LmbrCentral/Code/lmbrcentral_files.cmake @@ -145,8 +145,6 @@ set(FILES Source/Shape/ShapeComponentConverters.inl Source/Shape/ShapeGeometryUtil.h Source/Shape/ShapeGeometryUtil.cpp - Source/Unhandled/Material/MaterialAssetTypeInfo.cpp - Source/Unhandled/Material/MaterialAssetTypeInfo.h Source/Unhandled/Other/AudioAssetTypeInfo.cpp Source/Unhandled/Other/AudioAssetTypeInfo.h Source/Unhandled/Other/CharacterPhysicsAssetTypeInfo.cpp diff --git a/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp b/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp index dd38daa633..85ba4bda61 100644 --- a/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp +++ b/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp @@ -15,9 +15,6 @@ #include #include -#include -#include - #include #include #include From a544800536a5bebda96812951befa4d43b0474d3 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Thu, 11 Nov 2021 17:36:12 -0800 Subject: [PATCH 64/97] LYN-4946 | Merge Game Mode buttons in the Play Controls toolbar (#5557) * LYN-4946 Double play buttons - Tranformer style into one. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * compile fix Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Changes as per review. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Address minor confusion points. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Fix rename operation missing some matches... Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Remove extra newline. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Co-authored-by: sphrose <82213493+sphrose@users.noreply.github.com> --- Code/Editor/CryEdit.cpp | 12 +++++++---- Code/Editor/CryEdit.h | 1 + Code/Editor/MainWindow.cpp | 20 +++++++++-------- Code/Editor/Resource.h | 1 + Code/Editor/ToolbarManager.cpp | 39 ++++++++++++++++++++++++++++++---- Code/Editor/ToolbarManager.h | 6 ++++++ 6 files changed, 62 insertions(+), 17 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 0b40390a18..4008710786 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -371,10 +371,8 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_EDIT_FETCH, OnEditFetch) ON_COMMAND(ID_FILE_EXPORTTOGAMENOSURFACETEXTURE, OnFileExportToGameNoSurfaceTexture) ON_COMMAND(ID_VIEW_SWITCHTOGAME, OnViewSwitchToGame) - MainWindow::instance()->GetActionManager()->RegisterActionHandler(ID_VIEW_SWITCHTOGAME_FULLSCREEN, [this]() { - ed_previewGameInFullscreen_once = true; - OnViewSwitchToGame(); - }); + ON_COMMAND(ID_VIEW_SWITCHTOGAME_VIEWPORT, OnViewSwitchToGame) + ON_COMMAND(ID_VIEW_SWITCHTOGAME_FULLSCREEN, OnViewSwitchToGameFullScreen) ON_COMMAND(ID_MOVE_OBJECT, OnMoveObject) ON_COMMAND(ID_RENAME_OBJ, OnRenameObj) ON_COMMAND(ID_UNDO, OnUndo) @@ -2575,6 +2573,12 @@ void CCryEditApp::OnViewSwitchToGame() GetIEditor()->SetInGameMode(inGame); } +void CCryEditApp::OnViewSwitchToGameFullScreen() +{ + ed_previewGameInFullscreen_once = true; + OnViewSwitchToGame(); +} + ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnExportSelectedObjects() { diff --git a/Code/Editor/CryEdit.h b/Code/Editor/CryEdit.h index f68cfdc33d..dd597dcc55 100644 --- a/Code/Editor/CryEdit.h +++ b/Code/Editor/CryEdit.h @@ -212,6 +212,7 @@ public: void OnEditFetch(); void OnFileExportToGameNoSurfaceTexture(); void OnViewSwitchToGame(); + void OnViewSwitchToGameFullScreen(); void OnViewDeploy(); void DeleteSelectedEntities(bool includeDescendants); void OnMoveObject(); diff --git a/Code/Editor/MainWindow.cpp b/Code/Editor/MainWindow.cpp index ed72cd9170..1c5b6c567a 100644 --- a/Code/Editor/MainWindow.cpp +++ b/Code/Editor/MainWindow.cpp @@ -939,27 +939,27 @@ void MainWindow::InitActions() .Connect(&QAction::triggered, this, &MainWindow::OnRefreshAudioSystem); // Game actions - am->AddAction(ID_VIEW_SWITCHTOGAME, tr("Play &Game")) + am->AddAction(ID_VIEW_SWITCHTOGAME, tr("Play Game")) .SetIcon(QIcon(":/stylesheet/img/UI20/toolbar/Play.svg")) + .SetToolTip(tr("Play Game")) + .SetStatusTip(tr("Activate the game input mode")) + .SetCheckable(true) + .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdatePlayGame); + am->AddAction(ID_VIEW_SWITCHTOGAME_VIEWPORT, tr("Play Game")) .SetShortcut(tr("Ctrl+G")) .SetToolTip(tr("Play Game (Ctrl+G)")) .SetStatusTip(tr("Activate the game input mode")) - .SetApplyHoverEffect() - .SetCheckable(true) .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdatePlayGame); - am->AddAction(ID_VIEW_SWITCHTOGAME_FULLSCREEN, tr("Play &Game (Maximized)")) + am->AddAction(ID_VIEW_SWITCHTOGAME_FULLSCREEN, tr("Play Game (Maximized)")) .SetShortcut(tr("Ctrl+Shift+G")) .SetStatusTip(tr("Activate the game input mode (maximized)")) - .SetIcon(Style::icon("Play")) - .SetApplyHoverEffect() - .SetCheckable(true); + .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdatePlayGame); am->AddAction(ID_TOOLBAR_WIDGET_PLAYCONSOLE_LABEL, tr("Play Controls")) .SetText(tr("Play Controls")); am->AddAction(ID_SWITCH_PHYSICS, tr("Simulate")) .SetIcon(QIcon(":/stylesheet/img/UI20/toolbar/Simulate_Physics.svg")) .SetShortcut(tr("Ctrl+P")) .SetToolTip(tr("Simulate (Ctrl+P)")) - .SetCheckable(true) .SetStatusTip(tr("Enable processing of Physics and AI.")) .SetApplyHoverEffect() .SetCheckable(true) @@ -1266,7 +1266,9 @@ void MainWindow::OnGameModeChanged(bool inGameMode) // block signals on the switch to game actions before setting the checked state, as // setting the checked state triggers the action, which will re-enter this function // and result in an infinite loop - AZStd::vector actions = { m_actionManager->GetAction(ID_VIEW_SWITCHTOGAME), m_actionManager->GetAction(ID_VIEW_SWITCHTOGAME_FULLSCREEN) }; + AZStd::vector actions = { m_actionManager->GetAction(ID_VIEW_SWITCHTOGAME_VIEWPORT), + m_actionManager->GetAction(ID_VIEW_SWITCHTOGAME_FULLSCREEN), + m_actionManager->GetAction(ID_VIEW_SWITCHTOGAME)}; for (auto action : actions) { action->blockSignals(true); diff --git a/Code/Editor/Resource.h b/Code/Editor/Resource.h index b3640fac70..ba3cd39fe7 100644 --- a/Code/Editor/Resource.h +++ b/Code/Editor/Resource.h @@ -104,6 +104,7 @@ #define ID_FILE_EXPORTTOGAMENOSURFACETEXTURE 33473 #define ID_VIEW_SWITCHTOGAME 33477 #define ID_VIEW_SWITCHTOGAME_FULLSCREEN 33478 +#define ID_VIEW_SWITCHTOGAME_VIEWPORT 33479 #define ID_MOVE_OBJECT 33481 #define ID_RENAME_OBJ 33483 #define ID_FETCH 33496 diff --git a/Code/Editor/ToolbarManager.cpp b/Code/Editor/ToolbarManager.cpp index 00b7992ef0..6b610d23ce 100644 --- a/Code/Editor/ToolbarManager.cpp +++ b/Code/Editor/ToolbarManager.cpp @@ -590,6 +590,16 @@ AmazonToolbar ToolbarManager::GetObjectToolbar() const return t; } +QMenu* ToolbarManager::CreatePlayButtonMenu() const +{ + QMenu* playButtonMenu = new QMenu("Play Game"); + + playButtonMenu->addAction(m_actionManager->GetAction(ID_VIEW_SWITCHTOGAME_VIEWPORT)); + playButtonMenu->addAction(m_actionManager->GetAction(ID_VIEW_SWITCHTOGAME_FULLSCREEN)); + + return playButtonMenu; +} + AmazonToolbar ToolbarManager::GetPlayConsoleToolbar() const { AmazonToolbar t = AmazonToolbar("PlayConsole", QObject::tr("Play Controls")); @@ -598,8 +608,17 @@ AmazonToolbar ToolbarManager::GetPlayConsoleToolbar() const t.AddAction(ID_TOOLBAR_WIDGET_SPACER_RIGHT, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_TOOLBAR_SEPARATOR, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_TOOLBAR_WIDGET_PLAYCONSOLE_LABEL, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_VIEW_SWITCHTOGAME, TOOLBARS_WITH_PLAY_GAME); - t.AddAction(ID_VIEW_SWITCHTOGAME_FULLSCREEN, TOOLBARS_WITH_PLAY_GAME); + + QAction* playAction = m_actionManager->GetAction(ID_VIEW_SWITCHTOGAME); + QToolButton* playButton = new QToolButton(t.Toolbar()); + + QMenu* menu = CreatePlayButtonMenu(); + menu->setParent(t.Toolbar()); + playAction->setMenu(menu); + + playButton->setDefaultAction(playAction); + t.AddWidget(playButton, ID_VIEW_SWITCHTOGAME, ORIGINAL_TOOLBAR_VERSION); + t.AddAction(ID_TOOLBAR_SEPARATOR, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_SWITCH_PHYSICS, TOOLBARS_WITH_PLAY_GAME); return t; @@ -728,7 +747,14 @@ void AmazonToolbar::SetActionsOnInternalToolbar(ActionManager* actionManager) { if (actionManager->HasAction(actionId)) { - m_toolbar->addAction(actionManager->GetAction(actionId)); + if (actionData.widget != nullptr) + { + m_toolbar->addWidget(actionData.widget); + } + else + { + m_toolbar->addAction(actionManager->GetAction(actionId)); + } } } } @@ -1367,7 +1393,12 @@ void AmazonToolbar::InstantiateToolbar(QMainWindow* mainWindow, ToolbarManager* void AmazonToolbar::AddAction(int actionId, int toolbarVersionAdded) { - m_actions.push_back({ actionId, toolbarVersionAdded }); + AddWidget(nullptr, actionId, toolbarVersionAdded); +} + +void AmazonToolbar::AddWidget(QWidget* widget, int actionId, int toolbarVersionAdded) +{ + m_actions.push_back({ actionId, toolbarVersionAdded, widget }); } void AmazonToolbar::Clear() diff --git a/Code/Editor/ToolbarManager.h b/Code/Editor/ToolbarManager.h index be537533b6..ae6b0c7296 100644 --- a/Code/Editor/ToolbarManager.h +++ b/Code/Editor/ToolbarManager.h @@ -87,6 +87,7 @@ public: const QString& GetTranslatedName() const { return m_translatedName; } void AddAction(int actionId, int toolbarVersionAdded = 0); + void AddWidget(QWidget* widget, int actionId, int toolbarVersionAdded = 0); QToolBar* Toolbar() const { return m_toolbar; } @@ -117,6 +118,7 @@ private: { int actionId; int toolbarVersionAdded; + QWidget* widget; bool operator ==(const AmazonToolbar::ActionData& other) const { @@ -133,7 +135,9 @@ private: class AmazonToolBarExpanderWatcher; class ToolbarManager + : public QObject { + Q_OBJECT public: explicit ToolbarManager(ActionManager* actionManager, MainWindow* mainWindow); ~ToolbarManager(); @@ -178,6 +182,8 @@ private: void UpdateAllowedAreas(QToolBar* toolbar); bool IsDirty(const AmazonToolbar& toolbar) const; + QMenu* CreatePlayButtonMenu() const; + const AmazonToolbar* FindDefaultToolbar(const QString& toolbarName) const; AmazonToolbar* FindToolbar(const QString& toolbarName); From f18f838da6561bd0419c0dc2af9bb125fd262f64 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 20 Oct 2021 10:25:05 -0500 Subject: [PATCH 65/97] material editor and exporter save source materials with relative paths Signed-off-by: Guthrie Adams --- .../Material/MaterialTypeSourceData.h | 4 - .../Material/MaterialTypeSourceData.cpp | 42 ------- .../Util/MaterialPropertyUtil.h | 12 +- .../Code/Source/Util/MaterialPropertyUtil.cpp | 48 +++++++- .../Code/Source/Document/MaterialDocument.cpp | 110 ++++++++++-------- .../Code/Source/Document/MaterialDocument.h | 5 +- .../Material/EditorMaterialComponentUtil.cpp | 52 +++++---- 7 files changed, 151 insertions(+), 122 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h index 1234b15f95..f5336807c7 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h @@ -209,10 +209,6 @@ namespace AZ //! Traversal will stop once all properties have been enumerated or the callback function returns false void EnumeratePropertiesInDisplayOrder(const EnumeratePropertiesCallback& callback) const; - //! Convert the property value into the format that will be stored in the source data - //! This is primarily needed to support conversions of special types like enums and images - bool ConvertPropertyValueToSourceDataFormat(const PropertyDefinition& propertyDefinition, MaterialPropertyValue& propertyValue) const; - Outcome> CreateMaterialTypeAsset(Data::AssetId assetId, AZStd::string_view materialTypeSourceFilePath = "", bool elevateWarnings = true) const; //! Possibly renames @propertyId based on the material version update steps. diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp index 396ba71e14..d5551e89ae 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp @@ -300,48 +300,6 @@ namespace AZ } } - bool MaterialTypeSourceData::ConvertPropertyValueToSourceDataFormat(const PropertyDefinition& propertyDefinition, MaterialPropertyValue& propertyValue) const - { - if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Enum && propertyValue.Is()) - { - const uint32_t index = propertyValue.GetValue(); - if (index >= propertyDefinition.m_enumValues.size()) - { - AZ_Error("Material source data", false, "Invalid value for material enum property: '%s'.", propertyDefinition.m_name.c_str()); - return false; - } - - propertyValue = propertyDefinition.m_enumValues[index]; - return true; - } - - // Image asset references must be converted from asset IDs to a relative source file path - if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Image && propertyValue.Is>()) - { - const Data::Asset& imageAsset = propertyValue.GetValue>(); - - Data::AssetInfo imageAssetInfo; - if (imageAsset.GetId().IsValid()) - { - bool result = false; - AZStd::string rootFilePath; - const AZStd::string platformName = ""; // Empty for default - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetAssetInfoById, - imageAsset.GetId(), imageAsset.GetType(), platformName, imageAssetInfo, rootFilePath); - if (!result) - { - AZ_Error("Material source data", false, "Image asset could not be found for property: '%s'.", propertyDefinition.m_name.c_str()); - return false; - } - } - - propertyValue = imageAssetInfo.m_relativePath; - return true; - } - - return true; - } - Outcome> MaterialTypeSourceData::CreateMaterialTypeAsset(Data::AssetId assetId, AZStd::string_view materialTypeSourceFilePath, bool elevateWarnings) const { MaterialTypeAssetCreator materialTypeAssetCreator; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h index 333796493d..d888c76553 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h @@ -7,11 +7,12 @@ */ #pragma once -#include -#include #include #include #include +#include +#include +#include namespace AzToolsFramework { @@ -41,6 +42,13 @@ namespace AtomToolsFramework //! Compare equality of data types and values of editor property stored in AZStd::any bool ArePropertyValuesEqual(const AZStd::any& valueA, const AZStd::any& valueB); + //! Convert the property value into the format that will be stored in the source data + //! This is primarily needed to support conversions of special types like enums and images + bool ConvertToExportFormat( + const AZ::IO::BasicPath& exportFolder, + const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition, + AZ::RPI::MaterialPropertyValue& propertyValue); + //! Traverse up the instance data node hierarchy to find the containing dynamic property object const AtomToolsFramework::DynamicProperty* FindDynamicPropertyForInstanceDataNode(const AzToolsFramework::InstanceDataNode* pNode); } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp index 3f8a173918..b142977049 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp @@ -6,9 +6,10 @@ * */ -#include #include +#include +#include #include #include #include @@ -18,6 +19,7 @@ #include #include #include +#include #include namespace AtomToolsFramework @@ -163,6 +165,47 @@ namespace AtomToolsFramework return false; } + bool ConvertToExportFormat( + const AZ::IO::BasicPath& exportFolder, + const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition, + AZ::RPI::MaterialPropertyValue& propertyValue) + { + if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Enum && propertyValue.Is()) + { + const uint32_t index = propertyValue.GetValue(); + if (index >= propertyDefinition.m_enumValues.size()) + { + AZ_Error("AtomToolsFramework", false, "Invalid value for material enum property: '%s'.", propertyDefinition.m_name.c_str()); + return false; + } + + propertyValue = propertyDefinition.m_enumValues[index]; + return true; + } + + // Image asset references must be converted from asset IDs to a relative source file path + if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Image) + { + if (propertyValue.Is>()) + { + const auto& imageAsset = propertyValue.GetValue>(); + const auto& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(imageAsset.GetId()); + propertyValue = AZ::IO::PathView(sourcePath).LexicallyRelative(exportFolder).StringAsPosix(); + return true; + } + + if (propertyValue.Is>()) + { + const auto& image = propertyValue.GetValue>(); + const auto& sourcePath = image ? AZ::RPI::AssetUtils::GetSourcePathByAssetId(image->GetAssetId()) : ""; + propertyValue = AZ::IO::PathView(sourcePath).LexicallyRelative(exportFolder).StringAsPosix(); + return true; + } + } + + return true; + } + const AtomToolsFramework::DynamicProperty* FindDynamicPropertyForInstanceDataNode(const AzToolsFramework::InstanceDataNode* pNode) { // Traverse up the hierarchy from the input node to search for an instance corresponding to material inspector property @@ -172,7 +215,8 @@ namespace AtomToolsFramework const AZ::SerializeContext::ClassData* classData = currentNode->GetClassMetadata(); if (context && classData) { - if (context->CanDowncast(classData->m_typeId, azrtti_typeid(), classData->m_azRtti, nullptr)) + if (context->CanDowncast( + classData->m_typeId, azrtti_typeid(), classData->m_azRtti, nullptr)) { return static_cast(currentNode->FirstInstance()); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index ee58cbea3e..1d3ada6457 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -228,22 +228,22 @@ namespace MaterialEditor return false; } + AZ::IO::BasicPath exportFolder(m_absolutePath); + exportFolder.RemoveFilename(); + // create source data from properties MaterialSourceData sourceData; - sourceData.m_materialType = m_materialSourceData.m_materialType; - sourceData.m_parentMaterial = m_materialSourceData.m_parentMaterial; - - AZ_Assert(m_materialAsset && m_materialAsset->GetMaterialTypeAsset(), "When IsOpen() is true, these assets should not be null."); - sourceData.m_materialTypeVersion = m_materialAsset->GetMaterialTypeAsset()->GetVersion(); - - // Force save data to store forward slashes - AzFramework::StringFunc::Replace(sourceData.m_materialType, "\\", "/"); - AzFramework::StringFunc::Replace(sourceData.m_parentMaterial, "\\", "/"); + sourceData.m_propertyLayoutVersion = m_materialTypeSourceData.m_propertyLayout.m_version; + sourceData.m_materialType = AZ::IO::PathView(m_materialSourceData.m_materialType).LexicallyRelative(exportFolder).StringAsPosix(); + sourceData.m_parentMaterial = AZ::IO::PathView(m_materialSourceData.m_parentMaterial).LexicallyRelative(exportFolder).StringAsPosix(); // populate sourceData with modified or overwritten properties - const bool savedProperties = SavePropertiesToSourceData(sourceData, [](const AtomToolsFramework::DynamicProperty& property) { - return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue); - }); + const bool savedProperties = SavePropertiesToSourceData( + exportFolder, sourceData, + [](const AtomToolsFramework::DynamicProperty& property) + { + return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue); + }); if (!savedProperties) { @@ -302,22 +302,22 @@ namespace MaterialEditor return false; } + AZ::IO::BasicPath exportFolder(normalizedSavePath); + exportFolder.RemoveFilename(); + // create source data from properties MaterialSourceData sourceData; - sourceData.m_materialType = m_materialSourceData.m_materialType; - sourceData.m_parentMaterial = m_materialSourceData.m_parentMaterial; - - AZ_Assert(m_materialAsset && m_materialAsset->GetMaterialTypeAsset(), "When IsOpen() is true, these assets should not be null."); - sourceData.m_materialTypeVersion = m_materialAsset->GetMaterialTypeAsset()->GetVersion(); - - // Force save data to store forward slashes - AzFramework::StringFunc::Replace(sourceData.m_materialType, "\\", "/"); - AzFramework::StringFunc::Replace(sourceData.m_parentMaterial, "\\", "/"); + sourceData.m_propertyLayoutVersion = m_materialTypeSourceData.m_propertyLayout.m_version; + sourceData.m_materialType = AZ::IO::PathView(m_materialSourceData.m_materialType).LexicallyRelative(exportFolder).StringAsPosix(); + sourceData.m_parentMaterial = AZ::IO::PathView(m_materialSourceData.m_parentMaterial).LexicallyRelative(exportFolder).StringAsPosix(); // populate sourceData with modified or overwritten properties - const bool savedProperties = SavePropertiesToSourceData(sourceData, [](const AtomToolsFramework::DynamicProperty& property) { - return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue); - }); + const bool savedProperties = SavePropertiesToSourceData( + exportFolder, sourceData, + [](const AtomToolsFramework::DynamicProperty& property) + { + return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue); + }); if (!savedProperties) { @@ -375,17 +375,18 @@ namespace MaterialEditor return false; } + AZ::IO::BasicPath exportFolder(normalizedSavePath); + exportFolder.RemoveFilename(); + // create source data from properties MaterialSourceData sourceData; - sourceData.m_materialType = m_materialSourceData.m_materialType; - - AZ_Assert(m_materialAsset && m_materialAsset->GetMaterialTypeAsset(), "When IsOpen() is true, these assets should not be null."); - sourceData.m_materialTypeVersion = m_materialAsset->GetMaterialTypeAsset()->GetVersion(); + sourceData.m_propertyLayoutVersion = m_materialTypeSourceData.m_propertyLayout.m_version; + sourceData.m_materialType = AZ::IO::PathView(m_materialSourceData.m_materialType).LexicallyRelative(exportFolder).StringAsPosix(); // Only assign a parent path if the source was a .material if (AzFramework::StringFunc::Path::IsExtension(m_relativePath.c_str(), MaterialSourceData::Extension)) { - sourceData.m_parentMaterial = m_relativePath; + sourceData.m_parentMaterial = AZ::IO::PathView(m_absolutePath).LexicallyRelative(exportFolder).StringAsPosix(); } // Force save data to store forward slashes @@ -393,9 +394,12 @@ namespace MaterialEditor AzFramework::StringFunc::Replace(sourceData.m_parentMaterial, "\\", "/"); // populate sourceData with modified properties - const bool savedProperties = SavePropertiesToSourceData(sourceData, [](const AtomToolsFramework::DynamicProperty& property) { - return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_originalValue); - }); + const bool savedProperties = SavePropertiesToSourceData( + exportFolder, sourceData, + [](const AtomToolsFramework::DynamicProperty& property) + { + return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_originalValue); + }); if (!savedProperties) { @@ -590,7 +594,10 @@ namespace MaterialEditor } } - bool MaterialDocument::SavePropertiesToSourceData(AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const + bool MaterialDocument::SavePropertiesToSourceData( + const AZ::IO::BasicPath& exportFolder, + AZ::RPI::MaterialSourceData& sourceData, + PropertyFilterFunction propertyFilter) const { using namespace AZ; using namespace RPI; @@ -598,7 +605,7 @@ namespace MaterialEditor bool result = true; // populate sourceData with properties that meet the filter - m_materialTypeSourceData.EnumerateProperties([this, &sourceData, &propertyFilter, &result](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition) { + m_materialTypeSourceData.EnumerateProperties([&](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition) { const MaterialPropertyId propertyId(groupName, propertyName); @@ -608,7 +615,7 @@ namespace MaterialEditor MaterialPropertyValue propertyValue = AtomToolsFramework::ConvertToRuntimeType(it->second.GetValue()); if (propertyValue.IsValid()) { - if (!m_materialTypeSourceData.ConvertPropertyValueToSourceDataFormat(propertyDefinition, propertyValue)) + if (!AtomToolsFramework::ConvertToExportFormat(exportFolder, propertyDefinition, propertyValue)) { AZ_Error("MaterialDocument", false, "Material document property could not be converted: '%s' in '%s'.", propertyId.GetFullName().GetCStr(), m_absolutePath.c_str()); result = false; @@ -662,8 +669,6 @@ namespace MaterialEditor return false; } - AZStd::string materialTypeSourceFilePath; - // The material document and inspector are constructed from source data if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), MaterialSourceData::Extension)) { @@ -676,27 +681,29 @@ namespace MaterialEditor // We must also always load the material type data for a complete, ordered set of the // groups and properties that will be needed for comparison and building the inspector - materialTypeSourceFilePath = AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_materialType); - auto materialTypeOutcome = MaterialUtils::LoadMaterialTypeSourceData(materialTypeSourceFilePath); + if (!m_materialSourceData.m_parentMaterial.empty()) + { + m_materialSourceData.m_parentMaterial = + AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_parentMaterial); + } + + if (!m_materialSourceData.m_materialType.empty()) + { + m_materialSourceData.m_materialType = AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_materialType); + } + + auto materialTypeOutcome = MaterialUtils::LoadMaterialTypeSourceData(m_materialSourceData.m_materialType); if (!materialTypeOutcome.IsSuccess()) { - AZ_Error("MaterialDocument", false, "Material type source data could not be loaded: '%s'.", materialTypeSourceFilePath.c_str()); + AZ_Error("MaterialDocument", false, "Material type source data could not be loaded: '%s'.", m_materialSourceData.m_materialType.c_str()); return false; } m_materialTypeSourceData = materialTypeOutcome.GetValue(); - - if (MaterialSourceData::ApplyVersionUpdatesResult::Failed == m_materialSourceData.ApplyVersionUpdates(m_absolutePath)) - { - AZ_Error("MaterialDocument", false, "Material source data could not be auto updated to the latest version of the material type: '%s'.", m_materialSourceData.m_materialType.c_str()); - return false; - } } else if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), MaterialTypeSourceData::Extension)) { - materialTypeSourceFilePath = m_absolutePath; - // Load the material type source data, which will be used for enumerating properties and building material source data - auto materialTypeOutcome = MaterialUtils::LoadMaterialTypeSourceData(materialTypeSourceFilePath); + auto materialTypeOutcome = MaterialUtils::LoadMaterialTypeSourceData(m_absolutePath); if (!materialTypeOutcome.IsSuccess()) { AZ_Error("MaterialDocument", false, "Material type source data could not be loaded: '%s'.", m_absolutePath.c_str()); @@ -706,7 +713,7 @@ namespace MaterialEditor // The document represents a material, not a material type. // If the input data is a material type file we have to generate the material source data by referencing it. - m_materialSourceData.m_materialType = m_relativePath; + m_materialSourceData.m_materialType = m_absolutePath; m_materialSourceData.m_parentMaterial.clear(); } else @@ -877,7 +884,8 @@ namespace MaterialEditor m_properties[propertyConfig.m_id] = AtomToolsFramework::DynamicProperty(propertyConfig); } - const MaterialFunctorSourceData::EditorContext editorContext = MaterialFunctorSourceData::EditorContext(materialTypeSourceFilePath, m_materialAsset->GetMaterialPropertiesLayout()); + const MaterialFunctorSourceData::EditorContext editorContext = + MaterialFunctorSourceData::EditorContext(m_materialSourceData.m_materialType, m_materialAsset->GetMaterialPropertiesLayout()); for (Ptr functorData : m_materialTypeSourceData.m_materialFunctorSourceData) { MaterialFunctorSourceData::FunctorResult result2 = functorData->CreateFunctor(editorContext); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h index 452111f99a..c4fd263014 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h @@ -104,7 +104,10 @@ namespace MaterialEditor void SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid sourceUUID) override; ////////////////////////////////////////////////////////////////////////// - bool SavePropertiesToSourceData(AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const; + bool SavePropertiesToSourceData( + const AZ::IO::BasicPath& exportFolder, + AZ::RPI::MaterialSourceData& sourceData, + PropertyFilterFunction propertyFilter) const; bool OpenInternal(AZStd::string_view loadPath); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp index d15db886d6..c775676e68 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -97,29 +98,38 @@ namespace AZ bool SaveSourceMaterialFromEditData(const AZStd::string& path, const MaterialEditData& editData) { + AZ::IO::BasicPath exportFolder(path); + exportFolder.RemoveFilename(); + // Construct the material source data object that will be exported AZ::RPI::MaterialSourceData exportData; // Converting absolute material paths to relative paths - bool result = false; - AZ::Data::AssetInfo info; - AZStd::string watchFolder; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult( - result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, - editData.m_materialTypeSourcePath.c_str(), info, watchFolder); - if (!result) + if (!editData.m_materialTypeSourcePath.empty()) { - AZ_Error( - "AZ::Render::EditorMaterialComponentUtil", false, - "Failed to get material type source file info while attempting to export: %s", path.c_str()); - return false; - } + bool result = false; + AZ::Data::AssetInfo info; + AZStd::string watchFolder; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult( + result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, + editData.m_materialTypeSourcePath.c_str(), info, watchFolder); + if (!result) + { + AZ_Error( + "AZ::Render::EditorMaterialComponentUtil", false, + "Failed to get material type source file info while attempting to export: %s", path.c_str()); + return false; + } - exportData.m_materialType = info.m_relativePath; + exportData.m_materialType = + AZ::IO::PathView(editData.m_materialTypeSourcePath).LexicallyRelative(exportFolder).StringAsPosix(); + } if (!editData.m_materialParentSourcePath.empty()) { - result = false; + bool result = false; + AZ::Data::AssetInfo info; + AZStd::string watchFolder; AzToolsFramework::AssetSystemRequestBus::BroadcastResult( result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, editData.m_materialParentSourcePath.c_str(), info, watchFolder); @@ -131,17 +141,19 @@ namespace AZ return false; } - exportData.m_parentMaterial = info.m_relativePath; + exportData.m_parentMaterial = + AZ::IO::PathView(editData.m_materialParentSourcePath).LexicallyRelative(exportFolder).StringAsPosix(); } // Copy all of the properties from the material asset to the source data that will be exported - result = true; - editData.m_materialTypeSourceData.EnumerateProperties([&](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition) { + bool result = true; + editData.m_materialTypeSourceData.EnumerateProperties([&](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition){ const AZ::RPI::MaterialPropertyId propertyId(groupName, propertyName); const AZ::RPI::MaterialPropertyIndex propertyIndex = editData.m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyId.GetFullName()); - AZ::RPI::MaterialPropertyValue propertyValue = editData.m_materialAsset->GetPropertyValues()[propertyIndex.GetIndex()]; + AZ::RPI::MaterialPropertyValue propertyValue = + editData.m_materialAsset->GetPropertyValues()[propertyIndex.GetIndex()]; AZ::RPI::MaterialPropertyValue propertyValueDefault = propertyDefinition.m_value; if (editData.m_materialParentAsset.IsReady()) @@ -151,12 +163,12 @@ namespace AZ // Check for and apply any property overrides before saving property values auto propertyOverrideItr = editData.m_materialPropertyOverrideMap.find(propertyId.GetFullName()); - if(propertyOverrideItr != editData.m_materialPropertyOverrideMap.end()) + if (propertyOverrideItr != editData.m_materialPropertyOverrideMap.end()) { propertyValue = AZ::RPI::MaterialPropertyValue::FromAny(propertyOverrideItr->second); } - if (!editData.m_materialTypeSourceData.ConvertPropertyValueToSourceDataFormat(propertyDefinition, propertyValue)) + if (!AtomToolsFramework::ConvertToExportFormat(exportFolder, propertyDefinition, propertyValue)) { AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Failed to export: %s", path.c_str()); result = false; From ed4f7965da6f9459be64e7cac8523041696dea0d Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sun, 31 Oct 2021 22:49:14 -0500 Subject: [PATCH 66/97] =?UTF-8?q?=EF=BB=BFCreated=20function=20to=20get=20?= =?UTF-8?q?relative=20paths=20to=20referenced=20files=20that=20will=20fall?= =?UTF-8?q?=20back=20to=20asset=20folder=20relative=20paths=20under=20cert?= =?UTF-8?q?ain=20conditions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Guthrie Adams --- .../Util/MaterialPropertyUtil.h | 14 ++++- .../Code/Source/Util/MaterialPropertyUtil.cpp | 46 ++++++++++++++++- .../Code/Source/Document/MaterialDocument.cpp | 51 ++++++++----------- .../Code/Source/Document/MaterialDocument.h | 4 +- .../Material/EditorMaterialComponentUtil.cpp | 11 ++-- 5 files changed, 84 insertions(+), 42 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h index d888c76553..b191e01bce 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h @@ -45,10 +45,22 @@ namespace AtomToolsFramework //! Convert the property value into the format that will be stored in the source data //! This is primarily needed to support conversions of special types like enums and images bool ConvertToExportFormat( - const AZ::IO::BasicPath& exportFolder, + const AZStd::string& exportPath, const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition, AZ::RPI::MaterialPropertyValue& propertyValue); + //! Generate a file path from the exported file to the external reference. + //! This function is to support copying or moving a folder containing materials, models, and textures without modifying the files. The + //! general case returns a relative path from the export file to the reference file. If the reference path is too different or distant + //! from the export path then it might be more difficult to work with than an asset folder relative path. For example, material types + //! that Atom provides live in a folder that should be accessible from anywhere. When materials are created in arbitrary gems and + //! project folders, a relative path to the material type would need to be updated whenever the materials are copied or moved. The same + //! thing will happen with parent materials or textures if their paths can’t be resolved. To alleviate some of this, we use the asset + //! folder relative path if the export folder relative path is too complex. An alternate solution would be to only use export folder + //! relative paths if the referenced path is in the same folder or a sub folder the assets are not generally packaged like that. + AZStd::string GetExteralReferencePath( + const AZStd::string& exportPath, const AZStd::string& referencePath, const uint32_t maxPathDepth = 2); + //! Traverse up the instance data node hierarchy to find the containing dynamic property object const AtomToolsFramework::DynamicProperty* FindDynamicPropertyForInstanceDataNode(const AzToolsFramework::InstanceDataNode* pNode); } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp index b142977049..6ad9506fdd 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp @@ -166,10 +166,13 @@ namespace AtomToolsFramework } bool ConvertToExportFormat( - const AZ::IO::BasicPath& exportFolder, + const AZStd::string& exportPath, const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition, AZ::RPI::MaterialPropertyValue& propertyValue) { + AZ::IO::BasicPath exportFolder(exportPath); + exportFolder.RemoveFilename(); + if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Enum && propertyValue.Is()) { const uint32_t index = propertyValue.GetValue(); @@ -206,6 +209,47 @@ namespace AtomToolsFramework return true; } + AZStd::string GetExteralReferencePath(const AZStd::string& exportPath, const AZStd::string& referencePath, const uint32_t maxPathDepth) + { + if (referencePath.empty()) + { + return {}; + } + + AZ::IO::BasicPath exportFolder(exportPath); + exportFolder.RemoveFilename(); + + const AZStd::string relativePath = AZ::IO::PathView(referencePath).LexicallyRelative(exportFolder).StringAsPosix(); + + // Count the difference in depth between the export file path and the referenced file path. + uint32_t parentFolderCount = 0; + AZStd::string::size_type pos = 0; + const AZStd::string parentFolderToken = ".."; + while ((pos = relativePath.find(parentFolderToken, pos)) != AZStd::string::npos) + { + parentFolderCount++; + pos += parentFolderToken.length(); + } + + // If the difference in depth is too great then revert to using the asset folder relative path. + // We could change this to only use relative paths for references in subfolders. + if (parentFolderCount > maxPathDepth) + { + AZStd::string watchFolder; + AZ::Data::AssetInfo assetInfo; + bool sourceInfoFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult( + sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, referencePath.c_str(), + assetInfo, watchFolder); + if (sourceInfoFound) + { + return assetInfo.m_relativePath; + } + } + + return relativePath; + } + const AtomToolsFramework::DynamicProperty* FindDynamicPropertyForInstanceDataNode(const AzToolsFramework::InstanceDataNode* pNode) { // Traverse up the hierarchy from the input node to search for an instance corresponding to material inspector property diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 1d3ada6457..2a0dcb36c2 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -228,18 +228,15 @@ namespace MaterialEditor return false; } - AZ::IO::BasicPath exportFolder(m_absolutePath); - exportFolder.RemoveFilename(); - // create source data from properties MaterialSourceData sourceData; - sourceData.m_propertyLayoutVersion = m_materialTypeSourceData.m_propertyLayout.m_version; - sourceData.m_materialType = AZ::IO::PathView(m_materialSourceData.m_materialType).LexicallyRelative(exportFolder).StringAsPosix(); - sourceData.m_parentMaterial = AZ::IO::PathView(m_materialSourceData.m_parentMaterial).LexicallyRelative(exportFolder).StringAsPosix(); + sourceData.m_materialTypeVersion = m_materialAsset->GetMaterialTypeAsset()->GetVersion(); + sourceData.m_materialType = AtomToolsFramework::GetExteralReferencePath(m_absolutePath, m_materialSourceData.m_materialType); + sourceData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(m_absolutePath, m_materialSourceData.m_parentMaterial); // populate sourceData with modified or overwritten properties const bool savedProperties = SavePropertiesToSourceData( - exportFolder, sourceData, + m_absolutePath, sourceData, [](const AtomToolsFramework::DynamicProperty& property) { return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue); @@ -302,18 +299,16 @@ namespace MaterialEditor return false; } - AZ::IO::BasicPath exportFolder(normalizedSavePath); - exportFolder.RemoveFilename(); - // create source data from properties MaterialSourceData sourceData; - sourceData.m_propertyLayoutVersion = m_materialTypeSourceData.m_propertyLayout.m_version; - sourceData.m_materialType = AZ::IO::PathView(m_materialSourceData.m_materialType).LexicallyRelative(exportFolder).StringAsPosix(); - sourceData.m_parentMaterial = AZ::IO::PathView(m_materialSourceData.m_parentMaterial).LexicallyRelative(exportFolder).StringAsPosix(); + sourceData.m_materialTypeVersion = m_materialAsset->GetMaterialTypeAsset()->GetVersion(); + sourceData.m_materialType = AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_materialType); + sourceData.m_parentMaterial = + AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_parentMaterial); // populate sourceData with modified or overwritten properties const bool savedProperties = SavePropertiesToSourceData( - exportFolder, sourceData, + normalizedSavePath, sourceData, [](const AtomToolsFramework::DynamicProperty& property) { return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue); @@ -375,27 +370,21 @@ namespace MaterialEditor return false; } - AZ::IO::BasicPath exportFolder(normalizedSavePath); - exportFolder.RemoveFilename(); - // create source data from properties MaterialSourceData sourceData; - sourceData.m_propertyLayoutVersion = m_materialTypeSourceData.m_propertyLayout.m_version; - sourceData.m_materialType = AZ::IO::PathView(m_materialSourceData.m_materialType).LexicallyRelative(exportFolder).StringAsPosix(); + sourceData.m_materialTypeVersion = m_materialAsset->GetMaterialTypeAsset()->GetVersion(); + sourceData.m_materialType = AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_materialType); // Only assign a parent path if the source was a .material if (AzFramework::StringFunc::Path::IsExtension(m_relativePath.c_str(), MaterialSourceData::Extension)) { - sourceData.m_parentMaterial = AZ::IO::PathView(m_absolutePath).LexicallyRelative(exportFolder).StringAsPosix(); + sourceData.m_parentMaterial = + AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_parentMaterial); } - // Force save data to store forward slashes - AzFramework::StringFunc::Replace(sourceData.m_materialType, "\\", "/"); - AzFramework::StringFunc::Replace(sourceData.m_parentMaterial, "\\", "/"); - // populate sourceData with modified properties const bool savedProperties = SavePropertiesToSourceData( - exportFolder, sourceData, + normalizedSavePath, sourceData, [](const AtomToolsFramework::DynamicProperty& property) { return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_originalValue); @@ -595,9 +584,7 @@ namespace MaterialEditor } bool MaterialDocument::SavePropertiesToSourceData( - const AZ::IO::BasicPath& exportFolder, - AZ::RPI::MaterialSourceData& sourceData, - PropertyFilterFunction propertyFilter) const + const AZStd::string& exportPath, AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const { using namespace AZ; using namespace RPI; @@ -615,7 +602,7 @@ namespace MaterialEditor MaterialPropertyValue propertyValue = AtomToolsFramework::ConvertToRuntimeType(it->second.GetValue()); if (propertyValue.IsValid()) { - if (!AtomToolsFramework::ConvertToExportFormat(exportFolder, propertyDefinition, propertyValue)) + if (!AtomToolsFramework::ConvertToExportFormat(exportPath, propertyDefinition, propertyValue)) { AZ_Error("MaterialDocument", false, "Material document property could not be converted: '%s' in '%s'.", propertyId.GetFullName().GetCStr(), m_absolutePath.c_str()); result = false; @@ -699,6 +686,12 @@ namespace MaterialEditor return false; } m_materialTypeSourceData = materialTypeOutcome.GetValue(); + + if (MaterialSourceData::ApplyVersionUpdatesResult::Failed == m_materialSourceData.ApplyVersionUpdates(m_absolutePath)) + { + AZ_Error("MaterialDocument", false, "Material source data could not be auto updated to the latest version of the material type: '%s'.", m_materialSourceData.m_materialType.c_str()); + return false; + } } else if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), MaterialTypeSourceData::Extension)) { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h index c4fd263014..ceb3190f26 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h @@ -105,9 +105,7 @@ namespace MaterialEditor ////////////////////////////////////////////////////////////////////////// bool SavePropertiesToSourceData( - const AZ::IO::BasicPath& exportFolder, - AZ::RPI::MaterialSourceData& sourceData, - PropertyFilterFunction propertyFilter) const; + const AZStd::string& exportPath, AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const; bool OpenInternal(AZStd::string_view loadPath); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp index c775676e68..8dc6da077e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp @@ -98,9 +98,6 @@ namespace AZ bool SaveSourceMaterialFromEditData(const AZStd::string& path, const MaterialEditData& editData) { - AZ::IO::BasicPath exportFolder(path); - exportFolder.RemoveFilename(); - // Construct the material source data object that will be exported AZ::RPI::MaterialSourceData exportData; @@ -121,8 +118,7 @@ namespace AZ return false; } - exportData.m_materialType = - AZ::IO::PathView(editData.m_materialTypeSourcePath).LexicallyRelative(exportFolder).StringAsPosix(); + exportData.m_materialType = AtomToolsFramework::GetExteralReferencePath(path, editData.m_materialTypeSourcePath); } if (!editData.m_materialParentSourcePath.empty()) @@ -141,8 +137,7 @@ namespace AZ return false; } - exportData.m_parentMaterial = - AZ::IO::PathView(editData.m_materialParentSourcePath).LexicallyRelative(exportFolder).StringAsPosix(); + exportData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(path, editData.m_materialParentSourcePath); } // Copy all of the properties from the material asset to the source data that will be exported @@ -168,7 +163,7 @@ namespace AZ propertyValue = AZ::RPI::MaterialPropertyValue::FromAny(propertyOverrideItr->second); } - if (!AtomToolsFramework::ConvertToExportFormat(exportFolder, propertyDefinition, propertyValue)) + if (!AtomToolsFramework::ConvertToExportFormat(path, propertyDefinition, propertyValue)) { AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Failed to export: %s", path.c_str()); result = false; From b379c489b5dd28789e73587169eee92641dd2c25 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sun, 31 Oct 2021 22:55:07 -0500 Subject: [PATCH 67/97] updated comment Signed-off-by: Guthrie Adams --- .../AtomToolsFramework/Util/MaterialPropertyUtil.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h index b191e01bce..0c1ab08b24 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h @@ -51,12 +51,8 @@ namespace AtomToolsFramework //! Generate a file path from the exported file to the external reference. //! This function is to support copying or moving a folder containing materials, models, and textures without modifying the files. The - //! general case returns a relative path from the export file to the reference file. If the reference path is too different or distant - //! from the export path then it might be more difficult to work with than an asset folder relative path. For example, material types - //! that Atom provides live in a folder that should be accessible from anywhere. When materials are created in arbitrary gems and - //! project folders, a relative path to the material type would need to be updated whenever the materials are copied or moved. The same - //! thing will happen with parent materials or textures if their paths can’t be resolved. To alleviate some of this, we use the asset - //! folder relative path if the export folder relative path is too complex. An alternate solution would be to only use export folder + //! general case returns a relative path from the export file to the reference file. If the relative path is too different or distant + //! from the export path then we return the asset folder relative path. An alternate solution would be to only use export folder //! relative paths if the referenced path is in the same folder or a sub folder the assets are not generally packaged like that. AZStd::string GetExteralReferencePath( const AZStd::string& exportPath, const AZStd::string& referencePath, const uint32_t maxPathDepth = 2); From b3f3a4245b95449b69bc7ba90b2458ef3070a61a Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sun, 31 Oct 2021 23:08:16 -0500 Subject: [PATCH 68/97] updated image paths to use new function Signed-off-by: Guthrie Adams --- .../Code/Source/Util/MaterialPropertyUtil.cpp | 11 +++--- .../Code/Source/Document/MaterialDocument.cpp | 36 ++++++++----------- 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp index 6ad9506fdd..c49cd3fafb 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp @@ -170,9 +170,6 @@ namespace AtomToolsFramework const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition, AZ::RPI::MaterialPropertyValue& propertyValue) { - AZ::IO::BasicPath exportFolder(exportPath); - exportFolder.RemoveFilename(); - if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Enum && propertyValue.Is()) { const uint32_t index = propertyValue.GetValue(); @@ -192,16 +189,16 @@ namespace AtomToolsFramework if (propertyValue.Is>()) { const auto& imageAsset = propertyValue.GetValue>(); - const auto& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(imageAsset.GetId()); - propertyValue = AZ::IO::PathView(sourcePath).LexicallyRelative(exportFolder).StringAsPosix(); + const auto& imagePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(imageAsset.GetId()); + propertyValue = GetExteralReferencePath(exportPath, imagePath); return true; } if (propertyValue.Is>()) { const auto& image = propertyValue.GetValue>(); - const auto& sourcePath = image ? AZ::RPI::AssetUtils::GetSourcePathByAssetId(image->GetAssetId()) : ""; - propertyValue = AZ::IO::PathView(sourcePath).LexicallyRelative(exportFolder).StringAsPosix(); + const auto& imagePath = image ? AZ::RPI::AssetUtils::GetSourcePathByAssetId(image->GetAssetId()) : ""; + propertyValue = GetExteralReferencePath(exportPath, imagePath); return true; } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 2a0dcb36c2..c60da850a5 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -235,12 +235,10 @@ namespace MaterialEditor sourceData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(m_absolutePath, m_materialSourceData.m_parentMaterial); // populate sourceData with modified or overwritten properties - const bool savedProperties = SavePropertiesToSourceData( - m_absolutePath, sourceData, - [](const AtomToolsFramework::DynamicProperty& property) - { - return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue); - }); + const bool savedProperties = SavePropertiesToSourceData(m_absolutePath, sourceData, [](const AtomToolsFramework::DynamicProperty& property) + { + return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue); + }); if (!savedProperties) { @@ -303,16 +301,13 @@ namespace MaterialEditor MaterialSourceData sourceData; sourceData.m_materialTypeVersion = m_materialAsset->GetMaterialTypeAsset()->GetVersion(); sourceData.m_materialType = AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_materialType); - sourceData.m_parentMaterial = - AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_parentMaterial); + sourceData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_parentMaterial); // populate sourceData with modified or overwritten properties - const bool savedProperties = SavePropertiesToSourceData( - normalizedSavePath, sourceData, - [](const AtomToolsFramework::DynamicProperty& property) - { - return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue); - }); + const bool savedProperties = SavePropertiesToSourceData(normalizedSavePath, sourceData, [](const AtomToolsFramework::DynamicProperty& property) + { + return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue); + }); if (!savedProperties) { @@ -378,17 +373,14 @@ namespace MaterialEditor // Only assign a parent path if the source was a .material if (AzFramework::StringFunc::Path::IsExtension(m_relativePath.c_str(), MaterialSourceData::Extension)) { - sourceData.m_parentMaterial = - AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_parentMaterial); + sourceData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_absolutePath); } // populate sourceData with modified properties - const bool savedProperties = SavePropertiesToSourceData( - normalizedSavePath, sourceData, - [](const AtomToolsFramework::DynamicProperty& property) - { - return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_originalValue); - }); + const bool savedProperties = SavePropertiesToSourceData(normalizedSavePath, sourceData, [](const AtomToolsFramework::DynamicProperty& property) + { + return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_originalValue); + }); if (!savedProperties) { From 1689b880fe27a3564ea0ad1003a94fcb365aae00 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sun, 31 Oct 2021 23:28:15 -0500 Subject: [PATCH 69/97] added version to material component exporter deleted unnecessary checks Signed-off-by: Guthrie Adams --- .../Material/EditorMaterialComponentUtil.cpp | 49 ++++--------------- 1 file changed, 10 insertions(+), 39 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp index 8dc6da077e..0fd7b7164d 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp @@ -98,47 +98,18 @@ namespace AZ bool SaveSourceMaterialFromEditData(const AZStd::string& path, const MaterialEditData& editData) { + if (path.empty() || !editData.m_materialAsset.IsReady() || !editData.m_materialTypeAsset.IsReady() || + editData.m_materialTypeSourcePath.empty()) + { + AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Can not export: %s", path.c_str()); + return false; + } + // Construct the material source data object that will be exported AZ::RPI::MaterialSourceData exportData; - - // Converting absolute material paths to relative paths - if (!editData.m_materialTypeSourcePath.empty()) - { - bool result = false; - AZ::Data::AssetInfo info; - AZStd::string watchFolder; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult( - result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, - editData.m_materialTypeSourcePath.c_str(), info, watchFolder); - if (!result) - { - AZ_Error( - "AZ::Render::EditorMaterialComponentUtil", false, - "Failed to get material type source file info while attempting to export: %s", path.c_str()); - return false; - } - - exportData.m_materialType = AtomToolsFramework::GetExteralReferencePath(path, editData.m_materialTypeSourcePath); - } - - if (!editData.m_materialParentSourcePath.empty()) - { - bool result = false; - AZ::Data::AssetInfo info; - AZStd::string watchFolder; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult( - result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, - editData.m_materialParentSourcePath.c_str(), info, watchFolder); - if (!result) - { - AZ_Error( - "AZ::Render::EditorMaterialComponentUtil", false, - "Failed to get parent material source file info while attempting to export: %s", path.c_str()); - return false; - } - - exportData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(path, editData.m_materialParentSourcePath); - } + exportData.m_materialTypeVersion = editData.m_materialTypeAsset->GetVersion(); + exportData.m_materialType = AtomToolsFramework::GetExteralReferencePath(path, editData.m_materialTypeSourcePath); + exportData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(path, editData.m_materialParentSourcePath); // Copy all of the properties from the material asset to the source data that will be exported bool result = true; From 7d51912a6e315b06dc08d03a8a7b4734f47556a0 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 1 Nov 2021 20:33:21 -0500 Subject: [PATCH 70/97] updated comments Signed-off-by: Guthrie Adams --- .../AtomToolsFramework/Util/MaterialPropertyUtil.h | 14 +++++++++----- .../Code/Source/Document/MaterialDocument.cpp | 12 +++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h index 0c1ab08b24..08f59f9e0b 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h @@ -36,7 +36,7 @@ namespace AtomToolsFramework //! Convert and assign material property meta data fields to editor dynamic property configuration void ConvertToPropertyConfig(AtomToolsFramework::DynamicPropertyConfig& propertyConfig, const AZ::RPI::MaterialPropertyDynamicMetadata& propertyMetaData); - //! Convert and assign editor dynamic property configuration fields to material property meta data + //! Convert and assign editor dynamic property configuration fields to material property meta data void ConvertToPropertyMetaData(AZ::RPI::MaterialPropertyDynamicMetadata& propertyMetaData, const AtomToolsFramework::DynamicPropertyConfig& propertyConfig); //! Compare equality of data types and values of editor property stored in AZStd::any @@ -44,16 +44,20 @@ namespace AtomToolsFramework //! Convert the property value into the format that will be stored in the source data //! This is primarily needed to support conversions of special types like enums and images + //! @param exportPath absolute path of the file being saved + //! @param propertyDefinition describes type information and other details about propertyValue + //! @param propertyValue the value being converted before saving bool ConvertToExportFormat( const AZStd::string& exportPath, const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition, AZ::RPI::MaterialPropertyValue& propertyValue); //! Generate a file path from the exported file to the external reference. - //! This function is to support copying or moving a folder containing materials, models, and textures without modifying the files. The - //! general case returns a relative path from the export file to the reference file. If the relative path is too different or distant - //! from the export path then we return the asset folder relative path. An alternate solution would be to only use export folder - //! relative paths if the referenced path is in the same folder or a sub folder the assets are not generally packaged like that. + //! This function returns a relative path from the export file to the reference file. + //! If the relative path is too different or distant from the export path then we return the asset folder relative path. + //! @param exportPath absolute path of the file being saved + //! @param referencePath absolute path of a file that will be treated as an external reference + //! @param maxPathDepth the maximum relative depth or number of parent or child folders between the export path and the reference path AZStd::string GetExteralReferencePath( const AZStd::string& exportPath, const AZStd::string& referencePath, const uint32_t maxPathDepth = 2); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index c60da850a5..ea97a3f2c0 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -658,8 +658,8 @@ namespace MaterialEditor return false; } - // We must also always load the material type data for a complete, ordered set of the - // groups and properties that will be needed for comparison and building the inspector + // We always need the absolute path for the material type and parent material to load source data and resolving + // relative paths when saving. This will convert and store them as absolute paths for use within the document. if (!m_materialSourceData.m_parentMaterial.empty()) { m_materialSourceData.m_parentMaterial = @@ -671,6 +671,7 @@ namespace MaterialEditor m_materialSourceData.m_materialType = AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_materialType); } + // Load the material type source data which provides the layout and default values of all of the properties auto materialTypeOutcome = MaterialUtils::LoadMaterialTypeSourceData(m_materialSourceData.m_materialType); if (!materialTypeOutcome.IsSuccess()) { @@ -687,7 +688,9 @@ namespace MaterialEditor } else if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), MaterialTypeSourceData::Extension)) { - // Load the material type source data, which will be used for enumerating properties and building material source data + // A material document can be created or loaded from material or material type source data. If we are attempting to load + // material type source data then the material source data object can be created just by referencing the document path as the + // material type path. auto materialTypeOutcome = MaterialUtils::LoadMaterialTypeSourceData(m_absolutePath); if (!materialTypeOutcome.IsSuccess()) { @@ -696,8 +699,7 @@ namespace MaterialEditor } m_materialTypeSourceData = materialTypeOutcome.GetValue(); - // The document represents a material, not a material type. - // If the input data is a material type file we have to generate the material source data by referencing it. + // We are storing absolute paths in the loaded version of the source data so that the files can be resolved at all times. m_materialSourceData.m_materialType = m_absolutePath; m_materialSourceData.m_parentMaterial.clear(); } From 01ce02ffec2b4d1f21894b1202067aaa60a08cd4 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 3 Nov 2021 14:02:21 -0500 Subject: [PATCH 71/97] Added basic unit test for relative path function Moved asset system stub to RPI utils Signed-off-by: Guthrie Adams --- Gems/Atom/RPI/Code/CMakeLists.txt | 1 + .../RPI/Code/Tests/Common/RPITestFixture.h | 2 +- Gems/Atom/RPI/Code/atom_rpi_tests_files.cmake | 2 - .../AtomToolsFramework/Code/CMakeLists.txt | 28 +++++++ .../Code/Tests/AtomToolsFrameworkTest.cpp | 78 +++++++++++++++---- .../Code/atomtoolsframework_tests_files.cmake | 11 +++ Gems/Atom/Utils/Code/CMakeLists.txt | 21 +++++ .../Include/Atom/Utils}/AssetSystemStub.h | 0 .../Code/Source}/AssetSystemStub.cpp | 2 +- .../Utils/Code/atom_utils_editor_files.cmake | 12 +++ 10 files changed, 137 insertions(+), 20 deletions(-) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_tests_files.cmake rename Gems/Atom/{RPI/Code/Tests/Common => Utils/Code/Include/Atom/Utils}/AssetSystemStub.h (100%) rename Gems/Atom/{RPI/Code/Tests/Common => Utils/Code/Source}/AssetSystemStub.cpp (99%) create mode 100644 Gems/Atom/Utils/Code/atom_utils_editor_files.cmake diff --git a/Gems/Atom/RPI/Code/CMakeLists.txt b/Gems/Atom/RPI/Code/CMakeLists.txt index 521178be20..7bf47d675a 100644 --- a/Gems/Atom/RPI/Code/CMakeLists.txt +++ b/Gems/Atom/RPI/Code/CMakeLists.txt @@ -160,6 +160,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) Gem::Atom_RPI.Public Gem::Atom_RHI.Public Gem::Atom_RPI.Edit + Gem::Atom_Utils.Editor.Static ) ly_add_googletest( NAME Gem::Atom_RPI.Tests diff --git a/Gems/Atom/RPI/Code/Tests/Common/RPITestFixture.h b/Gems/Atom/RPI/Code/Tests/Common/RPITestFixture.h index 48d404d268..b745e55ee8 100644 --- a/Gems/Atom/RPI/Code/Tests/Common/RPITestFixture.h +++ b/Gems/Atom/RPI/Code/Tests/Common/RPITestFixture.h @@ -21,7 +21,7 @@ #include #include #include -#include +#include namespace UnitTest { diff --git a/Gems/Atom/RPI/Code/atom_rpi_tests_files.cmake b/Gems/Atom/RPI/Code/atom_rpi_tests_files.cmake index e99e4e456b..5d67948ac8 100644 --- a/Gems/Atom/RPI/Code/atom_rpi_tests_files.cmake +++ b/Gems/Atom/RPI/Code/atom_rpi_tests_files.cmake @@ -10,8 +10,6 @@ set(FILES Tests/Buffer/BufferTests.cpp Tests/Common/AssetManagerTestFixture.cpp Tests/Common/AssetManagerTestFixture.h - Tests/Common/AssetSystemStub.cpp - Tests/Common/AssetSystemStub.h Tests/Common/ErrorMessageFinder.cpp Tests/Common/ErrorMessageFinder.h Tests/Common/ErrorMessageFinderTests.cpp diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt b/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt index e64c9b80e7..bb2ac1f513 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt @@ -61,3 +61,31 @@ ly_add_target( PRIVATE Gem::AtomToolsFramework.Static ) + +################################################################################ +# Tests +################################################################################ +if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) + + ly_add_target( + NAME AtomToolsFramework.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} + NAMESPACE Gem + FILES_CMAKE + atomtoolsframework_tests_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + . + Tests + BUILD_DEPENDENCIES + PRIVATE + AZ::AzTest + AZ::AzTestShared + Gem::AtomToolsFramework.Static + Gem::Atom_Utils.Editor.Static + ) + + ly_add_googletest( + NAME Gem::AtomToolsFramework.Tests + ) + +endif() \ No newline at end of file diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/AtomToolsFrameworkTest.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/AtomToolsFrameworkTest.cpp index aee8e2a775..349c2b9ced 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/AtomToolsFrameworkTest.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/AtomToolsFrameworkTest.cpp @@ -7,25 +7,71 @@ */ #include +#include +#include -class AtomToolsFrameworkTest - : public ::testing::Test +namespace UnitTest { -protected: - void SetUp() override + class AtomToolsFrameworkTest : public ::testing::Test { + protected: + void SetUp() override + { + if (!AZ::AllocatorInstance::IsReady()) + { + AZ::AllocatorInstance::Create(AZ::SystemAllocator::Descriptor()); + } + m_assetSystemStub.Activate(); + + RegisterSourceAsset("objects/upgrades/materials/supercondor.material"); + RegisterSourceAsset("materials/condor.material"); + RegisterSourceAsset("materials/talisman.material"); + RegisterSourceAsset("materials/city.material"); + RegisterSourceAsset("materials/totem.material"); + RegisterSourceAsset("textures/orange.png"); + RegisterSourceAsset("textures/red.png"); + RegisterSourceAsset("textures/gold.png"); + RegisterSourceAsset("textures/fuzz.png"); + } + + void TearDown() override + { + m_assetSystemStub.Deactivate(); + + if (AZ::AllocatorInstance::IsReady()) + { + AZ::AllocatorInstance::Destroy(); + } + } + + void RegisterSourceAsset(const AZStd::string& path) + { + const AZ::IO::BasicPath assetRootPath = AZ::IO::PathView(m_assetRoot).LexicallyNormal(); + const AZ::IO::BasicPath normalizedPath = AZ::IO::BasicPath(assetRootPath).Append(path).LexicallyNormal(); + + AZ::Data::AssetInfo assetInfo = {}; + assetInfo.m_assetId = AZ::Uuid::CreateRandom(); + assetInfo.m_relativePath = normalizedPath.LexicallyRelative(assetRootPath).StringAsPosix(); + m_assetSystemStub.RegisterSourceInfo(normalizedPath.StringAsPosix().c_str(), assetInfo, assetRootPath.StringAsPosix().c_str()); + } + + static constexpr const char* m_assetRoot = "d:/project/assets/"; + AssetSystemStub m_assetSystemStub; + }; + + TEST_F(AtomToolsFrameworkTest, GetExteralReferencePath_Succeeds) + { + ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("", "", 2), ""); + ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/materials/condor.material", "", 2), ""); + ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/materials/talisman.material", "", 2), ""); + ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/materials/talisman.material", "d:/project/assets/textures/gold.png", 2), "../textures/gold.png"); + ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/materials/talisman.material", "d:/project/assets/textures/gold.png", 0), "textures/gold.png"); + ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/objects/upgrades/materials/supercondor.material", "d:/project/assets/materials/condor.material", 3), "../../../materials/condor.material"); + ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/objects/upgrades/materials/supercondor.material", "d:/project/assets/materials/condor.material", 2), "materials/condor.material"); + ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/objects/upgrades/materials/supercondor.material", "d:/project/assets/materials/condor.material", 1), "materials/condor.material"); + ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/objects/upgrades/materials/supercondor.material", "d:/project/assets/materials/condor.material", 0), "materials/condor.material"); } - void TearDown() override - { - - } -}; - -TEST_F(AtomToolsFrameworkTest, SanityTest) -{ - ASSERT_TRUE(true); -} - -AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); + AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); +} // namespace UnitTest diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_tests_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_tests_files.cmake new file mode 100644 index 0000000000..bd9ad9b3d8 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_tests_files.cmake @@ -0,0 +1,11 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +set(FILES + Tests/AtomToolsFrameworkTest.cpp +) \ No newline at end of file diff --git a/Gems/Atom/Utils/Code/CMakeLists.txt b/Gems/Atom/Utils/Code/CMakeLists.txt index 89bc8dd0a5..cbdfb016a1 100644 --- a/Gems/Atom/Utils/Code/CMakeLists.txt +++ b/Gems/Atom/Utils/Code/CMakeLists.txt @@ -27,6 +27,27 @@ ly_add_target( 3rdParty::libpng ) +if(PAL_TRAIT_BUILD_HOST_TOOLS) + + ly_add_target( + NAME Atom_Utils.Editor.Static STATIC + NAMESPACE Gem + FILES_CMAKE + atom_utils_editor_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + Source + PUBLIC + Include + BUILD_DEPENDENCIES + PRIVATE + AZ::AtomCore + AZ::AzCore + AZ::AzFramework + AZ::AzToolsFramework + ) +endif() + ################################################################################ # Tests ################################################################################ diff --git a/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/AssetSystemStub.h similarity index 100% rename from Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.h rename to Gems/Atom/Utils/Code/Include/Atom/Utils/AssetSystemStub.h diff --git a/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.cpp b/Gems/Atom/Utils/Code/Source/AssetSystemStub.cpp similarity index 99% rename from Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.cpp rename to Gems/Atom/Utils/Code/Source/AssetSystemStub.cpp index 31a46e9a6f..f026e8bcd7 100644 --- a/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.cpp +++ b/Gems/Atom/Utils/Code/Source/AssetSystemStub.cpp @@ -6,7 +6,7 @@ * */ -#include +#include #include namespace UnitTest diff --git a/Gems/Atom/Utils/Code/atom_utils_editor_files.cmake b/Gems/Atom/Utils/Code/atom_utils_editor_files.cmake new file mode 100644 index 0000000000..7d7eb10e7c --- /dev/null +++ b/Gems/Atom/Utils/Code/atom_utils_editor_files.cmake @@ -0,0 +1,12 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +set(FILES + Include/Atom/Utils/AssetSystemStub.h + Source/AssetSystemStub.cpp +) From 172ec938ccf9126c1dd332488889a957595db925 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 3 Nov 2021 17:28:12 -0500 Subject: [PATCH 72/97] moved AssetSystemStub to TestUtils folder Signed-off-by: Guthrie Adams --- Gems/Atom/RPI/Code/CMakeLists.txt | 2 +- Gems/Atom/RPI/Code/Tests/Common/RPITestFixture.h | 2 +- Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt | 2 +- .../AtomToolsFramework/Code/Tests/AtomToolsFrameworkTest.cpp | 2 +- Gems/Atom/Utils/Code/CMakeLists.txt | 2 +- .../Code/Include/Atom/Utils/{ => TestUtils}/AssetSystemStub.h | 0 .../Utils/Code/Source/{ => TestUtils}/AssetSystemStub.cpp | 2 +- Gems/Atom/Utils/Code/atom_utils_editor_files.cmake | 4 ++-- 8 files changed, 8 insertions(+), 8 deletions(-) rename Gems/Atom/Utils/Code/Include/Atom/Utils/{ => TestUtils}/AssetSystemStub.h (100%) rename Gems/Atom/Utils/Code/Source/{ => TestUtils}/AssetSystemStub.cpp (98%) diff --git a/Gems/Atom/RPI/Code/CMakeLists.txt b/Gems/Atom/RPI/Code/CMakeLists.txt index 7bf47d675a..f0459a23c2 100644 --- a/Gems/Atom/RPI/Code/CMakeLists.txt +++ b/Gems/Atom/RPI/Code/CMakeLists.txt @@ -160,7 +160,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) Gem::Atom_RPI.Public Gem::Atom_RHI.Public Gem::Atom_RPI.Edit - Gem::Atom_Utils.Editor.Static + Gem::Atom_Utils.TestUtils.Static ) ly_add_googletest( NAME Gem::Atom_RPI.Tests diff --git a/Gems/Atom/RPI/Code/Tests/Common/RPITestFixture.h b/Gems/Atom/RPI/Code/Tests/Common/RPITestFixture.h index b745e55ee8..0707528d7f 100644 --- a/Gems/Atom/RPI/Code/Tests/Common/RPITestFixture.h +++ b/Gems/Atom/RPI/Code/Tests/Common/RPITestFixture.h @@ -21,7 +21,7 @@ #include #include #include -#include +#include namespace UnitTest { diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt b/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt index bb2ac1f513..40c8d7956e 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt @@ -81,7 +81,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) AZ::AzTest AZ::AzTestShared Gem::AtomToolsFramework.Static - Gem::Atom_Utils.Editor.Static + Gem::Atom_Utils.TestUtils.Static ) ly_add_googletest( diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/AtomToolsFrameworkTest.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/AtomToolsFrameworkTest.cpp index 349c2b9ced..df16cfbc43 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/AtomToolsFrameworkTest.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/AtomToolsFrameworkTest.cpp @@ -7,7 +7,7 @@ */ #include -#include +#include #include namespace UnitTest diff --git a/Gems/Atom/Utils/Code/CMakeLists.txt b/Gems/Atom/Utils/Code/CMakeLists.txt index cbdfb016a1..90d7ce501b 100644 --- a/Gems/Atom/Utils/Code/CMakeLists.txt +++ b/Gems/Atom/Utils/Code/CMakeLists.txt @@ -30,7 +30,7 @@ ly_add_target( if(PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( - NAME Atom_Utils.Editor.Static STATIC + NAME Atom_Utils.TestUtils.Static STATIC NAMESPACE Gem FILES_CMAKE atom_utils_editor_files.cmake diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/AssetSystemStub.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/TestUtils/AssetSystemStub.h similarity index 100% rename from Gems/Atom/Utils/Code/Include/Atom/Utils/AssetSystemStub.h rename to Gems/Atom/Utils/Code/Include/Atom/Utils/TestUtils/AssetSystemStub.h diff --git a/Gems/Atom/Utils/Code/Source/AssetSystemStub.cpp b/Gems/Atom/Utils/Code/Source/TestUtils/AssetSystemStub.cpp similarity index 98% rename from Gems/Atom/Utils/Code/Source/AssetSystemStub.cpp rename to Gems/Atom/Utils/Code/Source/TestUtils/AssetSystemStub.cpp index f026e8bcd7..d57969ea9c 100644 --- a/Gems/Atom/Utils/Code/Source/AssetSystemStub.cpp +++ b/Gems/Atom/Utils/Code/Source/TestUtils/AssetSystemStub.cpp @@ -6,7 +6,7 @@ * */ -#include +#include #include namespace UnitTest diff --git a/Gems/Atom/Utils/Code/atom_utils_editor_files.cmake b/Gems/Atom/Utils/Code/atom_utils_editor_files.cmake index 7d7eb10e7c..6c4202fe09 100644 --- a/Gems/Atom/Utils/Code/atom_utils_editor_files.cmake +++ b/Gems/Atom/Utils/Code/atom_utils_editor_files.cmake @@ -7,6 +7,6 @@ # set(FILES - Include/Atom/Utils/AssetSystemStub.h - Source/AssetSystemStub.cpp + Include/Atom/Utils/TestUtils/AssetSystemStub.h + Source/TestUtils/AssetSystemStub.cpp ) From 198f225bbec7049fe71d4886d188c3df16c52d72 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 10 Nov 2021 14:42:55 -0600 Subject: [PATCH 73/97] Updating parent path usage has part of cherry picked from stabilization combining source data changes with relative path changes Signed-off-by: Guthrie Adams --- .../Code/Source/Document/MaterialDocument.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index ea97a3f2c0..8635d1eb3e 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -742,25 +742,24 @@ namespace MaterialEditor if (!m_materialSourceData.m_parentMaterial.empty()) { AZ::RPI::MaterialSourceData parentMaterialSourceData; - const auto parentMaterialFilePath = AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_parentMaterial); - if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentMaterialFilePath, parentMaterialSourceData)) + if (!AZ::RPI::JsonUtils::LoadObjectFromFile(m_materialSourceData.m_parentMaterial, parentMaterialSourceData)) { - AZ_Error("MaterialDocument", false, "Material parent source data could not be loaded for: '%s'.", parentMaterialFilePath.c_str()); + AZ_Error("MaterialDocument", false, "Material parent source data could not be loaded for: '%s'.", m_materialSourceData.m_parentMaterial.c_str()); return false; } - const auto parentMaterialAssetIdResult = AssetUtils::MakeAssetId(parentMaterialFilePath, 0); + const auto parentMaterialAssetIdResult = AssetUtils::MakeAssetId(m_materialSourceData.m_parentMaterial, 0); if (!parentMaterialAssetIdResult) { - AZ_Error("MaterialDocument", false, "Material parent asset ID could not be created: '%s'.", parentMaterialFilePath.c_str()); + AZ_Error("MaterialDocument", false, "Material parent asset ID could not be created: '%s'.", m_materialSourceData.m_parentMaterial.c_str()); return false; } auto parentMaterialAssetResult = parentMaterialSourceData.CreateMaterialAssetFromSourceData( - parentMaterialAssetIdResult.GetValue(), parentMaterialFilePath, true, true); + parentMaterialAssetIdResult.GetValue(), m_materialSourceData.m_parentMaterial, true, true); if (!parentMaterialAssetResult) { - AZ_Error("MaterialDocument", false, "Material parent asset could not be created from source data: '%s'.", parentMaterialFilePath.c_str()); + AZ_Error("MaterialDocument", false, "Material parent asset could not be created from source data: '%s'.", m_materialSourceData.m_parentMaterial.c_str()); return false; } From bceadf7597a4af57d37a18c4cb2f81b5e840dbb6 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 12 Nov 2021 08:40:10 -0800 Subject: [PATCH 74/97] Fixes for CMake 3.22rc (#5314) (#5580) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Platform/Common/MSVC/Configurations_msvc.cmake | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index a4d8533626..66a5b7b01f 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -139,11 +139,20 @@ endif() # Configure system includes ly_set(LY_CXX_SYSTEM_INCLUDE_CONFIGURATION_FLAG - /experimental:external # Turns on "external" headers feature for MSVC compilers + /experimental:external # Turns on "external" headers feature for MSVC compilers, required for MSVC < 16.10 /external:W0 # Set warning level in external headers to 0. This is used to suppress warnings 3rdParty libraries which uses the "system_includes" option in their json configuration ) + +# CMake 3.22rc added a definition for CMAKE_INCLUDE_SYSTEM_FLAG_CXX. However, its defined as "-external:I ", that space causes +# issues when trying to use in TargetIncludeSystemDirectories_unsupported.cmake. +# CMake 3.22rc has also not added support for external directories in MSVC through target_include_directories(... SYSTEM +# So we will just fix the flag that was added by 3.22rc so it works with our TargetIncludeSystemDirectories_unsupported.cmake +# Once target_include_directories(... SYSTEM is supported, we can branch and use TargetIncludeSystemDirectories_supported.cmake +# Reported this here: https://gitlab.kitware.com/cmake/cmake/-/issues/17904#note_1078281 if(NOT CMAKE_INCLUDE_SYSTEM_FLAG_CXX) - ly_set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX /external:I) + ly_set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "/external:I") +else() + string(STRIP ${CMAKE_INCLUDE_SYSTEM_FLAG_CXX} CMAKE_INCLUDE_SYSTEM_FLAG_CXX) endif() include(cmake/Platform/Common/TargetIncludeSystemDirectories_unsupported.cmake) From b44ce82435b7f737bca73bcf25e553d6c7b23f27 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 12 Nov 2021 08:40:56 -0800 Subject: [PATCH 75/97] Private dependencies are not propagated to other targets in generated install layout (#5581) * transfering private dependencies as runtime dependencies for the generated targets in the install layout Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * Update cmake/Platform/Common/Install_common.cmake Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Co-authored-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Update cmake/Platform/Common/Install_common.cmake Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Co-authored-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Co-authored-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- cmake/Platform/Common/Install_common.cmake | 30 +++++++++++++++------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index f22f4c43c9..f844b1bec9 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -167,18 +167,16 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar endforeach() list(JOIN INCLUDE_DIRECTORIES_PLACEHOLDER "\n" INCLUDE_DIRECTORIES_PLACEHOLDER) - string(REPEAT " " 8 PLACEHOLDER_INDENT) - get_target_property(RUNTIME_DEPENDENCIES_PLACEHOLDER ${TARGET_NAME} MANUALLY_ADDED_DEPENDENCIES) - if(RUNTIME_DEPENDENCIES_PLACEHOLDER) # not found properties return the name of the variable with a "-NOTFOUND" at the end, here we set it to empty if not found - set(RUNTIME_DEPENDENCIES_PLACEHOLDER "${PLACEHOLDER_INDENT}${RUNTIME_DEPENDENCIES_PLACEHOLDER}") - list(JOIN RUNTIME_DEPENDENCIES_PLACEHOLDER "\n${PLACEHOLDER_INDENT}" RUNTIME_DEPENDENCIES_PLACEHOLDER) - else() - unset(RUNTIME_DEPENDENCIES_PLACEHOLDER) - endif() - string(REPEAT " " 12 PLACEHOLDER_INDENT) get_property(interface_build_dependencies_props TARGET ${TARGET_NAME} PROPERTY LY_DELAYED_LINK) unset(INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER) + # We can have private build dependencies that contains direct or indirect runtime dependencies. + # Since imported targets cannot contain build dependencies, we need another way to propagate the runtime dependencies. + # We dont want to put such dependencies in the interface because a user can mistakenly use a symbol that is not available + # when using the engine from source (and that the author of the target didn't want to set public). + # To overcome this, we will actually expose the private build dependencies as runtime dependencies. Our runtime dependency + # algorithm will walk recursively also through static libraries and will only copy binaries to the output. + unset(RUNTIME_DEPENDENCIES_PLACEHOLDER) if(interface_build_dependencies_props) cmake_parse_arguments(build_deps "" "" "PRIVATE;PUBLIC;INTERFACE" ${interface_build_dependencies_props}) # Interface and public dependencies should always be exposed @@ -191,6 +189,8 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar if("${target_type}" STREQUAL "STATIC_LIBRARY") set(build_deps_target "${build_deps_target};${build_deps_PRIVATE}") endif() + # But we will also pass the private dependencies as runtime dependencies (note the comment above) + set(RUNTIME_DEPENDENCIES_PLACEHOLDER ${build_deps_PRIVATE}) foreach(build_dependency IN LISTS build_deps_target) # Skip wrapping produced when targets are not created in the same directory if(build_dependency) @@ -200,6 +200,18 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar endif() list(JOIN INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER "\n" INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER) + string(REPEAT " " 8 PLACEHOLDER_INDENT) + get_target_property(manually_added_dependencies ${TARGET_NAME} MANUALLY_ADDED_DEPENDENCIES) + if(manually_added_dependencies) # not found properties return the name of the variable with a "-NOTFOUND" at the end, here we set it to empty if not found + list(APPEND RUNTIME_DEPENDENCIES_PLACEHOLDER ${manually_added_dependencies}) + endif() + if(RUNTIME_DEPENDENCIES_PLACEHOLDER) + set(RUNTIME_DEPENDENCIES_PLACEHOLDER "${PLACEHOLDER_INDENT}${RUNTIME_DEPENDENCIES_PLACEHOLDER}") + list(JOIN RUNTIME_DEPENDENCIES_PLACEHOLDER "\n${PLACEHOLDER_INDENT}" RUNTIME_DEPENDENCIES_PLACEHOLDER) + else() + unset(RUNTIME_DEPENDENCIES_PLACEHOLDER) + endif() + string(REPEAT " " 8 PLACEHOLDER_INDENT) # If a target has an LY_PROJECT_NAME property, forward that property to new target get_target_property(target_project_association ${TARGET_NAME} LY_PROJECT_NAME) From c0df1846f4f34e7a8adb5191fbda213ff68a5a24 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Fri, 12 Nov 2021 11:03:43 -0800 Subject: [PATCH 76/97] Create desktop shortcut functionality (#5536) Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- .../Linux/ProjectManager_Traits_Linux.h | 1 + .../Platform/Linux/ProjectUtils_linux.cpp | 5 ++++ .../Platform/Mac/ProjectManager_Traits_Mac.h | 1 + .../Platform/Mac/ProjectUtils_mac.cpp | 5 ++++ .../Windows/ProjectManager_Traits_Windows.h | 1 + .../Platform/Windows/ProjectUtils_windows.cpp | 22 +++++++++++++++ .../Source/ProjectButtonWidget.cpp | 28 +++++++++++++++++++ .../ProjectManager/Source/ProjectUtils.cpp | 4 +-- .../ProjectManager/Source/ProjectUtils.h | 9 ++++++ 9 files changed, 74 insertions(+), 2 deletions(-) diff --git a/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Traits_Linux.h b/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Traits_Linux.h index 7c0543361f..d7edcfcf12 100644 --- a/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Traits_Linux.h +++ b/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Traits_Linux.h @@ -9,3 +9,4 @@ #pragma once #define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR false +#define AZ_TRAIT_PROJECT_MANAGER_CREATE_DESKTOP_SHORTCUT false diff --git a/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp b/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp index dc3ec55dee..a7bd2dae08 100644 --- a/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp +++ b/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp @@ -96,5 +96,10 @@ namespace O3DE::ProjectManager { return AZ::Utils::GetExecutableDirectory(); } + + AZ::Outcome CreateDesktopShortcut([[maybe_unused]] const QString& filename, [[maybe_unused]] const QString& targetPath, [[maybe_unused]] const QStringList& arguments) + { + return AZ::Failure(QObject::tr("Creating desktop shortcuts functionality not implemented for this platform yet.")); + } } // namespace ProjectUtils } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Traits_Mac.h b/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Traits_Mac.h index 7c0543361f..d7edcfcf12 100644 --- a/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Traits_Mac.h +++ b/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Traits_Mac.h @@ -9,3 +9,4 @@ #pragma once #define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR false +#define AZ_TRAIT_PROJECT_MANAGER_CREATE_DESKTOP_SHORTCUT false diff --git a/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp b/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp index b768200398..62011bf04b 100644 --- a/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp +++ b/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp @@ -137,5 +137,10 @@ namespace O3DE::ProjectManager return editorPath; } + + AZ::Outcome CreateDesktopShortcut([[maybe_unused]] const QString& filename, [[maybe_unused]] const QString& targetPath, [[maybe_unused]] const QStringList& arguments) + { + return AZ::Failure(QObject::tr("Creating desktop shortcuts functionality not implemented for this platform yet.")); + } } // namespace ProjectUtils } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Traits_Windows.h b/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Traits_Windows.h index e6422b5a77..9e4d29b58f 100644 --- a/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Traits_Windows.h +++ b/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Traits_Windows.h @@ -9,3 +9,4 @@ #pragma once #define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR true +#define AZ_TRAIT_PROJECT_MANAGER_CREATE_DESKTOP_SHORTCUT true diff --git a/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp b/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp index 871f8e9567..d08da1d5e1 100644 --- a/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp +++ b/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -146,5 +147,26 @@ namespace O3DE::ProjectManager { return AZ::Utils::GetExecutableDirectory(); } + + AZ::Outcome CreateDesktopShortcut(const QString& filename, const QString& targetPath, const QStringList& arguments) + { + const QString cmd{"powershell.exe"}; + const QString desktopPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); + const QString shortcutPath = QString("%1/%2.lnk").arg(desktopPath).arg(filename); + const QString arg = QString("$s=(New-Object -COM WScript.Shell).CreateShortcut('%1');$s.TargetPath='%2';$s.Arguments='%3';$s.Save();") + .arg(shortcutPath) + .arg(targetPath) + .arg(arguments.join(' ')); + auto createShortcutResult = ExecuteCommandResult(cmd, QStringList{"-Command", arg}, QProcessEnvironment::systemEnvironment()); + if (!createShortcutResult.IsSuccess()) + { + return AZ::Failure(QObject::tr("Failed to create desktop shortcut %1

" + "Please verify you have permission to create files at the specified location.

%2") + .arg(shortcutPath) + .arg(createShortcutResult.GetError())); + } + + return AZ::Success(QObject::tr("Desktop shortcut created at
%2").arg(desktopPath).arg(shortcutPath)); + } } // namespace ProjectUtils } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp index c425c344e1..98916cccf6 100644 --- a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp @@ -8,7 +8,11 @@ #include #include +#include +#include #include +#include +#include #include #include @@ -23,6 +27,7 @@ #include #include #include +#include namespace O3DE::ProjectManager { @@ -205,6 +210,29 @@ namespace O3DE::ProjectManager { AzQtComponents::ShowFileOnDesktop(m_projectInfo.m_path); }); + +#if AZ_TRAIT_PROJECT_MANAGER_CREATE_DESKTOP_SHORTCUT + menu->addAction(tr("Create Editor desktop shortcut..."), this, [this]() + { + AZ::IO::FixedMaxPath executableDirectory = ProjectUtils::GetEditorDirectory(); + AZStd::string executableFilename = "Editor"; + AZ::IO::FixedMaxPath editorExecutablePath = executableDirectory / (executableFilename + AZ_TRAIT_OS_EXECUTABLE_EXTENSION); + + const QString shortcutName = QString("%1 Editor").arg(m_projectInfo.m_displayName); + const QString arg = QString("--regset=\"/Amazon/AzCore/Bootstrap/project_path=%1\"").arg(m_projectInfo.m_path); + + auto result = ProjectUtils::CreateDesktopShortcut(shortcutName, editorExecutablePath.c_str(), { arg }); + if(result.IsSuccess()) + { + QMessageBox::information(this, tr("Desktop Shortcut Created"), result.GetValue()); + } + else + { + QMessageBox::critical(this, tr("Failed to create shortcut"), result.GetError()); + } + }); +#endif // AZ_TRAIT_PROJECT_MANAGER_CREATE_DESKTOP_SHORTCUT + menu->addSeparator(); menu->addAction(tr("Duplicate"), this, [this]() { emit CopyProject(m_projectInfo); }); menu->addSeparator(); diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp index bb2bcd070e..4a0e1c153c 100644 --- a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp @@ -628,11 +628,11 @@ namespace O3DE::ProjectManager return AZ::Failure(QObject::tr("Process for command '%1' timed out at %2 seconds").arg(cmd).arg(commandTimeoutSeconds)); } int resultCode = execProcess.exitCode(); + QString resultOutput = execProcess.readAllStandardOutput(); if (resultCode != 0) { - return AZ::Failure(QObject::tr("Process for command '%1' failed (result code %2").arg(cmd).arg(resultCode)); + return AZ::Failure(QObject::tr("Process for command '%1' failed (result code %2) %3").arg(cmd).arg(resultCode).arg(resultOutput)); } - QString resultOutput = execProcess.readAllStandardOutput(); return AZ::Success(resultOutput); } diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.h b/Code/Tools/ProjectManager/Source/ProjectUtils.h index 890d50d2de..ee605b5117 100644 --- a/Code/Tools/ProjectManager/Source/ProjectUtils.h +++ b/Code/Tools/ProjectManager/Source/ProjectUtils.h @@ -68,6 +68,15 @@ namespace O3DE::ProjectManager AZ::Outcome GetProjectBuildPath(const QString& projectPath); AZ::Outcome OpenCMakeGUI(const QString& projectPath); AZ::Outcome RunGetPythonScript(const QString& enginePath); + + /** + * Create a desktop shortcut. + * @param filename the name of the desktop shorcut file + * @param target the path to the target to run + * @param arguments the argument list to provide to the target + * @return AZ::Outcome with the command result on success + */ + AZ::Outcome CreateDesktopShortcut(const QString& filename, const QString& targetPath, const QStringList& arguments); AZ::IO::FixedMaxPath GetEditorDirectory(); From b0dfe26232b318e520887af65cd579ec87016636 Mon Sep 17 00:00:00 2001 From: galibzon <66021303+galibzon@users.noreply.github.com> Date: Fri, 12 Nov 2021 13:51:07 -0600 Subject: [PATCH 77/97] The Build Time Stamp of ShaderAsset And (#5373) * The Build Time Stamp of ShaderAsset And ShaderVariantAsset Should Be Based On GetTimeUTCMilliSecond() GetTimeNowMicroseconds() is useful to measure time stamp differences. GetTimeUTCMilliSecond() is for time stamps based on absolute clock/wall time. * Updated DiffuseGlobalIllumination precompiled shaders Co-authored-by: dmcdiar Signed-off-by: galibzon <66021303+galibzon@users.noreply.github.com> --- .../AzslShaderBuilderSystemComponent.cpp | 4 ++-- .../Code/Source/Editor/ShaderAssetBuilder.cpp | 10 +++++----- .../Editor/ShaderVariantAssetBuilder.cpp | 2 +- .../Source/Editor/ShaderVariantAssetBuilder.h | 2 +- .../diffuseprobegridblenddistance.azshader | Bin 77447 -> 77447 bytes ...begridblenddistance_dx12_0.azshadervariant | Bin 8258 -> 8258 bytes ...begridblenddistance_null_0.azshadervariant | Bin 486 -> 486 bytes ...gridblenddistance_vulkan_0.azshadervariant | Bin 8286 -> 8286 bytes .../diffuseprobegridblendirradiance.azshader | Bin 77491 -> 77491 bytes ...gridblendirradiance_dx12_0.azshadervariant | Bin 9034 -> 9034 bytes ...gridblendirradiance_null_0.azshadervariant | Bin 486 -> 486 bytes ...idblendirradiance_vulkan_0.azshadervariant | Bin 10002 -> 10002 bytes ...iffuseprobegridborderupdatecolumn.azshader | Bin 27583 -> 27583 bytes ...dborderupdatecolumn_dx12_0.azshadervariant | Bin 4522 -> 4522 bytes ...dborderupdatecolumn_null_0.azshadervariant | Bin 486 -> 486 bytes ...orderupdatecolumn_vulkan_0.azshadervariant | Bin 2701 -> 2701 bytes .../diffuseprobegridborderupdaterow.azshader | Bin 27580 -> 27580 bytes ...gridborderupdaterow_dx12_0.azshadervariant | Bin 4338 -> 4338 bytes ...gridborderupdaterow_null_0.azshadervariant | Bin 486 -> 486 bytes ...idborderupdaterow_vulkan_0.azshadervariant | Bin 2222 -> 2222 bytes .../diffuseprobegridclassification.azshader | Bin 74952 -> 74952 bytes ...egridclassification_dx12_0.azshadervariant | Bin 6166 -> 6166 bytes ...egridclassification_null_0.azshadervariant | Bin 486 -> 486 bytes ...ridclassification_vulkan_0.azshadervariant | Bin 4962 -> 4962 bytes .../diffuseprobegridraytracing.azshader | Bin 142100 -> 142100 bytes ...probegridraytracing_dx12_0.azshadervariant | Bin 31950 -> 32042 bytes ...probegridraytracing_null_0.azshadervariant | Bin 486 -> 486 bytes ...obegridraytracing_vulkan_0.azshadervariant | Bin 34448 -> 34600 bytes ...fuseprobegridraytracingclosesthit.azshader | Bin 142110 -> 142110 bytes ...aytracingclosesthit_dx12_0.azshadervariant | Bin 13094 -> 13094 bytes ...aytracingclosesthit_null_0.azshadervariant | Bin 486 -> 486 bytes ...tracingclosesthit_vulkan_0.azshadervariant | Bin 5404 -> 5404 bytes .../diffuseprobegridraytracingmiss.azshader | Bin 142104 -> 142104 bytes ...egridraytracingmiss_dx12_0.azshadervariant | Bin 13262 -> 13262 bytes ...egridraytracingmiss_null_0.azshadervariant | Bin 486 -> 486 bytes ...ridraytracingmiss_vulkan_0.azshadervariant | Bin 6396 -> 6396 bytes .../diffuseprobegridrelocation.azshader | Bin 77960 -> 77960 bytes ...probegridrelocation_dx12_0.azshadervariant | Bin 8046 -> 8046 bytes ...probegridrelocation_null_0.azshadervariant | Bin 486 -> 486 bytes ...obegridrelocation_vulkan_0.azshadervariant | Bin 9442 -> 9442 bytes .../diffuseprobegridrender.azshader | Bin 203892 -> 218052 bytes ...fuseprobegridrender_dx12_0.azshadervariant | Bin 30799 -> 30631 bytes ...fuseprobegridrender_null_0.azshadervariant | Bin 589 -> 589 bytes ...seprobegridrender_vulkan_0.azshadervariant | Bin 22565 -> 22565 bytes .../Shader/ShaderVariantAssetCreator.h | 2 +- .../Atom/RPI.Reflect/Shader/ShaderAsset.h | 2 +- .../RPI.Reflect/Shader/ShaderVariantAsset.h | 4 ++-- .../Shader/ShaderVariantAssetCreator.cpp | 2 +- .../Code/Source/RPI.Public/Shader/Shader.cpp | 8 ++++---- .../RPI.Reflect/Shader/ShaderVariantAsset.cpp | 2 +- 50 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp index e41c04a0be..99b7c814d1 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp @@ -82,7 +82,7 @@ namespace AZ // Register Shader Asset Builder AssetBuilderSDK::AssetBuilderDesc shaderAssetBuilderDescriptor; shaderAssetBuilderDescriptor.m_name = "Shader Asset Builder"; - shaderAssetBuilderDescriptor.m_version = 107; // Required .azsl extension in .shader file references + shaderAssetBuilderDescriptor.m_version = 108; // The Build Time Stamp of ShaderAsset And ShaderVariantAsset Should Be Based On GetTimeUTCMilliSecond() // .shader file changes trigger rebuilds shaderAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern( AZStd::string::format("*.%s", RPI::ShaderSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); shaderAssetBuilderDescriptor.m_busId = azrtti_typeid(); @@ -108,7 +108,7 @@ namespace AZ shaderVariantAssetBuilderDescriptor.m_name = "Shader Variant Asset Builder"; // Both "Shader Variant Asset Builder" and "Shader Asset Builder" produce ShaderVariantAsset products. If you update // ShaderVariantAsset you will need to update BOTH version numbers, not just "Shader Variant Asset Builder". - shaderVariantAssetBuilderDescriptor.m_version = 26; // [AZSL] Changing inlineConstant to rootConstant keyword work. + shaderVariantAssetBuilderDescriptor.m_version = 27; // The Build Time Stamp of ShaderAsset And ShaderVariantAsset Should Be Based On GetTimeUTCMilliSecond(). shaderVariantAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string::format("*.%s", RPI::ShaderVariantListSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); shaderVariantAssetBuilderDescriptor.m_busId = azrtti_typeid(); shaderVariantAssetBuilderDescriptor.m_createJobFunction = AZStd::bind(&ShaderVariantAssetBuilder::CreateJobs, &m_shaderVariantAssetBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp index 89e202a4bc..e431b74282 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp @@ -162,7 +162,7 @@ namespace AZ // has the same value, because later the ShaderVariantTreeAsset job will fetch this value from the local ShaderAsset // which could cross platforms (i.e. building an android ShaderVariantTreeAsset on PC would fetch the tiemstamp from // the PC's ShaderAsset). - AZStd::sys_time_t shaderAssetBuildTimestamp = AZStd::GetTimeNowMicroSecond(); + AZ::u64 shaderAssetBuildTimestamp = AZStd::GetTimeUTCMilliSecond(); // Need to get the name of the azsl file from the .shader source asset, to be able to declare a dependency to SRG Layout Job. // and the macro options to preprocess. @@ -229,8 +229,8 @@ namespace AZ } // for all request.m_enabledPlatforms AZ_TracePrintf( - ShaderAssetBuilderName, "CreateJobs for %s took %llu microseconds", shaderAssetSourceFileFullPath.c_str(), - AZStd::GetTimeNowMicroSecond() - shaderAssetBuildTimestamp); + ShaderAssetBuilderName, "CreateJobs for %s took %llu milliseconds", shaderAssetSourceFileFullPath.c_str(), + AZStd::GetTimeUTCMilliSecond() - shaderAssetBuildTimestamp); response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; } @@ -355,8 +355,8 @@ namespace AZ return; } - // Get the time stamp string as sys_time_t, and also convert back to string to make sure it was converted correctly. - AZStd::sys_time_t shaderAssetBuildTimestamp = 0; + // Get the time stamp string as u64, and also convert back to string to make sure it was converted correctly. + AZ::u64 shaderAssetBuildTimestamp = 0; auto shaderAssetBuildTimestampIterator = request.m_jobDescription.m_jobParameters.find(ShaderAssetBuildTimestampParam); if (shaderAssetBuildTimestampIterator != request.m_jobDescription.m_jobParameters.end()) { diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index bb40baca7d..5eaa0d9ddb 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -765,7 +765,7 @@ namespace AZ return; } - const AZStd::sys_time_t shaderVariantAssetBuildTimestamp = AZStd::GetTimeNowMicroSecond(); + const AZ::u64 shaderVariantAssetBuildTimestamp = AZStd::GetTimeUTCMilliSecond(); auto supervariantList = ShaderBuilderUtility::GetSupervariantListFromShaderSourceData(shaderSourceDescriptor); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.h b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.h index 2eaf1d9d8b..b0457656af 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.h +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.h @@ -38,7 +38,7 @@ namespace AZ const AZStd::string& m_tempDirPath; //! Used to synchronize versions of the ShaderAsset and ShaderVariantAsset, //! especially during hot-reload. A (ShaderVariantAsset.timestamp) >= (ShaderAsset.timestamp). - const AZStd::sys_time_t m_assetBuildTimestamp; + const AZ::u64 m_assetBuildTimestamp; const RPI::ShaderSourceData& m_shaderSourceDataDescriptor; const RPI::ShaderOptionGroupLayout& m_shaderOptionGroupLayout; const MapOfStringToStageType& m_shaderEntryPoints; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance.azshader index 31fae5d98bb261ee35faac2489e4138379a5b952..a9b5567f6b19d075222ab9881cf3b3ff0aae7994 100644 GIT binary patch delta 197 zcmZp_%hGSXJF>B$A!A5q1tG&!~`R>+wZb~bi1Z&-jZvTS?i0X0UKX##$(JJmp7^1+Ru=81EeEc F5CH#RP;&qP delta 197 zcmZp_%hGCR;deEULvjXnnh1H;^}a@ir9Rat@<+5DZu3v==& z&pV^Cxm#z8>SXJF>B$A!A5q1tG&$DhZ@F6}v!P})Z&-jZvTS?i0X0X F1OVHsPiz1H diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_dx12_0.azshadervariant index 19e9fdfc8d23db9d1ac4b062b395258ab3eeb219..6d4b6d0fcafe1d8560e2f3087ef300047cdfb436 100644 GIT binary patch delta 36 scmX@)aL8eUnu5%=$Vy}Pv;HS`3MPMkv|*+d2Ll6Rt>EF)G7Jn103vG*;{X5v delta 36 rcmX@)aL8eUnu1KhjYUlhU%BbdWeI%yLVk@t2Ll7c+^=%kAwU`cBliut diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_null_0.azshadervariant index 43c4a615cf8f6719d802c538b340952a17738839..5d8800a6fe3f085a433044ce5befe9e60dd2c764 100644 GIT binary patch delta 36 scmaFH{ET_SDMp!Vk(I{oXZ=s?6ioj7Xv0h^4h9CsTEWAoWf&M304zxkHUIzs delta 36 rcmaFH{ET_SDMp!s8;hD2zH-x@%M$qZh5QxnJe7Lx3~@E!7ST diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_vulkan_0.azshadervariant index 75f070a03eeb2ae0c9f4f2917e2ad8ba69a7ce42..930f7898c4f3489f042e62275da78b4618124577 100644 GIT binary patch delta 36 scmccTaL-|blY-2($Vy}Pv;HS`3MPMkv|*+d2Ll6Rt>EF)G7Jn104;Y8Hvj+t delta 36 rcmccTaL-|blY&gajYUlhU%BbdWeI%yLVk@t2Ll7c+^=%kAwU`cF9Qw@ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance.azshader index 0025388bc13bae5830f46f3b79be2b4a3a0800ba..268020b431045dd424ae16fef2656c7fff34e431 100644 GIT binary patch delta 174 zcmdmdmu2%^mJNI?lRxedW@D@sJbW~AvpP!cIh4NxswME($tQ;E^j2&Z+_h8)S$|(kKR%Z!fWGjv=@^mZM zT+jMS4Z*&ry4g4A1T#k&pGkx9hvIpT41rHED7@iF{ySEFKkqitB04Q4yK>z>% delta 36 rcmX@*cFJvop0Z5AjYUlhU%BbdWeI%yLVk@t2Ll7c+^=$q!9W@SCz}nG diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_null_0.azshadervariant index 4a2b0e9944d9b41fe3c3c98f4c7607eebe0d3a2d..3253ddba376ea446e0dfb402ea83e1973fb71589 100644 GIT binary patch delta 36 scmaFH{ET_SDMp!Vk(I{oXZ=s?6ioj7Xv0h^4h9CsTEW9dBN-SN04*O5Z2$lO delta 36 rcmaFH{ET_SDMp!s8;hD2zH-x@%M$qZh5QxnJcJgMl;vEME=5 diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_vulkan_0.azshadervariant index c053a7db199279cf7ef8929b0a12157414db2ec6..c38b94c4f1f7288e2c3fe0d1bf48d2d471c17763 100644 GIT binary patch delta 36 scmbQ_H_30qH#M1Sk(I{oXZ=s?6ioj7Xv0h^4h9CsTEW9dBN-SN05iP~tN;K2 delta 36 rcmbQ_H_30qH#M1p8;hD2zH-x@%M$qZh5QxnJcJgMl;vGW`w! diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn.azshader index c507b125634fdfcdfb749d15380513cc8527c5f8..5c46d368cef5f778fecab7a7abe845a3df753804 100644 GIT binary patch delta 196 zcmdmgopJwl#tnijlGh?Djor`spV%pw{Q1#_nN}PO42-pchYxXV)?x`_Wb^Y6cTP&4 zT&Sm1U7JRB;P+NH$nUVjm_sp Ltpz9dXBz+js5DEj delta 196 zcmdmgopJwl#tnijk_9&wH7$JQraPA<@a+rvHToP33=DI>%6V+sti=+<$d=*~kX_*Tco-;ixM6WGAPp(3%Vrd26v{pRzc K)`FA!vkd@nK1;#? diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_dx12_0.azshadervariant index f60c7135977ac8215b5c78551c6f716448afb590..eb6938f8c9c8c853e2d0c06160096440aa8357fa 100644 GIT binary patch delta 36 rcmZ3byh?dPpPEE9K$-yn9)JzC delta 36 rcmZ3byh?dPpP)>^jYUlhU%BbdWeI%yLVk@t2Ll7c+^=#Tn}9R`AyN(F diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_null_0.azshadervariant index 3e810bcfb51b320702134c14db816f744549bb72..8c83c1e3ff64da49fc860a44915cbb4b8a233482 100644 GIT binary patch delta 36 rcmaFH{ET_SDMp!Vk(I{oXZ=s?6ioj7Xv0h^4h9CsTEWAIfHVUDE6ffV delta 36 rcmaFH{ET_SDMp!s8;hD2zH-x@%M$qZh5QxnJcxHUVh>E}jlY diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_vulkan_0.azshadervariant index 5918f277b577ebd0685c1b784ad68aa7808ff1fc..2fbb9ffffee14a3a04cb4c7cd6be8cae358e5e64 100644 GIT binary patch delta 36 rcmeAb?G@cn$R%?vveMZ7tpACfg2|sBZJ24r!N9;+D|q-2kY)e?4uuUn delta 36 rcmeAb?G@cn$R$&7V^Pz>S8lp!);e#7&4E$Yf}4XqGhuds i6`l+{$~t*fz&B*WP6jq`aD3SJd7a(WeF;Eq*@6JVT0(UI delta 190 zcmdmUopH}~#tnQdk_9&wH7$JQraPA<@a+rvHToP33=DI>%KL8Etj-d|$mZf)5a8#s zxt{eC8-o3eb#tuHZYGW?hYXJzOPt-jSwS>F7%Dxvo>h7COpWs} ytQJ)>Yz~aF7Tg@{nF+H4tng&uQP#<;0=^*|b~3PmgJVJ1e5;nffro(FvIPN{x<`xv diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_dx12_0.azshadervariant index d38d779696b13c4fd7f5d21a534e2003d99c0abf..4bdbdddf334d634467a889a476ef3c6f474762ec 100644 GIT binary patch delta 36 scmeyQ_(^fYH36Axk(I{oXZ=s?6ioj7Xv0h^4h9CsTEWB5`4|`&06P;7vj6}9 delta 36 rcmeyQ_(^fYH36A|8;hD2zH-x@%M$qZh5QxnJddHvnk>Ju42n diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_null_0.azshadervariant index 6d7a604701b9a849b2be3939000072f11beb9371..77668a24503e7aedabd91d13903db31149c4c835 100644 GIT binary patch delta 36 scmaFH{ET_SDMp!Vk(I{oXZ=s?6ioj7Xv0h^4h9CsTEWB5`4|`&04$vjL;wH) delta 36 rcmaFH{ET_SDMp!s8;hD2zH-x@%M$qZh5QxnJddHvnk>F0~Fz diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_vulkan_0.azshadervariant index dee941cfae644d19cb161c0826cae0801f7b7d54..fb3dd771caf01ab5c24094232f627f6568550a80 100644 GIT binary patch delta 36 scmZ1{xK41xBo3Ktk(I{oXZ=s?6ioj7Xv0h^4h9CsTEWB5`4|`&02>btzW@LL delta 36 rcmZ1{xK41xBo3K^8;hD2zH-x@%M$qZh5QxnJddHvnk>9VZRO diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification.azshader index e2e0fa90f5cb67db90fc3022210ada280ffb5e2f..eda8d533767910a172d89f101652e0ca7879c702 100644 GIT binary patch delta 195 zcmX?clI6rnmJPftlGh?Djor`spV%pw{Q1#_nN}PO42-pchwnbxti}?=$d>2mni%3d zd1JTgW&`aomC5tFq$i7LeMA+Xrp{re85+GuOnmd^b3p;ZP}$8JyQ@_;&+p=a83Pp9 ztj;&}b6$Nzwqx(>8R{HqnfE?DKgQ(; I(w8j=0H3K(AOHXW delta 195 zcmX?clI6rnmJPftk_9&wH7$JQraPA<@a+rvHToP33=DI>%IoTHR$~cbWGl$`^smUC zys=w#vw?P)%H;W7(vwBBKB9_GQ|H)q_Lo9tf^OXAb3p;ZP}$8JyQ@_;&+p=a83Pp9 zta=5o7b>u$ejt0004f5yRc$0000kGY<{` delta 36 rcmbPcFwJ1YFL9ZI8;hD2zH-x@%M$qZh5QxnJdV^?@`1Dv1rM diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_null_0.azshadervariant index 43408b26f3c17afb2a726971c1fad38f24d2fd42..f2458e692b5673dc5a2aaf5f94b5f182c0f09097 100644 GIT binary patch delta 36 ucmV+<0NelO1Lgy;$^jhKS$Q)@%}>a=5o7b>u$ejt0004f5yRc$0000lyAKWk delta 36 rcmaFH{ET_SDMp!s8;hD2zH-x@%M$qZh5QxnJdV^?@`1ED;T= diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_vulkan_0.azshadervariant index 877085446de04b3f129ebb6273698e848ee45de7..0e08e84f74b293a4499b78c9ebef97564cd11777 100644 GIT binary patch delta 36 scmaE)_DF4mo3PBa$Vy}Pv;HS`3MPMkv|*+d2Ll6Rt>EFij~Eyj04fg-+5i9m delta 36 rcmaE)_DF4mo3Kp5jYUlhU%BbdWeI%yLVk@t2Ll7c+^_Pw`al{0CS?tF diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing.azshader index 2c403c77f88b4e7213022796f694f866ba71160a..1cea4860a113c2b0f46cc9dd25931dc36f7130ab 100644 GIT binary patch delta 74 zcmV-Q0JZ;=)(Di=2(S$Vmmy*S69xf&5yQg}vnB-HrU*C=veu-YWTvwVt1h?*3a^bH gf3XRNw?Sh8J+}y}r+$CtGNcK!=c`^2m*gq}FgBDO^8f$< delta 88 zcmV-e0H^( diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_dx12_0.azshadervariant index 4bcc47ee43a6bcc8c2b33f451d22a0b963981210..5605a47e9cb0dfd9223151cdce9e306852f730c4 100644 GIT binary patch delta 10619 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 a3p+j!k^iUH^!_vo1QE7`w6@|qBL5E)baG|@ delta 10489 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 diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_null_0.azshadervariant index f173416210a73847b2e552a0e2bdab355186d34b..15f3477cb5fc4baa7b937e388fc14ec277210841 100644 GIT binary patch delta 36 scmaFH{ET_SDMp!Vk(I{oXZ=s?6ioj7Xv0h^4h9CsTEWAI1sE6@04wnhA^-pY delta 36 rcmaFH{ET_SDMp!s8;hD2zH-x@%M$qZh5QwSD#V%|IFeF6s_h diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_vulkan_0.azshadervariant index 0eb04a25b814a01e4f4fcc3fcdc1506ad4eec5d8..c2bcd4ab07c8321b12d204a54ca52efa71d5e175 100644 GIT binary patch literal 34600 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%0AmO9S^Hh#js) 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 delta 93 zcmV-j0HXh%)(D=~2(T9f8F1L5f}!e0Eu92W?dTt@F9-kt0IruAtJuV*Uu diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_dx12_0.azshadervariant index 93cfb4781977a009b6b4aa6ca9c5baacdcf9a5e4..fbd1d902517b8c614396ab7b502495eb9b881f07 100644 GIT binary patch delta 36 scmZ3Mwk&M}m$A&X$Vy}Pv;HS`3MPMkv|*+d2Ll6Rt>EFKdJGH<03+KC`Tzg` delta 36 rcmZ3Mwk&M}m$6L2jYUlhU%BbdWeI%yLVk@t2Ll7cy6KXuZvkllCT$Kl diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_null_0.azshadervariant index 4a16e24211faaa39226db82f9bd88979700313f2..483be0eceb86381caef4e4ee7ec0e1622febdc23 100644 GIT binary patch delta 36 scmaFH{ET_SDMp!Vk(I{oXZ=s?6ioj7Xv0h^4h9CsTEW9d^%xi!04#G3LI3~& delta 36 rcmaFH{ET_SDMp!s8;hD2zH-x@%M$qZh5Qb<-tR-vZJAF9i;O diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_vulkan_0.azshadervariant index df52c9c8d28c576b1905f49c9f898491ecad94aa..530eef2f102873570848ef8ead9ace35c905822e 100644 GIT binary patch delta 35 rcmbQEHAicKsLZv5{8&0cijV+6{C7 diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss.azshader index d95fd5b3b2bccd1f9153241ab9ac8bfa7dad6a3b..eddac4e2bd277eab358b589f4f556eb13486257c 100644 GIT binary patch delta 93 zcmV-j0HXhx)(Du^2(S?Z8P-{OGe^x&$hi??^Ww0XItTy&0eum}ze%$y1l^_xvFp}( z)U&c1vk$8-xCm#GqG{YrTsgDqt6vbeq;mn@rU;ux>)#HQRH?J;t6mV7=qds*&Gjp8 delta 93 zcmV-j0HXhx)(Du^2(S?Z8F1L5f}!e0Eu92W?dTt@F9-kt0IiRAaul;F1l^_x>)U=w zi30W4vk$8-xCo=LjNbjA(ZsXrt6vbeq;mn@rU<{9 delta 36 rcmX??elC5(CS#d`8;hD2zH-x@%M$qZh5Qwf*HqB0w4dL%0rz diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_null_0.azshadervariant index 40e18c215c93079ffdbe3931f9df13c625ef5468..527b42569a3e6556bc398f8232b5ed49dd11b29c 100644 GIT binary patch delta 36 scmaFH{ET_SDMp!Vk(I{oXZ=s?6ioj7Xv0h^4h9CsTEWBnJsB7n04%`{R{#J2 delta 36 rcmaFH{ET_SDMp!s8;hD2zH-x@%M$qZh5Qwf*HqB0w4dEW{1g diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_vulkan_0.azshadervariant index 34761ccf98ae556858256ecf25608fd87d6c67ed..426d9559385e16ad59d7124796ed2f712b0f7a3f 100644 GIT binary patch delta 36 scmexk_{VU=0|}XHk(I{oXZ=s?6ioj7Xv0h^4h9CsTEWBnJsB7n07O|23;+NC delta 36 rcmexk_{VU=0|}Xe8;hD2zH-x@%M$qZh5Qwf*HqB0w4dL|hJw diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader index c19020dc84df5e5bf3c02c1496d86967dce3966c..08ed61ab03bc60c102e2fc65e020bd69f1e85358 100644 GIT binary patch delta 193 zcmeBp$kOqUWdkRRdtd{JfJV zCwx`hETikEHo1C&^kf#DkEr64G&xk1mkK^x{>*ywwy*$UWZ88S{nR#BPvAi@YTZPj z7KT@cKFwmuzq&aw+(vM7%b84=lFbQU3)Lp4eE9}72gu*5$uWO@bf{N)U($A2dB$u( E02+)=ApigX delta 193 zcmeBp$kOqUWdkRRWWkL^O$%SS>CR;deEULvjXnnh1H;^}ay|Z=l~{rp+0p`2T?@-5 zCwx`hETikEHo1C&^kf#DkEr64G&yYNid3BRnrOIrTUdZFvh2EverlVmC-9&cwQeF% zi=&Ka{D%6V- diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant index a7d44b55413ad60e422335b85570eae7f8ef57ad..d1012a896f24d3fa8b0caf6aae6aaa1ff82c9b6a 100644 GIT binary patch delta 36 scmaE7_s(uZki5*b$Vy}Pv;HS`3MPMkv|*+d2Ll6Rt>ED+5)2Fs05d)gX8-^I delta 36 rcmaE7_s(uZki1O6jYUlhU%BbdWeI%yLVk@t2Ll7c+^=#y{y-W4H9ihh diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant index 82e00652163427427f0e363c96a18d7135e11918..cb730be1df5626572cc2940e80934ad279099492 100644 GIT binary patch delta 36 scmaFH{ET_SDMp!Vk(I{oXZ=s?6ioj7Xv0h^4h9CsTEW9tBp4VN04!z>I{*Lx delta 36 rcmaFH{ET_SDMp!s8;hD2zH-x@%M$qZh5QxnJda{DCw8E@loW diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant index 20b81aee6c30ce6f6956ad4c8c50292b00350df7..b58af4c47357850ecf7ba75411a1051a27ff713f 100644 GIT binary patch delta 36 scmaFl`N(s_F%_9>k(I{oXZ=s?6ioj7Xv0h^4h9CsTEW9tBp4VN06~Nf-T(jq delta 36 rcmaFl`N(s_F%_AD8;hD2zH-x@%M$qZh5QxnJda{DCw8Lxc{? diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader index aec2786540c6611090a7e2ed7a270939a8fc40a6..56009d56abb497027e6d3aea639d3d232d0799b2 100644 GIT binary patch delta 7273 zcmeHLeQZ-z6zANP^47s7N`}Omor<;ehm^66d1!B~~8pEmc-}3Tjpc-)2c?}kesEZrK?shroHPuN(s(>A7l|H8;wUuB1_OeA2@t%3nT{| zf?AubeU*e$$Hp;AWtOC*{%VdcDM*G9Vr*Se`J1noEH5mnSjobdVfhGFfd^^DRLbbR z$`EbDeP1~%%VVM5A$mD4$H<511F3;dFpMUk6>93>Eug=+XEKR*6#S?ikSxMB;IVu( z=xE&RF#&aGJlg9RN1IlJXhTn$)X1a%w}<#!lG@(ReoS=-K`VtjSq=mjk5ycT3j?IX3Mh+S@2un=Fj?R2=YV)Q$-gspxR?Q)a zzQk!;IECPBe#JPoebn|*+h-9MY#(&Bf>+s(JgqvOhxQ^EOf9!lkwN={0IKJ-!&q8z zXdXmib~|JY0H#dQkzNz5o-|^_Gbdox0F%Jp-<<-hr;`-ZibM_S&yca$@>67tfsA>rHWHI7C#k5_Mh37wI^6%#j$*^HJ7@N_B*juR^-2gaN5>72B)S# zB<6K6U%rL;O6LiV{|G!ID)cF!p`*KEMW-VQ2uz%Ib%=1g8#;+Xd^SHkUAX!u6l%EI znz@Ah}Q@)z7lOEsJ9RmH6LZvoCjd0 z^`2_>nUtP^6*-LOXv=^CdCmR}>9C@R=x~2ipD_Ob#EV8|EcU_^?5o}j9|RpHkTUu4 zryZ~$@JJnxzs<~U?t}&=sP{0ENPq}z+ts(_+9M2>@;{c=7q*F3Hy7}pDJ+@tPx_3G z9Rwo|%VIk%f10qkEaO`Cc_3Z1KakENKZ8W0<4Ms$%!#L#<^+6px3s=Fg}5b`49f2@ z(I&5GGd3~o`7uqv1nbz(KR*Bh`N_H_= zv=0g)hGvJyvh90sk?F#neb6;jrjkA?jre`*wY!e{RMNO+o9E({a~YvjQXq5F$C;rwONnJN@lldnOAE0v*@*k;=!&CsfFCF9Y516N!Su0-l? zAw#$yS|M9WU;T3oUM_X)mI<={{FX}P{o7RD>i#oH$Kku|7Ru`> crA=%%eKUretY`6 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 delta 36 rcmX@ha+YO-A(KqOjYUlhU%BbdWeI%yLVk@t2Ll7cnh*RdlYuk<7Do+? diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant index c819e57c4c029d3645581a08520aca7ccbfd19ee..47789d9b9bd602bf760bf076fe039860dbfd562b 100644 GIT binary patch delta 84 zcmV-a0IUC{umPp80kB2^2)aQPtJ5ia=5o7b>u$ejt0004f5yQ~h0001x6d>UM delta 84 zcmZ3wfpO^u#tm+a9M{AG-v;wq)ou1;?BQY*+I*XP8V|>vRaT4jbawep_G6UXJW0Zy o2Pkn##oSn?;Krh+g|FOn=duL8eIdU_pM!ycVa*5rmB~OF058KHZvX%Q diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Shader/ShaderVariantAssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Shader/ShaderVariantAssetCreator.h index fd069f21e0..488bfb09f8 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Shader/ShaderVariantAssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Shader/ShaderVariantAssetCreator.h @@ -40,7 +40,7 @@ namespace AZ //! Set the timestamp value when the ProcessJob() started. //! This is needed to synchronize between the ShaderAsset and ShaderVariantAsset when hot-reloading shaders. //! The idea is that this timestamp must be greater or equal than the ShaderAsset. - void SetBuildTimestamp(AZStd::sys_time_t buildTimestamp); + void SetBuildTimestamp(AZ::u64 buildTimestamp); //! Assigns a shaderStageFunction, which contains the byte code, to the slot dictated by the shader stage. void SetShaderFunction(RHI::ShaderStage shaderStage, RHI::Ptr shaderStageFunction); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderAsset.h index c5df9a4b51..5dc990d93a 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderAsset.h @@ -294,7 +294,7 @@ namespace AZ Name m_drawListName; //! Use to synchronize versions of the ShaderAsset and ShaderVariantTreeAsset, especially during hot-reload. - AZStd::sys_time_t m_shaderAssetBuildTimestamp = 0; + AZ::u64 m_shaderAssetBuildTimestamp = 0; /////////////////////////////////////////////////////////////////// diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantAsset.h index 66bbd7b188..5146ae370a 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantAsset.h @@ -61,7 +61,7 @@ namespace AZ //! Return the timestamp when this asset was built, and it must be >= than the timestamp of the main ShaderAsset. //! This is used to synchronize versions of the ShaderAsset and ShaderVariantAsset, especially during hot-reload. - AZStd::sys_time_t GetBuildTimestamp() const; + AZ::u64 GetBuildTimestamp() const; bool IsRootVariant() const { return m_stableId == RPI::RootShaderVariantStableId; } @@ -80,7 +80,7 @@ namespace AZ AZStd::array, RHI::ShaderStageCount> m_functionsByStage; //! Used to synchronize versions of the ShaderAsset and ShaderVariantAsset, especially during hot-reload. - AZStd::sys_time_t m_buildTimestamp = 0; + AZ::u64 m_buildTimestamp = 0; }; class ShaderVariantAssetHandler final diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Shader/ShaderVariantAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Shader/ShaderVariantAssetCreator.cpp index e0e83cfce2..5b32edc0bf 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Shader/ShaderVariantAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Shader/ShaderVariantAssetCreator.cpp @@ -92,7 +92,7 @@ namespace AZ ///////////////////////////////////////////////////////////////////// // Methods for all shader variant types - void ShaderVariantAssetCreator::SetBuildTimestamp(AZStd::sys_time_t buildTimestamp) + void ShaderVariantAssetCreator::SetBuildTimestamp(AZ::u64 buildTimestamp) { if (ValidateIsReady()) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp index a2d91fefd6..7dbeac7098 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp @@ -202,17 +202,17 @@ namespace AZ return; } AZ_Assert(m_asset->m_shaderAssetBuildTimestamp == m_reloadedRootShaderVariantAsset->GetBuildTimestamp(), - "shaderAsset timeStamp=%lld, but Root ShaderVariantAsset timeStamp=%lld", + "shaderAsset '%s' timeStamp=%lld, but Root ShaderVariantAsset timeStamp=%lld", m_asset.GetHint().c_str(), m_asset->m_shaderAssetBuildTimestamp, m_reloadedRootShaderVariantAsset->GetBuildTimestamp()); m_asset->UpdateRootShaderVariantAsset(m_supervariantIndex, m_reloadedRootShaderVariantAsset); m_reloadedRootShaderVariantAsset = {}; // Clear the temporary reference. if (ShaderReloadDebugTracker::IsEnabled()) { - auto makeTimeString = [](AZStd::sys_time_t timestamp, AZStd::sys_time_t now) + auto makeTimeString = [](AZ::u64 timestamp, AZ::u64 now) { - AZStd::sys_time_t elapsedMicroseconds = now - timestamp; - double elapsedSeconds = aznumeric_cast(elapsedMicroseconds / 1'000'000); + AZ::u64 elapsedMillis = now - timestamp; + double elapsedSeconds = aznumeric_cast(elapsedMillis / 1'000); AZStd::string timeString = AZStd::string::format("%lld (%f seconds ago)", timestamp, elapsedSeconds); return timeString; }; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp index 442fc6a79f..ec1a65a6d5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp @@ -60,7 +60,7 @@ namespace AZ } } - AZStd::sys_time_t ShaderVariantAsset::GetBuildTimestamp() const + AZ::u64 ShaderVariantAsset::GetBuildTimestamp() const { return m_buildTimestamp; } From 9898b6ee45fa715043cb5c6d163988dd56709924 Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Fri, 12 Nov 2021 13:47:30 -0800 Subject: [PATCH 78/97] Move SC runtime asset static initialization out of data loading threads Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- .../Code/Editor/View/Widgets/CanvasWidget.cpp | 7 ++-- .../ScriptCanvas/Asset/RuntimeAsset.cpp | 1 + .../Include/ScriptCanvas/Asset/RuntimeAsset.h | 3 ++ .../Asset/RuntimeAssetHandler.cpp | 2 +- .../ScriptCanvas/Execution/ExecutionState.h | 4 +++ .../Interpreted/ExecutionInterpretedAPI.cpp | 2 ++ .../Interpreted/ExecutionStateInterpreted.cpp | 33 +++++++++++++++---- .../Execution/RuntimeComponent.cpp | 23 ++++++++----- 8 files changed, 57 insertions(+), 18 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/CanvasWidget.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/CanvasWidget.cpp index e448f3ea40..dfa39b0047 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/CanvasWidget.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/CanvasWidget.cpp @@ -84,9 +84,10 @@ namespace ScriptCanvasEditor { m_assetId = assetId; - EditorGraphRequests* editorGraphRequests = EditorGraphRequestBus::FindFirstHandler(m_scriptCanvasId); - - editorGraphRequests->SetAssetId(m_assetId); + if (EditorGraphRequests* editorGraphRequests = EditorGraphRequestBus::FindFirstHandler(m_scriptCanvasId)) + { + editorGraphRequests->SetAssetId(m_assetId); + } } const GraphCanvas::ViewId& CanvasWidget::GetViewId() const diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.cpp index 0dcd8ebbbd..d55fcf7838 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.cpp @@ -59,6 +59,7 @@ namespace ScriptCanvas m_script = AZStd::move(other.m_script); m_requiredAssets = AZStd::move(other.m_requiredAssets); m_requiredScriptEvents = AZStd::move(other.m_requiredScriptEvents); + m_areStaticsInitialized = AZStd::move(other.m_areStaticsInitialized); } return *this; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.h index 24c83b20a1..cc59f90e69 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.h @@ -76,6 +76,9 @@ namespace ScriptCanvas AZStd::vector m_activationInputStorage; Execution::ActivationInputRange m_activationInputRange; + // used to initialized statics only once, and not necessarily on the loading thread + bool m_areStaticsInitialized = false; + bool RequiresStaticInitialization() const; bool RequiresDependencyConstructionParameters() const; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAssetHandler.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAssetHandler.cpp index df7b07d37b..05b6f4397b 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAssetHandler.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAssetHandler.cpp @@ -94,7 +94,6 @@ namespace ScriptCanvas RuntimeAsset* runtimeAsset = asset.GetAs(); AZ_Assert(runtimeAsset, "RuntimeAssetHandler::InitAsset This should be a Script Canvas runtime asset, as this is the only type this handler processes!"); Execution::Context::InitializeActivationData(runtimeAsset->GetData()); - Execution::InitializeInterpretedStatics(runtimeAsset->GetData()); } } @@ -157,4 +156,5 @@ namespace ScriptCanvas } } } + } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/ExecutionState.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/ExecutionState.h index 8c2f0a67c4..89ddf178f3 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/ExecutionState.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/ExecutionState.h @@ -19,6 +19,10 @@ #include #include +#if !defined(_RELEASE) +#define SCRIPT_CANVAS_RUNTIME_ASSET_CHECK +#endif + namespace AZ { class ReflectContext; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp index 4d7c8a2cda..bba56847ce 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp @@ -506,6 +506,8 @@ namespace ScriptCanvas #if defined(AZ_PROFILE_BUILD) || defined(AZ_DEBUG_BUILD) Execution::InitializeFromLuaStackFunctions(const_cast(runtimeData.m_debugMap)); #endif + AZ_WarningOnce("ScriptCanvas", !runtimeData.m_areStaticsInitialized, "ScriptCanvas runtime data already initalized"); + if (runtimeData.RequiresStaticInitialization()) { AZ::ScriptLoadResult result{}; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionStateInterpreted.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionStateInterpreted.cpp index 9224d4f9a4..a92c13ac63 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionStateInterpreted.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionStateInterpreted.cpp @@ -6,14 +6,13 @@ * */ -#include "ExecutionStateInterpreted.h" - #include #include #include - -#include "Execution/Interpreted/ExecutionStateInterpretedUtility.h" -#include "Execution/RuntimeComponent.h" +#include +#include +#include +#include namespace ExecutionStateInterpretedCpp { @@ -33,7 +32,29 @@ namespace ScriptCanvas ExecutionStateInterpreted::ExecutionStateInterpreted(const ExecutionStateConfig& config) : ExecutionState(config) , m_interpretedAsset(config.runtimeData.m_script) - {} + { + RuntimeAsset* runtimeAsset = config.asset.Get(); + +#if defined(SCRIPT_CANVAS_RUNTIME_ASSET_CHECK) + if (!runtimeAsset) + { + AZ_Error("ScriptCanvas", false + , "ExecutionStateInterpreted created with ExecutionStateConfig that contained bad runtime asset data. %s" + , config.asset.GetId().ToString().data()); + return; + } +#else + AZ_Assert(false + , "ExecutionStateInterpreted created with ExecutionStateConfig that contained bad runtime asset data. %s" + , config.asset.GetId().ToString().data()); +#endif + + if (!runtimeAsset->GetData().m_areStaticsInitialized) + { + runtimeAsset->GetData().m_areStaticsInitialized = true; + Execution::InitializeInterpretedStatics(runtimeAsset->GetData()); + } + } void ExecutionStateInterpreted::ClearLuaRegistryIndex() { diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp index 5fe5c32a48..bc37bc05f6 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp @@ -19,9 +19,13 @@ #include #include -#if !defined(_RELEASE) -#define SCRIPT_CANVAS_RUNTIME_ASSET_CHECK -#endif +#include +#include + +namespace AZ +{ + AZ_TYPE_INFO_SPECIALIZE(AZ::Data::Asset, "{D9A4EB57-198B-4A0D-B1FB-D1B11FF88C66}"); +} AZ_DECLARE_BUDGET(ScriptCanvas); @@ -112,11 +116,13 @@ namespace ScriptCanvas #if defined(SCRIPT_CANVAS_RUNTIME_ASSET_CHECK) if (!m_runtimeOverrides.m_runtimeAsset.Get()) { - AZ_Error("ScriptCanvas", false, "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run", m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data()); + AZ_Error("ScriptCanvas", false, "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run" + , m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data()); return; } #else - AZ_Assert(m_runtimeOverrides.m_runtimeAsset.Get(), "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run", m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data()); + AZ_Assert(m_runtimeOverrides.m_runtimeAsset.Get(), "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run" + , m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data()); #endif AZ_PROFILE_SCOPE(ScriptCanvas, "RuntimeComponent::InitializeExecution (%s)", m_runtimeOverrides.m_runtimeAsset.GetId().ToString().c_str()); @@ -126,11 +132,13 @@ namespace ScriptCanvas #if defined(SCRIPT_CANVAS_RUNTIME_ASSET_CHECK) if (!m_executionState) { - AZ_Error("ScriptCanvas", false, "RuntimeComponent::m_runtimeAsset AssetId: %s failed to create an execution state, possibly due to missing dependent asset, script will not run", m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data()); + AZ_Error("ScriptCanvas", false, "RuntimeComponent::m_runtimeAsset AssetId: %s failed to create an execution state, possibly due to missing dependent asset, script will not run" + , m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data()); return; } #else - AZ_Assert(m_executionState, "RuntimeComponent::m_runtimeAsset AssetId: %s failed to create an execution state, possibly due to missing dependent asset, script will not run", m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data()); + AZ_Assert(m_executionState, "RuntimeComponent::m_runtimeAsset AssetId: %s failed to create an execution state, possibly due to missing dependent asset, script will not run" + , m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data()); #endif AZ::EntityBus::Handler::BusConnect(GetEntityId()); @@ -179,4 +187,3 @@ namespace ScriptCanvas } } -#undef SCRIPT_CANVAS_RUNTIME_ASSET_CHECK From 5ec582484978e61429ccd7a962405c3e9f1ba819 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Fri, 12 Nov 2021 14:16:44 -0800 Subject: [PATCH 79/97] Hide the "up one level" button temporarily. (#5595) Signed-off-by: Danilo Aimini Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../UI/Prefab/PrefabViewportFocusPathHandler.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp index 920e99665d..c1fc9138d1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp @@ -64,6 +64,9 @@ namespace AzToolsFramework::Prefab ); m_backButton->setToolTip("Up one level (-)"); + + // Currently hide this button until we can correctly disable/enable it based on context. + m_backButton->hide(); } void PrefabViewportFocusPathHandler::OnPrefabFocusChanged() From c140b882d25eb92cbf9ea5575fb9383d21d04e86 Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Fri, 12 Nov 2021 14:19:22 -0800 Subject: [PATCH 80/97] Fix mis-spelled comment Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- .../ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.h index cc59f90e69..8c5da5ac07 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.h @@ -76,7 +76,7 @@ namespace ScriptCanvas AZStd::vector m_activationInputStorage; Execution::ActivationInputRange m_activationInputRange; - // used to initialized statics only once, and not necessarily on the loading thread + // used to initialize statics only once, and not necessarily on the loading thread bool m_areStaticsInitialized = false; bool RequiresStaticInitialization() const; From d0cf18e7789c991e9b42944ce89f1ecbc774737a Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Fri, 12 Nov 2021 14:56:27 -0800 Subject: [PATCH 81/97] remove test code artifact Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- .../Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp index bc37bc05f6..930b84abe4 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp @@ -22,11 +22,6 @@ #include #include -namespace AZ -{ - AZ_TYPE_INFO_SPECIALIZE(AZ::Data::Asset, "{D9A4EB57-198B-4A0D-B1FB-D1B11FF88C66}"); -} - AZ_DECLARE_BUDGET(ScriptCanvas); namespace RuntimeComponentCpp From 76b7e73f6f1b34a2499e3d192a7683dc91ce70e2 Mon Sep 17 00:00:00 2001 From: AMZN-nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Fri, 12 Nov 2021 16:23:04 -0800 Subject: [PATCH 82/97] Fully Replaces Remote Gems in Model and Selects Them When Downloading and Deleting (#5593) Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- .../Source/GemCatalog/GemCatalogScreen.cpp | 58 ++++++++++++++----- .../Source/GemCatalog/GemModel.cpp | 24 ++++++-- .../Source/GemCatalog/GemModel.h | 4 +- .../Source/GemRepo/GemRepoScreen.cpp | 2 +- 4 files changed, 68 insertions(+), 20 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 6abbfe16ba..0dacbbb906 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -126,7 +126,8 @@ namespace O3DE::ProjectManager // Select the first entry after everything got correctly sized QTimer::singleShot(200, [=]{ QModelIndex firstModelIndex = m_gemModel->index(0, 0); - m_gemModel->GetSelectionModel()->select(firstModelIndex, QItemSelectionModel::ClearAndSelect); + QModelIndex proxyIndex = m_proxyModel->mapFromSource(firstModelIndex); + m_proxyModel->GetSelectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect); }); } @@ -209,7 +210,7 @@ namespace O3DE::ProjectManager const bool gemFound = gemInfoHash.contains(gemName); if (!gemFound && !m_gemModel->IsAdded(index) && !m_gemModel->IsAddedDependency(index)) { - m_gemModel->removeRow(i); + m_gemModel->RemoveGem(index); } else { @@ -239,7 +240,7 @@ namespace O3DE::ProjectManager m_filterWidget->ResetAllFilters(); // Reselect the same selection to proc UI updates - m_proxyModel->GetSelectionModel()->select(m_proxyModel->GetSelectionModel()->selection(), QItemSelectionModel::Select); + m_proxyModel->GetSelectionModel()->setCurrentIndex(m_proxyModel->GetSelectionModel()->currentIndex(), QItemSelectionModel::Select); } void GemCatalogScreen::OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies) @@ -268,7 +269,7 @@ namespace O3DE::ProjectManager if (added && GemModel::GetDownloadStatus(modelIndex) == GemInfo::DownloadStatus::NotDownloaded) { m_downloadController->AddGemDownload(GemModel::GetName(modelIndex)); - GemModel::SetDownloadStatus(*m_proxyModel, m_proxyModel->mapFromSource(modelIndex), GemInfo::DownloadStatus::Downloading); + GemModel::SetDownloadStatus(*m_gemModel, modelIndex, GemInfo::DownloadStatus::Downloading); } } @@ -300,7 +301,7 @@ namespace O3DE::ProjectManager } QModelIndex proxyIndex = m_proxyModel->mapFromSource(modelIndex); - m_proxyModel->GetSelectionModel()->select(proxyIndex, QItemSelectionModel::ClearAndSelect); + m_proxyModel->GetSelectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect); m_gemListView->scrollTo(proxyIndex); } @@ -362,6 +363,9 @@ namespace O3DE::ProjectManager { const QString selectedGemPath = m_gemModel->GetPath(modelIndex); + // Remove gem from gems to be added + GemModel::SetIsAdded(*m_gemModel, modelIndex, false); + // Unregister the gem auto unregisterResult = PythonBindingsInterface::Get()->UnregisterGem(selectedGemPath); if (!unregisterResult) @@ -370,8 +374,10 @@ namespace O3DE::ProjectManager } else { + const QString selectedGemName = m_gemModel->GetName(modelIndex); + // Remove gem from model - m_gemModel->removeRow(modelIndex.row()); + m_gemModel->RemoveGem(modelIndex); // Delete uninstalled gem directory if (!ProjectUtils::DeleteProjectFiles(selectedGemPath, /*force*/true)) @@ -382,6 +388,11 @@ namespace O3DE::ProjectManager // Show undownloaded remote gem again Refresh(); + + // Select remote gem + QModelIndex remoteGemIndex = m_gemModel->FindIndexByNameString(selectedGemName); + QModelIndex proxyIndex = m_proxyModel->mapFromSource(remoteGemIndex); + m_proxyModel->GetSelectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect); } } } @@ -564,7 +575,8 @@ namespace O3DE::ProjectManager if (succeeded) { // refresh the information for downloaded gems - const AZ::Outcome, AZStd::string>& allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(m_projectPath); + const AZ::Outcome, AZStd::string>& allGemInfosResult = + PythonBindingsInterface::Get()->GetAllGemInfos(m_projectPath); if (allGemInfosResult.IsSuccess()) { // we should find the gem name now in all gem infos @@ -572,15 +584,33 @@ namespace O3DE::ProjectManager { if (gemInfo.m_name == gemName) { - QModelIndex index = m_gemModel->FindIndexByNameString(gemName); - if (index.isValid()) + QModelIndex oldIndex = m_gemModel->FindIndexByNameString(gemName); + if (oldIndex.isValid()) { - m_proxyModel->setData(m_proxyModel->mapFromSource(index), GemInfo::DownloadSuccessful, GemModel::RoleDownloadStatus); - m_gemModel->setData(index, gemInfo.m_path, GemModel::RolePath); - m_gemModel->setData(index, gemInfo.m_path, GemModel::RoleDirectoryLink); + // Check if old gem is selected + bool oldGemSelected = false; + if (m_gemModel->GetSelectionModel()->currentIndex() == oldIndex) + { + oldGemSelected = true; + } + + // Remove old remote gem + m_gemModel->RemoveGem(oldIndex); + + // Add new downloaded version of gem + QModelIndex newIndex = m_gemModel->AddGem(gemInfo); + GemModel::SetDownloadStatus(*m_gemModel, newIndex, GemInfo::DownloadSuccessful); + GemModel::SetIsAdded(*m_gemModel, newIndex, true); + + // Select new version of gem if it was previously selected + if (oldGemSelected) + { + QModelIndex proxyIndex = m_proxyModel->mapFromSource(newIndex); + m_proxyModel->GetSelectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect); + } } - return; + break; } } } @@ -590,7 +620,7 @@ namespace O3DE::ProjectManager QModelIndex index = m_gemModel->FindIndexByNameString(gemName); if (index.isValid()) { - m_proxyModel->setData(m_proxyModel->mapFromSource(index), GemInfo::DownloadFailed, GemModel::RoleDownloadStatus); + GemModel::SetDownloadStatus(*m_gemModel, index, GemInfo::DownloadFailed); } } } diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp index 886b9e57c7..95fdc8e1e2 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp @@ -26,14 +26,14 @@ namespace O3DE::ProjectManager return m_selectionModel; } - void GemModel::AddGem(const GemInfo& gemInfo) + QModelIndex GemModel::AddGem(const GemInfo& gemInfo) { if (FindIndexByNameString(gemInfo.m_name).isValid()) { // do not add gems with duplicate names // this can happen by mistake or when a gem repo has a gem with the same name as a local gem AZ_TracePrintf("GemModel", "Ignoring duplicate gem: %s", gemInfo.m_name.toUtf8().constData()); - return; + return QModelIndex(); } QStandardItem* item = new QStandardItem(); @@ -67,6 +67,22 @@ namespace O3DE::ProjectManager const QModelIndex modelIndex = index(rowCount()-1, 0); m_nameToIndexMap[gemInfo.m_name] = modelIndex; + + return modelIndex; + } + + void GemModel::RemoveGem(const QModelIndex& modelIndex) + { + removeRow(modelIndex.row()); + } + + void GemModel::RemoveGem(const QString& gemName) + { + auto nameFind = m_nameToIndexMap.find(gemName); + if (nameFind != m_nameToIndexMap.end()) + { + removeRow(nameFind->row()); + } } void GemModel::Clear() @@ -391,11 +407,11 @@ namespace O3DE::ProjectManager // Select a valid row if currently selected row was removed if (selectedRowRemoved) { - for (const QModelIndex& index : m_nameToIndexMap) + for (const QModelIndex& index : m_nameToIndexMap) { if (index.isValid()) { - GetSelectionModel()->select(index, QItemSelectionModel::ClearAndSelect); + GetSelectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); break; } } diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h index 87a718d8c7..bb89d46861 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h @@ -55,7 +55,9 @@ namespace O3DE::ProjectManager RoleRepoUri }; - void AddGem(const GemInfo& gemInfo); + QModelIndex AddGem(const GemInfo& gemInfo); + void RemoveGem(const QModelIndex& modelIndex); + void RemoveGem(const QString& gemName); void Clear(); void UpdateGemDependencies(); diff --git a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp index 794635a3e3..91432c2346 100644 --- a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp @@ -75,7 +75,7 @@ namespace O3DE::ProjectManager // Select the first entry after everything got correctly sized QTimer::singleShot(200, [=]{ QModelIndex firstModelIndex = m_gemRepoListView->model()->index(0,0); - m_gemRepoListView->selectionModel()->select(firstModelIndex, QItemSelectionModel::ClearAndSelect); + m_gemRepoListView->selectionModel()->setCurrentIndex(firstModelIndex, QItemSelectionModel::ClearAndSelect); }); } From 1925d08f41d7888ce246fd6d098de7eed57e4acb Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sat, 13 Nov 2021 13:52:56 -0600 Subject: [PATCH 83/97] Fixing double registration of hair asset Signed-off-by: Guthrie Adams --- Gems/AtomTressFX/Code/Builders/HairBuilderComponent.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Gems/AtomTressFX/Code/Builders/HairBuilderComponent.cpp b/Gems/AtomTressFX/Code/Builders/HairBuilderComponent.cpp index f80261f4b5..7f99e4c55f 100644 --- a/Gems/AtomTressFX/Code/Builders/HairBuilderComponent.cpp +++ b/Gems/AtomTressFX/Code/Builders/HairBuilderComponent.cpp @@ -46,14 +46,6 @@ namespace AZ { m_hairAssetBuilder.RegisterBuilder(); m_hairAssetHandler.Register(); - - // Add asset types and extensions to AssetCatalog. - auto assetCatalog = AZ::Data::AssetCatalogRequestBus::FindFirstHandler(); - if (assetCatalog) - { - assetCatalog->EnableCatalogForAsset(azrtti_typeid()); - assetCatalog->AddExtension(AMD::TFXCombinedFileExtension); - } } void HairBuilderComponent::Deactivate() From f2068397fa4542bd034e9d34002cca4b976c31b1 Mon Sep 17 00:00:00 2001 From: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> Date: Mon, 15 Nov 2021 11:51:16 +0100 Subject: [PATCH 84/97] CameraRigComponent - Disable Component Checkbox when the two others are toggled (#5546) * Disable component checkbox when the other two components are already ignored. Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Fixed EditContext Indents Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Fixed Header file Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Fixed Spaces Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * fixed new line Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> --- .../SlideAlongAxisBasedOnAngle.cpp | 72 +++++++++++++------ .../SlideAlongAxisBasedOnAngle.h | 10 ++- 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.cpp b/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.cpp index 5031f149b8..1d8d6adf6c 100644 --- a/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.cpp +++ b/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.cpp @@ -9,8 +9,8 @@ #include "SlideAlongAxisBasedOnAngle.h" #include "StartingPointCamera/StartingPointCameraUtilities.h" #include -#include #include +#include namespace Camera { @@ -32,31 +32,43 @@ namespace Camera AZ::EditContext* editContext = serializeContext->GetEditContext(); if (editContext) { - editContext->Class("SlideAlongAxisBasedOnAngle", "Slide 0..SlideDistance along Axis based on Angle Type. Maps from 90..-90 degrees") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &SlideAlongAxisBasedOnAngle::m_axisToSlideAlong, "Axis to slide along", "The Axis to slide along") - ->EnumAttribute(RelativeAxisType::ForwardBackward, "Forwards and Backwards") - ->EnumAttribute(RelativeAxisType::LeftRight, "Right and Left") - ->EnumAttribute(RelativeAxisType::UpDown, "Up and Down") - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &SlideAlongAxisBasedOnAngle::m_angleTypeToChangeFor, "Angle Type", "The angle type to base the slide off of") - ->EnumAttribute(EulerAngleType::Pitch, "Pitch") - ->EnumAttribute(EulerAngleType::Roll, "Roll") - ->EnumAttribute(EulerAngleType::Yaw, "Yaw") - ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_maximumPositiveSlideDistance, "Max Positive Slide Distance", "The maximum distance to slide in the positive") - ->Attribute(AZ::Edit::Attributes::Suffix, "m") - ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_maximumNegativeSlideDistance, "Max Negative Slide Distance", "The maximum distance to slide in the negative") - ->Attribute(AZ::Edit::Attributes::Suffix, "m") - ->ClassElement(AZ::Edit::ClassElements::Group, "Vector Components To Ignore") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_ignoreX, "X", "When active, the X Component will be ignored.") - ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_ignoreY, "Y", "When active, the Y Component will be ignored.") - ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_ignoreZ, "Z", "When active, the Z Component will be ignored.") + editContext->Class("SlideAlongAxisBasedOnAngle", + "Slide 0..SlideDistance along Axis based on Angle Type. Maps from 90..-90 degrees") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &SlideAlongAxisBasedOnAngle::m_axisToSlideAlong, "Axis to slide along", + "The Axis to slide along") + ->EnumAttribute(RelativeAxisType::ForwardBackward, "Forwards and Backwards") + ->EnumAttribute(RelativeAxisType::LeftRight, "Right and Left") + ->EnumAttribute(RelativeAxisType::UpDown, "Up and Down") + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &SlideAlongAxisBasedOnAngle::m_angleTypeToChangeFor, "Angle Type", + "The angle type to base the slide off of") + ->EnumAttribute(EulerAngleType::Pitch, "Pitch") + ->EnumAttribute(EulerAngleType::Roll, "Roll") + ->EnumAttribute(EulerAngleType::Yaw, "Yaw") + ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_maximumPositiveSlideDistance, "Max Positive Slide Distance", + "The maximum distance to slide in the positive") + ->Attribute(AZ::Edit::Attributes::Suffix, "m") + ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_maximumNegativeSlideDistance, "Max Negative Slide Distance", + "The maximum distance to slide in the negative") + ->Attribute(AZ::Edit::Attributes::Suffix, "m") + ->ClassElement(AZ::Edit::ClassElements::Group, "Vector Components To Ignore") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_ignoreX, "X", "When active, the X Component will be ignored.") + ->Attribute(AZ::Edit::Attributes::ReadOnly, &SlideAlongAxisBasedOnAngle::YAndZIgnored) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues) + ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_ignoreY, "Y", "When active, the Y Component will be ignored.") + ->Attribute(AZ::Edit::Attributes::ReadOnly, &SlideAlongAxisBasedOnAngle::XAndZIgnored) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues) + ->DataElement(0, &SlideAlongAxisBasedOnAngle::m_ignoreZ, "Z", "When active, the Z Component will be ignored.") + ->Attribute(AZ::Edit::Attributes::ReadOnly, &SlideAlongAxisBasedOnAngle::XAndYIgnored) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues) ; } } } - void SlideAlongAxisBasedOnAngle::AdjustLookAtTarget([[maybe_unused]] float deltaTime, [[maybe_unused]] const AZ::Transform& targetTransform, AZ::Transform& outLookAtTargetTransform) + void SlideAlongAxisBasedOnAngle::AdjustLookAtTarget( + [[maybe_unused]] float deltaTime, [[maybe_unused]] const AZ::Transform& targetTransform, AZ::Transform& outLookAtTargetTransform) { float angle = GetEulerAngleFromTransform(outLookAtTargetTransform, m_angleTypeToChangeFor); float currentPositionOnRange = -angle / AZ::Constants::HalfPi; @@ -67,4 +79,20 @@ namespace Camera outLookAtTargetTransform.SetTranslation(outLookAtTargetTransform.GetTranslation() + basis * currentPositionOnRange * slideScale); } -} + + bool SlideAlongAxisBasedOnAngle::XAndYIgnored() const + { + return m_ignoreX && m_ignoreY; + } + + bool SlideAlongAxisBasedOnAngle::XAndZIgnored() const + { + return m_ignoreX && m_ignoreZ; + } + + bool SlideAlongAxisBasedOnAngle::YAndZIgnored() const + { + return m_ignoreY && m_ignoreZ; + } + +} // namespace Camera diff --git a/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.h b/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.h index 2c756d1ac7..e517b6ffbd 100644 --- a/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.h +++ b/Gems/StartingPointCamera/Code/Source/CameraLookAtBehaviors/SlideAlongAxisBasedOnAngle.h @@ -6,11 +6,11 @@ * */ #pragma once -#include -#include -#include #include "StartingPointCamera/StartingPointCameraConstants.h" +#include #include +#include +#include namespace Camera { @@ -38,6 +38,10 @@ namespace Camera void Activate(AZ::EntityId) override {} void Deactivate() override {} + bool XAndYIgnored() const; + bool XAndZIgnored() const; + bool YAndZIgnored() const; + private: ////////////////////////////////////////////////////////////////////////// // Reflected data From d9746647e10a7f9d2a8599063191826e613ad0fc Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 15 Nov 2021 10:54:34 -0600 Subject: [PATCH 85/97] Bug fix for material editor not taking focus when opening a new document from the main editor or outside of the material editor Signed-off-by: Guthrie Adams --- .../Code/Source/Window/AtomToolsMainWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp index aeca51230a..f07fd9c536 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp @@ -50,8 +50,9 @@ namespace AtomToolsFramework void AtomToolsMainWindow::ActivateWindow() { - activateWindow(); + show(); raise(); + activateWindow(); } bool AtomToolsMainWindow::AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation) From c44d03a40df0899851c6cbd929a673fac48ce82b Mon Sep 17 00:00:00 2001 From: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> Date: Mon, 15 Nov 2021 09:10:04 -0800 Subject: [PATCH 86/97] Asset bundler test fixes (#5548) * Cleaning up errors with default assets, used in bundled release builds Signed-off-by: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Updated simple asset references to be to the product, not source assets Signed-off-by: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Fixed test_WindowsAndMac_FilesMarkedSkip_FilesAreSkipped to pass again. Updated the test to verify the assets are actually skipped and not just missing, by having it first run without the skip command and verify they are in the first run. Also updated logging to print out sorted lists, to make it easier to debug failures on Jenkins in the future. Signed-off-by: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Removed a test marked skip for legacy levels that featured a lot of assets that are no longer valid. I don't think we need this specific test anymore in the future because prefabs replace the level system, and prefabs should have their own tests for product dependencies. Signed-off-by: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Updated project path to use absolute path (#5459) Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Updated project path to work with latest project path changes Signed-off-by: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> * Changed to workspace.paths.project() for getting full path to projects Signed-off-by: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> Co-authored-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> --- .../bundler_batch_setup_fixture.py | 2 +- .../asset_bundler_batch_tests.py | 277 ++++-------------- 2 files changed, 56 insertions(+), 223 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py index ff362c732c..9281d5947e 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py @@ -158,7 +158,7 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) -> else: cmd.append(f"--{key}") if append_defaults: - cmd.append(f"--project-path={workspace.project}") + cmd.append(f"--project-path={workspace.paths.project()}") return cmd # ****** diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py index 7f85e5e317..f5e5642573 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py @@ -88,214 +88,6 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): bundler_batch_helper.call_bundles(help="") bundler_batch_helper.call_bundleSeed(help="") - @pytest.mark.BAT - @pytest.mark.assetpipeline - @pytest.mark.test_case_id("C16877175") - @pytest.mark.skip("'animations/animationeditorfiles/sample1.animgraph' missing, needs investigation") - def test_WindowsAndMac_CreateAssetList_DependenciesCorrect(self, workspace, bundler_batch_helper): - r""" - Tests that an asset list created maps dependencies correctly. - testdependencieslevel\level.pak and lists of known dependencies are used for validation - - Test Steps: - 1. Create an asset list from the level.pak - 2. Create Lists of expected assets in the level.pak - 3. Add lists of expected assets to a single list - 4. Compare list of expected assets to actual assets - """ - helper = bundler_batch_helper - - # Create the asset list file - helper.call_assetLists( - addSeed=r"levels\testdependencieslevel\level.pak", - assetListFile=helper['asset_info_file_request'] - ) - - assert os.path.isfile(helper["asset_info_file_result"]) - - # Lists of known relative locations of assets - default_level_assets = [ - "engineassets/texturemsg/defaultnouvs.dds", - "engineassets/texturemsg/defaultnouvs.dds.1", - "engineassets/texturemsg/defaultnouvs.dds.2", - "engineassets/texturemsg/defaultnouvs.dds.3", - "engineassets/texturemsg/defaultnouvs.dds.4", - "engineassets/texturemsg/defaultnouvs.dds.5", - "engineassets/texturemsg/defaultnouvs.dds.6", - "engineassets/texturemsg/defaultnouvs.dds.7", - "engineassets/texturemsg/defaultnouvs_ddn.dds", - "engineassets/texturemsg/defaultnouvs_ddn.dds.1", - "engineassets/texturemsg/defaultnouvs_ddn.dds.2", - "engineassets/texturemsg/defaultnouvs_ddn.dds.3", - "engineassets/texturemsg/defaultnouvs_ddn.dds.4", - "engineassets/texturemsg/defaultnouvs_ddn.dds.5", - "engineassets/texturemsg/defaultnouvs_spec.dds", - "engineassets/texturemsg/defaultnouvs_spec.dds.1", - "engineassets/texturemsg/defaultnouvs_spec.dds.2", - "engineassets/texturemsg/defaultnouvs_spec.dds.3", - "engineassets/texturemsg/defaultnouvs_spec.dds.4", - "engineassets/texturemsg/defaultnouvs_spec.dds.5", - "engineassets/textures/defaults/16_grey.dds", - "engineassets/textures/cubemap/default_level_cubemap.dds", - "engineassets/textures/cubemap/default_level_cubemap.dds.1", - "engineassets/textures/cubemap/default_level_cubemap.dds.2", - "engineassets/textures/cubemap/default_level_cubemap.dds.3", - "engineassets/textures/cubemap/default_level_cubemap.dds.4", - "engineassets/textures/cubemap/default_level_cubemap_diff.dds", - "engineassets/materials/water/ocean_default.mtl", - "engineassets/textures/defaults/spot_default.dds", - "engineassets/textures/defaults/spot_default.dds.1", - "engineassets/textures/defaults/spot_default.dds.2", - "engineassets/textures/defaults/spot_default.dds.3", - "engineassets/textures/defaults/spot_default.dds.4", - "engineassets/textures/defaults/spot_default.dds.5", - "materials/material_terrain_default.mtl", - "textures/skys/night/half_moon.dds", - "textures/skys/night/half_moon.dds.1", - "textures/skys/night/half_moon.dds.2", - "textures/skys/night/half_moon.dds.3", - "textures/skys/night/half_moon.dds.4", - "textures/skys/night/half_moon.dds.5", - "textures/skys/night/half_moon.dds.6", - "engineassets/materials/sky/sky.mtl", - "levels/testdependencieslevel/level.pak", - "levels/testdependencieslevel/terrain/cover.ctc", - "levels/testdependencieslevel/terraintexture.pak", - ] - - sequence_material_cube_assets = [ - "textures/test_texture_sequence/test_texture_sequence000.dds", - "textures/test_texture_sequence/test_texture_sequence001.dds", - "textures/test_texture_sequence/test_texture_sequence002.dds", - "textures/test_texture_sequence/test_texture_sequence003.dds", - "textures/test_texture_sequence/test_texture_sequence004.dds", - "textures/test_texture_sequence/test_texture_sequence005.dds", - "objects/_primitives/_box_1x1.cgf", - "materials/test_texture_sequence.mtl", - "objects/_primitives/_box_1x1.mtl", - "textures/_primitives/middle_gray_checker.dds", - "textures/_primitives/middle_gray_checker.dds.1", - "textures/_primitives/middle_gray_checker.dds.2", - "textures/_primitives/middle_gray_checker.dds.3", - "textures/_primitives/middle_gray_checker.dds.4", - "textures/_primitives/middle_gray_checker.dds.5", - "textures/_primitives/middle_gray_checker_ddn.dds", - "textures/_primitives/middle_gray_checker_ddn.dds.1", - "textures/_primitives/middle_gray_checker_ddn.dds.2", - "textures/_primitives/middle_gray_checker_ddn.dds.3", - "textures/_primitives/middle_gray_checker_ddn.dds.4", - "textures/_primitives/middle_gray_checker_ddn.dds.5", - "textures/_primitives/middle_gray_checker_spec.dds", - "textures/_primitives/middle_gray_checker_spec.dds.1", - "textures/_primitives/middle_gray_checker_spec.dds.2", - "textures/_primitives/middle_gray_checker_spec.dds.3", - "textures/_primitives/middle_gray_checker_spec.dds.4", - "textures/_primitives/middle_gray_checker_spec.dds.5", - ] - - character_with_simplified_material_assets = [ - "objects/characters/jack/jack.actor", - "objects/characters/jack/jack.mtl", - "objects/characters/jack/textures/jack_diff.dds", - "objects/characters/jack/textures/jack_diff.dds.1", - "objects/characters/jack/textures/jack_diff.dds.2", - "objects/characters/jack/textures/jack_diff.dds.3", - "objects/characters/jack/textures/jack_diff.dds.4", - "objects/characters/jack/textures/jack_diff.dds.5", - "objects/characters/jack/textures/jack_diff.dds.6", - "objects/characters/jack/textures/jack_diff.dds.7", - "objects/characters/jack/textures/jack_spec.dds", - "objects/characters/jack/textures/jack_spec.dds.1", - "objects/characters/jack/textures/jack_spec.dds.2", - "objects/characters/jack/textures/jack_spec.dds.3", - "objects/characters/jack/textures/jack_spec.dds.4", - "objects/characters/jack/textures/jack_spec.dds.5", - "objects/characters/jack/textures/jack_spec.dds.6", - "objects/characters/jack/textures/jack_spec.dds.7", - "objects/default/editorprimitive.mtl", - "engineassets/textures/grey.dds", - "animations/animationeditorfiles/sample0.animgraph", - "animations/motions/jack_death_fall_back_zup.motion", - "animations/animationeditorfiles/sample1.animgraph", - "animations/animationeditorfiles/sample0.motionset", - "animations/motions/rin_jump.motion", - "animations/animationeditorfiles/sample1.motionset", - "animations/motions/rin_idle.motion", - "animations/motions/jack_idle_aim_zup.motion", - ] - - spawner_assets = [ - "slices/sphere.dynamicslice", - "objects/default/primitive_sphere.cgf", - "test1.luac", - "test2.luac", - ] - - ui_canvas_assets = [ - "fonts/vera.ttf", - "fonts/vera.font", - "scriptcanvas/mainmenu.scriptcanvas_compiled", - "fonts/vera.fontfamily", - "ui/canvas/start.uicanvas", - "fonts/vera-italic.font", - "ui/textureatlas/sample.texatlasidx", - "fonts/vera-bold-italic.ttf", - "fonts/vera-bold.font", - "ui/textures/prefab/button_normal.dds", - "ui/textures/prefab/button_normal.sprite", - "fonts/vera-italic.ttf", - "ui/textureatlas/sample.dds", - "fonts/vera-bold-italic.font", - "fonts/vera-bold.ttf", - "ui/textures/prefab/button_disabled.dds", - "ui/textures/prefab/button_disabled.sprite", - ] - - wwise_and_atl_assets = [ - "libs/gameaudio/wwise/levels/testdependencieslevel/test_dependencies_level.xml", - "sounds/wwise/test_bank3.bnk", - "sounds/wwise/test_bank4.bnk", - "sounds/wwise/test_bank5.bnk", - "sounds/wwise/test_bank1.bnk", - "sounds/wwise/init.bnk", - "sounds/wwise/499820003.wem", - "sounds/wwise/196049145.wem", - ] - - particle_library_assets = [ - "libs/particles/milestone2particles.xml", - "textures/milestone2/particles/fx_launchermuzzlering_01.dds", - "textures/milestone2/particles/fx_launchermuzzlering_01.dds.1", - "textures/milestone2/particles/fx_launchermuzzlering_01.dds.2", - "textures/milestone2/particles/fx_launchermuzzlering_01.dds.3", - "textures/milestone2/particles/fx_launchermuzzlering_01.dds.4", - "textures/milestone2/particles/fx_launchermuzzlering_01.dds.5", - "textures/milestone2/particles/fx_sparkstreak_01.dds", - "textures/milestone2/particles/fx_launchermuzzlefront_01.dds", - "textures/milestone2/particles/fx_launchermuzzlefront_01.dds.1", - "textures/milestone2/particles/fx_launchermuzzlefront_01.dds.2", - "textures/milestone2/particles/fx_launchermuzzlefront_01.dds.3", - "textures/milestone2/particles/fx_launchermuzzlefront_01.dds.4", - "textures/milestone2/particles/fx_launchermuzzlefront_01.dds.5", - ] - - lens_flares_library_assets = ["libs/flares/flares.xml", "textures/lights/flare01.dds"] - - expected_assets_list = default_level_assets - expected_assets_list.extend(sequence_material_cube_assets) - expected_assets_list.extend(character_with_simplified_material_assets) - expected_assets_list.extend(spawner_assets) - expected_assets_list.extend(ui_canvas_assets) - expected_assets_list.extend(wwise_and_atl_assets) - expected_assets_list.extend(particle_library_assets) - expected_assets_list.extend(lens_flares_library_assets) # All expected assets - - # Get actual calculated dependencies from the asset list created - actual_assets_list = [] - for rel_path in helper.get_asset_relative_paths(helper["asset_info_file_result"]): - actual_assets_list.append(rel_path) - - assert sorted(actual_assets_list) == sorted(expected_assets_list) @pytest.mark.BAT @pytest.mark.assetpipeline @@ -310,9 +102,9 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): 3. Read and store contents of asset list into memory 4. Attempt to create a new asset list in without using --allowOverwrites 5. Verify that Asset Bundler returns false - 6. Verify that file contents of the orignally created asset list did not change from what was stored in memory + 6. Verify that file contents of the originally created asset list did not change from what was stored in memory 7. Attempt to create a new asset list without debug while allowing overwrites - 8. Verify that file contents of the orignally created asset list changed from what was stored in memory + 8. Verify that file contents of the originally created asset list changed from what was stored in memory """ helper = bundler_batch_helper seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed") # Engine seed list @@ -919,7 +711,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): # Extra arguments for pattern comparison cmd.extend([f"--filePatternType={pattern_type}", f"--filePattern={pattern}"]) if workspace.project: - cmd.append(f'--project-path={project_name}') + cmd.append(f'--project-path={workspace.paths.project()}') return cmd # End generate_compare_command() @@ -960,7 +752,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): output_mac_asset_list = helper.platform_file_name(last_output_arg, platform) # Build execution command - cmd = generate_compare_command(platform_arg, workspace.project) + cmd = generate_compare_command(platform_arg, workspace.paths.project()) # Execute command subprocess.check_call(cmd) @@ -995,7 +787,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): f"--comparisonRulesFile={rule_file}", f"--comparisonType={args[1]}", r"--addComparison", - f"--project-path={workspace.project}", + f"--project-path={workspace.paths.project()}", ] if args[1] == "4": # If pattern comparison, append a few extra arguments @@ -1117,7 +909,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): "--addDefaultSeedListFiles", "--platform=pc", "--print", - f"--project-path={workspace.project}" + f"--project-path={workspace.paths.project()}" ], universal_newlines=True, ) @@ -1189,7 +981,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): # Make sure file gets deleted on teardown request.addfinalizer(lambda: fs.delete([bundle_result_path], True, False)) - bundles_folder = os.path.join(workspace.paths.engine_root(), workspace.project, "Bundles") + bundles_folder = os.path.join(workspace.paths.project(), "Bundles") level_pak = r"levels\testdependencieslevel\level.pak" bundle_request_path = os.path.join(bundles_folder, "bundle.pak") bundle_result_path = os.path.join(bundles_folder, @@ -1243,23 +1035,64 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): 2. Verify file was created 3. Verify that only the expected assets are present in the created asset list """ - expected_assets = [ + expected_assets = sorted([ "ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas", - "ui/textures/prefab/button_normal.sprite" - ] + "ui/textures/prefab/button_disabled.tif.streamingimage", + "ui/textures/prefab/tooltip_sliced.tif.streamingimage", + "ui/textures/prefab/button_normal.tif.streamingimage" + ]) + # Printing these lists out can save a step in debugging if this test fails on Jenkins. + logger.info(f"expected_assets: {expected_assets}") + + skip_assets = sorted([ + "ui/scripts/lyshineexamples/animation/multiplesequences.luac", + "ui/scripts/lyshineexamples/unloadthiscanvasbutton.luac", + "fonts/vera.fontfamily", + "fonts/vera-italic.font", + "fonts/vera.font", + "fonts/vera-bold.font", + "fonts/vera-bold-italic.font", + "fonts/vera-italic.ttf", + "fonts/vera.ttf", + "fonts/vera-bold.ttf", + "fonts/vera-bold-italic.ttf" + ]) + logger.info(f"skip_assets: {skip_assets}") + + expected_and_skip_assets = sorted(expected_assets + skip_assets) + # Printing both together to make it quick to compare the results in the logs for a test failure on Jenkins + logger.info(f"expected_and_skip_assets: {expected_and_skip_assets}") + + # First, generate an asset info file without skipping, to get a list that can be used as a baseline to verify + # the files were actually skipped, and not just missing. + bundler_batch_helper.call_assetLists( + assetListFile=bundler_batch_helper['asset_info_file_request'], + addSeed="ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas" + ) + assert os.path.isfile(bundler_batch_helper["asset_info_file_result"]) + assets_in_no_skip_list = [] + for rel_path in bundler_batch_helper.get_asset_relative_paths(bundler_batch_helper["asset_info_file_result"]): + assets_in_no_skip_list.append(rel_path) + assets_in_no_skip_list = sorted(assets_in_no_skip_list) + logger.info(f"assets_in_no_skip_list: {assets_in_no_skip_list}") + assert assets_in_no_skip_list == expected_and_skip_assets + + # Now generate an asset info file using the skip command, and verify the skip files are not in the list. bundler_batch_helper.call_assetLists( assetListFile=bundler_batch_helper['asset_info_file_request'], addSeed="ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas", - skip="ui/textures/prefab/button_disabled.sprite,ui/scripts/lyshineexamples/animation/multiplesequences.luac," - "ui/textures/prefab/tooltip_sliced.sprite,ui/scripts/lyshineexamples/unloadthiscanvasbutton.luac,fonts/vera.fontfamily,fonts/vera-italic.font," - "fonts/vera.font,fonts/vera-bold.font,fonts/vera-bold-italic.font,fonts/vera-italic.ttf,fonts/vera.ttf,fonts/vera-bold.ttf,fonts/vera-bold-italic.ttf" + allowOverwrites="", + skip=','.join(skip_assets) ) + assert os.path.isfile(bundler_batch_helper["asset_info_file_result"]) assets_in_list = [] for rel_path in bundler_batch_helper.get_asset_relative_paths(bundler_batch_helper["asset_info_file_result"]): assets_in_list.append(rel_path) + assets_in_list = sorted(assets_in_list) + logger.info(f"assets_in_list: {assets_in_list}") + assert assets_in_list == expected_assets - assert sorted(assets_in_list) == sorted(expected_assets) @pytest.mark.BAT @pytest.mark.assetpipeline From 533b80095b48857e02f4bfeba5a0ecfd1ad85b16 Mon Sep 17 00:00:00 2001 From: mrieggeramzn <61609885+mrieggeramzn@users.noreply.github.com> Date: Mon, 15 Nov 2021 10:16:06 -0800 Subject: [PATCH 87/97] Fix for cascade shadow map clipping out too close to the camera (#5509) Signed-off-by: mrieggeramzn --- .../Atom/Features/Shadow/DirectionalLightShadow.azsli | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli index a7122aaf3a..59817af701 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli @@ -166,7 +166,7 @@ float DirectionalLightShadow::GetThickness(uint lightIndex, float3 shadowCoords[ bool2 DirectionalLightShadow::IsShadowed(float3 shadowCoord, uint indexOfCascade) { static const float PixelMargin = 1.5; // avoiding artifact between cascade levels. - static const float DepthMargin = 0.01; // avoiding artifact when near depth bounds. + static const float DepthMargin = 1e-8; // avoiding artifact when near depth bounds. // size is the shadowap's width and height. const uint size = ViewSrg::m_directionalLightShadows[m_lightIndex].m_shadowmapSize; @@ -210,8 +210,8 @@ float DirectionalLightShadow::GetVisibilityFromLightNoFilter() float DirectionalLightShadow::GetVisibilityFromLightPcf() { - static const float DepthMargin = 0.01; // avoiding artifact when near depth bounds. static const float PixelMargin = 1.5; // avoiding artifact between cascade levels. + static const float DepthMargin = 1e-8; // avoiding artifact when near depth bounds. const uint size = ViewSrg::m_directionalLightShadows[m_lightIndex].m_shadowmapSize; const uint cascadeCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_cascadeCount; From 5c0fe6a54f14d1770334679e0457702a37a946c2 Mon Sep 17 00:00:00 2001 From: mrieggeramzn <61609885+mrieggeramzn@users.noreply.github.com> Date: Mon, 15 Nov 2021 10:16:25 -0800 Subject: [PATCH 88/97] Fix for CSM shimmering (#5607) * Fix for CSM shimmering Signed-off-by: mrieggeramzn * removing debug code Signed-off-by: mrieggeramzn --- .../DirectionalLightFeatureProcessor.cpp | 46 ++++++++++++++++--- .../DirectionalLightFeatureProcessor.h | 3 ++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index 410c80dbdc..ce5d3cc363 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -1248,6 +1248,32 @@ namespace AZ property.m_shadowmapViewNeedsUpdate = true; } + float DirectionalLightFeatureProcessor::GetShadowmapSizeFromCameraView(const LightHandle handle, const RPI::View* cameraView) const + { + const DirectionalLightShadowData& shadowData = m_shadowData.at(cameraView).GetData(handle.GetIndex()); + return static_cast(shadowData.m_shadowmapSize); + } + + void DirectionalLightFeatureProcessor::SnapAabbToPixelIncrements(const float invShadowmapSize, Vector3& orthoMin, Vector3& orthoMax) + { + // This function stops the cascaded shadowmap from shimmering as the camera moves. + // See CascadedShadowsManager.cpp in the Microsoft CascadedShadowMaps11 sample for details. + + const Vector3 normalizeByBufferSize = Vector3(invShadowmapSize, invShadowmapSize, invShadowmapSize); + + const Vector3 worldUnitsPerTexel = (orthoMax - orthoMin) * normalizeByBufferSize; + + // We snap the camera to 1 pixel increments so that moving the camera does not cause the shadows to jitter. + // This is a matter of dividing by the world space size of a texel + orthoMin /= worldUnitsPerTexel; + orthoMin = orthoMin.GetFloor(); + orthoMin *= worldUnitsPerTexel; + + orthoMax /= worldUnitsPerTexel; + orthoMax = orthoMax.GetFloor(); + orthoMax *= worldUnitsPerTexel; + } + void DirectionalLightFeatureProcessor::UpdateShadowmapViews(LightHandle handle) { ShadowProperty& property = m_shadowProperties.GetData(handle.GetIndex()); @@ -1259,18 +1285,26 @@ namespace AZ for (auto& segmentIt : property.m_segments) { + const float invShadowmapSize = 1.0f / GetShadowmapSizeFromCameraView(handle, segmentIt.first); + for (uint16_t cascadeIndex = 0; cascadeIndex < segmentIt.second.size(); ++cascadeIndex) { - const Aabb viewAabb = CalculateShadowViewAabb( - handle, segmentIt.first, cascadeIndex, lightTransform); + const Aabb viewAabb = CalculateShadowViewAabb(handle, segmentIt.first, cascadeIndex, lightTransform); if (viewAabb.IsValid() && viewAabb.IsFinite()) { + const float cascadeNear = viewAabb.GetMin().GetY(); + const float cascadeFar = viewAabb.GetMax().GetY(); + + Vector3 snappedAabbMin = viewAabb.GetMin(); + Vector3 snappedAabbMax = viewAabb.GetMax(); + + SnapAabbToPixelIncrements(invShadowmapSize, snappedAabbMin, snappedAabbMax); + Matrix4x4 viewToClipMatrix = Matrix4x4::CreateIdentity(); - MakeOrthographicMatrixRH(viewToClipMatrix, - viewAabb.GetMin().GetElement(0), viewAabb.GetMax().GetElement(0), - viewAabb.GetMin().GetElement(2), viewAabb.GetMax().GetElement(2), - viewAabb.GetMin().GetElement(1), viewAabb.GetMax().GetElement(1)); + MakeOrthographicMatrixRH( + viewToClipMatrix, snappedAabbMin.GetElement(0), snappedAabbMax.GetElement(0), snappedAabbMin.GetElement(2), + snappedAabbMax.GetElement(2), cascadeNear, cascadeFar); CascadeSegment& segment = segmentIt.second[cascadeIndex]; segment.m_aabb = viewAabb; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h index 8d7a9d76e4..77f2db38d6 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h @@ -341,6 +341,9 @@ namespace AZ //! This draws bounding boxes of cascades. void DrawCascadeBoundingBoxes(LightHandle handle); + float GetShadowmapSizeFromCameraView(const LightHandle handle, const RPI::View* cameraView) const; + void SnapAabbToPixelIncrements(const float invShadowmapSize, Vector3& orthoMin, Vector3& orthoMax); + IndexedDataVector m_shadowProperties; // [GFX TODO][ATOM-2012] shadow for multiple directional lights LightHandle m_shadowingLightHandle; From b3e2c3f075db1f28277c0a35987318449b4eeeb9 Mon Sep 17 00:00:00 2001 From: Mikhail Naumov <82239319+AMZN-mnaumov@users.noreply.github.com> Date: Mon, 15 Nov 2021 13:01:42 -0600 Subject: [PATCH 89/97] SetComponentProperty is now supported by undo operation (#5599) * Adding undo support to SetComponentProperty to make it function with prefab system Signed-off-by: Mikhail Naumov * Renaming a variable Signed-off-by: Mikhail Naumov * PR feedback Signed-off-by: Mikhail Naumov --- .../AzToolsFramework/Component/EditorComponentAPIComponent.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.cpp index 2cca3804ea..20a15643c6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.cpp @@ -597,11 +597,13 @@ namespace AzToolsFramework pte.SetVisibleEnforcement(true); } + ScopedUndoBatch undo("Modify Entity Property"); PropertyOutcome result = pte.SetProperty(propertyPath, value); if (result.IsSuccess()) { PropertyEditorEntityChangeNotificationBus::Event(componentInstance.GetEntityId(), &PropertyEditorEntityChangeNotifications::OnEntityComponentPropertyChanged, componentInstance.GetComponentId()); } + undo.MarkEntityDirty(componentInstance.GetEntityId()); return result; } From fc547d902c2e110b671a095b9731aff18154e68d Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Mon, 15 Nov 2021 12:09:43 -0800 Subject: [PATCH 90/97] Add message to indicate Json serialization of bitset is not supported (#5590) Signed-off-by: amzn-sj --- .../AzCore/Serialization/Json/JsonSystemComponent.cpp | 2 ++ .../Serialization/Json/UnsupportedTypesSerializer.cpp | 7 +++++++ .../Serialization/Json/UnsupportedTypesSerializer.h | 10 ++++++++++ 3 files changed, 19 insertions(+) diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp index da02e70181..0ba44e4e61 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp @@ -104,6 +104,8 @@ namespace AZ ->HandlesType(); jsonContext->Serializer() ->HandlesType(); + jsonContext->Serializer() + ->HandlesType(); MathReflect(jsonContext); } diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.cpp index 2392ff435f..ad1839f974 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.cpp @@ -15,6 +15,7 @@ namespace AZ AZ_CLASS_ALLOCATOR_IMPL(JsonAnySerializer, SystemAllocator, 0); AZ_CLASS_ALLOCATOR_IMPL(JsonVariantSerializer, SystemAllocator, 0); AZ_CLASS_ALLOCATOR_IMPL(JsonOptionalSerializer, SystemAllocator, 0); + AZ_CLASS_ALLOCATOR_IMPL(JsonBitsetSerializer, SystemAllocator, 0); JsonSerializationResult::Result JsonUnsupportedTypesSerializer::Load(void*, const Uuid&, const rapidjson::Value&, JsonDeserializerContext& context) @@ -49,4 +50,10 @@ namespace AZ return "The Json Serialization doesn't support AZStd::optional by design. No JSON format has yet been found that wasn't deemed too " "complex or overly verbose."; } + + AZStd::string_view JsonBitsetSerializer::GetMessage() const + { + return "The Json Serialization doesn't support AZStd::bitset by design. No JSON format has yet been found that is content creator " + "friendly i.e., easy to comprehend the intent."; + } } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.h index d913289d3d..fdcac4c761 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.h @@ -65,4 +65,14 @@ namespace AZ protected: AZStd::string_view GetMessage() const override; }; + + class JsonBitsetSerializer : public JsonUnsupportedTypesSerializer + { + public: + AZ_RTTI(JsonBitsetSerializer, "{10CE969D-D69E-4B3F-8593-069736F8F705}", JsonUnsupportedTypesSerializer); + AZ_CLASS_ALLOCATOR_DECL; + + protected: + AZStd::string_view GetMessage() const override; + }; } // namespace AZ From 8b7e538dd32f1eb3a96bedd225dfd6fc861f1ed3 Mon Sep 17 00:00:00 2001 From: amzn-mike <80125227+amzn-mike@users.noreply.github.com> Date: Mon, 15 Nov 2021 16:14:43 -0600 Subject: [PATCH 91/97] Cherry Pick: [LYN-7463] Fix insert streaming request failure (#5604) (#5622) * Fix race condition where asset would finish loading and another request would start before the streamer request could be cleared Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Re-enable disabled test which was failing for the same reason. Fix test timeout which was way too long. Reduce test iterations to keep test time safely under 5 seconds. Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Instead of using a mutex, re-order the statements to remove the streamer request first Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> (cherry picked from commit 0cea59d66998585f07c54e55f68dd117363fb4ea) Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp | 6 +++++- .../AzCore/Tests/Asset/AssetManagerLoadingTests.cpp | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp index 06bb0b0cac..b03e1affdc 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp +++ b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp @@ -1677,9 +1677,13 @@ namespace AZ // they will trigger a ReleaseAsset call sometime after the AssetManager has begun to shut down, which can lead to // race conditions. + // Make sure the streamer request is removed first before the asset is released + // If the asset is released first it could lead to a race condition where another thread starts loading the asset + // again and attempts to add a new streamer request with the same ID before the old one has been removed, causing + // that load request to fail + RemoveActiveStreamerRequest(assetId); weakAsset = {}; loadingAsset.Reset(); - RemoveActiveStreamerRequest(assetId); }; auto&& [deadline, priority] = GetEffectiveDeadlineAndPriority(*handler, asset.GetType(), loadParams); diff --git a/Code/Framework/AzCore/Tests/Asset/AssetManagerLoadingTests.cpp b/Code/Framework/AzCore/Tests/Asset/AssetManagerLoadingTests.cpp index e33dbce9c1..3f2d9491a7 100644 --- a/Code/Framework/AzCore/Tests/Asset/AssetManagerLoadingTests.cpp +++ b/Code/Framework/AzCore/Tests/Asset/AssetManagerLoadingTests.cpp @@ -652,7 +652,7 @@ namespace UnitTest threads.emplace_back([this, &threadCount, &cv, assetUuid]() { bool checkLoaded = true; - for (int i = 0; i < 5000; i++) + for (int i = 0; i < 1000; i++) { Asset asset1 = m_testAssetManager->GetAsset(assetUuid, azrtti_typeid(), AZ::Data::AssetLoadBehavior::PreLoad); @@ -678,7 +678,7 @@ namespace UnitTest while (threadCount > 0 && !timedOut) { AZStd::unique_lock lock(mutex); - timedOut = (AZStd::cv_status::timeout == cv.wait_until(lock, AZStd::chrono::system_clock::now() + DefaultTimeoutSeconds * 20000)); + timedOut = (AZStd::cv_status::timeout == cv.wait_until(lock, AZStd::chrono::system_clock::now() + DefaultTimeoutSeconds)); } ASSERT_EQ(threadCount, 0) << "Thread count is non-zero, a thread has likely deadlocked. Test will not shut down cleanly."; @@ -1190,7 +1190,7 @@ namespace UnitTest #if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS TEST_F(AssetJobsFloodTest, DISABLED_ContainerFilterTest_ContainersWithAndWithoutFiltering_Success) #else - TEST_F(AssetJobsFloodTest, DISABLED_ContainerFilterTest_ContainersWithAndWithoutFiltering_Success) + TEST_F(AssetJobsFloodTest, ContainerFilterTest_ContainersWithAndWithoutFiltering_Success) #endif // !AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS { m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusConnect(); From e1fb2ad368ca933fe6e299df5aeeb328e301c8be Mon Sep 17 00:00:00 2001 From: allisaurus <34254888+allisaurus@users.noreply.github.com> Date: Mon, 15 Nov 2021 14:48:32 -0800 Subject: [PATCH 92/97] Update resource mapping schema to make default account ID optional (#5475) Signed-off-by: Stanko --- .../aws_metrics_automation_test.py | 54 +++++++++++++++++++ .../core/test_aws_resource_interaction.py | 49 +++++++++++++++++ .../AWS/common/resource_mappings.py | 14 +++++ .../AWSResourceMappingConstants.h | 2 +- .../AWSResourceMappingManagerTest.cpp | 43 +++++++++++++++ 5 files changed, 161 insertions(+), 1 deletion(-) diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py index 34b2217916..6f3113d771 100644 --- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py +++ b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py @@ -14,6 +14,7 @@ from datetime import datetime import ly_test_tools.log.log_monitor from AWS.common import constants +from AWS.common.resource_mappings import AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY from .aws_metrics_custom_thread import AWSMetricsThread # fixture imports @@ -200,6 +201,59 @@ class TestAWSMetricsWindows(object): for thread in operational_threads: thread.join() + @pytest.mark.parametrize('level', ['AWS/Metrics']) + def test_realtime_and_batch_analytics_no_global_accountid(self, + level: str, + launcher: pytest.fixture, + asset_processor: pytest.fixture, + workspace: pytest.fixture, + aws_utils: pytest.fixture, + resource_mappings: pytest.fixture, + aws_metrics_utils: pytest.fixture): + """ + Verify that the metrics events are sent to CloudWatch and S3 for analytics. + """ + # Remove top-level account ID from resource mappings + resource_mappings.clear_select_keys([AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY]) + # Start Kinesis analytics application on a separate thread to avoid blocking the test. + kinesis_analytics_application_thread = AWSMetricsThread(target=update_kinesis_analytics_application_status, + args=(aws_metrics_utils, resource_mappings, True)) + kinesis_analytics_application_thread.start() + + log_monitor = setup(launcher, asset_processor) + + # Kinesis analytics application needs to be in the running state before we start the game launcher. + kinesis_analytics_application_thread.join() + launcher.args = ['+LoadLevel', level] + launcher.args.extend(['-rhi=null']) + start_time = datetime.utcnow() + with launcher.start(launch_ap=False): + monitor_metrics_submission(log_monitor) + + # Verify that real-time analytics metrics are delivered to CloudWatch. + aws_metrics_utils.verify_cloud_watch_delivery( + AWS_METRICS_FEATURE_NAME, + 'TotalLogins', + [], + start_time) + logger.info('Real-time metrics are sent to CloudWatch.') + + # Run time-consuming operations on separate threads to avoid blocking the test. + operational_threads = list() + operational_threads.append( + AWSMetricsThread(target=query_metrics_from_s3, + args=(aws_metrics_utils, resource_mappings))) + operational_threads.append( + AWSMetricsThread(target=verify_operational_metrics, + args=(aws_metrics_utils, resource_mappings, start_time))) + operational_threads.append( + AWSMetricsThread(target=update_kinesis_analytics_application_status, + args=(aws_metrics_utils, resource_mappings, False))) + for thread in operational_threads: + thread.start() + for thread in operational_threads: + thread.join() + @pytest.mark.parametrize('level', ['AWS/Metrics']) def test_unauthorized_user_request_rejected(self, level: str, diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/core/test_aws_resource_interaction.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/core/test_aws_resource_interaction.py index 949186ad50..59c517fd1c 100644 --- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/core/test_aws_resource_interaction.py +++ b/AutomatedTesting/Gem/PythonTests/AWS/Windows/core/test_aws_resource_interaction.py @@ -18,6 +18,7 @@ import ly_test_tools.environment.process_utils as process_utils import ly_test_tools.o3de.asset_processor_utils as asset_processor_utils from AWS.common import constants +from AWS.common.resource_mappings import AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY # fixture imports from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor @@ -141,3 +142,51 @@ class TestAWSCoreAWSResourceInteraction(object): 'The expected file wasn\'t successfully downloaded.' # clean up the file directories. shutil.rmtree(s3_download_dir) + + @pytest.mark.parametrize('expected_lines', [ + ['(Script) - [S3] Head object request is done', + '(Script) - [S3] Head object success: Object example.txt is found.', + '(Script) - [S3] Get object success: Object example.txt is downloaded.', + '(Script) - [Lambda] Completed Invoke', + '(Script) - [Lambda] Invoke success: {"statusCode": 200, "body": {}}', + '(Script) - [DynamoDB] Results finished']]) + @pytest.mark.parametrize('unexpected_lines', [ + ['(Script) - [S3] Head object error: No response body.', + '(Script) - [S3] Get object error: Request validation failed, output file directory doesn\'t exist.', + '(Script) - Request validation failed, output file miss full path.', + '(Script) - ']]) + def test_scripting_behavior_no_global_accountid(self, + level: str, + launcher: pytest.fixture, + workspace: pytest.fixture, + asset_processor: pytest.fixture, + resource_mappings: pytest.fixture, + aws_utils: pytest.fixture, + expected_lines: typing.List[str], + unexpected_lines: typing.List[str]): + """ + Setup: Updates resource mapping file using existing CloudFormation stacks. + Tests: Interact with AWS S3, DynamoDB and Lambda services. + Verification: Script canvas nodes can communicate with AWS services successfully. + """ + + resource_mappings.clear_select_keys([AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY]) + log_monitor, s3_download_dir = setup(launcher, asset_processor) + write_test_data_to_dynamodb_table(resource_mappings, aws_utils) + + launcher.args = ['+LoadLevel', level] + launcher.args.extend(['-rhi=null']) + + with launcher.start(launch_ap=False): + result = log_monitor.monitor_log_for_lines( + expected_lines=expected_lines, + unexpected_lines=unexpected_lines, + halt_on_unexpected=True + ) + + assert result, "Expected lines weren't found." + + assert os.path.exists(os.path.join(s3_download_dir, 'output.txt')), \ + 'The expected file wasn\'t successfully downloaded.' + # clean up the file directories. + shutil.rmtree(s3_download_dir) diff --git a/AutomatedTesting/Gem/PythonTests/AWS/common/resource_mappings.py b/AutomatedTesting/Gem/PythonTests/AWS/common/resource_mappings.py index 5f01ecdbf8..988d5bf1fc 100644 --- a/AutomatedTesting/Gem/PythonTests/AWS/common/resource_mappings.py +++ b/AutomatedTesting/Gem/PythonTests/AWS/common/resource_mappings.py @@ -102,3 +102,17 @@ class ResourceMappings: def get_resource_name_id(self, resource_key: str): return self._resource_mappings[AWS_RESOURCE_MAPPINGS_KEY][resource_key]['Name/ID'] + + def clear_select_keys(self, resource_keys=None) -> None: + """ + Clears values from select resource mapping keys. + :param resource_keys: list of keys to clear out + """ + with open(self._resource_mapping_file_path) as file_content: + resource_mappings = json.load(file_content) + + for key in resource_keys: + resource_mappings[key] = '' + + with open(self._resource_mapping_file_path, 'w') as file_content: + json.dump(resource_mappings, file_content, indent=4) \ No newline at end of file diff --git a/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingConstants.h b/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingConstants.h index 97eb5b6492..a3d18c1ea1 100644 --- a/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingConstants.h +++ b/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingConstants.h @@ -68,7 +68,7 @@ namespace AWSCore }, "AccountIdString": { "type": "string", - "pattern": "^[0-9]{12}$|EMPTY" + "pattern": "^[0-9]{12}$|EMPTY|^$" }, "NonEmptyString": { "type": "string", diff --git a/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp b/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp index fb03dea4c0..a90518006f 100644 --- a/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp +++ b/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp @@ -59,6 +59,34 @@ R"({ "Version": "1.0.0" })"; +static constexpr const char TEST_VALID_EMPTY_ACCOUNTID_RESOURCE_MAPPING_CONFIG_FILE[] = + R"({ + "AWSResourceMappings": { + "TestLambda": { + "Type": "AWS::Lambda::Function", + "Name/ID": "MyTestLambda", + "Region": "us-east-1", + "AccountId": "012345678912" + }, + "TestS3Bucket": { + "Type": "AWS::S3::Bucket", + "Name/ID": "MyTestS3Bucket" + }, + "TestService.RESTApiId": { + "Type": "AWS::ApiGateway::RestApi", + "Name/ID": "1234567890" + }, + "TestService.RESTApiStage": { + "Type": "AWS::ApiGateway::Stage", + "Name/ID": "prod", + "Region": "us-east-1" + } + }, + "AccountId": "", + "Region": "us-west-2", + "Version": "1.0.0" +})"; + static constexpr const char TEST_INVALID_RESOURCE_MAPPING_CONFIG_FILE[] = R"({ "AWSResourceMappings": {}, @@ -237,6 +265,21 @@ TEST_F(AWSResourceMappingManagerTest, ActivateManager_ParseValidConfigFile_Confi EXPECT_TRUE(actualEbusCalls == testThreadNumber); } +TEST_F(AWSResourceMappingManagerTest, ActivateManager_ParseValidConfigFile_GlobalAccountIdEmpty) +{ + CreateTestConfigFile(TEST_VALID_EMPTY_ACCOUNTID_RESOURCE_MAPPING_CONFIG_FILE); + m_resourceMappingManager->ActivateManager(); + + AZStd::string actualAccountId; + AZStd::string actualRegion; + AWSResourceMappingRequestBus::BroadcastResult(actualAccountId, &AWSResourceMappingRequests::GetDefaultAccountId); + AWSResourceMappingRequestBus::BroadcastResult(actualRegion, &AWSResourceMappingRequests::GetDefaultRegion); + EXPECT_EQ(m_reloadConfigurationCounter, 0); + EXPECT_TRUE(actualAccountId.empty()); + EXPECT_FALSE(actualRegion.empty()); + EXPECT_TRUE(m_resourceMappingManager->GetStatus() == AWSResourceMappingManager::Status::Ready); +} + TEST_F(AWSResourceMappingManagerTest, DeactivateManager_AfterActivatingWithValidConfigFile_ConfigDataGetCleanedUp) { CreateTestConfigFile(TEST_VALID_RESOURCE_MAPPING_CONFIG_FILE); From 7031147e324602fb20fcfe2070a942bf9eb4594a Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 15 Nov 2021 17:01:47 -0600 Subject: [PATCH 93/97] Added event to signal when the Editor is fully initialized so test scripts can listen for that instead of needed arbitrary wait commands. (#5623) Signed-off-by: Chris Galvan --- Code/Editor/CryEdit.cpp | 2 ++ .../AzToolsFramework/API/ToolsApplicationAPI.h | 3 +++ .../AzToolsFramework/Application/ToolsApplication.cpp | 8 +++++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 4008710786..b77c6c4b3a 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -4181,6 +4181,8 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[]) "\nThis could be because of incorrectly configured components, or missing required gems." "\nSee other errors for more details."); + AzToolsFramework::EditorEventsBus::Broadcast(&AzToolsFramework::EditorEvents::NotifyEditorInitialized); + if (didCryEditStart) { app->EnableOnIdle(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h index fd4196a296..282898c37d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h @@ -927,6 +927,9 @@ namespace AzToolsFramework /// Notify that the MainWindow has been fully initialized virtual void NotifyMainWindowInitialized(QMainWindow* /*mainWindow*/) {} + /// Notify that the Editor has been fully initialized + virtual void NotifyEditorInitialized() {} + /// Signal that an asset should be highlighted / selected virtual void SelectAsset(const QString& /* assetPath */) {} }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp index 3c7495e836..056872edab 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp @@ -214,12 +214,17 @@ namespace AzToolsFramework , public AZ::BehaviorEBusHandler { AZ_EBUS_BEHAVIOR_BINDER(EditorEventsBusHandler, "{352F80BB-469A-40B6-B322-FE57AB51E4DA}", AZ::SystemAllocator, - NotifyRegisterViews); + NotifyRegisterViews, NotifyEditorInitialized); void NotifyRegisterViews() override { Call(FN_NotifyRegisterViews); } + + void NotifyEditorInitialized() override + { + Call(FN_NotifyEditorInitialized); + } }; } // Internal @@ -443,6 +448,7 @@ namespace AzToolsFramework ->Attribute(AZ::Script::Attributes::Module, "editor") ->Handler() ->Event("NotifyRegisterViews", &EditorEvents::NotifyRegisterViews) + ->Event("NotifyEditorInitialized", &EditorEvents::NotifyEditorInitialized) ; behaviorContext->EBus("ViewPaneCallbackBus") From a5adf33427e3b2163c2f21c75148598b3364d8d4 Mon Sep 17 00:00:00 2001 From: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> Date: Tue, 16 Nov 2021 11:47:02 +0100 Subject: [PATCH 94/97] Deactivate new Asset Picker View by default in the Editor (#5614) Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> --- .../AssetBrowser/AssetPicker/AssetPickerDialog.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp index 4ebeb03a71..eae8ec2a1e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp @@ -31,7 +31,10 @@ AZ_POP_DISABLE_WARNING AZ_CVAR( bool, ed_hideAssetPickerPathColumn, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Hide AssetPicker path column for a clearer view."); -AZ_CVAR_EXTERNED(bool, ed_useNewAssetBrowserTableView); + +AZ_CVAR( + bool, ed_useNewAssetPickerView, false, nullptr, AZ::ConsoleFunctorFlags::Null, + "Uses the new Asset Picker View."); namespace AzToolsFramework { @@ -106,7 +109,7 @@ namespace AzToolsFramework m_persistentState = AZ::UserSettings::CreateFind(AZ::Crc32(("AssetBrowserTreeView_Dialog_" + name).toUtf8().data()), AZ::UserSettings::CT_GLOBAL); m_ui->m_assetBrowserTableViewWidget->setVisible(false); - if (ed_useNewAssetBrowserTableView) + if (ed_useNewAssetPickerView) { m_ui->m_assetBrowserTreeViewWidget->setVisible(false); m_ui->m_assetBrowserTableViewWidget->setVisible(true); From 7da0913900b6c93a0dfaa77f6880316ac70e7852 Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Tue, 16 Nov 2021 10:57:32 +0000 Subject: [PATCH 95/97] Fixed empty cluster UI appearing in joints component mode. (#5547) Happens if 'limits' or 'breakable' settings are off on the joint when entering component mode. Signed-off-by: amzn-sean <75276488+amzn-sean@users.noreply.github.com> --- .../Joints/JointsComponentMode.cpp | 128 +++++++++++------- 1 file changed, 78 insertions(+), 50 deletions(-) diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp index ce95e27db3..08e31a89f0 100644 --- a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp @@ -307,7 +307,16 @@ namespace PhysX AZStd::vector JointsComponentMode::PopulateViewportUiImpl() { - return AZStd::vector(m_modeSelectionClusterIds.begin(), m_modeSelectionClusterIds.end()); + AZStd::vector ids; + ids.reserve(m_modeSelectionClusterIds.size()); + for (auto clusterid : m_modeSelectionClusterIds) + { + if (clusterid != AzToolsFramework::ViewportUi::InvalidClusterId) + { + ids.emplace_back(clusterid); + } + } + return ids; } void JointsComponentMode::SetCurrentMode(JointsComponentModeCommon::SubComponentModes::ModeType newMode, ButtonData& buttonData) @@ -353,31 +362,64 @@ namespace PhysX void JointsComponentMode::SetupSubModes(const AZ::EntityComponentIdPair& entityComponentIdPair) { - //create the 3 cluster groups - for (auto& clusterId : m_modeSelectionClusterIds) - { - AzToolsFramework::ViewportUi::ViewportUiRequestBus::EventResult( - clusterId, AzToolsFramework::ViewportUi::DefaultViewportId, - &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::CreateCluster, - AzToolsFramework::ViewportUi::Alignment::TopLeft); - } - //retrieve the enabled sub components from the entity AZStd::vector subModesState; EditorJointRequestBus::EventResult(subModesState, entityComponentIdPair, &EditorJointRequests::GetSubComponentModesState); + //group 1 is always available so create it + AzToolsFramework::ViewportUi::ViewportUiRequestBus::EventResult( + m_modeSelectionClusterIds[static_cast(ClusterGroups::Group1)], AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::CreateCluster, AzToolsFramework::ViewportUi::Alignment::TopLeft); + + //check if groups 2 and/or 3 need to be created + for (auto [modeType, _] : subModesState) + { + const AzToolsFramework::ViewportUi::ClusterId group2Id = GetClusterId(ClusterGroups::Group2); + const AzToolsFramework::ViewportUi::ClusterId group3Id = GetClusterId(ClusterGroups::Group3); + switch (modeType) + { + case JointsComponentModeCommon::SubComponentModes::ModeType::Damping: + case JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness: + case JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits: + case JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits: + { + if (group2Id == AzToolsFramework::ViewportUi::InvalidClusterId) + { + AzToolsFramework::ViewportUi::ViewportUiRequestBus::EventResult( + m_modeSelectionClusterIds[static_cast(ClusterGroups::Group2)], + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::CreateCluster, + AzToolsFramework::ViewportUi::Alignment::TopLeft); + } + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce: + case JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque: + { + if (group3Id == AzToolsFramework::ViewportUi::InvalidClusterId) + { + AzToolsFramework::ViewportUi::ViewportUiRequestBus::EventResult( + m_modeSelectionClusterIds[static_cast(ClusterGroups::Group3)], + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::CreateCluster, + AzToolsFramework::ViewportUi::Alignment::TopLeft); + } + } + break; + default: + AZ_Error("Joints", false, "Joints component mode cluster UI setup found unknown sub mode."); + break; + } + //if both are created - break; + if (group2Id != AzToolsFramework::ViewportUi::InvalidClusterId && group3Id != AzToolsFramework::ViewportUi::InvalidClusterId) + { + break; + } + } + const AzToolsFramework::ViewportUi::ClusterId group1ClusterId = GetClusterId(ClusterGroups::Group1); const AzToolsFramework::ViewportUi::ClusterId group2ClusterId = GetClusterId(ClusterGroups::Group2); - //hide cluster 2, if something is added to it. it will make is visible - AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( - AzToolsFramework::ViewportUi::DefaultViewportId, &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, - group2ClusterId, false); - const AzToolsFramework::ViewportUi::ClusterId group3ClusterId = GetClusterId(ClusterGroups::Group3); - // hide cluster 3, if something is added to it. it will make is visible - AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( - AzToolsFramework::ViewportUi::DefaultViewportId, &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, - group3ClusterId, false); //translation and rotation are enabled for all joints in group 1 m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::Translation] = @@ -408,10 +450,6 @@ namespace PhysX Internal::RegisterClusterButton(group3ClusterId, "joints/MaxForce", SubModeData::MaxForceToolTip); m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce] = ButtonData{ group3ClusterId, buttonId }; - - AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( - AzToolsFramework::ViewportUi::DefaultViewportId, - &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group3ClusterId, true); } break; case JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque: @@ -424,10 +462,6 @@ namespace PhysX Internal::RegisterClusterButton(group3ClusterId, "joints/MaxTorque", SubModeData::MaxTorqueToolTip); m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque] = ButtonData{ group3ClusterId, buttonId }; - - AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( - AzToolsFramework::ViewportUi::DefaultViewportId, - &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group3ClusterId, true); } break; case JointsComponentModeCommon::SubComponentModes::ModeType::Damping: @@ -439,10 +473,6 @@ namespace PhysX const AzToolsFramework::ViewportUi::ButtonId buttonId = Internal::RegisterClusterButton(group2ClusterId, "joints/Damping", SubModeData::DampingToolTip); m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Damping] = ButtonData{ group2ClusterId, buttonId }; - - AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( - AzToolsFramework::ViewportUi::DefaultViewportId, - &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true); } break; case JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness: @@ -455,10 +485,6 @@ namespace PhysX Internal::RegisterClusterButton(group2ClusterId, "joints/Stiffness", SubModeData::StiffnessToolTip); m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness] = ButtonData{ group2ClusterId, buttonId }; - - AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( - AzToolsFramework::ViewportUi::DefaultViewportId, - &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true); } break; case JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits: @@ -473,10 +499,6 @@ namespace PhysX Internal::RegisterClusterButton(group2ClusterId, "joints/TwistLimits", SubModeData::TwistLimitsToolTip); m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits] = ButtonData{ group2ClusterId, buttonId }; - - AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( - AzToolsFramework::ViewportUi::DefaultViewportId, - &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true); } break; case JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits: @@ -489,10 +511,6 @@ namespace PhysX Internal::RegisterClusterButton(group2ClusterId, "joints/SwingLimits", SubModeData::SwingLimitsToolTip); m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits] = ButtonData{ group2ClusterId, buttonId }; - - AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( - AzToolsFramework::ViewportUi::DefaultViewportId, - &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true); } break; case JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition: @@ -517,6 +535,9 @@ namespace PhysX ButtonData{ group1ClusterId, buttonId }; } break; + default: + AZ_Error("Joints", false, "Joints component mode cluster button setup found unknown sub mode."); + break; } } @@ -560,10 +581,13 @@ namespace PhysX for (int i = 0; i < static_cast(ClusterGroups::GroupCount); i++) { - AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( - AzToolsFramework::ViewportUi::DefaultViewportId, - &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RegisterClusterEventHandler, m_modeSelectionClusterIds[i], - m_modeSelectionHandlers[i]); + if (m_modeSelectionClusterIds[i] != AzToolsFramework::ViewportUi::InvalidClusterId) + { + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RegisterClusterEventHandler, + m_modeSelectionClusterIds[i], m_modeSelectionHandlers[i]); + } } // set the translate as enabled by default. @@ -588,10 +612,14 @@ namespace PhysX { for (auto clusterid : m_modeSelectionClusterIds) { - AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( - AzToolsFramework::ViewportUi::DefaultViewportId, &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RemoveCluster, - clusterid); + if (clusterid != AzToolsFramework::ViewportUi::InvalidClusterId) + { + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RemoveCluster, clusterid); + } } + m_modeSelectionClusterIds.assign(static_cast(ClusterGroups::GroupCount), AzToolsFramework::ViewportUi::InvalidClusterId); } AzToolsFramework::ViewportUi::ClusterId JointsComponentMode::GetClusterId(ClusterGroups group) From ce10906671fcf47c6614285c94ac53905fa4a2c1 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Tue, 16 Nov 2021 08:08:53 -0600 Subject: [PATCH 96/97] Updated splash screen and about dialog with Stable 21.11 name Signed-off-by: Chris Galvan --- Code/Editor/AboutDialog.ui | 2 +- Code/Editor/StartupLogoDialog.ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Editor/AboutDialog.ui b/Code/Editor/AboutDialog.ui index a6c5bb5d52..a36d65e35b 100644 --- a/Code/Editor/AboutDialog.ui +++ b/Code/Editor/AboutDialog.ui @@ -125,7 +125,7 @@ - General Availability + Stable 21.11 Qt::AutoText diff --git a/Code/Editor/StartupLogoDialog.ui b/Code/Editor/StartupLogoDialog.ui index c0b8115cb0..c2cbfcfd69 100644 --- a/Code/Editor/StartupLogoDialog.ui +++ b/Code/Editor/StartupLogoDialog.ui @@ -103,7 +103,7 @@ - General Availability + Stable 21.11 From b20a9b5f39b025475d74f166a2634f74b835fdca Mon Sep 17 00:00:00 2001 From: bosnichd Date: Tue, 16 Nov 2021 08:27:32 -0700 Subject: [PATCH 97/97] Some modifications required for restricted platforms: (#5624) - Replace AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS with AZ_TRAIT_THREAD_NUM_JOB_MANAGER_WORKER_THREADS that allows the number of threads created by the job manager to be set directly. - Add AZ_TRAIT_THREAD_NUM_TASK_GRAPH_WORKER_THREADS that allows the number of threads created by the task graph to be set directly. - Add a define that forces the AsyncUploadQueue to use the primary copy queue instead of creating a secondary copy queue. Signed-off-by: bosnichd --- .../AzCore/AzCore/Jobs/JobManagerComponent.cpp | 7 ++++--- .../AzCore/AzCore/Task/TaskGraphSystemComponent.cpp | 7 ++++++- .../Platform/Android/AzCore/AzCore_Traits_Android.h | 1 - .../AzCore/Platform/Linux/AzCore/AzCore_Traits_Linux.h | 1 - .../AzCore/Platform/Mac/AzCore/AzCore_Traits_Mac.h | 1 - .../Platform/Windows/AzCore/AzCore_Traits_Windows.h | 1 - .../AzCore/Platform/iOS/AzCore/AzCore_Traits_iOS.h | 1 - .../Atom/RHI/DX12/Code/Source/RHI/AsyncUploadQueue.cpp | 10 +++++++++- 8 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp b/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp index 6f5ccc93e4..2307a9372c 100644 --- a/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp @@ -56,11 +56,12 @@ namespace AZ int numberOfWorkerThreads = m_numberOfWorkerThreads; if (numberOfWorkerThreads <= 0) // spawn default number of threads { + #if (AZ_TRAIT_THREAD_NUM_JOB_MANAGER_WORKER_THREADS) + numberOfWorkerThreads = AZ_TRAIT_THREAD_NUM_JOB_MANAGER_WORKER_THREADS; + #else uint32_t scaledHardwareThreads = Threading::CalcNumWorkerThreads(cl_jobThreadsConcurrencyRatio, cl_jobThreadsMinNumber, cl_jobThreadsNumReserved); numberOfWorkerThreads = AZ::GetMin(static_cast(desc.m_workerThreads.capacity()), scaledHardwareThreads); - #if (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS) - numberOfWorkerThreads = AZ::GetMin(numberOfWorkerThreads, AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS); - #endif // (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS) + #endif // (AZ_TRAIT_THREAD_NUM_JOB_MANAGER_WORKER_THREADS) } threadDesc.m_cpuId = AFFINITY_MASK_USERTHREADS; diff --git a/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp index 56b56e96a1..1cacef7ff3 100644 --- a/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp @@ -30,8 +30,13 @@ namespace AZ if (Interface::Get() == nullptr) { + #if (AZ_TRAIT_THREAD_NUM_TASK_GRAPH_WORKER_THREADS) + const uint32_t numberOfWorkerThreads = AZ_TRAIT_THREAD_NUM_TASK_GRAPH_WORKER_THREADS; + #else + const uint32_t numberOfWorkerThreads = Threading::CalcNumWorkerThreads(cl_taskGraphThreadsConcurrencyRatio, cl_taskGraphThreadsMinNumber, cl_taskGraphThreadsNumReserved); + #endif // (AZ_TRAIT_THREAD_NUM_TASK_GRAPH_WORKER_THREADS) Interface::Register(this); // small window that another thread can try to use taskgraph between this line and the set instance. - m_taskExecutor = aznew TaskExecutor(Threading::CalcNumWorkerThreads(cl_taskGraphThreadsConcurrencyRatio, cl_taskGraphThreadsMinNumber, cl_taskGraphThreadsNumReserved)); + m_taskExecutor = aznew TaskExecutor(numberOfWorkerThreads); TaskExecutor::SetInstance(m_taskExecutor); } } diff --git a/Code/Framework/AzCore/Platform/Android/AzCore/AzCore_Traits_Android.h b/Code/Framework/AzCore/Platform/Android/AzCore/AzCore_Traits_Android.h index 495c8d5f2c..e05e000a4e 100644 --- a/Code/Framework/AzCore/Platform/Android/AzCore/AzCore_Traits_Android.h +++ b/Code/Framework/AzCore/Platform/Android/AzCore/AzCore_Traits_Android.h @@ -75,7 +75,6 @@ #define AZ_TRAIT_HEAPSCHEMA_COMPILE_MALLINFO 0 #define AZ_TRAIT_IS_ABS_PATH_IF_COLON_FOUND_ANYWHERE 0 #define AZ_TRAIT_JSON_CLANG_IGNORE_UNKNOWN_WARNING 0 -#define AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS 0 #define AZ_TRAIT_PERF_MEMORYBENCHMARK_IS_AVAILABLE 0 #define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING 0 #define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING_INTERVAL_MS 0 diff --git a/Code/Framework/AzCore/Platform/Linux/AzCore/AzCore_Traits_Linux.h b/Code/Framework/AzCore/Platform/Linux/AzCore/AzCore_Traits_Linux.h index 6ba369e86d..2c0d554078 100644 --- a/Code/Framework/AzCore/Platform/Linux/AzCore/AzCore_Traits_Linux.h +++ b/Code/Framework/AzCore/Platform/Linux/AzCore/AzCore_Traits_Linux.h @@ -75,7 +75,6 @@ #define AZ_TRAIT_HEAPSCHEMA_COMPILE_MALLINFO 1 #define AZ_TRAIT_IS_ABS_PATH_IF_COLON_FOUND_ANYWHERE 0 #define AZ_TRAIT_JSON_CLANG_IGNORE_UNKNOWN_WARNING 0 -#define AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS 0 #define AZ_TRAIT_PERF_MEMORYBENCHMARK_IS_AVAILABLE 0 #define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING 0 #define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING_INTERVAL_MS 0 diff --git a/Code/Framework/AzCore/Platform/Mac/AzCore/AzCore_Traits_Mac.h b/Code/Framework/AzCore/Platform/Mac/AzCore/AzCore_Traits_Mac.h index a41b5c6baa..816a28b728 100644 --- a/Code/Framework/AzCore/Platform/Mac/AzCore/AzCore_Traits_Mac.h +++ b/Code/Framework/AzCore/Platform/Mac/AzCore/AzCore_Traits_Mac.h @@ -75,7 +75,6 @@ #define AZ_TRAIT_HEAPSCHEMA_COMPILE_MALLINFO 1 #define AZ_TRAIT_IS_ABS_PATH_IF_COLON_FOUND_ANYWHERE 0 #define AZ_TRAIT_JSON_CLANG_IGNORE_UNKNOWN_WARNING 0 -#define AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS 0 #define AZ_TRAIT_PERF_MEMORYBENCHMARK_IS_AVAILABLE 0 #define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING 0 #define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING_INTERVAL_MS 0 diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/AzCore_Traits_Windows.h b/Code/Framework/AzCore/Platform/Windows/AzCore/AzCore_Traits_Windows.h index 2f9fcefdbd..83cff9b54f 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/AzCore_Traits_Windows.h +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/AzCore_Traits_Windows.h @@ -75,7 +75,6 @@ #define AZ_TRAIT_HEAPSCHEMA_COMPILE_MALLINFO 1 #define AZ_TRAIT_IS_ABS_PATH_IF_COLON_FOUND_ANYWHERE 0 #define AZ_TRAIT_JSON_CLANG_IGNORE_UNKNOWN_WARNING 1 -#define AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS 0 #define AZ_TRAIT_PERF_MEMORYBENCHMARK_IS_AVAILABLE 1 #define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING 0 #define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING_INTERVAL_MS 0 diff --git a/Code/Framework/AzCore/Platform/iOS/AzCore/AzCore_Traits_iOS.h b/Code/Framework/AzCore/Platform/iOS/AzCore/AzCore_Traits_iOS.h index d53f4b057e..b0832c54f6 100644 --- a/Code/Framework/AzCore/Platform/iOS/AzCore/AzCore_Traits_iOS.h +++ b/Code/Framework/AzCore/Platform/iOS/AzCore/AzCore_Traits_iOS.h @@ -76,7 +76,6 @@ #define AZ_TRAIT_HEAPSCHEMA_COMPILE_MALLINFO 1 #define AZ_TRAIT_IS_ABS_PATH_IF_COLON_FOUND_ANYWHERE 0 #define AZ_TRAIT_JSON_CLANG_IGNORE_UNKNOWN_WARNING 0 -#define AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS 0 #define AZ_TRAIT_PERF_MEMORYBENCHMARK_IS_AVAILABLE 0 #define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING 0 #define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING_INTERVAL_MS 0 diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/AsyncUploadQueue.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/AsyncUploadQueue.cpp index 5f85d3ad03..fc80cc50d6 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/AsyncUploadQueue.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/AsyncUploadQueue.cpp @@ -33,12 +33,20 @@ namespace AZ ID3D12DeviceX* dx12Device = device.GetDevice(); m_copyQueue = CommandQueue::Create(); - + + // The async upload queue should always use the primary copy queue, + // but because this change is being made in the stabilization branch + // we will put it behind a define out of an abundance of caution, and + // change it to always do this once the change gets back to development. + #if defined(AZ_DX12_USE_PRIMARY_COPY_QUEUE_FOR_ASYNC_UPLOAD_QUEUE) + m_copyQueue = &device.GetCommandQueueContext().GetCommandQueue(RHI::HardwareQueueClass::Copy); + #else // Make a secondary Copy queue, the primary queue is owned by the CommandQueueContext CommandQueueDescriptor commandQueueDesc; commandQueueDesc.m_hardwareQueueClass = RHI::HardwareQueueClass::Copy; commandQueueDesc.m_hardwareQueueSubclass = HardwareQueueSubclass::Secondary; m_copyQueue->Init(device, commandQueueDesc); + #endif // defined(AZ_DX12_ASYNC_UPLOAD_QUEUE_USE_PRIMARY_COPY_QUEUE) m_uploadFence.Init(dx12Device, RHI::FenceState::Signaled); for (size_t i = 0; i < descriptor.m_frameCount; ++i)