From 592a8cad6d111a23baf6b2bd3fe79c9806e74e4a Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Fri, 25 Jun 2021 09:36:47 -0400 Subject: [PATCH] Don't block main thread to load data from file Signed-off-by: John --- .../Code/Source/Previewer/ImagePreviewer.cpp | 87 ++++++++++++++----- .../Code/Source/Previewer/ImagePreviewer.h | 15 ++++ 2 files changed, 81 insertions(+), 21 deletions(-) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Previewer/ImagePreviewer.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Previewer/ImagePreviewer.cpp index fcdc9cd0d3..3cdfb1d15c 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Previewer/ImagePreviewer.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Previewer/ImagePreviewer.cpp @@ -51,6 +51,12 @@ namespace ImageProcessingAtom ImagePreviewer::~ImagePreviewer() { + AZ::SystemTickBus::Handler::BusDisconnect(); + + if (m_createDisplayTextureResult.isRunning()) + { + m_createDisplayTextureResult.waitForFinished(); + } } void ImagePreviewer::Clear() const @@ -214,21 +220,30 @@ namespace ImageProcessingAtom m_ui->m_fileInfoCtrl->show(); m_fileinfo = QString::fromUtf8(product->GetName().c_str()); m_fileinfo += GetFileSize(product->GetRelativePath().c_str()); - - AZ::Data::Asset imageAsset = Utils::LoadImageAsset(product->GetAssetId()); - IImageObjectPtr image = Utils::LoadImageFromImageAsset(imageAsset); - if (image) + CreateAndDisplayTextureItemAsync( + [assetId = product->GetAssetId()] + () -> CreateDisplayTextureResult { - // Add product image info - AZStd::string productInfo; - GetImageInfoString(imageAsset, productInfo); + AZ::Data::Asset imageAsset = Utils::LoadImageAsset(assetId); + IImageObjectPtr image = Utils::LoadImageFromImageAsset(imageAsset); - m_fileinfo += QStringLiteral("\r\n"); - m_fileinfo += productInfo.c_str(); + if (image) + { + // Add product image info + AZStd::string productInfo; + GetImageInfoString(imageAsset, productInfo); - m_previewImageObject = ConvertImageForPreview(image); - } + QString fileInfo = QStringLiteral("\r\n"); + fileInfo += productInfo.c_str(); + + return { ConvertImageForPreview(image), fileInfo }; + } + else + { + return { nullptr, "" }; + } + }); DisplayTextureItem(); } @@ -239,19 +254,28 @@ namespace ImageProcessingAtom m_fileinfo = QString::fromUtf8(source->GetName().c_str()); m_fileinfo += GetFileSize(source->GetFullPath().c_str()); - IImageObjectPtr image = IImageObjectPtr(LoadImageFromFile(source->GetFullPath())); - - if (image) + CreateAndDisplayTextureItemAsync( + [fullPath = source->GetFullPath()] + () -> CreateDisplayTextureResult { - // Add source image info - AZStd::string sourceInfo; - GetImageInfoString(image, sourceInfo); + IImageObjectPtr image = IImageObjectPtr(LoadImageFromFile(fullPath)); - m_fileinfo += QStringLiteral("\r\n"); - m_fileinfo += sourceInfo.c_str(); + if (image) + { + // Add source image info + AZStd::string sourceInfo; + GetImageInfoString(image, sourceInfo); - m_previewImageObject = ConvertImageForPreview(image); - } + QString fileInfo = QStringLiteral("\r\n"); + fileInfo += sourceInfo.c_str(); + + return { ConvertImageForPreview(image), fileInfo }; + } + else + { + return { nullptr, "" }; + } + }); DisplayTextureItem(); } @@ -289,6 +313,27 @@ namespace ImageProcessingAtom updateGeometry(); } + template + void ImagePreviewer::CreateAndDisplayTextureItemAsync(CreateFn create) + { + AZ::SystemTickBus::Handler::BusConnect(); + m_createDisplayTextureResult = QtConcurrent::run(AZStd::move(create)); + } + + void ImagePreviewer::OnSystemTick() + { + if (m_createDisplayTextureResult.isFinished()) + { + CreateDisplayTextureResult result = m_createDisplayTextureResult.result(); + m_previewImageObject = AZStd::move(result.first); + m_fileinfo += result.second; + + AZ::SystemTickBus::Handler::BusDisconnect(); + + DisplayTextureItem(); + } + } + void ImagePreviewer::PreviewSubImage(uint32_t mip) { QImage previewImage = GetSubImagePreview(m_previewImageObject, mip); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Previewer/ImagePreviewer.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Previewer/ImagePreviewer.h index 3b487f3d95..9e7066c20c 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Previewer/ImagePreviewer.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Previewer/ImagePreviewer.h @@ -13,12 +13,15 @@ #if !defined(Q_MOC_RUN) #include +#include #include #include #include #include +#include +#include #endif namespace Ui @@ -42,6 +45,7 @@ namespace ImageProcessingAtom { class ImagePreviewer : public AzToolsFramework::AssetBrowser::Previewer + , private AZ::SystemTickBus::Handler { Q_OBJECT public: @@ -65,16 +69,27 @@ namespace ImageProcessingAtom QString GetFileSize(const char* path); void DisplayTextureItem(); + template + void CreateAndDisplayTextureItemAsync(CreateFn create); + void PreviewSubImage(uint32_t mip); // QLabel word wrap does not break long words such as filenames, so manual word wrap needed static QString WordWrap(const QString& string, int maxLength); + // SystemTickBus + void OnSystemTick() override; + QScopedPointer m_ui; QString m_fileinfo; QString m_name = "ImagePreviewer"; // Decompressed image in preview. Cache it so we can preview its sub images IImageObjectPtr m_previewImageObject; + + // Properties for tracking the status of an asynchronous request to display an asset browser entry + using CreateDisplayTextureResult = AZStd::pair; + + QFuture m_createDisplayTextureResult; }; }//namespace ImageProcessingAtom