Moved asynchronous image loading function to atom tools framework

Moved settings registry wrapper function to atom tools framework
Created registry settings with default values for preview configurations based on asset type
Changed lighting preset previews and thumbnails to use reflective material
Created registry settings for preset selection dialog borders, padding, sizes
Updated shared preview utility functions to compare against registered asset types instead of passing them in individually

Signed-off-by: Guthrie Adams <guthadam@amazon.com>
monroegm-disable-blank-issue-2
Guthrie Adams 4 years ago
parent 6dcbc64cd6
commit cb552256f8

@ -42,6 +42,7 @@ ly_add_target(
Gem::Atom_RHI.Reflect Gem::Atom_RHI.Reflect
Gem::Atom_Feature_Common.Static Gem::Atom_Feature_Common.Static
Gem::Atom_Bootstrap.Headers Gem::Atom_Bootstrap.Headers
Gem::ImageProcessingAtom.Headers
) )
ly_add_target( ly_add_target(
@ -60,6 +61,8 @@ ly_add_target(
BUILD_DEPENDENCIES BUILD_DEPENDENCIES
PRIVATE PRIVATE
Gem::AtomToolsFramework.Static Gem::AtomToolsFramework.Static
RUNTIME_DEPENDENCIES
Gem::ImageProcessingAtom.Editor
) )
################################################################################ ################################################################################

@ -8,8 +8,9 @@
#pragma once #pragma once
#include <AzCore/PlatformDef.h>
#include <AzCore/Asset/AssetManager.h> #include <AzCore/Asset/AssetManager.h>
#include <AzCore/PlatformDef.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzCore/std/containers/vector.h> #include <AzCore/std/containers/vector.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
@ -18,11 +19,24 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin
#include <QStringList> #include <QStringList>
AZ_POP_DISABLE_WARNING AZ_POP_DISABLE_WARNING
class QImage;
namespace AtomToolsFramework namespace AtomToolsFramework
{ {
template<typename T>
T GetSettingOrDefault(AZStd::string_view path, const T& defaultValue)
{
T result;
auto settingsRegistry = AZ::SettingsRegistry::Get();
return (settingsRegistry && settingsRegistry->Get(result, path)) ? result : defaultValue;
}
using LoadImageAsyncCallback = AZStd::function<void(const QImage&)>;
void LoadImageAsync(const AZStd::string& path, LoadImageAsyncCallback callback);
QFileInfo GetSaveFileInfo(const QString& initialPath); QFileInfo GetSaveFileInfo(const QString& initialPath);
QFileInfo GetOpenFileInfo(const AZStd::vector<AZ::Data::AssetType>& assetTypes); QFileInfo GetOpenFileInfo(const AZStd::vector<AZ::Data::AssetType>& assetTypes);
QFileInfo GetUniqueFileInfo(const QString& initialPath); QFileInfo GetUniqueFileInfo(const QString& initialPath);
QFileInfo GetDuplicationFileInfo(const QString& initialPath); QFileInfo GetDuplicationFileInfo(const QString& initialPath);
bool LaunchTool(const QString& baseName, const QString& extension, const QStringList& arguments); bool LaunchTool(const QString& baseName, const QString& extension, const QStringList& arguments);
} } // namespace AtomToolsFramework

@ -6,15 +6,18 @@
* *
*/ */
#include <Atom/ImageProcessing/ImageObject.h>
#include <Atom/ImageProcessing/ImageProcessingBus.h>
#include <AtomToolsFramework/Util/Util.h> #include <AtomToolsFramework/Util/Util.h>
#include <AzCore/IO/SystemFile.h> #include <AzCore/IO/SystemFile.h>
#include <AzCore/Jobs/JobFunction.h>
#include <AzCore/StringFunc/StringFunc.h> #include <AzCore/StringFunc/StringFunc.h>
#include <AzCore/Utils/Utils.h> #include <AzCore/Utils/Utils.h>
#include <AzFramework/API/ApplicationAPI.h> #include <AzFramework/API/ApplicationAPI.h>
#include <AzQtComponents/Components/Widgets/FileDialog.h> #include <AzQtComponents/Components/Widgets/FileDialog.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h> #include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h> #include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QApplication> #include <QApplication>
@ -24,6 +27,36 @@ AZ_POP_DISABLE_WARNING
namespace AtomToolsFramework namespace AtomToolsFramework
{ {
void LoadImageAsync(const AZStd::string& path, LoadImageAsyncCallback callback)
{
AZ::Job* job = AZ::CreateJobFunction(
[path, callback]()
{
ImageProcessingAtom::IImageObjectPtr imageObject;
ImageProcessingAtom::ImageProcessingRequestBus::BroadcastResult(
imageObject, &ImageProcessingAtom::ImageProcessingRequests::LoadImagePreview, path);
if (imageObject)
{
AZ::u8* imageBuf = nullptr;
AZ::u32 pitch = 0;
AZ::u32 mip = 0;
imageObject->GetImagePointer(mip, imageBuf, pitch);
const AZ::u32 width = imageObject->GetWidth(mip);
const AZ::u32 height = imageObject->GetHeight(mip);
QImage image(imageBuf, width, height, pitch, QImage::Format_RGBA8888);
if (callback)
{
callback(image);
}
}
},
true);
job->Start();
}
QFileInfo GetSaveFileInfo(const QString& initialPath) QFileInfo GetSaveFileInfo(const QString& initialPath)
{ {
const QFileInfo initialFileInfo(initialPath); const QFileInfo initialFileInfo(initialPath);

@ -60,7 +60,6 @@ ly_add_target(
Gem::AtomToolsFramework.Editor Gem::AtomToolsFramework.Editor
Gem::Atom_RPI.Public Gem::Atom_RPI.Public
Gem::Atom_Feature_Common.Public Gem::Atom_Feature_Common.Public
Gem::ImageProcessingAtom.Headers
) )
ly_add_target( ly_add_target(
@ -113,7 +112,6 @@ ly_add_target(
RUNTIME_DEPENDENCIES RUNTIME_DEPENDENCIES
Gem::AtomToolsFramework.Editor Gem::AtomToolsFramework.Editor
Gem::EditorPythonBindings.Editor Gem::EditorPythonBindings.Editor
Gem::ImageProcessingAtom.Editor
) )
ly_set_gem_variant_to_load(TARGETS MaterialEditor VARIANTS Tools) ly_set_gem_variant_to_load(TARGETS MaterialEditor VARIANTS Tools)

@ -6,61 +6,26 @@
* *
*/ */
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Common/JsonUtils.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <Atom/RPI.Reflect/System/AnyAsset.h>
#include <Atom/Viewport/MaterialViewportNotificationBus.h>
#include <Atom/Viewport/MaterialViewportSettings.h>
#include <AzCore/Component/TickBus.h> #include <AzCore/Component/TickBus.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/RTTI/BehaviorContext.h> #include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Jobs/JobFunction.h> #include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/Asset/AssetSystemBus.h> #include <AzFramework/Asset/AssetSystemBus.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzFramework/IO/LocalFileIO.h> #include <AzFramework/IO/LocalFileIO.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h> #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h> #include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <Viewport/MaterialViewportComponent.h> #include <Viewport/MaterialViewportComponent.h>
#include <Atom/Viewport/MaterialViewportNotificationBus.h>
#include <Atom/Viewport/MaterialViewportSettings.h>
#include <Atom/ImageProcessing/ImageObject.h>
#include <Atom/ImageProcessing/ImageProcessingBus.h>
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <Atom/RPI.Reflect/System/AnyAsset.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Common/JsonUtils.h>
namespace MaterialEditor namespace MaterialEditor
{ {
using LoadImageAsyncCallback = AZStd::function<void(const QImage&)>;
void LoadImageAsync(const AZStd::string& path, LoadImageAsyncCallback callback)
{
AZ::Job* job = AZ::CreateJobFunction([path, callback]() {
ImageProcessingAtom::IImageObjectPtr imageObject;
ImageProcessingAtom::ImageProcessingRequestBus::BroadcastResult(imageObject, &ImageProcessingAtom::ImageProcessingRequests::LoadImagePreview, path);
if (imageObject)
{
AZ::u8* imageBuf = nullptr;
AZ::u32 pitch = 0;
AZ::u32 mip = 0;
imageObject->GetImagePointer(mip, imageBuf, pitch);
const AZ::u32 width = imageObject->GetWidth(mip);
const AZ::u32 height = imageObject->GetHeight(mip);
QImage image(imageBuf, width, height, pitch, QImage::Format_RGBA8888);
if (callback)
{
callback(image);
}
}
}, true);
job->Start();
}
MaterialViewportComponent::MaterialViewportComponent() MaterialViewportComponent::MaterialViewportComponent()
{ {
} }

@ -28,13 +28,16 @@ namespace MaterialEditor
MaterialViewportRequestBus::BroadcastResult(presets, &MaterialViewportRequestBus::Events::GetLightingPresets); MaterialViewportRequestBus::BroadcastResult(presets, &MaterialViewportRequestBus::Events::GetLightingPresets);
AZStd::sort(presets.begin(), presets.end(), [](const auto& a, const auto& b) { return a->m_displayName < b->m_displayName; }); AZStd::sort(presets.begin(), presets.end(), [](const auto& a, const auto& b) { return a->m_displayName < b->m_displayName; });
const int itemSize = aznumeric_cast<int>(
AtomToolsFramework::GetSettingOrDefault<AZ::u64>("/O3DE/Atom/MaterialEditor/PresetBrowserDialog/LightingItemSize", 180));
QListWidgetItem* selectedItem = nullptr; QListWidgetItem* selectedItem = nullptr;
for (const auto& preset : presets) for (const auto& preset : presets)
{ {
AZStd::string path; AZStd::string path;
MaterialViewportRequestBus::BroadcastResult(path, &MaterialViewportRequestBus::Events::GetLightingPresetLastSavePath, preset); MaterialViewportRequestBus::BroadcastResult(path, &MaterialViewportRequestBus::Events::GetLightingPresetLastSavePath, preset);
QListWidgetItem* item = QListWidgetItem* item = CreateListItem(
CreateListItem(preset->m_displayName.c_str(), AZ::RPI::AssetUtils::MakeAssetId(path, 0).GetValue(), QSize(180, 180)); preset->m_displayName.c_str(), AZ::RPI::AssetUtils::MakeAssetId(path, 0).GetValue(), QSize(itemSize, itemSize));
m_listItemToPresetMap[item] = preset; m_listItemToPresetMap[item] = preset;

@ -27,10 +27,13 @@ namespace MaterialEditor
MaterialViewportRequestBus::BroadcastResult(presets, &MaterialViewportRequestBus::Events::GetModelPresets); MaterialViewportRequestBus::BroadcastResult(presets, &MaterialViewportRequestBus::Events::GetModelPresets);
AZStd::sort(presets.begin(), presets.end(), [](const auto& a, const auto& b) { return a->m_displayName < b->m_displayName; }); AZStd::sort(presets.begin(), presets.end(), [](const auto& a, const auto& b) { return a->m_displayName < b->m_displayName; });
const int itemSize = aznumeric_cast<int>(
AtomToolsFramework::GetSettingOrDefault<AZ::u64>("/O3DE/Atom/MaterialEditor/PresetBrowserDialog/ModelItemSize", 90));
QListWidgetItem* selectedItem = nullptr; QListWidgetItem* selectedItem = nullptr;
for (const auto& preset : presets) for (const auto& preset : presets)
{ {
QListWidgetItem* item = CreateListItem(preset->m_displayName.c_str(), preset->m_modelAsset.GetId(), QSize(90, 90)); QListWidgetItem* item = CreateListItem(preset->m_displayName.c_str(), preset->m_modelAsset.GetId(), QSize(itemSize, itemSize));
m_listItemToPresetMap[item] = preset; m_listItemToPresetMap[item] = preset;

@ -51,13 +51,21 @@ namespace MaterialEditor
QListWidgetItem* PresetBrowserDialog::CreateListItem(const QString& title, const AZ::Data::AssetId& assetId, const QSize& size) QListWidgetItem* PresetBrowserDialog::CreateListItem(const QString& title, const AZ::Data::AssetId& assetId, const QSize& size)
{ {
const int itemBorder = aznumeric_cast<int>(
AtomToolsFramework::GetSettingOrDefault<AZ::u64>("/O3DE/Atom/MaterialEditor/PresetBrowserDialog/ItemBorder", 4));
const int itemSpacing = aznumeric_cast<int>(
AtomToolsFramework::GetSettingOrDefault<AZ::u64>("/O3DE/Atom/MaterialEditor/PresetBrowserDialog/ItemSpacing", 10));
const int headerHeight = aznumeric_cast<int>(
AtomToolsFramework::GetSettingOrDefault<AZ::u64>("/O3DE/Atom/MaterialEditor/PresetBrowserDialog/HeaderHeight", 15));
const QSize gridSize = m_ui->m_presetList->gridSize(); const QSize gridSize = m_ui->m_presetList->gridSize();
m_ui->m_presetList->setGridSize( m_ui->m_presetList->setGridSize(QSize(
QSize(AZStd::max(gridSize.width(), size.width() + 10), AZStd::max(gridSize.height(), size.height() + 10 + 15))); AZStd::max(gridSize.width(), size.width() + itemSpacing),
AZStd::max(gridSize.height(), size.height() + itemSpacing + headerHeight)));
QListWidgetItem* item = new QListWidgetItem(m_ui->m_presetList); QListWidgetItem* item = new QListWidgetItem(m_ui->m_presetList);
item->setData(Qt::UserRole, title); item->setData(Qt::UserRole, title);
item->setSizeHint(size + QSize(4, 19)); item->setSizeHint(size + QSize(itemBorder, itemBorder + headerHeight));
m_ui->m_presetList->addItem(item); m_ui->m_presetList->addItem(item);
QWidget* itemWidget = new QWidget(m_ui->m_presetList); QWidget* itemWidget = new QWidget(m_ui->m_presetList);
@ -67,7 +75,7 @@ namespace MaterialEditor
AzQtComponents::ElidingLabel* header = new AzQtComponents::ElidingLabel(itemWidget); AzQtComponents::ElidingLabel* header = new AzQtComponents::ElidingLabel(itemWidget);
header->setText(title); header->setText(title);
header->setFixedSize(QSize(size.width(), 15)); header->setFixedSize(QSize(size.width(), headerHeight));
header->setMargin(0); header->setMargin(0);
header->setStyleSheet("background-color: rgb(35, 35, 35)"); header->setStyleSheet("background-color: rgb(35, 35, 35)");
AzQtComponents::Text::addPrimaryStyle(header); AzQtComponents::Text::addPrimaryStyle(header);

@ -51,7 +51,7 @@ namespace AZ
static constexpr float NearDist = 0.001f; static constexpr float NearDist = 0.001f;
static constexpr float FarDist = 100.0f; static constexpr float FarDist = 100.0f;
static constexpr float FieldOfView = Constants::HalfPi; static constexpr float FieldOfView = Constants::HalfPi;
static constexpr float CameraRotationAngle = Constants::HalfPi / 6.0f; static constexpr float CameraRotationAngle = Constants::QuarterPi / 3.0f;
RPI::ScenePtr m_scene; RPI::ScenePtr m_scene;
RPI::ViewPtr m_view; RPI::ViewPtr m_view;

@ -9,9 +9,11 @@
#include <API/EditorAssetSystemAPI.h> #include <API/EditorAssetSystemAPI.h>
#include <AssetBrowser/Thumbnails/ProductThumbnail.h> #include <AssetBrowser/Thumbnails/ProductThumbnail.h>
#include <AssetBrowser/Thumbnails/SourceThumbnail.h> #include <AssetBrowser/Thumbnails/SourceThumbnail.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h> #include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <Atom/RPI.Reflect/Model/ModelAsset.h> #include <Atom/RPI.Reflect/Model/ModelAsset.h>
#include <Atom/RPI.Reflect/System/AnyAsset.h> #include <Atom/RPI.Reflect/System/AnyAsset.h>
#include <AtomToolsFramework/Util/Util.h>
#include <SharedPreview/SharedPreviewUtils.h> #include <SharedPreview/SharedPreviewUtils.h>
namespace AZ namespace AZ
@ -20,45 +22,64 @@ namespace AZ
{ {
namespace SharedPreviewUtils namespace SharedPreviewUtils
{ {
Data::AssetId GetAssetId( AZStd::unordered_set<AZ::Uuid> GetSupportedAssetTypes()
AzToolsFramework::Thumbnailer::SharedThumbnailKey key, {
const Data::AssetType& assetType, return { RPI::AnyAsset::RTTI_Type(), RPI::MaterialAsset::RTTI_Type(), RPI::ModelAsset::RTTI_Type() };
const Data::AssetId& defaultAssetId) }
bool IsSupportedAssetType(AzToolsFramework::Thumbnailer::SharedThumbnailKey key)
{ {
return GetSupportedAssetInfo(key).m_assetId.IsValid();
}
AZ::Data::AssetInfo GetSupportedAssetInfo(AzToolsFramework::Thumbnailer::SharedThumbnailKey key)
{
const auto& supportedTypeIds = GetSupportedAssetTypes();
// if it's a source thumbnail key, find first product with a matching asset type // 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()); auto sourceKey = azrtti_cast<const AzToolsFramework::AssetBrowser::SourceThumbnailKey*>(key.data());
if (sourceKey) if (sourceKey)
{ {
bool foundIt = false; bool foundIt = false;
AZStd::vector<Data::AssetInfo> productsAssetInfo; AZStd::vector<AZ::Data::AssetInfo> productsAssetInfo;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult( AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
foundIt, &AzToolsFramework::AssetSystemRequestBus::Events::GetAssetsProducedBySourceUUID, foundIt, &AzToolsFramework::AssetSystemRequestBus::Events::GetAssetsProducedBySourceUUID,
sourceKey->GetSourceUuid(), productsAssetInfo); sourceKey->GetSourceUuid(), productsAssetInfo);
if (!foundIt)
{ for (const auto& assetInfo : productsAssetInfo)
return defaultAssetId;
}
auto assetInfoIt = AZStd::find_if(
productsAssetInfo.begin(), productsAssetInfo.end(),
[&assetType](const Data::AssetInfo& assetInfo)
{ {
return assetInfo.m_assetType == assetType; if (supportedTypeIds.find(assetInfo.m_assetType) != supportedTypeIds.end())
});
if (assetInfoIt == productsAssetInfo.end())
{ {
return defaultAssetId; return assetInfo;
} }
}
return assetInfoIt->m_assetId; return AZ::Data::AssetInfo();
} }
// if it's a product thumbnail key just return its assetId // if it's a product thumbnail key just return its assetId
AZ::Data::AssetInfo assetInfo;
auto productKey = azrtti_cast<const AzToolsFramework::AssetBrowser::ProductThumbnailKey*>(key.data()); auto productKey = azrtti_cast<const AzToolsFramework::AssetBrowser::ProductThumbnailKey*>(key.data());
if (productKey && productKey->GetAssetType() == assetType) if (productKey && supportedTypeIds.find(productKey->GetAssetType()) != supportedTypeIds.end())
{ {
return productKey->GetAssetId(); AZ::Data::AssetCatalogRequestBus::BroadcastResult(
assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, productKey->GetAssetId());
} }
return defaultAssetId; return assetInfo;
}
AZ::Data::AssetId GetSupportedAssetId(AzToolsFramework::Thumbnailer::SharedThumbnailKey key, const AZ::Data::AssetId& defaultAssetId)
{
const AZ::Data::AssetInfo assetInfo = GetSupportedAssetInfo(key);
return assetInfo.m_assetId.IsValid() ? assetInfo.m_assetId : defaultAssetId;
}
AZ::Data::AssetId GetAssetIdForProductPath(const AZStd::string_view productPath)
{
if (!productPath.empty())
{
return AZ::RPI::AssetUtils::GetAssetIdForProductPath(productPath.data());
}
return AZ::Data::AssetId();
} }
QString WordWrap(const QString& string, int maxLength) QString WordWrap(const QString& string, int maxLength)
@ -85,32 +106,6 @@ namespace AZ
} }
return result; return result;
} }
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 SharedPreviewUtils
} // namespace LyIntegration } // namespace LyIntegration
} // namespace AZ } // namespace AZ

@ -8,9 +8,9 @@
#pragma once #pragma once
#include <AzCore/Asset/AssetCommon.h>
#if !defined(Q_MOC_RUN) #if !defined(Q_MOC_RUN)
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzToolsFramework/Thumbnails/Thumbnail.h> #include <AzToolsFramework/Thumbnails/Thumbnail.h>
#endif #endif
@ -20,21 +20,25 @@ namespace AZ
{ {
namespace SharedPreviewUtils 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,
const Data::AssetId& defaultAssetId = {});
//! Word wrap function for previewer QLabel, since by default it does not break long words such as filenames, so manual word
//! wrap needed
QString WordWrap(const QString& string, int maxLength);
//! Get the set of all asset types supported by the shared preview //! Get the set of all asset types supported by the shared preview
AZStd::unordered_set<AZ::Uuid> GetSupportedAssetTypes(); AZStd::unordered_set<AZ::Uuid> GetSupportedAssetTypes();
//! Determine if a thumbnail key has an asset supported by the shared preview //! Determine if a thumbnail key has an asset supported by the shared preview
bool IsSupportedAssetType(AzToolsFramework::Thumbnailer::SharedThumbnailKey key); bool IsSupportedAssetType(AzToolsFramework::Thumbnailer::SharedThumbnailKey key);
//! Get assetInfo of source or product thumbnail key if asset type is supported by the shared preview
AZ::Data::AssetInfo GetSupportedAssetInfo(AzToolsFramework::Thumbnailer::SharedThumbnailKey key);
//! Get assetId of source or product thumbnail key if asset type is supported by the shared preview
AZ::Data::AssetId GetSupportedAssetId(
AzToolsFramework::Thumbnailer::SharedThumbnailKey key, const AZ::Data::AssetId& defaultAssetId = {});
//! Wraps AZ::RPI::AssetUtils::GetAssetIdForProductPath to handle empty productPath
AZ::Data::AssetId GetAssetIdForProductPath(const AZStd::string_view productPath);
//! Inserts new line characters into a string whenever the maximum number of characters per line is exceeded
QString WordWrap(const QString& string, int maxLength);
} // namespace SharedPreviewUtils } // namespace SharedPreviewUtils
} // namespace LyIntegration } // namespace LyIntegration
} // namespace AZ } // namespace AZ

@ -22,19 +22,14 @@ namespace AZ
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
SharedThumbnail::SharedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key) SharedThumbnail::SharedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey key)
: Thumbnail(key) : Thumbnail(key)
, m_assetInfo(SharedPreviewUtils::GetSupportedAssetInfo(key))
{ {
for (const AZ::Uuid& typeId : SharedPreviewUtils::GetSupportedAssetTypes()) if (m_assetInfo.m_assetId.IsValid())
{ {
const AZ::Data::AssetId& assetId = SharedPreviewUtils::GetAssetId(key, typeId);
if (assetId.IsValid())
{
m_assetId = assetId;
m_typeId = typeId;
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler::BusConnect(key); AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler::BusConnect(key);
AzFramework::AssetCatalogEventBus::Handler::BusConnect(); AzFramework::AssetCatalogEventBus::Handler::BusConnect();
return; return;
} }
}
AZ_Error("SharedThumbnail", false, "Failed to find matching assetId for the thumbnailKey."); AZ_Error("SharedThumbnail", false, "Failed to find matching assetId for the thumbnailKey.");
m_state = State::Failed; m_state = State::Failed;
@ -43,7 +38,9 @@ namespace AZ
void SharedThumbnail::LoadThread() void SharedThumbnail::LoadThread()
{ {
AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::QueueEvent( AzToolsFramework::Thumbnailer::ThumbnailerRendererRequestBus::QueueEvent(
m_typeId, &AzToolsFramework::Thumbnailer::ThumbnailerRendererRequests::RenderThumbnail, m_key, SharedThumbnailSize); m_assetInfo.m_assetType, &AzToolsFramework::Thumbnailer::ThumbnailerRendererRequests::RenderThumbnail, m_key,
SharedThumbnailSize);
// wait for response from thumbnail renderer // wait for response from thumbnail renderer
m_renderWait.acquire(); m_renderWait.acquire();
} }
@ -68,7 +65,7 @@ namespace AZ
void SharedThumbnail::OnCatalogAssetChanged([[maybe_unused]] const AZ::Data::AssetId& assetId) void SharedThumbnail::OnCatalogAssetChanged([[maybe_unused]] const AZ::Data::AssetId& assetId)
{ {
if (m_assetId == assetId && m_state == State::Ready) if (m_assetInfo.m_assetId == assetId && m_state == State::Ready)
{ {
m_state = State::Unloaded; m_state = State::Unloaded;
Load(); Load();

@ -43,8 +43,7 @@ namespace AZ
void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override; void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override;
AZStd::binary_semaphore m_renderWait; AZStd::binary_semaphore m_renderWait;
Data::AssetId m_assetId; Data::AssetInfo m_assetInfo;
AZ::Uuid m_typeId;
}; };
//! Cache configuration for shared thumbnails //! Cache configuration for shared thumbnails

@ -8,6 +8,7 @@
#include <AtomToolsFramework/PreviewRenderer/PreviewRendererCaptureRequest.h> #include <AtomToolsFramework/PreviewRenderer/PreviewRendererCaptureRequest.h>
#include <AtomToolsFramework/PreviewRenderer/PreviewRendererInterface.h> #include <AtomToolsFramework/PreviewRenderer/PreviewRendererInterface.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h> #include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h> #include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
#include <SharedPreview/SharedPreviewContent.h> #include <SharedPreview/SharedPreviewContent.h>
@ -20,9 +21,9 @@ namespace AZ
{ {
SharedThumbnailRenderer::SharedThumbnailRenderer() SharedThumbnailRenderer::SharedThumbnailRenderer()
{ {
m_defaultModelAsset.Create(DefaultModelAssetId, true); m_defaultModelAsset.Create(SharedPreviewUtils::GetAssetIdForProductPath(DefaultModelPath), true);
m_defaultMaterialAsset.Create(DefaultMaterialAssetId, true); m_defaultMaterialAsset.Create(SharedPreviewUtils::GetAssetIdForProductPath(DefaultMaterialPath), true);
m_defaultLightingPresetAsset.Create(DefaultLightingPresetAssetId, true); m_defaultLightingPresetAsset.Create(SharedPreviewUtils::GetAssetIdForProductPath(DefaultLightingPresetPath), true);
for (const AZ::Uuid& typeId : SharedPreviewUtils::GetSupportedAssetTypes()) for (const AZ::Uuid& typeId : SharedPreviewUtils::GetSupportedAssetTypes())
{ {
@ -37,17 +38,66 @@ namespace AZ
SystemTickBus::Handler::BusDisconnect(); SystemTickBus::Handler::BusDisconnect();
} }
SharedThumbnailRenderer::ThumbnailConfig SharedThumbnailRenderer::GetThumbnailConfig(
AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey)
{
ThumbnailConfig thumbnailConfig;
const auto assetInfo = SharedPreviewUtils::GetSupportedAssetInfo(thumbnailKey);
if (assetInfo.m_assetType == RPI::ModelAsset::RTTI_Type())
{
static constexpr const char* MaterialAssetPathSetting =
"/O3DE/Atom/CommonFeature/SharedPreview/ModelAssetType/MaterialAssetPath";
static constexpr const char* LightingAssetPathSetting =
"/O3DE/Atom/CommonFeature/SharedPreview/ModelAssetType/LightingAssetPath";
thumbnailConfig.m_modelId = assetInfo.m_assetId;
thumbnailConfig.m_materialId = SharedPreviewUtils::GetAssetIdForProductPath(
AtomToolsFramework::GetSettingOrDefault<AZStd::string>(MaterialAssetPathSetting, DefaultMaterialPath));
thumbnailConfig.m_lightingId = SharedPreviewUtils::GetAssetIdForProductPath(
AtomToolsFramework::GetSettingOrDefault<AZStd::string>(LightingAssetPathSetting, DefaultLightingPresetPath));
}
else if (assetInfo.m_assetType == RPI::MaterialAsset::RTTI_Type())
{
static constexpr const char* ModelAssetPathSetting =
"/O3DE/Atom/CommonFeature/SharedPreview/MaterialAssetType/ModelAssetPath";
static constexpr const char* LightingAssetPathSetting =
"/O3DE/Atom/CommonFeature/SharedPreview/MaterialAssetType/LightingAssetPath";
thumbnailConfig.m_modelId = SharedPreviewUtils::GetAssetIdForProductPath(
AtomToolsFramework::GetSettingOrDefault<AZStd::string>(ModelAssetPathSetting, DefaultModelPath));
thumbnailConfig.m_materialId = assetInfo.m_assetId;
thumbnailConfig.m_lightingId = SharedPreviewUtils::GetAssetIdForProductPath(
AtomToolsFramework::GetSettingOrDefault<AZStd::string>(LightingAssetPathSetting, DefaultLightingPresetPath));
}
else if (assetInfo.m_assetType == RPI::AnyAsset::RTTI_Type())
{
static constexpr const char* ModelAssetPathSetting =
"/O3DE/Atom/CommonFeature/SharedPreview/LightingAssetType/ModelAssetPath";
static constexpr const char* MaterialAssetPathSetting =
"/O3DE/Atom/CommonFeature/SharedPreview/LightingAssetType/MaterialAssetPath";
thumbnailConfig.m_modelId = SharedPreviewUtils::GetAssetIdForProductPath(
AtomToolsFramework::GetSettingOrDefault<AZStd::string>(ModelAssetPathSetting, DefaultModelPath));
thumbnailConfig.m_materialId = SharedPreviewUtils::GetAssetIdForProductPath(
AtomToolsFramework::GetSettingOrDefault<AZStd::string>(MaterialAssetPathSetting, "materials/reflectionprobe/reflectionprobevisualization.azmaterial"));
thumbnailConfig.m_lightingId = assetInfo.m_assetId;
}
return thumbnailConfig;
}
void SharedThumbnailRenderer::RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize) void SharedThumbnailRenderer::RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize)
{ {
if (auto previewRenderer = AZ::Interface<AtomToolsFramework::PreviewRendererInterface>::Get()) if (auto previewRenderer = AZ::Interface<AtomToolsFramework::PreviewRendererInterface>::Get())
{ {
const auto& thumbnailConfig = GetThumbnailConfig(thumbnailKey);
previewRenderer->AddCaptureRequest( previewRenderer->AddCaptureRequest(
{ thumbnailSize, { thumbnailSize,
AZStd::make_shared<SharedPreviewContent>( AZStd::make_shared<SharedPreviewContent>(
previewRenderer->GetScene(), previewRenderer->GetView(), previewRenderer->GetEntityContextId(), previewRenderer->GetScene(), previewRenderer->GetView(), previewRenderer->GetEntityContextId(),
SharedPreviewUtils::GetAssetId(thumbnailKey, RPI::ModelAsset::RTTI_Type(), DefaultModelAssetId), thumbnailConfig.m_modelId, thumbnailConfig.m_materialId, thumbnailConfig.m_lightingId,
SharedPreviewUtils::GetAssetId(thumbnailKey, RPI::MaterialAsset::RTTI_Type(), DefaultMaterialAssetId),
SharedPreviewUtils::GetAssetId(thumbnailKey, RPI::AnyAsset::RTTI_Type(), DefaultLightingPresetAssetId),
Render::MaterialPropertyOverrideMap()), Render::MaterialPropertyOverrideMap()),
[thumbnailKey]() [thumbnailKey]()
{ {

@ -33,6 +33,15 @@ namespace AZ
~SharedThumbnailRenderer(); ~SharedThumbnailRenderer();
private: private:
struct ThumbnailConfig
{
Data::AssetId m_modelId;
Data::AssetId m_materialId;
Data::AssetId m_lightingId;
};
ThumbnailConfig GetThumbnailConfig(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey);
//! ThumbnailerRendererRequestsBus::Handler interface overrides... //! ThumbnailerRendererRequestsBus::Handler interface overrides...
void RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize) override; void RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize) override;
bool Installed() const override; bool Installed() const override;
@ -42,15 +51,12 @@ namespace AZ
// Default assets to be kept loaded and used for rendering if not overridden // Default assets to be kept loaded and used for rendering if not overridden
static constexpr const char* DefaultLightingPresetPath = "lightingpresets/thumbnail.lightingpreset.azasset"; 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_defaultLightingPresetAsset;
static constexpr const char* DefaultModelPath = "models/sphere.azmodel"; 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_defaultModelAsset;
static constexpr const char* DefaultMaterialPath = ""; static constexpr const char* DefaultMaterialPath = "";
const Data::AssetId DefaultMaterialAssetId;
Data::Asset<RPI::MaterialAsset> m_defaultMaterialAsset; Data::Asset<RPI::MaterialAsset> m_defaultMaterialAsset;
}; };
} // namespace LyIntegration } // namespace LyIntegration

Loading…
Cancel
Save