Merge pull request #4652 from aws-lumberyard-dev/Atom/guthadam/thumbnail_and_preview_refactor

Material preview images update to reflect property changes
This commit is contained in:
Guthrie Adams
2021-10-15 09:56:59 -05:00
committed by GitHub
63 changed files with 1765 additions and 1867 deletions
@@ -36,6 +36,7 @@ ly_add_target(
Gem::Atom_RPI.Edit
Gem::Atom_RPI.Public
Gem::Atom_RHI.Reflect
Gem::Atom_Feature_Common.Static
Gem::Atom_Bootstrap.Headers
)
@@ -0,0 +1,39 @@
/*
* 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 <AzCore/Memory/Memory.h>
namespace AtomToolsFramework
{
//! Interface for describing scene content that will be rendered using the PreviewRenderer
class PreviewContent
{
public:
AZ_CLASS_ALLOCATOR(PreviewContent, AZ::SystemAllocator, 0);
PreviewContent() = default;
virtual ~PreviewContent() = default;
//! Initiate loading of scene content, models, materials, etc
virtual void Load() = 0;
//! Return true if content is loaded and ready to render
virtual bool IsReady() const = 0;
//! Return true if content failed to load
virtual bool IsError() const = 0;
//! Report any issues encountered while loading
virtual void ReportErrors() = 0;
//! Prepare or pose content before rendering
virtual void Update() = 0;
};
} // namespace AtomToolsFramework
@@ -0,0 +1,85 @@
/*
* 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 <Atom/RPI.Public/Base.h>
#include <Atom/RPI.Public/Pass/AttachmentReadback.h>
#include <AtomToolsFramework/PreviewRenderer/PreviewContent.h>
#include <AtomToolsFramework/PreviewRenderer/PreviewRendererState.h>
#include <AtomToolsFramework/PreviewRenderer/PreviewerFeatureProcessorProviderBus.h>
#include <AzFramework/Entity/GameEntityContextComponent.h>
namespace AzFramework
{
class Scene;
}
class QPixmap;
namespace AtomToolsFramework
{
//! Processes requests for setting up content that gets rendered to a texture and captured to an image
class PreviewRenderer final : public PreviewerFeatureProcessorProviderBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(PreviewRenderer, AZ::SystemAllocator, 0);
PreviewRenderer(const AZStd::string& sceneName, const AZStd::string& pipelineName);
~PreviewRenderer();
struct CaptureRequest final
{
int m_size = 512;
AZStd::shared_ptr<PreviewContent> m_content;
AZStd::function<void()> m_captureFailedCallback;
AZStd::function<void(const QPixmap&)> m_captureCompleteCallback;
};
void AddCaptureRequest(const CaptureRequest& captureRequest);
AZ::RPI::ScenePtr GetScene() const;
AZ::RPI::ViewPtr GetView() const;
AZ::Uuid GetEntityContextId() const;
void ProcessCaptureRequests();
void CancelCaptureRequest();
void CompleteCaptureRequest();
void LoadContent();
void UpdateLoadContent();
void CancelLoadContent();
void PoseContent();
bool StartCapture();
void EndCapture();
private:
//! AZ::Render::PreviewerFeatureProcessorProviderBus::Handler interface overrides...
void GetRequiredFeatureProcessors(AZStd::unordered_set<AZStd::string>& featureProcessors) const override;
static constexpr float AspectRatio = 1.0f;
static constexpr float NearDist = 0.001f;
static constexpr float FarDist = 100.0f;
static constexpr float FieldOfView = AZ::Constants::HalfPi;
AZ::RPI::ScenePtr m_scene;
AZStd::shared_ptr<AzFramework::Scene> m_frameworkScene;
AZ::RPI::RenderPipelinePtr m_renderPipeline;
AZ::RPI::ViewPtr m_view;
AZStd::vector<AZStd::string> m_passHierarchy;
AZStd::unique_ptr<AzFramework::EntityContext> m_entityContext;
//! Incoming requests are appended to this queue and processed one at a time in OnTick function.
AZStd::queue<CaptureRequest> m_captureRequestQueue;
CaptureRequest m_currentCaptureRequest;
AZStd::unique_ptr<PreviewRendererState> m_state;
};
} // namespace AtomToolsFramework
@@ -0,0 +1,29 @@
/*
* 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
namespace AtomToolsFramework
{
class PreviewRenderer;
//! PreviewRendererState decouples PreviewRenderer logic into easy-to-understand and debug pieces
class PreviewRendererState
{
public:
explicit PreviewRendererState(PreviewRenderer* renderer)
: m_renderer(renderer)
{
}
virtual ~PreviewRendererState() = default;
protected:
PreviewRenderer* m_renderer = {};
};
} // namespace AtomToolsFramework
@@ -0,0 +1,25 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzCore/std/containers/unordered_set.h>
#include <AzCore/std/string/string.h>
namespace AtomToolsFramework
{
//! PreviewerFeatureProcessorProviderRequests allows registering custom Feature Processors for preview image generation
class PreviewerFeatureProcessorProviderRequests : public AZ::EBusTraits
{
public:
//! Get a list of custom feature processors to register with preview image renderer
virtual void GetRequiredFeatureProcessors(AZStd::unordered_set<AZStd::string>& featureProcessors) const = 0;
};
using PreviewerFeatureProcessorProviderBus = AZ::EBus<PreviewerFeatureProcessorProviderRequests>;
} // namespace AtomToolsFramework
@@ -25,7 +25,7 @@
namespace AtomToolsFramework
{
//! The RenderViewportWidget class is a Qt wrapper around an Atom viewport.
//! RenderViewportWidget renders to an internal window using RPI::ViewportContext
//! RenderViewportWidget renders to an internal window using AZ::RPI::ViewportContext
//! and delegates input via its internal ViewportControllerList.
//! @see AZ::RPI::ViewportContext for Atom's API for setting up
class RenderViewportWidget
@@ -39,7 +39,7 @@ namespace AtomToolsFramework
public:
//! Creates a RenderViewportWidget.
//! Requires the Atom RPI to be initialized in order
//! to internally construct an RPI::ViewportContext.
//! to internally construct an AZ::RPI::ViewportContext.
//! If initializeViewportContext is set to false, nothing will be displayed on-screen until InitiliazeViewportContext is called.
explicit RenderViewportWidget(QWidget* parent = nullptr, bool shouldInitializeViewportContext = true);
~RenderViewportWidget();
@@ -0,0 +1,247 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Atom/Feature/Utils/FrameCaptureBus.h>
#include <Atom/RPI.Public/Pass/Specific/RenderToTexturePass.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <Atom/RPI.Public/RenderPipeline.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
#include <Atom/RPI.Public/View.h>
#include <Atom/RPI.Reflect/System/RenderPipelineDescriptor.h>
#include <Atom/RPI.Reflect/System/SceneDescriptor.h>
#include <AtomToolsFramework/PreviewRenderer/PreviewRenderer.h>
#include <AzCore/Math/MatrixUtils.h>
#include <AzCore/Math/Transform.h>
#include <AzFramework/Scene/Scene.h>
#include <AzFramework/Scene/SceneSystemInterface.h>
#include <PreviewRenderer/PreviewRendererCaptureState.h>
#include <PreviewRenderer/PreviewRendererIdleState.h>
#include <PreviewRenderer/PreviewRendererLoadState.h>
#include <QImage>
#include <QPixmap>
namespace AtomToolsFramework
{
PreviewRenderer::PreviewRenderer(const AZStd::string& sceneName, const AZStd::string& pipelineName)
{
PreviewerFeatureProcessorProviderBus::Handler::BusConnect();
m_entityContext = AZStd::make_unique<AzFramework::EntityContext>();
m_entityContext->InitContext();
// Create and register a scene with all required feature processors
AZStd::unordered_set<AZStd::string> featureProcessors;
PreviewerFeatureProcessorProviderBus::Broadcast(
&PreviewerFeatureProcessorProviderBus::Handler::GetRequiredFeatureProcessors, featureProcessors);
AZ::RPI::SceneDescriptor sceneDesc;
sceneDesc.m_featureProcessorNames.assign(featureProcessors.begin(), featureProcessors.end());
m_scene = AZ::RPI::Scene::CreateScene(sceneDesc);
// Bind m_frameworkScene to the entity context's AzFramework::Scene
auto sceneSystem = AzFramework::SceneSystemInterface::Get();
AZ_Assert(sceneSystem, "Failed to get scene system implementation.");
AZ::Outcome<AZStd::shared_ptr<AzFramework::Scene>, AZStd::string> createSceneOutcome = sceneSystem->CreateScene(sceneName);
AZ_Assert(createSceneOutcome, createSceneOutcome.GetError().c_str());
m_frameworkScene = createSceneOutcome.TakeValue();
m_frameworkScene->SetSubsystem(m_scene);
m_frameworkScene->SetSubsystem(m_entityContext.get());
// 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 = 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
// [GFX TODO] [ATOM-13551] Default value sand validation required to prevent pipeline crash and device lost
pipelineDesc.m_renderSettings.m_multisampleState.m_samples = 4;
m_renderPipeline = AZ::RPI::RenderPipeline::CreateRenderPipeline(pipelineDesc);
m_scene->AddRenderPipeline(m_renderPipeline);
m_scene->Activate();
AZ::RPI::RPISystemInterface::Get()->RegisterScene(m_scene);
m_passHierarchy.push_back(pipelineName);
m_passHierarchy.push_back("CopyToSwapChain");
// Connect camera to pipeline's default view after camera entity activated
AZ::Matrix4x4 viewToClipMatrix;
AZ::MakePerspectiveFovMatrixRH(viewToClipMatrix, FieldOfView, AspectRatio, NearDist, FarDist, true);
m_view = AZ::RPI::View::CreateView(AZ::Name("MainCamera"), AZ::RPI::View::UsageCamera);
m_view->SetViewToClipMatrix(viewToClipMatrix);
m_renderPipeline->SetDefaultView(m_view);
m_state.reset(new PreviewRendererIdleState(this));
}
PreviewRenderer::~PreviewRenderer()
{
PreviewerFeatureProcessorProviderBus::Handler::BusDisconnect();
m_state.reset();
m_currentCaptureRequest = {};
m_captureRequestQueue = {};
m_scene->Deactivate();
m_scene->RemoveRenderPipeline(m_renderPipeline->GetId());
AZ::RPI::RPISystemInterface::Get()->UnregisterScene(m_scene);
m_frameworkScene->UnsetSubsystem(m_scene);
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;
}
AZ::RPI::ViewPtr PreviewRenderer::GetView() const
{
return m_view;
}
AZ::Uuid PreviewRenderer::GetEntityContextId() const
{
return m_entityContext->GetContextId();
}
void PreviewRenderer::ProcessCaptureRequests()
{
if (!m_captureRequestQueue.empty())
{
// pop the next request to be rendered from the queue
m_currentCaptureRequest = m_captureRequestQueue.front();
m_captureRequestQueue.pop();
m_state.reset();
m_state.reset(new PreviewRendererLoadState(this));
}
}
void PreviewRenderer::CancelCaptureRequest()
{
if (m_currentCaptureRequest.m_captureFailedCallback)
{
m_currentCaptureRequest.m_captureFailedCallback();
}
m_state.reset();
m_state.reset(new PreviewRendererIdleState(this));
}
void PreviewRenderer::CompleteCaptureRequest()
{
m_state.reset();
m_state.reset(new PreviewRendererIdleState(this));
}
void PreviewRenderer::LoadContent()
{
m_currentCaptureRequest.m_content->Load();
}
void PreviewRenderer::UpdateLoadContent()
{
if (m_currentCaptureRequest.m_content->IsReady())
{
m_state.reset();
m_state.reset(new PreviewRendererCaptureState(this));
return;
}
if (m_currentCaptureRequest.m_content->IsError())
{
CancelLoadContent();
return;
}
}
void PreviewRenderer::CancelLoadContent()
{
m_currentCaptureRequest.m_content->ReportErrors();
CancelCaptureRequest();
}
void PreviewRenderer::PoseContent()
{
m_currentCaptureRequest.m_content->Update();
}
bool PreviewRenderer::StartCapture()
{
auto captureCompleteCallback = m_currentCaptureRequest.m_captureCompleteCallback;
auto captureFailedCallback = m_currentCaptureRequest.m_captureFailedCallback;
auto captureCallback = [captureCompleteCallback, captureFailedCallback](const AZ::RPI::AttachmentReadback::ReadbackResult& result)
{
if (result.m_dataBuffer)
{
if (captureCompleteCallback)
{
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)));
}
}
else
{
if (captureFailedCallback)
{
captureFailedCallback();
}
}
};
if (auto renderToTexturePass = azrtti_cast<AZ::RPI::RenderToTexturePass*>(m_renderPipeline->GetRootPass().get()))
{
renderToTexturePass->ResizeOutput(m_currentCaptureRequest.m_size, m_currentCaptureRequest.m_size);
}
m_renderPipeline->AddToRenderTickOnce();
bool startedCapture = false;
AZ::Render::FrameCaptureRequestBus::BroadcastResult(
startedCapture, &AZ::Render::FrameCaptureRequestBus::Events::CapturePassAttachmentWithCallback, m_passHierarchy,
AZStd::string("Output"), captureCallback, AZ::RPI::PassAttachmentReadbackOption::Output);
return startedCapture;
}
void PreviewRenderer::EndCapture()
{
m_currentCaptureRequest = {};
m_renderPipeline->RemoveFromRenderTick();
}
void PreviewRenderer::GetRequiredFeatureProcessors(AZStd::unordered_set<AZStd::string>& featureProcessors) const
{
featureProcessors.insert({
"AZ::Render::TransformServiceFeatureProcessor",
"AZ::Render::MeshFeatureProcessor",
"AZ::Render::SimplePointLightFeatureProcessor",
"AZ::Render::SimpleSpotLightFeatureProcessor",
"AZ::Render::PointLightFeatureProcessor",
// There is currently a bug where having multiple DirectionalLightFeatureProcessors active can result in shadow
// flickering [ATOM-13568]
// as well as continually rebuilding MeshDrawPackets [ATOM-13633]. Lets just disable the directional light FP for now.
// Possibly re-enable with [GFX TODO][ATOM-13639]
// "AZ::Render::DirectionalLightFeatureProcessor",
"AZ::Render::DiskLightFeatureProcessor",
"AZ::Render::CapsuleLightFeatureProcessor",
"AZ::Render::QuadLightFeatureProcessor",
"AZ::Render::DecalTextureArrayFeatureProcessor",
"AZ::Render::ImageBasedLightFeatureProcessor",
"AZ::Render::PostProcessFeatureProcessor",
"AZ::Render::SkyBoxFeatureProcessor" });
}
} // namespace AtomToolsFramework
@@ -0,0 +1,42 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AtomToolsFramework/PreviewRenderer/PreviewRenderer.h>
#include <PreviewRenderer/PreviewRendererCaptureState.h>
namespace AtomToolsFramework
{
PreviewRendererCaptureState::PreviewRendererCaptureState(PreviewRenderer* renderer)
: PreviewRendererState(renderer)
{
m_renderer->PoseContent();
AZ::TickBus::Handler::BusConnect();
}
PreviewRendererCaptureState::~PreviewRendererCaptureState()
{
AZ::Render::FrameCaptureNotificationBus::Handler::BusDisconnect();
AZ::TickBus::Handler::BusDisconnect();
m_renderer->EndCapture();
}
void PreviewRendererCaptureState::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
{
if ((m_ticksToCapture-- <= 0) && m_renderer->StartCapture())
{
AZ::Render::FrameCaptureNotificationBus::Handler::BusConnect();
AZ::TickBus::Handler::BusDisconnect();
}
}
void PreviewRendererCaptureState::OnCaptureFinished(
[[maybe_unused]] AZ::Render::FrameCaptureResult result, [[maybe_unused]] const AZStd::string& info)
{
m_renderer->CompleteCaptureRequest();
}
} // namespace AtomToolsFramework
@@ -0,0 +1,37 @@
/*
* 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 <Atom/Feature/Utils/FrameCaptureBus.h>
#include <AtomToolsFramework/PreviewRenderer/PreviewRendererState.h>
#include <AzCore/Component/TickBus.h>
namespace AtomToolsFramework
{
//! PreviewRendererCaptureState renders a thumbnail to a pixmap and notifies MaterialOrModelThumbnail once finished
class PreviewRendererCaptureState final
: public PreviewRendererState
, public AZ::TickBus::Handler
, public AZ::Render::FrameCaptureNotificationBus::Handler
{
public:
PreviewRendererCaptureState(PreviewRenderer* renderer);
~PreviewRendererCaptureState();
private:
//! AZ::TickBus::Handler interface overrides...
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
//! AZ::Render::FrameCaptureNotificationBus::Handler overrides...
void OnCaptureFinished(AZ::Render::FrameCaptureResult result, const AZStd::string& info) override;
//! This is necessary to suspend capture to allow a frame for Material and Mesh components to assign materials
int m_ticksToCapture = 1;
};
} // namespace AtomToolsFramework
@@ -0,0 +1,29 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AtomToolsFramework/PreviewRenderer/PreviewRenderer.h>
#include <PreviewRenderer/PreviewRendererIdleState.h>
namespace AtomToolsFramework
{
PreviewRendererIdleState::PreviewRendererIdleState(PreviewRenderer* renderer)
: PreviewRendererState(renderer)
{
AZ::TickBus::Handler::BusConnect();
}
PreviewRendererIdleState::~PreviewRendererIdleState()
{
AZ::TickBus::Handler::BusDisconnect();
}
void PreviewRendererIdleState::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
{
m_renderer->ProcessCaptureRequests();
}
} // namespace AtomToolsFramework
@@ -0,0 +1,29 @@
/*
* 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 <AtomToolsFramework/PreviewRenderer/PreviewRendererState.h>
#include <AzCore/Component/TickBus.h>
namespace AtomToolsFramework
{
//! PreviewRendererIdleState checks whether there are any new thumbnails that need to be rendered every tick
class PreviewRendererIdleState final
: public PreviewRendererState
, public AZ::TickBus::Handler
{
public:
PreviewRendererIdleState(PreviewRenderer* renderer);
~PreviewRendererIdleState();
private:
//! AZ::TickBus::Handler interface overrides...
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
};
} // namespace AtomToolsFramework
@@ -0,0 +1,36 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AtomToolsFramework/PreviewRenderer/PreviewRenderer.h>
#include <PreviewRenderer/PreviewRendererLoadState.h>
namespace AtomToolsFramework
{
PreviewRendererLoadState::PreviewRendererLoadState(PreviewRenderer* renderer)
: PreviewRendererState(renderer)
{
m_renderer->LoadContent();
AZ::TickBus::Handler::BusConnect();
}
PreviewRendererLoadState::~PreviewRendererLoadState()
{
AZ::TickBus::Handler::BusDisconnect();
}
void PreviewRendererLoadState::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
{
if ((m_timeRemainingS += deltaTime) > TimeOutS)
{
m_renderer->CancelLoadContent();
return;
}
m_renderer->UpdateLoadContent();
}
} // namespace AtomToolsFramework
@@ -0,0 +1,32 @@
/*
* 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 <AzCore/Component/TickBus.h>
#include <AtomToolsFramework/PreviewRenderer/PreviewRendererState.h>
namespace AtomToolsFramework
{
//! PreviewRendererLoadState pauses further rendering until all assets used for rendering a thumbnail have been loaded
class PreviewRendererLoadState final
: public PreviewRendererState
, public AZ::TickBus::Handler
{
public:
PreviewRendererLoadState(PreviewRenderer* renderer);
~PreviewRendererLoadState();
private:
//! AZ::TickBus::Handler interface overrides...
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
static constexpr float TimeOutS = 5.0f;
float m_timeRemainingS = 0.0f;
};
} // namespace AtomToolsFramework
@@ -58,4 +58,15 @@ set(FILES
Source/Window/AtomToolsMainWindow.cpp
Source/Window/AtomToolsMainWindowSystemComponent.cpp
Source/Window/AtomToolsMainWindowSystemComponent.h
Include/AtomToolsFramework/PreviewRenderer/PreviewContent.h
Include/AtomToolsFramework/PreviewRenderer/PreviewRenderer.h
Include/AtomToolsFramework/PreviewRenderer/PreviewRendererState.h
Include/AtomToolsFramework/PreviewRenderer/PreviewerFeatureProcessorProviderBus.h
Source/PreviewRenderer/PreviewRenderer.cpp
Source/PreviewRenderer/PreviewRendererIdleState.cpp
Source/PreviewRenderer/PreviewRendererIdleState.h
Source/PreviewRenderer/PreviewRendererLoadState.cpp
Source/PreviewRenderer/PreviewRendererLoadState.h
Source/PreviewRenderer/PreviewRendererCaptureState.cpp
Source/PreviewRenderer/PreviewRendererCaptureState.h
)
@@ -0,0 +1,34 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Atom/Feature/Material/MaterialAssignmentId.h>
#include <AzCore/Component/EntityId.h>
#include <AzCore/EBus/EBus.h>
class QPixmap;
namespace AZ
{
namespace Render
{
//! EditorMaterialSystemComponentNotifications is an interface for handling notifications from EditorMaterialSystemComponent, like
//! being informed that material preview images are available
class EditorMaterialSystemComponentNotifications : public AZ::EBusTraits
{
public:
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<EditorMaterialSystemComponentNotifications>;
} // namespace Render
} // namespace AZ
@@ -5,20 +5,22 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Atom/Feature/Material/MaterialAssignmentId.h>
#include <AzCore/Component/EntityId.h>
#include <AzCore/EBus/EBus.h>
#include <AzCore/std/string/string.h>
#include <QPixmap>
namespace AZ
{
namespace Render
{
//! EditorMaterialSystemComponentRequests provides an interface to communicate with MaterialEditor
class EditorMaterialSystemComponentRequests
: public AZ::EBusTraits
//! EditorMaterialSystemComponentRequests provides an interface for interacting with EditorMaterialSystemComponent, performing
//! different operations like opening the material editor, the material instance inspector, and managing material preview images
class EditorMaterialSystemComponentRequests : public AZ::EBusTraits
{
public:
// Only a single handler is allowed
@@ -31,6 +33,14 @@ 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;
//! Get recently rendered material preview image
virtual QPixmap GetRenderedMaterialPreview(
const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId) const = 0;
};
using EditorMaterialSystemComponentRequestBus = AZ::EBus<EditorMaterialSystemComponentRequests>;
} // namespace Render
@@ -1,33 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzCore/std/string/string.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
//! ThumbnailFeatureProcessorProviderRequests allows registering custom Feature Processors for thumbnail generation
//! Duplicates will be ignored
//! You can check minimal feature processors that are already registered in CommonThumbnailRenderer.cpp
class ThumbnailFeatureProcessorProviderRequests
: public AZ::EBusTraits
{
public:
//! Get a list of custom feature processors to register with thumbnail renderer
virtual const AZStd::vector<AZStd::string>& GetCustomFeatureProcessors() const = 0;
};
using ThumbnailFeatureProcessorProviderBus = AZ::EBus<ThumbnailFeatureProcessorProviderRequests>;
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -6,15 +6,17 @@
*
*/
#include <EditorCommonFeaturesSystemComponent.h>
#include <SkinnedMesh/SkinnedMeshDebugDisplay.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/EditContextConstants.inl>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzToolsFramework/API/EditorCameraBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
#include <EditorCommonFeaturesSystemComponent.h>
#include <SharedPreview/SharedThumbnail.h>
#include <SkinnedMesh/SkinnedMeshDebugDisplay.h>
#include <IEditor.h>
@@ -68,7 +70,7 @@ namespace AZ
void EditorCommonFeaturesSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
AZ_UNUSED(required);
required.push_back(AZ_CRC_CE("ThumbnailerService"));
}
void EditorCommonFeaturesSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
@@ -82,24 +84,23 @@ namespace AZ
void EditorCommonFeaturesSystemComponent::Activate()
{
m_renderer = AZStd::make_unique<AZ::LyIntegration::Thumbnails::CommonThumbnailRenderer>();
m_previewerFactory = AZStd::make_unique <LyIntegration::CommonPreviewerFactory>();
m_skinnedMeshDebugDisplay = AZStd::make_unique<SkinnedMeshDebugDisplay>();
AzToolsFramework::EditorLevelNotificationBus::Handler::BusConnect();
AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler::BusConnect();
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect();
}
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();
m_previewerFactory.reset();
m_renderer.reset();
TeardownThumbnails();
}
void EditorCommonFeaturesSystemComponent::OnNewLevelCreated()
@@ -191,6 +192,13 @@ namespace AZ
}
}
void EditorCommonFeaturesSystemComponent::OnCatalogLoaded([[maybe_unused]] const char* catalogFile)
{
AZ::TickBus::QueueFunction([this](){
SetupThumbnails();
});
}
const AzToolsFramework::AssetBrowser::PreviewerFactory* EditorCommonFeaturesSystemComponent::GetPreviewerFactory(
const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const
{
@@ -199,7 +207,33 @@ namespace AZ
void EditorCommonFeaturesSystemComponent::OnApplicationAboutToStop()
{
TeardownThumbnails();
}
void EditorCommonFeaturesSystemComponent::SetupThumbnails()
{
using namespace AzToolsFramework::Thumbnailer;
using namespace LyIntegration;
ThumbnailerRequestsBus::Broadcast(
&ThumbnailerRequests::RegisterThumbnailProvider, MAKE_TCACHE(SharedThumbnailCache),
ThumbnailContext::DefaultContext);
m_renderer = AZStd::make_unique<AZ::LyIntegration::SharedThumbnailRenderer>();
m_previewerFactory = AZStd::make_unique<LyIntegration::SharedPreviewerFactory>();
}
void EditorCommonFeaturesSystemComponent::TeardownThumbnails()
{
using namespace AzToolsFramework::Thumbnailer;
using namespace LyIntegration;
ThumbnailerRequestsBus::Broadcast(
&ThumbnailerRequests::UnregisterThumbnailProvider, SharedThumbnailCache::ProviderName,
ThumbnailContext::DefaultContext);
m_renderer.reset();
m_previewerFactory.reset();
}
} // namespace Render
} // namespace AZ
@@ -11,10 +11,10 @@
#include <AzCore/Component/Component.h>
#include <AzFramework/Application/Application.h>
#include <AzToolsFramework/API/EditorLevelNotificationBus.h>
#include <AzToolsFramework/Entity/SliceEditorEntityOwnershipServiceBus.h>
#include <AzToolsFramework/AssetBrowser/Previewer/PreviewerBus.h>
#include <Thumbnails/Rendering/CommonThumbnailRenderer.h>
#include <Source/Thumbnails/Preview/CommonPreviewerFactory.h>
#include <AzToolsFramework/Entity/SliceEditorEntityOwnershipServiceBus.h>
#include <SharedPreview/SharedPreviewerFactory.h>
#include <SharedPreview/SharedThumbnailRenderer.h>
namespace AZ
{
@@ -28,6 +28,7 @@ namespace AZ
, public AzToolsFramework::EditorLevelNotificationBus::Handler
, public AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler
, public AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler
, public AzFramework::AssetCatalogEventBus::Handler
, public AzFramework::ApplicationLifecycleEvents::Bus::Handler
{
public:
@@ -53,15 +54,23 @@ namespace AZ
void OnNewLevelCreated() override;
// SliceEditorEntityOwnershipServiceBus overrides ...
void OnSliceInstantiated(const AZ::Data::AssetId&, AZ::SliceComponent::SliceInstanceAddress&, const AzFramework::SliceInstantiationTicket&) override;
void OnSliceInstantiated(
const AZ::Data::AssetId&, AZ::SliceComponent::SliceInstanceAddress&, const AzFramework::SliceInstantiationTicket&) override;
void OnSliceInstantiationFailed(const AZ::Data::AssetId&, const AzFramework::SliceInstantiationTicket&) override;
// AzFramework::AssetCatalogEventBus::Handler overrides ...
void OnCatalogLoaded(const char* catalogFile) override;
// AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler overrides...
const AzToolsFramework::AssetBrowser::PreviewerFactory* GetPreviewerFactory(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const override;
const AzToolsFramework::AssetBrowser::PreviewerFactory* GetPreviewerFactory(
const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const override;
// AzFramework::ApplicationLifecycleEvents overrides...
void OnApplicationAboutToStop() override;
void SetupThumbnails();
void TeardownThumbnails();
private:
AZStd::unique_ptr<SkinnedMeshDebugDisplay> m_skinnedMeshDebugDisplay;
@@ -69,8 +78,8 @@ namespace AZ
AZStd::string m_atomLevelDefaultAssetPath{ "LevelAssets/default.slice" };
float m_envProbeHeight{ 200.0f };
AZStd::unique_ptr<AZ::LyIntegration::Thumbnails::CommonThumbnailRenderer> m_renderer;
AZStd::unique_ptr<LyIntegration::CommonPreviewerFactory> m_previewerFactory;
AZStd::unique_ptr<AZ::LyIntegration::SharedThumbnailRenderer> m_renderer;
AZStd::unique_ptr<LyIntegration::SharedPreviewerFactory> m_previewerFactory;
};
} // namespace Render
} // namespace AZ
@@ -148,11 +148,13 @@ namespace AZ
BaseClass::Activate();
MaterialReceiverNotificationBus::Handler::BusConnect(GetEntityId());
MaterialComponentNotificationBus::Handler::BusConnect(GetEntityId());
EditorMaterialSystemComponentNotificationBus::Handler::BusConnect();
UpdateMaterialSlots();
}
void EditorMaterialComponent::Deactivate()
{
EditorMaterialSystemComponentNotificationBus::Handler::BusDisconnect();
MaterialReceiverNotificationBus::Handler::BusDisconnect();
MaterialComponentNotificationBus::Handler::BusDisconnect();
BaseClass::Deactivate();
@@ -260,6 +262,18 @@ namespace AZ
}
}
void EditorMaterialComponent::OnRenderMaterialPreviewComplete(
[[maybe_unused]] const AZ::EntityId& entityId,
[[maybe_unused]] const AZ::Render::MaterialAssignmentId& materialAssignmentId,
[[maybe_unused]] const QPixmap& pixmap)
{
if (entityId == GetEntityId())
{
AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(
&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues);
}
}
AZ::u32 EditorMaterialComponent::OnConfigurationChanged()
{
return AZ::Edit::PropertyRefreshLevels::AttributesAndValues;
@@ -9,6 +9,7 @@
#pragma once
#include <Atom/Feature/Utils/EditorRenderComponentAdapter.h>
#include <AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentNotificationBus.h>
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h>
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentConstants.h>
#include <Material/EditorMaterialComponentSlot.h>
@@ -21,8 +22,9 @@ namespace AZ
//! In-editor material component for displaying and editing material assignments.
class EditorMaterialComponent final
: public EditorRenderComponentAdapter<MaterialComponentController, MaterialComponent, MaterialComponentConfig>
, private MaterialReceiverNotificationBus::Handler
, private MaterialComponentNotificationBus::Handler
, public MaterialReceiverNotificationBus::Handler
, public MaterialComponentNotificationBus::Handler
, public EditorMaterialSystemComponentNotificationBus::Handler
{
public:
using BaseClass = EditorRenderComponentAdapter<MaterialComponentController, MaterialComponent, MaterialComponentConfig>;
@@ -52,6 +54,10 @@ namespace AZ
//! MaterialComponentNotificationBus::Handler overrides...
void OnMaterialInstanceCreated(const MaterialAssignment& materialAssignment) override;
//! EditorMaterialSystemComponentNotificationBus::Handler overrides...
void OnRenderMaterialPreviewComplete(
const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId, const QPixmap& pixmap) override;
// Regenerates the editor component material slots based on the material and
// LOD mapping from the model or other consumer of materials.
// If any corresponding material assignments are found in the component
@@ -23,10 +23,6 @@
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/AssetBrowser/Thumbnails/ProductThumbnail.h>
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
#include <AzToolsFramework/Thumbnails/ThumbnailWidget.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
#include <AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h>
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h>
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentConfig.h>
@@ -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,63 @@ 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->setScaledContents(true);
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 +226,8 @@ namespace AZ
}
if (!materialTypeSourceFileInfo.fileName().isEmpty())
{
materialInfo += tr("<tr><td><b>Material Type&emsp;</b></td><td>%1</td></tr>").arg(materialTypeSourceFileInfo.fileName());
materialInfo +=
tr("<tr><td><b>Material Type&emsp;</b></td><td>%1</td></tr>").arg(materialTypeSourceFileInfo.fileName());
}
if (!materialSourceFileInfo.fileName().isEmpty())
{
@@ -234,14 +235,21 @@ namespace AZ
}
if (!materialParentSourceFileInfo.fileName().isEmpty())
{
materialInfo += tr("<tr><td><b>Material Parent&emsp;</b></td><td>%1</td></tr>").arg(materialParentSourceFileInfo.fileName());
materialInfo +=
tr("<tr><td><b>Material Parent&emsp;</b></td><td>%1</td></tr>").arg(materialParentSourceFileInfo.fileName());
}
materialInfo += tr("</table>");
materialInfoWidget->setText(materialInfo);
propertyGroupContainer->layout()->addWidget(materialInfoWidget);
m_overviewText->setText(materialInfo);
m_overviewText->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignTop);
AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupContainer);
QPixmap pixmap;
EditorMaterialSystemComponentRequestBus::BroadcastResult(
pixmap, &EditorMaterialSystemComponentRequestBus::Events::GetRenderedMaterialPreview, m_entityId,
m_materialAssignmentId);
m_overviewImage->setPixmap(pixmap);
m_overviewImage->setVisible(true);
m_updatePreview |= pixmap.isNull();
}
void MaterialPropertyInspector::AddUvNamesGroup()
@@ -282,13 +290,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 +330,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 +382,7 @@ namespace AZ
m_dirtyPropertyFlags.set();
RunEditorMaterialFunctors();
RebuildAll();
UpdateHeading();
}
void MaterialPropertyInspector::SaveOverridesToEntity(bool commitChanges)
@@ -398,6 +406,9 @@ namespace AZ
MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited);
m_internalEditNotification = false;
}
// m_updatePreview should be set to true here for continuous preview updates as slider/color properties change but needs
// throttling
}
void MaterialPropertyInspector::RunEditorMaterialFunctors()
@@ -607,7 +618,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 +714,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 +728,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,16 +784,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
//#include <AtomLyIntegration/CommonFeatures/moc_EditorMaterialComponentInspector.cpp>
@@ -9,6 +9,7 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentNotificationBus.h>
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h>
#include <AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h>
#include <AtomToolsFramework/Inspector/InspectorWidget.h>
@@ -31,14 +32,13 @@ namespace AZ
{
namespace EditorMaterialComponentInspector
{
using PropertyChangedCallback = AZStd::function<void(const MaterialPropertyOverrideMap&)>;
class MaterialPropertyInspector
: public AtomToolsFramework::InspectorWidget
, public AzToolsFramework::IPropertyEditorNotify
, public AZ::EntitySystemBus::Handler
, public AZ::TickBus::Handler
, public MaterialComponentNotificationBus::Handler
, public EditorMaterialSystemComponentNotificationBus::Handler
{
Q_OBJECT
public:
@@ -89,11 +89,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 +123,10 @@ namespace AZ
AZ::RPI::MaterialPropertyFlags m_dirtyPropertyFlags = {};
AZStd::unordered_map<AZStd::string, AtomToolsFramework::DynamicPropertyGroup> m_groups = {};
bool m_internalEditNotification = {};
QLabel* m_messageLabel = {};
bool m_updateUI = {};
bool m_updatePreview = {};
QLabel* m_overviewText = {};
QLabel* m_overviewImage = {};
};
} // namespace EditorMaterialComponentInspector
} // namespace Render
@@ -6,23 +6,25 @@
*
*/
#include <Material/EditorMaterialComponentSlot.h>
#include <Material/EditorMaterialComponentExporter.h>
#include <Material/EditorMaterialComponentInspector.h>
#include <Material/EditorMaterialModelUvNameMapInspector.h>
#include <AzCore/Asset/AssetSerializer.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
#include <AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h>
#include <AzCore/Asset/AssetSerializer.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <Material/EditorMaterialComponentExporter.h>
#include <Material/EditorMaterialComponentInspector.h>
#include <Material/EditorMaterialComponentSlot.h>
#include <Material/EditorMaterialModelUvNameMapInspector.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QMenu>
#include <QAction>
#include <QAction>
#include <QByteArray>
#include <QCursor>
#include <QDataStream>
#include <QMenu>
AZ_POP_DISABLE_WARNING
namespace AZ
@@ -100,6 +102,7 @@ namespace AZ
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &EditorMaterialComponentSlot::GetLabel)
->Attribute(AZ::Edit::Attributes::ShowProductAssetFileName, true)
->Attribute("ThumbnailCallback", &EditorMaterialComponentSlot::OpenPopupMenu)
->Attribute("ThumbnailIcon", &EditorMaterialComponentSlot::GetPreviewPixmapData)
;
}
}
@@ -118,6 +121,33 @@ namespace AZ
}
};
AZStd::vector<char> EditorMaterialComponentSlot::GetPreviewPixmapData() const
{
if (!GetActiveAssetId().IsValid())
{
return {};
}
QPixmap pixmap;
EditorMaterialSystemComponentRequestBus::BroadcastResult(
pixmap, &EditorMaterialSystemComponentRequestBus::Events::GetRenderedMaterialPreview, m_entityId, m_id);
if (pixmap.isNull())
{
if (m_updatePreview)
{
EditorMaterialSystemComponentRequestBus::Broadcast(
&EditorMaterialSystemComponentRequestBus::Events::RenderMaterialPreview, m_entityId, m_id);
m_updatePreview = false;
}
return {};
}
QByteArray pixmapBytes;
QDataStream stream(&pixmapBytes, QIODevice::WriteOnly);
stream << pixmap;
return AZStd::vector<char>(pixmapBytes.begin(), pixmapBytes.end());
}
AZ::Data::AssetId EditorMaterialComponentSlot::GetActiveAssetId() const
{
return m_materialAsset.GetId().IsValid() ? m_materialAsset.GetId() : GetDefaultAssetId();
@@ -169,14 +199,6 @@ namespace AZ
ClearOverrides();
}
void EditorMaterialComponentSlot::ClearToDefaultAsset()
{
m_materialAsset = AZ::Data::Asset<AZ::RPI::MaterialAsset>(GetDefaultAssetId(), AZ::AzTypeInfo<AZ::RPI::MaterialAsset>::Uuid());
MaterialComponentRequestBus::Event(
m_entityId, &MaterialComponentRequestBus::Events::SetMaterialOverride, m_id, m_materialAsset.GetId());
ClearOverrides();
}
void EditorMaterialComponentSlot::ClearOverrides()
{
MaterialComponentRequestBus::Event(
@@ -315,6 +337,10 @@ namespace AZ
AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast(
&AzToolsFramework::ToolsApplicationRequests::Bus::Events::AddDirtyEntity, m_entityId);
EditorMaterialSystemComponentRequestBus::Broadcast(
&EditorMaterialSystemComponentRequestBus::Events::RenderMaterialPreview, m_entityId, m_id);
m_updatePreview = false;
MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited);
AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(
@@ -8,37 +8,52 @@
#pragma once
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/Asset/AssetCommon.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <Atom/Feature/Material/MaterialAssignment.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
#include <QPixmap>
namespace AZ
{
namespace Render
{
static const size_t DefaultMaterialSlotIndex = std::numeric_limits<size_t>::max();
//! Details for a single editable material assignment
struct EditorMaterialComponentSlot final
{
AZ_RTTI(EditorMaterialComponentSlot, "{344066EB-7C3D-4E92-B53D-3C9EBD546488}");
AZ_CLASS_ALLOCATOR(EditorMaterialComponentSlot, SystemAllocator, 0);
static void Reflect(ReflectContext* context);
static bool ConvertVersion(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement);
static void Reflect(ReflectContext* context);
//! Get cached preview image as a buffer to use as an RPE attribute
//! If a cached image isn't avalible then a request will be made to render one
AZStd::vector<char> GetPreviewPixmapData() const;
//! Returns the overridden asset id if it's valid, otherwise gets the default asseet id
AZ::Data::AssetId GetActiveAssetId() const;
//! Returns the default asseet id of the material provded by the model
AZ::Data::AssetId GetDefaultAssetId() const;
//! Returns the display name of the material slot
AZStd::string GetLabel() const;
//! Returns true if the active material asset has a source material
bool HasSourceData() const;
//! Assign a new material override asset
void SetAsset(const Data::AssetId& assetId);
//! Assign a new material override asset
void SetAsset(const Data::Asset<RPI::MaterialAsset>& asset);
//! Remove material and prperty overrides
void Clear();
void ClearToDefaultAsset();
//! Remove prperty overrides
void ClearOverrides();
void OpenMaterialExporter();
@@ -54,6 +69,7 @@ namespace AZ
void OpenPopupMenu(const AZ::Data::AssetId& assetId, const AZ::Data::AssetType& assetType);
void OnMaterialChanged() const;
void OnDataChanged() const;
mutable bool m_updatePreview = true;
};
// Vector of slots for assignable or overridable material data.
@@ -62,8 +78,8 @@ namespace AZ
// Table containing all editable material data that is displayed in the edit context and inspector
// The vector represents all the LODs that can have material overrides.
// The container will be populated with every potential material slot on an associated model, using its default values.
// Whenever changes are made to this container, the modified values are copied into the controller configuration material assignment map
// as overrides that will be applied to material instances
// Whenever changes are made to this container, the modified values are copied into the controller configuration material assignment
// map as overrides that will be applied to material instances
using EditorMaterialComponentSlotsByLodContainer = AZStd::vector<EditorMaterialComponentSlotContainer>;
} // namespace Render
} // namespace AZ
@@ -6,7 +6,10 @@
*
*/
#include <AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentNotificationBus.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/EditContextConstants.inl>
@@ -16,11 +19,10 @@
#include <AzFramework/Application/Application.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/ViewPaneOptions.h>
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
#include <Editor/LyViewPaneNames.h>
#include <Material/EditorMaterialComponentInspector.h>
#include <Material/EditorMaterialSystemComponent.h>
#include <Material/MaterialThumbnail.h>
#include <SharedPreview/SharedPreviewContent.h>
// Disables warning messages triggered by the Qt library
// 4251: class needs to have dll-interface to be used by clients of class
@@ -30,6 +32,8 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option")
#include <QApplication>
#include <QDockWidget>
#include <QObject>
#include <QPixmap>
#include <QImage>
#include <QProcessEnvironment>
AZ_POP_DISABLE_WARNING
@@ -72,11 +76,6 @@ namespace AZ
incompatible.push_back(AZ_CRC("EditorMaterialSystem", 0x5c93bc4e));
}
void EditorMaterialSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
required.push_back(AZ_CRC("ThumbnailerService", 0x65422b97));
}
void EditorMaterialSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
{
AZ_UNUSED(dependent);
@@ -89,25 +88,26 @@ namespace AZ
void EditorMaterialSystemComponent::Activate()
{
EditorMaterialSystemComponentNotificationBus::Handler::BusConnect();
EditorMaterialSystemComponentRequestBus::Handler::BusConnect();
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect();
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect();
AzToolsFramework::EditorMenuNotificationBus::Handler::BusConnect();
AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
SetupThumbnails();
m_materialBrowserInteractions.reset(aznew MaterialBrowserInteractions);
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect();
}
void EditorMaterialSystemComponent::Deactivate()
{
EditorMaterialSystemComponentRequestBus::Handler::BusDisconnect();
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect();
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
EditorMaterialSystemComponentNotificationBus::Handler::BusDisconnect();
EditorMaterialSystemComponentRequestBus::Handler::BusDisconnect();
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect();
AzToolsFramework::EditorMenuNotificationBus::Handler::BusDisconnect();
AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
TeardownThumbnails();
m_previewRenderer.reset();
m_materialBrowserInteractions.reset();
if (m_openMaterialEditorAction)
@@ -154,11 +154,74 @@ namespace AZ
}
}
void EditorMaterialSystemComponent::OnApplicationAboutToStop()
void EditorMaterialSystemComponent::RenderMaterialPreview(
const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId)
{
TeardownThumbnails();
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);
if (!materialAssetId.IsValid())
{
return;
}
}
AZ::Render::MaterialPropertyOverrideMap propertyOverrides;
AZ::Render::MaterialComponentRequestBus::EventResult(
propertyOverrides, entityId, &AZ::Render::MaterialComponentRequestBus::Events::GetPropertyOverrides,
materialAssignmentId);
m_previewRenderer->AddCaptureRequest(
{ 128,
AZStd::make_shared<AZ::LyIntegration::SharedPreviewContent>(
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);
} });
}
}
QPixmap EditorMaterialSystemComponent::GetRenderedMaterialPreview(
const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId) const
{
const auto& itr1 = m_materialPreviews.find(entityId);
if (itr1 != m_materialPreviews.end())
{
const auto& itr2 = itr1->second.find(materialAssignmentId);
if (itr2 != itr1->second.end())
{
return itr2->second;
}
}
return QPixmap();
}
void EditorMaterialSystemComponent::OnRenderMaterialPreviewComplete(
[[maybe_unused]] const AZ::EntityId& entityId,
[[maybe_unused]] const AZ::Render::MaterialAssignmentId& materialAssignmentId,
[[maybe_unused]] const QPixmap& pixmap)
{
m_materialPreviews[entityId][materialAssignmentId] = pixmap;
}
void EditorMaterialSystemComponent::OnPopulateToolMenuItems()
{
if (!m_openMaterialEditorAction)
@@ -201,24 +264,19 @@ namespace AZ
"Material Property Inspector", LyViewPane::CategoryTools, inspectorOptions);
}
void EditorMaterialSystemComponent::SetupThumbnails()
void EditorMaterialSystemComponent::OnCatalogLoaded([[maybe_unused]] const char* catalogFile)
{
using namespace AzToolsFramework::Thumbnailer;
using namespace LyIntegration;
ThumbnailerRequestsBus::Broadcast(
&ThumbnailerRequests::RegisterThumbnailProvider, MAKE_TCACHE(Thumbnails::MaterialThumbnailCache),
ThumbnailContext::DefaultContext);
AZ::TickBus::QueueFunction([this](){
m_materialBrowserInteractions.reset(aznew MaterialBrowserInteractions);
m_previewRenderer.reset(aznew AtomToolsFramework::PreviewRenderer(
"EditorMaterialSystemComponent Preview Scene", "EditorMaterialSystemComponent Preview Pipeline"));
});
}
void EditorMaterialSystemComponent::TeardownThumbnails()
void EditorMaterialSystemComponent::OnApplicationAboutToStop()
{
using namespace AzToolsFramework::Thumbnailer;
using namespace LyIntegration;
ThumbnailerRequestsBus::Broadcast(
&ThumbnailerRequests::UnregisterThumbnailProvider, Thumbnails::MaterialThumbnailCache::ProviderName,
ThumbnailContext::DefaultContext);
m_previewRenderer.reset();
m_materialBrowserInteractions.reset();
}
AzToolsFramework::AssetBrowser::SourceFileDetails EditorMaterialSystemComponent::GetSourceFileDetails(
@@ -7,29 +7,31 @@
*/
#pragma once
#include <AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h>
#include <AtomToolsFramework/PreviewRenderer/PreviewRenderer.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Component/Component.h>
#include <AzFramework/Application/Application.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
#include <AzToolsFramework/Viewport/ActionBus.h>
#include <AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h>
#include <Material/MaterialBrowserInteractions.h>
#include <QPixmap>
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 AzFramework::ApplicationLifecycleEvents::Bus::Handler
, private AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler
, private AzToolsFramework::EditorMenuNotificationBus::Handler
, private AzToolsFramework::EditorEvents::Bus::Handler
, public EditorMaterialSystemComponentNotificationBus::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}");
@@ -38,7 +40,6 @@ namespace AZ
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
protected:
@@ -51,9 +52,13 @@ 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;
QPixmap GetRenderedMaterialPreview(
const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId) const override;
// AzFramework::ApplicationLifecycleEvents overrides...
void OnApplicationAboutToStop() override;
//! EditorMaterialSystemComponentNotificationBus::Handler overrides...
void OnRenderMaterialPreviewComplete(
const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId, const QPixmap& pixmap)override;
//! AssetBrowserInteractionNotificationBus::Handler overrides...
AzToolsFramework::AssetBrowser::SourceFileDetails GetSourceFileDetails(const char* fullSourceFileName) override;
@@ -65,12 +70,17 @@ namespace AZ
// AztoolsFramework::EditorEvents::Bus::Handler overrides...
void NotifyRegisterViews() override;
void SetupThumbnails();
void TeardownThumbnails();
// AzFramework::AssetCatalogEventBus::Handler overrides ...
void OnCatalogLoaded(const char* catalogFile) override;
// AzFramework::ApplicationLifecycleEvents overrides...
void OnApplicationAboutToStop() override;
QAction* m_openMaterialEditorAction = nullptr;
AZStd::unique_ptr<MaterialBrowserInteractions> m_materialBrowserInteractions;
AZStd::unique_ptr<AtomToolsFramework::PreviewRenderer> m_previewRenderer;
AZStd::unordered_map<AZ::EntityId, AZStd::unordered_map<AZ::Render::MaterialAssignmentId, QPixmap>> m_materialPreviews;
};
} // namespace Render
} // namespace AZ
@@ -1,112 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <QtConcurrent/QtConcurrent>
#include <Source/Material/MaterialThumbnail.h>
#include <Source/Thumbnails/ThumbnailUtils.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
static constexpr const int MaterialThumbnailSize = 512; // 512 is the default size in render to texture pass
//////////////////////////////////////////////////////////////////////////
// MaterialThumbnail
//////////////////////////////////////////////////////////////////////////
MaterialThumbnail::MaterialThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key)
: Thumbnail(key)
{
m_assetId = GetAssetId(key, RPI::MaterialAsset::RTTI_Type());
if (!m_assetId.IsValid())
{
AZ_Error("MaterialThumbnail", false, "Failed to find matching assetId for the thumbnailKey.");
m_state = State::Failed;
return;
}
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler::BusConnect(key);
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
}
void MaterialThumbnail::LoadThread()
{
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::QueueEvent(
RPI::MaterialAsset::RTTI_Type(),
&AzToolsFramework::Thumbnailer::ThumbnailerRendererRequests::RenderThumbnail,
m_key,
MaterialThumbnailSize);
// wait for response from thumbnail renderer
m_renderWait.acquire();
}
MaterialThumbnail::~MaterialThumbnail()
{
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler::BusDisconnect();
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
}
void MaterialThumbnail::ThumbnailRendered(const QPixmap& thumbnailImage)
{
m_pixmap = thumbnailImage;
m_renderWait.release();
}
void MaterialThumbnail::ThumbnailFailedToRender()
{
m_state = State::Failed;
m_renderWait.release();
}
void MaterialThumbnail::OnCatalogAssetChanged([[maybe_unused]] const AZ::Data::AssetId& assetId)
{
if (m_assetId == assetId &&
m_state == State::Ready)
{
m_state = State::Unloaded;
Load();
}
}
//////////////////////////////////////////////////////////////////////////
// MaterialThumbnailCache
//////////////////////////////////////////////////////////////////////////
MaterialThumbnailCache::MaterialThumbnailCache()
: ThumbnailCache<MaterialThumbnail>()
{
}
MaterialThumbnailCache::~MaterialThumbnailCache() = default;
int MaterialThumbnailCache::GetPriority() const
{
// Material thumbnails override default source thumbnails, so carry higher priority
return 1;
}
const char* MaterialThumbnailCache::GetProviderName() const
{
return ProviderName;
}
bool MaterialThumbnailCache::IsSupportedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key) const
{
return
GetAssetId(key, RPI::MaterialAsset::RTTI_Type()).IsValid() &&
// in case it's a source scene file, it will contain both material and model products
// model thumbnails are handled by MeshThumbnail
!GetAssetId(key, RPI::ModelAsset::RTTI_Type()).IsValid();
}
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
#include <Material/moc_MaterialThumbnail.cpp>
@@ -1,73 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/std/parallel/binary_semaphore.h>
#include <AzFramework/Asset/AssetCatalogBus.h>
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
#include <Thumbnails/Rendering/CommonThumbnailRenderer.h>
#endif
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
/**
* Custom material or model thumbnail that detects when an asset changes and updates the thumbnail
*/
class MaterialThumbnail
: public AzToolsFramework::Thumbnailer::Thumbnail
, public AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler
, private AzFramework::AssetCatalogEventBus::Handler
{
Q_OBJECT
public:
MaterialThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key);
~MaterialThumbnail() override;
//! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides...
void ThumbnailRendered(const QPixmap& thumbnailImage) override;
void ThumbnailFailedToRender() override;
protected:
void LoadThread() override;
private:
// AzFramework::AssetCatalogEventBus::Handler interface overrides...
void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override;
AZStd::binary_semaphore m_renderWait;
Data::AssetId m_assetId;
};
/**
* Cache configuration for large material thumbnails
*/
class MaterialThumbnailCache
: public AzToolsFramework::Thumbnailer::ThumbnailCache<MaterialThumbnail>
{
public:
MaterialThumbnailCache();
~MaterialThumbnailCache() override;
int GetPriority() const override;
const char* GetProviderName() const override;
static constexpr const char* ProviderName = "Material Thumbnails";
protected:
bool IsSupportedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key) const override;
};
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -6,13 +6,10 @@
*
*/
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/EditContextConstants.inl>
#include <AzCore/Utils/Utils.h>
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
#include <Source/Mesh/EditorMeshSystemComponent.h>
#include <Source/Mesh/MeshThumbnail.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <Mesh/EditorMeshSystemComponent.h>
namespace AZ
{
@@ -47,11 +44,6 @@ namespace AZ
incompatible.push_back(AZ_CRC_CE("EditorMeshSystem"));
}
void EditorMeshSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
required.push_back(AZ_CRC_CE("ThumbnailerService"));
}
void EditorMeshSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
{
AZ_UNUSED(dependent);
@@ -59,39 +51,10 @@ namespace AZ
void EditorMeshSystemComponent::Activate()
{
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect();
SetupThumbnails();
}
void EditorMeshSystemComponent::Deactivate()
{
TeardownThumbnails();
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect();
}
void EditorMeshSystemComponent::OnApplicationAboutToStop()
{
TeardownThumbnails();
}
void EditorMeshSystemComponent::SetupThumbnails()
{
using namespace AzToolsFramework::Thumbnailer;
using namespace LyIntegration;
ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterThumbnailProvider,
MAKE_TCACHE(Thumbnails::MeshThumbnailCache),
ThumbnailContext::DefaultContext);
}
void EditorMeshSystemComponent::TeardownThumbnails()
{
using namespace AzToolsFramework::Thumbnailer;
using namespace LyIntegration;
ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::UnregisterThumbnailProvider,
Thumbnails::MeshThumbnailCache::ProviderName,
ThumbnailContext::DefaultContext);
}
} // namespace Render
} // namespace AZ
@@ -8,7 +8,6 @@
#pragma once
#include <AzCore/Component/Component.h>
#include <AzFramework/Application/Application.h>
namespace AZ
{
@@ -17,7 +16,6 @@ namespace AZ
//! System component that sets up necessary logic related to EditorMeshComponent.
class EditorMeshSystemComponent
: public AZ::Component
, private AzFramework::ApplicationLifecycleEvents::Bus::Handler
{
public:
AZ_COMPONENT(EditorMeshSystemComponent, "{4D332E3D-C4FC-410B-A915-8E234CBDD4EC}");
@@ -26,20 +24,12 @@ namespace AZ
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
protected:
// AZ::Component interface overrides...
void Activate() override;
void Deactivate() override;
private:
// AzFramework::ApplicationLifecycleEvents overrides...
void OnApplicationAboutToStop() override;
void SetupThumbnails();
void TeardownThumbnails();
};
} // namespace Render
} // namespace AZ
@@ -1,109 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
#include <QtConcurrent/QtConcurrent>
#include <Source/Mesh/MeshThumbnail.h>
#include <Source/Thumbnails/ThumbnailUtils.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
static constexpr const int MeshThumbnailSize = 512; // 512 is the default size in render to texture pass
//////////////////////////////////////////////////////////////////////////
// MeshThumbnail
//////////////////////////////////////////////////////////////////////////
MeshThumbnail::MeshThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key)
: Thumbnail(key)
{
m_assetId = GetAssetId(key, RPI::ModelAsset::RTTI_Type());
if (!m_assetId.IsValid())
{
AZ_Error("MeshThumbnail", false, "Failed to find matching assetId for the thumbnailKey.");
m_state = State::Failed;
return;
}
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler::BusConnect(key);
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
}
void MeshThumbnail::LoadThread()
{
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::QueueEvent(
RPI::ModelAsset::RTTI_Type(),
&AzToolsFramework::Thumbnailer::ThumbnailerRendererRequests::RenderThumbnail,
m_key,
MeshThumbnailSize);
// wait for response from thumbnail renderer
m_renderWait.acquire();
}
MeshThumbnail::~MeshThumbnail()
{
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler::BusDisconnect();
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
}
void MeshThumbnail::ThumbnailRendered(const QPixmap& thumbnailImage)
{
m_pixmap = thumbnailImage;
m_renderWait.release();
}
void MeshThumbnail::ThumbnailFailedToRender()
{
m_state = State::Failed;
m_renderWait.release();
}
void MeshThumbnail::OnCatalogAssetChanged([[maybe_unused]] const AZ::Data::AssetId& assetId)
{
if (m_assetId == assetId &&
m_state == State::Ready)
{
m_state = State::Unloaded;
Load();
}
}
//////////////////////////////////////////////////////////////////////////
// MeshThumbnailCache
//////////////////////////////////////////////////////////////////////////
MeshThumbnailCache::MeshThumbnailCache()
: ThumbnailCache<MeshThumbnail>()
{
}
MeshThumbnailCache::~MeshThumbnailCache() = default;
int MeshThumbnailCache::GetPriority() const
{
// Material thumbnails override default source thumbnails, so carry higher priority
return 1;
}
const char* MeshThumbnailCache::GetProviderName() const
{
return ProviderName;
}
bool MeshThumbnailCache::IsSupportedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key) const
{
return GetAssetId(key, RPI::ModelAsset::RTTI_Type()).IsValid();
}
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
#include <Mesh/moc_MeshThumbnail.cpp>
@@ -1,72 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/std/parallel/binary_semaphore.h>
#include <AzFramework/Asset/AssetCatalogBus.h>
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
#endif
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
/**
* Custom material or model thumbnail that detects when an asset changes and updates the thumbnail
*/
class MeshThumbnail
: public AzToolsFramework::Thumbnailer::Thumbnail
, public AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler
, private AzFramework::AssetCatalogEventBus::Handler
{
Q_OBJECT
public:
MeshThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key);
~MeshThumbnail() override;
//! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides...
void ThumbnailRendered(const QPixmap& thumbnailImage) override;
void ThumbnailFailedToRender() override;
protected:
void LoadThread() override;
private:
// AzFramework::AssetCatalogEventBus::Handler interface overrides...
void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override;
AZStd::binary_semaphore m_renderWait;
Data::AssetId m_assetId;
};
/**
* Cache configuration for large material thumbnails
*/
class MeshThumbnailCache
: public AzToolsFramework::Thumbnailer::ThumbnailCache<MeshThumbnail>
{
public:
MeshThumbnailCache();
~MeshThumbnailCache() override;
int GetPriority() const override;
const char* GetProviderName() const override;
static constexpr const char* ProviderName = "Mesh Thumbnails";
protected:
bool IsSupportedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key) const override;
};
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -0,0 +1,173 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Atom/Feature/ImageBasedLights/ImageBasedLightFeatureProcessorInterface.h>
#include <Atom/Feature/PostProcess/PostProcessFeatureProcessorInterface.h>
#include <Atom/Feature/SkyBox/SkyBoxFeatureProcessorInterface.h>
#include <Atom/Feature/Utils/LightingPreset.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h>
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentConstants.h>
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h>
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentConstants.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/MatrixUtils.h>
#include <AzCore/Math/Transform.h>
#include <AzFramework/Components/TransformComponent.h>
#include <AzFramework/Entity/EntityContextBus.h>
#include <SharedPreview/SharedPreviewContent.h>
namespace AZ
{
namespace LyIntegration
{
SharedPreviewContent::SharedPreviewContent(
RPI::ScenePtr scene,
RPI::ViewPtr view,
AZ::Uuid entityContextId,
const Data::AssetId& modelAssetId,
const Data::AssetId& materialAssetId,
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(
m_modelEntity, m_entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "SharedPreviewContentModel");
m_modelEntity->CreateComponent(Render::MeshComponentTypeId);
m_modelEntity->CreateComponent(Render::MaterialComponentTypeId);
m_modelEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
m_modelEntity->Init();
m_modelEntity->Activate();
m_modelAsset.Create(modelAssetId);
m_materialAsset.Create(materialAssetId);
m_lightingPresetAsset.Create(lightingPresetAssetId);
}
SharedPreviewContent::~SharedPreviewContent()
{
if (m_modelEntity)
{
m_modelEntity->Deactivate();
AzFramework::EntityContextRequestBus::Event(
m_entityContextId, &AzFramework::EntityContextRequestBus::Events::DestroyEntity, m_modelEntity);
m_modelEntity = nullptr;
}
}
void SharedPreviewContent::Load()
{
m_modelAsset.QueueLoad();
m_materialAsset.QueueLoad();
m_lightingPresetAsset.QueueLoad();
}
bool SharedPreviewContent::IsReady() const
{
return (!m_modelAsset.GetId().IsValid() || m_modelAsset.IsReady()) &&
(!m_materialAsset.GetId().IsValid() || m_materialAsset.IsReady()) &&
(!m_lightingPresetAsset.GetId().IsValid() || m_lightingPresetAsset.IsReady());
}
bool SharedPreviewContent::IsError() const
{
return m_modelAsset.IsError() || m_materialAsset.IsError() || m_lightingPresetAsset.IsError();
}
void SharedPreviewContent::ReportErrors()
{
AZ_Warning(
"SharedPreviewContent", !m_modelAsset.GetId().IsValid() || m_modelAsset.IsReady(), "Asset failed to load in time: %s",
m_modelAsset.ToString<AZStd::string>().c_str());
AZ_Warning(
"SharedPreviewContent", !m_materialAsset.GetId().IsValid() || m_materialAsset.IsReady(), "Asset failed to load in time: %s",
m_materialAsset.ToString<AZStd::string>().c_str());
AZ_Warning(
"SharedPreviewContent", !m_lightingPresetAsset.GetId().IsValid() || m_lightingPresetAsset.IsReady(),
"Asset failed to load in time: %s", m_lightingPresetAsset.ToString<AZStd::string>().c_str());
}
void SharedPreviewContent::Update()
{
UpdateModel();
UpdateLighting();
UpdateCamera();
}
void SharedPreviewContent::UpdateModel()
{
Render::MeshComponentRequestBus::Event(
m_modelEntity->GetId(), &Render::MeshComponentRequestBus::Events::SetModelAsset, m_modelAsset);
Render::MaterialComponentRequestBus::Event(
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 SharedPreviewContent::UpdateLighting()
{
if (m_lightingPresetAsset.IsReady())
{
auto preset = m_lightingPresetAsset->GetDataAs<Render::LightingPreset>();
if (preset)
{
auto iblFeatureProcessor = m_scene->GetFeatureProcessor<Render::ImageBasedLightFeatureProcessorInterface>();
auto postProcessFeatureProcessor = m_scene->GetFeatureProcessor<Render::PostProcessFeatureProcessorInterface>();
auto postProcessSettingInterface = postProcessFeatureProcessor->GetOrCreateSettingsInterface(EntityId());
auto exposureControlSettingInterface = postProcessSettingInterface->GetOrCreateExposureControlSettingsInterface();
auto directionalLightFeatureProcessor =
m_scene->GetFeatureProcessor<Render::DirectionalLightFeatureProcessorInterface>();
auto skyboxFeatureProcessor = m_scene->GetFeatureProcessor<Render::SkyBoxFeatureProcessorInterface>();
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;
AZStd::vector<Render::DirectionalLightFeatureProcessorInterface::LightHandle> lightHandles;
preset->ApplyLightingPreset(
iblFeatureProcessor, skyboxFeatureProcessor, exposureControlSettingInterface, directionalLightFeatureProcessor,
cameraConfig, lightHandles);
}
}
}
void SharedPreviewContent::UpdateCamera()
{
// Get bounding sphere of the model asset and estimate how far the camera needs to be see all of it
Vector3 center = {};
float radius = {};
if (m_modelAsset.IsReady())
{
m_modelAsset->GetAabb().GetAsSphere(center, radius);
}
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::CreateLookAt(cameraPosition, center);
m_view->SetCameraTransform(Matrix3x4::CreateFromTransform(cameraTransform));
}
} // namespace LyIntegration
} // namespace AZ
@@ -0,0 +1,67 @@
/*
* 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 <Atom/Feature/Material/MaterialAssignment.h>
#include <Atom/RPI.Public/Base.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
#include <Atom/RPI.Reflect/System/AnyAsset.h>
#include <AtomToolsFramework/PreviewRenderer/PreviewContent.h>
namespace AZ
{
namespace LyIntegration
{
//! Creates a simple scene used for most previews and thumbnails
class SharedPreviewContent final : public AtomToolsFramework::PreviewContent
{
public:
AZ_CLASS_ALLOCATOR(SharedPreviewContent, AZ::SystemAllocator, 0);
SharedPreviewContent(
RPI::ScenePtr scene,
RPI::ViewPtr view,
AZ::Uuid entityContextId,
const Data::AssetId& modelAssetId,
const Data::AssetId& materialAssetId,
const Data::AssetId& lightingPresetAssetId,
const Render::MaterialPropertyOverrideMap& materialPropertyOverrides);
~SharedPreviewContent() override;
void Load() override;
bool IsReady() const override;
bool IsError() const override;
void ReportErrors() override;
void Update() override;
private:
void UpdateModel();
void UpdateLighting();
void UpdateCamera();
static constexpr float AspectRatio = 1.0f;
static constexpr float NearDist = 0.001f;
static constexpr float FarDist = 100.0f;
static constexpr float FieldOfView = Constants::HalfPi;
static constexpr float CameraRotationAngle = Constants::QuarterPi / 2.0f;
RPI::ScenePtr m_scene;
RPI::ViewPtr m_view;
AZ::Uuid m_entityContextId;
Entity* m_modelEntity = nullptr;
Data::Asset<RPI::ModelAsset> m_modelAsset;
Data::Asset<RPI::MaterialAsset> m_materialAsset;
Data::Asset<RPI::AnyAsset> m_lightingPresetAsset;
Render::MaterialPropertyOverrideMap m_materialPropertyOverrides;
};
} // namespace LyIntegration
} // namespace AZ
@@ -11,37 +11,42 @@
#include <AssetBrowser/Thumbnails/SourceThumbnail.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
#include <Thumbnails/ThumbnailUtils.h>
#include <Atom/RPI.Reflect/System/AnyAsset.h>
#include <SharedPreview/SharedPreviewUtils.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
namespace SharedPreviewUtils
{
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<const AzToolsFramework::AssetBrowser::SourceThumbnailKey*>(key.data());
if (sourceKey)
{
bool foundIt = false;
AZStd::vector<Data::AssetInfo> productsAssetInfo;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(foundIt, &AzToolsFramework::AssetSystemRequestBus::Events::GetAssetsProducedBySourceUUID, sourceKey->GetSourceUuid(), productsAssetInfo);
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(),
auto assetInfoIt = AZStd::find_if(
productsAssetInfo.begin(), productsAssetInfo.end(),
[&assetType](const Data::AssetInfo& assetInfo)
{
return assetInfo.m_assetType == assetType;
});
if (assetInfoIt == productsAssetInfo.end())
{
return invalidAssetId;
return defaultAssetId;
}
return assetInfoIt->m_assetId;
@@ -53,10 +58,9 @@ namespace AZ
{
return productKey->GetAssetId();
}
return invalidAssetId;
return defaultAssetId;
}
QString WordWrap(const QString& string, int maxLength)
{
QString result;
@@ -81,6 +85,32 @@ namespace AZ
}
return result;
}
} // namespace Thumbnails
AZStd::unordered_set<AZ::Uuid> GetSupportedAssetTypes()
{
return { RPI::AnyAsset::RTTI_Type(), RPI::MaterialAsset::RTTI_Type(), RPI::ModelAsset::RTTI_Type() };
}
bool IsSupportedAssetType(AzToolsFramework::Thumbnailer::SharedThumbnailKey key)
{
for (const AZ::Uuid& typeId : SharedPreviewUtils::GetSupportedAssetTypes())
{
const AZ::Data::AssetId& assetId = SharedPreviewUtils::GetAssetId(key, typeId);
if (assetId.IsValid())
{
if (typeId == RPI::AnyAsset::RTTI_Type())
{
AZ::Data::AssetInfo assetInfo;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, assetId);
return AzFramework::StringFunc::EndsWith(assetInfo.m_relativePath.c_str(), "lightingpreset.azasset");
}
return true;
}
}
return false;
}
} // namespace SharedPreviewUtils
} // namespace LyIntegration
} // namespace AZ
@@ -18,13 +18,23 @@ namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
namespace SharedPreviewUtils
{
//! 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
//! 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);
} // namespace Thumbnails
//! Get the set of all asset types supported by the shared preview
AZStd::unordered_set<AZ::Uuid> GetSupportedAssetTypes();
//! Determine if a thumbnail key has an asset supported by the shared preview
bool IsSupportedAssetType(AzToolsFramework::Thumbnailer::SharedThumbnailKey key);
} // namespace SharedPreviewUtils
} // namespace LyIntegration
} // namespace AZ
@@ -7,23 +7,21 @@
*/
#include <AzCore/IO/FileIO.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
#include <Source/Thumbnails/Preview/CommonPreviewer.h>
#include <Source/Thumbnails/ThumbnailUtils.h>
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
#include <SharedPreview/SharedPreviewUtils.h>
#include <SharedPreview/SharedPreviewer.h>
// Disables warning messages triggered by the Qt library
// 4251: class needs to have dll-interface to be used by clients of class
// 4251: class needs to have dll-interface to be used by clients of class
// 4800: forcing value to bool 'true' or 'false' (performance warning)
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option")
#include <Source/Thumbnails/Preview/ui_CommonPreviewer.h>
#include <QString>
#include <QResizeEvent>
#include <QString>
#include <SharedPreview/ui_SharedPreviewer.h>
AZ_POP_DISABLE_WARNING
namespace AZ
@@ -32,18 +30,22 @@ namespace AZ
{
static constexpr int CharWidth = 6;
CommonPreviewer::CommonPreviewer(QWidget* parent)
SharedPreviewer::SharedPreviewer(QWidget* parent)
: Previewer(parent)
, m_ui(new Ui::CommonPreviewerClass())
, m_ui(new Ui::SharedPreviewerClass())
{
m_ui->setupUi(this);
}
CommonPreviewer::~CommonPreviewer()
SharedPreviewer::~SharedPreviewer()
{
}
void CommonPreviewer::Display(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
void SharedPreviewer::Clear() const
{
}
void SharedPreviewer::Display(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
{
using namespace AzToolsFramework::AssetBrowser;
using namespace AzToolsFramework::Thumbnailer;
@@ -54,23 +56,23 @@ namespace AZ
UpdateFileInfo();
}
const QString& CommonPreviewer::GetName() const
const QString& SharedPreviewer::GetName() const
{
return m_name;
}
void CommonPreviewer::resizeEvent([[maybe_unused]] QResizeEvent* event)
void SharedPreviewer::resizeEvent([[maybe_unused]] QResizeEvent* event)
{
m_ui->m_previewWidget->setMaximumHeight(m_ui->m_previewWidget->width());
UpdateFileInfo();
}
void CommonPreviewer::UpdateFileInfo() const
void SharedPreviewer::UpdateFileInfo() const
{
m_ui->m_fileInfoLabel->setText(Thumbnails::WordWrap(m_fileInfo, m_ui->m_fileInfoLabel->width() / CharWidth));
m_ui->m_fileInfoLabel->setText(SharedPreviewUtils::WordWrap(m_fileInfo, m_ui->m_fileInfoLabel->width() / CharWidth));
}
} // namespace LyIntegration
} // namespace AZ
#include <Source/Thumbnails/Preview/moc_CommonPreviewer.cpp>
#include <SharedPreview/moc_SharedPreviewer.cpp>
@@ -5,22 +5,23 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzToolsFramework/AssetBrowser/Previewer/Previewer.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QWidget>
#include <QScopedPointer>
#include <QWidget>
AZ_POP_DISABLE_WARNING
#endif
namespace Ui
{
class CommonPreviewerClass;
class SharedPreviewerClass;
}
namespace AzToolsFramework
@@ -30,8 +31,8 @@ namespace AzToolsFramework
class ProductAssetBrowserEntry;
class SourceAssetBrowserEntry;
class AssetBrowserEntry;
}
}
} // namespace AssetBrowser
} // namespace AzToolsFramework
class QResizeEvent;
@@ -39,18 +40,17 @@ namespace AZ
{
namespace LyIntegration
{
class CommonPreviewer final
: public AzToolsFramework::AssetBrowser::Previewer
class SharedPreviewer final : public AzToolsFramework::AssetBrowser::Previewer
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(CommonPreviewer, AZ::SystemAllocator, 0);
AZ_CLASS_ALLOCATOR(SharedPreviewer, AZ::SystemAllocator, 0);
explicit CommonPreviewer(QWidget* parent = nullptr);
~CommonPreviewer();
explicit SharedPreviewer(QWidget* parent = nullptr);
~SharedPreviewer();
// AzToolsFramework::AssetBrowser::Previewer overrides...
void Clear() const override {}
void Clear() const override;
void Display(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) override;
const QString& GetName() const override;
@@ -60,9 +60,9 @@ namespace AZ
private:
void UpdateFileInfo() const;
QScopedPointer<Ui::CommonPreviewerClass> m_ui;
QScopedPointer<Ui::SharedPreviewerClass> m_ui;
QString m_fileInfo;
QString m_name = "CommonPreviewer";
QString m_name = "SharedPreviewer";
};
} // namespace LyIntegration
} // namespace AZ
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CommonPreviewerClass</class>
<widget class="QWidget" name="CommonPreviewerClass">
<class>SharedPreviewerClass</class>
<widget class="QWidget" name="SharedPreviewerClass">
<property name="geometry">
<rect>
<x>0</x>
@@ -0,0 +1,33 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <SharedPreview/SharedPreviewUtils.h>
#include <SharedPreview/SharedPreviewer.h>
#include <SharedPreview/SharedPreviewerFactory.h>
namespace AZ
{
namespace LyIntegration
{
AzToolsFramework::AssetBrowser::Previewer* SharedPreviewerFactory::CreatePreviewer(QWidget* parent) const
{
return new SharedPreviewer(parent);
}
bool SharedPreviewerFactory::IsEntrySupported(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const
{
return SharedPreviewUtils::IsSupportedAssetType(entry->GetThumbnailKey());
}
const QString& SharedPreviewerFactory::GetName() const
{
return m_name;
}
} // namespace LyIntegration
} // namespace AZ
@@ -5,6 +5,7 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Memory/SystemAllocator.h>
@@ -18,14 +19,13 @@ namespace AZ
{
namespace LyIntegration
{
class CommonPreviewerFactory final
: public AzToolsFramework::AssetBrowser::PreviewerFactory
class SharedPreviewerFactory final : public AzToolsFramework::AssetBrowser::PreviewerFactory
{
public:
AZ_CLASS_ALLOCATOR(CommonPreviewerFactory, AZ::SystemAllocator, 0);
AZ_CLASS_ALLOCATOR(SharedPreviewerFactory, AZ::SystemAllocator, 0);
CommonPreviewerFactory() = default;
~CommonPreviewerFactory() = default;
SharedPreviewerFactory() = default;
~SharedPreviewerFactory() = default;
// AzToolsFramework::AssetBrowser::PreviewerFactory overrides...
AzToolsFramework::AssetBrowser::Previewer* CreatePreviewer(QWidget* parent = nullptr) const override;
@@ -33,7 +33,7 @@ namespace AZ
const QString& GetName() const override;
private:
QString m_name = "CommonPreviewer";
QString m_name = "SharedPreviewer";
};
} // namespace LyIntegration
} // namespace AZ
@@ -0,0 +1,106 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <QtConcurrent/QtConcurrent>
#include <SharedPreview/SharedPreviewUtils.h>
#include <SharedPreview/SharedThumbnail.h>
namespace AZ
{
namespace LyIntegration
{
static constexpr const int SharedThumbnailSize = 256;
//////////////////////////////////////////////////////////////////////////
// SharedThumbnail
//////////////////////////////////////////////////////////////////////////
SharedThumbnail::SharedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key)
: Thumbnail(key)
{
for (const AZ::Uuid& typeId : SharedPreviewUtils::GetSupportedAssetTypes())
{
const AZ::Data::AssetId& assetId = SharedPreviewUtils::GetAssetId(key, typeId);
if (assetId.IsValid())
{
m_assetId = assetId;
m_typeId = typeId;
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler::BusConnect(key);
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
return;
}
}
AZ_Error("SharedThumbnail", false, "Failed to find matching assetId for the thumbnailKey.");
m_state = State::Failed;
}
void SharedThumbnail::LoadThread()
{
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::QueueEvent(
m_typeId, &AzToolsFramework::Thumbnailer::ThumbnailerRendererRequests::RenderThumbnail, m_key, SharedThumbnailSize);
// wait for response from thumbnail renderer
m_renderWait.acquire();
}
SharedThumbnail::~SharedThumbnail()
{
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler::BusDisconnect();
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
}
void SharedThumbnail::ThumbnailRendered(const QPixmap& thumbnailImage)
{
m_pixmap = thumbnailImage;
m_renderWait.release();
}
void SharedThumbnail::ThumbnailFailedToRender()
{
m_state = State::Failed;
m_renderWait.release();
}
void SharedThumbnail::OnCatalogAssetChanged([[maybe_unused]] const AZ::Data::AssetId& assetId)
{
if (m_assetId == assetId && m_state == State::Ready)
{
m_state = State::Unloaded;
Load();
}
}
//////////////////////////////////////////////////////////////////////////
// SharedThumbnailCache
//////////////////////////////////////////////////////////////////////////
SharedThumbnailCache::SharedThumbnailCache()
: ThumbnailCache<SharedThumbnail>()
{
}
SharedThumbnailCache::~SharedThumbnailCache() = default;
int SharedThumbnailCache::GetPriority() const
{
// Thumbnails override default source thumbnails, so carry higher priority
return 1;
}
const char* SharedThumbnailCache::GetProviderName() const
{
return ProviderName;
}
bool SharedThumbnailCache::IsSupportedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key) const
{
return SharedPreviewUtils::IsSupportedAssetType(key);
}
} // namespace LyIntegration
} // namespace AZ
#include <SharedPreview/moc_SharedThumbnail.cpp>
@@ -0,0 +1,65 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/std/parallel/binary_semaphore.h>
#include <AzFramework/Asset/AssetCatalogBus.h>
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
#endif
namespace AZ
{
namespace LyIntegration
{
//! Custom thumbnail that detects when an asset changes and updates the thumbnail
class SharedThumbnail final
: public AzToolsFramework::Thumbnailer::Thumbnail
, public AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler
, private AzFramework::AssetCatalogEventBus::Handler
{
Q_OBJECT
public:
SharedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key);
~SharedThumbnail() override;
//! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides...
void ThumbnailRendered(const QPixmap& thumbnailImage) override;
void ThumbnailFailedToRender() override;
protected:
void LoadThread() override;
private:
// AzFramework::AssetCatalogEventBus::Handler interface overrides...
void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override;
AZStd::binary_semaphore m_renderWait;
Data::AssetId m_assetId;
AZ::Uuid m_typeId;
};
//! Cache configuration for large thumbnails
class SharedThumbnailCache final : public AzToolsFramework::Thumbnailer::ThumbnailCache<SharedThumbnail>
{
public:
SharedThumbnailCache();
~SharedThumbnailCache() override;
int GetPriority() const override;
const char* GetProviderName() const override;
static constexpr const char* ProviderName = "Common Feature Shared Thumbnail= Provider";
protected:
bool IsSupportedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key) const override;
};
} // namespace LyIntegration
} // namespace AZ
@@ -0,0 +1,73 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
#include <SharedPreview/SharedPreviewContent.h>
#include <SharedPreview/SharedPreviewUtils.h>
#include <SharedPreview/SharedThumbnailRenderer.h>
namespace AZ
{
namespace LyIntegration
{
SharedThumbnailRenderer::SharedThumbnailRenderer()
{
m_previewRenderer.reset(aznew AtomToolsFramework::PreviewRenderer(
"SharedThumbnailRenderer Preview Scene", "SharedThumbnailRenderer Preview Pipeline"));
m_defaultModelAsset.Create(DefaultModelAssetId, true);
m_defaultMaterialAsset.Create(DefaultMaterialAssetId, true);
m_defaultLightingPresetAsset.Create(DefaultLightingPresetAssetId, true);
for (const AZ::Uuid& typeId : SharedPreviewUtils::GetSupportedAssetTypes())
{
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler::BusConnect(typeId);
}
SystemTickBus::Handler::BusConnect();
}
SharedThumbnailRenderer::~SharedThumbnailRenderer()
{
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler::BusDisconnect();
SystemTickBus::Handler::BusDisconnect();
}
void SharedThumbnailRenderer::RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize)
{
m_previewRenderer->AddCaptureRequest(
{ thumbnailSize,
AZStd::make_shared<SharedPreviewContent>(
m_previewRenderer->GetScene(), m_previewRenderer->GetView(), m_previewRenderer->GetEntityContextId(),
SharedPreviewUtils::GetAssetId(thumbnailKey, RPI::ModelAsset::RTTI_Type(), DefaultModelAssetId),
SharedPreviewUtils::GetAssetId(thumbnailKey, RPI::MaterialAsset::RTTI_Type(), DefaultMaterialAssetId),
SharedPreviewUtils::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 SharedThumbnailRenderer::Installed() const
{
return true;
}
void SharedThumbnailRenderer::OnSystemTick()
{
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::ExecuteQueuedEvents();
}
} // namespace LyIntegration
} // namespace AZ
@@ -0,0 +1,60 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
#include <Atom/RPI.Reflect/System/AnyAsset.h>
#include <AtomToolsFramework/PreviewRenderer/PreviewRenderer.h>
#include <AzCore/Component/TickBus.h>
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
#include <Thumbnails/Thumbnail.h>
namespace AZ
{
namespace LyIntegration
{
//! Provides custom rendering thumbnails of supported asset types
class SharedThumbnailRenderer final
: public AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler
, public SystemTickBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(SharedThumbnailRenderer, AZ::SystemAllocator, 0);
SharedThumbnailRenderer();
~SharedThumbnailRenderer();
private:
//! ThumbnailerRendererRequestsBus::Handler interface overrides...
void RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize) override;
bool Installed() const override;
//! SystemTickBus::Handler interface overrides...
void OnSystemTick() override;
// Default assets to be kept loaded and used for rendering if not overridden
static constexpr const char* DefaultLightingPresetPath = "lightingpresets/thumbnail.lightingpreset.azasset";
const Data::AssetId DefaultLightingPresetAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultLightingPresetPath);
Data::Asset<RPI::AnyAsset> m_defaultLightingPresetAsset;
static constexpr const char* DefaultModelPath = "models/sphere.azmodel";
const Data::AssetId DefaultModelAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultModelPath);
Data::Asset<RPI::ModelAsset> m_defaultModelAsset;
static constexpr const char* DefaultMaterialPath = "";
const Data::AssetId DefaultMaterialAssetId;
Data::Asset<RPI::MaterialAsset> m_defaultMaterialAsset;
AZStd::unique_ptr<AtomToolsFramework::PreviewRenderer> m_previewRenderer;
};
} // namespace LyIntegration
} // namespace AZ
@@ -1,37 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
#include <Source/Thumbnails/Preview/CommonPreviewer.h>
#include <Source/Thumbnails/Preview/CommonPreviewerFactory.h>
#include <Source/Thumbnails/ThumbnailUtils.h>
namespace AZ
{
namespace LyIntegration
{
AzToolsFramework::AssetBrowser::Previewer* CommonPreviewerFactory::CreatePreviewer(QWidget* parent) const
{
return new CommonPreviewer(parent);
}
bool CommonPreviewerFactory::IsEntrySupported(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const
{
return
Thumbnails::GetAssetId(entry->GetThumbnailKey(), RPI::MaterialAsset::RTTI_Type()).IsValid() ||
Thumbnails::GetAssetId(entry->GetThumbnailKey(), RPI::ModelAsset::RTTI_Type()).IsValid();
}
const QString& CommonPreviewerFactory::GetName() const
{
return m_name;
}
} // namespace LyIntegration
} // namespace AZ
@@ -1,120 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <Thumbnails/Rendering/CommonThumbnailRenderer.h>
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/FindThumbnailToRenderStep.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/ReleaseResourcesStep.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/WaitForAssetsToLoadStep.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
CommonThumbnailRenderer::CommonThumbnailRenderer()
: m_data(new ThumbnailRendererData)
{
// CommonThumbnailRenderer supports both models and materials, but we connect on materialAssetType
// since MaterialOrModelThumbnail dispatches event on materialAssetType address too
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler::BusConnect(RPI::MaterialAsset::RTTI_Type());
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler::BusConnect(RPI::ModelAsset::RTTI_Type());
SystemTickBus::Handler::BusConnect();
ThumbnailFeatureProcessorProviderBus::Handler::BusConnect();
m_steps[Step::Initialize] = AZStd::make_shared<InitializeStep>(this);
m_steps[Step::FindThumbnailToRender] = AZStd::make_shared<FindThumbnailToRenderStep>(this);
m_steps[Step::WaitForAssetsToLoad] = AZStd::make_shared<WaitForAssetsToLoadStep>(this);
m_steps[Step::Capture] = AZStd::make_shared<CaptureStep>(this);
m_steps[Step::ReleaseResources] = AZStd::make_shared<ReleaseResourcesStep>(this);
m_minimalFeatureProcessors =
{
"AZ::Render::TransformServiceFeatureProcessor",
"AZ::Render::MeshFeatureProcessor",
"AZ::Render::SimplePointLightFeatureProcessor",
"AZ::Render::SimpleSpotLightFeatureProcessor",
"AZ::Render::PointLightFeatureProcessor",
// There is currently a bug where having multiple DirectionalLightFeatureProcessors active can result in shadow
// flickering [ATOM-13568]
// as well as continually rebuilding MeshDrawPackets [ATOM-13633]. Lets just disable the directional light FP for now.
// Possibly re-enable with [GFX TODO][ATOM-13639]
// "AZ::Render::DirectionalLightFeatureProcessor",
"AZ::Render::DiskLightFeatureProcessor",
"AZ::Render::CapsuleLightFeatureProcessor",
"AZ::Render::QuadLightFeatureProcessor",
"AZ::Render::DecalTextureArrayFeatureProcessor",
"AZ::Render::ImageBasedLightFeatureProcessor",
"AZ::Render::PostProcessFeatureProcessor",
"AZ::Render::SkyBoxFeatureProcessor"
};
}
CommonThumbnailRenderer::~CommonThumbnailRenderer()
{
if (m_currentStep != Step::None)
{
CommonThumbnailRenderer::SetStep(Step::ReleaseResources);
}
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler::BusDisconnect();
SystemTickBus::Handler::BusDisconnect();
ThumbnailFeatureProcessorProviderBus::Handler::BusDisconnect();
}
void CommonThumbnailRenderer::SetStep(Step step)
{
if (m_currentStep != Step::None)
{
m_steps[m_currentStep]->Stop();
}
m_currentStep = step;
m_steps[m_currentStep]->Start();
}
Step CommonThumbnailRenderer::GetStep() const
{
return m_currentStep;
}
bool CommonThumbnailRenderer::Installed() const
{
return true;
}
void CommonThumbnailRenderer::OnSystemTick()
{
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::ExecuteQueuedEvents();
}
const AZStd::vector<AZStd::string>& CommonThumbnailRenderer::GetCustomFeatureProcessors() const
{
return m_minimalFeatureProcessors;
}
AZStd::shared_ptr<ThumbnailRendererData> CommonThumbnailRenderer::GetData() const
{
return m_data;
}
void CommonThumbnailRenderer::RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize)
{
m_data->m_thumbnailSize = thumbnailSize;
m_data->m_thumbnailQueue.push(thumbnailKey);
if (m_currentStep == Step::None)
{
SetStep(Step::Initialize);
}
}
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,69 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
#include <Thumbnails/Rendering/ThumbnailRendererContext.h>
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
#include <AtomLyIntegration/CommonFeatures/Thumbnails/ThumbnailFeatureProcessorProviderBus.h>
// Disables warning messages triggered by the Qt library
// 4251: class needs to have dll-interface to be used by clients of class
// 4800: forcing value to bool 'true' or 'false' (performance warning)
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option")
#include <QPixmap>
AZ_POP_DISABLE_WARNING
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
class ThumbnailRendererStep;
//! Provides custom rendering of material and model thumbnails
class CommonThumbnailRenderer
: public ThumbnailRendererContext
, private AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler
, private SystemTickBus::Handler
, private ThumbnailFeatureProcessorProviderBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(CommonThumbnailRenderer, AZ::SystemAllocator, 0)
CommonThumbnailRenderer();
~CommonThumbnailRenderer();
//! ThumbnailRendererContext overrides...
void SetStep(Step step) override;
Step GetStep() const override;
AZStd::shared_ptr<ThumbnailRendererData> GetData() const override;
private:
//! ThumbnailerRendererRequestsBus::Handler interface overrides...
void RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize) override;
bool Installed() const override;
//! SystemTickBus::Handler interface overrides...
void OnSystemTick() override;
//! Render::ThumbnailFeatureProcessorProviderBus::Handler interface overrides...
const AZStd::vector<AZStd::string>& GetCustomFeatureProcessors() const override;
AZStd::unordered_map<Step, AZStd::shared_ptr<ThumbnailRendererStep>> m_steps;
Step m_currentStep = Step::None;
AZStd::shared_ptr<ThumbnailRendererData> m_data;
AZStd::vector<AZStd::string> m_minimalFeatureProcessors;
};
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,42 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/ThumbnailRendererStep.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
struct ThumbnailRendererData;
enum class Step
{
None,
Initialize,
FindThumbnailToRender,
WaitForAssetsToLoad,
Capture,
ReleaseResources
};
//! An interface for ThumbnailRendererSteps to communicate with thumbnail renderer
class ThumbnailRendererContext
{
public:
virtual void SetStep(Step step) = 0;
virtual Step GetStep() const = 0;
virtual AZStd::shared_ptr<ThumbnailRendererData> GetData() const = 0;
};
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,70 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include "Atom/RPI.Reflect/Model/ModelAsset.h"
#include <Atom/RPI.Public/Base.h>
#include <Atom/RPI.Reflect/System/AnyAsset.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Math/Transform.h>
#include <AzFramework/Entity/GameEntityContextComponent.h>
#include <Thumbnails/Thumbnail.h>
namespace AzFramework
{
class Scene;
}
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
//! ThumbnailRendererData encapsulates all data used by thumbnail renderer and caches assets
struct ThumbnailRendererData final
{
static constexpr const char* LightingPresetPath = "lightingpresets/thumbnail.lightingpreset.azasset";
static constexpr const char* DefaultModelPath = "models/sphere.azmodel";
static constexpr const char* DefaultMaterialPath = "materials/basic_grey.azmaterial";
RPI::ScenePtr m_scene;
AZStd::string m_sceneName = "Material Thumbnail Scene";
AZStd::string m_pipelineName = "Material Thumbnail Pipeline";
AZStd::shared_ptr<AzFramework::Scene> m_frameworkScene;
RPI::RenderPipelinePtr m_renderPipeline;
AZStd::unique_ptr<AzFramework::EntityContext> m_entityContext;
AZStd::vector<AZStd::string> m_passHierarchy;
RPI::ViewPtr m_view = nullptr;
Entity* m_modelEntity = nullptr;
int m_thumbnailSize = 512;
//! Incoming thumbnail requests are appended to this queue and processed one at a time in OnTick function.
AZStd::queue<AzToolsFramework::Thumbnailer::SharedThumbnailKey> m_thumbnailQueue;
//! Current thumbnail key being rendered.
AzToolsFramework::Thumbnailer::SharedThumbnailKey m_thumbnailKeyRendered;
Data::Asset<RPI::AnyAsset> m_lightingPresetAsset;
Data::Asset<RPI::ModelAsset> m_defaultModelAsset;
//! Model asset about to be rendered
Data::Asset<RPI::ModelAsset> m_modelAsset;
Data::Asset<RPI::MaterialAsset> m_defaultMaterialAsset;
//! Material asset about to be rendered
Data::Asset<RPI::MaterialAsset> m_materialAsset;
AZStd::unordered_set<Data::AssetId> m_assetsToLoad;
};
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,130 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Atom/Feature/Utils/FrameCaptureBus.h>
#include <Atom/RPI.Public/RenderPipeline.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <Atom/RPI.Public/View.h>
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h>
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Component/TransformBus.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
#include <Thumbnails/Rendering/ThumbnailRendererContext.h>
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.h>
#include <AzCore/Math/MatrixUtils.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
CaptureStep::CaptureStep(ThumbnailRendererContext* context)
: ThumbnailRendererStep(context)
{
}
void CaptureStep::Start()
{
if (!m_context->GetData()->m_materialAsset ||
!m_context->GetData()->m_modelAsset)
{
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
m_context->GetData()->m_thumbnailKeyRendered,
&AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender);
m_context->SetStep(Step::FindThumbnailToRender);
return;
}
Render::MaterialComponentRequestBus::Event(
m_context->GetData()->m_modelEntity->GetId(),
&Render::MaterialComponentRequestBus::Events::SetDefaultMaterialOverride,
m_context->GetData()->m_materialAsset.GetId());
Render::MeshComponentRequestBus::Event(
m_context->GetData()->m_modelEntity->GetId(),
&Render::MeshComponentRequestBus::Events::SetModelAsset,
m_context->GetData()->m_modelAsset);
RepositionCamera();
m_readyToCapture = true;
m_ticksToCapture = 1;
TickBus::Handler::BusConnect();
}
void CaptureStep::Stop()
{
m_context->GetData()->m_renderPipeline->RemoveFromRenderTick();
TickBus::Handler::BusDisconnect();
Render::FrameCaptureNotificationBus::Handler::BusDisconnect();
}
void CaptureStep::RepositionCamera() const
{
// Get bounding sphere of the model asset and estimate how far the camera needs to be see all of it
const Aabb& aabb = m_context->GetData()->m_modelAsset->GetAabb();
Vector3 modelCenter;
float radius;
aabb.GetAsSphere(modelCenter, radius);
float distance = StartingDistanceMultiplier *
GetMax(GetMax(aabb.GetExtents().GetX(), aabb.GetExtents().GetY()), aabb.GetExtents().GetZ()) +
DepthNear;
const Quaternion cameraRotation = Quaternion::CreateFromAxisAngle(Vector3::CreateAxisZ(), StartingRotationAngle);
Vector3 cameraPosition(modelCenter.GetX(), modelCenter.GetY() - distance, modelCenter.GetZ());
cameraPosition = cameraRotation.TransformVector(cameraPosition);
auto cameraTransform = Transform::CreateFromQuaternionAndTranslation(cameraRotation, cameraPosition);
m_context->GetData()->m_view->SetCameraTransform(Matrix3x4::CreateFromTransform(cameraTransform));
}
void CaptureStep::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] ScriptTimePoint time)
{
if (m_readyToCapture && m_ticksToCapture-- <= 0)
{
m_context->GetData()->m_renderPipeline->AddToRenderTickOnce();
RPI::AttachmentReadback::CallbackFunction readbackCallback = [&](const RPI::AttachmentReadback::ReadbackResult& result)
{
if (!result.m_dataBuffer)
{
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
m_context->GetData()->m_thumbnailKeyRendered,
&AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender);
return;
}
uchar* data = result.m_dataBuffer.get()->data();
QImage image(
data, result.m_imageDescriptor.m_size.m_width, result.m_imageDescriptor.m_size.m_height, QImage::Format_RGBA8888);
QPixmap pixmap;
pixmap.convertFromImage(image);
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
m_context->GetData()->m_thumbnailKeyRendered,
&AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailRendered,
pixmap);
};
Render::FrameCaptureNotificationBus::Handler::BusConnect();
bool startedCapture = false;
Render::FrameCaptureRequestBus::BroadcastResult(
startedCapture,
&Render::FrameCaptureRequestBus::Events::CapturePassAttachmentWithCallback,
m_context->GetData()->m_passHierarchy, AZStd::string("Output"), readbackCallback, RPI::PassAttachmentReadbackOption::Output);
// Reset the capture flag if the capture request was successful. Otherwise try capture it again next tick.
if (startedCapture)
{
m_readyToCapture = false;
}
}
}
void CaptureStep::OnCaptureFinished([[maybe_unused]] Render::FrameCaptureResult result, [[maybe_unused]] const AZStd::string& info)
{
m_context->SetStep(Step::FindThumbnailToRender);
}
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,55 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Atom/Feature/Utils/FrameCaptureBus.h>
#include <AzCore/Component/TickBus.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/ThumbnailRendererStep.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
//! CaptureStep renders a thumbnail to a pixmap and notifies MaterialOrModelThumbnail once finished
class CaptureStep
: public ThumbnailRendererStep
, private TickBus::Handler
, private Render::FrameCaptureNotificationBus::Handler
{
public:
CaptureStep(ThumbnailRendererContext* context);
void Start() override;
void Stop() override;
private:
//! Places the camera so that the entire model is visible
void RepositionCamera() const;
//! AZ::TickBus::Handler interface overrides...
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
//! Render::FrameCaptureNotificationBus::Handler overrides...
void OnCaptureFinished(Render::FrameCaptureResult result, const AZStd::string& info) override;
static constexpr float DepthNear = 0.01f;
static constexpr float StartingDistanceMultiplier = 1.75f;
static constexpr float StartingRotationAngle = Constants::QuarterPi / 2.0f;
//! This flag is needed to wait one frame after each frame capture to reset FrameCaptureSystemComponent
bool m_readyToCapture = true;
//! This is necessary to suspend capture to allow a frame for Material and Mesh components to assign materials
int m_ticksToCapture = 0;
};
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,79 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
#include <Thumbnails/ThumbnailUtils.h>
#include <Thumbnails/Rendering/ThumbnailRendererContext.h>
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/FindThumbnailToRenderStep.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
FindThumbnailToRenderStep::FindThumbnailToRenderStep(ThumbnailRendererContext* context)
: ThumbnailRendererStep(context)
{
}
void FindThumbnailToRenderStep::Start()
{
TickBus::Handler::BusConnect();
}
void FindThumbnailToRenderStep::Stop()
{
TickBus::Handler::BusDisconnect();
}
void FindThumbnailToRenderStep::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] ScriptTimePoint time)
{
PickNextThumbnail();
}
void FindThumbnailToRenderStep::PickNextThumbnail()
{
if (!m_context->GetData()->m_thumbnailQueue.empty())
{
// pop the next thumbnailkey to be rendered from the queue
m_context->GetData()->m_thumbnailKeyRendered = m_context->GetData()->m_thumbnailQueue.front();
m_context->GetData()->m_thumbnailQueue.pop();
// Find whether thumbnailkey contains a material asset or set a default material
m_context->GetData()->m_materialAsset = m_context->GetData()->m_defaultMaterialAsset;
Data::AssetId materialAssetId = GetAssetId(m_context->GetData()->m_thumbnailKeyRendered, RPI::MaterialAsset::RTTI_Type());
if (materialAssetId.IsValid())
{
if (m_context->GetData()->m_assetsToLoad.emplace(materialAssetId).second)
{
m_context->GetData()->m_materialAsset.Create(materialAssetId);
m_context->GetData()->m_materialAsset.QueueLoad();
}
}
// Find whether thumbnailkey contains a model asset or set a default model
m_context->GetData()->m_modelAsset = m_context->GetData()->m_defaultModelAsset;
Data::AssetId modelAssetId = GetAssetId(m_context->GetData()->m_thumbnailKeyRendered, RPI::ModelAsset::RTTI_Type());
if (modelAssetId.IsValid())
{
if (m_context->GetData()->m_assetsToLoad.emplace(modelAssetId).second)
{
m_context->GetData()->m_modelAsset.Create(modelAssetId);
m_context->GetData()->m_modelAsset.QueueLoad();
}
}
m_context->SetStep(Step::WaitForAssetsToLoad);
}
}
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,40 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Thumbnails/Rendering/ThumbnailRendererSteps/ThumbnailRendererStep.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
//! FindThumbnailToRenderStep checks whether there are any new thumbnails that need to be rendered every tick
class FindThumbnailToRenderStep
: public ThumbnailRendererStep
, private TickBus::Handler
{
public:
FindThumbnailToRenderStep(ThumbnailRendererContext* context);
void Start() override;
void Stop() override;
private:
//! AZ::TickBus::Handler interface overrides...
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
void PickNextThumbnail();
};
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,191 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Math/MatrixUtils.h>
#include <AzCore/EBus/Results.h>
#include <AzFramework/Components/TransformComponent.h>
#include <Atom/Feature/ImageBasedLights/ImageBasedLightFeatureProcessorInterface.h>
#include <Atom/Feature/PostProcess/PostProcessFeatureProcessorInterface.h>
#include <Atom/Feature/SkyBox/SkyBoxFeatureProcessorInterface.h>
#include <Atom/Feature/Utils/LightingPreset.h>
#include <Atom/RPI.Public/RenderPipeline.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/View.h>
#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
#include <Atom/RPI.Reflect/System/RenderPipelineDescriptor.h>
#include <Atom/RPI.Reflect/System/SceneDescriptor.h>
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentConstants.h>
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentConstants.h>
#include <AtomLyIntegration/CommonFeatures/Thumbnails/ThumbnailFeatureProcessorProviderBus.h>
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
#include <Thumbnails/Rendering/ThumbnailRendererContext.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
InitializeStep::InitializeStep(ThumbnailRendererContext* context)
: ThumbnailRendererStep(context)
{
}
void InitializeStep::Start()
{
auto data = m_context->GetData();
data->m_entityContext = AZStd::make_unique<AzFramework::EntityContext>();
data->m_entityContext->InitContext();
// Create and register a scene with all required feature processors
RPI::SceneDescriptor sceneDesc;
AZ::EBusAggregateResults<AZStd::vector<AZStd::string>> results;
ThumbnailFeatureProcessorProviderBus::BroadcastResult(results, &ThumbnailFeatureProcessorProviderBus::Handler::GetCustomFeatureProcessors);
AZStd::set<AZStd::string> featureProcessorNames;
for (auto& resultCollection : results.values)
{
for (auto& featureProcessorName : resultCollection)
{
if (featureProcessorNames.emplace(featureProcessorName).second)
{
sceneDesc.m_featureProcessorNames.push_back(featureProcessorName);
}
}
}
data->m_scene = RPI::Scene::CreateScene(sceneDesc);
// Bind m_defaultScene to the GameEntityContext's AzFramework::Scene
auto* sceneSystem = AzFramework::SceneSystemInterface::Get();
AZ_Assert(sceneSystem, "Thumbnail system failed to get scene system implementation.");
Outcome<AZStd::shared_ptr<AzFramework::Scene>, AZStd::string> createSceneOutcome =
sceneSystem->CreateScene(data->m_sceneName);
AZ_Assert(createSceneOutcome, createSceneOutcome.GetError().c_str()); // This should never happen unless scene creation has changed.
data->m_frameworkScene = createSceneOutcome.TakeValue();
data->m_frameworkScene->SetSubsystem(data->m_scene);
data->m_frameworkScene->SetSubsystem(data->m_entityContext.get());
// Create a render pipeline from the specified asset for the window context and add the pipeline to the scene
RPI::RenderPipelineDescriptor pipelineDesc;
pipelineDesc.m_mainViewTagName = "MainCamera";
pipelineDesc.m_name = data->m_pipelineName;
pipelineDesc.m_rootPassTemplate = "ThumbnailPipelineRenderToTexture";
// We have to set the samples to 4 to match the pipeline passes' setting, otherwise it may lead to device lost issue
// [GFX TODO] [ATOM-13551] Default value sand validation required to prevent pipeline crash and device lost
pipelineDesc.m_renderSettings.m_multisampleState.m_samples = 4;
data->m_renderPipeline = RPI::RenderPipeline::CreateRenderPipeline(pipelineDesc);
data->m_scene->AddRenderPipeline(data->m_renderPipeline);
data->m_scene->Activate();
RPI::RPISystemInterface::Get()->RegisterScene(data->m_scene);
data->m_passHierarchy.push_back(data->m_pipelineName);
data->m_passHierarchy.push_back("CopyToSwapChain");
// Connect camera to pipeline's default view after camera entity activated
Name viewName = Name("MainCamera");
data->m_view = RPI::View::CreateView(viewName, RPI::View::UsageCamera);
Matrix4x4 viewToClipMatrix;
MakePerspectiveFovMatrixRH(viewToClipMatrix,
Constants::QuarterPi,
AspectRatio,
NearDist,
FarDist, true);
data->m_view->SetViewToClipMatrix(viewToClipMatrix);
data->m_renderPipeline->SetDefaultView(data->m_view);
// Create lighting preset
data->m_lightingPresetAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath<AZ::RPI::AnyAsset>(ThumbnailRendererData::LightingPresetPath);
if (data->m_lightingPresetAsset.IsReady())
{
auto preset = data->m_lightingPresetAsset->GetDataAs<Render::LightingPreset>();
if (preset)
{
auto iblFeatureProcessor = data->m_scene->GetFeatureProcessor<Render::ImageBasedLightFeatureProcessorInterface>();
auto postProcessFeatureProcessor = data->m_scene->GetFeatureProcessor<Render::PostProcessFeatureProcessorInterface>();
auto exposureControlSettingInterface = postProcessFeatureProcessor->GetOrCreateSettingsInterface(EntityId())->GetOrCreateExposureControlSettingsInterface();
auto directionalLightFeatureProcessor = data->m_scene->GetFeatureProcessor<Render::DirectionalLightFeatureProcessorInterface>();
auto skyboxFeatureProcessor = data->m_scene->GetFeatureProcessor<Render::SkyBoxFeatureProcessorInterface>();
skyboxFeatureProcessor->Enable(true);
skyboxFeatureProcessor->SetSkyboxMode(Render::SkyBoxMode::Cubemap);
Camera::Configuration cameraConfig;
cameraConfig.m_fovRadians = Constants::HalfPi;
cameraConfig.m_nearClipDistance = NearDist;
cameraConfig.m_farClipDistance = FarDist;
cameraConfig.m_frustumWidth = 100.0f;
cameraConfig.m_frustumHeight = 100.0f;
AZStd::vector<Render::DirectionalLightFeatureProcessorInterface::LightHandle> lightHandles;
preset->ApplyLightingPreset(
iblFeatureProcessor,
skyboxFeatureProcessor,
exposureControlSettingInterface,
directionalLightFeatureProcessor,
cameraConfig,
lightHandles);
}
}
// Create preview model
AzFramework::EntityContextRequestBus::EventResult(data->m_modelEntity, data->m_entityContext->GetContextId(),
&AzFramework::EntityContextRequestBus::Events::CreateEntity, "ThumbnailPreviewModel");
data->m_modelEntity->CreateComponent(Render::MeshComponentTypeId);
data->m_modelEntity->CreateComponent(Render::MaterialComponentTypeId);
data->m_modelEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
data->m_modelEntity->Init();
data->m_modelEntity->Activate();
// preload default model
Data::AssetId defaultModelAssetId;
Data::AssetCatalogRequestBus::BroadcastResult(
defaultModelAssetId,
&Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
m_context->GetData()->DefaultModelPath,
RPI::ModelAsset::RTTI_Type(),
false);
AZ_Error("ThumbnailRenderer", defaultModelAssetId.IsValid(), "Default model asset is invalid. Verify the asset %s exists.", m_context->GetData()->DefaultModelPath);
if (m_context->GetData()->m_assetsToLoad.emplace(defaultModelAssetId).second)
{
data->m_defaultModelAsset.Create(defaultModelAssetId);
data->m_defaultModelAsset.QueueLoad();
}
// preload default material
Data::AssetId defaultMaterialAssetId;
Data::AssetCatalogRequestBus::BroadcastResult(
defaultMaterialAssetId,
&Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
m_context->GetData()->DefaultMaterialPath,
RPI::MaterialAsset::RTTI_Type(),
false);
AZ_Error("ThumbnailRenderer", defaultMaterialAssetId.IsValid(), "Default material asset is invalid. Verify the asset %s exists.", m_context->GetData()->DefaultMaterialPath);
if (m_context->GetData()->m_assetsToLoad.emplace(defaultMaterialAssetId).second)
{
data->m_defaultMaterialAsset.Create(defaultMaterialAssetId);
data->m_defaultMaterialAsset.QueueLoad();
}
m_context->SetStep(Step::FindThumbnailToRender);
}
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,37 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Thumbnails/Rendering/ThumbnailRendererSteps/ThumbnailRendererStep.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
//! InitializeStep sets up RPI system and scene and prepares it for rendering thumbnail entities
//! This step is only called once when CommonThumbnailRenderer begins rendering its first thumbnail
class InitializeStep
: public ThumbnailRendererStep
{
public:
InitializeStep(ThumbnailRendererContext* context);
void Start() override;
private:
static constexpr float AspectRatio = 1.0f;
static constexpr float NearDist = 0.1f;
static constexpr float FarDist = 100.0f;
};
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,57 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Atom/RPI.Public/RenderPipeline.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <Atom/RPI.Public/Scene.h>
#include <AzFramework/Scene/Scene.h>
#include <AzFramework/Scene/SceneSystemInterface.h>
#include <Thumbnails/Rendering/ThumbnailRendererContext.h>
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/ReleaseResourcesStep.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
ReleaseResourcesStep::ReleaseResourcesStep(ThumbnailRendererContext* context)
: ThumbnailRendererStep(context)
{
}
void ReleaseResourcesStep::Start()
{
auto data = m_context->GetData();
data->m_defaultMaterialAsset.Release();
data->m_defaultModelAsset.Release();
data->m_materialAsset.Release();
data->m_modelAsset.Release();
data->m_lightingPresetAsset.Release();
if (data->m_modelEntity)
{
AzFramework::EntityContextRequestBus::Event(data->m_entityContext->GetContextId(),
&AzFramework::EntityContextRequestBus::Events::DestroyEntity, data->m_modelEntity);
data->m_modelEntity = nullptr;
}
data->m_scene->Deactivate();
data->m_scene->RemoveRenderPipeline(data->m_renderPipeline->GetId());
RPI::RPISystemInterface::Get()->UnregisterScene(data->m_scene);
data->m_frameworkScene->UnsetSubsystem(data->m_scene);
data->m_frameworkScene->UnsetSubsystem(data->m_entityContext.get());
data->m_scene = nullptr;
data->m_frameworkScene = nullptr;
data->m_renderPipeline = nullptr;
}
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,30 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Thumbnails/Rendering/ThumbnailRendererSteps/ThumbnailRendererStep.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
class ReleaseResourcesStep
: public ThumbnailRendererStep
{
public:
ReleaseResourcesStep(ThumbnailRendererContext* context);
void Start() override;
};
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,37 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
class ThumbnailRendererContext;
//! ThumbnailRendererStep decouples CommonThumbnailRenderer logic into easy-to-understand and debug pieces
class ThumbnailRendererStep
{
public:
explicit ThumbnailRendererStep(ThumbnailRendererContext* context) : m_context(context) {}
virtual ~ThumbnailRendererStep() = default;
//! Start is called when step begins execution
virtual void Start() {}
//! Stop is called when step ends execution
virtual void Stop() {}
protected:
ThumbnailRendererContext* m_context;
};
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,101 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "Thumbnails/ThumbnailerBus.h"
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
#include <Thumbnails/Rendering/ThumbnailRendererContext.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/WaitForAssetsToLoadStep.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
WaitForAssetsToLoadStep::WaitForAssetsToLoadStep(ThumbnailRendererContext* context)
: ThumbnailRendererStep(context)
{
}
void WaitForAssetsToLoadStep::Start()
{
LoadNextAsset();
}
void WaitForAssetsToLoadStep::Stop()
{
Data::AssetBus::Handler::BusDisconnect();
TickBus::Handler::BusDisconnect();
m_context->GetData()->m_assetsToLoad.clear();
}
void WaitForAssetsToLoadStep::LoadNextAsset()
{
if (m_context->GetData()->m_assetsToLoad.empty())
{
// When all assets are loaded, render the thumbnail itself
m_context->SetStep(Step::Capture);
}
else
{
// Pick the the next asset and wait until its ready
const auto assetIdIt = m_context->GetData()->m_assetsToLoad.begin();
m_context->GetData()->m_assetsToLoad.erase(assetIdIt);
m_assetId = *assetIdIt;
Data::AssetBus::Handler::BusConnect(m_assetId);
// If asset is already loaded, then AssetEvents will call OnAssetReady instantly and we don't need to wait this time
if (Data::AssetBus::Handler::BusIsConnected())
{
TickBus::Handler::BusConnect();
m_timeRemainingS = TimeOutS;
}
}
}
void WaitForAssetsToLoadStep::OnAssetReady([[maybe_unused]] Data::Asset<Data::AssetData> asset)
{
Data::AssetBus::Handler::BusDisconnect();
LoadNextAsset();
}
void WaitForAssetsToLoadStep::OnAssetError([[maybe_unused]] Data::Asset<Data::AssetData> asset)
{
Data::AssetBus::Handler::BusDisconnect();
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
m_context->GetData()->m_thumbnailKeyRendered,
&AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender);
m_context->SetStep(Step::FindThumbnailToRender);
}
void WaitForAssetsToLoadStep::OnAssetCanceled([[maybe_unused]] Data::AssetId assetId)
{
Data::AssetBus::Handler::BusDisconnect();
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
m_context->GetData()->m_thumbnailKeyRendered,
&AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender);
m_context->SetStep(Step::FindThumbnailToRender);
}
void WaitForAssetsToLoadStep::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
{
m_timeRemainingS -= deltaTime;
if (m_timeRemainingS < 0)
{
auto assetIdStr = m_assetId.ToString<AZStd::string>();
AZ_Warning("CommonThumbnailRenderer", false, "Timed out waiting for asset %s to load.", assetIdStr.c_str());
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
m_context->GetData()->m_thumbnailKeyRendered,
&AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender);
m_context->SetStep(Step::FindThumbnailToRender);
}
}
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -1,50 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Asset/AssetCommon.h>
#include <Thumbnails/Rendering/ThumbnailRendererSteps/ThumbnailRendererStep.h>
namespace AZ
{
namespace LyIntegration
{
namespace Thumbnails
{
//! WaitForAssetsToLoadStep pauses further rendering until all assets used for rendering a thumbnail have been loaded
class WaitForAssetsToLoadStep
: public ThumbnailRendererStep
, private Data::AssetBus::Handler
, private TickBus::Handler
{
public:
WaitForAssetsToLoadStep(ThumbnailRendererContext* context);
void Start() override;
void Stop() override;
private:
void LoadNextAsset();
// AZ::Data::AssetBus::Handler
void OnAssetReady(Data::Asset<Data::AssetData> asset) override;
void OnAssetError(Data::Asset<Data::AssetData> asset) override;
void OnAssetCanceled(Data::AssetId assetId) override;
//! AZ::TickBus::Handler interface overrides...
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
static constexpr float TimeOutS = 3.0f;
Data::AssetId m_assetId;
float m_timeRemainingS = 0;
};
} // namespace Thumbnails
} // namespace LyIntegration
} // namespace AZ
@@ -7,9 +7,9 @@
#
set(FILES
Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentNotificationBus.h
Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h
Include/AtomLyIntegration/CommonFeatures/ReflectionProbe/EditorReflectionProbeBus.h
Include/AtomLyIntegration/CommonFeatures/Thumbnails/ThumbnailFeatureProcessorProviderBus.h
Source/Module.cpp
Source/Animation/EditorAttachmentComponent.h
Source/Animation/EditorAttachmentComponent.cpp
@@ -45,8 +45,6 @@ set(FILES
Source/Material/EditorMaterialSystemComponent.h
Source/Material/MaterialBrowserInteractions.h
Source/Material/MaterialBrowserInteractions.cpp
Source/Material/MaterialThumbnail.cpp
Source/Material/MaterialThumbnail.h
Source/Mesh/EditorMeshComponent.h
Source/Mesh/EditorMeshComponent.cpp
Source/Mesh/EditorMeshStats.h
@@ -55,8 +53,6 @@ set(FILES
Source/Mesh/EditorMeshSystemComponent.h
Source/Mesh/EditorMeshStatsSerializer.cpp
Source/Mesh/EditorMeshStatsSerializer.h
Source/Mesh/MeshThumbnail.h
Source/Mesh/MeshThumbnail.cpp
Source/OcclusionCullingPlane/EditorOcclusionCullingPlaneComponent.h
Source/OcclusionCullingPlane/EditorOcclusionCullingPlaneComponent.cpp
Source/PostProcess/EditorPostFxLayerComponent.cpp
@@ -95,28 +91,19 @@ set(FILES
Source/SkyBox/EditorHDRiSkyboxComponent.h
Source/SkyBox/EditorPhysicalSkyComponent.cpp
Source/SkyBox/EditorPhysicalSkyComponent.h
Source/Thumbnails/ThumbnailUtils.h
Source/Thumbnails/ThumbnailUtils.cpp
Source/Thumbnails/Preview/CommonPreviewer.cpp
Source/Thumbnails/Preview/CommonPreviewer.h
Source/Thumbnails/Preview/CommonPreviewer.ui
Source/Thumbnails/Preview/CommonPreviewerFactory.cpp
Source/Thumbnails/Preview/CommonPreviewerFactory.h
Source/Thumbnails/Rendering/CommonThumbnailRenderer.cpp
Source/Thumbnails/Rendering/CommonThumbnailRenderer.h
Source/Thumbnails/Rendering/ThumbnailRendererData.h
Source/Thumbnails/Rendering/ThumbnailRendererContext.h
Source/Thumbnails/Rendering/ThumbnailRendererSteps/ThumbnailRendererStep.h
Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp
Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.h
Source/Thumbnails/Rendering/ThumbnailRendererSteps/FindThumbnailToRenderStep.cpp
Source/Thumbnails/Rendering/ThumbnailRendererSteps/FindThumbnailToRenderStep.h
Source/Thumbnails/Rendering/ThumbnailRendererSteps/WaitForAssetsToLoadStep.cpp
Source/Thumbnails/Rendering/ThumbnailRendererSteps/WaitForAssetsToLoadStep.h
Source/Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.cpp
Source/Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.h
Source/Thumbnails/Rendering/ThumbnailRendererSteps/ReleaseResourcesStep.cpp
Source/Thumbnails/Rendering/ThumbnailRendererSteps/ReleaseResourcesStep.h
Source/SharedPreview/SharedPreviewer.cpp
Source/SharedPreview/SharedPreviewer.h
Source/SharedPreview/SharedPreviewer.ui
Source/SharedPreview/SharedPreviewerFactory.cpp
Source/SharedPreview/SharedPreviewerFactory.h
Source/SharedPreview/SharedPreviewContent.cpp
Source/SharedPreview/SharedPreviewContent.h
Source/SharedPreview/SharedPreviewUtils.cpp
Source/SharedPreview/SharedPreviewUtils.h
Source/SharedPreview/SharedThumbnail.cpp
Source/SharedPreview/SharedThumbnail.h
Source/SharedPreview/SharedThumbnailRenderer.cpp
Source/SharedPreview/SharedThumbnailRenderer.h
Source/Scripting/EditorEntityReferenceComponent.cpp
Source/Scripting/EditorEntityReferenceComponent.h
Source/SurfaceData/EditorSurfaceDataMeshComponent.cpp