From 672c82f69dc0fd8002ebb33bb928cfe6fdf6b772 Mon Sep 17 00:00:00 2001 From: Tommy Walton Date: Tue, 2 Nov 2021 16:40:56 -0700 Subject: [PATCH 01/32] Add a default fallback image when a StreamingImageAsset fails to load Signed-off-by: Tommy Walton --- .../Image/StreamingImageAssetHandler.h | 2 ++ .../Image/StreamingImageAssetHandler.cpp | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+) 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..f69463ae60 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,8 @@ namespace AZ const Data::Asset& asset, AZStd::shared_ptr stream, const Data::AssetFilterCB& assetLoadFilterCB) override; + + 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..e73d8e1c03 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,7 @@ */ #include +#include namespace AZ { @@ -40,5 +41,34 @@ namespace AZ return loadResult; } + + Data::AssetId StreamingImageAssetHandler::AssetMissingInCatalog(const Data::Asset& asset) + { + // Escalate the asset to the top of the list + AzFramework::AssetSystemRequestBus::Broadcast( + &AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetByUuid, asset.GetId().m_guid); + + // Make sure the default fallback image has been processed so that it is part of the asset catalog + AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown; + AzFramework::AssetSystemRequestBus::BroadcastResult( + status, &AzFramework::AssetSystemRequestBus::Events::CompileAssetSync, "textures/defaults/defaultnouvs.tif.streamingimage"); + + // Get the id of the fallback image + Data::AssetInfo assetInfo; + assetInfo.m_relativePath = "textures/defaults/defaultnouvs.tif.streamingimage"; + Data::AssetId assetId; + Data::AssetCatalogRequestBus::BroadcastResult( + assetId, &Data::AssetCatalogRequestBus::Events::GenerateAssetIdTEMP, + assetInfo.m_relativePath.c_str()); + + assetInfo.m_assetId = Data::AssetId(assetId.m_guid, StreamingImageAsset::GetImageAssetSubId()); + + // Register the fallback image with the asset catalog + Data::AssetCatalogRequestBus::Broadcast( + &Data::AssetCatalogRequestBus::Events::RegisterAsset, assetInfo.m_assetId, assetInfo); + + // Use a default Image as a fallback + return assetInfo.m_assetId; + } } } From ae1c0f6f83b13a7b2e589eae71f9810dd4a59920 Mon Sep 17 00:00:00 2001 From: Tommy Walton Date: Wed, 3 Nov 2021 15:05:37 -0700 Subject: [PATCH 02/32] 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 --- .../Code/Source/SkyBox/HDRiSkyboxComponentController.cpp | 2 -- 1 file changed, 2 deletions(-) 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 c93d678cf462a3399e8e82895f4c26e59800077f Mon Sep 17 00:00:00 2001 From: Tommy Walton Date: Wed, 3 Nov 2021 16:32:03 -0700 Subject: [PATCH 03/32] 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 --- .../ImageBasedLights/ImageBasedLightComponentController.cpp | 2 -- 1 file changed, 2 deletions(-) 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; } From 09b9d371e05a8dc085d40f5f8fac4ae01165f0be Mon Sep 17 00:00:00 2001 From: Tommy Walton Date: Wed, 10 Nov 2021 13:20:25 -0800 Subject: [PATCH 04/32] 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 --- .../Image/StreamingImageAssetHandler.cpp | 59 ++++++++++++++----- .../Atom/RPI/Registry/atom_rpi.release.setreg | 9 +++ Gems/Atom/RPI/Registry/atom_rpi.setreg | 3 +- 3 files changed, 55 insertions(+), 16 deletions(-) create mode 100644 Gems/Atom/RPI/Registry/atom_rpi.release.setreg 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 e73d8e1c03..f241ba6602 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,7 @@ */ #include +#include #include namespace AZ @@ -44,30 +45,58 @@ namespace AZ Data::AssetId StreamingImageAssetHandler::AssetMissingInCatalog(const Data::Asset& asset) { - // Escalate the asset to the top of the list - AzFramework::AssetSystemRequestBus::Broadcast( - &AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetByUuid, asset.GetId().m_guid); - - // Make sure the default fallback image has been processed so that it is part of the asset catalog - AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown; + // 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( - status, &AzFramework::AssetSystemRequestBus::Events::CompileAssetSync, "textures/defaults/defaultnouvs.tif.streamingimage"); + missingAssetStatus, &AzFramework::AssetSystem::AssetSystemRequests::GetAssetStatusById, asset.GetId().m_guid); - // Get the id of the fallback image + // Generate asset info to use to register the fallback asset with the asset catalog Data::AssetInfo assetInfo; - assetInfo.m_relativePath = "textures/defaults/defaultnouvs.tif.streamingimage"; - Data::AssetId assetId; + assetInfo.m_relativePath = "textures/defaults/defaultfallback.png.streamingimage"; + assetInfo.m_assetType = azrtti_typeid(); + + 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: + assetInfo.m_relativePath = "textures/defaults/processing.png.streamingimage"; + break; + case AzFramework::AssetSystem::AssetStatus::AssetStatus_Failed: + assetInfo.m_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: + assetInfo.m_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, assetInfo.m_relativePath); + + // Generate the id of the fallback image Data::AssetCatalogRequestBus::BroadcastResult( - assetId, &Data::AssetCatalogRequestBus::Events::GenerateAssetIdTEMP, + assetInfo.m_assetId, &Data::AssetCatalogRequestBus::Events::GenerateAssetIdTEMP, assetInfo.m_relativePath.c_str()); - assetInfo.m_assetId = Data::AssetId(assetId.m_guid, StreamingImageAsset::GetImageAssetSubId()); + assetInfo.m_assetId.m_subId = StreamingImageAsset::GetImageAssetSubId(); // Register the fallback image with the asset catalog - Data::AssetCatalogRequestBus::Broadcast( - &Data::AssetCatalogRequestBus::Events::RegisterAsset, assetInfo.m_assetId, assetInfo); + Data::AssetCatalogRequestBus::Broadcast(&Data::AssetCatalogRequestBus::Events::RegisterAsset, assetInfo.m_assetId, assetInfo); - // Use a default Image as a fallback + // Return the asset id of the fallback image return assetInfo.m_assetId; } } 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..d1be96431d --- /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..bf6d95602e 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 } } } From 98ca3aab6b2d9c2158eef94819182ae02a1d8d4d Mon Sep 17 00:00:00 2001 From: Tommy Walton Date: Wed, 10 Nov 2021 13:55:22 -0800 Subject: [PATCH 05/32] Adding the stubbed in fallback textures Signed-off-by: Tommy Walton --- Gems/Atom/RPI/Assets/Textures/Defaults/DefaultFallback.png | 3 +++ Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png | 3 +++ Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png | 3 +++ Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png | 3 +++ 4 files changed, 12 insertions(+) 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 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 From cd28d210abef5e0dc20c331b99be2909fdd7688b Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Wed, 10 Nov 2021 14:02:17 -0800 Subject: [PATCH 06/32] Working on making Material Editor able to open materials that have missing textures. Made it a warning instead of an error when MaterialAssetCreator can't find a texture. Updated the Material Editor's MaterialDocument class to not elevate warnings to errors. Material Editor uses new features in TraceRecorder to show a message dialog when warnings are detected so the user is notified of the missing texture. Next I will work on making MaterialAssetCreator put a "missing" texture in place of the requested one. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../RPI.Edit/Material/MaterialSourceData.cpp | 2 +- .../AtomToolsFramework/Debug/TraceRecorder.h | 21 ++++++++ .../Code/Source/Debug/TraceRecorder.cpp | 51 +++++++++++++++++++ .../AtomToolsDocumentSystemComponent.cpp | 8 ++- .../Code/Source/Document/MaterialDocument.cpp | 8 +-- 5 files changed, 84 insertions(+), 6 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 d6308ec655..40fc9e096f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -329,7 +329,7 @@ namespace AZ } else { - materialAssetCreator.ReportError( + materialAssetCreator.ReportWarning( "Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), property.second.m_value.GetValue().data()); } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h index 96a8728a43..fc19aea2d3 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h @@ -26,6 +26,21 @@ namespace AtomToolsFramework //! Get the combined output of all messages AZStd::string GetDump() const; + //! Return the number of OnAssert calls + size_t GetAssertCount() const; + + //! Return the number of OnException calls + size_t GetExceptionCount() const; + + //! Return the number of OnError calls, and includes OnAssert and OnException if @includeHigher is true + size_t GetErrorCount(bool includeHigher = false) const; + + //! Return the number of OnWarning calls, and includes higher categories if @includeHigher is true + size_t GetWarningCount(bool includeHigher = false) const; + + //! Return the number of OnPrintf calls, and includes higher categories if @includeHigher is true + size_t GetPrintfCount(bool includeHigher = false) const; + private: ////////////////////////////////////////////////////////////////////////// // AZ::Debug::TraceMessageBus::Handler overrides... @@ -38,5 +53,11 @@ namespace AtomToolsFramework size_t m_maxMessageCount = std::numeric_limits::max(); AZStd::list m_messages; + + size_t m_assertCount = 0; + size_t m_exceptionCount = 0; + size_t m_errorCount = 0; + size_t m_warningCount = 0; + size_t m_printfCount = 0; }; } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp index 3fd069ff0b..5f8c8b9004 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp @@ -31,6 +31,7 @@ namespace AtomToolsFramework bool TraceRecorder::OnAssert(const char* message) { + ++m_assertCount; if (m_messages.size() < m_maxMessageCount) { m_messages.push_back(AZStd::string::format("Assert: %s", message)); @@ -40,6 +41,7 @@ namespace AtomToolsFramework bool TraceRecorder::OnException(const char* message) { + ++m_exceptionCount; if (m_messages.size() < m_maxMessageCount) { m_messages.push_back(AZStd::string::format("Exception: %s", message)); @@ -49,6 +51,7 @@ namespace AtomToolsFramework bool TraceRecorder::OnError(const char* /*window*/, const char* message) { + ++m_errorCount; if (m_messages.size() < m_maxMessageCount) { m_messages.push_back(AZStd::string::format("Error: %s", message)); @@ -58,6 +61,7 @@ namespace AtomToolsFramework bool TraceRecorder::OnWarning(const char* /*window*/, const char* message) { + ++m_warningCount; if (m_messages.size() < m_maxMessageCount) { m_messages.push_back(AZStd::string::format("Warning: %s", message)); @@ -67,11 +71,58 @@ namespace AtomToolsFramework bool TraceRecorder::OnPrintf(const char* /*window*/, const char* message) { + ++m_printfCount; if (m_messages.size() < m_maxMessageCount) { m_messages.push_back(AZStd::string::format("%s", message)); } return false; +} + + size_t TraceRecorder::GetAssertCount() const + { + return m_assertCount; + } + + size_t TraceRecorder::GetExceptionCount() const + { + return m_exceptionCount; + } + + size_t TraceRecorder::GetErrorCount(bool includeHigher) const + { + if (includeHigher) + { + return m_errorCount + GetAssertCount() + GetExceptionCount(); + } + else + { + return m_errorCount; + } + } + + size_t TraceRecorder::GetWarningCount(bool includeHigher) const + { + if (includeHigher) + { + return m_warningCount + GetErrorCount(true); + } + else + { + return m_warningCount; + } + } + + size_t TraceRecorder::GetPrintfCount(bool includeHigher) const + { + if (includeHigher) + { + return m_printfCount + GetWarningCount(true); + } + else + { + return m_printfCount; + } } } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp index 00de2a7c4c..3a392c1413 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp @@ -495,8 +495,6 @@ namespace AtomToolsFramework return AZ::Uuid::CreateNull(); } - traceRecorder.GetDump().clear(); - bool openResult = false; AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Open, requestedPath); if (!openResult) @@ -507,6 +505,12 @@ namespace AtomToolsFramework AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId); return AZ::Uuid::CreateNull(); } + else if (traceRecorder.GetWarningCount(true) > 0) + { + QMessageBox::warning( + QApplication::activeWindow(), QString("Document opened with warnings"), + QString("Warnings encountered: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); + } return documentId; } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index ee58cbea3e..6969e9f923 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -714,6 +714,8 @@ namespace MaterialEditor AZ_Error("MaterialDocument", false, "Material document extension not supported: '%s'.", m_absolutePath.c_str()); return false; } + + const bool elevateWarnings = false; // In order to support automation, general usability, and 'save as' functionality, the user must not have to wait // for their JSON file to be cooked by the asset processor before opening or editing it. @@ -722,7 +724,7 @@ namespace MaterialEditor // 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 materialAssetResult = - m_materialSourceData.CreateMaterialAssetFromSourceData(Uuid::CreateRandom(), m_absolutePath, true, true, &m_sourceDependencies); + m_materialSourceData.CreateMaterialAssetFromSourceData(Uuid::CreateRandom(), m_absolutePath, elevateWarnings, true, &m_sourceDependencies); if (!materialAssetResult) { AZ_Error("MaterialDocument", false, "Material asset could not be created from source data: '%s'.", m_absolutePath.c_str()); @@ -761,9 +763,9 @@ namespace MaterialEditor AZ_Error("MaterialDocument", false, "Material parent asset ID could not be created: '%s'.", parentMaterialFilePath.c_str()); return false; } - + auto parentMaterialAssetResult = parentMaterialSourceData.CreateMaterialAssetFromSourceData( - parentMaterialAssetIdResult.GetValue(), parentMaterialFilePath, true, true); + parentMaterialAssetIdResult.GetValue(), parentMaterialFilePath, elevateWarnings, true); if (!parentMaterialAssetResult) { AZ_Error("MaterialDocument", false, "Material parent asset could not be created from source data: '%s'.", parentMaterialFilePath.c_str()); From e40b226374b8e21f4a7614e05ece103057097565 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Wed, 10 Nov 2021 19:22:44 -0800 Subject: [PATCH 07/32] Updated the default fallback textures to have a smaller version of the message they they can be read at different UV scales. Added assetinfo files to make these be processed as "Reference Image" to avoid texture compression that makes the text difficult to read. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../RPI/Assets/Textures/Defaults/Missing.png | 4 +- .../Textures/Defaults/Missing.png.assetinfo | 91 +++++++++++ .../Assets/Textures/Defaults/Processing.png | 4 +- .../Defaults/Processing.png.assetinfo | 148 ++++++++++++++++++ .../Textures/Defaults/ProcessingFailed.png | 4 +- .../Defaults/ProcessingFailed.png.assetinfo | 148 ++++++++++++++++++ .../Assets/Textures/Defaults/wip/Missing.pdn | Bin 0 -> 18928 bytes .../Textures/Defaults/wip/Processing.pdn | Bin 0 -> 18995 bytes .../Defaults/wip/ProcessingFailed.pdn | Bin 0 -> 21667 bytes 9 files changed, 393 insertions(+), 6 deletions(-) create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png.assetinfo create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png.assetinfo create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png.assetinfo create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/wip/Missing.pdn create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/wip/Processing.pdn create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/wip/ProcessingFailed.pdn diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png b/Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png index 3e9bc68ea5..198d034892 100644 --- a/Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:28c3cfd8958813b4b539738bfff589731da0aeec5b3376558f377da2ebe973ff -size 5455 +oid sha256:7028c8db4f935f23aa4396668278a67691d92fe345cc9d417a9f47bd9a4af32b +size 8130 diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png.assetinfo b/Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png.assetinfo new file mode 100644 index 0000000000..264a7f2a25 --- /dev/null +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png.assetinfo @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png b/Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png index 914499d6e7..14c3ec76b0 100644 --- a/Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a0935be7347d695ed1716d030b5bae68153a88239b0ff15f67f900ac90be442 -size 5038 +oid sha256:a7d94b9c0a77741736b93d8ed4d2b22bc9ae4cf649f3d8b3f10cbaf595a3ed31 +size 8336 diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png.assetinfo b/Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png.assetinfo new file mode 100644 index 0000000000..4a234ef9f3 --- /dev/null +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png.assetinfo @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png b/Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png index 558b16b96e..aafdcc2681 100644 --- a/Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb243cd6d6414b4e95eab919fa94193b57825902b8d09f40ce3f334d829e74e2 -size 6286 +oid sha256:3bbd45e3ef81850da81d1cc01775930a53c424e64e287b00990af3e7e6a682ba +size 9701 diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png.assetinfo b/Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png.assetinfo new file mode 100644 index 0000000000..747ce3e0e2 --- /dev/null +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png.assetinfo @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/wip/Missing.pdn b/Gems/Atom/RPI/Assets/Textures/Defaults/wip/Missing.pdn new file mode 100644 index 0000000000000000000000000000000000000000..2ede3d837b276aca67709f35c243bc30cbcd7c35 GIT binary patch literal 18928 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 literal 0 HcmV?d00001 diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/wip/Processing.pdn b/Gems/Atom/RPI/Assets/Textures/Defaults/wip/Processing.pdn new file mode 100644 index 0000000000000000000000000000000000000000..994513301fa9993020455f12824abbf543cafd93 GIT binary patch literal 18995 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 literal 0 HcmV?d00001 diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/wip/ProcessingFailed.pdn b/Gems/Atom/RPI/Assets/Textures/Defaults/wip/ProcessingFailed.pdn new file mode 100644 index 0000000000000000000000000000000000000000..d6388621371a5f6fff90a7a3972ce9588cd1f6b6 GIT binary patch literal 21667 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 literal 0 HcmV?d00001 From f27203a5fa1c7e7701ce330648ea3cefec3f9689 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Wed, 10 Nov 2021 19:28:42 -0800 Subject: [PATCH 08/32] Updated Material Editor to use the available default fallback images to visually indicate a missing texture. Material Editor also warns the user when saving a material that is populated with fallback image references. Factored out the path strings for the default images to ImateSystemInterface.h. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Atom/RPI.Edit/Material/MaterialUtils.h | 14 +++++++- .../RPI.Public/Image/ImageSystemInterface.h | 8 +++++ .../RPI.Edit/Material/MaterialSourceData.cpp | 18 +++++------ .../Material/MaterialTypeSourceData.cpp | 9 +++--- .../RPI.Edit/Material/MaterialUtils.cpp | 28 +++++++++++----- .../Image/StreamingImageAssetHandler.cpp | 9 +++--- .../Document/AtomToolsDocumentRequestBus.h | 3 ++ .../AtomToolsDocumentSystemComponent.cpp | 18 +++++++++++ .../Code/Source/Document/MaterialDocument.cpp | 32 +++++++++++++++++++ .../Code/Source/Document/MaterialDocument.h | 1 + 10 files changed, 113 insertions(+), 27 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h index d12e848a02..f39b8e7aaa 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h @@ -28,7 +28,19 @@ namespace AZ namespace MaterialUtils { - Outcome> GetImageAssetReference(AZStd::string_view materialSourceFilePath, const AZStd::string imageFilePath); + enum class GetImageAssetResult + { + Empty, //! No image was actually requested, the path was empty + Found, //! The requested asset was found + Missing, //! The requested asset was not found, and a placeholder asset was used instead + MissingNoFallback //! The requested asset was not found, and a placeholder asset was not found either + }; + + //! Finds an ImageAsset referenced by a material file (or a placeholder) + //! @param imageAsset the resulting ImageAsset + //! @param materialSourceFilePath the full path to a material source file that is referenfing an image file + //! @param imageFilePath the path to an image source file, which could be relative to the asset root or relative to the material file + GetImageAssetResult GetImageAssetReference(Data::Asset& imageAsset, AZStd::string_view materialSourceFilePath, const AZStd::string imageFilePath); //! Resolve an enum to a uint32_t given its name and definition array (in MaterialPropertyDescriptor). //! @param propertyDescriptor it contains the definition of all enum names in an array. diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/ImageSystemInterface.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/ImageSystemInterface.h index f567881c50..920b763bc3 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/ImageSystemInterface.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/ImageSystemInterface.h @@ -29,6 +29,14 @@ namespace AZ Count }; + namespace DefaultImageAssetPaths + { + static constexpr char DefaultFallback[] = "textures/defaults/defaultfallback.png.streamingimage"; + static constexpr char Processing[] = "textures/defaults/processing.png.streamingimage"; + static constexpr char ProcessingFailed[] = "textures/defaults/processingfailed.png.streamingimage"; + static constexpr char Missing[] = "textures/defaults/missing.png.streamingimage"; + } + class ImageSystemInterface { public: 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 40fc9e096f..a8d61465a5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -317,22 +317,20 @@ namespace AZ { case MaterialPropertyDataType::Image: { - Outcome> imageAssetResult = MaterialUtils::GetImageAssetReference( - materialSourceFilePath, property.second.m_value.GetValue()); + Data::Asset imageAsset; - if (imageAssetResult.IsSuccess()) - { - auto& imageAsset = imageAssetResult.GetValue(); - // Load referenced images when load material - imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); - materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); - } - else + MaterialUtils::GetImageAssetResult result = MaterialUtils::GetImageAssetReference( + imageAsset, materialSourceFilePath, property.second.m_value.GetValue()); + + if (result == MaterialUtils::GetImageAssetResult::Missing || result == MaterialUtils::GetImageAssetResult::MissingNoFallback) { materialAssetCreator.ReportWarning( "Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), property.second.m_value.GetValue().data()); } + + imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); + materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); } break; case MaterialPropertyDataType::Enum: 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..61f3d5282a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp @@ -493,12 +493,13 @@ namespace AZ { case MaterialPropertyDataType::Image: { - auto imageAssetResult = MaterialUtils::GetImageAssetReference( - materialTypeSourceFilePath, property.m_value.GetValue()); + Data::Asset imageAsset; - if (imageAssetResult) + MaterialUtils::GetImageAssetResult result = MaterialUtils::GetImageAssetReference( + imageAsset, materialTypeSourceFilePath, property.m_value.GetValue()); + + if (result == MaterialUtils::GetImageAssetResult::Empty || result == MaterialUtils::GetImageAssetResult::Found) { - auto imageAsset = imageAssetResult.GetValue(); materialTypeAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); } else diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp index 90ce9e66ce..4bb4d75d40 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp @@ -28,25 +28,37 @@ namespace AZ { namespace MaterialUtils { - Outcome> GetImageAssetReference(AZStd::string_view materialSourceFilePath, const AZStd::string imageFilePath) + GetImageAssetResult GetImageAssetReference(Data::Asset& imageAsset, AZStd::string_view materialSourceFilePath, const AZStd::string imageFilePath) { + imageAsset = {}; + if (imageFilePath.empty()) { // The image value was present but specified an empty string, meaning the texture asset should be explicitly cleared. - return AZ::Success(Data::Asset()); + return GetImageAssetResult::Empty; } else { Outcome imageAssetId = AssetUtils::MakeAssetId(materialSourceFilePath, imageFilePath, StreamingImageAsset::GetImageAssetSubId()); + if (!imageAssetId.IsSuccess()) { - return AZ::Failure(); - } - else - { - Data::Asset unloadedImageAssetReference(imageAssetId.GetValue(), azrtti_typeid(), imageFilePath); - return AZ::Success(unloadedImageAssetReference); + constexpr static char ErrorMissingTexture[] = "textures/defaults/missing.png"; + imageAssetId = AssetUtils::MakeAssetId(ErrorMissingTexture, StreamingImageAsset::GetImageAssetSubId()); + + if (imageAssetId.IsSuccess()) + { + imageAsset = Data::Asset{imageAssetId.GetValue(), azrtti_typeid(), imageFilePath}; + return GetImageAssetResult::Missing; + } + else + { + return GetImageAssetResult::MissingNoFallback; + } } + + imageAsset = Data::Asset{imageAssetId.GetValue(), azrtti_typeid(), imageFilePath}; + return GetImageAssetResult::Found; } } 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 f241ba6602..0b51962e86 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,7 @@ */ #include +#include #include #include @@ -53,7 +54,7 @@ namespace AZ // Generate asset info to use to register the fallback asset with the asset catalog Data::AssetInfo assetInfo; - assetInfo.m_relativePath = "textures/defaults/defaultfallback.png.streamingimage"; + assetInfo.m_relativePath = DefaultImageAssetPaths::DefaultFallback; assetInfo.m_assetType = azrtti_typeid(); bool useDebugFallbackImages = true; @@ -68,15 +69,15 @@ namespace AZ { case AzFramework::AssetSystem::AssetStatus::AssetStatus_Queued: case AzFramework::AssetSystem::AssetStatus::AssetStatus_Compiling: - assetInfo.m_relativePath = "textures/defaults/processing.png.streamingimage"; + assetInfo.m_relativePath = DefaultImageAssetPaths::Processing; break; case AzFramework::AssetSystem::AssetStatus::AssetStatus_Failed: - assetInfo.m_relativePath = "textures/defaults/processingfailed.png.streamingimage"; + assetInfo.m_relativePath = DefaultImageAssetPaths::ProcessingFailed; break; case AzFramework::AssetSystem::AssetStatus::AssetStatus_Missing: case AzFramework::AssetSystem::AssetStatus::AssetStatus_Unknown: case AzFramework::AssetSystem::AssetStatus::AssetStatus_Compiled: - assetInfo.m_relativePath = "textures/defaults/missing.png.streamingimage"; + assetInfo.m_relativePath = DefaultImageAssetPaths::Missing; break; } } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h index 6a21a8a2df..b385f21a5e 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h @@ -73,6 +73,9 @@ namespace AtomToolsFramework //! Can the document be saved virtual bool IsSavable() const = 0; + //! Get a list of warnings about the data that would be good to know before saving + virtual AZStd::vector GetDataWarnings() const { return {}; } + //! Returns true if there are reversible modifications to the document virtual bool CanUndo() const = 0; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp index 3a392c1413..416babcbde 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp @@ -365,6 +365,24 @@ namespace AtomToolsFramework return false; } + AZStd::vector dataWarnings; + AtomToolsDocumentRequestBus::EventResult(dataWarnings, documentId, &AtomToolsDocumentRequestBus::Events::GetDataWarnings); + if (!dataWarnings.empty()) + { + AZStd::string allWarnings; + AzFramework::StringFunc::Join(allWarnings, dataWarnings.begin(), dataWarnings.end(), "\n"); + + auto result = QMessageBox::warning( + QApplication::activeWindow(), QString("Data Warnings"), + QString("Are you sure you want to save with the following data warnings? \n\n%1").arg(allWarnings.c_str()), + QMessageBox::StandardButton::Yes, QMessageBox::StandardButton::No); + + if (result == QMessageBox::StandardButton::No) + { + return false; + } + } + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool result = false; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 6969e9f923..ea3d1fa319 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -467,6 +468,37 @@ namespace MaterialEditor { return AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::MaterialSourceData::Extension); } + + AZStd::vector MaterialDocument::GetDataWarnings() const + { + AZStd::vector warnings; + + for (auto& [propertyName, dynamicProperty] : m_properties) + { + AZ::RPI::MaterialPropertyValue propertyValue = AtomToolsFramework::ConvertToRuntimeType(dynamicProperty.GetValue()); + if (propertyValue.Is>()) + { + auto isSameAsset = [&propertyValue](const char* path) + { + AZ::Data::AssetId assetId = propertyValue.GetValue>().GetId(); + AZ::Data::AssetId otherAssetId; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(otherAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, path, AZ::Data::AssetType{}, false); + return assetId == otherAssetId; + }; + + if (isSameAsset(AZ::RPI::DefaultImageAssetPaths::DefaultFallback) || + isSameAsset(AZ::RPI::DefaultImageAssetPaths::Missing) || + isSameAsset(AZ::RPI::DefaultImageAssetPaths::Processing) || + isSameAsset(AZ::RPI::DefaultImageAssetPaths::ProcessingFailed) + ) + { + warnings.push_back(AZStd::string::format("%s is using a placeholder image asset.", propertyName.GetCStr())); + } + } + } + + return warnings; + } bool MaterialDocument::CanUndo() const { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h index 452111f99a..d9f9dded0a 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h @@ -55,6 +55,7 @@ namespace MaterialEditor bool IsOpen() const override; bool IsModified() const override; bool IsSavable() const override; + AZStd::vector GetDataWarnings() const override; bool CanUndo() const override; bool CanRedo() const override; bool Undo() override; From 57989c35db45b57f2f73a3dcf7d26d2a865659da Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Thu, 11 Nov 2021 12:50:17 -0800 Subject: [PATCH 09/32] Changed material builder to not fail on warnings. The main reason for this is to give consistent results between the AP and Material Editor, where a placholder texture can be used if a texture is missing. Otherwise, you could get a placeholder texture in Material Editor and stale data in the runtime; this inconsistency would be confusing. As a consequence, it is possible for example that the user could mess up the name of a property in a .material file and not notice the problem because it is now a warning instead of an error. If warnings-as-errors is desirable, you can enable the new "/O3DE/Atom/RPI/MaterialBuilder/WarningsAsErrors" registry setting. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../RPI.Builders/Material/MaterialBuilder.cpp | 18 ++++++++++++++---- .../RPI.Builders/Material/MaterialBuilder.h | 5 +++++ .../RPI.Edit/Material/MaterialSourceData.cpp | 2 +- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index e9cebf29c7..f11b2f94ac 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -63,11 +63,21 @@ namespace AZ { BusDisconnect(); } + + bool MaterialBuilder::ReportMaterialAssetWarningsAsErrors() const + { + bool warningsAsErrors = false; + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + settingsRegistry->Get(warningsAsErrors, "/O3DE/Atom/RPI/MaterialBuilder/WarningsAsErrors"); + } + return warningsAsErrors; + } //! Adds all relevant dependencies for a referenced source file, considering that the path might be relative to the original file location or a full asset path. //! This will usually include multiple source dependencies and a single job dependency, but will include only source dependencies if the file is not found. //! Note the AssetBuilderSDK::JobDependency::m_platformIdentifier will not be set by this function. The calling code must set this value before passing back - //! to the AssetBuilderSDK::CreateJobsResponse. If isOrderedOnceForMaterialTypes is true and the dependency is a materialtype file, the job dependency type + //! to the AssetBuilderSDK::CreateJobsResponse. If isOrderedOnceForMaterialTypes is true and the dependency is a .materialtype file, the job dependency type //! will be set to JobDependencyType::OrderOnce. void AddPossibleDependencies(AZStd::string_view currentFilePath, AZStd::string_view referencedParentPath, @@ -277,8 +287,8 @@ namespace AZ return materialTypeAssetOutcome.GetValue(); } - - AZ::Data::Asset CreateMaterialAsset(AZStd::string_view materialSourceFilePath, const rapidjson::Value& json) + + AZ::Data::Asset MaterialBuilder::CreateMaterialAsset(AZStd::string_view materialSourceFilePath, const rapidjson::Value& json) const { auto material = LoadSourceData(json, materialSourceFilePath); @@ -292,7 +302,7 @@ namespace AZ return {}; } - auto materialAssetOutcome = material.GetValue().CreateMaterialAsset(Uuid::CreateRandom(), materialSourceFilePath, true); + auto materialAssetOutcome = material.GetValue().CreateMaterialAsset(Uuid::CreateRandom(), materialSourceFilePath, ReportMaterialAssetWarningsAsErrors()); if (!materialAssetOutcome.IsSuccess()) { return {}; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.h b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.h index afb0789dcf..4fa5f3cf10 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.h +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.h @@ -9,6 +9,8 @@ #pragma once #include +#include +#include namespace AZ { @@ -37,6 +39,9 @@ namespace AZ private: + AZ::Data::Asset CreateMaterialAsset(AZStd::string_view materialSourceFilePath, const rapidjson::Value& json) const; + bool ReportMaterialAssetWarningsAsErrors() const; + bool m_isShuttingDown = false; }; 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 a8d61465a5..b2c449a05d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -303,7 +303,7 @@ namespace AZ 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."); + materialAssetCreator.ReportWarning("Source data for material property value is invalid."); } else { From e1ac57b4a5d4855120956c0794a779a58edc4154 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Thu, 11 Nov 2021 13:21:30 -0800 Subject: [PATCH 10/32] Fixed tabs Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- Gems/Atom/RPI/Registry/atom_rpi.release.setreg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Registry/atom_rpi.release.setreg b/Gems/Atom/RPI/Registry/atom_rpi.release.setreg index d1be96431d..72fb4f01e8 100644 --- a/Gems/Atom/RPI/Registry/atom_rpi.release.setreg +++ b/Gems/Atom/RPI/Registry/atom_rpi.release.setreg @@ -2,7 +2,7 @@ "O3DE": { "Atom": { "RPI": { - "UseDebugFallbackImages": false + "UseDebugFallbackImages": false } } } From 282c93c20c1d93c8eeb4867974087126a883fd7c Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Fri, 12 Nov 2021 10:33:47 -0800 Subject: [PATCH 11/32] Removed source art files for default textures. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Assets/Textures/Defaults/wip/Missing.pdn | Bin 18928 -> 0 bytes .../Assets/Textures/Defaults/wip/Processing.pdn | Bin 18995 -> 0 bytes .../Textures/Defaults/wip/ProcessingFailed.pdn | Bin 21667 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/wip/Missing.pdn delete mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/wip/Processing.pdn delete mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/wip/ProcessingFailed.pdn diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/wip/Missing.pdn b/Gems/Atom/RPI/Assets/Textures/Defaults/wip/Missing.pdn deleted file mode 100644 index 2ede3d837b276aca67709f35c243bc30cbcd7c35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18928 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 diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/wip/Processing.pdn b/Gems/Atom/RPI/Assets/Textures/Defaults/wip/Processing.pdn deleted file mode 100644 index 994513301fa9993020455f12824abbf543cafd93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18995 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 diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/wip/ProcessingFailed.pdn b/Gems/Atom/RPI/Assets/Textures/Defaults/wip/ProcessingFailed.pdn deleted file mode 100644 index d6388621371a5f6fff90a7a3972ce9588cd1f6b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21667 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 From 7d849cc0d259ba33325fa041651910d4c68c0c74 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Mon, 15 Nov 2021 16:51:22 -0800 Subject: [PATCH 12/32] Changed the overall strategy for how to handle missing image references. Instead of replacing it with one of the placeholder assets, we replace it with an random UUID which will be interpreted as a missing asset (unless some discovers discovers a UUID collision). This eventually gets replaced by one of the placeholder textures at runtime. This approach gives more consistent results in how missing texture are handled between Material Editor and Material Component. I actually tried this approach before and it didn't seem to work the way we needed, but I realized that's because PropertyAssetCtrl wasn't handling missing assets properly. I fixed a few issues there including showing the error button when the asset can't be found, and fixing a broken reference to the error icon file. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../UI/PropertyEditor/PropertyAssetCtrl.cpp | 33 ++++++++++++++++--- .../UI/PropertyEditor/PropertyAssetCtrl.hxx | 4 ++- .../Material/MaterialTypeSourceData.h | 2 +- .../Material/MaterialTypeSourceData.cpp | 6 ++-- .../RPI.Edit/Material/MaterialUtils.cpp | 15 ++------- .../Code/Source/Document/MaterialDocument.cpp | 2 +- .../Material/EditorMaterialComponentUtil.cpp | 2 +- 7 files changed, 40 insertions(+), 24 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp index 24b2c7466e..384b384a23 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp @@ -527,8 +527,8 @@ namespace AzToolsFramework m_errorButton = nullptr; } } - - void PropertyAssetCtrl::UpdateErrorButton(const AZStd::string& errorLog) + + void PropertyAssetCtrl::UpdateErrorButton() { if (m_errorButton) { @@ -543,12 +543,17 @@ namespace AzToolsFramework m_errorButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_errorButton->setFixedSize(QSize(16, 16)); m_errorButton->setMouseTracking(true); - m_errorButton->setIcon(QIcon("Icons/PropertyEditor/error_icon.png")); + m_errorButton->setIcon(QIcon(":/PropertyEditor/Resources/error_icon.png")); m_errorButton->setToolTip("Show Errors"); // Insert the error button after the asset label qobject_cast(layout())->insertWidget(1, m_errorButton); } + } + + void PropertyAssetCtrl::UpdateErrorButtonWithLog(const AZStd::string& errorLog) + { + UpdateErrorButton(); // Connect pressed to opening the error dialog // Must capture this for call to QObject::connect @@ -587,6 +592,21 @@ namespace AzToolsFramework logDialog->show(); }); } + + void PropertyAssetCtrl::UpdateErrorButtonWithMessage(const AZStd::string& message) + { + UpdateErrorButton(); + + connect(m_errorButton, &QPushButton::clicked, this, [this, message]() { + QMessageBox::critical(nullptr, "Error", message.c_str()); + + // Without this, the error button would maintain focus after clicking, which left the red error icon in a blue-highlighted state + if (parentWidget()) + { + parentWidget()->setFocus(); + } + }); + } void PropertyAssetCtrl::ClearAssetInternal() { @@ -960,7 +980,6 @@ namespace AzToolsFramework else { const AZ::Data::AssetId assetID = GetCurrentAssetID(); - m_currentAssetHint = ""; AZ::Outcome jobOutcome = AZ::Failure(); AssetSystemJobRequestBus::BroadcastResult(jobOutcome, &AssetSystemJobRequestBus::Events::GetAssetJobsInfoByAssetID, assetID, false, false); @@ -1018,7 +1037,7 @@ namespace AzToolsFramework // In case of failure, render failure icon case AssetSystem::JobStatus::Failed: { - UpdateErrorButton(errorLog); + UpdateErrorButtonWithLog(errorLog); } break; @@ -1043,6 +1062,10 @@ namespace AzToolsFramework m_currentAssetHint = assetPath; } } + else + { + UpdateErrorButtonWithMessage(AZStd::string::format("Asset is missing.\n\nID: %s\nHint:%s", assetID.ToString().c_str(), GetCurrentAssetHint().c_str())); + } } // Get the asset file name diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx index 0b98278bc5..58ddbb967e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx @@ -168,7 +168,9 @@ namespace AzToolsFramework bool IsCorrectMimeData(const QMimeData* pData, AZ::Data::AssetId* pAssetId = nullptr, AZ::Data::AssetType* pAssetType = nullptr) const; void ClearErrorButton(); - void UpdateErrorButton(const AZStd::string& errorLog); + void UpdateErrorButton(); + void UpdateErrorButtonWithLog(const AZStd::string& errorLog); + void UpdateErrorButtonWithMessage(const AZStd::string& message); virtual const AZStd::string GetFolderSelection() const { return AZStd::string(); } virtual void SetFolderSelection(const AZStd::string& /* folderPath */) {} virtual void ClearAssetInternal(); 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..3dbedb7a4b 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 @@ -211,7 +211,7 @@ namespace AZ //! 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; + bool ConvertPropertyValueToSourceDataFormat(const AZ::Name& propertyId, const PropertyDefinition& propertyDefinition, MaterialPropertyValue& propertyValue) const; Outcome> CreateMaterialTypeAsset(Data::AssetId assetId, AZStd::string_view materialTypeSourceFilePath = "", bool elevateWarnings = true) const; 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 61f3d5282a..8d439c99ab 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp @@ -300,14 +300,14 @@ namespace AZ } } - bool MaterialTypeSourceData::ConvertPropertyValueToSourceDataFormat(const PropertyDefinition& propertyDefinition, MaterialPropertyValue& propertyValue) const + bool MaterialTypeSourceData::ConvertPropertyValueToSourceDataFormat([[maybe_unused]] const AZ::Name& propertyId, 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()); + AZ_Error("Material source data", false, "Invalid value for material enum property: '%s'.", propertyId.GetCStr()); return false; } @@ -330,7 +330,7 @@ namespace AZ 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()); + AZ_Error("Material source data", false, "Image asset could not be found for property: '%s'.", propertyId.GetCStr()); return false; } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp index 4bb4d75d40..fbc06e7294 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp @@ -43,18 +43,9 @@ namespace AZ if (!imageAssetId.IsSuccess()) { - constexpr static char ErrorMissingTexture[] = "textures/defaults/missing.png"; - imageAssetId = AssetUtils::MakeAssetId(ErrorMissingTexture, StreamingImageAsset::GetImageAssetSubId()); - - if (imageAssetId.IsSuccess()) - { - imageAsset = Data::Asset{imageAssetId.GetValue(), azrtti_typeid(), imageFilePath}; - return GetImageAssetResult::Missing; - } - else - { - return GetImageAssetResult::MissingNoFallback; - } + static const Uuid InvalidAssetPlaceholderId = "{BADA55E7-1A1D-4940-B655-9D08679BD62F}"; + imageAsset = Data::Asset{InvalidAssetPlaceholderId, azrtti_typeid(), imageFilePath}; + return GetImageAssetResult::Missing; } imageAsset = Data::Asset{imageAssetId.GetValue(), azrtti_typeid(), imageFilePath}; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index ea3d1fa319..5e1fbac282 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -640,7 +640,7 @@ namespace MaterialEditor MaterialPropertyValue propertyValue = AtomToolsFramework::ConvertToRuntimeType(it->second.GetValue()); if (propertyValue.IsValid()) { - if (!m_materialTypeSourceData.ConvertPropertyValueToSourceDataFormat(propertyDefinition, propertyValue)) + if (!m_materialTypeSourceData.ConvertPropertyValueToSourceDataFormat(propertyId.GetFullName(), 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; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp index d15db886d6..8620ec34f4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp @@ -156,7 +156,7 @@ namespace AZ propertyValue = AZ::RPI::MaterialPropertyValue::FromAny(propertyOverrideItr->second); } - if (!editData.m_materialTypeSourceData.ConvertPropertyValueToSourceDataFormat(propertyDefinition, propertyValue)) + if (!editData.m_materialTypeSourceData.ConvertPropertyValueToSourceDataFormat(propertyId.GetFullName(), propertyDefinition, propertyValue)) { AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Failed to export: %s", path.c_str()); result = false; From aa85963a2b3284930cbe79380d16182f27ebaa2d Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Mon, 15 Nov 2021 23:21:21 -0800 Subject: [PATCH 13/32] Fixed MaterialPropertyValue::FromAny to preserve the Hint string when converting Asset objects. This fixed an issue where the hint didn't show up in the Material Component's instance inspector. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Source/RPI.Reflect/Material/MaterialPropertyValue.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyValue.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyValue.cpp index d1017139fc..b74305613e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyValue.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyValue.cpp @@ -118,12 +118,16 @@ namespace AZ else if (value.is>()) { result.m_value = Data::Asset( - AZStd::any_cast>(value).GetId(), azrtti_typeid()); + AZStd::any_cast>(value).GetId(), + azrtti_typeid(), + AZStd::any_cast>(value).GetHint()); } else if (value.is>()) { result.m_value = Data::Asset( - AZStd::any_cast>(value).GetId(), azrtti_typeid()); + AZStd::any_cast>(value).GetId(), + azrtti_typeid(), + AZStd::any_cast>(value).GetHint()); } else if (value.is>()) { From 26576208463fd3b0bebb9d36d57740042a6a98ae Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Mon, 15 Nov 2021 23:56:10 -0800 Subject: [PATCH 14/32] Minor code cleanup. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h | 3 +-- .../Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h index f39b8e7aaa..c1183c7aa1 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h @@ -32,8 +32,7 @@ namespace AZ { Empty, //! No image was actually requested, the path was empty Found, //! The requested asset was found - Missing, //! The requested asset was not found, and a placeholder asset was used instead - MissingNoFallback //! The requested asset was not found, and a placeholder asset was not found either + Missing //! The requested asset was not found, and a placeholder asset was used instead }; //! Finds an ImageAsset referenced by a material file (or a placeholder) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp index fbc06e7294..2b51be736e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp @@ -43,6 +43,11 @@ namespace AZ if (!imageAssetId.IsSuccess()) { + // When the AssetId cannot be found, we don't want to outright fail, because the runtime has mechanisms for displaying fallback textures which gives the + // user a better recovery workflow. On the other hand we can't just provide an empty/invalid Asset because that would be interpreted as simply + // no value was present and result in using no texture, and this would amount to a silent failure. + // So we use a randomly generated (well except for the "BADA55E7" bit ;) UUID which the runtime and tools will interpret as a missing asset and represent + // it as such. static const Uuid InvalidAssetPlaceholderId = "{BADA55E7-1A1D-4940-B655-9D08679BD62F}"; imageAsset = Data::Asset{InvalidAssetPlaceholderId, azrtti_typeid(), imageFilePath}; return GetImageAssetResult::Missing; From a789d7b762665d4528907e2fdf8edbb3987631a4 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 16 Nov 2021 00:00:10 -0800 Subject: [PATCH 15/32] Minor code cleanup. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b2c449a05d..d886a523cb 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -322,7 +322,7 @@ namespace AZ MaterialUtils::GetImageAssetResult result = MaterialUtils::GetImageAssetReference( imageAsset, materialSourceFilePath, property.second.m_value.GetValue()); - if (result == MaterialUtils::GetImageAssetResult::Missing || result == MaterialUtils::GetImageAssetResult::MissingNoFallback) + if (result == MaterialUtils::GetImageAssetResult::Missing) { materialAssetCreator.ReportWarning( "Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), From 224e0bd20f8bf328e4ff3deac026eb7a7c4b88b6 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 16 Nov 2021 00:02:20 -0800 Subject: [PATCH 16/32] Removed the 'data-warnings' concept for checking before saving a material document. It's no longer necessary since we no longer replace the original data with placeholders. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Document/AtomToolsDocumentRequestBus.h | 3 -- .../AtomToolsDocumentSystemComponent.cpp | 18 ----------- .../Code/Source/Document/MaterialDocument.cpp | 31 ------------------- .../Code/Source/Document/MaterialDocument.h | 1 - 4 files changed, 53 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h index b385f21a5e..6a21a8a2df 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h @@ -73,9 +73,6 @@ namespace AtomToolsFramework //! Can the document be saved virtual bool IsSavable() const = 0; - //! Get a list of warnings about the data that would be good to know before saving - virtual AZStd::vector GetDataWarnings() const { return {}; } - //! Returns true if there are reversible modifications to the document virtual bool CanUndo() const = 0; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp index 416babcbde..3a392c1413 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp @@ -365,24 +365,6 @@ namespace AtomToolsFramework return false; } - AZStd::vector dataWarnings; - AtomToolsDocumentRequestBus::EventResult(dataWarnings, documentId, &AtomToolsDocumentRequestBus::Events::GetDataWarnings); - if (!dataWarnings.empty()) - { - AZStd::string allWarnings; - AzFramework::StringFunc::Join(allWarnings, dataWarnings.begin(), dataWarnings.end(), "\n"); - - auto result = QMessageBox::warning( - QApplication::activeWindow(), QString("Data Warnings"), - QString("Are you sure you want to save with the following data warnings? \n\n%1").arg(allWarnings.c_str()), - QMessageBox::StandardButton::Yes, QMessageBox::StandardButton::No); - - if (result == QMessageBox::StandardButton::No) - { - return false; - } - } - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool result = false; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 5e1fbac282..0174871502 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -468,37 +468,6 @@ namespace MaterialEditor { return AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::MaterialSourceData::Extension); } - - AZStd::vector MaterialDocument::GetDataWarnings() const - { - AZStd::vector warnings; - - for (auto& [propertyName, dynamicProperty] : m_properties) - { - AZ::RPI::MaterialPropertyValue propertyValue = AtomToolsFramework::ConvertToRuntimeType(dynamicProperty.GetValue()); - if (propertyValue.Is>()) - { - auto isSameAsset = [&propertyValue](const char* path) - { - AZ::Data::AssetId assetId = propertyValue.GetValue>().GetId(); - AZ::Data::AssetId otherAssetId; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(otherAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, path, AZ::Data::AssetType{}, false); - return assetId == otherAssetId; - }; - - if (isSameAsset(AZ::RPI::DefaultImageAssetPaths::DefaultFallback) || - isSameAsset(AZ::RPI::DefaultImageAssetPaths::Missing) || - isSameAsset(AZ::RPI::DefaultImageAssetPaths::Processing) || - isSameAsset(AZ::RPI::DefaultImageAssetPaths::ProcessingFailed) - ) - { - warnings.push_back(AZStd::string::format("%s is using a placeholder image asset.", propertyName.GetCStr())); - } - } - } - - return warnings; - } bool MaterialDocument::CanUndo() const { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h index d9f9dded0a..452111f99a 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h @@ -55,7 +55,6 @@ namespace MaterialEditor bool IsOpen() const override; bool IsModified() const override; bool IsSavable() const override; - AZStd::vector GetDataWarnings() const override; bool CanUndo() const override; bool CanRedo() const override; bool Undo() override; From 9f7815fa0405a42b78cdd2709aae0f10eb2c8531 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 16 Nov 2021 10:35:49 -0800 Subject: [PATCH 17/32] Fixed up a couple incorrectly or incompletely resolved merge conflicts. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Include/AtomToolsFramework/Util/MaterialPropertyUtil.h | 1 + .../Code/Source/Util/MaterialPropertyUtil.cpp | 3 ++- .../MaterialEditor/Code/Source/Document/MaterialDocument.cpp | 2 +- 3 files changed, 4 insertions(+), 2 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 08f59f9e0b..d27f2403a1 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h @@ -49,6 +49,7 @@ namespace AtomToolsFramework //! @param propertyValue the value being converted before saving bool ConvertToExportFormat( const AZStd::string& exportPath, + [[maybe_unused]] const AZ::Name& propertyId, const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition, AZ::RPI::MaterialPropertyValue& propertyValue); diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp index c49cd3fafb..8fe7115488 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp @@ -167,6 +167,7 @@ namespace AtomToolsFramework bool ConvertToExportFormat( const AZStd::string& exportPath, + [[maybe_unused]] const AZ::Name& propertyId, const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition, AZ::RPI::MaterialPropertyValue& propertyValue) { @@ -175,7 +176,7 @@ namespace AtomToolsFramework 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()); + AZ_Error("AtomToolsFramework", false, "Invalid value for material enum property: '%s'.", propertyId.GetCStr()); return false; } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 4ac0b745fd..2d7768feec 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -759,7 +759,7 @@ namespace MaterialEditor } 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'.", m_materialSourceData.m_parentMaterial.c_str()); From ebc92c5b088c28263a5aab091ced3c0f4aa4f7e5 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 16 Nov 2021 10:52:03 -0800 Subject: [PATCH 18/32] Restored a bit of error checking that appears to have been removed by mistake, in MaterialPropertyUtil ConvertToExportFormat(). This is important for the missing texture use cases, because this error checking is what will prevent the Material Editor from silently replacing a broken texture reference with no texture reference. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Code/Source/Util/MaterialPropertyUtil.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp index 8fe7115488..91e3d5c2f0 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp @@ -187,18 +187,27 @@ namespace AtomToolsFramework // Image asset references must be converted from asset IDs to a relative source file path if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Image) { + AZStd::string imagePath; + if (propertyValue.Is>()) { const auto& imageAsset = propertyValue.GetValue>(); - const auto& imagePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(imageAsset.GetId()); - propertyValue = GetExteralReferencePath(exportPath, imagePath); - return true; + imagePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(imageAsset.GetId()); } if (propertyValue.Is>()) { const auto& image = propertyValue.GetValue>(); - const auto& imagePath = image ? AZ::RPI::AssetUtils::GetSourcePathByAssetId(image->GetAssetId()) : ""; + imagePath = image ? AZ::RPI::AssetUtils::GetSourcePathByAssetId(image->GetAssetId()) : ""; + } + + if (imagePath.empty()) + { + AZ_Error("AtomToolsFramework", false, "Image asset could not be found for property: '%s'.", propertyId.GetCStr()); + return false; + } + else + { propertyValue = GetExteralReferencePath(exportPath, imagePath); return true; } From 284a44d74c8b064967af8c07cd47a5edb4a63ef9 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 16 Nov 2021 11:45:26 -0800 Subject: [PATCH 19/32] Updated AssetUtils::ResolvePathReference to avoid "The second join parameter is an absolute path" warnings from StringFunc::Path::Join. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp index c940ef808b..c779453c25 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace AZ { @@ -46,6 +47,12 @@ namespace AZ AZStd::string ResolvePathReference(const AZStd::string& originatingSourceFilePath, const AZStd::string& referencedSourceFilePath) { + // Prevents "second join parameter is an absolute path" warnings in StringFunc::Path::Join below + if (AZ::IO::PathView{referencedSourceFilePath}.IsAbsolute()) + { + return referencedSourceFilePath; + } + AZStd::string normalizedReferencedPath = referencedSourceFilePath; AzFramework::StringFunc::Path::Normalize(normalizedReferencedPath); From 5cf65012b1ca9d01defa769439e6a6cf1cf81f9d Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 16 Nov 2021 12:31:33 -0800 Subject: [PATCH 20/32] Updated RPI.Edit's AssetUtils to use the same TraceLevel enum as RPI.Reflect's AssetUtils. This is now used in GetImageAssetReference to remove a redundant error message since the error is also reported in MaterialSourceData and MaterialTypeSourceData. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Include/Atom/RPI.Edit/Common/AssetUtils.h | 36 ++++++++++--------- .../Source/RPI.Edit/Common/AssetUtils.cpp | 8 ++--- .../Material/MaterialTypeSourceData.cpp | 10 +++--- .../RPI.Edit/Material/MaterialUtils.cpp | 5 ++- 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/AssetUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/AssetUtils.h index bd11965ffa..f758019cfb 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/AssetUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/AssetUtils.h @@ -12,6 +12,7 @@ #include #include +#include namespace AZ { @@ -21,21 +22,24 @@ namespace AZ { // Declarations... - Outcome MakeAssetId(const AZStd::string& sourcePath, uint32_t productSubId); + // Note that these functions default to TraceLevel::Error to preserve legacy behavior of these APIs. It would be nice to make the default match + // RPI.Reflect/Asset/AssetUtils.h which is TraceLevel::Warning, but we are close to a release so it isn't worth the risk at this time. - Outcome MakeAssetId(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId); + Outcome MakeAssetId(const AZStd::string& sourcePath, uint32_t productSubId, TraceLevel reporting = TraceLevel::Error); + + Outcome MakeAssetId(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId, TraceLevel reporting = TraceLevel::Error); template - Outcome> LoadAsset(const AZStd::string& sourcePath, uint32_t productSubId = 0); + Outcome> LoadAsset(const AZStd::string& sourcePath, uint32_t productSubId = 0, TraceLevel reporting = TraceLevel::Error); template - Outcome> LoadAsset(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId = 0); + Outcome> LoadAsset(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId = 0, TraceLevel reporting = TraceLevel::Error); template - Outcome> LoadAsset(const AZ::Data::AssetId& assetId, const char* sourcePathForDebug); + Outcome> LoadAsset(const AZ::Data::AssetId& assetId, const char* sourcePathForDebug, TraceLevel reporting = TraceLevel::Error); template - Outcome> LoadAsset(const AZ::Data::AssetId& assetId); + Outcome> LoadAsset(const AZ::Data::AssetId& assetId, TraceLevel reporting = TraceLevel::Error); //! Attempts to resolve the full path to a product asset given its ID AZStd::string GetProductPathByAssetId(const AZ::Data::AssetId& assetId); @@ -65,12 +69,12 @@ namespace AZ // Definitions... template - Outcome> LoadAsset(const AZStd::string& sourcePath, uint32_t productSubId) + Outcome> LoadAsset(const AZStd::string& sourcePath, uint32_t productSubId, TraceLevel reporting) { - auto assetId = MakeAssetId(sourcePath, productSubId); + auto assetId = MakeAssetId(sourcePath, productSubId, reporting); if (assetId.IsSuccess()) { - return LoadAsset(assetId.GetValue(), sourcePath.c_str()); + return LoadAsset(assetId.GetValue(), sourcePath.c_str(), reporting); } else { @@ -79,20 +83,20 @@ namespace AZ } template - Outcome> LoadAsset(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId) + Outcome> LoadAsset(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId, TraceLevel reporting) { AZStd::string resolvedPath = ResolvePathReference(originatingSourcePath, referencedSourceFilePath); - return LoadAsset(resolvedPath, productSubId); + return LoadAsset(resolvedPath, productSubId, reporting); } template - Outcome> LoadAsset(const AZ::Data::AssetId& assetId) + Outcome> LoadAsset(const AZ::Data::AssetId& assetId, TraceLevel reporting) { - return LoadAsset(assetId, nullptr); + return LoadAsset(assetId, nullptr, reporting); } template - Outcome> LoadAsset(const AZ::Data::AssetId& assetId, [[maybe_unused]] const char* sourcePathForDebug) + Outcome> LoadAsset(const AZ::Data::AssetId& assetId, [[maybe_unused]] const char* sourcePathForDebug, TraceLevel reporting) { if (nullptr == AZ::IO::FileIOBase::GetInstance()->GetAlias("@products@")) { @@ -111,11 +115,11 @@ namespace AZ } else { - AZ_Error("AssetUtils", false, "Could not load %s [Source='%s' Cache='%s' AssetID=%s] ", + AssetUtilsInternal::ReportIssue(reporting, AZStd::string::format("Could not load %s [Source='%s' Cache='%s' AssetID=%s] ", AzTypeInfo::Name(), sourcePathForDebug ? sourcePathForDebug : "", asset.GetHint().empty() ? "" : asset.GetHint().c_str(), - assetId.ToString().c_str()); + assetId.ToString().c_str()).c_str()); return AZ::Failure(); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp index c779453c25..73c64b8015 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp @@ -120,7 +120,7 @@ namespace AZ return results; } - Outcome MakeAssetId(const AZStd::string& sourcePath, uint32_t productSubId) + Outcome MakeAssetId(const AZStd::string& sourcePath, uint32_t productSubId, TraceLevel reporting) { bool assetFound = false; AZ::Data::AssetInfo sourceInfo; @@ -129,7 +129,7 @@ namespace AZ if (!assetFound) { - AZ_Error("AssetUtils", false, "Could not find asset [%s]", sourcePath.c_str()); + AssetUtilsInternal::ReportIssue(reporting, AZStd::string::format("Could not find asset [%s]", sourcePath.c_str()).c_str()); return AZ::Failure(); } else @@ -138,10 +138,10 @@ namespace AZ } } - Outcome MakeAssetId(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId) + Outcome MakeAssetId(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId, TraceLevel reporting) { AZStd::string resolvedPath = ResolvePathReference(originatingSourcePath, referencedSourceFilePath); - return MakeAssetId(resolvedPath, productSubId); + return MakeAssetId(resolvedPath, productSubId, reporting); } } // namespace AssetUtils } // namespace RPI 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 c6fa4653c3..d8e6c156be 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp @@ -456,16 +456,16 @@ namespace AZ MaterialUtils::GetImageAssetResult result = MaterialUtils::GetImageAssetReference( imageAsset, materialTypeSourceFilePath, property.m_value.GetValue()); - if (result == MaterialUtils::GetImageAssetResult::Empty || result == MaterialUtils::GetImageAssetResult::Found) - { - materialTypeAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); - } - else + if (result == MaterialUtils::GetImageAssetResult::Missing) { materialTypeAssetCreator.ReportError( "Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), property.m_value.GetValue().data()); } + else + { + materialTypeAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); + } } break; case MaterialPropertyDataType::Enum: diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp index 2b51be736e..7fff8d81bc 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp @@ -39,7 +39,10 @@ namespace AZ } else { - Outcome imageAssetId = AssetUtils::MakeAssetId(materialSourceFilePath, imageFilePath, StreamingImageAsset::GetImageAssetSubId()); + // We use TraceLevel::None because fallback textures are available and we'll return GetImageAssetResult::Missing below in that case. + // Callers of GetImageAssetReference will be responsible for logging warnings or errors as needed. + + Outcome imageAssetId = AssetUtils::MakeAssetId(materialSourceFilePath, imageFilePath, StreamingImageAsset::GetImageAssetSubId(), AssetUtils::TraceLevel::None); if (!imageAssetId.IsSuccess()) { From cdb38251d86d089871fe6d290d6052e7bfb687fa Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 16 Nov 2021 17:19:44 -0800 Subject: [PATCH 21/32] Fixed an issue that prevented saving child materials with explicitly empty texture properties. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Code/Source/Util/MaterialPropertyUtil.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp index 91e3d5c2f0..3ffd8efa6e 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp @@ -188,20 +188,26 @@ namespace AtomToolsFramework if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Image) { AZStd::string imagePath; + AZ::Data::AssetId imageAssetId; if (propertyValue.Is>()) { const auto& imageAsset = propertyValue.GetValue>(); - imagePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(imageAsset.GetId()); + imageAssetId = imageAsset.GetId(); } if (propertyValue.Is>()) { const auto& image = propertyValue.GetValue>(); - imagePath = image ? AZ::RPI::AssetUtils::GetSourcePathByAssetId(image->GetAssetId()) : ""; + if (image) + { + imageAssetId = image->GetAssetId(); + } } + + imagePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(imageAssetId); - if (imagePath.empty()) + if (imageAssetId.IsValid() && imagePath.empty()) { AZ_Error("AtomToolsFramework", false, "Image asset could not be found for property: '%s'.", propertyId.GetCStr()); return false; From 7d48e8209c94749d027d17daea91c795cad9c3c6 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 16 Nov 2021 17:28:57 -0800 Subject: [PATCH 22/32] Updated a failing unit test. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp index fa8eed35de..0ce819efa2 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp @@ -692,10 +692,10 @@ namespace UnitTest }); // Missing image reference - expectError([](MaterialSourceData& materialSourceData) + expectWarning([](MaterialSourceData& materialSourceData) { AddProperty(materialSourceData, "general", "MyImage", AZStd::string("doesNotExist.streamingimage")); - }, 3); // Expect a 3rd error because AssetUtils reports its own assertion failure + }); } From 8b82452a1bcb1781a8866ec4979f3600efb5686c Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 16 Nov 2021 17:30:33 -0800 Subject: [PATCH 23/32] Updated ResolvePathReference to also early-return when the path is empty. @gadams3 said this would be helpful to him. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp index 73c64b8015..e2877aa163 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp @@ -47,8 +47,8 @@ namespace AZ AZStd::string ResolvePathReference(const AZStd::string& originatingSourceFilePath, const AZStd::string& referencedSourceFilePath) { - // Prevents "second join parameter is an absolute path" warnings in StringFunc::Path::Join below - if (AZ::IO::PathView{referencedSourceFilePath}.IsAbsolute()) + // The IsAbsolute part prevents "second join parameter is an absolute path" warnings in StringFunc::Path::Join below + if (referencedSourceFilePath.empty() || AZ::IO::PathView{referencedSourceFilePath}.IsAbsolute()) { return referencedSourceFilePath; } From 2ae7a5ef9f6cc9c0ffd4b41f148dbf58866d8f3b Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Wed, 17 Nov 2021 12:04:46 -0800 Subject: [PATCH 24/32] Added a unit test for the MaterialPropertyValue bug fix. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../RPI/Code/Tests/Material/MaterialTests.cpp | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp index 9c3e08ee08..95aa343ed5 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp @@ -888,4 +888,54 @@ namespace UnitTest EXPECT_EQ(indexFromOldName, indexFromNewName); } + template + void CheckPropertyValueRoundTrip(const T& value) + { + AZ::RPI::MaterialPropertyValue materialPropertyValue{value}; + AZStd::any anyValue{value}; + AZ::RPI::MaterialPropertyValue materialPropertyValueFromAny = MaterialPropertyValue::FromAny(anyValue); + AZ::RPI::MaterialPropertyValue materialPropertyValueFromRoundTrip = MaterialPropertyValue::FromAny(MaterialPropertyValue::ToAny(materialPropertyValue)); + + EXPECT_EQ(materialPropertyValue, materialPropertyValueFromAny); + EXPECT_EQ(materialPropertyValue, materialPropertyValueFromRoundTrip); + + if (materialPropertyValue.Is>()) + { + EXPECT_EQ(materialPropertyValue.GetValue>().GetHint(), materialPropertyValueFromAny.GetValue>().GetHint()); + EXPECT_EQ(materialPropertyValue.GetValue>().GetHint(), materialPropertyValueFromRoundTrip.GetValue>().GetHint()); + } + } + + TEST_F(MaterialTests, TestMaterialPropertyValueAsAny) + { + auto checkRoundTrip = [](const AZ::RPI::MaterialPropertyValue &original) + { + AZ::RPI::MaterialPropertyValue convertedValue = MaterialPropertyValue::FromAny(MaterialPropertyValue::ToAny(original)); + EXPECT_EQ(original, convertedValue); + + if (original.Is>()) + { + EXPECT_EQ(original.GetValue>().GetHint(), convertedValue.GetValue>().GetHint()); + } + }; + + CheckPropertyValueRoundTrip(true); + CheckPropertyValueRoundTrip(false); + CheckPropertyValueRoundTrip(7); + CheckPropertyValueRoundTrip(8u); + CheckPropertyValueRoundTrip(9.0f); + CheckPropertyValueRoundTrip(AZ::Vector2(1.0f, 2.0f)); + CheckPropertyValueRoundTrip(AZ::Vector3(1.0f, 2.0f, 3.0f)); + CheckPropertyValueRoundTrip(AZ::Vector4(1.0f, 2.0f, 3.0f, 4.0f)); + CheckPropertyValueRoundTrip(AZ::Color(1.0f, 2.0f, 3.0f, 4.0f)); + CheckPropertyValueRoundTrip(Data::Asset{}); + CheckPropertyValueRoundTrip(Data::Asset{}); + CheckPropertyValueRoundTrip(Data::Asset{}); + CheckPropertyValueRoundTrip(Data::Asset{Uuid::CreateRandom(), azrtti_typeid(), "TestAssetPath.png"}); + CheckPropertyValueRoundTrip(Data::Asset{Uuid::CreateRandom(), azrtti_typeid(), "TestAssetPath.png"}); + CheckPropertyValueRoundTrip(Data::Asset{Uuid::CreateRandom(), azrtti_typeid(), "TestAssetPath.png"}); + CheckPropertyValueRoundTrip(m_testImageAsset); + CheckPropertyValueRoundTrip(Data::Instance{m_testImage}); + CheckPropertyValueRoundTrip(AZStd::string{"hello"}); + } } From d3de1689adc092e2804852510a4be4950cf1a3e2 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Wed, 17 Nov 2021 13:53:11 -0800 Subject: [PATCH 25/32] Removed unused lambda function. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Tests/Material/MaterialSourceDataTests.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp index 0ce819efa2..d4bf3e5eaa 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp @@ -625,23 +625,6 @@ namespace UnitTest // We use local functions to easily start a new MaterialAssetCreator for each test case because // the AssetCreator would just skip subsequent operations after the first failure is detected. - auto expectError = [](AZStd::function setOneBadInput, [[maybe_unused]] uint32_t expectedAsserts = 2) - { - MaterialSourceData sourceData; - - sourceData.m_materialType = "@exefolder@/Temp/test.materialtype"; - - AddPropertyGroup(sourceData, "general"); - - setOneBadInput(sourceData); - - AZ_TEST_START_ASSERTTEST; - auto materialAssetOutcome = sourceData.CreateMaterialAsset(Uuid::CreateRandom(), "", false); - AZ_TEST_STOP_ASSERTTEST(expectedAsserts); // Usually one for the initial error, and one for when End() is called - - EXPECT_FALSE(materialAssetOutcome.IsSuccess()); - }; - auto expectWarning = [](AZStd::function setOneBadInput, [[maybe_unused]] uint32_t expectedAsserts = 1) { MaterialSourceData sourceData; From 9a887bd6907739ff6a278b601430f83cb2ed29f3 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Wed, 17 Nov 2021 15:11:05 -0800 Subject: [PATCH 26/32] Removed unused lambda function. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp index 95aa343ed5..61999d808e 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp @@ -908,17 +908,6 @@ namespace UnitTest TEST_F(MaterialTests, TestMaterialPropertyValueAsAny) { - auto checkRoundTrip = [](const AZ::RPI::MaterialPropertyValue &original) - { - AZ::RPI::MaterialPropertyValue convertedValue = MaterialPropertyValue::FromAny(MaterialPropertyValue::ToAny(original)); - EXPECT_EQ(original, convertedValue); - - if (original.Is>()) - { - EXPECT_EQ(original.GetValue>().GetHint(), convertedValue.GetValue>().GetHint()); - } - }; - CheckPropertyValueRoundTrip(true); CheckPropertyValueRoundTrip(false); CheckPropertyValueRoundTrip(7); From b533a9566a0a221dd4f70486ab2a3d397bcae5c7 Mon Sep 17 00:00:00 2001 From: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> Date: Thu, 18 Nov 2021 09:11:46 +0000 Subject: [PATCH 27/32] Fix for viewport not updating correctly when switching camera views (#5719) Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> --- .../AtomToolsFramework/Viewport/ViewportInteractionImpl.h | 8 +++++++- .../Code/Source/Viewport/ViewportInteractionImpl.cpp | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ViewportInteractionImpl.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ViewportInteractionImpl.h index 9de74752ff..b6ad6e17d1 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ViewportInteractionImpl.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ViewportInteractionImpl.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -17,7 +18,9 @@ namespace AtomToolsFramework { //! A concrete implementation of the ViewportInteractionRequestBus. //! Primarily concerned with picking (screen to world and world to screen transformations). - class ViewportInteractionImpl : public AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler + class ViewportInteractionImpl + : public AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler + , private AZ::RPI::ViewportContextIdNotificationBus::Handler { public: explicit ViewportInteractionImpl(AZ::RPI::ViewPtr viewPtr); @@ -37,6 +40,9 @@ namespace AtomToolsFramework AZStd::function m_deviceScalingFactorFn; //! Callback to determine the device scaling factor. private: + // ViewportContextIdNotificationBus overrides ... + void OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view) override; + AZ::RPI::ViewPtr m_viewPtr; }; } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ViewportInteractionImpl.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ViewportInteractionImpl.cpp index 475566ccee..1a015c167c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ViewportInteractionImpl.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ViewportInteractionImpl.cpp @@ -19,10 +19,12 @@ namespace AtomToolsFramework void ViewportInteractionImpl::Connect(const AzFramework::ViewportId viewportId) { AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusConnect(viewportId); + AZ::RPI::ViewportContextIdNotificationBus::Handler::BusConnect(viewportId); } void ViewportInteractionImpl::Disconnect() { + AZ::RPI::ViewportContextIdNotificationBus::Handler::BusDisconnect(); AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusDisconnect(); } @@ -58,4 +60,9 @@ namespace AtomToolsFramework { return m_deviceScalingFactorFn(); } + + void ViewportInteractionImpl::OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view) + { + m_viewPtr = AZStd::move(view); + } } // namespace AtomToolsFramework From cf540b6f44c7e439505a29d8d2ce4989c4ae8232 Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Thu, 18 Nov 2021 09:57:29 +0000 Subject: [PATCH 28/32] Defaulting the joint setup display to ON instead of OFF (#5696) Signed-off-by: amzn-sean <75276488+amzn-sean@users.noreply.github.com> --- .../Code/Editor/EditorJointConfiguration.cpp | 58 ++++++++++++++++++- .../Code/Editor/EditorJointConfiguration.h | 16 ++++- .../Code/Source/EditorBallJointComponent.cpp | 2 +- .../Code/Source/EditorHingeJointComponent.cpp | 2 +- 4 files changed, 72 insertions(+), 6 deletions(-) diff --git a/Gems/PhysX/Code/Editor/EditorJointConfiguration.cpp b/Gems/PhysX/Code/Editor/EditorJointConfiguration.cpp index 02e684de63..166c44de22 100644 --- a/Gems/PhysX/Code/Editor/EditorJointConfiguration.cpp +++ b/Gems/PhysX/Code/Editor/EditorJointConfiguration.cpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace { @@ -213,7 +214,7 @@ namespace PhysX if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(4, &EditorJointConfig::VersionConverter) + ->Version(5, &EditorJointConfig::VersionConverter) ->Field("Local Position", &EditorJointConfig::m_localPosition) ->Field("Local Rotation", &EditorJointConfig::m_localRotation) ->Field("Parent Entity", &EditorJointConfig::m_leadEntity) @@ -228,6 +229,12 @@ namespace PhysX if (auto* editContext = serializeContext->GetEditContext()) { + editContext->Enum("Joint Display Setup State", "Options for displaying joint setup.") + ->Value("Never", EditorJointConfig::DisplaySetupState::Never) + ->Value("Selected", EditorJointConfig::DisplaySetupState::Selected) + ->Value("Always", EditorJointConfig::DisplaySetupState::Always) + ; + editContext->Class( "PhysX Joint Configuration", "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") @@ -244,8 +251,11 @@ namespace PhysX ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorJointConfig::ValidateLeadEntityId) ->DataElement(0, &PhysX::EditorJointConfig::m_selfCollide, "Lead-Follower Collide" , "When active, the lead and follower pair will collide with each other.") - ->DataElement(0, &PhysX::EditorJointConfig::m_displayJointSetup, "Display Setup in Viewport" - , "Display joint setup in the viewport.") + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &PhysX::EditorJointConfig::m_displayJointSetup, "Display Setup in Viewport" + , "Never = Not shown." + "Select = Show setup display when entity is selected." + "Always = Always show setup display.") ->Attribute(AZ::Edit::Attributes::ReadOnly, &EditorJointConfig::IsInComponentMode) ->DataElement(0, &PhysX::EditorJointConfig::m_selectLeadOnSnap, "Select Lead on Snap" , "Select lead entity on snap to position in component mode.") @@ -306,6 +316,23 @@ namespace PhysX m_followerEntity); } + bool EditorJointConfig::ShowSetupDisplay() const + { + switch(m_displayJointSetup) + { + case DisplaySetupState::Always: + return true; + case DisplaySetupState::Selected: + { + bool showSetup = false; + AzToolsFramework::EditorEntityInfoRequestBus::EventResult( + showSetup, m_followerEntity, &AzToolsFramework::EditorEntityInfoRequests::IsSelected); + return showSetup; + } + } + return false; + } + bool EditorJointConfig::IsInComponentMode() const { return m_inComponentMode; @@ -343,6 +370,31 @@ namespace PhysX } } + // convert m_displayJointSetup from a bool to the enum with the option Never,Selected,Always show joint setup helpers. + if (classElement.GetVersion() <= 4) + { + // get the current bool setting and remove it. + bool oldSetting = false; + const int displayJointSetupIndex = classElement.FindElement(AZ_CRC_CE("Display Debug")); + if (displayJointSetupIndex >= 0) + { + AZ::SerializeContext::DataElementNode& elementNode = classElement.GetSubElement(displayJointSetupIndex); + elementNode.GetData(oldSetting); + classElement.RemoveElement(displayJointSetupIndex); + } + + //if the old setting was on set it to 'Selected'. otherwise 'Never' + if (oldSetting) + { + classElement.AddElementWithData(context, "Display Debug", EditorJointConfig::DisplaySetupState::Selected); + } + else + { + classElement.AddElementWithData(context, "Display Debug", EditorJointConfig::DisplaySetupState::Never); + } + } + + return result; } diff --git a/Gems/PhysX/Code/Editor/EditorJointConfiguration.h b/Gems/PhysX/Code/Editor/EditorJointConfiguration.h index 89ab31e4a7..f3dcd4afed 100644 --- a/Gems/PhysX/Code/Editor/EditorJointConfiguration.h +++ b/Gems/PhysX/Code/Editor/EditorJointConfiguration.h @@ -100,12 +100,21 @@ namespace PhysX AZ_TYPE_INFO(EditorJointConfig, "{8A966D65-CA97-4786-A13C-ACAA519D97EA}"); static void Reflect(AZ::ReflectContext* context); + enum class DisplaySetupState : AZ::u8 + { + Never = 0, + Selected, + Always + }; + void SetLeadEntityId(AZ::EntityId leadEntityId); JointGenericProperties ToGenericProperties() const; JointComponentConfiguration ToGameTimeConfig() const; + bool ShowSetupDisplay() const; + bool m_breakable = false; - bool m_displayJointSetup = false; + DisplaySetupState m_displayJointSetup = DisplaySetupState::Selected; bool m_inComponentMode = false; bool m_selectLeadOnSnap = true; bool m_selfCollide = false; @@ -129,3 +138,8 @@ namespace PhysX }; } // namespace PhysX + +namespace AZ +{ + AZ_TYPE_INFO_SPECIALIZE(PhysX::EditorJointConfig::DisplaySetupState, "{17EBE6BD-289A-4326-8A24-DCE3B7FEC51E}"); +} // namespace AZ diff --git a/Gems/PhysX/Code/Source/EditorBallJointComponent.cpp b/Gems/PhysX/Code/Source/EditorBallJointComponent.cpp index fa71fa0061..d7065a869d 100644 --- a/Gems/PhysX/Code/Source/EditorBallJointComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorBallJointComponent.cpp @@ -215,7 +215,7 @@ namespace PhysX { EditorJointComponent::DisplayEntityViewport(viewportInfo, debugDisplay); - if (!m_config.m_displayJointSetup && + if (!m_config.ShowSetupDisplay() && !m_config.m_inComponentMode) { return; diff --git a/Gems/PhysX/Code/Source/EditorHingeJointComponent.cpp b/Gems/PhysX/Code/Source/EditorHingeJointComponent.cpp index 1b575074e2..f009c990b4 100644 --- a/Gems/PhysX/Code/Source/EditorHingeJointComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorHingeJointComponent.cpp @@ -211,7 +211,7 @@ namespace PhysX { EditorJointComponent::DisplayEntityViewport(viewportInfo, debugDisplay); - if (!m_config.m_displayJointSetup && + if (!m_config.ShowSetupDisplay() && !m_config.m_inComponentMode) { return; From bf4f52e146b09a3171c98926e29d0101be868dc8 Mon Sep 17 00:00:00 2001 From: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> Date: Thu, 18 Nov 2021 10:58:18 +0000 Subject: [PATCH 29/32] Updates and fixes to viewport placement (#5712) * updates to use more modern viewport intersection logic Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * updates to editor viewport ray intersection for object placement Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * make ed_defaultEntityPlacementDistance visible to Viewport.cpp Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * fix link error for AZ_CVAR variable Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * updates following review feedback Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> --- Code/Editor/2DViewport.cpp | 24 +- Code/Editor/EditorViewportWidget.cpp | 6 +- Code/Editor/EditorViewportWidget.h | 3 +- .../SandboxIntegration.cpp | 10 +- Code/Editor/Viewport.cpp | 236 ++---------------- Code/Editor/Viewport.h | 43 ++-- .../Viewport/ViewportMessages.cpp | 30 +++ .../Viewport/ViewportMessages.h | 6 + .../ViewportSelection/EditorSelectionUtil.cpp | 3 - .../ViewportSelection/EditorSelectionUtil.h | 3 + 10 files changed, 98 insertions(+), 266 deletions(-) diff --git a/Code/Editor/2DViewport.cpp b/Code/Editor/2DViewport.cpp index ba433c869f..4d0609907f 100644 --- a/Code/Editor/2DViewport.cpp +++ b/Code/Editor/2DViewport.cpp @@ -234,7 +234,7 @@ void Q2DViewport::UpdateContent(int flags) } ////////////////////////////////////////////////////////////////////////// -void Q2DViewport::OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) +void Q2DViewport::OnRButtonDown([[maybe_unused]] Qt::KeyboardModifiers modifiers, const QPoint& point) { if (GetIEditor()->IsInGameMode()) { @@ -246,9 +246,6 @@ void Q2DViewport::OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& p setFocus(); } - // Check Edit Tool. - MouseCallback(eMouseRDown, point, modifiers); - SetCurrentCursor(STD_CURSOR_MOVE, QString()); // Save the mouse down position @@ -273,17 +270,8 @@ void Q2DViewport::OnRButtonUp([[maybe_unused]] Qt::KeyboardModifiers modifiers, } ////////////////////////////////////////////////////////////////////////// -void Q2DViewport::OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) +void Q2DViewport::OnMButtonDown([[maybe_unused]] Qt::KeyboardModifiers modifiers, const QPoint& point) { - //////////////////////////////////////////////////////////////////////// - // User pressed the middle mouse button - //////////////////////////////////////////////////////////////////////// - // Check Edit Tool. - if (MouseCallback(eMouseMDown, point, modifiers)) - { - return; - } - // Save the mouse down position m_RMouseDownPos = point; @@ -300,14 +288,8 @@ void Q2DViewport::OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& p } ////////////////////////////////////////////////////////////////////////// -void Q2DViewport::OnMButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) +void Q2DViewport::OnMButtonUp([[maybe_unused]] Qt::KeyboardModifiers modifiers, [[maybe_unused]] const QPoint& point) { - // Check Edit Tool. - if (MouseCallback(eMouseMUp, point, modifiers)) - { - return; - } - SetViewMode(NothingMode); ReleaseMouse(); diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 86a91a25bb..8f94afd514 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -2307,10 +2307,10 @@ void* EditorViewportWidget::GetSystemCursorConstraintWindow() const return systemCursorConstrained ? renderOverlayHWND() : nullptr; } -void EditorViewportWidget::BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt) +void EditorViewportWidget::BuildDragDropContext( + AzQtComponents::ViewportDragContext& context, const AzFramework::ViewportId viewportId, const QPoint& point) { - const auto scaledPoint = WidgetToViewport(pt); - QtViewport::BuildDragDropContext(context, scaledPoint); + QtViewport::BuildDragDropContext(context, viewportId, point); } void EditorViewportWidget::RestoreViewportAfterGameMode() diff --git a/Code/Editor/EditorViewportWidget.h b/Code/Editor/EditorViewportWidget.h index d20f3fe939..7d8daba8c5 100644 --- a/Code/Editor/EditorViewportWidget.h +++ b/Code/Editor/EditorViewportWidget.h @@ -273,7 +273,8 @@ private: bool CheckRespondToInput() const; - void BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt) override; + void BuildDragDropContext( + AzQtComponents::ViewportDragContext& context, AzFramework::ViewportId viewportId, const QPoint& point) override; void SetAsActiveViewport(); void PushDisableRendering(); diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 4aae4191a0..64bd943d63 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -57,6 +56,7 @@ #include #include #include +#include #include #include @@ -1394,13 +1394,13 @@ void SandboxIntegrationManager::ContextMenu_NewEntity() { AZ::Vector3 worldPosition = AZ::Vector3::CreateZero(); - CViewport* view = GetIEditor()->GetViewManager()->GetGameViewport(); // If we don't have a viewport active to aid in placement, the object // will be created at the origin. - if (view) + if (CViewport* view = GetIEditor()->GetViewManager()->GetGameViewport()) { - const QPoint viewPoint(static_cast(m_contextMenuViewPoint.GetX()), static_cast(m_contextMenuViewPoint.GetY())); - worldPosition = view->GetHitLocation(viewPoint); + worldPosition = AzToolsFramework::FindClosestPickIntersection( + view->GetViewportId(), AzFramework::ScreenPointFromVector2(m_contextMenuViewPoint), AzToolsFramework::EditorPickRayLength, + GetDefaultEntityPlacementDistance()); } CreateNewEntityAtPosition(worldPosition); diff --git a/Code/Editor/Viewport.cpp b/Code/Editor/Viewport.cpp index c8f2e268d9..77be6e260e 100644 --- a/Code/Editor/Viewport.cpp +++ b/Code/Editor/Viewport.cpp @@ -14,14 +14,19 @@ // Qt #include +// AzCore +#include + // AzQtComponents #include #include #include #include +#include // Editor +#include "Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h" #include "ViewManager.h" #include "Include/ITransformManipulator.h" #include "Include/HitContext.h" @@ -32,22 +37,35 @@ #include "GameEngine.h" #include "Settings.h" - #ifdef LoadCursor #undef LoadCursor #endif +AZ_CVAR( + float, + ed_defaultEntityPlacementDistance, + 10.0f, + nullptr, + AZ::ConsoleFunctorFlags::Null, + "The default distance to place an entity from the camera if no intersection is found"); + +float GetDefaultEntityPlacementDistance() +{ + return ed_defaultEntityPlacementDistance; +} + ////////////////////////////////////////////////////////////////////// // Viewport drag and drop support ////////////////////////////////////////////////////////////////////// -void QtViewport::BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt) +void QtViewport::BuildDragDropContext( + AzQtComponents::ViewportDragContext& context, const AzFramework::ViewportId viewportId, const QPoint& point) { - context.m_hitLocation = AZ::Vector3::CreateZero(); - context.m_hitLocation = GetHitLocation(pt); + context.m_hitLocation = AzToolsFramework::FindClosestPickIntersection( + viewportId, AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(point), AzToolsFramework::EditorPickRayLength, + GetDefaultEntityPlacementDistance()); } - void QtViewport::dragEnterEvent(QDragEnterEvent* event) { if (!GetIEditor()->GetGameEngine()->IsLevelLoaded()) @@ -66,7 +84,7 @@ void QtViewport::dragEnterEvent(QDragEnterEvent* event) // new bus-based way of doing it (install a listener!) using namespace AzQtComponents; ViewportDragContext context; - BuildDragDropContext(context, event->pos()); + BuildDragDropContext(context, GetViewportId(), event->pos()); DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragEnter, event, context); } } @@ -89,7 +107,7 @@ void QtViewport::dragMoveEvent(QDragMoveEvent* event) // new bus-based way of doing it (install a listener!) using namespace AzQtComponents; ViewportDragContext context; - BuildDragDropContext(context, event->pos()); + BuildDragDropContext(context, GetViewportId(), event->pos()); DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragMove, event, context); } } @@ -112,7 +130,7 @@ void QtViewport::dropEvent(QDropEvent* event) { // new bus-based way of doing it (install a listener!) ViewportDragContext context; - BuildDragDropContext(context, event->pos()); + BuildDragDropContext(context, GetViewportId(), event->pos()); DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::Drop, event, context); } } @@ -340,13 +358,6 @@ void QtViewport::resizeEvent(QResizeEvent* event) Update(); } -////////////////////////////////////////////////////////////////////////// -void QtViewport::leaveEvent(QEvent* event) -{ - QWidget::leaveEvent(event); - MouseCallback(eMouseLeave, QPoint(), Qt::KeyboardModifiers(), Qt::MouseButtons()); -} - ////////////////////////////////////////////////////////////////////////// void QtViewport::paintEvent([[maybe_unused]] QPaintEvent* event) { @@ -581,63 +592,7 @@ void QtViewport::keyReleaseEvent(QKeyEvent* event) OnKeyUp(nativeKey, 1, event->nativeModifiers()); } -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnLButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - // Save the mouse down position - m_cMouseDownPos = point; - - if (MouseCallback(eMouseLDown, point, modifiers)) - { - return; - } -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnLButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - // Check Edit Tool. - MouseCallback(eMouseLUp, point, modifiers); -} -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - MouseCallback(eMouseRDown, point, modifiers); -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnRButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - MouseCallback(eMouseRUp, point, modifiers); -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - // Check Edit Tool. - MouseCallback(eMouseMDown, point, modifiers); -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnMButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - // Move the viewer to the mouse location. - // Check Edit Tool. - MouseCallback(eMouseMUp, point, modifiers); -} -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnMButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - MouseCallback(eMouseMDblClick, point, modifiers); -} - - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnMouseMove(Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint& point) -{ - MouseCallback(eMouseMove, point, modifiers, buttons); -} ////////////////////////////////////////////////////////////////////////// void QtViewport::OnSetCursor() @@ -696,44 +651,6 @@ void QtViewport::OnDragSelectRectangle(const QRect& rect, bool bNormalizeRect) GetIEditor()->SetStatusText(szNewStatusText); } -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnLButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - if (GetIEditor()->IsInGameMode()) - { - // Ignore double clicks while in game. - return; - } - - MouseCallback(eMouseLDblClick, point, modifiers); -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnRButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - MouseCallback(eMouseRDblClick, point, modifiers); -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnKeyDown([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) -{ - if (GetIEditor()->IsInGameMode()) - { - // Ignore key downs while in game. - return; - } -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnKeyUp([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) -{ - if (GetIEditor()->IsInGameMode()) - { - // Ignore key downs while in game. - return; - } -} - ////////////////////////////////////////////////////////////////////////// void QtViewport::SetCurrentCursor(const QCursor& hCursor, const QString& cursorString) { @@ -1119,29 +1036,6 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo) return false; } -AZ::Vector3 QtViewport::GetHitLocation(const QPoint& point) -{ - Vec3 pos = Vec3(ZERO); - HitContext hit; - if (HitTest(point, hit)) - { - pos = hit.raySrc + hit.rayDir * hit.dist; - pos = SnapToGrid(pos); - } - else - { - bool hitTerrain; - pos = ViewToWorld(point, &hitTerrain); - if (hitTerrain) - { - pos.z = GetIEditor()->GetTerrainElevation(pos.x, pos.y); - } - pos = SnapToGrid(pos); - } - - return AZ::Vector3(pos.x, pos.y, pos.z); -} - ////////////////////////////////////////////////////////////////////////// void QtViewport::SetZoomFactor(float fZoomFactor) { @@ -1315,84 +1209,6 @@ bool QtViewport::GetAdvancedSelectModeFlag() return m_bAdvancedSelectMode; } -////////////////////////////////////////////////////////////////////////// -bool QtViewport::MouseCallback(EMouseEvent event, const QPoint& point, Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons) -{ - AZ_PROFILE_FUNCTION(Editor); - - // Ignore any mouse events in game mode. - if (GetIEditor()->IsInGameMode()) - { - return true; - } - - // We must ignore mouse events when we are in the middle of an assert. - // Reason: If we have an assert called from an engine module under the editor, if we call this function, - // it may call the engine again and cause a deadlock. - // Concrete example: CryPhysics called from Trackview causing an assert, and moving the cursor over the viewport - // would cause the editor to freeze as it calls CryPhysics again for a raycast while it didn't release the lock. - if (gEnv->pSystem->IsAssertDialogVisible()) - { - return true; - } - - ////////////////////////////////////////////////////////////////////////// - // Hit test gizmo objects. - ////////////////////////////////////////////////////////////////////////// - bool bAltClick = (modifiers & Qt::AltModifier); - bool bCtrlClick = (modifiers & Qt::ControlModifier); - bool bShiftClick = (modifiers & Qt::ShiftModifier); - - int flags = (bCtrlClick ? MK_CONTROL : 0) | - (bShiftClick ? MK_SHIFT : 0) | - ((buttons& Qt::LeftButton) ? MK_LBUTTON : 0) | - ((buttons& Qt::MiddleButton) ? MK_MBUTTON : 0) | - ((buttons& Qt::RightButton) ? MK_RBUTTON : 0); - - switch (event) - { - case eMouseMove: - - if (m_nLastUpdateFrame == m_nLastMouseMoveFrame) - { - // If mouse move event generated in the same frame, ignore it. - return false; - } - m_nLastMouseMoveFrame = m_nLastUpdateFrame; - - // Skip the marker position update if anything is selected, since it is only used - // by the info bar which doesn't show the marker when there is an active selection. - // This helps a performance issue when calling ViewToWorld (which calls RayWorldIntersection) - // on every mouse movement becomes very expensive in scenes with large amounts of entities. - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (!(buttons & Qt::RightButton) /* && m_nLastUpdateFrame != m_nLastMouseMoveFrame*/ && (selection && selection->IsEmpty())) - { - //m_nLastMouseMoveFrame = m_nLastUpdateFrame; - Vec3 pos = ViewToWorld(point); - GetIEditor()->SetMarkerPosition(pos); - } - break; - } - - QPoint tempPoint(point.x(), point.y()); - - ////////////////////////////////////////////////////////////////////////// - // Handle viewport manipulators. - ////////////////////////////////////////////////////////////////////////// - if (!bAltClick) - { - ITransformManipulator* pManipulator = GetIEditor()->GetTransformManipulator(); - if (pManipulator) - { - if (pManipulator->MouseCallback(this, event, tempPoint, flags)) - { - return true; - } - } - } - - return false; -} ////////////////////////////////////////////////////////////////////////// void QtViewport::ProcessRenderLisneters(DisplayContext& rstDisplayContext) { diff --git a/Code/Editor/Viewport.h b/Code/Editor/Viewport.h index 7f8ccc4c4f..bf44b914aa 100644 --- a/Code/Editor/Viewport.h +++ b/Code/Editor/Viewport.h @@ -6,13 +6,12 @@ * */ - // Description : interface for the CViewport class. - #pragma once #if !defined(Q_MOC_RUN) +#include #include #include #include @@ -88,6 +87,9 @@ enum EStdCursor STD_CURSOR_LAST, }; +//! The default distance an entity is placed from the camera if there is no intersection +SANDBOX_API float GetDefaultEntityPlacementDistance(); + AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING class SANDBOX_API CViewport : public IDisplayViewport @@ -201,7 +203,6 @@ public: //! Performs hit testing of 2d point in view to find which object hit. virtual bool HitTest(const QPoint& point, HitContext& hitInfo) = 0; - virtual AZ::Vector3 GetHitLocation(const QPoint& point) = 0; virtual void MakeConstructionPlane(int axis) = 0; @@ -432,7 +433,6 @@ public: //! Performs hit testing of 2d point in view to find which object hit. bool HitTest(const QPoint& point, HitContext& hitInfo) override; - AZ::Vector3 GetHitLocation(const QPoint& point) override; //! Do 2D hit testing of line in world space. // pToCameraDistance is an optional output parameter in which distance from the camera to the line is returned. @@ -522,9 +522,6 @@ protected: void setRenderOverlayVisible(bool); bool isRenderOverlayVisible() const; - // called to process mouse callback inside the viewport. - virtual bool MouseCallback(EMouseEvent event, const QPoint& point, Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons = Qt::NoButton); - void ProcessRenderLisneters(DisplayContext& rstDisplayContext); void mousePressEvent(QMouseEvent* event) override; @@ -535,29 +532,29 @@ protected: void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; void resizeEvent(QResizeEvent* event) override; - void leaveEvent(QEvent* event) override; - void paintEvent(QPaintEvent* event) override; - virtual void OnMouseMove(Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint& point); - virtual void OnMouseWheel(Qt::KeyboardModifiers modifiers, short zDelta, const QPoint& pt); - virtual void OnLButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnLButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnRButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnMButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnMButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnLButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnRButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); - virtual void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); + virtual void OnMouseMove(Qt::KeyboardModifiers, Qt::MouseButtons, const QPoint&) {} + virtual void OnMouseWheel(Qt::KeyboardModifiers, short zDelta, const QPoint&); + virtual void OnLButtonDown(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnLButtonUp(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnRButtonDown(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnRButtonUp(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnMButtonDblClk(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnMButtonDown(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnMButtonUp(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnLButtonDblClk(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnRButtonDblClk(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnKeyDown([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) {} + virtual void OnKeyUp([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) {} #if defined(AZ_PLATFORM_WINDOWS) void OnRawInput(UINT wParam, HRAWINPUT lParam); #endif void OnSetCursor(); - virtual void BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt); + virtual void BuildDragDropContext( + AzQtComponents::ViewportDragContext& context, AzFramework::ViewportId viewportId, const QPoint& point); + void dragEnterEvent(QDragEnterEvent* event) override; void dragMoveEvent(QDragMoveEvent* event) override; void dragLeaveEvent(QDragLeaveEvent* event) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.cpp index e3b45aca2b..8f8bd3e3f9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.cpp @@ -6,6 +6,7 @@ * */ +#include #include namespace AzToolsFramework @@ -62,4 +63,33 @@ namespace AzToolsFramework return circleBoundWidth; } + + AZ::Vector3 FindClosestPickIntersection( + AzFramework::ViewportId viewportId, const AzFramework::ScreenPoint& screenPoint, const float rayLength, const float defaultDistance) + { + using AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus; + AzToolsFramework::ViewportInteraction::ProjectedViewportRay viewportRay{}; + ViewportInteractionRequestBus::EventResult( + viewportRay, viewportId, &ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay, screenPoint); + + AzFramework::RenderGeometry::RayRequest ray; + ray.m_startWorldPosition = viewportRay.origin; + ray.m_endWorldPosition = viewportRay.origin + viewportRay.direction * rayLength; + ray.m_onlyVisible = true; + + AzFramework::RenderGeometry::RayResult renderGeometryIntersectionResult; + AzFramework::RenderGeometry::IntersectorBus::EventResult( + renderGeometryIntersectionResult, AzToolsFramework::GetEntityContextId(), + &AzFramework::RenderGeometry::IntersectorBus::Events::RayIntersect, ray); + + // attempt a ray intersection with any visible mesh and return the intersection position if successful + if (renderGeometryIntersectionResult) + { + return renderGeometryIntersectionResult.m_worldPosition; + } + else + { + return viewportRay.origin + viewportRay.direction * defaultDistance; + } + } } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h index 84a8daa83e..aa97eb361e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h @@ -334,6 +334,12 @@ namespace AzToolsFramework return entityContextId; } + //! Performs an intersection test against meshes in the scene, if there is a hit (the ray intersects + //! a mesh), that position is returned, otherwise a point projected defaultDistance from the + //! origin of the ray will be returned. + AZ::Vector3 FindClosestPickIntersection( + AzFramework::ViewportId viewportId, const AzFramework::ScreenPoint& screenPoint, float rayLength, float defaultDistance); + //! Maps a mouse interaction event to a ClickDetector event. //! @note Function only cares about up or down events, all other events are mapped to Nil (ignored). AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp index a5ef66e7a3..0a7bed6b18 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp @@ -18,9 +18,6 @@ namespace AzToolsFramework { - // default ray length for picking in the viewport - static const float EditorPickRayLength = 1000.0f; - AZ::Vector3 CalculateCenterOffset(const AZ::EntityId entityId, const EditorTransformComponentSelectionRequests::Pivot pivot) { if (Centered(pivot)) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h index d58549b329..5c9f47fdd3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h @@ -26,6 +26,9 @@ namespace AzFramework namespace AzToolsFramework { + //! Default ray length for picking in the viewport. + inline constexpr float EditorPickRayLength = 1000.0f; + //! Is the pivot at the center of the object (middle of extents) or at the //! exported authored object root position. inline bool Centered(const EditorTransformComponentSelectionRequests::Pivot pivot) From ca6b7d1d1f6659f5711677482f688ac35c95bf8e Mon Sep 17 00:00:00 2001 From: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> Date: Thu, 18 Nov 2021 13:09:06 +0000 Subject: [PATCH 30/32] Add test for ViewportInteractionImpl use of ViewportInteractionRequestBus (#5741) Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> --- .../Tests/ViewportInteractionImplTests.cpp | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/ViewportInteractionImplTests.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/ViewportInteractionImplTests.cpp index fa5bc5b6e5..2dfe4f7c29 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/ViewportInteractionImplTests.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/ViewportInteractionImplTests.cpp @@ -7,12 +7,14 @@ */ #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -169,4 +171,39 @@ namespace UnitTest EXPECT_EQ(intersection, AZ::Intersect::SphereIsectTypes::ISECT_RAY_SPHERE_ISECT); } + + TEST_F(ViewportInteractionImplFixture, ViewportInteractionRequestsReturnsNewViewWhenItIsChanged) + { + // Given + const auto primaryViewTransform = AZ::Matrix3x4::CreateFromMatrix3x3AndTranslation( + AZ::Matrix3x3::CreateRotationZ(AZ::DegToRad(90.0f)) * AZ::Matrix3x3::CreateRotationX(AZ::DegToRad(-45.0f)), + AZ::Vector3(-10.0f, -15.0f, 20.0f)); + + m_view->SetCameraTransform(primaryViewTransform); + + AZ::RPI::ViewPtr secondaryView = AZ::RPI::View::CreateView(AZ::Name("SecondaryView"), AZ::RPI::View::UsageCamera); + + const auto secondaryViewTransform = AZ::Matrix3x4::CreateFromMatrix3x3AndTranslation( + AZ::Matrix3x3::CreateRotationZ(AZ::DegToRad(-90.0f)) * AZ::Matrix3x3::CreateRotationX(AZ::DegToRad(30.0f)), + AZ::Vector3(-50.0f, -25.0f, 10.0f)); + + secondaryView->SetCameraTransform(secondaryViewTransform); + + // When + AZ::RPI::ViewportContextIdNotificationBus::Event( + TestViewportId, &AZ::RPI::ViewportContextIdNotificationBus::Events::OnViewportDefaultViewChanged, secondaryView); + + // retrieve updated camera transform + AzFramework::CameraState cameraState; + AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::EventResult( + cameraState, TestViewportId, &AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Events::GetCameraState); + + const auto cameraMatrix = AzFramework::CameraTransform(cameraState); + const auto cameraTransform = AZ::Matrix3x4::CreateFromMatrix3x3AndTranslation( + AZ::Matrix3x3::CreateFromMatrix4x4(cameraMatrix), cameraMatrix.GetTranslation()); + + // Then + // camera transform matches that of the secondary view + EXPECT_THAT(cameraTransform, IsClose(secondaryViewTransform)); + } } // namespace UnitTest From f18f5318c0559c1a899fcf04f219bea387f454f4 Mon Sep 17 00:00:00 2001 From: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> Date: Thu, 18 Nov 2021 15:34:30 +0000 Subject: [PATCH 31/32] Fix for gizmo axis text not displaying correctly on high dpi screens (#5745) Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> --- .../Code/Source/AtomDebugDisplayViewportInterface.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp index 12e4ccd8ad..e2d99dbbef 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp @@ -1353,9 +1353,8 @@ namespace AZ::AtomBridge // if 2d draw need to project pos to screen first AzFramework::TextDrawParameters params; AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); - const auto dpiScaleFactor = viewportContext->GetDpiScalingFactor(); params.m_drawViewportId = viewportContext->GetId(); // get the viewport ID so default viewport works - params.m_position = AZ::Vector3(x * dpiScaleFactor, y * dpiScaleFactor, 1.0f); + params.m_position = AZ::Vector3(x, y, 1.0f); params.m_color = m_rendState.m_color; params.m_scale = AZ::Vector2(size); params.m_hAlign = center ? AzFramework::TextHorizontalAlignment::Center : AzFramework::TextHorizontalAlignment::Left; //! Horizontal text alignment From a54a149877ee2054b315e9b9276dfec255713f62 Mon Sep 17 00:00:00 2001 From: John Jones-Steele <82226755+jjjoness@users.noreply.github.com> Date: Thu, 18 Nov 2021 16:06:54 +0000 Subject: [PATCH 32/32] Changes from comments made after merge (#5738) Signed-off-by: John Jones-Steele <82226755+jjjoness@users.noreply.github.com> --- .../Terrain/EditorScripts/Terrain_SupportsPhysics.py | 10 +++++----- .../Gem/PythonTests/Terrain/TestSuite_Main.py | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/Terrain/EditorScripts/Terrain_SupportsPhysics.py b/AutomatedTesting/Gem/PythonTests/Terrain/EditorScripts/Terrain_SupportsPhysics.py index 8ecafb8600..e68b0932c2 100644 --- a/AutomatedTesting/Gem/PythonTests/Terrain/EditorScripts/Terrain_SupportsPhysics.py +++ b/AutomatedTesting/Gem/PythonTests/Terrain/EditorScripts/Terrain_SupportsPhysics.py @@ -31,7 +31,7 @@ def Terrain_SupportsPhysics(): Test Steps: 1) Load the base level 2) Create 2 test entities, one parent at 512.0, 512.0, 50.0 and one child at the default position and add the required components - 2a) Create a ball at 600.0, 600.0, 46.0 - This position is bot too high over the heighfield so will collide in a reasonable time + 2a) Create a ball at 600.0, 600.0, 46.0 - This position is not too high over the heightfield so will collide in a reasonable time 3) Start the Tracer to catch any errors and warnings 4) Change the Axis Aligned Box Shape dimensions 5) Set the Vegetation Shape reference to TestEntity1 @@ -80,7 +80,7 @@ def Terrain_SupportsPhysics(): height_provider_entity = hydra.Entity("TestEntity2") height_provider_entity.create_entity(azmath.Vector3(0.0, 0.0, 0.0), entity2_components_to_add,terrain_spawner_entity.id) Report.result(Tests.create_height_provider_entity, height_provider_entity.id.IsValid()) - # 2a) Create a ball at 600.0, 600.0, 46.0 - This position is bot too high over the heighfield so will collide in a reasonable time + # 2a) Create a ball at 600.0, 600.0, 46.0 - This position is not too high over the heightfield so will collide in a reasonable time ball = hydra.Entity("Ball") ball.create_entity(azmath.Vector3(600.0, 600.0, 46.0), ball_components_to_add) Report.result(Tests.create_test_ball, ball.id.IsValid()) @@ -107,9 +107,9 @@ def Terrain_SupportsPhysics(): Report.result(Tests.frequency_changed, math.isclose(Frequency, FrequencyVal, abs_tol = 0.00001)) # 7) Set the Gradient List to TestEntity2 - pte = hydra.get_property_tree(terrain_spawner_entity.components[2]) - pte.add_container_item("Configuration|Gradient Entities", 0, height_provider_entity.id) - checkID = pte.get_container_item("Configuration|Gradient Entities", 0) + propertyTree = hydra.get_property_tree(terrain_spawner_entity.components[2]) + propertyTree.add_container_item("Configuration|Gradient Entities", 0, height_provider_entity.id) + checkID = propertyTree.get_container_item("Configuration|Gradient Entities", 0) Report.result(Tests.entity_added, checkID.GetValue() == height_provider_entity.id) # 8) Set the PhysX Collider to Sphere mode diff --git a/AutomatedTesting/Gem/PythonTests/Terrain/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/Terrain/TestSuite_Main.py index 8942065472..c5eec74c08 100644 --- a/AutomatedTesting/Gem/PythonTests/Terrain/TestSuite_Main.py +++ b/AutomatedTesting/Gem/PythonTests/Terrain/TestSuite_Main.py @@ -13,15 +13,15 @@ import os import sys from ly_test_tools import LAUNCHERS -from ly_test_tools.o3de.editor_test import EditorTestSuite, EditorSingleTest +from ly_test_tools.o3de.editor_test import EditorTestSuite, EditorSharedTest @pytest.mark.SUITE_main @pytest.mark.parametrize("launcher_platform", ['windows_editor']) @pytest.mark.parametrize("project", ["AutomatedTesting"]) class TestAutomation(EditorTestSuite): - class test_AxisAlignedBoxShape_ConfigurationWorks(EditorSingleTest): + class test_AxisAlignedBoxShape_ConfigurationWorks(EditorSharedTest): from .EditorScripts import TerrainPhysicsCollider_ChangesSizeWithAxisAlignedBoxShapeChanges as test_module - class test_Terrain_SupportsPhysics(EditorSingleTest): + class test_Terrain_SupportsPhysics(EditorSharedTest): from .EditorScripts import Terrain_SupportsPhysics as test_module