Merge branch 'stabilization/2110' into Atom/santorac/MaterialEditorHandlesMissingTextures

monroegm-disable-blank-issue-2
santorac 4 years ago
commit 2774ac1811

@ -30,7 +30,6 @@ namespace AZ
AZStd::string m_displayName;
AZ::Data::Asset<AZ::RPI::ModelAsset> m_modelAsset;
AZ::Data::Asset<AZ::RPI::StreamingImageAsset> m_previewImageAsset;
};
using ModelPresetPtr = AZStd::shared_ptr<ModelPreset>;

@ -29,7 +29,6 @@ namespace AZ
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &ModelPreset::m_displayName, "Display Name", "Identifier used for display and selection")
->DataElement(AZ::Edit::UIHandlers::Default, &ModelPreset::m_modelAsset, "Model Asset", "Model asset reference")
->DataElement(AZ::Edit::UIHandlers::Default, &ModelPreset::m_previewImageAsset, "Preview Image Asset", "Preview image asset reference")
;
}
}

@ -24,10 +24,9 @@ namespace AZ
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<ModelPreset>()
->Version(3)
->Version(4)
->Field("displayName", &ModelPreset::m_displayName)
->Field("modelAsset", &ModelPreset::m_modelAsset)
->Field("previewImageAsset", &ModelPreset::m_previewImageAsset)
;
}
@ -41,7 +40,6 @@ namespace AZ
->Constructor<const ModelPreset&>()
->Property("displayName", BehaviorValueProperty(&ModelPreset::m_displayName))
->Property("modelAsset", BehaviorValueProperty(&ModelPreset::m_modelAsset))
->Property("previewImageAsset", BehaviorValueProperty(&ModelPreset::m_previewImageAsset))
;
}
}

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

@ -8,8 +8,9 @@
#pragma once
#include <AzCore/PlatformDef.h>
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/PlatformDef.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzCore/std/containers/vector.h>
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>
AZ_POP_DISABLE_WARNING
class QImage;
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 GetOpenFileInfo(const AZStd::vector<AZ::Data::AssetType>& assetTypes);
QFileInfo GetUniqueFileInfo(const QString& initialPath);
QFileInfo GetDuplicationFileInfo(const QString& initialPath);
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 <AzCore/IO/SystemFile.h>
#include <AzCore/Jobs/JobFunction.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzQtComponents/Components/Widgets/FileDialog.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.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
#include <QApplication>
@ -24,6 +27,36 @@ AZ_POP_DISABLE_WARNING
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)
{
const QFileInfo initialFileInfo(initialPath);

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

@ -62,15 +62,6 @@ namespace MaterialEditor
//! Get set of lighting preset names
virtual MaterialViewportPresetNameSet GetLightingPresetNames() const = 0;
//! Set lighting preset preview image
//! @param preset used to set preview image
//! @param preview image
virtual void SetLightingPresetPreview(AZ::Render::LightingPresetPtr preset, const QImage& image) = 0;
//! Get lighting preset preview image
//! @param preset used to find preview image
virtual QImage GetLightingPresetPreview(AZ::Render::LightingPresetPtr preset) const = 0;
//! Get model preset last save path
//! @param preset to lookup last save path
virtual AZStd::string GetLightingPresetLastSavePath(AZ::Render::LightingPresetPtr preset) const = 0;
@ -108,15 +99,6 @@ namespace MaterialEditor
//! Get set of model preset names
virtual MaterialViewportPresetNameSet GetModelPresetNames() const = 0;
//! Set model preset preview image
//! @param preset used to set preview image
//! @param preview image
virtual void SetModelPresetPreview(AZ::Render::ModelPresetPtr preset, const QImage& image) = 0;
//! Get model preset preview image
//! @param preset used to find preview image
virtual QImage GetModelPresetPreview(AZ::Render::ModelPresetPtr preset) const = 0;
//! Get model preset last save path
//! @param preset to lookup last save path
virtual AZStd::string GetModelPresetLastSavePath(AZ::Render::ModelPresetPtr preset) const = 0;

@ -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/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.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/StringFunc/StringFunc.h>
#include <AzFramework/IO/LocalFileIO.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.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
{
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()
{
}
@ -162,12 +127,6 @@ namespace MaterialEditor
m_viewportSettings =
AZ::UserSettings::CreateFind<MaterialViewportSettings>(AZ::Crc32("MaterialViewportSettings"), AZ::UserSettings::CT_GLOBAL);
m_lightingPresetPreviewImageDefault = QImage(180, 90, QImage::Format::Format_RGBA8888);
m_lightingPresetPreviewImageDefault.fill(Qt::GlobalColor::black);
m_modelPresetPreviewImageDefault = QImage(90, 90, QImage::Format::Format_RGBA8888);
m_modelPresetPreviewImageDefault.fill(Qt::GlobalColor::black);
MaterialViewportRequestBus::Handler::BusConnect();
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
}
@ -177,12 +136,10 @@ namespace MaterialEditor
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
MaterialViewportRequestBus::Handler::BusDisconnect();
m_lightingPresetPreviewImages.clear();
m_lightingPresetVector.clear();
m_lightingPresetLastSavePathMap.clear();
m_lightingPresetSelection.reset();
m_modelPresetPreviewImages.clear();
m_modelPresetVector.clear();
m_modelPresetLastSavePathMap.clear();
m_modelPresetSelection.reset();
@ -286,14 +243,6 @@ namespace MaterialEditor
SelectLightingPreset(presetPtr);
}
const auto& imagePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(presetPtr->m_skyboxImageAsset.GetId());
LoadImageAsync(imagePath, [presetPtr](const QImage& image) {
QImage imageScaled = image.scaled(180, 90, Qt::AspectRatioMode::KeepAspectRatio);
AZ::TickBus::QueueFunction([presetPtr, imageScaled]() {
MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Events::SetLightingPresetPreview, presetPtr, imageScaled);
});
});
return presetPtr;
}
@ -353,17 +302,6 @@ namespace MaterialEditor
return names;
}
void MaterialViewportComponent::SetLightingPresetPreview(AZ::Render::LightingPresetPtr preset, const QImage& image)
{
m_lightingPresetPreviewImages[preset] = image;
}
QImage MaterialViewportComponent::GetLightingPresetPreview(AZ::Render::LightingPresetPtr preset) const
{
auto imageItr = m_lightingPresetPreviewImages.find(preset);
return imageItr != m_lightingPresetPreviewImages.end() ? imageItr->second : m_lightingPresetPreviewImageDefault;
}
AZStd::string MaterialViewportComponent::GetLightingPresetLastSavePath(AZ::Render::LightingPresetPtr preset) const
{
auto pathItr = m_lightingPresetLastSavePathMap.find(preset);
@ -382,14 +320,6 @@ namespace MaterialEditor
SelectModelPreset(presetPtr);
}
const auto& imagePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(presetPtr->m_previewImageAsset.GetId());
LoadImageAsync(imagePath, [presetPtr](const QImage& image) {
QImage imageScaled = image.scaled(90, 90, Qt::AspectRatioMode::KeepAspectRatio);
AZ::TickBus::QueueFunction([presetPtr, imageScaled]() {
MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Events::SetModelPresetPreview, presetPtr, imageScaled);
});
});
return presetPtr;
}
@ -449,17 +379,6 @@ namespace MaterialEditor
return names;
}
void MaterialViewportComponent::SetModelPresetPreview(AZ::Render::ModelPresetPtr preset, const QImage& image)
{
m_modelPresetPreviewImages[preset] = image;
}
QImage MaterialViewportComponent::GetModelPresetPreview(AZ::Render::ModelPresetPtr preset) const
{
auto imageItr = m_modelPresetPreviewImages.find(preset);
return imageItr != m_modelPresetPreviewImages.end() ? imageItr->second : m_modelPresetPreviewImageDefault;
}
AZStd::string MaterialViewportComponent::GetModelPresetLastSavePath(AZ::Render::ModelPresetPtr preset) const
{
auto pathItr = m_modelPresetLastSavePathMap.find(preset);

@ -58,8 +58,6 @@ namespace MaterialEditor
void SelectLightingPreset(AZ::Render::LightingPresetPtr preset) override;
void SelectLightingPresetByName(const AZStd::string& name) override;
MaterialViewportPresetNameSet GetLightingPresetNames() const override;
void SetLightingPresetPreview(AZ::Render::LightingPresetPtr preset, const QImage& image) override;
QImage GetLightingPresetPreview(AZ::Render::LightingPresetPtr preset) const override;
AZStd::string GetLightingPresetLastSavePath(AZ::Render::LightingPresetPtr preset) const override;
AZ::Render::ModelPresetPtr AddModelPreset(const AZ::Render::ModelPreset& preset) override;
@ -70,8 +68,6 @@ namespace MaterialEditor
void SelectModelPreset(AZ::Render::ModelPresetPtr preset) override;
void SelectModelPresetByName(const AZStd::string& name) override;
MaterialViewportPresetNameSet GetModelPresetNames() const override;
void SetModelPresetPreview(AZ::Render::ModelPresetPtr preset, const QImage& image) override;
QImage GetModelPresetPreview(AZ::Render::ModelPresetPtr preset) const override;
AZStd::string GetModelPresetLastSavePath(AZ::Render::ModelPresetPtr preset) const override;
void SetShadowCatcherEnabled(bool enable) override;
@ -97,12 +93,6 @@ namespace MaterialEditor
AZ::Render::ModelPresetPtrVector m_modelPresetVector;
AZ::Render::ModelPresetPtr m_modelPresetSelection;
AZStd::map<AZ::Render::LightingPresetPtr, QImage> m_lightingPresetPreviewImages;
AZStd::map<AZ::Render::ModelPresetPtr, QImage> m_modelPresetPreviewImages;
QImage m_lightingPresetPreviewImageDefault;
QImage m_modelPresetPreviewImageDefault;
mutable AZStd::map<AZ::Render::LightingPresetPtr, AZStd::string> m_lightingPresetLastSavePathMap;
mutable AZStd::map<AZ::Render::ModelPresetPtr, AZStd::string> m_modelPresetLastSavePathMap;

@ -7,6 +7,7 @@
*/
#include <Atom/Feature/Utils/LightingPreset.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/Viewport/MaterialViewportRequestBus.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzFramework/Application/Application.h>
@ -27,13 +28,16 @@ namespace MaterialEditor
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; });
const int itemSize = aznumeric_cast<int>(
AtomToolsFramework::GetSettingOrDefault<AZ::u64>("/O3DE/Atom/MaterialEditor/PresetBrowserDialog/LightingItemSize", 180));
QListWidgetItem* selectedItem = nullptr;
for (const auto& preset : presets)
{
QImage image;
MaterialViewportRequestBus::BroadcastResult(image, &MaterialViewportRequestBus::Events::GetLightingPresetPreview, preset);
QListWidgetItem* item = CreateListItem(preset->m_displayName.c_str(), image);
AZStd::string path;
MaterialViewportRequestBus::BroadcastResult(path, &MaterialViewportRequestBus::Events::GetLightingPresetLastSavePath, preset);
QListWidgetItem* item = CreateListItem(
preset->m_displayName.c_str(), AZ::RPI::AssetUtils::MakeAssetId(path, 0).GetValue(), QSize(itemSize, itemSize));
m_listItemToPresetMap[item] = preset;

@ -27,13 +27,13 @@ namespace MaterialEditor
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; });
const int itemSize = aznumeric_cast<int>(
AtomToolsFramework::GetSettingOrDefault<AZ::u64>("/O3DE/Atom/MaterialEditor/PresetBrowserDialog/ModelItemSize", 90));
QListWidgetItem* selectedItem = nullptr;
for (const auto& preset : presets)
{
QImage image;
MaterialViewportRequestBus::BroadcastResult(image, &MaterialViewportRequestBus::Events::GetModelPresetPreview, preset);
QListWidgetItem* item = CreateListItem(preset->m_displayName.c_str(), image);
QListWidgetItem* item = CreateListItem(preset->m_displayName.c_str(), preset->m_modelAsset.GetId(), QSize(itemSize, itemSize));
m_listItemToPresetMap[item] = preset;

@ -12,11 +12,16 @@
#include <AzQtComponents/Components/Widgets/ElidingLabel.h>
#include <AzQtComponents/Components/Widgets/LineEdit.h>
#include <AzQtComponents/Components/Widgets/Text.h>
#include <AzToolsFramework/AssetBrowser/Thumbnails/ProductThumbnail.h>
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
#include <AzToolsFramework/Thumbnails/ThumbnailWidget.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
#include <Window/PresetBrowserDialogs/PresetBrowserDialog.h>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
#include <QVBoxLayout>
namespace MaterialEditor
{
@ -41,35 +46,51 @@ namespace MaterialEditor
m_ui->m_presetList->setGridSize(QSize(0, 0));
m_ui->m_presetList->setWrapping(true);
QObject::connect(m_ui->m_presetList, &QListWidget::currentItemChanged, [this]() { SelectCurrentPreset(); });
QObject::connect(m_ui->m_presetList, &QListWidget::currentItemChanged, [this](){ SelectCurrentPreset(); });
}
QListWidgetItem* PresetBrowserDialog::CreateListItem(const QString& title, const QImage& image)
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();
m_ui->m_presetList->setGridSize(
QSize(AZStd::max(gridSize.width(), image.width() + 10), AZStd::max(gridSize.height(), image.height() + 10)));
m_ui->m_presetList->setGridSize(QSize(
AZStd::max(gridSize.width(), size.width() + itemSpacing),
AZStd::max(gridSize.height(), size.height() + itemSpacing + headerHeight)));
QListWidgetItem* item = new QListWidgetItem(m_ui->m_presetList);
item->setData(Qt::UserRole, title);
item->setSizeHint(image.size() + QSize(4, 4));
item->setSizeHint(size + QSize(itemBorder, itemBorder + headerHeight));
m_ui->m_presetList->addItem(item);
QLabel* previewImage = new QLabel(m_ui->m_presetList);
previewImage->setFixedSize(image.size());
previewImage->setMargin(0);
previewImage->setPixmap(QPixmap::fromImage(image));
previewImage->updateGeometry();
AzQtComponents::ElidingLabel* previewLabel = new AzQtComponents::ElidingLabel(previewImage);
previewLabel->setText(title);
previewLabel->setFixedSize(QSize(image.width(), 15));
previewLabel->setMargin(0);
previewLabel->setStyleSheet("background-color: rgb(35, 35, 35)");
AzQtComponents::Text::addPrimaryStyle(previewLabel);
AzQtComponents::Text::addLabelStyle(previewLabel);
m_ui->m_presetList->setItemWidget(item, previewImage);
QWidget* itemWidget = new QWidget(m_ui->m_presetList);
itemWidget->setLayout(new QVBoxLayout(itemWidget));
itemWidget->layout()->setSpacing(0);
itemWidget->layout()->setMargin(0);
AzQtComponents::ElidingLabel* header = new AzQtComponents::ElidingLabel(itemWidget);
header->setText(title);
header->setFixedSize(QSize(size.width(), headerHeight));
header->setMargin(0);
header->setStyleSheet("background-color: rgb(35, 35, 35)");
AzQtComponents::Text::addPrimaryStyle(header);
AzQtComponents::Text::addLabelStyle(header);
itemWidget->layout()->addWidget(header);
AzToolsFramework::Thumbnailer::ThumbnailWidget* thumbnail = new AzToolsFramework::Thumbnailer::ThumbnailWidget(itemWidget);
thumbnail->setFixedSize(size);
thumbnail->SetThumbnailKey(
MAKE_TKEY(AzToolsFramework::AssetBrowser::ProductThumbnailKey, assetId),
AzToolsFramework::Thumbnailer::ThumbnailContext::DefaultContext);
thumbnail->updateGeometry();
itemWidget->layout()->addWidget(thumbnail);
m_ui->m_presetList->setItemWidget(item, itemWidget);
return item;
}
@ -79,15 +100,15 @@ namespace MaterialEditor
m_ui->m_searchWidget->setReadOnly(false);
m_ui->m_searchWidget->setContextMenuPolicy(Qt::CustomContextMenu);
AzQtComponents::LineEdit::applySearchStyle(m_ui->m_searchWidget);
connect(m_ui->m_searchWidget, &QLineEdit::textChanged, this, [this]() { ApplySearchFilter(); });
connect(m_ui->m_searchWidget, &QWidget::customContextMenuRequested, this, [this](const QPoint& pos) { ShowSearchMenu(pos); });
connect(m_ui->m_searchWidget, &QLineEdit::textChanged, this, [this](){ ApplySearchFilter(); });
connect(m_ui->m_searchWidget, &QWidget::customContextMenuRequested, this, [this](const QPoint& pos){ ShowSearchMenu(pos); });
}
void PresetBrowserDialog::SetupDialogButtons()
{
connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(this, &QDialog::rejected, this, [this]() { SelectInitialPreset(); });
connect(this, &QDialog::rejected, this, [this](){ SelectInitialPreset(); });
}
void PresetBrowserDialog::ApplySearchFilter()

@ -9,12 +9,12 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/std/containers/vector.h>
#include <QDialog>
#endif
#include <Source/Window/PresetBrowserDialogs/ui_PresetBrowserDialog.h>
#include <Window/PresetBrowserDialogs/ui_PresetBrowserDialog.h>
class QImage;
class QListWidgetItem;
@ -32,7 +32,7 @@ namespace MaterialEditor
protected:
void SetupPresetList();
QListWidgetItem* CreateListItem(const QString& title, const QImage& image);
QListWidgetItem* CreateListItem(const QString& title, const AZ::Data::AssetId& assetId, const QSize& size);
void SetupSearchWidget();
void SetupDialogButtons();

@ -163,9 +163,9 @@ namespace AZ
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 distance = fabsf(radius / sinf(FieldOfView)) + NearDist;
const auto cameraRotation = Quaternion::CreateFromAxisAngle(Vector3::CreateAxisX(), -CameraRotationAngle);
const auto cameraPosition = center + cameraRotation.TransformVector(-Vector3::CreateAxisY() * distance);
const auto cameraTransform = Transform::CreateLookAt(cameraPosition, center);
m_view->SetCameraTransform(Matrix3x4::CreateFromTransform(cameraTransform));
}

@ -51,7 +51,7 @@ namespace AZ
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;
static constexpr float CameraRotationAngle = Constants::QuarterPi / 3.0f;
RPI::ScenePtr m_scene;
RPI::ViewPtr m_view;

@ -9,9 +9,11 @@
#include <API/EditorAssetSystemAPI.h>
#include <AssetBrowser/Thumbnails/ProductThumbnail.h>
#include <AssetBrowser/Thumbnails/SourceThumbnail.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/AnyAsset.h>
#include <AtomToolsFramework/Util/Util.h>
#include <SharedPreview/SharedPreviewUtils.h>
namespace AZ
@ -20,45 +22,64 @@ namespace AZ
{
namespace SharedPreviewUtils
{
Data::AssetId GetAssetId(
AzToolsFramework::Thumbnailer::SharedThumbnailKey key,
const Data::AssetType& assetType,
const Data::AssetId& defaultAssetId)
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)
{
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
auto sourceKey = azrtti_cast<const AzToolsFramework::AssetBrowser::SourceThumbnailKey*>(key.data());
if (sourceKey)
{
bool foundIt = false;
AZStd::vector<Data::AssetInfo> productsAssetInfo;
AZStd::vector<AZ::Data::AssetInfo> productsAssetInfo;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
foundIt, &AzToolsFramework::AssetSystemRequestBus::Events::GetAssetsProducedBySourceUUID,
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)
if (supportedTypeIds.find(assetInfo.m_assetType) != supportedTypeIds.end())
{
return assetInfo.m_assetType == assetType;
});
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
AZ::Data::AssetInfo assetInfo;
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)
@ -85,32 +106,6 @@ namespace AZ
}
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 LyIntegration
} // namespace AZ

@ -8,9 +8,9 @@
#pragma once
#include <AzCore/Asset/AssetCommon.h>
#if !defined(Q_MOC_RUN)
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
#endif
@ -20,21 +20,25 @@ namespace AZ
{
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
AZStd::unordered_set<AZ::Uuid> GetSupportedAssetTypes();
//! Determine if a thumbnail key has an asset supported by the shared preview
bool IsSupportedAssetType(AzToolsFramework::Thumbnailer::SharedThumbnailKey key);
//! 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 LyIntegration
} // namespace AZ

@ -22,18 +22,13 @@ namespace AZ
//////////////////////////////////////////////////////////////////////////
SharedThumbnail::SharedThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey 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);
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
return;
}
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Handler::BusConnect(key);
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
return;
}
AZ_Error("SharedThumbnail", false, "Failed to find matching assetId for the thumbnailKey.");
@ -43,7 +38,9 @@ namespace AZ
void SharedThumbnail::LoadThread()
{
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
m_renderWait.acquire();
}
@ -68,7 +65,7 @@ namespace AZ
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;
Load();

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

@ -8,6 +8,7 @@
#include <AtomToolsFramework/PreviewRenderer/PreviewRendererCaptureRequest.h>
#include <AtomToolsFramework/PreviewRenderer/PreviewRendererInterface.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
#include <SharedPreview/SharedPreviewContent.h>
@ -20,9 +21,9 @@ namespace AZ
{
SharedThumbnailRenderer::SharedThumbnailRenderer()
{
m_defaultModelAsset.Create(DefaultModelAssetId, true);
m_defaultMaterialAsset.Create(DefaultMaterialAssetId, true);
m_defaultLightingPresetAsset.Create(DefaultLightingPresetAssetId, true);
m_defaultModelAsset.Create(SharedPreviewUtils::GetAssetIdForProductPath(DefaultModelPath), true);
m_defaultMaterialAsset.Create(SharedPreviewUtils::GetAssetIdForProductPath(DefaultMaterialPath), true);
m_defaultLightingPresetAsset.Create(SharedPreviewUtils::GetAssetIdForProductPath(DefaultLightingPresetPath), true);
for (const AZ::Uuid& typeId : SharedPreviewUtils::GetSupportedAssetTypes())
{
@ -37,17 +38,66 @@ namespace AZ
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)
{
if (auto previewRenderer = AZ::Interface<AtomToolsFramework::PreviewRendererInterface>::Get())
{
const auto& thumbnailConfig = GetThumbnailConfig(thumbnailKey);
previewRenderer->AddCaptureRequest(
{ thumbnailSize,
AZStd::make_shared<SharedPreviewContent>(
previewRenderer->GetScene(), previewRenderer->GetView(), previewRenderer->GetEntityContextId(),
SharedPreviewUtils::GetAssetId(thumbnailKey, RPI::ModelAsset::RTTI_Type(), DefaultModelAssetId),
SharedPreviewUtils::GetAssetId(thumbnailKey, RPI::MaterialAsset::RTTI_Type(), DefaultMaterialAssetId),
SharedPreviewUtils::GetAssetId(thumbnailKey, RPI::AnyAsset::RTTI_Type(), DefaultLightingPresetAssetId),
thumbnailConfig.m_modelId, thumbnailConfig.m_materialId, thumbnailConfig.m_lightingId,
Render::MaterialPropertyOverrideMap()),
[thumbnailKey]()
{

@ -33,6 +33,15 @@ namespace AZ
~SharedThumbnailRenderer();
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...
void RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize) override;
bool Installed() const override;
@ -42,15 +51,12 @@ namespace AZ
// Default assets to be kept loaded and used for rendering if not overridden
static constexpr const char* DefaultLightingPresetPath = "lightingpresets/thumbnail.lightingpreset.azasset";
const Data::AssetId DefaultLightingPresetAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultLightingPresetPath);
Data::Asset<RPI::AnyAsset> m_defaultLightingPresetAsset;
static constexpr const char* DefaultModelPath = "models/sphere.azmodel";
const Data::AssetId DefaultModelAssetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultModelPath);
Data::Asset<RPI::ModelAsset> m_defaultModelAsset;
static constexpr const char* DefaultMaterialPath = "";
const Data::AssetId DefaultMaterialAssetId;
Data::Asset<RPI::MaterialAsset> m_defaultMaterialAsset;
};
} // namespace LyIntegration

Loading…
Cancel
Save