3
0

ImageThumbnailSystemComponent.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/Serialization/EditContext.h>
  9. #include <AzCore/Serialization/SerializeContext.h>
  10. #include <AzCore/Utils/Utils.h>
  11. #include <AzCore/Jobs/JobFunction.h>
  12. #include <AzFramework/Asset/AssetSystemBus.h>
  13. #include <AzFramework/StringFunc/StringFunc.h>
  14. #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
  15. #include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
  16. #include <AzToolsFramework/AssetBrowser/Thumbnails/ProductThumbnail.h>
  17. #include <AzToolsFramework/AssetBrowser/Thumbnails/SourceThumbnail.h>
  18. #include <ImageLoader/ImageLoaders.h>
  19. #include <Processing/ImageConvert.h>
  20. #include <Processing/ImageToProcess.h>
  21. #include <Thumbnail/ImageThumbnail.h>
  22. #include <Thumbnail/ImageThumbnailSystemComponent.h>
  23. #include <Processing/Utils.h>
  24. namespace ImageProcessingAtom
  25. {
  26. namespace Thumbnails
  27. {
  28. void ImageThumbnailSystemComponent::Reflect(AZ::ReflectContext* context)
  29. {
  30. if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
  31. {
  32. serialize->Class<ImageThumbnailSystemComponent, AZ::Component>()
  33. ->Version(0);
  34. if (AZ::EditContext* ec = serialize->GetEditContext())
  35. {
  36. ec->Class<ImageThumbnailSystemComponent>("ImageThumbnailSystemComponent", "System component for image thumbnails.")
  37. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  38. ->Attribute(AZ::Edit::Attributes::AutoExpand, true);
  39. }
  40. }
  41. }
  42. void ImageThumbnailSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  43. {
  44. provided.push_back(AZ_CRC_CE("ImageThumbnailSystem"));
  45. }
  46. void ImageThumbnailSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  47. {
  48. incompatible.push_back(AZ_CRC_CE("ImageThumbnailSystem"));
  49. }
  50. void ImageThumbnailSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  51. {
  52. required.push_back(AZ_CRC_CE("ThumbnailerService"));
  53. }
  54. void ImageThumbnailSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
  55. {
  56. AZ_UNUSED(dependent);
  57. }
  58. void ImageThumbnailSystemComponent::Activate()
  59. {
  60. AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect();
  61. AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::Handler::BusConnect(AZ::RPI::StreamingImageAsset::RTTI_Type());
  62. SetupThumbnails();
  63. }
  64. void ImageThumbnailSystemComponent::Deactivate()
  65. {
  66. TeardownThumbnails();
  67. AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::Handler::BusDisconnect();
  68. AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect();
  69. }
  70. void ImageThumbnailSystemComponent::SetupThumbnails()
  71. {
  72. using namespace AzToolsFramework::Thumbnailer;
  73. ThumbnailerRequestBus::Broadcast(&ThumbnailerRequests::RegisterThumbnailProvider, MAKE_TCACHE(Thumbnails::ImageThumbnailCache));
  74. m_imageAssetLoader.reset(aznew Utils::AsyncImageAssetLoader());
  75. }
  76. void ImageThumbnailSystemComponent::TeardownThumbnails()
  77. {
  78. using namespace AzToolsFramework::Thumbnailer;
  79. ThumbnailerRequestBus::Broadcast(
  80. &ThumbnailerRequests::UnregisterThumbnailProvider, Thumbnails::ImageThumbnailCache::ProviderName);
  81. m_imageAssetLoader.reset();
  82. }
  83. void ImageThumbnailSystemComponent::OnApplicationAboutToStop()
  84. {
  85. TeardownThumbnails();
  86. }
  87. bool ImageThumbnailSystemComponent::Installed() const
  88. {
  89. return true;
  90. }
  91. void ImageThumbnailSystemComponent::RenderThumbnail(
  92. AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize)
  93. {
  94. if (auto sourceKey = azrtti_cast<const AzToolsFramework::AssetBrowser::SourceThumbnailKey*>(thumbnailKey.data()))
  95. {
  96. bool foundIt = false;
  97. AZ::Data::AssetInfo assetInfo;
  98. AZStd::string watchFolder;
  99. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
  100. foundIt, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourceUUID, sourceKey->GetSourceUuid(),
  101. assetInfo, watchFolder);
  102. if (foundIt)
  103. {
  104. AZStd::string fullPath;
  105. AZ::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), fullPath);
  106. RenderThumbnailFromImage(thumbnailKey, thumbnailSize,
  107. [fullPath]() { return IImageObjectPtr(LoadImageFromFile(fullPath)); }
  108. );
  109. }
  110. }
  111. else if (auto productKey = azrtti_cast<const AzToolsFramework::AssetBrowser::ProductThumbnailKey*>(thumbnailKey.data()))
  112. {
  113. m_imageAssetLoader->QueueAsset(
  114. productKey->GetAssetId(),
  115. [this, thumbnailKey, thumbnailSize](const AZ::Data::Asset<AZ::RPI::StreamingImageAsset>& asset) {
  116. RenderThumbnailFromImage(thumbnailKey, thumbnailSize, [asset]() {
  117. return Utils::LoadImageFromImageAsset(asset);
  118. });
  119. });
  120. }
  121. else
  122. {
  123. AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
  124. thumbnailKey, &AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender);
  125. }
  126. }
  127. template<class MkImageFn>
  128. void ImageThumbnailSystemComponent::RenderThumbnailFromImage(
  129. AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize, MkImageFn mkPreviewImage) const
  130. {
  131. auto jobRunner = [mkPreviewImage, thumbnailKey, thumbnailSize]()
  132. {
  133. IImageObjectPtr previewImage = mkPreviewImage();
  134. if (!previewImage)
  135. {
  136. AZ::SystemTickBus::QueueFunction(
  137. [thumbnailKey]()
  138. {
  139. AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
  140. thumbnailKey, &AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender);
  141. });
  142. return;
  143. }
  144. ImageToProcess imageToProcess(previewImage);
  145. imageToProcess.ConvertFormat(ePixelFormat_R8G8B8A8);
  146. previewImage = imageToProcess.Get();
  147. AZ::u8* imageBuf = nullptr;
  148. AZ::u32 mip = 0;
  149. AZ::u32 pitch = 0;
  150. previewImage->GetImagePointer(mip, imageBuf, pitch);
  151. const AZ::u32 width = previewImage->GetWidth(mip);
  152. const AZ::u32 height = previewImage->GetHeight(mip);
  153. // Note that this image holds a non-owning pointer to the `previewImage' raw data buffer
  154. const QImage image(imageBuf, width, height, pitch, QImage::Format_RGBA8888);
  155. // Dispatch event on main thread
  156. AZ::SystemTickBus::QueueFunction(
  157. [thumbnailKey,
  158. pixmap = QPixmap::fromImage(
  159. image.scaled(QSize(thumbnailSize, thumbnailSize), Qt::KeepAspectRatio, Qt::SmoothTransformation))]()
  160. {
  161. AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
  162. thumbnailKey, &AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailRendered, pixmap);
  163. });
  164. };
  165. AZ::CreateJobFunction(jobRunner, true)->Start();
  166. }
  167. } // namespace Thumbnails
  168. } // namespace ImageProcessingAtom