From 2c6cfdd7dc73a57a1ed1714c8c3a5dacdc1e9258 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sat, 9 Oct 2021 18:17:50 -0500 Subject: [PATCH] Implemented support for semi-live previews of materials in the material property inspector. Changed thumbnailer bus to use const pixmap Changed capture request call back to use const pixmap instead of image Replaced scene and pipeline members with constructor parameters Added material preview renderer to editor material system component with new requests and notifications Changed material property inspector details group to persistent heading so the preview image widget would not get destroyed during refreshes. But this was also a backlog task. Changed common preview render camera to use lookat Moved default asset caching to thumbnail renderer Signed-off-by: Guthrie Adams --- .../Thumbnails/ThumbnailerBus.h | 2 +- .../Code/Source/Thumbnail/ImageThumbnail.cpp | 2 +- .../Code/Source/Thumbnail/ImageThumbnail.h | 2 +- .../PreviewRenderer/PreviewRenderer.h | 12 +- .../PreviewRenderer/PreviewRenderer.cpp | 25 +-- ...orMaterialSystemComponentNotificationBus.h | 35 ++++ .../EditorMaterialSystemComponentRequestBus.h | 8 +- .../EditorCommonFeaturesSystemComponent.cpp | 2 +- .../EditorMaterialComponentInspector.cpp | 177 +++++++++--------- .../EditorMaterialComponentInspector.h | 21 ++- .../Material/EditorMaterialComponentSlot.cpp | 3 + .../EditorMaterialSystemComponent.cpp | 69 ++++++- .../Material/EditorMaterialSystemComponent.h | 30 ++- .../Source/Previewer/CommonPreviewContent.cpp | 69 ++++--- .../Source/Previewer/CommonPreviewContent.h | 21 +-- .../Previewer/CommonThumbnailRenderer.cpp | 41 ++-- .../Previewer/CommonThumbnailRenderer.h | 18 +- .../Previewer/LightingPresetThumbnail.cpp | 2 +- .../Previewer/LightingPresetThumbnail.h | 2 +- .../Source/Previewer/MaterialThumbnail.cpp | 2 +- .../Code/Source/Previewer/MaterialThumbnail.h | 2 +- .../Code/Source/Previewer/ModelThumbnail.cpp | 2 +- .../Code/Source/Previewer/ModelThumbnail.h | 2 +- .../Code/Source/Previewer/ThumbnailUtils.cpp | 13 +- .../Code/Source/Previewer/ThumbnailUtils.h | 5 +- ...egration_commonfeatures_editor_files.cmake | 1 + 26 files changed, 365 insertions(+), 203 deletions(-) create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentNotificationBus.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h index 6f074da878..acd8ba3966 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h @@ -90,7 +90,7 @@ namespace AzToolsFramework typedef SharedThumbnailKey BusIdType; //! notify product thumbnail that the data is ready - virtual void ThumbnailRendered(QPixmap& thumbnailImage) = 0; + virtual void ThumbnailRendered(const QPixmap& thumbnailImage) = 0; //! notify product thumbnail that the thumbnail failed to render virtual void ThumbnailFailedToRender() = 0; }; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.cpp index 084e38a2db..cdd63dca18 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.cpp @@ -67,7 +67,7 @@ namespace ImageProcessingAtom m_renderWait.acquire(); } - void ImageThumbnail::ThumbnailRendered(QPixmap& thumbnailImage) + void ImageThumbnail::ThumbnailRendered(const QPixmap& thumbnailImage) { m_pixmap = thumbnailImage; m_renderWait.release(); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.h index 45fd178285..eadbfca945 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.h @@ -34,7 +34,7 @@ namespace ImageProcessingAtom ~ImageThumbnail() override; //! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides... - void ThumbnailRendered(QPixmap& thumbnailImage) override; + void ThumbnailRendered(const QPixmap& thumbnailImage) override; void ThumbnailFailedToRender() override; protected: diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/PreviewRenderer/PreviewRenderer.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/PreviewRenderer/PreviewRenderer.h index b772bfcaf2..acedc77751 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/PreviewRenderer/PreviewRenderer.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/PreviewRenderer/PreviewRenderer.h @@ -20,7 +20,7 @@ namespace AzFramework class Scene; } -class QImage; +class QPixmap; namespace AtomToolsFramework { @@ -30,7 +30,7 @@ namespace AtomToolsFramework public: AZ_CLASS_ALLOCATOR(PreviewRenderer, AZ::SystemAllocator, 0); - PreviewRenderer(); + PreviewRenderer(const AZStd::string& sceneName, const AZStd::string& pipelineName); ~PreviewRenderer(); struct CaptureRequest final @@ -38,15 +38,15 @@ namespace AtomToolsFramework int m_size = 512; AZStd::shared_ptr m_content; AZStd::function m_captureFailedCallback; - AZStd::function m_captureCompleteCallback; + AZStd::function m_captureCompleteCallback; }; + void AddCaptureRequest(const CaptureRequest& captureRequest); + AZ::RPI::ScenePtr GetScene() const; AZ::RPI::ViewPtr GetView() const; AZ::Uuid GetEntityContextId() const; - void AddCaptureRequest(const CaptureRequest& captureRequest); - enum class State : AZ::s8 { None, @@ -81,8 +81,6 @@ namespace AtomToolsFramework static constexpr float FieldOfView = AZ::Constants::HalfPi; AZ::RPI::ScenePtr m_scene; - AZStd::string m_sceneName = "Preview Renderer Scene"; - AZStd::string m_pipelineName = "Preview Renderer Pipeline"; AZStd::shared_ptr m_frameworkScene; AZ::RPI::RenderPipelinePtr m_renderPipeline; AZ::RPI::ViewPtr m_view; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRenderer.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRenderer.cpp index dfefd0203e..06969abee4 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRenderer.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRenderer.cpp @@ -24,9 +24,12 @@ #include #include +#include +#include + namespace AtomToolsFramework { - PreviewRenderer::PreviewRenderer() + PreviewRenderer::PreviewRenderer(const AZStd::string& sceneName, const AZStd::string& pipelineName) { PreviewerFeatureProcessorProviderBus::Handler::BusConnect(); @@ -46,7 +49,7 @@ namespace AtomToolsFramework auto sceneSystem = AzFramework::SceneSystemInterface::Get(); AZ_Assert(sceneSystem, "Failed to get scene system implementation."); - AZ::Outcome, AZStd::string> createSceneOutcome = sceneSystem->CreateScene(m_sceneName); + AZ::Outcome, AZStd::string> createSceneOutcome = sceneSystem->CreateScene(sceneName); AZ_Assert(createSceneOutcome, createSceneOutcome.GetError().c_str()); m_frameworkScene = createSceneOutcome.TakeValue(); @@ -56,7 +59,7 @@ namespace AtomToolsFramework // Create a render pipeline from the specified asset for the window context and add the pipeline to the scene AZ::RPI::RenderPipelineDescriptor pipelineDesc; pipelineDesc.m_mainViewTagName = "MainCamera"; - pipelineDesc.m_name = m_pipelineName; + pipelineDesc.m_name = pipelineName; pipelineDesc.m_rootPassTemplate = "MainPipelineRenderToTexture"; // We have to set the samples to 4 to match the pipeline passes' setting, otherwise it may lead to device lost issue @@ -66,7 +69,7 @@ namespace AtomToolsFramework m_scene->AddRenderPipeline(m_renderPipeline); m_scene->Activate(); AZ::RPI::RPISystemInterface::Get()->RegisterScene(m_scene); - m_passHierarchy.push_back(m_pipelineName); + m_passHierarchy.push_back(pipelineName); m_passHierarchy.push_back("CopyToSwapChain"); // Connect camera to pipeline's default view after camera entity activated @@ -97,6 +100,11 @@ namespace AtomToolsFramework m_frameworkScene->UnsetSubsystem(m_entityContext.get()); } + void PreviewRenderer::AddCaptureRequest(const CaptureRequest& captureRequest) + { + m_captureRequestQueue.push(captureRequest); + } + AZ::RPI::ScenePtr PreviewRenderer::GetScene() const { return m_scene; @@ -112,11 +120,6 @@ namespace AtomToolsFramework return m_entityContext->GetContextId(); } - void PreviewRenderer::AddCaptureRequest(const CaptureRequest& captureRequest) - { - m_captureRequestQueue.push(captureRequest); - } - void PreviewRenderer::SetState(State state) { auto stepItr = m_states.find(m_currentState); @@ -199,9 +202,9 @@ namespace AtomToolsFramework { if (result.m_dataBuffer) { - currentCaptureRequest.m_captureCompleteCallback(QImage( + currentCaptureRequest.m_captureCompleteCallback(QPixmap::fromImage(QImage( result.m_dataBuffer.get()->data(), result.m_imageDescriptor.m_size.m_width, result.m_imageDescriptor.m_size.m_height, - QImage::Format_RGBA8888)); + QImage::Format_RGBA8888))); } else { diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentNotificationBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentNotificationBus.h new file mode 100644 index 0000000000..4e655c7835 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentNotificationBus.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include +#include +#include + +class QPixmap; + +namespace AZ +{ + namespace Render + { + //! EditorMaterialSystemComponentNotifications provides an interface to communicate with EditorMaterialSystemComponent + class EditorMaterialSystemComponentNotifications : public AZ::EBusTraits + { + public: + // Only a single handler is allowed + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; + + //! Notify that a material preview image is ready + virtual void OnRenderMaterialPreviewComplete( + const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId, const QPixmap& pixmap) = 0; + }; + using EditorMaterialSystemComponentNotificationBus = AZ::EBus; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h index 47fad038b6..059e6dec8e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ + #pragma once #include @@ -17,8 +18,7 @@ namespace AZ namespace Render { //! EditorMaterialSystemComponentRequests provides an interface to communicate with MaterialEditor - class EditorMaterialSystemComponentRequests - : public AZ::EBusTraits + class EditorMaterialSystemComponentRequests : public AZ::EBusTraits { public: // Only a single handler is allowed @@ -31,6 +31,10 @@ namespace AZ //! Open material instance editor virtual void OpenMaterialInspector( const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId) = 0; + + //! Generate a material preview image + virtual void RenderMaterialPreview( + const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId) = 0; }; using EditorMaterialSystemComponentRequestBus = AZ::EBus; } // namespace Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/EditorCommonFeaturesSystemComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/EditorCommonFeaturesSystemComponent.cpp index 19a7eda24b..34cd9f59d0 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/EditorCommonFeaturesSystemComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/EditorCommonFeaturesSystemComponent.cpp @@ -98,9 +98,9 @@ namespace AZ void EditorCommonFeaturesSystemComponent::Deactivate() { - AzToolsFramework::EditorLevelNotificationBus::Handler::BusDisconnect(); AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect(); AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); + AzToolsFramework::EditorLevelNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler::BusDisconnect(); m_skinnedMeshDebugDisplay.reset(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp index 665adcd568..7562049031 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp @@ -23,10 +23,6 @@ #include #include #include -#include -#include -#include -#include #include #include #include @@ -49,29 +45,18 @@ namespace AZ MaterialPropertyInspector::MaterialPropertyInspector(QWidget* parent) : AtomToolsFramework::InspectorWidget(parent) { - // Create the menu button - QToolButton* menuButton = new QToolButton(this); - menuButton->setAutoRaise(true); - menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg")); - menuButton->setVisible(true); - QObject::connect(menuButton, &QToolButton::clicked, this, [this]() { OpenMenu(); }); - AddHeading(menuButton); - - m_messageLabel = new QLabel(this); - m_messageLabel->setWordWrap(true); - m_messageLabel->setVisible(true); - m_messageLabel->setAlignment(Qt::AlignCenter); - m_messageLabel->setText(tr("Material not available")); - AddHeading(m_messageLabel); - + CreateHeading(); + AZ::TickBus::Handler::BusConnect(); AZ::EntitySystemBus::Handler::BusConnect(); + EditorMaterialSystemComponentNotificationBus::Handler::BusConnect(); } MaterialPropertyInspector::~MaterialPropertyInspector() { AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect(); - AZ::EntitySystemBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); + AZ::EntitySystemBus::Handler::BusDisconnect(); + EditorMaterialSystemComponentNotificationBus::Handler::BusDisconnect(); MaterialComponentNotificationBus::Handler::BusDisconnect(); } @@ -140,7 +125,7 @@ namespace AZ } Populate(); - m_messageLabel->setVisible(false); + LoadOverridesFromEntity(); return true; } @@ -152,8 +137,9 @@ namespace AZ m_dirtyPropertyFlags.set(); m_editorFunctors = {}; m_internalEditNotification = {}; - m_messageLabel->setVisible(true); - m_messageLabel->setText(tr("Material not available")); + m_updateUI = {}; + m_updatePreview = {}; + UpdateHeading(); } bool MaterialPropertyInspector::IsLoaded() const @@ -168,49 +154,62 @@ namespace AZ m_dirtyPropertyFlags.set(); m_internalEditNotification = {}; - AZ::TickBus::Handler::BusDisconnect(); AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect(); AtomToolsFramework::InspectorWidget::Reset(); } - void MaterialPropertyInspector::AddDetailsGroup() + void MaterialPropertyInspector::CreateHeading() { - const AZStd::string& groupName = "Details"; - const AZStd::string& groupDisplayName = "Details"; - const AZStd::string& groupDescription = ""; + // Create the menu button + QToolButton* menuButton = new QToolButton(this); + menuButton->setAutoRaise(true); + menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg")); + menuButton->setVisible(true); + QObject::connect(menuButton, &QToolButton::clicked, this, [this]() { OpenMenu(); }); + AddHeading(menuButton); - auto propertyGroupContainer = new QWidget(this); - propertyGroupContainer->setLayout(new QHBoxLayout()); + m_overviewImage = new QLabel(this); + m_overviewImage->setFixedSize(QSize(120, 120)); + m_overviewImage->setVisible(false); - AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey = - MAKE_TKEY(AzToolsFramework::AssetBrowser::ProductThumbnailKey, m_editData.m_materialAssetId); - auto thumbnailWidget = new AzToolsFramework::Thumbnailer::ThumbnailWidget(this); - thumbnailWidget->setFixedSize(QSize(120, 120)); - thumbnailWidget->setVisible(true); - thumbnailWidget->SetThumbnailKey(thumbnailKey, AzToolsFramework::Thumbnailer::ThumbnailContext::DefaultContext); - propertyGroupContainer->layout()->addWidget(thumbnailWidget); - - auto materialInfoWidget = new QLabel(this); + m_overviewText = new QLabel(this); QSizePolicy sizePolicy1(QSizePolicy::Ignored, QSizePolicy::Preferred); sizePolicy1.setHorizontalStretch(0); sizePolicy1.setVerticalStretch(0); - sizePolicy1.setHeightForWidth(materialInfoWidget->sizePolicy().hasHeightForWidth()); - materialInfoWidget->setSizePolicy(sizePolicy1); - materialInfoWidget->setMinimumSize(QSize(0, 0)); - materialInfoWidget->setMaximumSize(QSize(16777215, 16777215)); - materialInfoWidget->setTextFormat(Qt::AutoText); - materialInfoWidget->setScaledContents(false); - materialInfoWidget->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignTop); - materialInfoWidget->setWordWrap(true); + sizePolicy1.setHeightForWidth(m_overviewText->sizePolicy().hasHeightForWidth()); + m_overviewText->setSizePolicy(sizePolicy1); + m_overviewText->setMinimumSize(QSize(0, 0)); + m_overviewText->setMaximumSize(QSize(16777215, 16777215)); + m_overviewText->setTextFormat(Qt::AutoText); + m_overviewText->setScaledContents(false); + m_overviewText->setWordWrap(true); + m_overviewText->setVisible(true); + + auto overviewContainer = new QWidget(this); + overviewContainer->setLayout(new QHBoxLayout()); + overviewContainer->layout()->addWidget(m_overviewImage); + overviewContainer->layout()->addWidget(m_overviewText); + AddHeading(overviewContainer); + } + + void MaterialPropertyInspector::UpdateHeading() + { + if (!IsLoaded()) + { + m_overviewText->setText(tr("Material not available")); + m_overviewText->setAlignment(Qt::AlignCenter); + m_overviewImage->setVisible(false); + return; + } QFileInfo materialFileInfo(AZ::RPI::AssetUtils::GetProductPathByAssetId(m_editData.m_materialAsset.GetId()).c_str()); QFileInfo materialSourceFileInfo(m_editData.m_materialSourcePath.c_str()); QFileInfo materialTypeSourceFileInfo(m_editData.m_materialTypeSourcePath.c_str()); - QFileInfo materialParentSourceFileInfo(AZ::RPI::AssetUtils::GetSourcePathByAssetId(m_editData.m_materialParentAsset.GetId()).c_str()); + QFileInfo materialParentSourceFileInfo( + AZ::RPI::AssetUtils::GetSourcePathByAssetId(m_editData.m_materialParentAsset.GetId()).c_str()); AZStd::string entityName; - AZ::ComponentApplicationBus::BroadcastResult( - entityName, &AZ::ComponentApplicationBus::Events::GetEntityName, m_entityId); + AZ::ComponentApplicationBus::BroadcastResult(entityName, &AZ::ComponentApplicationBus::Events::GetEntityName, m_entityId); AZStd::string slotName; MaterialComponentRequestBus::EventResult( @@ -226,7 +225,8 @@ namespace AZ } if (!materialTypeSourceFileInfo.fileName().isEmpty()) { - materialInfo += tr("Material Type %1").arg(materialTypeSourceFileInfo.fileName()); + materialInfo += + tr("Material Type %1").arg(materialTypeSourceFileInfo.fileName()); } if (!materialSourceFileInfo.fileName().isEmpty()) { @@ -234,14 +234,15 @@ namespace AZ } if (!materialParentSourceFileInfo.fileName().isEmpty()) { - materialInfo += tr("Material Parent %1").arg(materialParentSourceFileInfo.fileName()); + materialInfo += + tr("Material Parent %1").arg(materialParentSourceFileInfo.fileName()); } materialInfo += tr(""); - materialInfoWidget->setText(materialInfo); - propertyGroupContainer->layout()->addWidget(materialInfoWidget); - - AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupContainer); + m_overviewText->setText(materialInfo); + m_overviewText->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignTop); + m_overviewImage->setVisible(true); + m_updatePreview = true; } void MaterialPropertyInspector::AddUvNamesGroup() @@ -282,13 +283,8 @@ namespace AZ AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupWidget); } - void MaterialPropertyInspector::Populate() + void MaterialPropertyInspector::AddPropertiesGroup() { - AddGroupsBegin(); - - AddDetailsGroup(); - AddUvNamesGroup(); - // Copy all of the properties from the material asset to the source data that will be exported for (const auto& groupDefinition : m_editData.m_materialTypeSourceData.GetGroupDefinitionsInDisplayOrder()) { @@ -327,10 +323,14 @@ namespace AZ [this](const auto node) { return GetInstanceNodePropertyIndicator(node); }, 0); AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupWidget); } + } + void MaterialPropertyInspector::Populate() + { + AddGroupsBegin(); + AddUvNamesGroup(); + AddPropertiesGroup(); AddGroupsEnd(); - - LoadOverridesFromEntity(); } void MaterialPropertyInspector::LoadOverridesFromEntity() @@ -375,6 +375,7 @@ namespace AZ m_dirtyPropertyFlags.set(); RunEditorMaterialFunctors(); RebuildAll(); + UpdateHeading(); } void MaterialPropertyInspector::SaveOverridesToEntity(bool commitChanges) @@ -398,6 +399,8 @@ namespace AZ MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited); m_internalEditNotification = false; } + + m_updatePreview = true; } void MaterialPropertyInspector::RunEditorMaterialFunctors() @@ -607,7 +610,8 @@ namespace AZ MaterialComponentRequestBus::Event( m_entityId, &MaterialComponentRequestBus::Events::SetPropertyOverrides, m_materialAssignmentId, MaterialPropertyOverrideMap()); - QueueUpdateUI(); + m_updateUI = true; + m_updatePreview = true; }); action->setEnabled(IsLoaded()); @@ -702,10 +706,7 @@ namespace AZ void MaterialPropertyInspector::OnEntityActivated(const AZ::EntityId& entityId) { - if (m_entityId == entityId) - { - QueueUpdateUI(); - } + m_updateUI |= (m_entityId == entityId); } void MaterialPropertyInspector::OnEntityDeactivated(const AZ::EntityId& entityId) @@ -719,25 +720,39 @@ namespace AZ void MaterialPropertyInspector::OnEntityNameChanged(const AZ::EntityId& entityId, const AZStd::string& name) { AZ_UNUSED(name); - if (m_entityId == entityId) - { - QueueUpdateUI(); - } + m_updateUI |= (m_entityId == entityId); } void MaterialPropertyInspector::OnTick(float deltaTime, ScriptTimePoint time) { AZ_UNUSED(time); AZ_UNUSED(deltaTime); - UpdateUI(); - AZ::TickBus::Handler::BusDisconnect(); + if (m_updateUI) + { + m_updateUI = false; + UpdateUI(); + } + + if (m_updatePreview) + { + m_updatePreview = false; + EditorMaterialSystemComponentRequestBus::Broadcast( + &EditorMaterialSystemComponentRequestBus::Events::RenderMaterialPreview, m_entityId, m_materialAssignmentId); + } } void MaterialPropertyInspector::OnMaterialsEdited() { - if (!m_internalEditNotification) + m_updateUI |= !m_internalEditNotification; + m_updatePreview = true; + } + + void MaterialPropertyInspector::OnRenderMaterialPreviewComplete( + const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId, const QPixmap& pixmap) + { + if (m_overviewImage && m_entityId == entityId && m_materialAssignmentId == materialAssignmentId) { - QueueUpdateUI(); + m_overviewImage->setPixmap(pixmap); } } @@ -761,14 +776,6 @@ namespace AZ LoadMaterial(m_entityId, m_materialAssignmentId); } } - - void MaterialPropertyInspector::QueueUpdateUI() - { - if (!AZ::TickBus::Handler::BusIsConnected()) - { - AZ::TickBus::Handler::BusConnect(); - } - } } // namespace EditorMaterialComponentInspector } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.h index 048c1e19cb..6199fba179 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.h @@ -9,6 +9,7 @@ #pragma once #if !defined(Q_MOC_RUN) +#include #include #include #include @@ -39,6 +40,7 @@ namespace AZ , public AZ::EntitySystemBus::Handler , public AZ::TickBus::Handler , public MaterialComponentNotificationBus::Handler + , public EditorMaterialSystemComponentNotificationBus::Handler { Q_OBJECT public: @@ -89,11 +91,19 @@ namespace AZ //! MaterialComponentNotificationBus::Handler overrides... void OnMaterialsEdited() override; - void UpdateUI(); - void QueueUpdateUI(); + //! EditorMaterialSystemComponentNotificationBus::Handler overrides... + void OnRenderMaterialPreviewComplete( + const AZ::EntityId& entityId, + const AZ::Render::MaterialAssignmentId& materialAssignmentId, + const QPixmap& pixmap) override; + + void UpdateUI(); + + void CreateHeading(); + void UpdateHeading(); - void AddDetailsGroup(); void AddUvNamesGroup(); + void AddPropertiesGroup(); void LoadOverridesFromEntity(); void SaveOverridesToEntity(bool commitChanges); @@ -115,7 +125,10 @@ namespace AZ AZ::RPI::MaterialPropertyFlags m_dirtyPropertyFlags = {}; AZStd::unordered_map m_groups = {}; bool m_internalEditNotification = {}; - QLabel* m_messageLabel = {}; + bool m_updateUI = {}; + bool m_updatePreview = {}; + QLabel* m_overviewText = {}; + QLabel* m_overviewImage = {}; }; } // namespace EditorMaterialComponentInspector } // namespace Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index f5d38f48c4..21d045a072 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -315,6 +315,9 @@ namespace AZ AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast( &AzToolsFramework::ToolsApplicationRequests::Bus::Events::AddDirtyEntity, m_entityId); + EditorMaterialSystemComponentRequestBus::Broadcast( + &EditorMaterialSystemComponentRequestBus::Events::RenderMaterialPreview, m_entityId, m_id); + MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited); AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp index 9efa8eb333..e18cc0b907 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp @@ -6,7 +6,10 @@ * */ +#include #include +#include +#include #include #include #include @@ -19,6 +22,7 @@ #include #include #include +#include // Disables warning messages triggered by the Qt library // 4251: class needs to have dll-interface to be used by clients of class @@ -28,6 +32,8 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") #include #include #include +#include +#include #include AZ_POP_DISABLE_WARNING @@ -86,17 +92,20 @@ namespace AZ AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect(); AzToolsFramework::EditorMenuNotificationBus::Handler::BusConnect(); AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); - - m_materialBrowserInteractions.reset(aznew MaterialBrowserInteractions); + AzFramework::AssetCatalogEventBus::Handler::BusConnect(); + AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect(); } void EditorMaterialSystemComponent::Deactivate() { + AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect(); + AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); EditorMaterialSystemComponentRequestBus::Handler::BusDisconnect(); AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); AzToolsFramework::EditorMenuNotificationBus::Handler::BusDisconnect(); AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); + m_previewRenderer.reset(); m_materialBrowserInteractions.reset(); if (m_openMaterialEditorAction) @@ -143,6 +152,47 @@ namespace AZ } } + void EditorMaterialSystemComponent::RenderMaterialPreview( + const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId) + { + static constexpr const char* DefaultModelPath = "models/sphere.azmodel"; + static constexpr const char* DefaultLightingPresetPath = "lightingpresets/thumbnail.lightingpreset.azasset"; + + if (m_previewRenderer) + { + AZ::Data::AssetId materialAssetId = {}; + MaterialComponentRequestBus::EventResult( + materialAssetId, entityId, &MaterialComponentRequestBus::Events::GetMaterialOverride, materialAssignmentId); + if (!materialAssetId.IsValid()) + { + MaterialComponentRequestBus::EventResult( + materialAssetId, entityId, &MaterialComponentRequestBus::Events::GetDefaultMaterialAssetId, materialAssignmentId); + } + + AZ::Render::MaterialPropertyOverrideMap propertyOverrides; + AZ::Render::MaterialComponentRequestBus::EventResult( + propertyOverrides, entityId, &AZ::Render::MaterialComponentRequestBus::Events::GetPropertyOverrides, + materialAssignmentId); + + m_previewRenderer->AddCaptureRequest( + { 128, + AZStd::make_shared( + m_previewRenderer->GetScene(), m_previewRenderer->GetView(), m_previewRenderer->GetEntityContextId(), + AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultModelPath), materialAssetId, + AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultLightingPresetPath), propertyOverrides), + []() + { + // failed + }, + [entityId, materialAssignmentId](const QPixmap& pixmap) + { + AZ::Render::EditorMaterialSystemComponentNotificationBus::Broadcast( + &AZ::Render::EditorMaterialSystemComponentNotificationBus::Events::OnRenderMaterialPreviewComplete, entityId, + materialAssignmentId, pixmap); + } }); + } + } + void EditorMaterialSystemComponent::OnPopulateToolMenuItems() { if (!m_openMaterialEditorAction) @@ -185,6 +235,21 @@ namespace AZ "Material Property Inspector", LyViewPane::CategoryTools, inspectorOptions); } + void EditorMaterialSystemComponent::OnCatalogLoaded([[maybe_unused]] const char* catalogFile) + { + AZ::TickBus::QueueFunction([this](){ + m_materialBrowserInteractions.reset(aznew MaterialBrowserInteractions); + m_previewRenderer.reset(aznew AtomToolsFramework::PreviewRenderer( + "EditorMaterialSystemComponent Preview Scene", "EditorMaterialSystemComponent Preview Pipeline")); + }); + } + + void EditorMaterialSystemComponent::OnApplicationAboutToStop() + { + m_previewRenderer.reset(); + m_materialBrowserInteractions.reset(); + } + AzToolsFramework::AssetBrowser::SourceFileDetails EditorMaterialSystemComponent::GetSourceFileDetails( const char* fullSourceFileName) { diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h index 60e489f55e..f2ccbdc435 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h @@ -7,13 +7,14 @@ */ #pragma once +#include +#include +#include #include +#include #include #include #include - -#include - #include namespace AZ @@ -21,12 +22,14 @@ namespace AZ namespace Render { //! System component that manages launching and maintaining connections with the material editor. - class EditorMaterialSystemComponent + class EditorMaterialSystemComponent final : public AZ::Component - , private EditorMaterialSystemComponentRequestBus::Handler - , private AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler - , private AzToolsFramework::EditorMenuNotificationBus::Handler - , private AzToolsFramework::EditorEvents::Bus::Handler + , public EditorMaterialSystemComponentRequestBus::Handler + , public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler + , public AzToolsFramework::EditorMenuNotificationBus::Handler + , public AzToolsFramework::EditorEvents::Bus::Handler + , public AzFramework::AssetCatalogEventBus::Handler + , public AzFramework::ApplicationLifecycleEvents::Bus::Handler { public: AZ_COMPONENT(EditorMaterialSystemComponent, "{96652157-DA0B-420F-B49C-0207C585144C}"); @@ -47,6 +50,8 @@ namespace AZ //! EditorMaterialSystemComponentRequestBus::Handler overrides... void OpenMaterialEditor(const AZStd::string& sourcePath) override; void OpenMaterialInspector(const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId) override; + void RenderMaterialPreview( + const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId) override; //! AssetBrowserInteractionNotificationBus::Handler overrides... AzToolsFramework::AssetBrowser::SourceFileDetails GetSourceFileDetails(const char* fullSourceFileName) override; @@ -58,9 +63,16 @@ namespace AZ // AztoolsFramework::EditorEvents::Bus::Handler overrides... void NotifyRegisterViews() override; - QAction* m_openMaterialEditorAction = nullptr; + // AzFramework::AssetCatalogEventBus::Handler overrides ... + void OnCatalogLoaded(const char* catalogFile) override; + + // AzFramework::ApplicationLifecycleEvents overrides... + void OnApplicationAboutToStop() override; + + QAction* m_openMaterialEditorAction = nullptr; AZStd::unique_ptr m_materialBrowserInteractions; + AZStd::unique_ptr m_previewRenderer; }; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonPreviewContent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonPreviewContent.cpp index 6890fabb01..966877317c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonPreviewContent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonPreviewContent.cpp @@ -35,10 +35,12 @@ namespace AZ AZ::Uuid entityContextId, const Data::AssetId& modelAssetId, const Data::AssetId& materialAssetId, - const Data::AssetId& lightingPresetAssetId) + const Data::AssetId& lightingPresetAssetId, + const Render::MaterialPropertyOverrideMap& materialPropertyOverrides) : m_scene(scene) , m_view(view) , m_entityContextId(entityContextId) + , m_materialPropertyOverrides(materialPropertyOverrides) { // Create preview model AzFramework::EntityContextRequestBus::EventResult( @@ -49,13 +51,9 @@ namespace AZ m_modelEntity->Init(); m_modelEntity->Activate(); - m_defaultModelAsset.Create(DefaultModelAssetId, true); - m_defaultMaterialAsset.Create(DefaultMaterialAssetId, true); - m_defaultLightingPresetAsset.Create(DefaultLightingPresetAssetId, true); - - m_modelAsset.Create(modelAssetId.IsValid() ? modelAssetId : DefaultModelAssetId, false); - m_materialAsset.Create(materialAssetId.IsValid() ? materialAssetId : DefaultMaterialAssetId, false); - m_lightingPresetAsset.Create(lightingPresetAssetId.IsValid() ? lightingPresetAssetId : DefaultLightingPresetAssetId, false); + m_modelAsset.Create(modelAssetId); + m_materialAsset.Create(materialAssetId); + m_lightingPresetAsset.Create(lightingPresetAssetId); } CommonPreviewContent::~CommonPreviewContent() @@ -113,35 +111,44 @@ namespace AZ m_modelEntity->GetId(), &Render::MeshComponentRequestBus::Events::SetModelAsset, m_modelAsset); Render::MaterialComponentRequestBus::Event( - m_modelEntity->GetId(), &Render::MaterialComponentRequestBus::Events::SetDefaultMaterialOverride, m_materialAsset.GetId()); + m_modelEntity->GetId(), &Render::MaterialComponentRequestBus::Events::SetMaterialOverride, + Render::DefaultMaterialAssignmentId, m_materialAsset.GetId()); + + Render::MaterialComponentRequestBus::Event( + m_modelEntity->GetId(), &Render::MaterialComponentRequestBus::Events::SetPropertyOverrides, + Render::DefaultMaterialAssignmentId, m_materialPropertyOverrides); } void CommonPreviewContent::UpdateLighting() { - auto preset = m_lightingPresetAsset->GetDataAs(); - if (preset) + if (m_lightingPresetAsset.IsReady()) { - auto iblFeatureProcessor = m_scene->GetFeatureProcessor(); - auto postProcessFeatureProcessor = m_scene->GetFeatureProcessor(); - auto postProcessSettingInterface = postProcessFeatureProcessor->GetOrCreateSettingsInterface(EntityId()); - auto exposureControlSettingInterface = postProcessSettingInterface->GetOrCreateExposureControlSettingsInterface(); - auto directionalLightFeatureProcessor = m_scene->GetFeatureProcessor(); - auto skyboxFeatureProcessor = m_scene->GetFeatureProcessor(); - skyboxFeatureProcessor->Enable(true); - skyboxFeatureProcessor->SetSkyboxMode(Render::SkyBoxMode::Cubemap); + auto preset = m_lightingPresetAsset->GetDataAs(); + if (preset) + { + auto iblFeatureProcessor = m_scene->GetFeatureProcessor(); + auto postProcessFeatureProcessor = m_scene->GetFeatureProcessor(); + auto postProcessSettingInterface = postProcessFeatureProcessor->GetOrCreateSettingsInterface(EntityId()); + auto exposureControlSettingInterface = postProcessSettingInterface->GetOrCreateExposureControlSettingsInterface(); + auto directionalLightFeatureProcessor = + m_scene->GetFeatureProcessor(); + auto skyboxFeatureProcessor = m_scene->GetFeatureProcessor(); + skyboxFeatureProcessor->Enable(true); + skyboxFeatureProcessor->SetSkyboxMode(Render::SkyBoxMode::Cubemap); - Camera::Configuration cameraConfig; - cameraConfig.m_fovRadians = FieldOfView; - cameraConfig.m_nearClipDistance = NearDist; - cameraConfig.m_farClipDistance = FarDist; - cameraConfig.m_frustumWidth = 100.0f; - cameraConfig.m_frustumHeight = 100.0f; + Camera::Configuration cameraConfig; + cameraConfig.m_fovRadians = FieldOfView; + cameraConfig.m_nearClipDistance = NearDist; + cameraConfig.m_farClipDistance = FarDist; + cameraConfig.m_frustumWidth = 100.0f; + cameraConfig.m_frustumHeight = 100.0f; - AZStd::vector lightHandles; + AZStd::vector lightHandles; - preset->ApplyLightingPreset( - iblFeatureProcessor, skyboxFeatureProcessor, exposureControlSettingInterface, directionalLightFeatureProcessor, - cameraConfig, lightHandles); + preset->ApplyLightingPreset( + iblFeatureProcessor, skyboxFeatureProcessor, exposureControlSettingInterface, directionalLightFeatureProcessor, + cameraConfig, lightHandles); + } } } @@ -157,8 +164,8 @@ namespace AZ const auto distance = radius + NearDist; const auto cameraRotation = Quaternion::CreateFromAxisAngle(Vector3::CreateAxisZ(), CameraRotationAngle); - const auto cameraPosition = center - cameraRotation.TransformVector(Vector3(0.0f, distance, 0.0f)); - const auto cameraTransform = Transform::CreateFromQuaternionAndTranslation(cameraRotation, cameraPosition); + const auto cameraPosition = center + cameraRotation.TransformVector(Vector3(0.0f, distance, 0.0f)); + const auto cameraTransform = Transform::CreateLookAt(cameraPosition, center); m_view->SetCameraTransform(Matrix3x4::CreateFromTransform(cameraTransform)); } } // namespace LyIntegration diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonPreviewContent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonPreviewContent.h index 482dde2986..a6bb2f6c4e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonPreviewContent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonPreviewContent.h @@ -8,8 +8,8 @@ #pragma once +#include #include -#include #include #include #include @@ -31,7 +31,8 @@ namespace AZ AZ::Uuid entityContextId, const Data::AssetId& modelAssetId, const Data::AssetId& materialAssetId, - const Data::AssetId& lightingPresetAssetId); + const Data::AssetId& lightingPresetAssetId, + const Render::MaterialPropertyOverrideMap& materialPropertyOverrides); ~CommonPreviewContent() override; @@ -57,22 +58,10 @@ namespace AZ AZ::Uuid m_entityContextId; Entity* m_modelEntity = nullptr; - static constexpr const char* DefaultLightingPresetPath = "lightingpresets/thumbnail.lightingpreset.azasset"; - const Data::AssetId DefaultLightingPresetAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultLightingPresetPath); - Data::Asset m_defaultLightingPresetAsset; - Data::Asset m_lightingPresetAsset; - - //! Model asset about to be rendered - static constexpr const char* DefaultModelPath = "models/sphere.azmodel"; - const Data::AssetId DefaultModelAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultModelPath); - Data::Asset m_defaultModelAsset; Data::Asset m_modelAsset; - - //! Material asset about to be rendered - static constexpr const char* DefaultMaterialPath = "materials/basic_grey.azmaterial"; - const Data::AssetId DefaultMaterialAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultMaterialPath); - Data::Asset m_defaultMaterialAsset; Data::Asset m_materialAsset; + Data::Asset m_lightingPresetAsset; + Render::MaterialPropertyOverrideMap m_materialPropertyOverrides; }; } // namespace LyIntegration } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonThumbnailRenderer.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonThumbnailRenderer.cpp index e9eba7a08d..f29762b563 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonThumbnailRenderer.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonThumbnailRenderer.cpp @@ -20,6 +20,13 @@ namespace AZ { CommonThumbnailRenderer::CommonThumbnailRenderer() { + m_previewRenderer.reset(aznew AtomToolsFramework::PreviewRenderer( + "CommonThumbnailRenderer Preview Scene", "CommonThumbnailRenderer Preview Pipeline")); + + m_defaultModelAsset.Create(DefaultModelAssetId, true); + m_defaultMaterialAsset.Create(DefaultMaterialAssetId, true); + m_defaultLightingPresetAsset.Create(DefaultLightingPresetAssetId, true); + // CommonThumbnailRenderer supports both models and materials AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler::BusConnect(RPI::MaterialAsset::RTTI_Type()); AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler::BusConnect(RPI::ModelAsset::RTTI_Type()); @@ -35,26 +42,24 @@ namespace AZ void CommonThumbnailRenderer::RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize) { - m_previewRenderer.AddCaptureRequest( + m_previewRenderer->AddCaptureRequest( { thumbnailSize, AZStd::make_shared( - m_previewRenderer.GetScene(), - m_previewRenderer.GetView(), - m_previewRenderer.GetEntityContextId(), - GetAssetId(thumbnailKey, RPI::ModelAsset::RTTI_Type()), - GetAssetId(thumbnailKey, RPI::MaterialAsset::RTTI_Type()), - GetAssetId(thumbnailKey, RPI::AnyAsset::RTTI_Type())), - [thumbnailKey]() - { - AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event( - thumbnailKey, &AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender); - }, - [thumbnailKey](const QImage& image) - { - AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event( - thumbnailKey, &AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailRendered, - QPixmap::fromImage(image)); - } }); + m_previewRenderer->GetScene(), m_previewRenderer->GetView(), m_previewRenderer->GetEntityContextId(), + GetAssetId(thumbnailKey, RPI::ModelAsset::RTTI_Type(), DefaultModelAssetId), + GetAssetId(thumbnailKey, RPI::MaterialAsset::RTTI_Type(), DefaultMaterialAssetId), + GetAssetId(thumbnailKey, RPI::AnyAsset::RTTI_Type(), DefaultLightingPresetAssetId), + Render::MaterialPropertyOverrideMap()), + [thumbnailKey]() + { + AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event( + thumbnailKey, &AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender); + }, + [thumbnailKey](const QPixmap& pixmap) + { + AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event( + thumbnailKey, &AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailRendered, pixmap); + } }); } bool CommonThumbnailRenderer::Installed() const diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonThumbnailRenderer.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonThumbnailRenderer.h index 0497521d44..a57c3dae8e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonThumbnailRenderer.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/CommonThumbnailRenderer.h @@ -8,6 +8,10 @@ #pragma once +#include +#include +#include +#include #include #include #include @@ -39,7 +43,19 @@ namespace AZ //! SystemTickBus::Handler interface overrides... void OnSystemTick() override; - AtomToolsFramework::PreviewRenderer m_previewRenderer; + static constexpr const char* DefaultLightingPresetPath = "lightingpresets/thumbnail.lightingpreset.azasset"; + const Data::AssetId DefaultLightingPresetAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultLightingPresetPath); + Data::Asset m_defaultLightingPresetAsset; + + static constexpr const char* DefaultModelPath = "models/sphere.azmodel"; + const Data::AssetId DefaultModelAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultModelPath); + Data::Asset m_defaultModelAsset; + + static constexpr const char* DefaultMaterialPath = ""; + const Data::AssetId DefaultMaterialAssetId; + Data::Asset m_defaultMaterialAsset; + + AZStd::unique_ptr m_previewRenderer; }; } // namespace Thumbnails } // namespace LyIntegration diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/LightingPresetThumbnail.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/LightingPresetThumbnail.cpp index 566a8d7b58..6a9c2ca2ca 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/LightingPresetThumbnail.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/LightingPresetThumbnail.cpp @@ -53,7 +53,7 @@ namespace AZ AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); } - void LightingPresetThumbnail::ThumbnailRendered(QPixmap& thumbnailImage) + void LightingPresetThumbnail::ThumbnailRendered(const QPixmap& thumbnailImage) { m_pixmap = thumbnailImage; m_renderWait.release(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/LightingPresetThumbnail.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/LightingPresetThumbnail.h index efbfe5b7d5..437a372c3c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/LightingPresetThumbnail.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/LightingPresetThumbnail.h @@ -33,7 +33,7 @@ namespace AZ ~LightingPresetThumbnail() override; //! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides... - void ThumbnailRendered(QPixmap& thumbnailImage) override; + void ThumbnailRendered(const QPixmap& thumbnailImage) override; void ThumbnailFailedToRender() override; protected: diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/MaterialThumbnail.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/MaterialThumbnail.cpp index b6a93aa59c..b9a3412d0e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/MaterialThumbnail.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/MaterialThumbnail.cpp @@ -53,7 +53,7 @@ namespace AZ AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); } - void MaterialThumbnail::ThumbnailRendered(QPixmap& thumbnailImage) + void MaterialThumbnail::ThumbnailRendered(const QPixmap& thumbnailImage) { m_pixmap = thumbnailImage; m_renderWait.release(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/MaterialThumbnail.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/MaterialThumbnail.h index 9a580d07ce..1349336245 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/MaterialThumbnail.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/MaterialThumbnail.h @@ -33,7 +33,7 @@ namespace AZ ~MaterialThumbnail() override; //! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides... - void ThumbnailRendered(QPixmap& thumbnailImage) override; + void ThumbnailRendered(const QPixmap& thumbnailImage) override; void ThumbnailFailedToRender() override; protected: diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ModelThumbnail.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ModelThumbnail.cpp index 6fe490e9dc..e3eb7a3af6 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ModelThumbnail.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ModelThumbnail.cpp @@ -53,7 +53,7 @@ namespace AZ AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); } - void ModelThumbnail::ThumbnailRendered(QPixmap& thumbnailImage) + void ModelThumbnail::ThumbnailRendered(const QPixmap& thumbnailImage) { m_pixmap = thumbnailImage; m_renderWait.release(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ModelThumbnail.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ModelThumbnail.h index 2925abe36e..5d9449e988 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ModelThumbnail.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ModelThumbnail.h @@ -33,7 +33,7 @@ namespace AZ ~ModelThumbnail() override; //! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides... - void ThumbnailRendered(QPixmap& thumbnailImage) override; + void ThumbnailRendered(const QPixmap& thumbnailImage) override; void ThumbnailFailedToRender() override; protected: diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ThumbnailUtils.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ThumbnailUtils.cpp index 8293b33763..6d3d07faef 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ThumbnailUtils.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ThumbnailUtils.cpp @@ -19,10 +19,11 @@ namespace AZ { namespace Thumbnails { - Data::AssetId GetAssetId(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, const Data::AssetType& assetType) + Data::AssetId GetAssetId( + AzToolsFramework::Thumbnailer::SharedThumbnailKey key, + const Data::AssetType& assetType, + const Data::AssetId& defaultAssetId) { - static const Data::AssetId invalidAssetId; - // if it's a source thumbnail key, find first product with a matching asset type auto sourceKey = azrtti_cast(key.data()); if (sourceKey) @@ -32,7 +33,7 @@ namespace AZ AzToolsFramework::AssetSystemRequestBus::BroadcastResult(foundIt, &AzToolsFramework::AssetSystemRequestBus::Events::GetAssetsProducedBySourceUUID, sourceKey->GetSourceUuid(), productsAssetInfo); if (!foundIt) { - return invalidAssetId; + return defaultAssetId; } auto assetInfoIt = AZStd::find_if(productsAssetInfo.begin(), productsAssetInfo.end(), [&assetType](const Data::AssetInfo& assetInfo) @@ -41,7 +42,7 @@ namespace AZ }); if (assetInfoIt == productsAssetInfo.end()) { - return invalidAssetId; + return defaultAssetId; } return assetInfoIt->m_assetId; @@ -53,7 +54,7 @@ namespace AZ { return productKey->GetAssetId(); } - return invalidAssetId; + return defaultAssetId; } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ThumbnailUtils.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ThumbnailUtils.h index e4efcd6b49..a88a25c2b7 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ThumbnailUtils.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Previewer/ThumbnailUtils.h @@ -21,7 +21,10 @@ namespace AZ namespace Thumbnails { //! Get assetId by assetType that belongs to either source or product thumbnail key - Data::AssetId GetAssetId(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, const Data::AssetType& assetType); + Data::AssetId GetAssetId( + AzToolsFramework::Thumbnailer::SharedThumbnailKey key, + const Data::AssetType& assetType, + const Data::AssetId& defaultAssetId = {}); //! Word wrap function for previewer QLabel, since by default it does not break long words such as filenames, so manual word wrap needed QString WordWrap(const QString& string, int maxLength); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake index 32f1bd882e..7c7765d3af 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake @@ -7,6 +7,7 @@ # set(FILES + Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentNotificationBus.h Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h Include/AtomLyIntegration/CommonFeatures/ReflectionProbe/EditorReflectionProbeBus.h Source/Module.cpp