First phase of refactoring atom thumbnail and preview rendering into a reusable system that can be used for additional thumbnail types and capturing preview images for other purposes. Our
• Removed classes for initialization and teardown steps of the renderer • Moved initialization and teardown logic back to the renderer constructor and destructor • Combined thumbnail render context and data with the main renderer class • Made all render data private and instead implemented a public interface • Remaining steps were simplified and updated to work directly with the new public interface • Changed the waiting for assets to load state to poll asset status on tick because we were timing out there anyway • Unified redundant camera configuration variables and made sure they were used consistently when initializing and updating the scene and camera • Changed interface for custom feature processor request API to build a set instead of returning a vector • Moved initialization of the thumbnail renderer and preview factory after asset catalog has loaded Signed-off-by: Guthrie Adams <guthadam@amazon.com>
This commit is contained in:
+1
-1
@@ -24,7 +24,7 @@ namespace AZ
|
||||
{
|
||||
public:
|
||||
//! Get a list of custom feature processors to register with thumbnail renderer
|
||||
virtual const AZStd::vector<AZStd::string>& GetCustomFeatureProcessors() const = 0;
|
||||
virtual void GetCustomFeatureProcessors(AZStd::unordered_set<AZStd::string>& featureProcessors) const = 0;
|
||||
};
|
||||
|
||||
using ThumbnailFeatureProcessorProviderBus = AZ::EBus<ThumbnailFeatureProcessorProviderRequests>;
|
||||
|
||||
+10
-2
@@ -82,12 +82,11 @@ 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();
|
||||
}
|
||||
|
||||
@@ -95,6 +94,7 @@ namespace AZ
|
||||
{
|
||||
AzToolsFramework::EditorLevelNotificationBus::Handler::BusDisconnect();
|
||||
AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect();
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::AssetBrowser::PreviewerRequestBus::Handler::BusDisconnect();
|
||||
|
||||
m_skinnedMeshDebugDisplay.reset();
|
||||
@@ -191,6 +191,14 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void EditorCommonFeaturesSystemComponent::OnCatalogLoaded([[maybe_unused]] const char* catalogFile)
|
||||
{
|
||||
AZ::TickBus::QueueFunction([this](){
|
||||
m_renderer = AZStd::make_unique<AZ::LyIntegration::Thumbnails::CommonThumbnailRenderer>();
|
||||
m_previewerFactory = AZStd::make_unique<LyIntegration::CommonPreviewerFactory>();
|
||||
});
|
||||
}
|
||||
|
||||
const AzToolsFramework::AssetBrowser::PreviewerFactory* EditorCommonFeaturesSystemComponent::GetPreviewerFactory(
|
||||
const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const
|
||||
{
|
||||
|
||||
+4
@@ -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:
|
||||
@@ -56,6 +57,9 @@ namespace AZ
|
||||
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;
|
||||
|
||||
|
||||
+327
-65
@@ -6,15 +6,42 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/Feature/ImageBasedLights/ImageBasedLightFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/PostProcess/PostProcessFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/SkyBox/SkyBoxFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/Utils/FrameCaptureBus.h>
|
||||
#include <Atom/Feature/Utils/LightingPreset.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/Asset/AssetUtils.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialAsset.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/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/EBus/Results.h>
|
||||
#include <AzCore/Math/MatrixUtils.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <AzFramework/Scene/Scene.h>
|
||||
#include <AzFramework/Scene/SceneSystemInterface.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.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>
|
||||
#include <Thumbnails/ThumbnailUtils.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -23,23 +50,310 @@ namespace AZ
|
||||
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();
|
||||
SystemTickBus::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_entityContext = AZStd::make_unique<AzFramework::EntityContext>();
|
||||
m_entityContext->InitContext();
|
||||
|
||||
m_minimalFeatureProcessors =
|
||||
// Create and register a scene with all required feature processors
|
||||
AZStd::unordered_set<AZStd::string> featureProcessors;
|
||||
ThumbnailFeatureProcessorProviderBus::Broadcast(
|
||||
&ThumbnailFeatureProcessorProviderBus::Handler::GetCustomFeatureProcessors, featureProcessors);
|
||||
|
||||
RPI::SceneDescriptor sceneDesc;
|
||||
sceneDesc.m_featureProcessorNames.assign(featureProcessors.begin(), featureProcessors.end());
|
||||
m_scene = RPI::Scene::CreateScene(sceneDesc);
|
||||
|
||||
// Bind m_frameworkScene to the entity context'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(m_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
|
||||
RPI::RenderPipelineDescriptor pipelineDesc;
|
||||
pipelineDesc.m_mainViewTagName = "MainCamera";
|
||||
pipelineDesc.m_name = m_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 = RPI::RenderPipeline::CreateRenderPipeline(pipelineDesc);
|
||||
m_scene->AddRenderPipeline(m_renderPipeline);
|
||||
m_scene->Activate();
|
||||
RPI::RPISystemInterface::Get()->RegisterScene(m_scene);
|
||||
m_passHierarchy.push_back(m_pipelineName);
|
||||
m_passHierarchy.push_back("CopyToSwapChain");
|
||||
|
||||
// Connect camera to pipeline's default view after camera entity activated
|
||||
Matrix4x4 viewToClipMatrix;
|
||||
MakePerspectiveFovMatrixRH(viewToClipMatrix, FieldOfView, AspectRatio, NearDist, FarDist, true);
|
||||
m_view = RPI::View::CreateView(Name("MainCamera"), RPI::View::UsageCamera);
|
||||
m_view->SetViewToClipMatrix(viewToClipMatrix);
|
||||
m_renderPipeline->SetDefaultView(m_view);
|
||||
|
||||
// Create preview model
|
||||
AzFramework::EntityContextRequestBus::EventResult(
|
||||
m_modelEntity, m_entityContext->GetContextId(), &AzFramework::EntityContextRequestBus::Events::CreateEntity,
|
||||
"ThumbnailPreviewModel");
|
||||
m_modelEntity->CreateComponent(Render::MeshComponentTypeId);
|
||||
m_modelEntity->CreateComponent(Render::MaterialComponentTypeId);
|
||||
m_modelEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
|
||||
m_modelEntity->Init();
|
||||
m_modelEntity->Activate();
|
||||
|
||||
m_defaultLightingPresetAsset.Create(DefaultLightingPresetAssetId, true);
|
||||
m_defaultMaterialAsset.Create(DefaultMaterialAssetId, true);
|
||||
m_defaultModelAsset.Create(DefaultModelAssetId, true);
|
||||
|
||||
m_steps[CommonThumbnailRenderer::Step::FindThumbnailToRender] = AZStd::make_shared<FindThumbnailToRenderStep>(this);
|
||||
m_steps[CommonThumbnailRenderer::Step::WaitForAssetsToLoad] = AZStd::make_shared<WaitForAssetsToLoadStep>(this);
|
||||
m_steps[CommonThumbnailRenderer::Step::Capture] = AZStd::make_shared<CaptureStep>(this);
|
||||
SetStep(CommonThumbnailRenderer::Step::FindThumbnailToRender);
|
||||
}
|
||||
|
||||
CommonThumbnailRenderer::~CommonThumbnailRenderer()
|
||||
{
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler::BusDisconnect();
|
||||
SystemTickBus::Handler::BusDisconnect();
|
||||
ThumbnailFeatureProcessorProviderBus::Handler::BusDisconnect();
|
||||
|
||||
SetStep(CommonThumbnailRenderer::Step::None);
|
||||
|
||||
if (m_modelEntity)
|
||||
{
|
||||
AzFramework::EntityContextRequestBus::Event(
|
||||
m_entityContext->GetContextId(), &AzFramework::EntityContextRequestBus::Events::DestroyEntity, m_modelEntity);
|
||||
m_modelEntity = nullptr;
|
||||
}
|
||||
|
||||
m_scene->Deactivate();
|
||||
m_scene->RemoveRenderPipeline(m_renderPipeline->GetId());
|
||||
RPI::RPISystemInterface::Get()->UnregisterScene(m_scene);
|
||||
m_frameworkScene->UnsetSubsystem(m_scene);
|
||||
m_frameworkScene->UnsetSubsystem(m_entityContext.get());
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::SetStep(Step step)
|
||||
{
|
||||
auto stepItr = m_steps.find(m_currentStep);
|
||||
if (stepItr != m_steps.end())
|
||||
{
|
||||
stepItr->second->Stop();
|
||||
}
|
||||
|
||||
m_currentStep = step;
|
||||
|
||||
stepItr = m_steps.find(m_currentStep);
|
||||
if (stepItr != m_steps.end())
|
||||
{
|
||||
stepItr->second->Start();
|
||||
}
|
||||
}
|
||||
|
||||
CommonThumbnailRenderer::Step CommonThumbnailRenderer::GetStep() const
|
||||
{
|
||||
return m_currentStep;
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::SelectThumbnail()
|
||||
{
|
||||
if (!m_thumbnailInfoQueue.empty())
|
||||
{
|
||||
// pop the next thumbnailkey to be rendered from the queue
|
||||
m_currentThubnailInfo = m_thumbnailInfoQueue.front();
|
||||
m_thumbnailInfoQueue.pop();
|
||||
|
||||
SetStep(CommonThumbnailRenderer::Step::WaitForAssetsToLoad);
|
||||
}
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::CancelThumbnail()
|
||||
{
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
|
||||
m_currentThubnailInfo.m_key, &AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender);
|
||||
SetStep(CommonThumbnailRenderer::Step::FindThumbnailToRender);
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::CompleteThumbnail()
|
||||
{
|
||||
SetStep(CommonThumbnailRenderer::Step::FindThumbnailToRender);
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::LoadAssets()
|
||||
{
|
||||
// Determine if thumbnailkey contains a material asset or set a default material
|
||||
const Data::AssetId materialAssetId = GetAssetId(m_currentThubnailInfo.m_key, RPI::MaterialAsset::RTTI_Type());
|
||||
m_materialAsset.Create(materialAssetId.IsValid() ? materialAssetId : DefaultMaterialAssetId, true);
|
||||
|
||||
// Determine if thumbnailkey contains a model asset or set a default model
|
||||
const Data::AssetId modelAssetId = GetAssetId(m_currentThubnailInfo.m_key, RPI::ModelAsset::RTTI_Type());
|
||||
m_modelAsset.Create(modelAssetId.IsValid() ? modelAssetId : DefaultModelAssetId, true);
|
||||
|
||||
// Determine if thumbnailkey contains a lighting preset asset or set a default lighting preset
|
||||
const Data::AssetId lightingPresetAssetId = GetAssetId(m_currentThubnailInfo.m_key, RPI::AnyAsset::RTTI_Type());
|
||||
m_lightingPresetAsset.Create(lightingPresetAssetId.IsValid() ? lightingPresetAssetId : DefaultLightingPresetAssetId, true);
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::UpdateLoadAssets()
|
||||
{
|
||||
if (m_materialAsset.IsReady() && m_modelAsset.IsReady() && m_lightingPresetAsset.IsReady())
|
||||
{
|
||||
SetStep(CommonThumbnailRenderer::Step::Capture);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_materialAsset.IsError() || m_modelAsset.IsError() || m_lightingPresetAsset.IsError())
|
||||
{
|
||||
CancelLoadAssets();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::CancelLoadAssets()
|
||||
{
|
||||
AZ_Warning(
|
||||
"CommonThumbnailRenderer", m_materialAsset.IsReady(), "Asset failed to load in time: %s",
|
||||
m_materialAsset.ToString<AZStd::string>().c_str());
|
||||
AZ_Warning(
|
||||
"CommonThumbnailRenderer", m_modelAsset.IsReady(), "Asset failed to load in time: %s",
|
||||
m_modelAsset.ToString<AZStd::string>().c_str());
|
||||
AZ_Warning(
|
||||
"CommonThumbnailRenderer", m_lightingPresetAsset.IsReady(), "Asset failed to load in time: %s",
|
||||
m_lightingPresetAsset.ToString<AZStd::string>().c_str());
|
||||
CancelThumbnail();
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::UpdateScene()
|
||||
{
|
||||
UpdateModel();
|
||||
UpdateLighting();
|
||||
UpdateCamera();
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::UpdateModel()
|
||||
{
|
||||
Render::MaterialComponentRequestBus::Event(
|
||||
m_modelEntity->GetId(), &Render::MaterialComponentRequestBus::Events::SetDefaultMaterialOverride,
|
||||
m_materialAsset.GetId());
|
||||
|
||||
Render::MeshComponentRequestBus::Event(
|
||||
m_modelEntity->GetId(), &Render::MeshComponentRequestBus::Events::SetModelAsset, m_modelAsset);
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::UpdateLighting()
|
||||
{
|
||||
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 CommonThumbnailRenderer::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 = {};
|
||||
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::CreateFromQuaternionAndTranslation(cameraRotation, cameraPosition);
|
||||
m_view->SetCameraTransform(Matrix3x4::CreateFromTransform(cameraTransform));
|
||||
}
|
||||
|
||||
RPI::AttachmentReadback::CallbackFunction CommonThumbnailRenderer::GetCaptureCallback()
|
||||
{
|
||||
return [this](const RPI::AttachmentReadback::ReadbackResult& result)
|
||||
{
|
||||
if (result.m_dataBuffer)
|
||||
{
|
||||
QImage image(
|
||||
result.m_dataBuffer.get()->data(), result.m_imageDescriptor.m_size.m_width,
|
||||
result.m_imageDescriptor.m_size.m_height, QImage::Format_RGBA8888);
|
||||
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
|
||||
m_currentThubnailInfo.m_key,
|
||||
&AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailRendered, QPixmap::fromImage(image));
|
||||
}
|
||||
else
|
||||
{
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
|
||||
m_currentThubnailInfo.m_key,
|
||||
&AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool CommonThumbnailRenderer::StartCapture()
|
||||
{
|
||||
if (auto renderToTexturePass = azrtti_cast<AZ::RPI::RenderToTexturePass*>(m_renderPipeline->GetRootPass().get()))
|
||||
{
|
||||
renderToTexturePass->ResizeOutput(m_currentThubnailInfo.m_size, m_currentThubnailInfo.m_size);
|
||||
}
|
||||
|
||||
m_renderPipeline->AddToRenderTickOnce();
|
||||
|
||||
bool startedCapture = false;
|
||||
Render::FrameCaptureRequestBus::BroadcastResult(
|
||||
startedCapture, &Render::FrameCaptureRequestBus::Events::CapturePassAttachmentWithCallback, m_passHierarchy,
|
||||
AZStd::string("Output"), GetCaptureCallback(), RPI::PassAttachmentReadbackOption::Output);
|
||||
return startedCapture;
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::EndCapture()
|
||||
{
|
||||
m_renderPipeline->RemoveFromRenderTick();
|
||||
}
|
||||
|
||||
bool CommonThumbnailRenderer::Installed() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::OnSystemTick()
|
||||
{
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::ExecuteQueuedEvents();
|
||||
}
|
||||
|
||||
void CommonThumbnailRenderer::GetCustomFeatureProcessors(AZStd::unordered_set<AZStd::string>& featureProcessors) const
|
||||
{
|
||||
featureProcessors.insert({
|
||||
"AZ::Render::TransformServiceFeatureProcessor",
|
||||
"AZ::Render::MeshFeatureProcessor",
|
||||
"AZ::Render::SimplePointLightFeatureProcessor",
|
||||
@@ -56,64 +370,12 @@ namespace AZ
|
||||
"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;
|
||||
"AZ::Render::SkyBoxFeatureProcessor" });
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
m_thumbnailInfoQueue.push({ thumbnailKey, thumbnailSize });
|
||||
}
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
|
||||
+88
-16
@@ -8,15 +8,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RPI.Public/Base.h>
|
||||
#include <Atom/RPI.Public/Pass/AttachmentReadback.h>
|
||||
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
|
||||
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
|
||||
#include <Atom/RPI.Reflect/System/AnyAsset.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Thumbnails/ThumbnailFeatureProcessorProviderBus.h>
|
||||
#include <AzFramework/Entity/GameEntityContextComponent.h>
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererContext.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
|
||||
#include <Thumbnails/Thumbnail.h>
|
||||
|
||||
#include <AtomLyIntegration/CommonFeatures/Thumbnails/ThumbnailFeatureProcessorProviderBus.h>
|
||||
namespace AzFramework
|
||||
{
|
||||
class Scene;
|
||||
}
|
||||
|
||||
// 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 <QPixmap>
|
||||
@@ -32,10 +41,9 @@ namespace AZ
|
||||
|
||||
//! Provides custom rendering of material and model thumbnails
|
||||
class CommonThumbnailRenderer
|
||||
: public ThumbnailRendererContext
|
||||
, private AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler
|
||||
, private SystemTickBus::Handler
|
||||
, private ThumbnailFeatureProcessorProviderBus::Handler
|
||||
: public AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::MultiHandler
|
||||
, public SystemTickBus::Handler
|
||||
, public ThumbnailFeatureProcessorProviderBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CommonThumbnailRenderer, AZ::SystemAllocator, 0)
|
||||
@@ -43,10 +51,33 @@ namespace AZ
|
||||
CommonThumbnailRenderer();
|
||||
~CommonThumbnailRenderer();
|
||||
|
||||
//! ThumbnailRendererContext overrides...
|
||||
void SetStep(Step step) override;
|
||||
Step GetStep() const override;
|
||||
AZStd::shared_ptr<ThumbnailRendererData> GetData() const override;
|
||||
enum class Step : AZ::s8
|
||||
{
|
||||
None,
|
||||
FindThumbnailToRender,
|
||||
WaitForAssetsToLoad,
|
||||
Capture
|
||||
};
|
||||
|
||||
void SetStep(Step step);
|
||||
Step GetStep() const;
|
||||
|
||||
void SelectThumbnail();
|
||||
void CancelThumbnail();
|
||||
void CompleteThumbnail();
|
||||
|
||||
void LoadAssets();
|
||||
void UpdateLoadAssets();
|
||||
void CancelLoadAssets();
|
||||
|
||||
void UpdateScene();
|
||||
void UpdateModel();
|
||||
void UpdateLighting();
|
||||
void UpdateCamera();
|
||||
|
||||
RPI::AttachmentReadback::CallbackFunction GetCaptureCallback();
|
||||
bool StartCapture();
|
||||
void EndCapture();
|
||||
|
||||
private:
|
||||
//! ThumbnailerRendererRequestsBus::Handler interface overrides...
|
||||
@@ -57,12 +88,53 @@ namespace AZ
|
||||
void OnSystemTick() override;
|
||||
|
||||
//! Render::ThumbnailFeatureProcessorProviderBus::Handler interface overrides...
|
||||
const AZStd::vector<AZStd::string>& GetCustomFeatureProcessors() const override;
|
||||
void GetCustomFeatureProcessors(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 = Constants::HalfPi;
|
||||
static constexpr float CameraRotationAngle = Constants::QuarterPi / 2.0f;
|
||||
|
||||
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;
|
||||
RPI::ViewPtr m_view;
|
||||
AZStd::vector<AZStd::string> m_passHierarchy;
|
||||
AZStd::unique_ptr<AzFramework::EntityContext> m_entityContext;
|
||||
|
||||
//! Incoming thumbnail requests are appended to this queue and processed one at a time in OnTick function.
|
||||
struct ThumbnailInfo
|
||||
{
|
||||
AzToolsFramework::Thumbnailer::SharedThumbnailKey m_key;
|
||||
int m_size = 512;
|
||||
};
|
||||
AZStd::queue<ThumbnailInfo> m_thumbnailInfoQueue;
|
||||
ThumbnailInfo m_currentThubnailInfo;
|
||||
|
||||
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;
|
||||
Step m_currentStep = CommonThumbnailRenderer::Step::None;
|
||||
|
||||
static constexpr const char* DefaultLightingPresetPath = "lightingpresets/thumbnail.lightingpreset.azasset";
|
||||
const Data::AssetId DefaultLightingPresetAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultLightingPresetPath);
|
||||
Data::Asset<RPI::AnyAsset> m_defaultLightingPresetAsset;
|
||||
Data::Asset<RPI::AnyAsset> m_lightingPresetAsset;
|
||||
|
||||
//! Model asset about to be rendered
|
||||
static constexpr const char* DefaultModelPath = "models/sphere.azmodel";
|
||||
const Data::AssetId DefaultModelAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultModelPath);
|
||||
Data::Asset<RPI::ModelAsset> m_defaultModelAsset;
|
||||
Data::Asset<RPI::ModelAsset> m_modelAsset;
|
||||
|
||||
//! Material asset about to be rendered
|
||||
static constexpr const char* DefaultMaterialPath = "materials/basic_grey.azmaterial";
|
||||
const Data::AssetId DefaultMaterialAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultMaterialPath);
|
||||
Data::Asset<RPI::MaterialAsset> m_defaultMaterialAsset;
|
||||
Data::Asset<RPI::MaterialAsset> m_materialAsset;
|
||||
|
||||
Entity* m_modelEntity = nullptr;
|
||||
};
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
|
||||
-42
@@ -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
|
||||
-70
@@ -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
|
||||
+12
-85
@@ -6,19 +6,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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/CommonThumbnailRenderer.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.h>
|
||||
#include <AzCore/Math/MatrixUtils.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -26,104 +15,42 @@ namespace AZ
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
CaptureStep::CaptureStep(ThumbnailRendererContext* context)
|
||||
: ThumbnailRendererStep(context)
|
||||
CaptureStep::CaptureStep(CommonThumbnailRenderer* renderer)
|
||||
: ThumbnailRendererStep(renderer)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
m_renderer->UpdateScene();
|
||||
TickBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void CaptureStep::Stop()
|
||||
{
|
||||
m_context->GetData()->m_renderPipeline->RemoveFromRenderTick();
|
||||
m_renderer->EndCapture();
|
||||
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)
|
||||
if (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)
|
||||
if (m_renderer->StartCapture())
|
||||
{
|
||||
m_readyToCapture = false;
|
||||
Render::FrameCaptureNotificationBus::Handler::BusConnect();
|
||||
TickBus::Handler::BusDisconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureStep::OnCaptureFinished([[maybe_unused]] Render::FrameCaptureResult result, [[maybe_unused]] const AZStd::string& info)
|
||||
void CaptureStep::OnCaptureFinished(
|
||||
[[maybe_unused]] Render::FrameCaptureResult result, [[maybe_unused]] const AZStd::string& info)
|
||||
{
|
||||
m_context->SetStep(Step::FindThumbnailToRender);
|
||||
m_renderer->CompleteThumbnail();
|
||||
}
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
|
||||
+1
-10
@@ -25,27 +25,18 @@ namespace AZ
|
||||
, private Render::FrameCaptureNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
CaptureStep(ThumbnailRendererContext* context);
|
||||
CaptureStep(CommonThumbnailRenderer* renderer);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
+4
-44
@@ -6,11 +6,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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/CommonThumbnailRenderer.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererSteps/FindThumbnailToRenderStep.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -19,8 +15,8 @@ namespace AZ
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
FindThumbnailToRenderStep::FindThumbnailToRenderStep(ThumbnailRendererContext* context)
|
||||
: ThumbnailRendererStep(context)
|
||||
FindThumbnailToRenderStep::FindThumbnailToRenderStep(CommonThumbnailRenderer* renderer)
|
||||
: ThumbnailRendererStep(renderer)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -36,43 +32,7 @@ namespace AZ
|
||||
|
||||
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);
|
||||
}
|
||||
m_renderer->SelectThumbnail();
|
||||
}
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
|
||||
+1
-3
@@ -22,7 +22,7 @@ namespace AZ
|
||||
, private TickBus::Handler
|
||||
{
|
||||
public:
|
||||
FindThumbnailToRenderStep(ThumbnailRendererContext* context);
|
||||
FindThumbnailToRenderStep(CommonThumbnailRenderer* renderer);
|
||||
|
||||
void Start() override;
|
||||
void Stop() override;
|
||||
@@ -31,8 +31,6 @@ namespace AZ
|
||||
|
||||
//! AZ::TickBus::Handler interface overrides...
|
||||
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
|
||||
|
||||
void PickNextThumbnail();
|
||||
};
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
|
||||
-191
@@ -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
|
||||
-37
@@ -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
|
||||
|
||||
-57
@@ -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
|
||||
-30
@@ -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
|
||||
|
||||
+3
-3
@@ -14,13 +14,13 @@ namespace AZ
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
class ThumbnailRendererContext;
|
||||
class CommonThumbnailRenderer;
|
||||
|
||||
//! ThumbnailRendererStep decouples CommonThumbnailRenderer logic into easy-to-understand and debug pieces
|
||||
class ThumbnailRendererStep
|
||||
{
|
||||
public:
|
||||
explicit ThumbnailRendererStep(ThumbnailRendererContext* context) : m_context(context) {}
|
||||
explicit ThumbnailRendererStep(CommonThumbnailRenderer* renderer) : m_renderer(renderer) {}
|
||||
virtual ~ThumbnailRendererStep() = default;
|
||||
|
||||
//! Start is called when step begins execution
|
||||
@@ -29,7 +29,7 @@ namespace AZ
|
||||
virtual void Stop() {}
|
||||
|
||||
protected:
|
||||
ThumbnailRendererContext* m_context;
|
||||
CommonThumbnailRenderer* m_renderer;
|
||||
};
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
|
||||
+12
-62
@@ -7,9 +7,7 @@
|
||||
*/
|
||||
|
||||
#include "Thumbnails/ThumbnailerBus.h"
|
||||
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererData.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererContext.h>
|
||||
#include <Thumbnails/Rendering/CommonThumbnailRenderer.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererSteps/WaitForAssetsToLoadStep.h>
|
||||
|
||||
@@ -19,81 +17,33 @@ namespace AZ
|
||||
{
|
||||
namespace Thumbnails
|
||||
{
|
||||
WaitForAssetsToLoadStep::WaitForAssetsToLoadStep(ThumbnailRendererContext* context)
|
||||
: ThumbnailRendererStep(context)
|
||||
WaitForAssetsToLoadStep::WaitForAssetsToLoadStep(CommonThumbnailRenderer* renderer)
|
||||
: ThumbnailRendererStep(renderer)
|
||||
{
|
||||
}
|
||||
|
||||
void WaitForAssetsToLoadStep::Start()
|
||||
{
|
||||
LoadNextAsset();
|
||||
m_renderer->LoadAssets();
|
||||
m_timeRemainingS = TimeOutS;
|
||||
TickBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
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)
|
||||
if (m_timeRemainingS > 0.0f)
|
||||
{
|
||||
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);
|
||||
m_renderer->UpdateLoadAssets();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_renderer->CancelLoadAssets();
|
||||
}
|
||||
}
|
||||
} // namespace Thumbnails
|
||||
|
||||
+3
-13
@@ -8,7 +8,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <Thumbnails/Rendering/ThumbnailRendererSteps/ThumbnailRendererStep.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -20,29 +19,20 @@ namespace AZ
|
||||
//! 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);
|
||||
WaitForAssetsToLoadStep(CommonThumbnailRenderer* renderer);
|
||||
|
||||
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;
|
||||
static constexpr float TimeOutS = 5.0f;
|
||||
float m_timeRemainingS = TimeOutS;
|
||||
};
|
||||
} // namespace Thumbnails
|
||||
} // namespace LyIntegration
|
||||
|
||||
-6
@@ -104,19 +104,13 @@ set(FILES
|
||||
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/Scripting/EditorEntityReferenceComponent.cpp
|
||||
Source/Scripting/EditorEntityReferenceComponent.h
|
||||
Source/SurfaceData/EditorSurfaceDataMeshComponent.cpp
|
||||
|
||||
Reference in New Issue
Block a user